#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <bio.h>#include <ctype.h>#include <ndb.h>#include <ip.h> enum{ Nreply= 20, Maxreply= 256, Maxrequest= 128, Maxpath= 128, Maxfdata= 8192, Qdir= 0, Qcs= 1,}; typedef struct Mfile Mfile;typedef struct Mlist Mlist;typedef struct Network Network;typedef struct Flushreq Flushreq;typedef struct Job Job; int vers; /* incremented each clone/attach */ struct Mfile{ int busy; char *user; Qid qid; int fid; /* * current request */ char *net; char *host; char *serv; char *rem; /* * result of the last lookup */ Network *nextnet; int nreply; char *reply[Nreply]; int replylen[Nreply];}; struct Mlist{ Mlist *next; Mfile mf;}; //// active requests//struct Job{ Job *next; int flushed; Fcall request; Fcall reply;};Lock joblock;Job *joblist; Mlist *mlist;int mfd[2];int debug;int paranoia;jmp_buf masterjmp; /* return through here after a slave process has been created */int *isslave; /* *isslave non-zero means this is a slave process */char *dbfile;Ndb *db, *netdb; void rversion(Job*);void rflush(Job*);void rattach(Job*, Mfile*);char* rwalk(Job*, Mfile*);void ropen(Job*, Mfile*);void rcreate(Job*, Mfile*);void rread(Job*, Mfile*);void rwrite(Job*, Mfile*);void rclunk(Job*, Mfile*);void rremove(Job*, Mfile*);void rstat(Job*, Mfile*);void rwstat(Job*, Mfile*);void rauth(Job*);void sendmsg(Job*, char*);void error(char*);void mountinit(char*, char*);void io(void);void ndbinit(void);void netinit(int);void netadd(char*);char *genquery(Mfile*, char*);char* ipinfoquery(Mfile*, char**, int);int needproto(Network*, Ndbtuple*);int lookup(Mfile*);Ndbtuple* reorder(Ndbtuple*, Ndbtuple*);void ipid(void);void readipinterfaces(void);void* emalloc(int);char* estrdup(char*);Job* newjob(void);void freejob(Job*);void setext(char*, int, char*);void cleanmf(Mfile*); extern void paralloc(void); Lock dblock; /* mutex on database operations */Lock netlock; /* mutex for netinit() */ char *logfile = "cs";char *paranoiafile = "cs.paranoia"; char mntpt[Maxpath];char netndb[Maxpath]; /* * Network specific translators */Ndbtuple* iplookup(Network*, char*, char*, int);char* iptrans(Ndbtuple*, Network*, char*, char*, int);Ndbtuple* telcolookup(Network*, char*, char*, int);char* telcotrans(Ndbtuple*, Network*, char*, char*, int);Ndbtuple* dnsiplookup(char*, Ndbs*); struct Network{ char *net; Ndbtuple *(*lookup)(Network*, char*, char*, int); char *(*trans)(Ndbtuple*, Network*, char*, char*, int); int considered; int fasttimeouthack; Network *next;}; enum{ Nilfast, Ntcp, Nil, Nudp, Nicmp, Nrudp, Ntelco,}; /* * net doesn't apply to udp, icmp, or telco (for speed) */Network network[] = {[Nilfast] { "il", iplookup, iptrans, 0, 1 },[Ntcp] { "tcp", iplookup, iptrans, 0, 0 },[Nil] { "il", iplookup, iptrans, 0, 0 },[Nudp] { "udp", iplookup, iptrans, 1, 0 },[Nicmp] { "icmp", iplookup, iptrans, 1, 0 },[Nrudp] { "rudp", iplookup, iptrans, 1, 0 },[Ntelco] { "telco", telcolookup, telcotrans, 1, 0 }, { 0 },}; Lock ipifclock;Ipifc *ipifcs; char eaddr[Ndbvlen]; /* ascii ethernet address */char ipaddr[Ndbvlen]; /* ascii internet address */uchar ipa[IPaddrlen]; /* binary internet address */char mysysname[Ndbvlen]; Network *netlist; /* networks ordered by preference */Network *last; voidusage(void){ fprint(2, "usage: %s [-d] [-f ndb-file] [-x netmtpt] [-n]\n", argv0); exits("usage");} voidmain(int argc, char *argv[]){ char servefile[Maxpath]; int justsetname; char *p; char ext[Maxpath]; justsetname = 0; setnetmtpt(mntpt, sizeof(mntpt), nil); ext[0] = 0; ARGBEGIN{ case 'd': debug = 1; break; case 'f': p = ARGF(); if(p == nil) usage(); dbfile = p; break; case 'x': p = ARGF(); if(p == nil) usage(); setnetmtpt(mntpt, sizeof(mntpt), p); setext(ext, sizeof(ext), mntpt); break; case 'n': justsetname = 1; break; }ARGEND USED(argc); USED(argv); rfork(RFREND|RFNOTEG); snprint(servefile, sizeof(servefile), "#s/cs%s", ext); snprint(netndb, sizeof(netndb), "%s/ndb", mntpt); unmount(servefile, mntpt); remove(servefile); fmtinstall('E', eipfmt); fmtinstall('I', eipfmt); fmtinstall('M', eipfmt); fmtinstall('F', fcallfmt); ndbinit(); netinit(0); if(!justsetname){ mountinit(servefile, mntpt); io(); } exits(0);} /* * if a mount point is specified, set the cs extention to be the mount point * with '_'s replacing '/'s */voidsetext(char *ext, int n, char *p){ int i, c; n--; for(i = 0; i < n; i++){ c = p[i]; if(c == 0) break; if(c == '/') c = '_'; ext[i] = c; } ext[i] = 0;} voidmountinit(char *service, char *mntpt){ int f; int p[2]; char buf[32]; if(pipe(p) < 0) error("pipe failed"); switch(rfork(RFFDG|RFPROC|RFNAMEG)){ case 0: close(p[1]); break; case -1: error("fork failed\n"); default: /* * make a /srv/cs */ f = create(service, 1, 0666); if(f < 0) error(service); snprint(buf, sizeof(buf), "%d", p[1]); if(write(f, buf, strlen(buf)) != strlen(buf)) error("write /srv/cs"); close(f); /* * put ourselves into the file system */ close(p[0]); if(mount(p[1], -1, mntpt, MAFTER, "") < 0) error("mount failed\n"); _exits(0); } mfd[0] = mfd[1] = p[0];} voidndbinit(void){ db = ndbopen(dbfile); if(db == nil) error("can't open network database"); netdb = ndbopen(netndb); if(netdb != nil){ netdb->nohash = 1; db = ndbcat(netdb, db); }} Mfile*newfid(int fid){ Mlist *f, *ff; Mfile *mf; ff = 0; for(f = mlist; f; f = f->next) if(f->mf.busy && f->mf.fid == fid) return &f->mf; else if(!ff && !f->mf.busy) ff = f; if(ff == 0){ ff = emalloc(sizeof *f); ff->next = mlist; mlist = ff; } mf = &ff->mf; memset(mf, 0, sizeof *mf); mf->fid = fid; return mf;} Job*newjob(void){ Job *job; job = mallocz(sizeof(Job), 1); lock(&joblock); job->next = joblist; joblist = job; job->request.tag = -1; unlock(&joblock); return job;} voidfreejob(Job *job){ Job **l; lock(&joblock); for(l = &joblist; *l; l = &(*l)->next){ if((*l) == job){ *l = job->next; free(job); break; } } unlock(&joblock);} voidflushjob(int tag){ Job *job; lock(&joblock); for(job = joblist; job; job = job->next){ if(job->request.tag == tag && job->request.type != Tflush){ job->flushed = 1; break; } } unlock(&joblock);} voidio(void){ long n; Mfile *mf; int slaveflag; uchar mdata[IOHDRSZ + Maxfdata]; Job *job; /* * if we ask dns to fulfill requests, * a slave process is created to wait for replies. The * master process returns immediately via a longjmp * through 'masterjmp'. * * *isslave is a pointer into the call stack to a variable * that tells whether or not the current process is a slave. */ slaveflag = 0; /* init slave variable */ isslave = &slaveflag; setjmp(masterjmp); for(;;){ n = read9pmsg(mfd[0], mdata, sizeof mdata); if(n<=0) error("mount read"); job = newjob(); if(convM2S(mdata, n, &job->request) != n){ syslog(1, logfile, "format error %ux %ux %ux %ux %ux", mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]); freejob(job); continue; } if(job->request.fid<0) error("fid out of range"); lock(&dblock); mf = newfid(job->request.fid); if(debug) syslog(0, logfile, "%F", &job->request); switch(job->request.type){ default: syslog(1, logfile, "unknown request type %d", job->request.type); break; case Tversion: rversion(job); break; case Tauth: rauth(job); break; case Tflush: rflush(job); break; case Tattach: rattach(job, mf); break; case Twalk: rwalk(job, mf); break; case Topen: ropen(job, mf); break; case Tcreate: rcreate(job, mf); break; case Tread: rread(job, mf); break; case Twrite: rwrite(job, mf); break; case Tclunk: rclunk(job, mf); break; case Tremove: rremove(job, mf); break; case Tstat: rstat(job, mf); break; case Twstat: rwstat(job, mf); break; } unlock(&dblock); freejob(job); /* * slave processes die after replying */ if(*isslave){ if(debug) syslog(0, logfile, "slave death %d", getpid()); _exits(0); } }} voidrversion(Job *job){ if(job->request.msize > IOHDRSZ + Maxfdata) job->reply.msize = IOHDRSZ + Maxfdata; else job->reply.msize = job->request.msize; if(strncmp(job->request.version, "9P2000", 6) != 0) sendmsg(job, "unknown 9P version"); else{ job->reply.version = "9P2000"; sendmsg(job, 0); }Lines 1–500 of 1821. Load more
#include <u.h> #include <libc.h> #include <auth.h> #include <fcall.h> #include <bio.h> #include <ctype.h> #include <ndb.h> #include <ip.h> enum { Nreply= 20, Maxreply= 256, Maxrequest= 128, Maxpath= 128, Maxfdata= 8192, Qdir= 0, Qcs= 1, }; typedef struct Mfile Mfile; typedef struct Mlist Mlist; typedef struct Network Network; typedef struct Flushreq Flushreq; typedef struct Job Job; int vers; /* incremented each clone/attach */ struct Mfile { int busy; char *user; Qid qid; int fid; /* * current request */ char *net; char *host; char *serv; char *rem; /* * result of the last lookup */ Network *nextnet; int nreply; char *reply[Nreply]; int replylen[Nreply]; }; struct Mlist { Mlist *next; Mfile mf; }; // // active requests // struct Job { Job *next; int flushed; Fcall request; Fcall reply; }; Lock joblock; Job *joblist; Mlist *mlist; int mfd[2]; int debug; int paranoia; jmp_buf masterjmp; /* return through here after a slave process has been created */ int *isslave; /* *isslave non-zero means this is a slave process */ char *dbfile; Ndb *db, *netdb; void rversion(Job*); void rflush(Job*); void rattach(Job*, Mfile*); char* rwalk(Job*, Mfile*); void ropen(Job*, Mfile*); void rcreate(Job*, Mfile*); void rread(Job*, Mfile*); void rwrite(Job*, Mfile*); void rclunk(Job*, Mfile*); void rremove(Job*, Mfile*); void rstat(Job*, Mfile*); void rwstat(Job*, Mfile*); void rauth(Job*); void sendmsg(Job*, char*); void error(char*); void mountinit(char*, char*); void io(void); void ndbinit(void); void netinit(int); void netadd(char*); char *genquery(Mfile*, char*); char* ipinfoquery(Mfile*, char**, int); int needproto(Network*, Ndbtuple*); int lookup(Mfile*); Ndbtuple* reorder(Ndbtuple*, Ndbtuple*); void ipid(void); void readipinterfaces(void); void* emalloc(int); char* estrdup(char*); Job* newjob(void); void freejob(Job*); void setext(char*, int, char*); void cleanmf(Mfile*); extern void paralloc(void); Lock dblock; /* mutex on database operations */ Lock netlock; /* mutex for netinit() */ char *logfile = "cs"; char *paranoiafile = "cs.paranoia"; char mntpt[Maxpath]; char netndb[Maxpath]; /* * Network specific translators */ Ndbtuple* iplookup(Network*, char*, char*, int); char* iptrans(Ndbtuple*, Network*, char*, char*, int); Ndbtuple* telcolookup(Network*, char*, char*, int); char* telcotrans(Ndbtuple*, Network*, char*, char*, int); Ndbtuple* dnsiplookup(char*, Ndbs*); struct Network { char *net; Ndbtuple *(*lookup)(Network*, char*, char*, int); char *(*trans)(Ndbtuple*, Network*, char*, char*, int); int considered; int fasttimeouthack; Network *next; }; enum { Nilfast, Ntcp, Nil, Nudp, Nicmp, Nrudp, Ntelco, }; /* * net doesn't apply to udp, icmp, or telco (for speed) */ Network network[] = { [Nilfast] { "il", iplookup, iptrans, 0, 1 }, [Ntcp] { "tcp", iplookup, iptrans, 0, 0 }, [Nil] { "il", iplookup, iptrans, 0, 0 }, [Nudp] { "udp", iplookup, iptrans, 1, 0 }, [Nicmp] { "icmp", iplookup, iptrans, 1, 0 }, [Nrudp] { "rudp", iplookup, iptrans, 1, 0 }, [Ntelco] { "telco", telcolookup, telcotrans, 1, 0 }, { 0 }, }; Lock ipifclock; Ipifc *ipifcs; char eaddr[Ndbvlen]; /* ascii ethernet address */ char ipaddr[Ndbvlen]; /* ascii internet address */ uchar ipa[IPaddrlen]; /* binary internet address */ char mysysname[Ndbvlen]; Network *netlist; /* networks ordered by preference */ Network *last; void usage(void) { fprint(2, "usage: %s [-d] [-f ndb-file] [-x netmtpt] [-n]\n", argv0); exits("usage"); } void main(int argc, char *argv[]) { char servefile[Maxpath]; int justsetname; char *p; char ext[Maxpath]; justsetname = 0; setnetmtpt(mntpt, sizeof(mntpt), nil); ext[0] = 0; ARGBEGIN{ case 'd': debug = 1; break; case 'f': p = ARGF(); if(p == nil) usage(); dbfile = p; break; case 'x': p = ARGF(); if(p == nil) usage(); setnetmtpt(mntpt, sizeof(mntpt), p); setext(ext, sizeof(ext), mntpt); break; case 'n': justsetname = 1; break; }ARGEND USED(argc); USED(argv); rfork(RFREND|RFNOTEG); snprint(servefile, sizeof(servefile), "#s/cs%s", ext); snprint(netndb, sizeof(netndb), "%s/ndb", mntpt); unmount(servefile, mntpt); remove(servefile); fmtinstall('E', eipfmt); fmtinstall('I', eipfmt); fmtinstall('M', eipfmt); fmtinstall('F', fcallfmt); ndbinit(); netinit(0); if(!justsetname){ mountinit(servefile, mntpt); io(); } exits(0); } /* * if a mount point is specified, set the cs extention to be the mount point * with '_'s replacing '/'s */ void setext(char *ext, int n, char *p) { int i, c; n--; for(i = 0; i < n; i++){ c = p[i]; if(c == 0) break; if(c == '/') c = '_'; ext[i] = c; } ext[i] = 0; } void mountinit(char *service, char *mntpt) { int f; int p[2]; char buf[32]; if(pipe(p) < 0) error("pipe failed"); switch(rfork(RFFDG|RFPROC|RFNAMEG)){ case 0: close(p[1]); break; case -1: error("fork failed\n"); default: /* * make a /srv/cs */ f = create(service, 1, 0666); if(f < 0) error(service); snprint(buf, sizeof(buf), "%d", p[1]); if(write(f, buf, strlen(buf)) != strlen(buf)) error("write /srv/cs"); close(f); /* * put ourselves into the file system */ close(p[0]); if(mount(p[1], -1, mntpt, MAFTER, "") < 0) error("mount failed\n"); _exits(0); } mfd[0] = mfd[1] = p[0]; } void ndbinit(void) { db = ndbopen(dbfile); if(db == nil) error("can't open network database"); netdb = ndbopen(netndb); if(netdb != nil){ netdb->nohash = 1; db = ndbcat(netdb, db); } } Mfile* newfid(int fid) { Mlist *f, *ff; Mfile *mf; ff = 0; for(f = mlist; f; f = f->next) if(f->mf.busy && f->mf.fid == fid) return &f->mf; else if(!ff && !f->mf.busy) ff = f; if(ff == 0){ ff = emalloc(sizeof *f); ff->next = mlist; mlist = ff; } mf = &ff->mf; memset(mf, 0, sizeof *mf); mf->fid = fid; return mf; } Job* newjob(void) { Job *job; job = mallocz(sizeof(Job), 1); lock(&joblock); job->next = joblist; joblist = job; job->request.tag = -1; unlock(&joblock); return job; } void freejob(Job *job) { Job **l; lock(&joblock); for(l = &joblist; *l; l = &(*l)->next){ if((*l) == job){ *l = job->next; free(job); break; } } unlock(&joblock); } void flushjob(int tag) { Job *job; lock(&joblock); for(job = joblist; job; job = job->next){ if(job->request.tag == tag && job->request.type != Tflush){ job->flushed = 1; break; } } unlock(&joblock); } void io(void) { long n; Mfile *mf; int slaveflag; uchar mdata[IOHDRSZ + Maxfdata]; Job *job; /* * if we ask dns to fulfill requests, * a slave process is created to wait for replies. The * master process returns immediately via a longjmp * through 'masterjmp'. * * *isslave is a pointer into the call stack to a variable * that tells whether or not the current process is a slave. */ slaveflag = 0; /* init slave variable */ isslave = &slaveflag; setjmp(masterjmp); for(;;){ n = read9pmsg(mfd[0], mdata, sizeof mdata); if(n<=0) error("mount read"); job = newjob(); if(convM2S(mdata, n, &job->request) != n){ syslog(1, logfile, "format error %ux %ux %ux %ux %ux", mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]); freejob(job); continue; } if(job->request.fid<0) error("fid out of range"); lock(&dblock); mf = newfid(job->request.fid); if(debug) syslog(0, logfile, "%F", &job->request); switch(job->request.type){ default: syslog(1, logfile, "unknown request type %d", job->request.type); break; case Tversion: rversion(job); break; case Tauth: rauth(job); break; case Tflush: rflush(job); break; case Tattach: rattach(job, mf); break; case Twalk: rwalk(job, mf); break; case Topen: ropen(job, mf); break; case Tcreate: rcreate(job, mf); break; case Tread: rread(job, mf); break; case Twrite: rwrite(job, mf); break; case Tclunk: rclunk(job, mf); break; case Tremove: rremove(job, mf); break; case Tstat: rstat(job, mf); break; case Twstat: rwstat(job, mf); break; } unlock(&dblock); freejob(job); /* * slave processes die after replying */ if(*isslave){ if(debug) syslog(0, logfile, "slave death %d", getpid()); _exits(0); } } } void rversion(Job *job) { if(job->request.msize > IOHDRSZ + Maxfdata) job->reply.msize = IOHDRSZ + Maxfdata; else job->reply.msize = job->request.msize; if(strncmp(job->request.version, "9P2000", 6) != 0) sendmsg(job, "unknown 9P version"); else{ job->reply.version = "9P2000"; sendmsg(job, 0); }