#include #include #include #include #include <9p.h> #include #include #include "ber.h" #include "ndbutil.h" #include "snmp.h" #include "fs.h" Tree *fstree; /* no auth, just mount the selected host */ void fsattach(Req *r) { char *host; File *f; host = strdup(r->ifcall.aname); error(DEBUG,"fsattach(): mount %s as %s\n",host,r->fid->file->name); if (strncmp(host,"all",3) != 0 ) { /* test if the machine exists */ f = walkfile(fstree->root,host); if ( f == nil ) { werrstr("fsattach(): error: host %s not registered",host); free(host); responderror(r); return; } } else { f = fstree->root; } r->fid->file = f; incref(r->fid->file); r->ofcall.qid = f->qid; r->fid->qid = r->ofcall.qid; free(host); respond(r,nil); return; } /* we store snmpinfo temporally in f->aux, to get long walks */ /* and we free'd them as soon as are completly readed */ /* root->name should be the host as it appears in ndb */ /* file->name should be the oid in the dotted or name form */ void fsread(Req *r) { File *f,*root; vlong offset; long count; Session *s; Packet *p; char *aux; Bytes *ptr; f = r->fid->file; root = f->parent; offset = r->ifcall.offset; count = r->ifcall.count; ptr = (Bytes*)f->aux; /* fill the bytes with the collected data */ if( f->aux == nil ) { s = mksession(root->name); p = mkpacket(root->name,f->name,nil); aux = (void*)dosnmp(s,p); f->aux = (void*)makebytes((uchar*)aux, strlen(aux)+1); ptr = (Bytes*)f->aux; free(aux); freepacket(p); freesession(s); } if (offset >= ptr->len ) { r->ofcall.count = 0; freebytes(ptr); f->aux = nil; respond(r, nil); return; } if(offset+count >= ptr->len) count = ptr->len - offset; memmove(r->ofcall.data, ptr->data+offset, count); r->ofcall.count = count; /* free the content each time it is completly readed we don't want to cache */ if ( count == ptr->len) { freebytes(ptr); f->aux = nil; } respond(r,nil); } void fswrite(Req *r) { File *f,*root; vlong offset; long count; Session *s; Packet *p; char *host, *oid, *val,*aux; f = r->fid->file; root = f->parent; offset = r->ifcall.offset; count = r->ifcall.count; if( f->aux == nil ) { host = strdup(root->name); oid= strdup(f->name); val = (char*)emalloc(count+1); memcpy(val,r->ifcall.data, count); val[count] = '\0'; s = mksession(host); p = mkpacket(host,oid,val); free(host); free(oid); free(val); aux =(char*)dosnmp(s,p); /*store a possible error */ f->aux = (void*)makebytes((uchar*)aux, strlen(aux)); freepacket(p); freesession(s); free(aux); r->ofcall.count = count; respond(r, nil); return; } respond(r,"file should be empty, read it first"); return; } void fscreate(Req *r) { File *f; File *nf; f = r->fid->file; if(nf = createfile(f, r->ifcall.name, r->fid->uid, r->ifcall.perm, nil)){ r->fid->file = nf; r->ofcall.qid = nf->qid; respond(r, nil); return; } respond(r, Ecreate); return; } Srv fs = { .attach= fsattach, .read= fsread, .write= fswrite, .create= fscreate, }; Session* mksession(char *host) { Session *s; char *aux; s = (Session*)emalloc(sizeof(Session)); s->host=strdup(host); s->port=strdup(DPORT); aux = ndbget(host,"rocomm"); s->rocomm = (aux != nil )? strdup(aux) : strdup(DROCOMM); free(aux); aux = ndbget(host,"rwcomm"); s->rwcomm = (aux != nil )? strdup(aux) : strdup(DRWCOMM); free(aux); aux = ndbget(host,"timeout"); s->timeout = (aux != nil )? atoi(aux) : DTIMEOUT; free(aux); aux = ndbget(host,"retries"); s->retries = (aux != nil )? atoi(aux) : DRETRIES; free(aux); error(DEBUG,"mksession(): Host = %s comm = %s timeout = %d",s->host,s->rocomm,s->timeout); return s; } Packet* mkpacket(char *host, char *ooid, char *val) { Packet *p; char *aux; char *oid; int i,j,op; char *oids[MAX_OID]; p = (Packet*)emalloc(sizeof(Packet)); aux= ndbget(host,"version"); p->ver = (aux != nil )? atoi(aux) : DVERSION; free(aux); oid = strdup(ooid); if ( val != nil ) op = 4; // SetRequest type else op = ndbgetop(host,oid); switch(op) { case 0: p->pdu.type = GetRequest; break; case 1: p->pdu.type = GetNextRequest; break; case 2: p->pdu.type = WalkRequest; break; case 3: p->pdu.type = GetBulkRequest; break; case 4: p->pdu.type = SetRequest; break; default: error(DEBUG,"mkpacket(): unknown op type %d",op); break; } p->pdu.errstat=0; p->pdu.erridx=0; aux = ndbget(host,"nrep"); p->pdu.nrep = (aux != nil )? atoi(aux) : DNREP; free(aux); aux = ndbget(host,"maxrep"); p->pdu.maxrep = (aux != nil )? atoi(aux) : DNREP; free(aux); i=getfields(oid, oids, MAX_OID, 0,","); if ( i == 0 ) { i=1; oids[0] = oid; } p->pdu.nbind=i; p->pdu.varbind = (Tuple*)emalloc(sizeof(Tuple)*(p->pdu.nbind)); for(j=0;jpdu.varbind[j].oid= resolve(oids[j]); p->pdu.varbind[j].value= (val == nil ) ? nil : strdup(val); } free(oid); return p; } /* search ndb file for system configuration */ /* and creates initial fs layout */ int fsinit(char *user) { File *ndir; File *nf; Qid q; Ndbtuple *ht, *pht; /* host tuple and pointer to ht*/ Ndbtuple *ot, *pot; /* oid tuple and pointer to ot*/ char *sys = "sys"; char *oid = "oid"; fs.tree = alloctree(nil, nil, DMDIR|0777, fsdestroyfile); fstree = fs.tree; q = fs.tree->root->qid; /* for each snmp enabled hosts .... */ ht = ndbipinfo(NDB, "snmp", "enabled", &sys, 1); for(pht = ht; pht; pht = pht->entry) { ndir = createfile(fs.tree->root,pht->val,user,DMDIR|0777,nil); error(DEBUG,"fsinit(): NDIR %s QID = %d",pht->val, ndir->qid.path); /*... fill oid layout of each host */ ot = ndbipinfo(NDB, "sys", pht->val, &oid, 1); for(pot=ot;pot; pot = pot->entry) { nf = createfile(ndir,pot->val,user,0666,nil); error(DEBUG,"fsinit(): NF %s, QID = %d",pot->val, nf->qid.path); } ndbfree(ot); } ndbfree(ht); return 1; } void fsdestroyfile(File *f) { Bytes *ptr; ptr = (Bytes*)f->aux; if(ptr) freebytes(ptr); } void usage(void) { fprint(2, "usage: snmpfs [-D] [-a addr] [-s srvname] [-m mtpt] [-n ndb]\n"); exits("usage"); } void threadmain(int argc, char **argv) { char *addr = nil; char *srvname = nil; char *mtpt = nil; char *ndbfile = nil; rfork(RFNOTEG); ARGBEGIN{ case 'D': chatty9p++; DEBUG++; break; case 'a': addr = EARGF(usage()); break; case 's': srvname = EARGF(usage()); break; case 'm': mtpt = EARGF(usage()); break; case 'n': ndbfile= ARGF(); break; default: usage(); }ARGEND; if(argc) usage(); if(chatty9p) fprint(2, "ramsrv.nopipe %d srvname %s mtpt %s\n", fs.nopipe, srvname, mtpt); if(addr == nil && srvname == nil && mtpt == nil) sysfatal("must specify -a, -s, or -m option"); if(addr) listensrv(&fs, addr); /* NDB came from ndbutil.h */ if ( ndbfile == nil ) ndbfile = smprint("/lib/ndb/local"); NDB = ndbopen(ndbfile); fsinit("gdiaz"); if(srvname || mtpt) threadpostmountsrv(&fs, srvname, mtpt, MREPL|MCREATE); exits(0); }