Plan 9 from Bell Labs’s /usr/web/sources/contrib/gabidiaz/root/sys/src/cmd/snmpfs/fs.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include <bio.h>
#include <ndb.h>
#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;j<i;j++) {	 
		p->pdu.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);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.