13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3219b2ee8SDavid du Colombier #include <auth.h> 43e12c5d1SDavid du Colombier #include <fcall.h> 53e12c5d1SDavid du Colombier #include <bio.h> 63e12c5d1SDavid du Colombier #include <ctype.h> 73e12c5d1SDavid du Colombier #include <ndb.h> 83e12c5d1SDavid du Colombier #include <ip.h> 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier enum 113e12c5d1SDavid du Colombier { 1280ee5cbfSDavid du Colombier Nreply= 20, 133e12c5d1SDavid du Colombier Maxreply= 256, 147dd7cddfSDavid du Colombier Maxrequest= 128, 157dd7cddfSDavid du Colombier Maxpath= 128, 169a747e4fSDavid du Colombier Maxfdata= 8192, 173e12c5d1SDavid du Colombier 189a747e4fSDavid du Colombier Qdir= 0, 193e12c5d1SDavid du Colombier Qcs= 1, 203e12c5d1SDavid du Colombier }; 213e12c5d1SDavid du Colombier 223e12c5d1SDavid du Colombier typedef struct Mfile Mfile; 23219b2ee8SDavid du Colombier typedef struct Mlist Mlist; 243e12c5d1SDavid du Colombier typedef struct Network Network; 257dd7cddfSDavid du Colombier typedef struct Flushreq Flushreq; 267dd7cddfSDavid du Colombier typedef struct Job Job; 273e12c5d1SDavid du Colombier 283e12c5d1SDavid du Colombier int vers; /* incremented each clone/attach */ 293e12c5d1SDavid du Colombier 303e12c5d1SDavid du Colombier struct Mfile 313e12c5d1SDavid du Colombier { 323e12c5d1SDavid du Colombier int busy; 33219b2ee8SDavid du Colombier 349a747e4fSDavid du Colombier char *user; 353e12c5d1SDavid du Colombier Qid qid; 363e12c5d1SDavid du Colombier int fid; 373e12c5d1SDavid du Colombier 3880ee5cbfSDavid du Colombier /* 3980ee5cbfSDavid du Colombier * current request 4080ee5cbfSDavid du Colombier */ 4180ee5cbfSDavid du Colombier char *net; 4280ee5cbfSDavid du Colombier char *host; 4380ee5cbfSDavid du Colombier char *serv; 4480ee5cbfSDavid du Colombier char *rem; 4580ee5cbfSDavid du Colombier 4680ee5cbfSDavid du Colombier /* 4780ee5cbfSDavid du Colombier * result of the last lookup 4880ee5cbfSDavid du Colombier */ 4980ee5cbfSDavid du Colombier Network *nextnet; 50219b2ee8SDavid du Colombier int nreply; 51219b2ee8SDavid du Colombier char *reply[Nreply]; 52219b2ee8SDavid du Colombier int replylen[Nreply]; 53219b2ee8SDavid du Colombier }; 54219b2ee8SDavid du Colombier 55219b2ee8SDavid du Colombier struct Mlist 56219b2ee8SDavid du Colombier { 57219b2ee8SDavid du Colombier Mlist *next; 58219b2ee8SDavid du Colombier Mfile mf; 593e12c5d1SDavid du Colombier }; 603e12c5d1SDavid du Colombier 619a747e4fSDavid du Colombier 627dd7cddfSDavid du Colombier // 637dd7cddfSDavid du Colombier // active requests 647dd7cddfSDavid du Colombier // 657dd7cddfSDavid du Colombier struct Job 667dd7cddfSDavid du Colombier { 677dd7cddfSDavid du Colombier Job *next; 687dd7cddfSDavid du Colombier int flushed; 697dd7cddfSDavid du Colombier Fcall request; 707dd7cddfSDavid du Colombier Fcall reply; 717dd7cddfSDavid du Colombier }; 727dd7cddfSDavid du Colombier Lock joblock; 737dd7cddfSDavid du Colombier Job *joblist; 747dd7cddfSDavid du Colombier 75219b2ee8SDavid du Colombier Mlist *mlist; 763e12c5d1SDavid du Colombier int mfd[2]; 773e12c5d1SDavid du Colombier int debug; 787dd7cddfSDavid du Colombier int paranoia; 793e12c5d1SDavid du Colombier jmp_buf masterjmp; /* return through here after a slave process has been created */ 803e12c5d1SDavid du Colombier int *isslave; /* *isslave non-zero means this is a slave process */ 81bd389b36SDavid du Colombier char *dbfile; 827dd7cddfSDavid du Colombier Ndb *db, *netdb; 833e12c5d1SDavid du Colombier 849a747e4fSDavid du Colombier void rversion(Job*); 857dd7cddfSDavid du Colombier void rflush(Job*); 867dd7cddfSDavid du Colombier void rattach(Job*, Mfile*); 877dd7cddfSDavid du Colombier char* rwalk(Job*, Mfile*); 887dd7cddfSDavid du Colombier void ropen(Job*, Mfile*); 897dd7cddfSDavid du Colombier void rcreate(Job*, Mfile*); 907dd7cddfSDavid du Colombier void rread(Job*, Mfile*); 917dd7cddfSDavid du Colombier void rwrite(Job*, Mfile*); 927dd7cddfSDavid du Colombier void rclunk(Job*, Mfile*); 937dd7cddfSDavid du Colombier void rremove(Job*, Mfile*); 947dd7cddfSDavid du Colombier void rstat(Job*, Mfile*); 957dd7cddfSDavid du Colombier void rwstat(Job*, Mfile*); 969a747e4fSDavid du Colombier void rauth(Job*); 977dd7cddfSDavid du Colombier void sendmsg(Job*, char*); 983e12c5d1SDavid du Colombier void error(char*); 997dd7cddfSDavid du Colombier void mountinit(char*, char*); 1003e12c5d1SDavid du Colombier void io(void); 1017dd7cddfSDavid du Colombier void ndbinit(void); 1027dd7cddfSDavid du Colombier void netinit(int); 1033e12c5d1SDavid du Colombier void netadd(char*); 104219b2ee8SDavid du Colombier char *genquery(Mfile*, char*); 1057dd7cddfSDavid du Colombier char* ipinfoquery(Mfile*, char**, int); 106bd389b36SDavid du Colombier int needproto(Network*, Ndbtuple*); 1079a747e4fSDavid du Colombier int lookup(Mfile*); 1083e12c5d1SDavid du Colombier Ndbtuple* reorder(Ndbtuple*, Ndbtuple*); 1097dd7cddfSDavid du Colombier void ipid(void); 1107dd7cddfSDavid du Colombier void readipinterfaces(void); 1117dd7cddfSDavid du Colombier void* emalloc(int); 1129a747e4fSDavid du Colombier char* estrdup(char*); 1137dd7cddfSDavid du Colombier Job* newjob(void); 1147dd7cddfSDavid du Colombier void freejob(Job*); 1157dd7cddfSDavid du Colombier void setext(char*, int, char*); 11680ee5cbfSDavid du Colombier void cleanmf(Mfile*); 1173e12c5d1SDavid du Colombier 118bd389b36SDavid du Colombier extern void paralloc(void); 119bd389b36SDavid du Colombier 120bd389b36SDavid du Colombier Lock dblock; /* mutex on database operations */ 1217dd7cddfSDavid du Colombier Lock netlock; /* mutex for netinit() */ 122bd389b36SDavid du Colombier 123219b2ee8SDavid du Colombier char *logfile = "cs"; 1247dd7cddfSDavid du Colombier char *paranoiafile = "cs.paranoia"; 125219b2ee8SDavid du Colombier 1267dd7cddfSDavid du Colombier char mntpt[Maxpath]; 1277dd7cddfSDavid du Colombier char netndb[Maxpath]; 1287dd7cddfSDavid du Colombier 12980ee5cbfSDavid du Colombier /* 13080ee5cbfSDavid du Colombier * Network specific translators 13180ee5cbfSDavid du Colombier */ 13280ee5cbfSDavid du Colombier Ndbtuple* iplookup(Network*, char*, char*, int); 13380ee5cbfSDavid du Colombier char* iptrans(Ndbtuple*, Network*, char*, char*, int); 13480ee5cbfSDavid du Colombier Ndbtuple* telcolookup(Network*, char*, char*, int); 13580ee5cbfSDavid du Colombier char* telcotrans(Ndbtuple*, Network*, char*, char*, int); 13680ee5cbfSDavid du Colombier Ndbtuple* dnsiplookup(char*, Ndbs*); 13780ee5cbfSDavid du Colombier 13880ee5cbfSDavid du Colombier struct Network 13980ee5cbfSDavid du Colombier { 14080ee5cbfSDavid du Colombier char *net; 14180ee5cbfSDavid du Colombier Ndbtuple *(*lookup)(Network*, char*, char*, int); 14280ee5cbfSDavid du Colombier char *(*trans)(Ndbtuple*, Network*, char*, char*, int); 14380ee5cbfSDavid du Colombier int considered; 14480ee5cbfSDavid du Colombier int fasttimeouthack; 14580ee5cbfSDavid du Colombier Network *next; 14680ee5cbfSDavid du Colombier }; 14780ee5cbfSDavid du Colombier 14880ee5cbfSDavid du Colombier enum 14980ee5cbfSDavid du Colombier { 15080ee5cbfSDavid du Colombier Nilfast, 15180ee5cbfSDavid du Colombier Ntcp, 15280ee5cbfSDavid du Colombier Nil, 15380ee5cbfSDavid du Colombier Nudp, 15480ee5cbfSDavid du Colombier Nicmp, 15580ee5cbfSDavid du Colombier Nrudp, 15680ee5cbfSDavid du Colombier Ntelco, 15780ee5cbfSDavid du Colombier }; 15880ee5cbfSDavid du Colombier 15980ee5cbfSDavid du Colombier /* 16080ee5cbfSDavid du Colombier * net doesn't apply to udp, icmp, or telco (for speed) 16180ee5cbfSDavid du Colombier */ 16280ee5cbfSDavid du Colombier Network network[] = { 16380ee5cbfSDavid du Colombier [Nilfast] { "il", iplookup, iptrans, 0, 1 }, 16480ee5cbfSDavid du Colombier [Ntcp] { "tcp", iplookup, iptrans, 0, 0 }, 16580ee5cbfSDavid du Colombier [Nil] { "il", iplookup, iptrans, 0, 0 }, 16680ee5cbfSDavid du Colombier [Nudp] { "udp", iplookup, iptrans, 1, 0 }, 16780ee5cbfSDavid du Colombier [Nicmp] { "icmp", iplookup, iptrans, 1, 0 }, 16880ee5cbfSDavid du Colombier [Nrudp] { "rudp", iplookup, iptrans, 1, 0 }, 16980ee5cbfSDavid du Colombier [Ntelco] { "telco", telcolookup, telcotrans, 1, 0 }, 17080ee5cbfSDavid du Colombier { 0 }, 17180ee5cbfSDavid du Colombier }; 17280ee5cbfSDavid du Colombier 17380ee5cbfSDavid du Colombier Lock ipifclock; 17480ee5cbfSDavid du Colombier Ipifc *ipifcs; 17580ee5cbfSDavid du Colombier 17680ee5cbfSDavid du Colombier char eaddr[Ndbvlen]; /* ascii ethernet address */ 17780ee5cbfSDavid du Colombier char ipaddr[Ndbvlen]; /* ascii internet address */ 17880ee5cbfSDavid du Colombier uchar ipa[IPaddrlen]; /* binary internet address */ 17980ee5cbfSDavid du Colombier char mysysname[Ndbvlen]; 18080ee5cbfSDavid du Colombier 18180ee5cbfSDavid du Colombier Network *netlist; /* networks ordered by preference */ 18280ee5cbfSDavid du Colombier Network *last; 18380ee5cbfSDavid du Colombier 1847dd7cddfSDavid du Colombier void 1857dd7cddfSDavid du Colombier usage(void) 1867dd7cddfSDavid du Colombier { 1877dd7cddfSDavid du Colombier fprint(2, "usage: %s [-d] [-f ndb-file] [-x netmtpt] [-n]\n", argv0); 1887dd7cddfSDavid du Colombier exits("usage"); 1897dd7cddfSDavid du Colombier } 190219b2ee8SDavid du Colombier 1913e12c5d1SDavid du Colombier void 1923e12c5d1SDavid du Colombier main(int argc, char *argv[]) 1933e12c5d1SDavid du Colombier { 1947dd7cddfSDavid du Colombier char servefile[Maxpath]; 195219b2ee8SDavid du Colombier int justsetname; 1967dd7cddfSDavid du Colombier char *p; 1977dd7cddfSDavid du Colombier char ext[Maxpath]; 1983e12c5d1SDavid du Colombier 199219b2ee8SDavid du Colombier justsetname = 0; 2007dd7cddfSDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), nil); 2017dd7cddfSDavid du Colombier ext[0] = 0; 2023e12c5d1SDavid du Colombier ARGBEGIN{ 2033e12c5d1SDavid du Colombier case 'd': 2043e12c5d1SDavid du Colombier debug = 1; 2053e12c5d1SDavid du Colombier break; 206bd389b36SDavid du Colombier case 'f': 2077dd7cddfSDavid du Colombier p = ARGF(); 2087dd7cddfSDavid du Colombier if(p == nil) 2097dd7cddfSDavid du Colombier usage(); 2107dd7cddfSDavid du Colombier dbfile = p; 2117dd7cddfSDavid du Colombier break; 2127dd7cddfSDavid du Colombier case 'x': 2137dd7cddfSDavid du Colombier p = ARGF(); 2147dd7cddfSDavid du Colombier if(p == nil) 2157dd7cddfSDavid du Colombier usage(); 2167dd7cddfSDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), p); 2177dd7cddfSDavid du Colombier setext(ext, sizeof(ext), mntpt); 218bd389b36SDavid du Colombier break; 219219b2ee8SDavid du Colombier case 'n': 220219b2ee8SDavid du Colombier justsetname = 1; 221219b2ee8SDavid du Colombier break; 2223e12c5d1SDavid du Colombier }ARGEND 2233e12c5d1SDavid du Colombier USED(argc); 2243e12c5d1SDavid du Colombier USED(argv); 2253e12c5d1SDavid du Colombier 2267dd7cddfSDavid du Colombier rfork(RFREND|RFNOTEG); 2277dd7cddfSDavid du Colombier 2287dd7cddfSDavid du Colombier snprint(servefile, sizeof(servefile), "#s/cs%s", ext); 2297dd7cddfSDavid du Colombier snprint(netndb, sizeof(netndb), "%s/ndb", mntpt); 2307dd7cddfSDavid du Colombier unmount(servefile, mntpt); 2317dd7cddfSDavid du Colombier remove(servefile); 2327dd7cddfSDavid du Colombier 2339a747e4fSDavid du Colombier fmtinstall('E', eipfmt); 2349a747e4fSDavid du Colombier fmtinstall('I', eipfmt); 2359a747e4fSDavid du Colombier fmtinstall('M', eipfmt); 2369a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 2377dd7cddfSDavid du Colombier 2387dd7cddfSDavid du Colombier ndbinit(); 2397dd7cddfSDavid du Colombier netinit(0); 2407dd7cddfSDavid du Colombier 2417dd7cddfSDavid du Colombier if(!justsetname){ 2427dd7cddfSDavid du Colombier mountinit(servefile, mntpt); 2437dd7cddfSDavid du Colombier io(); 2447dd7cddfSDavid du Colombier } 245219b2ee8SDavid du Colombier exits(0); 246219b2ee8SDavid du Colombier } 247219b2ee8SDavid du Colombier 2487dd7cddfSDavid du Colombier /* 2497dd7cddfSDavid du Colombier * if a mount point is specified, set the cs extention to be the mount point 2507dd7cddfSDavid du Colombier * with '_'s replacing '/'s 2517dd7cddfSDavid du Colombier */ 2527dd7cddfSDavid du Colombier void 2537dd7cddfSDavid du Colombier setext(char *ext, int n, char *p) 2547dd7cddfSDavid du Colombier { 2557dd7cddfSDavid du Colombier int i, c; 2563e12c5d1SDavid du Colombier 2577dd7cddfSDavid du Colombier n--; 2587dd7cddfSDavid du Colombier for(i = 0; i < n; i++){ 2597dd7cddfSDavid du Colombier c = p[i]; 2607dd7cddfSDavid du Colombier if(c == 0) 2617dd7cddfSDavid du Colombier break; 2627dd7cddfSDavid du Colombier if(c == '/') 2637dd7cddfSDavid du Colombier c = '_'; 2647dd7cddfSDavid du Colombier ext[i] = c; 2657dd7cddfSDavid du Colombier } 2667dd7cddfSDavid du Colombier ext[i] = 0; 2673e12c5d1SDavid du Colombier } 2683e12c5d1SDavid du Colombier 2693e12c5d1SDavid du Colombier void 2707dd7cddfSDavid du Colombier mountinit(char *service, char *mntpt) 2713e12c5d1SDavid du Colombier { 2723e12c5d1SDavid du Colombier int f; 2733e12c5d1SDavid du Colombier int p[2]; 2743e12c5d1SDavid du Colombier char buf[32]; 2753e12c5d1SDavid du Colombier 2763e12c5d1SDavid du Colombier if(pipe(p) < 0) 2773e12c5d1SDavid du Colombier error("pipe failed"); 278219b2ee8SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG)){ 2793e12c5d1SDavid du Colombier case 0: 280219b2ee8SDavid du Colombier close(p[1]); 2813e12c5d1SDavid du Colombier break; 2823e12c5d1SDavid du Colombier case -1: 2833e12c5d1SDavid du Colombier error("fork failed\n"); 2843e12c5d1SDavid du Colombier default: 2853e12c5d1SDavid du Colombier /* 2863e12c5d1SDavid du Colombier * make a /srv/cs 2873e12c5d1SDavid du Colombier */ 2883e12c5d1SDavid du Colombier f = create(service, 1, 0666); 2893e12c5d1SDavid du Colombier if(f < 0) 2903e12c5d1SDavid du Colombier error(service); 291bd389b36SDavid du Colombier snprint(buf, sizeof(buf), "%d", p[1]); 2923e12c5d1SDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf)) 293219b2ee8SDavid du Colombier error("write /srv/cs"); 2943e12c5d1SDavid du Colombier close(f); 2953e12c5d1SDavid du Colombier 2963e12c5d1SDavid du Colombier /* 2973e12c5d1SDavid du Colombier * put ourselves into the file system 2983e12c5d1SDavid du Colombier */ 299219b2ee8SDavid du Colombier close(p[0]); 3009a747e4fSDavid du Colombier if(mount(p[1], -1, mntpt, MAFTER, "") < 0) 3013e12c5d1SDavid du Colombier error("mount failed\n"); 302219b2ee8SDavid du Colombier _exits(0); 3033e12c5d1SDavid du Colombier } 3043e12c5d1SDavid du Colombier mfd[0] = mfd[1] = p[0]; 3053e12c5d1SDavid du Colombier } 3063e12c5d1SDavid du Colombier 3077dd7cddfSDavid du Colombier void 3087dd7cddfSDavid du Colombier ndbinit(void) 3097dd7cddfSDavid du Colombier { 3107dd7cddfSDavid du Colombier db = ndbopen(dbfile); 3117dd7cddfSDavid du Colombier if(db == nil) 3127dd7cddfSDavid du Colombier error("can't open network database"); 3137dd7cddfSDavid du Colombier 3147dd7cddfSDavid du Colombier netdb = ndbopen(netndb); 3157dd7cddfSDavid du Colombier if(netdb != nil){ 3167dd7cddfSDavid du Colombier netdb->nohash = 1; 3177dd7cddfSDavid du Colombier db = ndbcat(netdb, db); 3187dd7cddfSDavid du Colombier } 3197dd7cddfSDavid du Colombier } 3207dd7cddfSDavid du Colombier 3213e12c5d1SDavid du Colombier Mfile* 3223e12c5d1SDavid du Colombier newfid(int fid) 3233e12c5d1SDavid du Colombier { 324219b2ee8SDavid du Colombier Mlist *f, *ff; 3253e12c5d1SDavid du Colombier Mfile *mf; 3263e12c5d1SDavid du Colombier 327219b2ee8SDavid du Colombier ff = 0; 328219b2ee8SDavid du Colombier for(f = mlist; f; f = f->next) 329219b2ee8SDavid du Colombier if(f->mf.busy && f->mf.fid == fid) 330219b2ee8SDavid du Colombier return &f->mf; 331219b2ee8SDavid du Colombier else if(!ff && !f->mf.busy) 332219b2ee8SDavid du Colombier ff = f; 333219b2ee8SDavid du Colombier if(ff == 0){ 3347dd7cddfSDavid du Colombier ff = emalloc(sizeof *f); 335219b2ee8SDavid du Colombier ff->next = mlist; 336219b2ee8SDavid du Colombier mlist = ff; 3373e12c5d1SDavid du Colombier } 338219b2ee8SDavid du Colombier mf = &ff->mf; 339219b2ee8SDavid du Colombier memset(mf, 0, sizeof *mf); 3403e12c5d1SDavid du Colombier mf->fid = fid; 3413e12c5d1SDavid du Colombier return mf; 3423e12c5d1SDavid du Colombier } 3433e12c5d1SDavid du Colombier 3447dd7cddfSDavid du Colombier Job* 3457dd7cddfSDavid du Colombier newjob(void) 3467dd7cddfSDavid du Colombier { 3477dd7cddfSDavid du Colombier Job *job; 3487dd7cddfSDavid du Colombier 3497dd7cddfSDavid du Colombier job = mallocz(sizeof(Job), 1); 3507dd7cddfSDavid du Colombier lock(&joblock); 3517dd7cddfSDavid du Colombier job->next = joblist; 3527dd7cddfSDavid du Colombier joblist = job; 3537dd7cddfSDavid du Colombier job->request.tag = -1; 3547dd7cddfSDavid du Colombier unlock(&joblock); 3557dd7cddfSDavid du Colombier return job; 3567dd7cddfSDavid du Colombier } 3577dd7cddfSDavid du Colombier 3587dd7cddfSDavid du Colombier void 3597dd7cddfSDavid du Colombier freejob(Job *job) 3607dd7cddfSDavid du Colombier { 3617dd7cddfSDavid du Colombier Job **l; 3627dd7cddfSDavid du Colombier 3637dd7cddfSDavid du Colombier lock(&joblock); 3647dd7cddfSDavid du Colombier for(l = &joblist; *l; l = &(*l)->next){ 3657dd7cddfSDavid du Colombier if((*l) == job){ 3667dd7cddfSDavid du Colombier *l = job->next; 3677dd7cddfSDavid du Colombier free(job); 3687dd7cddfSDavid du Colombier break; 3697dd7cddfSDavid du Colombier } 3707dd7cddfSDavid du Colombier } 3717dd7cddfSDavid du Colombier unlock(&joblock); 3727dd7cddfSDavid du Colombier } 3737dd7cddfSDavid du Colombier 3747dd7cddfSDavid du Colombier void 3757dd7cddfSDavid du Colombier flushjob(int tag) 3767dd7cddfSDavid du Colombier { 3777dd7cddfSDavid du Colombier Job *job; 3787dd7cddfSDavid du Colombier 3797dd7cddfSDavid du Colombier lock(&joblock); 3807dd7cddfSDavid du Colombier for(job = joblist; job; job = job->next){ 3817dd7cddfSDavid du Colombier if(job->request.tag == tag && job->request.type != Tflush){ 3827dd7cddfSDavid du Colombier job->flushed = 1; 3837dd7cddfSDavid du Colombier break; 3847dd7cddfSDavid du Colombier } 3857dd7cddfSDavid du Colombier } 3867dd7cddfSDavid du Colombier unlock(&joblock); 3877dd7cddfSDavid du Colombier } 3887dd7cddfSDavid du Colombier 3893e12c5d1SDavid du Colombier void 3903e12c5d1SDavid du Colombier io(void) 3913e12c5d1SDavid du Colombier { 3923e12c5d1SDavid du Colombier long n; 3933e12c5d1SDavid du Colombier Mfile *mf; 3943e12c5d1SDavid du Colombier int slaveflag; 3959a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 3967dd7cddfSDavid du Colombier Job *job; 3973e12c5d1SDavid du Colombier 3983e12c5d1SDavid du Colombier /* 3993e12c5d1SDavid du Colombier * if we ask dns to fulfill requests, 4003e12c5d1SDavid du Colombier * a slave process is created to wait for replies. The 4019a747e4fSDavid du Colombier * master process returns immediately via a longjmp 4023e12c5d1SDavid du Colombier * through 'masterjmp'. 4033e12c5d1SDavid du Colombier * 4043e12c5d1SDavid du Colombier * *isslave is a pointer into the call stack to a variable 4053e12c5d1SDavid du Colombier * that tells whether or not the current process is a slave. 4063e12c5d1SDavid du Colombier */ 4073e12c5d1SDavid du Colombier slaveflag = 0; /* init slave variable */ 4083e12c5d1SDavid du Colombier isslave = &slaveflag; 4093e12c5d1SDavid du Colombier setjmp(masterjmp); 4103e12c5d1SDavid du Colombier 4113e12c5d1SDavid du Colombier for(;;){ 4129a747e4fSDavid du Colombier n = read9pmsg(mfd[0], mdata, sizeof mdata); 4133e12c5d1SDavid du Colombier if(n<=0) 4143e12c5d1SDavid du Colombier error("mount read"); 4157dd7cddfSDavid du Colombier job = newjob(); 4169a747e4fSDavid du Colombier if(convM2S(mdata, n, &job->request) != n){ 417219b2ee8SDavid du Colombier syslog(1, logfile, "format error %ux %ux %ux %ux %ux", mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]); 4187dd7cddfSDavid du Colombier freejob(job); 4193e12c5d1SDavid du Colombier continue; 4203e12c5d1SDavid du Colombier } 4217dd7cddfSDavid du Colombier if(job->request.fid<0) 4223e12c5d1SDavid du Colombier error("fid out of range"); 423bd389b36SDavid du Colombier lock(&dblock); 4247dd7cddfSDavid du Colombier mf = newfid(job->request.fid); 425219b2ee8SDavid du Colombier if(debug) 4267dd7cddfSDavid du Colombier syslog(0, logfile, "%F", &job->request); 4273e12c5d1SDavid du Colombier 4283e12c5d1SDavid du Colombier 4297dd7cddfSDavid du Colombier switch(job->request.type){ 4303e12c5d1SDavid du Colombier default: 4317dd7cddfSDavid du Colombier syslog(1, logfile, "unknown request type %d", job->request.type); 4323e12c5d1SDavid du Colombier break; 4339a747e4fSDavid du Colombier case Tversion: 4349a747e4fSDavid du Colombier rversion(job); 4353e12c5d1SDavid du Colombier break; 4369a747e4fSDavid du Colombier case Tauth: 4379a747e4fSDavid du Colombier rauth(job); 4383e12c5d1SDavid du Colombier break; 4393e12c5d1SDavid du Colombier case Tflush: 4407dd7cddfSDavid du Colombier rflush(job); 4413e12c5d1SDavid du Colombier break; 4423e12c5d1SDavid du Colombier case Tattach: 4437dd7cddfSDavid du Colombier rattach(job, mf); 4443e12c5d1SDavid du Colombier break; 4453e12c5d1SDavid du Colombier case Twalk: 4467dd7cddfSDavid du Colombier rwalk(job, mf); 4473e12c5d1SDavid du Colombier break; 4483e12c5d1SDavid du Colombier case Topen: 4497dd7cddfSDavid du Colombier ropen(job, mf); 4503e12c5d1SDavid du Colombier break; 4513e12c5d1SDavid du Colombier case Tcreate: 4527dd7cddfSDavid du Colombier rcreate(job, mf); 4533e12c5d1SDavid du Colombier break; 4543e12c5d1SDavid du Colombier case Tread: 4557dd7cddfSDavid du Colombier rread(job, mf); 4563e12c5d1SDavid du Colombier break; 4573e12c5d1SDavid du Colombier case Twrite: 4587dd7cddfSDavid du Colombier rwrite(job, mf); 4593e12c5d1SDavid du Colombier break; 4603e12c5d1SDavid du Colombier case Tclunk: 4617dd7cddfSDavid du Colombier rclunk(job, mf); 4623e12c5d1SDavid du Colombier break; 4633e12c5d1SDavid du Colombier case Tremove: 4647dd7cddfSDavid du Colombier rremove(job, mf); 4653e12c5d1SDavid du Colombier break; 4663e12c5d1SDavid du Colombier case Tstat: 4677dd7cddfSDavid du Colombier rstat(job, mf); 4683e12c5d1SDavid du Colombier break; 4693e12c5d1SDavid du Colombier case Twstat: 4707dd7cddfSDavid du Colombier rwstat(job, mf); 4713e12c5d1SDavid du Colombier break; 4723e12c5d1SDavid du Colombier } 473bd389b36SDavid du Colombier unlock(&dblock); 4747dd7cddfSDavid du Colombier 4757dd7cddfSDavid du Colombier freejob(job); 4767dd7cddfSDavid du Colombier 4773e12c5d1SDavid du Colombier /* 4783e12c5d1SDavid du Colombier * slave processes die after replying 4793e12c5d1SDavid du Colombier */ 480219b2ee8SDavid du Colombier if(*isslave){ 481219b2ee8SDavid du Colombier if(debug) 482219b2ee8SDavid du Colombier syslog(0, logfile, "slave death %d", getpid()); 4833e12c5d1SDavid du Colombier _exits(0); 4843e12c5d1SDavid du Colombier } 4853e12c5d1SDavid du Colombier } 486219b2ee8SDavid du Colombier } 487219b2ee8SDavid du Colombier 488219b2ee8SDavid du Colombier void 4899a747e4fSDavid du Colombier rversion(Job *job) 490219b2ee8SDavid du Colombier { 4919a747e4fSDavid du Colombier if(job->request.msize > IOHDRSZ + Maxfdata) 4929a747e4fSDavid du Colombier job->reply.msize = IOHDRSZ + Maxfdata; 4939a747e4fSDavid du Colombier else 4949a747e4fSDavid du Colombier job->reply.msize = job->request.msize; 4959a747e4fSDavid du Colombier if(strncmp(job->request.version, "9P2000", 6) != 0) 4969a747e4fSDavid du Colombier sendmsg(job, "unknown 9P version"); 4979a747e4fSDavid du Colombier else{ 4989a747e4fSDavid du Colombier job->reply.version = "9P2000"; 4997dd7cddfSDavid du Colombier sendmsg(job, 0); 500219b2ee8SDavid du Colombier } 5019a747e4fSDavid du Colombier } 5023e12c5d1SDavid du Colombier 5033e12c5d1SDavid du Colombier void 5049a747e4fSDavid du Colombier rauth(Job *job) 5053e12c5d1SDavid du Colombier { 506*3ff48bf5SDavid du Colombier sendmsg(job, "cs: authentication not required"); 5077dd7cddfSDavid du Colombier } 5087dd7cddfSDavid du Colombier 5097dd7cddfSDavid du Colombier /* 5107dd7cddfSDavid du Colombier * don't flush till all the slaves are done 5117dd7cddfSDavid du Colombier */ 5127dd7cddfSDavid du Colombier void 5137dd7cddfSDavid du Colombier rflush(Job *job) 5147dd7cddfSDavid du Colombier { 5157dd7cddfSDavid du Colombier flushjob(job->request.oldtag); 5167dd7cddfSDavid du Colombier sendmsg(job, 0); 5173e12c5d1SDavid du Colombier } 5183e12c5d1SDavid du Colombier 5193e12c5d1SDavid du Colombier void 5207dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf) 5213e12c5d1SDavid du Colombier { 5223e12c5d1SDavid du Colombier if(mf->busy == 0){ 5233e12c5d1SDavid du Colombier mf->busy = 1; 5249a747e4fSDavid du Colombier mf->user = estrdup(job->request.uname); 5253e12c5d1SDavid du Colombier } 5263e12c5d1SDavid du Colombier mf->qid.vers = vers++; 5279a747e4fSDavid du Colombier mf->qid.type = QTDIR; 5289a747e4fSDavid du Colombier mf->qid.path = 0LL; 5297dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 5307dd7cddfSDavid du Colombier sendmsg(job, 0); 5313e12c5d1SDavid du Colombier } 5323e12c5d1SDavid du Colombier 5333e12c5d1SDavid du Colombier 5343e12c5d1SDavid du Colombier char* 5357dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf) 5363e12c5d1SDavid du Colombier { 5373e12c5d1SDavid du Colombier char *err; 5389a747e4fSDavid du Colombier char **elems; 5399a747e4fSDavid du Colombier int nelems; 5409a747e4fSDavid du Colombier int i; 5419a747e4fSDavid du Colombier Mfile *nmf; 5429a747e4fSDavid du Colombier Qid qid; 5433e12c5d1SDavid du Colombier 5443e12c5d1SDavid du Colombier err = 0; 5459a747e4fSDavid du Colombier nmf = nil; 5469a747e4fSDavid du Colombier elems = job->request.wname; 5479a747e4fSDavid du Colombier nelems = job->request.nwname; 5489a747e4fSDavid du Colombier job->reply.nwqid = 0; 5499a747e4fSDavid du Colombier 5509a747e4fSDavid du Colombier if(job->request.newfid != job->request.fid){ 5519a747e4fSDavid du Colombier /* clone fid */ 5529a747e4fSDavid du Colombier if(job->request.newfid<0){ 5539a747e4fSDavid du Colombier err = "clone newfid out of range"; 5549a747e4fSDavid du Colombier goto send; 5559a747e4fSDavid du Colombier } 5569a747e4fSDavid du Colombier nmf = newfid(job->request.newfid); 5579a747e4fSDavid du Colombier if(nmf->busy){ 5589a747e4fSDavid du Colombier nmf = nil; 5599a747e4fSDavid du Colombier err = "clone to used channel"; 5609a747e4fSDavid du Colombier goto send; 5619a747e4fSDavid du Colombier } 5629a747e4fSDavid du Colombier *nmf = *mf; 5639a747e4fSDavid du Colombier nmf->user = estrdup(mf->user); 5649a747e4fSDavid du Colombier nmf->fid = job->request.newfid; 5659a747e4fSDavid du Colombier nmf->qid.vers = vers++; 5669a747e4fSDavid du Colombier mf = nmf; 5679a747e4fSDavid du Colombier } 5689a747e4fSDavid du Colombier /* else nmf will be nil */ 5699a747e4fSDavid du Colombier 5709a747e4fSDavid du Colombier qid = mf->qid; 5719a747e4fSDavid du Colombier if(nelems > 0){ 5729a747e4fSDavid du Colombier /* walk fid */ 5739a747e4fSDavid du Colombier for(i=0; i<nelems && i<MAXWELEM; i++){ 5749a747e4fSDavid du Colombier if((qid.type & QTDIR) == 0){ 5753e12c5d1SDavid du Colombier err = "not a directory"; 5769a747e4fSDavid du Colombier break; 5773e12c5d1SDavid du Colombier } 5789a747e4fSDavid du Colombier if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){ 5799a747e4fSDavid du Colombier qid.type = QTDIR; 5809a747e4fSDavid du Colombier qid.path = Qdir; 5819a747e4fSDavid du Colombier Found: 5829a747e4fSDavid du Colombier job->reply.wqid[i] = qid; 5839a747e4fSDavid du Colombier job->reply.nwqid++; 5849a747e4fSDavid du Colombier continue; 5853e12c5d1SDavid du Colombier } 5869a747e4fSDavid du Colombier if(strcmp(elems[i], "cs") == 0){ 5879a747e4fSDavid du Colombier qid.type = QTFILE; 5889a747e4fSDavid du Colombier qid.path = Qcs; 5899a747e4fSDavid du Colombier goto Found; 5903e12c5d1SDavid du Colombier } 5919a747e4fSDavid du Colombier err = "file does not exist"; 5929a747e4fSDavid du Colombier break; 5939a747e4fSDavid du Colombier } 5949a747e4fSDavid du Colombier } 5959a747e4fSDavid du Colombier 5963e12c5d1SDavid du Colombier send: 5979a747e4fSDavid du Colombier if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)){ 5989a747e4fSDavid du Colombier nmf->busy = 0; 5999a747e4fSDavid du Colombier nmf->fid = 0; 6009a747e4fSDavid du Colombier } 6019a747e4fSDavid du Colombier if(err == nil) 6029a747e4fSDavid du Colombier mf->qid = qid; 6037dd7cddfSDavid du Colombier sendmsg(job, err); 6043e12c5d1SDavid du Colombier return err; 6053e12c5d1SDavid du Colombier } 6063e12c5d1SDavid du Colombier 6073e12c5d1SDavid du Colombier void 6087dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf) 6093e12c5d1SDavid du Colombier { 6103e12c5d1SDavid du Colombier int mode; 6113e12c5d1SDavid du Colombier char *err; 6123e12c5d1SDavid du Colombier 6133e12c5d1SDavid du Colombier err = 0; 6147dd7cddfSDavid du Colombier mode = job->request.mode; 6159a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6163e12c5d1SDavid du Colombier if(mode) 6173e12c5d1SDavid du Colombier err = "permission denied"; 6189a747e4fSDavid du Colombier } 6197dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 6209a747e4fSDavid du Colombier job->reply.iounit = 0; 6217dd7cddfSDavid du Colombier sendmsg(job, err); 6223e12c5d1SDavid du Colombier } 6233e12c5d1SDavid du Colombier 6243e12c5d1SDavid du Colombier void 6257dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf) 6263e12c5d1SDavid du Colombier { 6273e12c5d1SDavid du Colombier USED(mf); 6287dd7cddfSDavid du Colombier sendmsg(job, "creation permission denied"); 6293e12c5d1SDavid du Colombier } 6303e12c5d1SDavid du Colombier 6313e12c5d1SDavid du Colombier void 6327dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf) 6333e12c5d1SDavid du Colombier { 634219b2ee8SDavid du Colombier int i, n, cnt; 635219b2ee8SDavid du Colombier long off, toff, clock; 6363e12c5d1SDavid du Colombier Dir dir; 6379a747e4fSDavid du Colombier uchar buf[Maxfdata]; 6383e12c5d1SDavid du Colombier char *err; 6393e12c5d1SDavid du Colombier 6403e12c5d1SDavid du Colombier n = 0; 6413e12c5d1SDavid du Colombier err = 0; 6427dd7cddfSDavid du Colombier off = job->request.offset; 6437dd7cddfSDavid du Colombier cnt = job->request.count; 6449a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6453e12c5d1SDavid du Colombier clock = time(0); 6463e12c5d1SDavid du Colombier if(off == 0){ 6479a747e4fSDavid du Colombier dir.name = "cs"; 6489a747e4fSDavid du Colombier dir.qid.type = QTFILE; 6493e12c5d1SDavid du Colombier dir.qid.vers = vers; 6503e12c5d1SDavid du Colombier dir.qid.path = Qcs; 6513e12c5d1SDavid du Colombier dir.mode = 0666; 6523e12c5d1SDavid du Colombier dir.length = 0; 6539a747e4fSDavid du Colombier dir.uid = mf->user; 6549a747e4fSDavid du Colombier dir.gid = mf->user; 6559a747e4fSDavid du Colombier dir.muid = mf->user; 6563e12c5d1SDavid du Colombier dir.atime = clock; /* wrong */ 6573e12c5d1SDavid du Colombier dir.mtime = clock; /* wrong */ 6589a747e4fSDavid du Colombier n = convD2M(&dir, buf, sizeof buf); 6593e12c5d1SDavid du Colombier } 6609a747e4fSDavid du Colombier job->reply.data = (char*)buf; 6613e12c5d1SDavid du Colombier } else { 66280ee5cbfSDavid du Colombier for(;;){ 66380ee5cbfSDavid du Colombier /* look for an answer at the right offset */ 664219b2ee8SDavid du Colombier toff = 0; 665219b2ee8SDavid du Colombier for(i = 0; mf->reply[i] && i < mf->nreply; i++){ 666219b2ee8SDavid du Colombier n = mf->replylen[i]; 667219b2ee8SDavid du Colombier if(off < toff + n) 668219b2ee8SDavid du Colombier break; 669219b2ee8SDavid du Colombier toff += n; 6703e12c5d1SDavid du Colombier } 67180ee5cbfSDavid du Colombier if(i < mf->nreply) 67280ee5cbfSDavid du Colombier break; /* got something to return */ 67380ee5cbfSDavid du Colombier 67480ee5cbfSDavid du Colombier /* try looking up more answers */ 67580ee5cbfSDavid du Colombier if(lookup(mf) == 0){ 67680ee5cbfSDavid du Colombier /* no more */ 677219b2ee8SDavid du Colombier n = 0; 678219b2ee8SDavid du Colombier goto send; 679219b2ee8SDavid du Colombier } 68080ee5cbfSDavid du Colombier } 68180ee5cbfSDavid du Colombier 68280ee5cbfSDavid du Colombier /* give back a single reply (or part of one) */ 6837dd7cddfSDavid du Colombier job->reply.data = mf->reply[i] + (off - toff); 684219b2ee8SDavid du Colombier if(cnt > toff - off + n) 685219b2ee8SDavid du Colombier n = toff - off + n; 686219b2ee8SDavid du Colombier else 687219b2ee8SDavid du Colombier n = cnt; 6883e12c5d1SDavid du Colombier } 6893e12c5d1SDavid du Colombier send: 6907dd7cddfSDavid du Colombier job->reply.count = n; 6917dd7cddfSDavid du Colombier sendmsg(job, err); 6927dd7cddfSDavid du Colombier } 69380ee5cbfSDavid du Colombier void 69480ee5cbfSDavid du Colombier cleanmf(Mfile *mf) 6957dd7cddfSDavid du Colombier { 6967dd7cddfSDavid du Colombier int i; 6977dd7cddfSDavid du Colombier 6989a747e4fSDavid du Colombier if(mf->net != nil){ 69980ee5cbfSDavid du Colombier free(mf->net); 70080ee5cbfSDavid du Colombier mf->net = nil; 7019a747e4fSDavid du Colombier } 7029a747e4fSDavid du Colombier if(mf->host != nil){ 70380ee5cbfSDavid du Colombier free(mf->host); 70480ee5cbfSDavid du Colombier mf->host = nil; 7059a747e4fSDavid du Colombier } 7069a747e4fSDavid du Colombier if(mf->serv != nil){ 70780ee5cbfSDavid du Colombier free(mf->serv); 70880ee5cbfSDavid du Colombier mf->serv = nil; 7099a747e4fSDavid du Colombier } 7109a747e4fSDavid du Colombier if(mf->rem != nil){ 71180ee5cbfSDavid du Colombier free(mf->rem); 71280ee5cbfSDavid du Colombier mf->rem = nil; 7139a747e4fSDavid du Colombier } 7149a747e4fSDavid du Colombier if(mf->user != nil){ 7159a747e4fSDavid du Colombier free(mf->user); 7169a747e4fSDavid du Colombier mf->user = nil; 7179a747e4fSDavid du Colombier } 71880ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++){ 71980ee5cbfSDavid du Colombier free(mf->reply[i]); 72080ee5cbfSDavid du Colombier mf->reply[i] = nil; 72180ee5cbfSDavid du Colombier mf->replylen[i] = 0; 7227dd7cddfSDavid du Colombier } 72380ee5cbfSDavid du Colombier mf->nreply = 0; 72480ee5cbfSDavid du Colombier mf->nextnet = netlist; 7253e12c5d1SDavid du Colombier } 7263e12c5d1SDavid du Colombier 7273e12c5d1SDavid du Colombier void 7287dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf) 7293e12c5d1SDavid du Colombier { 7303e12c5d1SDavid du Colombier int cnt, n; 73180ee5cbfSDavid du Colombier char *err; 7327dd7cddfSDavid du Colombier char *field[4]; 7333e12c5d1SDavid du Colombier 7343e12c5d1SDavid du Colombier err = 0; 7357dd7cddfSDavid du Colombier cnt = job->request.count; 7369a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 7373e12c5d1SDavid du Colombier err = "can't write directory"; 7383e12c5d1SDavid du Colombier goto send; 7393e12c5d1SDavid du Colombier } 7403e12c5d1SDavid du Colombier if(cnt >= Maxrequest){ 7413e12c5d1SDavid du Colombier err = "request too long"; 7423e12c5d1SDavid du Colombier goto send; 7433e12c5d1SDavid du Colombier } 7447dd7cddfSDavid du Colombier job->request.data[cnt] = 0; 7453e12c5d1SDavid du Colombier 7463e12c5d1SDavid du Colombier /* 747219b2ee8SDavid du Colombier * toggle debugging 748219b2ee8SDavid du Colombier */ 7497dd7cddfSDavid du Colombier if(strncmp(job->request.data, "debug", 5)==0){ 750219b2ee8SDavid du Colombier debug ^= 1; 751219b2ee8SDavid du Colombier syslog(1, logfile, "debug %d", debug); 752219b2ee8SDavid du Colombier goto send; 753219b2ee8SDavid du Colombier } 754219b2ee8SDavid du Colombier 755219b2ee8SDavid du Colombier /* 7567dd7cddfSDavid du Colombier * toggle debugging 7577dd7cddfSDavid du Colombier */ 7587dd7cddfSDavid du Colombier if(strncmp(job->request.data, "paranoia", 8)==0){ 7597dd7cddfSDavid du Colombier paranoia ^= 1; 7607dd7cddfSDavid du Colombier syslog(1, logfile, "paranoia %d", paranoia); 7617dd7cddfSDavid du Colombier goto send; 7627dd7cddfSDavid du Colombier } 7637dd7cddfSDavid du Colombier 7647dd7cddfSDavid du Colombier /* 7653e12c5d1SDavid du Colombier * add networks to the default list 7663e12c5d1SDavid du Colombier */ 7677dd7cddfSDavid du Colombier if(strncmp(job->request.data, "add ", 4)==0){ 7687dd7cddfSDavid du Colombier if(job->request.data[cnt-1] == '\n') 7697dd7cddfSDavid du Colombier job->request.data[cnt-1] = 0; 7707dd7cddfSDavid du Colombier netadd(job->request.data+4); 7717dd7cddfSDavid du Colombier readipinterfaces(); 7727dd7cddfSDavid du Colombier goto send; 7737dd7cddfSDavid du Colombier } 7747dd7cddfSDavid du Colombier 7757dd7cddfSDavid du Colombier /* 7767dd7cddfSDavid du Colombier * refresh all state 7777dd7cddfSDavid du Colombier */ 7787dd7cddfSDavid du Colombier if(strncmp(job->request.data, "refresh", 7)==0){ 7797dd7cddfSDavid du Colombier netinit(1); 7803e12c5d1SDavid du Colombier goto send; 7813e12c5d1SDavid du Colombier } 7823e12c5d1SDavid du Colombier 78380ee5cbfSDavid du Colombier /* start transaction with a clean slate */ 78480ee5cbfSDavid du Colombier cleanmf(mf); 78580ee5cbfSDavid du Colombier 7863e12c5d1SDavid du Colombier /* 787219b2ee8SDavid du Colombier * look for a general query 788219b2ee8SDavid du Colombier */ 7897dd7cddfSDavid du Colombier if(*job->request.data == '!'){ 7907dd7cddfSDavid du Colombier err = genquery(mf, job->request.data+1); 791219b2ee8SDavid du Colombier goto send; 792219b2ee8SDavid du Colombier } 793219b2ee8SDavid du Colombier 7947dd7cddfSDavid du Colombier if(debug) 7957dd7cddfSDavid du Colombier syslog(0, logfile, "write %s", job->request.data); 7967dd7cddfSDavid du Colombier if(paranoia) 7977dd7cddfSDavid du Colombier syslog(0, paranoiafile, "write %s by %s", job->request.data, mf->user); 7987dd7cddfSDavid du Colombier 799219b2ee8SDavid du Colombier /* 8003e12c5d1SDavid du Colombier * break up name 8013e12c5d1SDavid du Colombier */ 8027dd7cddfSDavid du Colombier n = getfields(job->request.data, field, 4, 1, "!"); 8033e12c5d1SDavid du Colombier switch(n){ 8043e12c5d1SDavid du Colombier case 1: 80580ee5cbfSDavid du Colombier mf->net = strdup("net"); 80680ee5cbfSDavid du Colombier mf->host = strdup(field[0]); 8077dd7cddfSDavid du Colombier break; 8087dd7cddfSDavid du Colombier case 4: 80980ee5cbfSDavid du Colombier mf->rem = strdup(field[3]); 81080ee5cbfSDavid du Colombier /* fall through */ 81180ee5cbfSDavid du Colombier case 3: 81280ee5cbfSDavid du Colombier mf->serv = strdup(field[2]); 81380ee5cbfSDavid du Colombier /* fall through */ 81480ee5cbfSDavid du Colombier case 2: 81580ee5cbfSDavid du Colombier mf->host = strdup(field[1]); 81680ee5cbfSDavid du Colombier mf->net = strdup(field[0]); 8173e12c5d1SDavid du Colombier break; 8183e12c5d1SDavid du Colombier } 8193e12c5d1SDavid du Colombier 82080ee5cbfSDavid du Colombier /* 82180ee5cbfSDavid du Colombier * do the first net worth of lookup 82280ee5cbfSDavid du Colombier */ 82380ee5cbfSDavid du Colombier if(lookup(mf) == 0) 8243e12c5d1SDavid du Colombier err = "can't translate address"; 8253e12c5d1SDavid du Colombier send: 8267dd7cddfSDavid du Colombier job->reply.count = cnt; 8277dd7cddfSDavid du Colombier sendmsg(job, err); 8283e12c5d1SDavid du Colombier } 8293e12c5d1SDavid du Colombier 8303e12c5d1SDavid du Colombier void 8317dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf) 8323e12c5d1SDavid du Colombier { 83380ee5cbfSDavid du Colombier cleanmf(mf); 8343e12c5d1SDavid du Colombier mf->busy = 0; 8353e12c5d1SDavid du Colombier mf->fid = 0; 8367dd7cddfSDavid du Colombier sendmsg(job, 0); 8373e12c5d1SDavid du Colombier } 8383e12c5d1SDavid du Colombier 8393e12c5d1SDavid du Colombier void 8407dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf) 8413e12c5d1SDavid du Colombier { 8423e12c5d1SDavid du Colombier USED(mf); 8437dd7cddfSDavid du Colombier sendmsg(job, "remove permission denied"); 8443e12c5d1SDavid du Colombier } 8453e12c5d1SDavid du Colombier 8463e12c5d1SDavid du Colombier void 8477dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf) 8483e12c5d1SDavid du Colombier { 8493e12c5d1SDavid du Colombier Dir dir; 8509a747e4fSDavid du Colombier uchar buf[IOHDRSZ+Maxfdata]; 8513e12c5d1SDavid du Colombier 8529a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 8539a747e4fSDavid du Colombier dir.name = "."; 8549a747e4fSDavid du Colombier dir.mode = DMDIR|0555; 855219b2ee8SDavid du Colombier } else { 8569a747e4fSDavid du Colombier dir.name = "cs"; 8573e12c5d1SDavid du Colombier dir.mode = 0666; 858219b2ee8SDavid du Colombier } 859219b2ee8SDavid du Colombier dir.qid = mf->qid; 8603e12c5d1SDavid du Colombier dir.length = 0; 8619a747e4fSDavid du Colombier dir.uid = mf->user; 8629a747e4fSDavid du Colombier dir.gid = mf->user; 8639a747e4fSDavid du Colombier dir.muid = mf->user; 8643e12c5d1SDavid du Colombier dir.atime = dir.mtime = time(0); 8659a747e4fSDavid du Colombier job->reply.nstat = convD2M(&dir, buf, sizeof buf); 8669a747e4fSDavid du Colombier job->reply.stat = buf; 8677dd7cddfSDavid du Colombier sendmsg(job, 0); 8683e12c5d1SDavid du Colombier } 8693e12c5d1SDavid du Colombier 8703e12c5d1SDavid du Colombier void 8717dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf) 8723e12c5d1SDavid du Colombier { 8733e12c5d1SDavid du Colombier USED(mf); 8747dd7cddfSDavid du Colombier sendmsg(job, "wstat permission denied"); 8753e12c5d1SDavid du Colombier } 8763e12c5d1SDavid du Colombier 8773e12c5d1SDavid du Colombier void 8787dd7cddfSDavid du Colombier sendmsg(Job *job, char *err) 8793e12c5d1SDavid du Colombier { 8803e12c5d1SDavid du Colombier int n; 8819a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 8829a747e4fSDavid du Colombier char ename[ERRMAX]; 8833e12c5d1SDavid du Colombier 8843e12c5d1SDavid du Colombier if(err){ 8857dd7cddfSDavid du Colombier job->reply.type = Rerror; 8869a747e4fSDavid du Colombier snprint(ename, sizeof(ename), "cs: %s", err); 8879a747e4fSDavid du Colombier job->reply.ename = ename; 8883e12c5d1SDavid du Colombier }else{ 8897dd7cddfSDavid du Colombier job->reply.type = job->request.type+1; 8903e12c5d1SDavid du Colombier } 8917dd7cddfSDavid du Colombier job->reply.tag = job->request.tag; 8929a747e4fSDavid du Colombier n = convS2M(&job->reply, mdata, sizeof mdata); 893219b2ee8SDavid du Colombier if(n == 0){ 8947dd7cddfSDavid du Colombier syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply); 895219b2ee8SDavid du Colombier abort(); 896219b2ee8SDavid du Colombier } 8977dd7cddfSDavid du Colombier lock(&joblock); 8987dd7cddfSDavid du Colombier if(job->flushed == 0) 8999a747e4fSDavid du Colombier if(write(mfd[1], mdata, n)!=n) 9003e12c5d1SDavid du Colombier error("mount write"); 9017dd7cddfSDavid du Colombier unlock(&joblock); 902219b2ee8SDavid du Colombier if(debug) 9037dd7cddfSDavid du Colombier syslog(0, logfile, "%F %d", &job->reply, n); 9043e12c5d1SDavid du Colombier } 9053e12c5d1SDavid du Colombier 9063e12c5d1SDavid du Colombier void 9073e12c5d1SDavid du Colombier error(char *s) 9083e12c5d1SDavid du Colombier { 909bd389b36SDavid du Colombier syslog(1, "cs", "%s: %r", s); 910bd389b36SDavid du Colombier _exits(0); 9113e12c5d1SDavid du Colombier } 9123e12c5d1SDavid du Colombier 9137dd7cddfSDavid du Colombier static int 9147dd7cddfSDavid du Colombier isvalidip(uchar *ip) 9157dd7cddfSDavid du Colombier { 9167dd7cddfSDavid du Colombier return ipcmp(ip, IPnoaddr) != 0 && ipcmp(ip, v4prefix) != 0; 9177dd7cddfSDavid du Colombier } 9183e12c5d1SDavid du Colombier 9197dd7cddfSDavid du Colombier void 9207dd7cddfSDavid du Colombier readipinterfaces(void) 9217dd7cddfSDavid du Colombier { 9229a747e4fSDavid du Colombier Ipifc *nifc; 9239a747e4fSDavid du Colombier Iplifc *lifc; 9247dd7cddfSDavid du Colombier 9259a747e4fSDavid du Colombier ipifcs = readipifc(mntpt, ipifcs, -1); 9269a747e4fSDavid du Colombier for(nifc = ipifcs; nifc; nifc = nifc->next) 9279a747e4fSDavid du Colombier for(lifc = nifc->lifc; lifc; lifc = lifc->next) 9289a747e4fSDavid du Colombier if(ipcmp(lifc->ip, IPnoaddr) != 0){ 9299a747e4fSDavid du Colombier ipmove(ipa, lifc->ip); 9307dd7cddfSDavid du Colombier sprint(ipaddr, "%I", ipa); 9317dd7cddfSDavid du Colombier if(debug) 9327dd7cddfSDavid du Colombier syslog(0, "dns", "ipaddr is %s\n", ipaddr); 933*3ff48bf5SDavid du Colombier return; 9347dd7cddfSDavid du Colombier } 9359a747e4fSDavid du Colombier ipmove(ipa, IPnoaddr); 9367dd7cddfSDavid du Colombier } 9373e12c5d1SDavid du Colombier 9383e12c5d1SDavid du Colombier /* 9397dd7cddfSDavid du Colombier * get the system name 9403e12c5d1SDavid du Colombier */ 9413e12c5d1SDavid du Colombier void 9423e12c5d1SDavid du Colombier ipid(void) 9433e12c5d1SDavid du Colombier { 9443e12c5d1SDavid du Colombier uchar addr[6]; 9453e12c5d1SDavid du Colombier Ndbtuple *t; 946219b2ee8SDavid du Colombier char *p, *attr; 9473e12c5d1SDavid du Colombier Ndbs s; 9483e12c5d1SDavid du Colombier int f; 9497dd7cddfSDavid du Colombier char buf[Maxpath]; 9503e12c5d1SDavid du Colombier 9513e12c5d1SDavid du Colombier 952219b2ee8SDavid du Colombier /* use environment, ether addr, or ipaddr to get system name */ 9537dd7cddfSDavid du Colombier if(*mysysname == 0){ 9547dd7cddfSDavid du Colombier /* 9557dd7cddfSDavid du Colombier * environment has priority. 9567dd7cddfSDavid du Colombier * 9577dd7cddfSDavid du Colombier * on the sgi power the default system name 9587dd7cddfSDavid du Colombier * is the ip address. ignore that. 9597dd7cddfSDavid du Colombier * 9607dd7cddfSDavid du Colombier */ 961219b2ee8SDavid du Colombier p = getenv("sysname"); 962219b2ee8SDavid du Colombier if(p){ 963219b2ee8SDavid du Colombier attr = ipattr(p); 964219b2ee8SDavid du Colombier if(strcmp(attr, "ip") != 0) 9657dd7cddfSDavid du Colombier strcpy(mysysname, p); 9663e12c5d1SDavid du Colombier } 9673e12c5d1SDavid du Colombier 9683e12c5d1SDavid du Colombier /* 9697dd7cddfSDavid du Colombier * the /net/ndb contains what the network 9707dd7cddfSDavid du Colombier * figured out from DHCP. use that name if 9717dd7cddfSDavid du Colombier * there is one. 9723e12c5d1SDavid du Colombier */ 9737dd7cddfSDavid du Colombier if(*mysysname == 0 && netdb != nil){ 9747dd7cddfSDavid du Colombier ndbreopen(netdb); 9757dd7cddfSDavid du Colombier for(t = ndbparse(netdb); t != nil; t = t->entry){ 9767dd7cddfSDavid du Colombier if(strcmp(t->attr, "sys") == 0){ 9777dd7cddfSDavid du Colombier strcpy(mysysname, t->val); 9783e12c5d1SDavid du Colombier break; 9793e12c5d1SDavid du Colombier } 9807dd7cddfSDavid du Colombier } 9817dd7cddfSDavid du Colombier ndbfree(t); 9827dd7cddfSDavid du Colombier } 9837dd7cddfSDavid du Colombier 9847dd7cddfSDavid du Colombier /* next network database, ip address, and ether address to find a name */ 9857dd7cddfSDavid du Colombier if(*mysysname == 0){ 9867dd7cddfSDavid du Colombier t = nil; 9877dd7cddfSDavid du Colombier if(isvalidip(ipa)) 9887dd7cddfSDavid du Colombier t = ndbgetval(db, &s, "ip", ipaddr, "sys", mysysname); 9897dd7cddfSDavid du Colombier else { 9907dd7cddfSDavid du Colombier for(f = 0; f < 3; f++){ 9917dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/ether%d", mntpt, f); 9927dd7cddfSDavid du Colombier if(myetheraddr(addr, buf) >= 0){ 9937dd7cddfSDavid du Colombier snprint(eaddr, sizeof(eaddr), "%E", addr); 9947dd7cddfSDavid du Colombier t = ndbgetval(db, &s, "ether", eaddr, "sys", 9957dd7cddfSDavid du Colombier mysysname); 9967dd7cddfSDavid du Colombier if(t != nil) 9977dd7cddfSDavid du Colombier break; 9987dd7cddfSDavid du Colombier } 9997dd7cddfSDavid du Colombier } 10007dd7cddfSDavid du Colombier } 10017dd7cddfSDavid du Colombier ndbfree(t); 10027dd7cddfSDavid du Colombier } 10037dd7cddfSDavid du Colombier 100480ee5cbfSDavid du Colombier /* nothing else worked, use the ip address */ 100580ee5cbfSDavid du Colombier if(*mysysname == 0 && isvalidip(ipa)) 100680ee5cbfSDavid du Colombier strcpy(mysysname, ipaddr); 100780ee5cbfSDavid du Colombier 100880ee5cbfSDavid du Colombier 10097dd7cddfSDavid du Colombier /* set /dev/mysysname if we now know it */ 10107dd7cddfSDavid du Colombier if(*mysysname){ 10117dd7cddfSDavid du Colombier f = open("/dev/sysname", OWRITE); 10127dd7cddfSDavid du Colombier if(f >= 0){ 10137dd7cddfSDavid du Colombier write(f, mysysname, strlen(mysysname)); 10143e12c5d1SDavid du Colombier close(f); 10153e12c5d1SDavid du Colombier } 10163e12c5d1SDavid du Colombier } 10173e12c5d1SDavid du Colombier } 10183e12c5d1SDavid du Colombier } 10193e12c5d1SDavid du Colombier 10203e12c5d1SDavid du Colombier /* 10213e12c5d1SDavid du Colombier * Set up a list of default networks by looking for 10223e12c5d1SDavid du Colombier * /net/ * /clone. 10233e12c5d1SDavid du Colombier */ 10243e12c5d1SDavid du Colombier void 10257dd7cddfSDavid du Colombier netinit(int background) 10263e12c5d1SDavid du Colombier { 10277dd7cddfSDavid du Colombier char clone[Maxpath]; 10283e12c5d1SDavid du Colombier Network *np; 10297dd7cddfSDavid du Colombier static int working; 10307dd7cddfSDavid du Colombier 10317dd7cddfSDavid du Colombier if(background){ 10327dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 10337dd7cddfSDavid du Colombier case 0: 10347dd7cddfSDavid du Colombier break; 10357dd7cddfSDavid du Colombier default: 10367dd7cddfSDavid du Colombier return; 10377dd7cddfSDavid du Colombier } 10387dd7cddfSDavid du Colombier lock(&netlock); 10397dd7cddfSDavid du Colombier } 10403e12c5d1SDavid du Colombier 10413e12c5d1SDavid du Colombier /* add the mounted networks to the default list */ 10423e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 10437dd7cddfSDavid du Colombier if(np->considered) 10447dd7cddfSDavid du Colombier continue; 10457dd7cddfSDavid du Colombier snprint(clone, sizeof(clone), "%s/%s/clone", mntpt, np->net); 10469a747e4fSDavid du Colombier if(access(clone, AEXIST) < 0) 10473e12c5d1SDavid du Colombier continue; 10483e12c5d1SDavid du Colombier if(netlist) 10493e12c5d1SDavid du Colombier last->next = np; 10503e12c5d1SDavid du Colombier else 10513e12c5d1SDavid du Colombier netlist = np; 10523e12c5d1SDavid du Colombier last = np; 10533e12c5d1SDavid du Colombier np->next = 0; 10547dd7cddfSDavid du Colombier np->considered = 1; 10553e12c5d1SDavid du Colombier } 10563e12c5d1SDavid du Colombier 10577dd7cddfSDavid du Colombier /* find out what our ip address is */ 10587dd7cddfSDavid du Colombier readipinterfaces(); 10593e12c5d1SDavid du Colombier 10607dd7cddfSDavid du Colombier /* set the system name if we need to, these says ip is all we have */ 10613e12c5d1SDavid du Colombier ipid(); 10623e12c5d1SDavid du Colombier 1063219b2ee8SDavid du Colombier if(debug) 10647dd7cddfSDavid du Colombier syslog(0, logfile, "mysysname %s eaddr %s ipaddr %s ipa %I\n", 10657dd7cddfSDavid du Colombier mysysname, eaddr, ipaddr, ipa); 10667dd7cddfSDavid du Colombier 10677dd7cddfSDavid du Colombier if(background){ 10687dd7cddfSDavid du Colombier unlock(&netlock); 10697dd7cddfSDavid du Colombier _exits(0); 10707dd7cddfSDavid du Colombier } 10713e12c5d1SDavid du Colombier } 10723e12c5d1SDavid du Colombier 10733e12c5d1SDavid du Colombier /* 10743e12c5d1SDavid du Colombier * add networks to the standard list 10753e12c5d1SDavid du Colombier */ 10763e12c5d1SDavid du Colombier void 10773e12c5d1SDavid du Colombier netadd(char *p) 10783e12c5d1SDavid du Colombier { 10793e12c5d1SDavid du Colombier Network *np; 10803e12c5d1SDavid du Colombier char *field[12]; 10813e12c5d1SDavid du Colombier int i, n; 10823e12c5d1SDavid du Colombier 10837dd7cddfSDavid du Colombier n = getfields(p, field, 12, 1, " "); 10843e12c5d1SDavid du Colombier for(i = 0; i < n; i++){ 10853e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 10863e12c5d1SDavid du Colombier if(strcmp(field[i], np->net) != 0) 10873e12c5d1SDavid du Colombier continue; 10887dd7cddfSDavid du Colombier if(np->considered) 10893e12c5d1SDavid du Colombier break; 10903e12c5d1SDavid du Colombier if(netlist) 10913e12c5d1SDavid du Colombier last->next = np; 10923e12c5d1SDavid du Colombier else 10933e12c5d1SDavid du Colombier netlist = np; 10943e12c5d1SDavid du Colombier last = np; 10953e12c5d1SDavid du Colombier np->next = 0; 10967dd7cddfSDavid du Colombier np->considered = 1; 10973e12c5d1SDavid du Colombier } 10983e12c5d1SDavid du Colombier } 10993e12c5d1SDavid du Colombier } 11003e12c5d1SDavid du Colombier 11013e12c5d1SDavid du Colombier /* 1102219b2ee8SDavid du Colombier * make a tuple 1103219b2ee8SDavid du Colombier */ 1104219b2ee8SDavid du Colombier Ndbtuple* 1105219b2ee8SDavid du Colombier mktuple(char *attr, char *val) 1106219b2ee8SDavid du Colombier { 1107219b2ee8SDavid du Colombier Ndbtuple *t; 1108219b2ee8SDavid du Colombier 11097dd7cddfSDavid du Colombier t = emalloc(sizeof(Ndbtuple)); 1110219b2ee8SDavid du Colombier strcpy(t->attr, attr); 1111219b2ee8SDavid du Colombier strncpy(t->val, val, sizeof(t->val)); 1112219b2ee8SDavid du Colombier t->val[sizeof(t->val)-1] = 0; 1113219b2ee8SDavid du Colombier t->line = t; 1114219b2ee8SDavid du Colombier t->entry = 0; 1115219b2ee8SDavid du Colombier return t; 1116219b2ee8SDavid du Colombier } 1117219b2ee8SDavid du Colombier 111880ee5cbfSDavid du Colombier int 111980ee5cbfSDavid du Colombier lookforproto(Ndbtuple *t, char *proto) 112080ee5cbfSDavid du Colombier { 112180ee5cbfSDavid du Colombier for(; t != nil; t = t->entry) 112280ee5cbfSDavid du Colombier if(strcmp(t->attr, "proto") == 0 && strcmp(t->val, proto) == 0) 112380ee5cbfSDavid du Colombier return 1; 112480ee5cbfSDavid du Colombier return 0; 112580ee5cbfSDavid du Colombier } 112680ee5cbfSDavid du Colombier 1127219b2ee8SDavid du Colombier /* 11283e12c5d1SDavid du Colombier * lookup a request. the network "net" means we should pick the 11293e12c5d1SDavid du Colombier * best network to get there. 11303e12c5d1SDavid du Colombier */ 11313e12c5d1SDavid du Colombier int 113280ee5cbfSDavid du Colombier lookup(Mfile *mf) 11333e12c5d1SDavid du Colombier { 113480ee5cbfSDavid du Colombier Network *np; 1135219b2ee8SDavid du Colombier char *cp; 1136219b2ee8SDavid du Colombier Ndbtuple *nt, *t; 1137219b2ee8SDavid du Colombier char reply[Maxreply]; 113880ee5cbfSDavid du Colombier int i, rv; 113980ee5cbfSDavid du Colombier int hack; 11403e12c5d1SDavid du Colombier 11413e12c5d1SDavid du Colombier /* open up the standard db files */ 11423e12c5d1SDavid du Colombier if(db == 0) 11437dd7cddfSDavid du Colombier ndbinit(); 11443e12c5d1SDavid du Colombier if(db == 0) 114580ee5cbfSDavid du Colombier error("can't open mf->network database\n"); 11463e12c5d1SDavid du Colombier 114780ee5cbfSDavid du Colombier rv = 0; 114880ee5cbfSDavid du Colombier 114980ee5cbfSDavid du Colombier if(mf->net == nil) 115080ee5cbfSDavid du Colombier return 0; /* must have been a genquery */ 115180ee5cbfSDavid du Colombier 115280ee5cbfSDavid du Colombier if(strcmp(mf->net, "net") == 0){ 11533e12c5d1SDavid du Colombier /* 11543e12c5d1SDavid du Colombier * go through set of default nets 11553e12c5d1SDavid du Colombier */ 115680ee5cbfSDavid du Colombier for(np = mf->nextnet; np; np = np->next){ 115780ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 115880ee5cbfSDavid du Colombier if(nt == nil) 1159219b2ee8SDavid du Colombier continue; 116080ee5cbfSDavid du Colombier hack = np->fasttimeouthack && !lookforproto(nt, np->net); 116180ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 116280ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, hack); 1163219b2ee8SDavid du Colombier if(cp){ 116480ee5cbfSDavid du Colombier /* avoid duplicates */ 116580ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++) 116680ee5cbfSDavid du Colombier if(strcmp(mf->reply[i], cp) == 0) 116780ee5cbfSDavid du Colombier break; 116880ee5cbfSDavid du Colombier if(i == mf->nreply){ 116980ee5cbfSDavid du Colombier /* save the reply */ 1170219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 1171219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = cp; 117280ee5cbfSDavid du Colombier rv++; 1173219b2ee8SDavid du Colombier } 1174219b2ee8SDavid du Colombier } 1175219b2ee8SDavid du Colombier } 1176219b2ee8SDavid du Colombier ndbfree(nt); 117780ee5cbfSDavid du Colombier np = np->next; 117880ee5cbfSDavid du Colombier break; 117980ee5cbfSDavid du Colombier } 118080ee5cbfSDavid du Colombier mf->nextnet = np; 118180ee5cbfSDavid du Colombier return rv; 118280ee5cbfSDavid du Colombier } 118380ee5cbfSDavid du Colombier 118480ee5cbfSDavid du Colombier /* 118580ee5cbfSDavid du Colombier * if not /net, we only get one lookup 118680ee5cbfSDavid du Colombier */ 118780ee5cbfSDavid du Colombier if(mf->nreply != 0) 1188219b2ee8SDavid du Colombier return 0; 118980ee5cbfSDavid du Colombier 119080ee5cbfSDavid du Colombier /* 119180ee5cbfSDavid du Colombier * look for a specific network 119280ee5cbfSDavid du Colombier */ 119380ee5cbfSDavid du Colombier for(np = netlist; np->net != nil; np++){ 119480ee5cbfSDavid du Colombier if(np->fasttimeouthack) 119580ee5cbfSDavid du Colombier continue; 119680ee5cbfSDavid du Colombier if(strcmp(np->net, mf->net) == 0) 119780ee5cbfSDavid du Colombier break; 119880ee5cbfSDavid du Colombier } 119980ee5cbfSDavid du Colombier 120080ee5cbfSDavid du Colombier if(np->net != nil){ 120180ee5cbfSDavid du Colombier /* 120280ee5cbfSDavid du Colombier * known network 120380ee5cbfSDavid du Colombier */ 120480ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 120580ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 120680ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, 0); 120780ee5cbfSDavid du Colombier if(cp){ 120880ee5cbfSDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 120980ee5cbfSDavid du Colombier mf->reply[mf->nreply++] = cp; 121080ee5cbfSDavid du Colombier rv++; 121180ee5cbfSDavid du Colombier } 121280ee5cbfSDavid du Colombier } 121380ee5cbfSDavid du Colombier ndbfree(nt); 121480ee5cbfSDavid du Colombier return rv; 12153e12c5d1SDavid du Colombier } else { 12163e12c5d1SDavid du Colombier /* 1217219b2ee8SDavid du Colombier * not a known network, don't translate host or service 12183e12c5d1SDavid du Colombier */ 121980ee5cbfSDavid du Colombier if(mf->serv) 12207dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s", 122180ee5cbfSDavid du Colombier mntpt, mf->net, mf->host, mf->serv); 1222bd389b36SDavid du Colombier else 12237dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s", 122480ee5cbfSDavid du Colombier mntpt, mf->net, mf->host); 1225219b2ee8SDavid du Colombier mf->reply[0] = strdup(reply); 1226219b2ee8SDavid du Colombier mf->replylen[0] = strlen(reply); 1227219b2ee8SDavid du Colombier mf->nreply = 1; 122880ee5cbfSDavid du Colombier return 1; 12293e12c5d1SDavid du Colombier } 12303e12c5d1SDavid du Colombier } 12313e12c5d1SDavid du Colombier 12323e12c5d1SDavid du Colombier /* 12333e12c5d1SDavid du Colombier * translate an ip service name into a port number. If it's a numeric port 12343e12c5d1SDavid du Colombier * number, look for restricted access. 12353e12c5d1SDavid du Colombier * 12363e12c5d1SDavid du Colombier * the service '*' needs no translation. 12373e12c5d1SDavid du Colombier */ 12383e12c5d1SDavid du Colombier char* 12393e12c5d1SDavid du Colombier ipserv(Network *np, char *name, char *buf) 12403e12c5d1SDavid du Colombier { 12413e12c5d1SDavid du Colombier char *p; 12423e12c5d1SDavid du Colombier int alpha = 0; 12433e12c5d1SDavid du Colombier int restr = 0; 12443e12c5d1SDavid du Colombier char port[Ndbvlen]; 12453e12c5d1SDavid du Colombier Ndbtuple *t, *nt; 12463e12c5d1SDavid du Colombier Ndbs s; 12473e12c5d1SDavid du Colombier 12483e12c5d1SDavid du Colombier /* '*' means any service */ 12493e12c5d1SDavid du Colombier if(strcmp(name, "*")==0){ 12503e12c5d1SDavid du Colombier strcpy(buf, name); 12513e12c5d1SDavid du Colombier return buf; 12523e12c5d1SDavid du Colombier } 12533e12c5d1SDavid du Colombier 12543e12c5d1SDavid du Colombier /* see if it's numeric or symbolic */ 12553e12c5d1SDavid du Colombier port[0] = 0; 12563e12c5d1SDavid du Colombier for(p = name; *p; p++){ 12573e12c5d1SDavid du Colombier if(isdigit(*p)) 12589a747e4fSDavid du Colombier {} 12593e12c5d1SDavid du Colombier else if(isalpha(*p) || *p == '-' || *p == '$') 12603e12c5d1SDavid du Colombier alpha = 1; 12613e12c5d1SDavid du Colombier else 12623e12c5d1SDavid du Colombier return 0; 12633e12c5d1SDavid du Colombier } 12643e12c5d1SDavid du Colombier if(alpha){ 12653e12c5d1SDavid du Colombier t = ndbgetval(db, &s, np->net, name, "port", port); 12663e12c5d1SDavid du Colombier if(t == 0) 12673e12c5d1SDavid du Colombier return 0; 12683e12c5d1SDavid du Colombier } else { 12693e12c5d1SDavid du Colombier t = ndbgetval(db, &s, "port", name, "port", port); 12703e12c5d1SDavid du Colombier if(t == 0){ 12713e12c5d1SDavid du Colombier strncpy(port, name, sizeof(port)); 12723e12c5d1SDavid du Colombier port[sizeof(port)-1] = 0; 12733e12c5d1SDavid du Colombier } 12743e12c5d1SDavid du Colombier } 12753e12c5d1SDavid du Colombier 12763e12c5d1SDavid du Colombier if(t){ 12773e12c5d1SDavid du Colombier for(nt = t; nt; nt = nt->entry) 12783e12c5d1SDavid du Colombier if(strcmp(nt->attr, "restricted") == 0) 12793e12c5d1SDavid du Colombier restr = 1; 12803e12c5d1SDavid du Colombier ndbfree(t); 12813e12c5d1SDavid du Colombier } 12823e12c5d1SDavid du Colombier sprint(buf, "%s%s", port, restr ? "!r" : ""); 12833e12c5d1SDavid du Colombier return buf; 12843e12c5d1SDavid du Colombier } 12853e12c5d1SDavid du Colombier 12863e12c5d1SDavid du Colombier /* 12877dd7cddfSDavid du Colombier * lookup an ip attribute 12883e12c5d1SDavid du Colombier */ 12897dd7cddfSDavid du Colombier int 12907dd7cddfSDavid du Colombier ipattrlookup(Ndb *db, char *ipa, char *attr, char *val) 12913e12c5d1SDavid du Colombier { 12923e12c5d1SDavid du Colombier 12937dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 12947dd7cddfSDavid du Colombier char *alist[2]; 12953e12c5d1SDavid du Colombier 12967dd7cddfSDavid du Colombier alist[0] = attr; 12977dd7cddfSDavid du Colombier t = ndbipinfo(db, "ip", ipa, alist, 1); 12987dd7cddfSDavid du Colombier if(t == nil) 12997dd7cddfSDavid du Colombier return 0; 13009a747e4fSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 13017dd7cddfSDavid du Colombier if(strcmp(nt->attr, attr) == 0){ 13027dd7cddfSDavid du Colombier strcpy(val, nt->val); 13033e12c5d1SDavid du Colombier ndbfree(t); 13047dd7cddfSDavid du Colombier return 1; 1305219b2ee8SDavid du Colombier } 13069a747e4fSDavid du Colombier } 13073e12c5d1SDavid du Colombier 13087dd7cddfSDavid du Colombier /* we shouldn't get here */ 13093e12c5d1SDavid du Colombier ndbfree(t); 13107dd7cddfSDavid du Colombier return 0; 13113e12c5d1SDavid du Colombier } 13123e12c5d1SDavid du Colombier 13133e12c5d1SDavid du Colombier /* 13143e12c5d1SDavid du Colombier * lookup (and translate) an ip destination 13153e12c5d1SDavid du Colombier */ 1316219b2ee8SDavid du Colombier Ndbtuple* 1317219b2ee8SDavid du Colombier iplookup(Network *np, char *host, char *serv, int nolookup) 13183e12c5d1SDavid du Colombier { 13193e12c5d1SDavid du Colombier char *attr; 13207dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13213e12c5d1SDavid du Colombier Ndbs s; 13223e12c5d1SDavid du Colombier char ts[Ndbvlen+1]; 13233e12c5d1SDavid du Colombier char th[Ndbvlen+1]; 13243e12c5d1SDavid du Colombier char dollar[Ndbvlen+1]; 13257dd7cddfSDavid du Colombier uchar ip[IPaddrlen]; 13267dd7cddfSDavid du Colombier uchar net[IPaddrlen]; 13277dd7cddfSDavid du Colombier uchar tnet[IPaddrlen]; 13287dd7cddfSDavid du Colombier Ipifc *ifc; 13299a747e4fSDavid du Colombier Iplifc *lifc; 13303e12c5d1SDavid du Colombier 1331219b2ee8SDavid du Colombier USED(nolookup); 1332219b2ee8SDavid du Colombier 13333e12c5d1SDavid du Colombier /* 13343e12c5d1SDavid du Colombier * start with the service since it's the most likely to fail 13353e12c5d1SDavid du Colombier * and costs the least 13363e12c5d1SDavid du Colombier */ 13377dd7cddfSDavid du Colombier if(serv==0 || ipserv(np, serv, ts) == 0){ 13387dd7cddfSDavid du Colombier werrstr("can't translate address"); 1339219b2ee8SDavid du Colombier return 0; 13407dd7cddfSDavid du Colombier } 13413e12c5d1SDavid du Colombier 13423e12c5d1SDavid du Colombier /* for dial strings with no host */ 1343219b2ee8SDavid du Colombier if(strcmp(host, "*") == 0) 1344219b2ee8SDavid du Colombier return mktuple("ip", "*"); 13453e12c5d1SDavid du Colombier 13463e12c5d1SDavid du Colombier /* 13477dd7cddfSDavid du Colombier * hack till we go v6 :: = 0.0.0.0 13487dd7cddfSDavid du Colombier */ 13497dd7cddfSDavid du Colombier if(strcmp("::", host) == 0) 13507dd7cddfSDavid du Colombier return mktuple("ip", "*"); 13517dd7cddfSDavid du Colombier 13527dd7cddfSDavid du Colombier /* 13533e12c5d1SDavid du Colombier * '$' means the rest of the name is an attribute that we 13543e12c5d1SDavid du Colombier * need to search for 13553e12c5d1SDavid du Colombier */ 13563e12c5d1SDavid du Colombier if(*host == '$'){ 13577dd7cddfSDavid du Colombier if(ipattrlookup(db, ipaddr, host+1, dollar)) 13583e12c5d1SDavid du Colombier host = dollar; 13593e12c5d1SDavid du Colombier } 13603e12c5d1SDavid du Colombier 13613e12c5d1SDavid du Colombier /* 13627dd7cddfSDavid du Colombier * turn '[ip address]' into just 'ip address' 13637dd7cddfSDavid du Colombier */ 13647dd7cddfSDavid du Colombier if(*host == '[' && host[strlen(host)-1] == ']'){ 13657dd7cddfSDavid du Colombier host++; 13667dd7cddfSDavid du Colombier host[strlen(host)-1] = 0; 13677dd7cddfSDavid du Colombier } 13687dd7cddfSDavid du Colombier 13697dd7cddfSDavid du Colombier /* 13703e12c5d1SDavid du Colombier * just accept addresses 13713e12c5d1SDavid du Colombier */ 1372219b2ee8SDavid du Colombier attr = ipattr(host); 1373219b2ee8SDavid du Colombier if(strcmp(attr, "ip") == 0) 1374219b2ee8SDavid du Colombier return mktuple("ip", host); 13753e12c5d1SDavid du Colombier 13763e12c5d1SDavid du Colombier /* 13773e12c5d1SDavid du Colombier * give the domain name server the first opportunity to 1378bd389b36SDavid du Colombier * resolve domain names. if that fails try the database. 13793e12c5d1SDavid du Colombier */ 13803e12c5d1SDavid du Colombier t = 0; 13813e12c5d1SDavid du Colombier if(strcmp(attr, "dom") == 0) 13827dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 13833e12c5d1SDavid du Colombier if(t == 0) 13843e12c5d1SDavid du Colombier t = ndbgetval(db, &s, attr, host, "ip", th); 13853e12c5d1SDavid du Colombier if(t == 0) 13867dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 13877dd7cddfSDavid du Colombier if(t == 0 && strcmp(attr, "dom") != 0) 13887dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 13897dd7cddfSDavid du Colombier if(t == 0) 1390219b2ee8SDavid du Colombier return 0; 1391bd389b36SDavid du Colombier 1392bd389b36SDavid du Colombier /* 1393bd389b36SDavid du Colombier * reorder the tuple to have the matched line first and 1394bd389b36SDavid du Colombier * save that in the request structure. 1395bd389b36SDavid du Colombier */ 13967dd7cddfSDavid du Colombier t = reorder(t, s.t); 13977dd7cddfSDavid du Colombier 13987dd7cddfSDavid du Colombier /* 13997dd7cddfSDavid du Colombier * reorder according to our interfaces 14007dd7cddfSDavid du Colombier */ 14017dd7cddfSDavid du Colombier lock(&ipifclock); 14029a747e4fSDavid du Colombier for(ifc = ipifcs; ifc != nil; ifc = ifc->next){ 14039a747e4fSDavid du Colombier for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ 14049a747e4fSDavid du Colombier maskip(lifc->ip, lifc->mask, net); 14057dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry){ 14067dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0) 14077dd7cddfSDavid du Colombier continue; 14087dd7cddfSDavid du Colombier parseip(ip, nt->val); 14099a747e4fSDavid du Colombier maskip(ip, lifc->mask, tnet); 14107dd7cddfSDavid du Colombier if(memcmp(net, tnet, IPaddrlen) == 0){ 14117dd7cddfSDavid du Colombier t = reorder(t, nt); 14127dd7cddfSDavid du Colombier unlock(&ipifclock); 14137dd7cddfSDavid du Colombier return t; 14147dd7cddfSDavid du Colombier } 14157dd7cddfSDavid du Colombier } 14167dd7cddfSDavid du Colombier } 14179a747e4fSDavid du Colombier } 14187dd7cddfSDavid du Colombier unlock(&ipifclock); 14197dd7cddfSDavid du Colombier 14207dd7cddfSDavid du Colombier return t; 14213e12c5d1SDavid du Colombier } 14223e12c5d1SDavid du Colombier 14233e12c5d1SDavid du Colombier /* 14243e12c5d1SDavid du Colombier * translate an ip address 14253e12c5d1SDavid du Colombier */ 1426219b2ee8SDavid du Colombier char* 142780ee5cbfSDavid du Colombier iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack) 14283e12c5d1SDavid du Colombier { 14293e12c5d1SDavid du Colombier char ts[Ndbvlen+1]; 1430219b2ee8SDavid du Colombier char reply[Maxreply]; 14317dd7cddfSDavid du Colombier char x[Ndbvlen+1]; 14323e12c5d1SDavid du Colombier 1433219b2ee8SDavid du Colombier if(strcmp(t->attr, "ip") != 0) 14343e12c5d1SDavid du Colombier return 0; 1435219b2ee8SDavid du Colombier 1436219b2ee8SDavid du Colombier if(serv == 0 || ipserv(np, serv, ts) == 0) 1437219b2ee8SDavid du Colombier return 0; 1438219b2ee8SDavid du Colombier 14397dd7cddfSDavid du Colombier if(rem != nil) 14407dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 14417dd7cddfSDavid du Colombier else 14427dd7cddfSDavid du Colombier *x = 0; 144380ee5cbfSDavid du Colombier 1444219b2ee8SDavid du Colombier if(*t->val == '*') 14457dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", 14467dd7cddfSDavid du Colombier mntpt, np->net, ts, x); 1447219b2ee8SDavid du Colombier else 144880ee5cbfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s%s", 144980ee5cbfSDavid du Colombier mntpt, np->net, t->val, ts, x, hack?"!fasttimeout":""); 1450219b2ee8SDavid du Colombier 1451219b2ee8SDavid du Colombier return strdup(reply); 14523e12c5d1SDavid du Colombier } 14533e12c5d1SDavid du Colombier 1454219b2ee8SDavid du Colombier /* 1455219b2ee8SDavid du Colombier * lookup a telephone number 1456219b2ee8SDavid du Colombier */ 1457219b2ee8SDavid du Colombier Ndbtuple* 1458219b2ee8SDavid du Colombier telcolookup(Network *np, char *host, char *serv, int nolookup) 1459219b2ee8SDavid du Colombier { 1460219b2ee8SDavid du Colombier Ndbtuple *t; 1461219b2ee8SDavid du Colombier Ndbs s; 1462219b2ee8SDavid du Colombier char th[Ndbvlen+1]; 1463219b2ee8SDavid du Colombier 1464219b2ee8SDavid du Colombier USED(np, nolookup, serv); 1465219b2ee8SDavid du Colombier 1466219b2ee8SDavid du Colombier t = ndbgetval(db, &s, "sys", host, "telco", th); 1467219b2ee8SDavid du Colombier if(t == 0) 1468219b2ee8SDavid du Colombier return mktuple("telco", host); 1469219b2ee8SDavid du Colombier 1470219b2ee8SDavid du Colombier return reorder(t, s.t); 1471219b2ee8SDavid du Colombier } 1472219b2ee8SDavid du Colombier 1473219b2ee8SDavid du Colombier /* 1474219b2ee8SDavid du Colombier * translate a telephone address 1475219b2ee8SDavid du Colombier */ 1476219b2ee8SDavid du Colombier char* 147780ee5cbfSDavid du Colombier telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int) 1478219b2ee8SDavid du Colombier { 1479219b2ee8SDavid du Colombier char reply[Maxreply]; 14807dd7cddfSDavid du Colombier char x[Ndbvlen+1]; 1481219b2ee8SDavid du Colombier 1482219b2ee8SDavid du Colombier if(strcmp(t->attr, "telco") != 0) 1483219b2ee8SDavid du Colombier return 0; 1484219b2ee8SDavid du Colombier 14857dd7cddfSDavid du Colombier if(rem != nil) 14867dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 1487219b2ee8SDavid du Colombier else 14887dd7cddfSDavid du Colombier *x = 0; 14897dd7cddfSDavid du Colombier if(serv) 14907dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s", mntpt, np->net, 14917dd7cddfSDavid du Colombier t->val, serv, x); 14927dd7cddfSDavid du Colombier else 14937dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net, 14947dd7cddfSDavid du Colombier t->val, x); 1495219b2ee8SDavid du Colombier return strdup(reply); 1496219b2ee8SDavid du Colombier } 14973e12c5d1SDavid du Colombier 14983e12c5d1SDavid du Colombier /* 14993e12c5d1SDavid du Colombier * reorder the tuple to put x's line first in the entry 15003e12c5d1SDavid du Colombier */ 15013e12c5d1SDavid du Colombier Ndbtuple* 15023e12c5d1SDavid du Colombier reorder(Ndbtuple *t, Ndbtuple *x) 15033e12c5d1SDavid du Colombier { 15043e12c5d1SDavid du Colombier Ndbtuple *nt; 15053e12c5d1SDavid du Colombier Ndbtuple *line; 15063e12c5d1SDavid du Colombier 1507219b2ee8SDavid du Colombier /* find start of this entry's line */ 1508219b2ee8SDavid du Colombier for(line = x; line->entry == line->line; line = line->line) 15093e12c5d1SDavid du Colombier ; 1510219b2ee8SDavid du Colombier line = line->line; 1511219b2ee8SDavid du Colombier if(line == t) 1512219b2ee8SDavid du Colombier return t; /* already the first line */ 15133e12c5d1SDavid du Colombier 1514219b2ee8SDavid du Colombier /* remove this line and everything after it from the entry */ 1515219b2ee8SDavid du Colombier for(nt = t; nt->entry != line; nt = nt->entry) 1516219b2ee8SDavid du Colombier ; 1517219b2ee8SDavid du Colombier nt->entry = 0; 15183e12c5d1SDavid du Colombier 1519219b2ee8SDavid du Colombier /* make that the start of the entry */ 1520219b2ee8SDavid du Colombier for(nt = line; nt->entry; nt = nt->entry) 1521219b2ee8SDavid du Colombier ; 15223e12c5d1SDavid du Colombier nt->entry = t; 15233e12c5d1SDavid du Colombier return line; 15243e12c5d1SDavid du Colombier } 15253e12c5d1SDavid du Colombier 15263e12c5d1SDavid du Colombier /* 15273e12c5d1SDavid du Colombier * create a slave process to handle a request to avoid one request blocking 15287dd7cddfSDavid du Colombier * another. parent returns to job loop. 15293e12c5d1SDavid du Colombier */ 15303e12c5d1SDavid du Colombier void 15313e12c5d1SDavid du Colombier slave(void) 15323e12c5d1SDavid du Colombier { 15333e12c5d1SDavid du Colombier if(*isslave) 15343e12c5d1SDavid du Colombier return; /* we're already a slave process */ 15353e12c5d1SDavid du Colombier 15363e12c5d1SDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 15373e12c5d1SDavid du Colombier case -1: 15383e12c5d1SDavid du Colombier break; 15393e12c5d1SDavid du Colombier case 0: 1540219b2ee8SDavid du Colombier if(debug) 1541219b2ee8SDavid du Colombier syslog(0, logfile, "slave %d", getpid()); 15423e12c5d1SDavid du Colombier *isslave = 1; 15433e12c5d1SDavid du Colombier break; 15443e12c5d1SDavid du Colombier default: 15453e12c5d1SDavid du Colombier longjmp(masterjmp, 1); 15463e12c5d1SDavid du Colombier } 15473e12c5d1SDavid du Colombier 1548219b2ee8SDavid du Colombier } 1549219b2ee8SDavid du Colombier 15503e12c5d1SDavid du Colombier /* 15513e12c5d1SDavid du Colombier * call the dns process and have it try to translate a name 15523e12c5d1SDavid du Colombier */ 15533e12c5d1SDavid du Colombier Ndbtuple* 15547dd7cddfSDavid du Colombier dnsiplookup(char *host, Ndbs *s) 15553e12c5d1SDavid du Colombier { 15563e12c5d1SDavid du Colombier char buf[Ndbvlen + 4]; 15577dd7cddfSDavid du Colombier Ndbtuple *t; 15583e12c5d1SDavid du Colombier 1559bd389b36SDavid du Colombier unlock(&dblock); 1560bd389b36SDavid du Colombier 15613e12c5d1SDavid du Colombier /* save the name before starting a slave */ 15627dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s", host); 15633e12c5d1SDavid du Colombier 15643e12c5d1SDavid du Colombier slave(); 15653e12c5d1SDavid du Colombier 15667dd7cddfSDavid du Colombier if(strcmp(ipattr(buf), "ip") == 0) 15677dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ptr"); 15687dd7cddfSDavid du Colombier else 15697dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ip"); 15703e12c5d1SDavid du Colombier s->t = t; 15717dd7cddfSDavid du Colombier 1572bd389b36SDavid du Colombier lock(&dblock); 15733e12c5d1SDavid du Colombier return t; 15743e12c5d1SDavid du Colombier } 1575219b2ee8SDavid du Colombier 1576219b2ee8SDavid du Colombier int 1577219b2ee8SDavid du Colombier qmatch(Ndbtuple *t, char **attr, char **val, int n) 1578219b2ee8SDavid du Colombier { 1579219b2ee8SDavid du Colombier int i, found; 1580219b2ee8SDavid du Colombier Ndbtuple *nt; 1581219b2ee8SDavid du Colombier 1582219b2ee8SDavid du Colombier for(i = 1; i < n; i++){ 1583219b2ee8SDavid du Colombier found = 0; 1584219b2ee8SDavid du Colombier for(nt = t; nt; nt = nt->entry) 1585219b2ee8SDavid du Colombier if(strcmp(attr[i], nt->attr) == 0) 1586219b2ee8SDavid du Colombier if(strcmp(val[i], "*") == 0 1587219b2ee8SDavid du Colombier || strcmp(val[i], nt->val) == 0){ 1588219b2ee8SDavid du Colombier found = 1; 1589219b2ee8SDavid du Colombier break; 1590219b2ee8SDavid du Colombier } 1591219b2ee8SDavid du Colombier if(found == 0) 1592219b2ee8SDavid du Colombier break; 1593219b2ee8SDavid du Colombier } 1594219b2ee8SDavid du Colombier return i == n; 1595219b2ee8SDavid du Colombier } 1596219b2ee8SDavid du Colombier 1597219b2ee8SDavid du Colombier void 1598219b2ee8SDavid du Colombier qreply(Mfile *mf, Ndbtuple *t) 1599219b2ee8SDavid du Colombier { 1600219b2ee8SDavid du Colombier int i; 1601219b2ee8SDavid du Colombier Ndbtuple *nt; 16027dd7cddfSDavid du Colombier char buf[2048]; 1603219b2ee8SDavid du Colombier 1604219b2ee8SDavid du Colombier buf[0] = 0; 1605219b2ee8SDavid du Colombier for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){ 1606219b2ee8SDavid du Colombier strcat(buf, nt->attr); 1607219b2ee8SDavid du Colombier strcat(buf, "="); 1608219b2ee8SDavid du Colombier strcat(buf, nt->val); 1609219b2ee8SDavid du Colombier i = strlen(buf); 1610219b2ee8SDavid du Colombier if(nt->line != nt->entry || sizeof(buf) - i < 2*Ndbvlen+2){ 1611219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(buf); 1612219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = strdup(buf); 1613219b2ee8SDavid du Colombier buf[0] = 0; 1614219b2ee8SDavid du Colombier } else 1615219b2ee8SDavid du Colombier strcat(buf, " "); 1616219b2ee8SDavid du Colombier } 1617219b2ee8SDavid du Colombier } 1618219b2ee8SDavid du Colombier 16197dd7cddfSDavid du Colombier enum 16207dd7cddfSDavid du Colombier { 16217dd7cddfSDavid du Colombier Maxattr= 32, 16227dd7cddfSDavid du Colombier }; 16237dd7cddfSDavid du Colombier 1624219b2ee8SDavid du Colombier /* 16257dd7cddfSDavid du Colombier * generic query lookup. The query is of one of the following 16267dd7cddfSDavid du Colombier * forms: 16277dd7cddfSDavid du Colombier * 16287dd7cddfSDavid du Colombier * attr1=val1 attr2=val2 attr3=val3 ... 16297dd7cddfSDavid du Colombier * 16307dd7cddfSDavid du Colombier * returns the matching tuple 16317dd7cddfSDavid du Colombier * 16327dd7cddfSDavid du Colombier * ipinfo attr=val attr1 attr2 attr3 ... 16337dd7cddfSDavid du Colombier * 16347dd7cddfSDavid du Colombier * is like ipinfo and returns the attr{1-n} 16357dd7cddfSDavid du Colombier * associated with the ip address. 1636219b2ee8SDavid du Colombier */ 1637219b2ee8SDavid du Colombier char* 1638219b2ee8SDavid du Colombier genquery(Mfile *mf, char *query) 1639219b2ee8SDavid du Colombier { 1640219b2ee8SDavid du Colombier int i, n; 1641219b2ee8SDavid du Colombier char *p; 16427dd7cddfSDavid du Colombier char *attr[Maxattr]; 16437dd7cddfSDavid du Colombier char *val[Maxattr]; 1644219b2ee8SDavid du Colombier Ndbtuple *t; 1645219b2ee8SDavid du Colombier Ndbs s; 1646219b2ee8SDavid du Colombier 16477dd7cddfSDavid du Colombier n = getfields(query, attr, 32, 1, " "); 1648219b2ee8SDavid du Colombier if(n == 0) 1649219b2ee8SDavid du Colombier return "bad query"; 1650219b2ee8SDavid du Colombier 16517dd7cddfSDavid du Colombier if(strcmp(attr[0], "ipinfo") == 0) 16527dd7cddfSDavid du Colombier return ipinfoquery(mf, attr, n); 16537dd7cddfSDavid du Colombier 1654219b2ee8SDavid du Colombier /* parse pairs */ 1655219b2ee8SDavid du Colombier for(i = 0; i < n; i++){ 1656219b2ee8SDavid du Colombier p = strchr(attr[i], '='); 1657219b2ee8SDavid du Colombier if(p == 0) 1658219b2ee8SDavid du Colombier return "bad query"; 1659219b2ee8SDavid du Colombier *p++ = 0; 1660219b2ee8SDavid du Colombier val[i] = p; 1661219b2ee8SDavid du Colombier } 1662219b2ee8SDavid du Colombier 1663219b2ee8SDavid du Colombier /* give dns a chance */ 1664219b2ee8SDavid du Colombier if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){ 16657dd7cddfSDavid du Colombier t = dnsiplookup(val[0], &s); 1666219b2ee8SDavid du Colombier if(t){ 1667219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1668219b2ee8SDavid du Colombier qreply(mf, t); 1669219b2ee8SDavid du Colombier ndbfree(t); 1670219b2ee8SDavid du Colombier return 0; 1671219b2ee8SDavid du Colombier } 1672219b2ee8SDavid du Colombier ndbfree(t); 1673219b2ee8SDavid du Colombier } 1674219b2ee8SDavid du Colombier } 1675219b2ee8SDavid du Colombier 1676219b2ee8SDavid du Colombier /* first pair is always the key. It can't be a '*' */ 1677219b2ee8SDavid du Colombier t = ndbsearch(db, &s, attr[0], val[0]); 1678219b2ee8SDavid du Colombier 1679219b2ee8SDavid du Colombier /* search is the and of all the pairs */ 1680219b2ee8SDavid du Colombier while(t){ 1681219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1682219b2ee8SDavid du Colombier qreply(mf, t); 1683219b2ee8SDavid du Colombier ndbfree(t); 1684219b2ee8SDavid du Colombier return 0; 1685219b2ee8SDavid du Colombier } 1686219b2ee8SDavid du Colombier 1687219b2ee8SDavid du Colombier ndbfree(t); 1688219b2ee8SDavid du Colombier t = ndbsnext(&s, attr[0], val[0]); 1689219b2ee8SDavid du Colombier } 1690219b2ee8SDavid du Colombier 1691219b2ee8SDavid du Colombier return "no match"; 1692219b2ee8SDavid du Colombier } 16937dd7cddfSDavid du Colombier 16947dd7cddfSDavid du Colombier /* 16957dd7cddfSDavid du Colombier * resolve an ip address 16967dd7cddfSDavid du Colombier */ 16977dd7cddfSDavid du Colombier static Ndbtuple* 16987dd7cddfSDavid du Colombier ipresolve(char *attr, char *host) 16997dd7cddfSDavid du Colombier { 17007dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17017dd7cddfSDavid du Colombier 17027dd7cddfSDavid du Colombier t = iplookup(&network[Ntcp], host, "*", 0); 17037dd7cddfSDavid du Colombier for(l = &t; *l != nil; ){ 17047dd7cddfSDavid du Colombier nt = *l; 17057dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0){ 17067dd7cddfSDavid du Colombier *l = nt->entry; 17077dd7cddfSDavid du Colombier nt->entry = nil; 17087dd7cddfSDavid du Colombier ndbfree(nt); 17097dd7cddfSDavid du Colombier continue; 17107dd7cddfSDavid du Colombier } 17117dd7cddfSDavid du Colombier strcpy(nt->attr, attr); 17127dd7cddfSDavid du Colombier l = &nt->entry; 17137dd7cddfSDavid du Colombier } 17147dd7cddfSDavid du Colombier return t; 17157dd7cddfSDavid du Colombier } 17167dd7cddfSDavid du Colombier 17177dd7cddfSDavid du Colombier char* 17187dd7cddfSDavid du Colombier ipinfoquery(Mfile *mf, char **list, int n) 17197dd7cddfSDavid du Colombier { 17207dd7cddfSDavid du Colombier int i, nresolve; 17217dd7cddfSDavid du Colombier int resolve[Maxattr]; 17227dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17237dd7cddfSDavid du Colombier char *attr, *val; 17247dd7cddfSDavid du Colombier 17257dd7cddfSDavid du Colombier /* skip 'ipinfo' */ 17267dd7cddfSDavid du Colombier list++; n--; 17277dd7cddfSDavid du Colombier 17287dd7cddfSDavid du Colombier if(n < 2) 17297dd7cddfSDavid du Colombier return "bad query"; 17307dd7cddfSDavid du Colombier 17317dd7cddfSDavid du Colombier /* get search attribute=value */ 17327dd7cddfSDavid du Colombier attr = *list++; n--; 17337dd7cddfSDavid du Colombier val = strchr(attr, '='); 17347dd7cddfSDavid du Colombier if(val == nil) 17357dd7cddfSDavid du Colombier return "bad query"; 17367dd7cddfSDavid du Colombier *val++ = 0; 17377dd7cddfSDavid du Colombier 17387dd7cddfSDavid du Colombier /* 17397dd7cddfSDavid du Colombier * don't let ndbipinfo resolve the addresses, we're 17407dd7cddfSDavid du Colombier * better at it. 17417dd7cddfSDavid du Colombier */ 17427dd7cddfSDavid du Colombier nresolve = 0; 17437dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 17447dd7cddfSDavid du Colombier if(*list[i] == '@'){ 17457dd7cddfSDavid du Colombier list[i]++; 17467dd7cddfSDavid du Colombier resolve[i] = 1; 17477dd7cddfSDavid du Colombier nresolve++; 17487dd7cddfSDavid du Colombier } else 17497dd7cddfSDavid du Colombier resolve[i] = 0; 17507dd7cddfSDavid du Colombier 17517dd7cddfSDavid du Colombier t = ndbipinfo(db, attr, val, list, n); 17527dd7cddfSDavid du Colombier if(t == nil) 17537dd7cddfSDavid du Colombier return "no match"; 17547dd7cddfSDavid du Colombier 17557dd7cddfSDavid du Colombier if(nresolve != 0){ 17567dd7cddfSDavid du Colombier for(l = &t; *l != nil;){ 17577dd7cddfSDavid du Colombier nt = *l; 17587dd7cddfSDavid du Colombier 17597dd7cddfSDavid du Colombier /* already an address? */ 17607dd7cddfSDavid du Colombier if(strcmp(ipattr(nt->val), "ip") == 0){ 17617dd7cddfSDavid du Colombier l = &(*l)->entry; 17627dd7cddfSDavid du Colombier continue; 17637dd7cddfSDavid du Colombier } 17647dd7cddfSDavid du Colombier 17657dd7cddfSDavid du Colombier /* user wants it resolved? */ 17667dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 17677dd7cddfSDavid du Colombier if(strcmp(list[i], nt->attr) == 0) 17687dd7cddfSDavid du Colombier break; 17697dd7cddfSDavid du Colombier if(i >= n || resolve[i] == 0){ 17707dd7cddfSDavid du Colombier l = &(*l)->entry; 17717dd7cddfSDavid du Colombier continue; 17727dd7cddfSDavid du Colombier } 17737dd7cddfSDavid du Colombier 17747dd7cddfSDavid du Colombier /* resolve address and replace entry */ 17757dd7cddfSDavid du Colombier *l = ipresolve(nt->attr, nt->val); 17767dd7cddfSDavid du Colombier while(*l != nil) 17777dd7cddfSDavid du Colombier l = &(*l)->entry; 17787dd7cddfSDavid du Colombier *l = nt->entry; 17797dd7cddfSDavid du Colombier 17807dd7cddfSDavid du Colombier nt->entry = nil; 17817dd7cddfSDavid du Colombier ndbfree(nt); 17827dd7cddfSDavid du Colombier } 17837dd7cddfSDavid du Colombier } 17847dd7cddfSDavid du Colombier 17857dd7cddfSDavid du Colombier /* make it all one line */ 17867dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 17877dd7cddfSDavid du Colombier if(nt->entry == nil) 17887dd7cddfSDavid du Colombier nt->line = t; 17897dd7cddfSDavid du Colombier else 17907dd7cddfSDavid du Colombier nt->line = nt->entry; 17917dd7cddfSDavid du Colombier } 17927dd7cddfSDavid du Colombier 17937dd7cddfSDavid du Colombier qreply(mf, t); 17947dd7cddfSDavid du Colombier 17957dd7cddfSDavid du Colombier return nil; 17967dd7cddfSDavid du Colombier } 17977dd7cddfSDavid du Colombier 17987dd7cddfSDavid du Colombier void* 17997dd7cddfSDavid du Colombier emalloc(int size) 18007dd7cddfSDavid du Colombier { 18017dd7cddfSDavid du Colombier void *x; 18027dd7cddfSDavid du Colombier 18037dd7cddfSDavid du Colombier x = malloc(size); 18047dd7cddfSDavid du Colombier if(x == nil) 18057dd7cddfSDavid du Colombier abort(); 18067dd7cddfSDavid du Colombier memset(x, 0, size); 18077dd7cddfSDavid du Colombier return x; 18087dd7cddfSDavid du Colombier } 18099a747e4fSDavid du Colombier 18109a747e4fSDavid du Colombier char* 18119a747e4fSDavid du Colombier estrdup(char *s) 18129a747e4fSDavid du Colombier { 18139a747e4fSDavid du Colombier int size; 18149a747e4fSDavid du Colombier char *p; 18159a747e4fSDavid du Colombier 18169a747e4fSDavid du Colombier size = strlen(s)+1; 18179a747e4fSDavid du Colombier p = malloc(size); 18189a747e4fSDavid du Colombier if(p == nil) 18199a747e4fSDavid du Colombier abort(); 18209a747e4fSDavid du Colombier memmove(p, s, size); 18219a747e4fSDavid du Colombier return p; 18229a747e4fSDavid du Colombier } 1823