Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

NFS.cc

Go to the documentation of this file.
00001 // $Id: NFS.cc,v 1.2 2005/09/07 17:23:52 vern Exp $
00002 //
00003 // Copyright (c) 2005
00004 //      The Regents of the University of California.  All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that: (1) source code distributions
00008 // retain the above copyright notice and this paragraph in its entirety, (2)
00009 // distributions including binary code include the above copyright notice and
00010 // this paragraph in its entirety in the documentation or other materials
00011 // provided with the distribution, and (3) all advertising materials mentioning
00012 // features or use of this software display the following acknowledgement:
00013 // ``This product includes software developed by the University of California,
00014 // Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
00015 // the University nor the names of its contributors may be used to endorse
00016 // or promote products derived from this software without specific prior
00017 // written permission.
00018 // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
00019 // WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00020 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022 #include "config.h"
00023 
00024 #include "NetVar.h"
00025 #include "XDR.h"
00026 #include "NFS.h"
00027 #include "Event.h"
00028 
00029 #define NFS_PROC_NULL           0
00030 #define NFS_PROC_GETATTR        1
00031 #define NFS_PROC_SETATTR        2
00032 #define NFS_PROC_LOOKUP         3
00033 #define NFS_PROC_READ           6
00034 #define NFS_PROC_WRITE          7
00035 #define NFS_PROC_FSSTAT         18
00036 
00037 int NFS_Interp::RPC_BuildCall(RPC_CallInfo* c, const u_char*& buf, int& n)
00038         {
00039         if ( c->Program() != 100003 )
00040                 Weird("bad_RPC_program");
00041 
00042         uint32 proc = c->Proc();
00043         switch ( proc ) {
00044         case NFS_PROC_NULL:
00045                 break;
00046 
00047         case NFS_PROC_GETATTR:
00048                 {
00049                 Val* v = ExtractFH(buf, n);
00050                 if ( ! v )
00051                         return 0;
00052                 c->AddVal(v);
00053                 }
00054                 break;
00055 
00056         case NFS_PROC_LOOKUP:
00057                 {
00058                 StringVal* fh = ExtractFH(buf, n);
00059 
00060                 int name_len;
00061                 const u_char* name = extract_XDR_opaque(buf, n, name_len);
00062 
00063                 if ( ! fh || ! name )
00064                         return 0;
00065 
00066                 RecordVal* args = new RecordVal(nfs3_lookup_args);
00067                 args->Assign(0, fh);
00068                 args->Assign(1, new StringVal(new BroString(name, name_len, 0)));
00069                 c->AddVal(args);
00070                 }
00071                 break;
00072 
00073         case NFS_PROC_FSSTAT:
00074                 {
00075                 Val* v = ExtractFH(buf, n);
00076                 if ( ! v )
00077                         return 0;
00078                 c->AddVal(v);
00079                 }
00080                 break;
00081 
00082         case NFS_PROC_READ:
00083                 break;
00084 
00085         default:
00086                 Weird(fmt("unknown_NFS_request(%u)", proc));
00087 
00088                 // Return 1 so that replies to unprocessed calls will still
00089                 // be processed, and the return status extracted
00090                 return 1;
00091         }
00092 
00093         return 1;
00094         }
00095 
00096 int NFS_Interp::RPC_BuildReply(const RPC_CallInfo* c, int success,
00097                                         const u_char*& buf, int& n,
00098                                         EventHandlerPtr& event, Val*& reply)
00099         {
00100         reply = 0;
00101         uint32 status = 0;
00102         if ( success )
00103                 {
00104                 if ( n >= 4 )
00105                         status = extract_XDR_uint32(buf, n);
00106                 else
00107                         status = 0xffffffff;
00108                 }
00109 
00110         if ( nfs_reply_status )
00111                 {
00112                 val_list* vl = new val_list;
00113                 vl->append(Conn()->BuildConnVal());
00114                 vl->append(new Val(status, TYPE_COUNT));
00115                 Conn()->ConnectionEvent(nfs_reply_status, vl);
00116                 }
00117 
00118         switch ( c->Proc() ) {
00119         case NFS_PROC_NULL:
00120                 event = success ? nfs_request_null : nfs_attempt_null;
00121                 break;
00122 
00123         case NFS_PROC_GETATTR:
00124                 if ( success )
00125                         {
00126                         if ( ! buf || status != 0 )
00127                                 return 0;
00128 
00129                         reply = ExtractAttrs(buf, n);
00130                         event = nfs_request_getattr;
00131                         }
00132                 else
00133                         event = nfs_attempt_getattr;
00134 
00135                 break;
00136 
00137         case NFS_PROC_LOOKUP:
00138                 if ( success )
00139                         {
00140                         if ( ! buf || status != 0 )
00141                                 return 0;
00142 
00143                         RecordVal* r = new RecordVal(nfs3_lookup_reply);
00144                         r->Assign(0, ExtractFH(buf, n));
00145                         r->Assign(1, ExtractOptAttrs(buf, n));
00146                         r->Assign(2, ExtractOptAttrs(buf, n));
00147 
00148                         reply = r;
00149                         event = nfs_request_lookup;
00150                         }
00151                 else
00152                         {
00153                         reply = ExtractOptAttrs(buf, n);
00154                         event = nfs_attempt_lookup;
00155                         }
00156 
00157                 break;
00158 
00159         case NFS_PROC_FSSTAT:
00160                 if ( success )
00161                         {
00162                         if ( ! buf || status != 0 )
00163                                 return 0;
00164 
00165                         RecordVal* r = new RecordVal(nfs3_fsstat);
00166                         r->Assign(0, ExtractOptAttrs(buf, n));
00167                         r->Assign(1, ExtractLongAsDouble(buf, n)); // tbytes
00168                         r->Assign(2, ExtractLongAsDouble(buf, n)); // fbytes
00169                         r->Assign(3, ExtractLongAsDouble(buf, n)); // abytes
00170                         r->Assign(4, ExtractLongAsDouble(buf, n)); // tfiles
00171                         r->Assign(5, ExtractLongAsDouble(buf, n)); // ffiles
00172                         r->Assign(6, ExtractLongAsDouble(buf, n)); // afiles
00173                         r->Assign(7, ExtractInterval(buf, n)); // invarsec
00174 
00175                         reply = r;
00176                         event = nfs_request_fsstat;
00177                         }
00178                 else
00179                         {
00180                         reply = ExtractOptAttrs(buf, n);
00181                         event = nfs_attempt_fsstat;
00182                         }
00183 
00184                 break;
00185 
00186         default:
00187                 return 0;
00188         }
00189 
00190         return 1;
00191         }
00192 
00193 StringVal* NFS_Interp::ExtractFH(const u_char*& buf, int& n)
00194         {
00195         int fh_n;
00196         const u_char* fh = extract_XDR_opaque(buf, n, fh_n, 64);
00197 
00198         if ( ! fh )
00199                 return 0;
00200 
00201         return new StringVal(new BroString(fh, fh_n, 0));
00202         }
00203 
00204 RecordVal* NFS_Interp::ExtractAttrs(const u_char*& buf, int& n)
00205         {
00206         RecordVal* attrs = new RecordVal(nfs3_attrs);
00207         attrs->Assign(0, ExtractCount(buf, n)); // file type
00208         attrs->Assign(1, ExtractCount(buf, n)); // mode
00209         attrs->Assign(2, ExtractCount(buf, n)); // nlink
00210         attrs->Assign(3, ExtractCount(buf, n)); // uid
00211         attrs->Assign(4, ExtractCount(buf, n)); // gid
00212         attrs->Assign(5, ExtractLongAsDouble(buf, n));  // size
00213         attrs->Assign(6, ExtractLongAsDouble(buf, n));  // used
00214         attrs->Assign(7, ExtractCount(buf, n)); // rdev1
00215         attrs->Assign(8, ExtractCount(buf, n)); // rdev2
00216         attrs->Assign(9, ExtractLongAsDouble(buf, n));  // fsid
00217         attrs->Assign(10, ExtractLongAsDouble(buf, n)); // fileid
00218         attrs->Assign(11, ExtractTime(buf, n)); // atime
00219         attrs->Assign(12, ExtractTime(buf, n)); // mtime
00220         attrs->Assign(13, ExtractTime(buf, n)); // ctime
00221 
00222         return attrs;
00223         }
00224 
00225 RecordVal* NFS_Interp::ExtractOptAttrs(const u_char*& buf, int& n)
00226         {
00227         int have_attrs = extract_XDR_uint32(buf, n);
00228 
00229         if ( buf && have_attrs )
00230                 return ExtractAttrs(buf, n);
00231 
00232         else
00233                 return 0;
00234         }
00235 
00236 Val* NFS_Interp::ExtractCount(const u_char*& buf, int& n)
00237         {
00238         return new Val(extract_XDR_uint32(buf, n), TYPE_COUNT);
00239         }
00240 
00241 Val* NFS_Interp::ExtractLongAsDouble(const u_char*& buf, int& n)
00242         {
00243         return new Val(extract_XDR_uint64_as_double(buf, n), TYPE_DOUBLE);
00244         }
00245 
00246 Val* NFS_Interp::ExtractTime(const u_char*& buf, int& n)
00247         {
00248         return new Val(extract_XDR_time(buf, n), TYPE_TIME);
00249         }
00250 
00251 Val* NFS_Interp::ExtractInterval(const u_char*& buf, int& n)
00252         {
00253         return new IntervalVal(double(extract_XDR_uint32(buf, n)), 1.0);
00254         }
00255 
00256 void NFS_Interp::Event(EventHandlerPtr f, Val* request, int status, Val* reply)
00257         {
00258         if ( ! f )
00259                 {
00260                 Unref(request);
00261                 Unref(reply);
00262                 return;
00263                 }
00264 
00265         val_list* vl = new val_list;
00266 
00267         vl->append(conn->BuildConnVal());
00268         if ( status == RPC_SUCCESS )
00269                 {
00270                 if ( request )
00271                         vl->append(request);
00272                 if ( reply )
00273                         vl->append(reply);
00274                 }
00275         else
00276                 {
00277                 vl->append(new Val(status, TYPE_COUNT));
00278                 if ( request )
00279                         vl->append(request);
00280                 }
00281 
00282         conn->ConnectionEvent(f, vl);
00283         }
00284 
00285 NFS_Conn::NFS_Conn(NetSessions* s, HashKey* k, double t,
00286                 const ConnID* id, const struct tcphdr* tp)
00287 : TCP_Connection(s, k, t, id, tp)
00288         {
00289         interp = new NFS_Interp(this);
00290         orig_rpc = resp_rpc = 0;
00291         }
00292 
00293 void NFS_Conn::BuildEndpoints()
00294         {
00295         orig_rpc = new TCP_Contents_RPC(interp, orig);
00296         resp_rpc = new TCP_Contents_RPC(interp, resp);
00297 
00298         orig->AddContentsProcessor(orig_rpc);
00299         resp->AddContentsProcessor(resp_rpc);
00300         }
00301 
00302 NFS_Conn::~NFS_Conn()
00303         {
00304         delete interp;
00305         }
00306 
00307 void NFS_Conn::Done()
00308         {
00309         if ( orig_rpc->State() != RPC_COMPLETE &&
00310              (orig->state == TCP_CLOSED || orig->prev_state == TCP_CLOSED) &&
00311              // Sometimes things like tcpwrappers will immediately close
00312              // the connection, without any data having been transferred.
00313              // Don't bother flagging these.
00314              orig->Size() > 0 )
00315                 Weird("partial_NFS_request");
00316 
00317         interp->Timeout();
00318 
00319         TCP_Connection::Done();
00320         }

Generated on Wed Sep 14 02:56:17 2005 for bro_docs by doxygen 1.3.5