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){ 417271b8d73SDavid du Colombier syslog(1, logfile, "format error %ux %ux %ux %ux %ux", 418271b8d73SDavid du Colombier mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]); 4197dd7cddfSDavid du Colombier freejob(job); 4203e12c5d1SDavid du Colombier continue; 4213e12c5d1SDavid du Colombier } 4227dd7cddfSDavid du Colombier if(job->request.fid<0) 4233e12c5d1SDavid du Colombier error("fid out of range"); 424bd389b36SDavid du Colombier lock(&dblock); 4257dd7cddfSDavid du Colombier mf = newfid(job->request.fid); 426219b2ee8SDavid du Colombier if(debug) 4277dd7cddfSDavid du Colombier syslog(0, logfile, "%F", &job->request); 4283e12c5d1SDavid du Colombier 4293e12c5d1SDavid du Colombier 4307dd7cddfSDavid du Colombier switch(job->request.type){ 4313e12c5d1SDavid du Colombier default: 4327dd7cddfSDavid du Colombier syslog(1, logfile, "unknown request type %d", job->request.type); 4333e12c5d1SDavid du Colombier break; 4349a747e4fSDavid du Colombier case Tversion: 4359a747e4fSDavid du Colombier rversion(job); 4363e12c5d1SDavid du Colombier break; 4379a747e4fSDavid du Colombier case Tauth: 4389a747e4fSDavid du Colombier rauth(job); 4393e12c5d1SDavid du Colombier break; 4403e12c5d1SDavid du Colombier case Tflush: 4417dd7cddfSDavid du Colombier rflush(job); 4423e12c5d1SDavid du Colombier break; 4433e12c5d1SDavid du Colombier case Tattach: 4447dd7cddfSDavid du Colombier rattach(job, mf); 4453e12c5d1SDavid du Colombier break; 4463e12c5d1SDavid du Colombier case Twalk: 4477dd7cddfSDavid du Colombier rwalk(job, mf); 4483e12c5d1SDavid du Colombier break; 4493e12c5d1SDavid du Colombier case Topen: 4507dd7cddfSDavid du Colombier ropen(job, mf); 4513e12c5d1SDavid du Colombier break; 4523e12c5d1SDavid du Colombier case Tcreate: 4537dd7cddfSDavid du Colombier rcreate(job, mf); 4543e12c5d1SDavid du Colombier break; 4553e12c5d1SDavid du Colombier case Tread: 4567dd7cddfSDavid du Colombier rread(job, mf); 4573e12c5d1SDavid du Colombier break; 4583e12c5d1SDavid du Colombier case Twrite: 4597dd7cddfSDavid du Colombier rwrite(job, mf); 4603e12c5d1SDavid du Colombier break; 4613e12c5d1SDavid du Colombier case Tclunk: 4627dd7cddfSDavid du Colombier rclunk(job, mf); 4633e12c5d1SDavid du Colombier break; 4643e12c5d1SDavid du Colombier case Tremove: 4657dd7cddfSDavid du Colombier rremove(job, mf); 4663e12c5d1SDavid du Colombier break; 4673e12c5d1SDavid du Colombier case Tstat: 4687dd7cddfSDavid du Colombier rstat(job, mf); 4693e12c5d1SDavid du Colombier break; 4703e12c5d1SDavid du Colombier case Twstat: 4717dd7cddfSDavid du Colombier rwstat(job, mf); 4723e12c5d1SDavid du Colombier break; 4733e12c5d1SDavid du Colombier } 474bd389b36SDavid du Colombier unlock(&dblock); 4757dd7cddfSDavid du Colombier 4767dd7cddfSDavid du Colombier freejob(job); 4777dd7cddfSDavid du Colombier 4783e12c5d1SDavid du Colombier /* 4793e12c5d1SDavid du Colombier * slave processes die after replying 4803e12c5d1SDavid du Colombier */ 481219b2ee8SDavid du Colombier if(*isslave){ 482219b2ee8SDavid du Colombier if(debug) 483219b2ee8SDavid du Colombier syslog(0, logfile, "slave death %d", getpid()); 4843e12c5d1SDavid du Colombier _exits(0); 4853e12c5d1SDavid du Colombier } 4863e12c5d1SDavid du Colombier } 487219b2ee8SDavid du Colombier } 488219b2ee8SDavid du Colombier 489219b2ee8SDavid du Colombier void 4909a747e4fSDavid du Colombier rversion(Job *job) 491219b2ee8SDavid du Colombier { 4929a747e4fSDavid du Colombier if(job->request.msize > IOHDRSZ + Maxfdata) 4939a747e4fSDavid du Colombier job->reply.msize = IOHDRSZ + Maxfdata; 4949a747e4fSDavid du Colombier else 4959a747e4fSDavid du Colombier job->reply.msize = job->request.msize; 4969a747e4fSDavid du Colombier if(strncmp(job->request.version, "9P2000", 6) != 0) 4979a747e4fSDavid du Colombier sendmsg(job, "unknown 9P version"); 4989a747e4fSDavid du Colombier else{ 4999a747e4fSDavid du Colombier job->reply.version = "9P2000"; 5007dd7cddfSDavid du Colombier sendmsg(job, 0); 501219b2ee8SDavid du Colombier } 5029a747e4fSDavid du Colombier } 5033e12c5d1SDavid du Colombier 5043e12c5d1SDavid du Colombier void 5059a747e4fSDavid du Colombier rauth(Job *job) 5063e12c5d1SDavid du Colombier { 5073ff48bf5SDavid du Colombier sendmsg(job, "cs: authentication not required"); 5087dd7cddfSDavid du Colombier } 5097dd7cddfSDavid du Colombier 5107dd7cddfSDavid du Colombier /* 5117dd7cddfSDavid du Colombier * don't flush till all the slaves are done 5127dd7cddfSDavid du Colombier */ 5137dd7cddfSDavid du Colombier void 5147dd7cddfSDavid du Colombier rflush(Job *job) 5157dd7cddfSDavid du Colombier { 5167dd7cddfSDavid du Colombier flushjob(job->request.oldtag); 5177dd7cddfSDavid du Colombier sendmsg(job, 0); 5183e12c5d1SDavid du Colombier } 5193e12c5d1SDavid du Colombier 5203e12c5d1SDavid du Colombier void 5217dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf) 5223e12c5d1SDavid du Colombier { 5233e12c5d1SDavid du Colombier if(mf->busy == 0){ 5243e12c5d1SDavid du Colombier mf->busy = 1; 5259a747e4fSDavid du Colombier mf->user = estrdup(job->request.uname); 5263e12c5d1SDavid du Colombier } 5273e12c5d1SDavid du Colombier mf->qid.vers = vers++; 5289a747e4fSDavid du Colombier mf->qid.type = QTDIR; 5299a747e4fSDavid du Colombier mf->qid.path = 0LL; 5307dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 5317dd7cddfSDavid du Colombier sendmsg(job, 0); 5323e12c5d1SDavid du Colombier } 5333e12c5d1SDavid du Colombier 5343e12c5d1SDavid du Colombier 5353e12c5d1SDavid du Colombier char* 5367dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf) 5373e12c5d1SDavid du Colombier { 5383e12c5d1SDavid du Colombier char *err; 5399a747e4fSDavid du Colombier char **elems; 5409a747e4fSDavid du Colombier int nelems; 5419a747e4fSDavid du Colombier int i; 5429a747e4fSDavid du Colombier Mfile *nmf; 5439a747e4fSDavid du Colombier Qid qid; 5443e12c5d1SDavid du Colombier 5453e12c5d1SDavid du Colombier err = 0; 5469a747e4fSDavid du Colombier nmf = nil; 5479a747e4fSDavid du Colombier elems = job->request.wname; 5489a747e4fSDavid du Colombier nelems = job->request.nwname; 5499a747e4fSDavid du Colombier job->reply.nwqid = 0; 5509a747e4fSDavid du Colombier 5519a747e4fSDavid du Colombier if(job->request.newfid != job->request.fid){ 5529a747e4fSDavid du Colombier /* clone fid */ 5539a747e4fSDavid du Colombier if(job->request.newfid<0){ 5549a747e4fSDavid du Colombier err = "clone newfid out of range"; 5559a747e4fSDavid du Colombier goto send; 5569a747e4fSDavid du Colombier } 5579a747e4fSDavid du Colombier nmf = newfid(job->request.newfid); 5589a747e4fSDavid du Colombier if(nmf->busy){ 5599a747e4fSDavid du Colombier nmf = nil; 5609a747e4fSDavid du Colombier err = "clone to used channel"; 5619a747e4fSDavid du Colombier goto send; 5629a747e4fSDavid du Colombier } 5639a747e4fSDavid du Colombier *nmf = *mf; 5649a747e4fSDavid du Colombier nmf->user = estrdup(mf->user); 5659a747e4fSDavid du Colombier nmf->fid = job->request.newfid; 5669a747e4fSDavid du Colombier nmf->qid.vers = vers++; 5679a747e4fSDavid du Colombier mf = nmf; 5689a747e4fSDavid du Colombier } 5699a747e4fSDavid du Colombier /* else nmf will be nil */ 5709a747e4fSDavid du Colombier 5719a747e4fSDavid du Colombier qid = mf->qid; 5729a747e4fSDavid du Colombier if(nelems > 0){ 5739a747e4fSDavid du Colombier /* walk fid */ 5749a747e4fSDavid du Colombier for(i=0; i<nelems && i<MAXWELEM; i++){ 5759a747e4fSDavid du Colombier if((qid.type & QTDIR) == 0){ 5763e12c5d1SDavid du Colombier err = "not a directory"; 5779a747e4fSDavid du Colombier break; 5783e12c5d1SDavid du Colombier } 5799a747e4fSDavid du Colombier if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){ 5809a747e4fSDavid du Colombier qid.type = QTDIR; 5819a747e4fSDavid du Colombier qid.path = Qdir; 5829a747e4fSDavid du Colombier Found: 5839a747e4fSDavid du Colombier job->reply.wqid[i] = qid; 5849a747e4fSDavid du Colombier job->reply.nwqid++; 5859a747e4fSDavid du Colombier continue; 5863e12c5d1SDavid du Colombier } 5879a747e4fSDavid du Colombier if(strcmp(elems[i], "cs") == 0){ 5889a747e4fSDavid du Colombier qid.type = QTFILE; 5899a747e4fSDavid du Colombier qid.path = Qcs; 5909a747e4fSDavid du Colombier goto Found; 5913e12c5d1SDavid du Colombier } 5929a747e4fSDavid du Colombier err = "file does not exist"; 5939a747e4fSDavid du Colombier break; 5949a747e4fSDavid du Colombier } 5959a747e4fSDavid du Colombier } 5969a747e4fSDavid du Colombier 5973e12c5d1SDavid du Colombier send: 5989a747e4fSDavid du Colombier if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)){ 5999a747e4fSDavid du Colombier nmf->busy = 0; 6009a747e4fSDavid du Colombier nmf->fid = 0; 6019a747e4fSDavid du Colombier } 6029a747e4fSDavid du Colombier if(err == nil) 6039a747e4fSDavid du Colombier mf->qid = qid; 6047dd7cddfSDavid du Colombier sendmsg(job, err); 6053e12c5d1SDavid du Colombier return err; 6063e12c5d1SDavid du Colombier } 6073e12c5d1SDavid du Colombier 6083e12c5d1SDavid du Colombier void 6097dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf) 6103e12c5d1SDavid du Colombier { 6113e12c5d1SDavid du Colombier int mode; 6123e12c5d1SDavid du Colombier char *err; 6133e12c5d1SDavid du Colombier 6143e12c5d1SDavid du Colombier err = 0; 6157dd7cddfSDavid du Colombier mode = job->request.mode; 6169a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6173e12c5d1SDavid du Colombier if(mode) 6183e12c5d1SDavid du Colombier err = "permission denied"; 6199a747e4fSDavid du Colombier } 6207dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 6219a747e4fSDavid du Colombier job->reply.iounit = 0; 6227dd7cddfSDavid du Colombier sendmsg(job, err); 6233e12c5d1SDavid du Colombier } 6243e12c5d1SDavid du Colombier 6253e12c5d1SDavid du Colombier void 6267dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf) 6273e12c5d1SDavid du Colombier { 6283e12c5d1SDavid du Colombier USED(mf); 6297dd7cddfSDavid du Colombier sendmsg(job, "creation permission denied"); 6303e12c5d1SDavid du Colombier } 6313e12c5d1SDavid du Colombier 6323e12c5d1SDavid du Colombier void 6337dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf) 6343e12c5d1SDavid du Colombier { 635219b2ee8SDavid du Colombier int i, n, cnt; 636219b2ee8SDavid du Colombier long off, toff, clock; 6373e12c5d1SDavid du Colombier Dir dir; 6389a747e4fSDavid du Colombier uchar buf[Maxfdata]; 6393e12c5d1SDavid du Colombier char *err; 6403e12c5d1SDavid du Colombier 6413e12c5d1SDavid du Colombier n = 0; 6423e12c5d1SDavid du Colombier err = 0; 6437dd7cddfSDavid du Colombier off = job->request.offset; 6447dd7cddfSDavid du Colombier cnt = job->request.count; 6459a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6463e12c5d1SDavid du Colombier clock = time(0); 6473e12c5d1SDavid du Colombier if(off == 0){ 6489a747e4fSDavid du Colombier dir.name = "cs"; 6499a747e4fSDavid du Colombier dir.qid.type = QTFILE; 6503e12c5d1SDavid du Colombier dir.qid.vers = vers; 6513e12c5d1SDavid du Colombier dir.qid.path = Qcs; 6523e12c5d1SDavid du Colombier dir.mode = 0666; 6533e12c5d1SDavid du Colombier dir.length = 0; 6549a747e4fSDavid du Colombier dir.uid = mf->user; 6559a747e4fSDavid du Colombier dir.gid = mf->user; 6569a747e4fSDavid du Colombier dir.muid = mf->user; 6573e12c5d1SDavid du Colombier dir.atime = clock; /* wrong */ 6583e12c5d1SDavid du Colombier dir.mtime = clock; /* wrong */ 6599a747e4fSDavid du Colombier n = convD2M(&dir, buf, sizeof buf); 6603e12c5d1SDavid du Colombier } 6619a747e4fSDavid du Colombier job->reply.data = (char*)buf; 6623e12c5d1SDavid du Colombier } else { 66380ee5cbfSDavid du Colombier for(;;){ 66480ee5cbfSDavid du Colombier /* look for an answer at the right offset */ 665219b2ee8SDavid du Colombier toff = 0; 666219b2ee8SDavid du Colombier for(i = 0; mf->reply[i] && i < mf->nreply; i++){ 667219b2ee8SDavid du Colombier n = mf->replylen[i]; 668219b2ee8SDavid du Colombier if(off < toff + n) 669219b2ee8SDavid du Colombier break; 670219b2ee8SDavid du Colombier toff += n; 6713e12c5d1SDavid du Colombier } 67280ee5cbfSDavid du Colombier if(i < mf->nreply) 67380ee5cbfSDavid du Colombier break; /* got something to return */ 67480ee5cbfSDavid du Colombier 67580ee5cbfSDavid du Colombier /* try looking up more answers */ 67680ee5cbfSDavid du Colombier if(lookup(mf) == 0){ 67780ee5cbfSDavid du Colombier /* no more */ 678219b2ee8SDavid du Colombier n = 0; 679219b2ee8SDavid du Colombier goto send; 680219b2ee8SDavid du Colombier } 68180ee5cbfSDavid du Colombier } 68280ee5cbfSDavid du Colombier 68380ee5cbfSDavid du Colombier /* give back a single reply (or part of one) */ 6847dd7cddfSDavid du Colombier job->reply.data = mf->reply[i] + (off - toff); 685219b2ee8SDavid du Colombier if(cnt > toff - off + n) 686219b2ee8SDavid du Colombier n = toff - off + n; 687219b2ee8SDavid du Colombier else 688219b2ee8SDavid du Colombier n = cnt; 6893e12c5d1SDavid du Colombier } 6903e12c5d1SDavid du Colombier send: 6917dd7cddfSDavid du Colombier job->reply.count = n; 6927dd7cddfSDavid du Colombier sendmsg(job, err); 6937dd7cddfSDavid du Colombier } 69480ee5cbfSDavid du Colombier void 69580ee5cbfSDavid du Colombier cleanmf(Mfile *mf) 6967dd7cddfSDavid du Colombier { 6977dd7cddfSDavid du Colombier int i; 6987dd7cddfSDavid du Colombier 6999a747e4fSDavid du Colombier if(mf->net != nil){ 70080ee5cbfSDavid du Colombier free(mf->net); 70180ee5cbfSDavid du Colombier mf->net = nil; 7029a747e4fSDavid du Colombier } 7039a747e4fSDavid du Colombier if(mf->host != nil){ 70480ee5cbfSDavid du Colombier free(mf->host); 70580ee5cbfSDavid du Colombier mf->host = nil; 7069a747e4fSDavid du Colombier } 7079a747e4fSDavid du Colombier if(mf->serv != nil){ 70880ee5cbfSDavid du Colombier free(mf->serv); 70980ee5cbfSDavid du Colombier mf->serv = nil; 7109a747e4fSDavid du Colombier } 7119a747e4fSDavid du Colombier if(mf->rem != nil){ 71280ee5cbfSDavid du Colombier free(mf->rem); 71380ee5cbfSDavid du Colombier mf->rem = nil; 7149a747e4fSDavid du Colombier } 7159a747e4fSDavid du Colombier if(mf->user != nil){ 7169a747e4fSDavid du Colombier free(mf->user); 7179a747e4fSDavid du Colombier mf->user = nil; 7189a747e4fSDavid du Colombier } 71980ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++){ 72080ee5cbfSDavid du Colombier free(mf->reply[i]); 72180ee5cbfSDavid du Colombier mf->reply[i] = nil; 72280ee5cbfSDavid du Colombier mf->replylen[i] = 0; 7237dd7cddfSDavid du Colombier } 72480ee5cbfSDavid du Colombier mf->nreply = 0; 72580ee5cbfSDavid du Colombier mf->nextnet = netlist; 7263e12c5d1SDavid du Colombier } 7273e12c5d1SDavid du Colombier 7283e12c5d1SDavid du Colombier void 7297dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf) 7303e12c5d1SDavid du Colombier { 7313e12c5d1SDavid du Colombier int cnt, n; 73280ee5cbfSDavid du Colombier char *err; 7337dd7cddfSDavid du Colombier char *field[4]; 734271b8d73SDavid du Colombier char curerr[64]; 7353e12c5d1SDavid du Colombier 7363e12c5d1SDavid du Colombier err = 0; 7377dd7cddfSDavid du Colombier cnt = job->request.count; 7389a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 7393e12c5d1SDavid du Colombier err = "can't write directory"; 7403e12c5d1SDavid du Colombier goto send; 7413e12c5d1SDavid du Colombier } 7423e12c5d1SDavid du Colombier if(cnt >= Maxrequest){ 7433e12c5d1SDavid du Colombier err = "request too long"; 7443e12c5d1SDavid du Colombier goto send; 7453e12c5d1SDavid du Colombier } 7467dd7cddfSDavid du Colombier job->request.data[cnt] = 0; 7473e12c5d1SDavid du Colombier 7483e12c5d1SDavid du Colombier /* 749219b2ee8SDavid du Colombier * toggle debugging 750219b2ee8SDavid du Colombier */ 7517dd7cddfSDavid du Colombier if(strncmp(job->request.data, "debug", 5)==0){ 752219b2ee8SDavid du Colombier debug ^= 1; 753219b2ee8SDavid du Colombier syslog(1, logfile, "debug %d", debug); 754219b2ee8SDavid du Colombier goto send; 755219b2ee8SDavid du Colombier } 756219b2ee8SDavid du Colombier 757219b2ee8SDavid du Colombier /* 7587dd7cddfSDavid du Colombier * toggle debugging 7597dd7cddfSDavid du Colombier */ 7607dd7cddfSDavid du Colombier if(strncmp(job->request.data, "paranoia", 8)==0){ 7617dd7cddfSDavid du Colombier paranoia ^= 1; 7627dd7cddfSDavid du Colombier syslog(1, logfile, "paranoia %d", paranoia); 7637dd7cddfSDavid du Colombier goto send; 7647dd7cddfSDavid du Colombier } 7657dd7cddfSDavid du Colombier 7667dd7cddfSDavid du Colombier /* 7673e12c5d1SDavid du Colombier * add networks to the default list 7683e12c5d1SDavid du Colombier */ 7697dd7cddfSDavid du Colombier if(strncmp(job->request.data, "add ", 4)==0){ 7707dd7cddfSDavid du Colombier if(job->request.data[cnt-1] == '\n') 7717dd7cddfSDavid du Colombier job->request.data[cnt-1] = 0; 7727dd7cddfSDavid du Colombier netadd(job->request.data+4); 7737dd7cddfSDavid du Colombier readipinterfaces(); 7747dd7cddfSDavid du Colombier goto send; 7757dd7cddfSDavid du Colombier } 7767dd7cddfSDavid du Colombier 7777dd7cddfSDavid du Colombier /* 7787dd7cddfSDavid du Colombier * refresh all state 7797dd7cddfSDavid du Colombier */ 7807dd7cddfSDavid du Colombier if(strncmp(job->request.data, "refresh", 7)==0){ 7817dd7cddfSDavid du Colombier netinit(1); 7823e12c5d1SDavid du Colombier goto send; 7833e12c5d1SDavid du Colombier } 7843e12c5d1SDavid du Colombier 78580ee5cbfSDavid du Colombier /* start transaction with a clean slate */ 78680ee5cbfSDavid du Colombier cleanmf(mf); 78780ee5cbfSDavid du Colombier 7883e12c5d1SDavid du Colombier /* 789219b2ee8SDavid du Colombier * look for a general query 790219b2ee8SDavid du Colombier */ 7917dd7cddfSDavid du Colombier if(*job->request.data == '!'){ 7927dd7cddfSDavid du Colombier err = genquery(mf, job->request.data+1); 793219b2ee8SDavid du Colombier goto send; 794219b2ee8SDavid du Colombier } 795219b2ee8SDavid du Colombier 7967dd7cddfSDavid du Colombier if(debug) 7977dd7cddfSDavid du Colombier syslog(0, logfile, "write %s", job->request.data); 7987dd7cddfSDavid du Colombier if(paranoia) 7997dd7cddfSDavid du Colombier syslog(0, paranoiafile, "write %s by %s", job->request.data, mf->user); 8007dd7cddfSDavid du Colombier 801219b2ee8SDavid du Colombier /* 8023e12c5d1SDavid du Colombier * break up name 8033e12c5d1SDavid du Colombier */ 8047dd7cddfSDavid du Colombier n = getfields(job->request.data, field, 4, 1, "!"); 8053e12c5d1SDavid du Colombier switch(n){ 8063e12c5d1SDavid du Colombier case 1: 80780ee5cbfSDavid du Colombier mf->net = strdup("net"); 80880ee5cbfSDavid du Colombier mf->host = strdup(field[0]); 8097dd7cddfSDavid du Colombier break; 8107dd7cddfSDavid du Colombier case 4: 81180ee5cbfSDavid du Colombier mf->rem = strdup(field[3]); 81280ee5cbfSDavid du Colombier /* fall through */ 81380ee5cbfSDavid du Colombier case 3: 81480ee5cbfSDavid du Colombier mf->serv = strdup(field[2]); 81580ee5cbfSDavid du Colombier /* fall through */ 81680ee5cbfSDavid du Colombier case 2: 81780ee5cbfSDavid du Colombier mf->host = strdup(field[1]); 81880ee5cbfSDavid du Colombier mf->net = strdup(field[0]); 8193e12c5d1SDavid du Colombier break; 8203e12c5d1SDavid du Colombier } 8213e12c5d1SDavid du Colombier 82280ee5cbfSDavid du Colombier /* 82380ee5cbfSDavid du Colombier * do the first net worth of lookup 82480ee5cbfSDavid du Colombier */ 825271b8d73SDavid du Colombier if(lookup(mf) == 0){ 826271b8d73SDavid du Colombier rerrstr(curerr, sizeof curerr); 827271b8d73SDavid du Colombier err = curerr; 828271b8d73SDavid du Colombier } 8293e12c5d1SDavid du Colombier send: 8307dd7cddfSDavid du Colombier job->reply.count = cnt; 8317dd7cddfSDavid du Colombier sendmsg(job, err); 8323e12c5d1SDavid du Colombier } 8333e12c5d1SDavid du Colombier 8343e12c5d1SDavid du Colombier void 8357dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf) 8363e12c5d1SDavid du Colombier { 83780ee5cbfSDavid du Colombier cleanmf(mf); 8383e12c5d1SDavid du Colombier mf->busy = 0; 8393e12c5d1SDavid du Colombier mf->fid = 0; 8407dd7cddfSDavid du Colombier sendmsg(job, 0); 8413e12c5d1SDavid du Colombier } 8423e12c5d1SDavid du Colombier 8433e12c5d1SDavid du Colombier void 8447dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf) 8453e12c5d1SDavid du Colombier { 8463e12c5d1SDavid du Colombier USED(mf); 8477dd7cddfSDavid du Colombier sendmsg(job, "remove permission denied"); 8483e12c5d1SDavid du Colombier } 8493e12c5d1SDavid du Colombier 8503e12c5d1SDavid du Colombier void 8517dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf) 8523e12c5d1SDavid du Colombier { 8533e12c5d1SDavid du Colombier Dir dir; 8549a747e4fSDavid du Colombier uchar buf[IOHDRSZ+Maxfdata]; 8553e12c5d1SDavid du Colombier 8569a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 8579a747e4fSDavid du Colombier dir.name = "."; 8589a747e4fSDavid du Colombier dir.mode = DMDIR|0555; 859219b2ee8SDavid du Colombier } else { 8609a747e4fSDavid du Colombier dir.name = "cs"; 8613e12c5d1SDavid du Colombier dir.mode = 0666; 862219b2ee8SDavid du Colombier } 863219b2ee8SDavid du Colombier dir.qid = mf->qid; 8643e12c5d1SDavid du Colombier dir.length = 0; 8659a747e4fSDavid du Colombier dir.uid = mf->user; 8669a747e4fSDavid du Colombier dir.gid = mf->user; 8679a747e4fSDavid du Colombier dir.muid = mf->user; 8683e12c5d1SDavid du Colombier dir.atime = dir.mtime = time(0); 8699a747e4fSDavid du Colombier job->reply.nstat = convD2M(&dir, buf, sizeof buf); 8709a747e4fSDavid du Colombier job->reply.stat = buf; 8717dd7cddfSDavid du Colombier sendmsg(job, 0); 8723e12c5d1SDavid du Colombier } 8733e12c5d1SDavid du Colombier 8743e12c5d1SDavid du Colombier void 8757dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf) 8763e12c5d1SDavid du Colombier { 8773e12c5d1SDavid du Colombier USED(mf); 8787dd7cddfSDavid du Colombier sendmsg(job, "wstat permission denied"); 8793e12c5d1SDavid du Colombier } 8803e12c5d1SDavid du Colombier 8813e12c5d1SDavid du Colombier void 8827dd7cddfSDavid du Colombier sendmsg(Job *job, char *err) 8833e12c5d1SDavid du Colombier { 8843e12c5d1SDavid du Colombier int n; 8859a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 8869a747e4fSDavid du Colombier char ename[ERRMAX]; 8873e12c5d1SDavid du Colombier 8883e12c5d1SDavid du Colombier if(err){ 8897dd7cddfSDavid du Colombier job->reply.type = Rerror; 8909a747e4fSDavid du Colombier snprint(ename, sizeof(ename), "cs: %s", err); 8919a747e4fSDavid du Colombier job->reply.ename = ename; 8923e12c5d1SDavid du Colombier }else{ 8937dd7cddfSDavid du Colombier job->reply.type = job->request.type+1; 8943e12c5d1SDavid du Colombier } 8957dd7cddfSDavid du Colombier job->reply.tag = job->request.tag; 8969a747e4fSDavid du Colombier n = convS2M(&job->reply, mdata, sizeof mdata); 897219b2ee8SDavid du Colombier if(n == 0){ 8987dd7cddfSDavid du Colombier syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply); 899219b2ee8SDavid du Colombier abort(); 900219b2ee8SDavid du Colombier } 9017dd7cddfSDavid du Colombier lock(&joblock); 9027dd7cddfSDavid du Colombier if(job->flushed == 0) 9039a747e4fSDavid du Colombier if(write(mfd[1], mdata, n)!=n) 9043e12c5d1SDavid du Colombier error("mount write"); 9057dd7cddfSDavid du Colombier unlock(&joblock); 906219b2ee8SDavid du Colombier if(debug) 9077dd7cddfSDavid du Colombier syslog(0, logfile, "%F %d", &job->reply, n); 9083e12c5d1SDavid du Colombier } 9093e12c5d1SDavid du Colombier 9103e12c5d1SDavid du Colombier void 9113e12c5d1SDavid du Colombier error(char *s) 9123e12c5d1SDavid du Colombier { 913bd389b36SDavid du Colombier syslog(1, "cs", "%s: %r", s); 914bd389b36SDavid du Colombier _exits(0); 9153e12c5d1SDavid du Colombier } 9163e12c5d1SDavid du Colombier 9177dd7cddfSDavid du Colombier static int 9187dd7cddfSDavid du Colombier isvalidip(uchar *ip) 9197dd7cddfSDavid du Colombier { 9207dd7cddfSDavid du Colombier return ipcmp(ip, IPnoaddr) != 0 && ipcmp(ip, v4prefix) != 0; 9217dd7cddfSDavid du Colombier } 9223e12c5d1SDavid du Colombier 9230103620dSDavid du Colombier static uchar loopbacknet[IPaddrlen] = { 9240103620dSDavid du Colombier 0, 0, 0, 0, 9250103620dSDavid du Colombier 0, 0, 0, 0, 9260103620dSDavid du Colombier 0, 0, 0xff, 0xff, 9270103620dSDavid du Colombier 127, 0, 0, 0 9280103620dSDavid du Colombier }; 9290103620dSDavid du Colombier static uchar loopbackmask[IPaddrlen] = { 9300103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9310103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9320103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9330103620dSDavid du Colombier 0xff, 0, 0, 0 9340103620dSDavid du Colombier }; 9350103620dSDavid du Colombier 9367dd7cddfSDavid du Colombier void 9377dd7cddfSDavid du Colombier readipinterfaces(void) 9387dd7cddfSDavid du Colombier { 9390103620dSDavid du Colombier if(myipaddr(ipa, mntpt) != 0) 9400103620dSDavid du Colombier ipmove(ipa, IPnoaddr); 9417dd7cddfSDavid du Colombier sprint(ipaddr, "%I", ipa); 9427dd7cddfSDavid du Colombier if (debug) 9437dd7cddfSDavid du Colombier syslog(0, "dns", "ipaddr is %s\n", ipaddr); 9447dd7cddfSDavid du Colombier } 9453e12c5d1SDavid du Colombier 9463e12c5d1SDavid du Colombier /* 9477dd7cddfSDavid du Colombier * get the system name 9483e12c5d1SDavid du Colombier */ 9493e12c5d1SDavid du Colombier void 9503e12c5d1SDavid du Colombier ipid(void) 9513e12c5d1SDavid du Colombier { 9523e12c5d1SDavid du Colombier uchar addr[6]; 9533e12c5d1SDavid du Colombier Ndbtuple *t; 954219b2ee8SDavid du Colombier char *p, *attr; 9553e12c5d1SDavid du Colombier Ndbs s; 9563e12c5d1SDavid du Colombier int f; 9577dd7cddfSDavid du Colombier char buf[Maxpath]; 9583e12c5d1SDavid du Colombier 9593e12c5d1SDavid du Colombier 960219b2ee8SDavid du Colombier /* use environment, ether addr, or ipaddr to get system name */ 9617dd7cddfSDavid du Colombier if(*mysysname == 0){ 9627dd7cddfSDavid du Colombier /* 9637dd7cddfSDavid du Colombier * environment has priority. 9647dd7cddfSDavid du Colombier * 9657dd7cddfSDavid du Colombier * on the sgi power the default system name 9667dd7cddfSDavid du Colombier * is the ip address. ignore that. 9677dd7cddfSDavid du Colombier * 9687dd7cddfSDavid du Colombier */ 969219b2ee8SDavid du Colombier p = getenv("sysname"); 970219b2ee8SDavid du Colombier if(p){ 971219b2ee8SDavid du Colombier attr = ipattr(p); 972219b2ee8SDavid du Colombier if(strcmp(attr, "ip") != 0) 9737dd7cddfSDavid du Colombier strcpy(mysysname, p); 9743e12c5d1SDavid du Colombier } 9753e12c5d1SDavid du Colombier 9763e12c5d1SDavid du Colombier /* 9777dd7cddfSDavid du Colombier * the /net/ndb contains what the network 9787dd7cddfSDavid du Colombier * figured out from DHCP. use that name if 9797dd7cddfSDavid du Colombier * there is one. 9803e12c5d1SDavid du Colombier */ 9817dd7cddfSDavid du Colombier if(*mysysname == 0 && netdb != nil){ 9827dd7cddfSDavid du Colombier ndbreopen(netdb); 9837dd7cddfSDavid du Colombier for(t = ndbparse(netdb); t != nil; t = t->entry){ 9847dd7cddfSDavid du Colombier if(strcmp(t->attr, "sys") == 0){ 9857dd7cddfSDavid du Colombier strcpy(mysysname, t->val); 9863e12c5d1SDavid du Colombier break; 9873e12c5d1SDavid du Colombier } 9887dd7cddfSDavid du Colombier } 9897dd7cddfSDavid du Colombier ndbfree(t); 9907dd7cddfSDavid du Colombier } 9917dd7cddfSDavid du Colombier 9927dd7cddfSDavid du Colombier /* next network database, ip address, and ether address to find a name */ 9937dd7cddfSDavid du Colombier if(*mysysname == 0){ 9947dd7cddfSDavid du Colombier t = nil; 9957dd7cddfSDavid du Colombier if(isvalidip(ipa)) 9967dd7cddfSDavid du Colombier t = ndbgetval(db, &s, "ip", ipaddr, "sys", mysysname); 9977dd7cddfSDavid du Colombier else { 9987dd7cddfSDavid du Colombier for(f = 0; f < 3; f++){ 9997dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/ether%d", mntpt, f); 10007dd7cddfSDavid du Colombier if(myetheraddr(addr, buf) >= 0){ 10017dd7cddfSDavid du Colombier snprint(eaddr, sizeof(eaddr), "%E", addr); 10027dd7cddfSDavid du Colombier t = ndbgetval(db, &s, "ether", eaddr, "sys", 10037dd7cddfSDavid du Colombier mysysname); 10047dd7cddfSDavid du Colombier if(t != nil) 10057dd7cddfSDavid du Colombier break; 10067dd7cddfSDavid du Colombier } 10077dd7cddfSDavid du Colombier } 10087dd7cddfSDavid du Colombier } 10097dd7cddfSDavid du Colombier ndbfree(t); 10107dd7cddfSDavid du Colombier } 10117dd7cddfSDavid du Colombier 101280ee5cbfSDavid du Colombier /* nothing else worked, use the ip address */ 101380ee5cbfSDavid du Colombier if(*mysysname == 0 && isvalidip(ipa)) 101480ee5cbfSDavid du Colombier strcpy(mysysname, ipaddr); 101580ee5cbfSDavid du Colombier 101680ee5cbfSDavid du Colombier 1017dc5a79c1SDavid du Colombier /* set /dev/sysname if we now know it */ 10187dd7cddfSDavid du Colombier if(*mysysname){ 10197dd7cddfSDavid du Colombier f = open("/dev/sysname", OWRITE); 10207dd7cddfSDavid du Colombier if(f >= 0){ 10217dd7cddfSDavid du Colombier write(f, mysysname, strlen(mysysname)); 10223e12c5d1SDavid du Colombier close(f); 10233e12c5d1SDavid du Colombier } 10243e12c5d1SDavid du Colombier } 10253e12c5d1SDavid du Colombier } 10263e12c5d1SDavid du Colombier } 10273e12c5d1SDavid du Colombier 10283e12c5d1SDavid du Colombier /* 10293e12c5d1SDavid du Colombier * Set up a list of default networks by looking for 10303e12c5d1SDavid du Colombier * /net/ * /clone. 10313e12c5d1SDavid du Colombier */ 10323e12c5d1SDavid du Colombier void 10337dd7cddfSDavid du Colombier netinit(int background) 10343e12c5d1SDavid du Colombier { 10357dd7cddfSDavid du Colombier char clone[Maxpath]; 10363e12c5d1SDavid du Colombier Network *np; 10377dd7cddfSDavid du Colombier static int working; 10387dd7cddfSDavid du Colombier 10397dd7cddfSDavid du Colombier if(background){ 10407dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 10417dd7cddfSDavid du Colombier case 0: 10427dd7cddfSDavid du Colombier break; 10437dd7cddfSDavid du Colombier default: 10447dd7cddfSDavid du Colombier return; 10457dd7cddfSDavid du Colombier } 10467dd7cddfSDavid du Colombier lock(&netlock); 10477dd7cddfSDavid du Colombier } 10483e12c5d1SDavid du Colombier 10493e12c5d1SDavid du Colombier /* add the mounted networks to the default list */ 10503e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 10517dd7cddfSDavid du Colombier if(np->considered) 10527dd7cddfSDavid du Colombier continue; 10537dd7cddfSDavid du Colombier snprint(clone, sizeof(clone), "%s/%s/clone", mntpt, np->net); 10549a747e4fSDavid du Colombier if(access(clone, AEXIST) < 0) 10553e12c5d1SDavid du Colombier continue; 10563e12c5d1SDavid du Colombier if(netlist) 10573e12c5d1SDavid du Colombier last->next = np; 10583e12c5d1SDavid du Colombier else 10593e12c5d1SDavid du Colombier netlist = np; 10603e12c5d1SDavid du Colombier last = np; 10613e12c5d1SDavid du Colombier np->next = 0; 10627dd7cddfSDavid du Colombier np->considered = 1; 10633e12c5d1SDavid du Colombier } 10643e12c5d1SDavid du Colombier 10657dd7cddfSDavid du Colombier /* find out what our ip address is */ 10667dd7cddfSDavid du Colombier readipinterfaces(); 10673e12c5d1SDavid du Colombier 10687dd7cddfSDavid du Colombier /* set the system name if we need to, these says ip is all we have */ 10693e12c5d1SDavid du Colombier ipid(); 10703e12c5d1SDavid du Colombier 1071219b2ee8SDavid du Colombier if(debug) 10727dd7cddfSDavid du Colombier syslog(0, logfile, "mysysname %s eaddr %s ipaddr %s ipa %I\n", 10737dd7cddfSDavid du Colombier mysysname, eaddr, ipaddr, ipa); 10747dd7cddfSDavid du Colombier 10757dd7cddfSDavid du Colombier if(background){ 10767dd7cddfSDavid du Colombier unlock(&netlock); 10777dd7cddfSDavid du Colombier _exits(0); 10787dd7cddfSDavid du Colombier } 10793e12c5d1SDavid du Colombier } 10803e12c5d1SDavid du Colombier 10813e12c5d1SDavid du Colombier /* 10823e12c5d1SDavid du Colombier * add networks to the standard list 10833e12c5d1SDavid du Colombier */ 10843e12c5d1SDavid du Colombier void 10853e12c5d1SDavid du Colombier netadd(char *p) 10863e12c5d1SDavid du Colombier { 10873e12c5d1SDavid du Colombier Network *np; 10883e12c5d1SDavid du Colombier char *field[12]; 10893e12c5d1SDavid du Colombier int i, n; 10903e12c5d1SDavid du Colombier 10917dd7cddfSDavid du Colombier n = getfields(p, field, 12, 1, " "); 10923e12c5d1SDavid du Colombier for(i = 0; i < n; i++){ 10933e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 10943e12c5d1SDavid du Colombier if(strcmp(field[i], np->net) != 0) 10953e12c5d1SDavid du Colombier continue; 10967dd7cddfSDavid du Colombier if(np->considered) 10973e12c5d1SDavid du Colombier break; 10983e12c5d1SDavid du Colombier if(netlist) 10993e12c5d1SDavid du Colombier last->next = np; 11003e12c5d1SDavid du Colombier else 11013e12c5d1SDavid du Colombier netlist = np; 11023e12c5d1SDavid du Colombier last = np; 11033e12c5d1SDavid du Colombier np->next = 0; 11047dd7cddfSDavid du Colombier np->considered = 1; 11053e12c5d1SDavid du Colombier } 11063e12c5d1SDavid du Colombier } 11073e12c5d1SDavid du Colombier } 11083e12c5d1SDavid du Colombier 11093e12c5d1SDavid du Colombier /* 1110219b2ee8SDavid du Colombier * make a tuple 1111219b2ee8SDavid du Colombier */ 1112219b2ee8SDavid du Colombier Ndbtuple* 1113219b2ee8SDavid du Colombier mktuple(char *attr, char *val) 1114219b2ee8SDavid du Colombier { 1115219b2ee8SDavid du Colombier Ndbtuple *t; 1116219b2ee8SDavid du Colombier 11177dd7cddfSDavid du Colombier t = emalloc(sizeof(Ndbtuple)); 1118219b2ee8SDavid du Colombier strcpy(t->attr, attr); 1119219b2ee8SDavid du Colombier strncpy(t->val, val, sizeof(t->val)); 1120219b2ee8SDavid du Colombier t->val[sizeof(t->val)-1] = 0; 1121219b2ee8SDavid du Colombier t->line = t; 1122219b2ee8SDavid du Colombier t->entry = 0; 1123219b2ee8SDavid du Colombier return t; 1124219b2ee8SDavid du Colombier } 1125219b2ee8SDavid du Colombier 112680ee5cbfSDavid du Colombier int 112780ee5cbfSDavid du Colombier lookforproto(Ndbtuple *t, char *proto) 112880ee5cbfSDavid du Colombier { 112980ee5cbfSDavid du Colombier for(; t != nil; t = t->entry) 113080ee5cbfSDavid du Colombier if(strcmp(t->attr, "proto") == 0 && strcmp(t->val, proto) == 0) 113180ee5cbfSDavid du Colombier return 1; 113280ee5cbfSDavid du Colombier return 0; 113380ee5cbfSDavid du Colombier } 113480ee5cbfSDavid du Colombier 1135219b2ee8SDavid du Colombier /* 11363e12c5d1SDavid du Colombier * lookup a request. the network "net" means we should pick the 11373e12c5d1SDavid du Colombier * best network to get there. 11383e12c5d1SDavid du Colombier */ 11393e12c5d1SDavid du Colombier int 114080ee5cbfSDavid du Colombier lookup(Mfile *mf) 11413e12c5d1SDavid du Colombier { 114280ee5cbfSDavid du Colombier Network *np; 1143219b2ee8SDavid du Colombier char *cp; 1144219b2ee8SDavid du Colombier Ndbtuple *nt, *t; 1145219b2ee8SDavid du Colombier char reply[Maxreply]; 114680ee5cbfSDavid du Colombier int i, rv; 114780ee5cbfSDavid du Colombier int hack; 11483e12c5d1SDavid du Colombier 11493e12c5d1SDavid du Colombier /* open up the standard db files */ 11503e12c5d1SDavid du Colombier if(db == 0) 11517dd7cddfSDavid du Colombier ndbinit(); 11523e12c5d1SDavid du Colombier if(db == 0) 115380ee5cbfSDavid du Colombier error("can't open mf->network database\n"); 11543e12c5d1SDavid du Colombier 115580ee5cbfSDavid du Colombier rv = 0; 115680ee5cbfSDavid du Colombier 115780ee5cbfSDavid du Colombier if(mf->net == nil) 115880ee5cbfSDavid du Colombier return 0; /* must have been a genquery */ 115980ee5cbfSDavid du Colombier 116080ee5cbfSDavid du Colombier if(strcmp(mf->net, "net") == 0){ 11613e12c5d1SDavid du Colombier /* 11623e12c5d1SDavid du Colombier * go through set of default nets 11633e12c5d1SDavid du Colombier */ 116480ee5cbfSDavid du Colombier for(np = mf->nextnet; np; np = np->next){ 116580ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 116680ee5cbfSDavid du Colombier if(nt == nil) 1167219b2ee8SDavid du Colombier continue; 116880ee5cbfSDavid du Colombier hack = np->fasttimeouthack && !lookforproto(nt, np->net); 116980ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 117080ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, hack); 1171219b2ee8SDavid du Colombier if(cp){ 117280ee5cbfSDavid du Colombier /* avoid duplicates */ 117380ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++) 117480ee5cbfSDavid du Colombier if(strcmp(mf->reply[i], cp) == 0) 117580ee5cbfSDavid du Colombier break; 117680ee5cbfSDavid du Colombier if(i == mf->nreply){ 117780ee5cbfSDavid du Colombier /* save the reply */ 1178219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 1179219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = cp; 118080ee5cbfSDavid du Colombier rv++; 1181219b2ee8SDavid du Colombier } 1182219b2ee8SDavid du Colombier } 1183219b2ee8SDavid du Colombier } 1184219b2ee8SDavid du Colombier ndbfree(nt); 118580ee5cbfSDavid du Colombier np = np->next; 118680ee5cbfSDavid du Colombier break; 118780ee5cbfSDavid du Colombier } 118880ee5cbfSDavid du Colombier mf->nextnet = np; 118980ee5cbfSDavid du Colombier return rv; 119080ee5cbfSDavid du Colombier } 119180ee5cbfSDavid du Colombier 119280ee5cbfSDavid du Colombier /* 119380ee5cbfSDavid du Colombier * if not /net, we only get one lookup 119480ee5cbfSDavid du Colombier */ 119580ee5cbfSDavid du Colombier if(mf->nreply != 0) 1196219b2ee8SDavid du Colombier return 0; 119780ee5cbfSDavid du Colombier 119880ee5cbfSDavid du Colombier /* 119980ee5cbfSDavid du Colombier * look for a specific network 120080ee5cbfSDavid du Colombier */ 120180ee5cbfSDavid du Colombier for(np = netlist; np->net != nil; np++){ 120280ee5cbfSDavid du Colombier if(np->fasttimeouthack) 120380ee5cbfSDavid du Colombier continue; 120480ee5cbfSDavid du Colombier if(strcmp(np->net, mf->net) == 0) 120580ee5cbfSDavid du Colombier break; 120680ee5cbfSDavid du Colombier } 120780ee5cbfSDavid du Colombier 120880ee5cbfSDavid du Colombier if(np->net != nil){ 120980ee5cbfSDavid du Colombier /* 121080ee5cbfSDavid du Colombier * known network 121180ee5cbfSDavid du Colombier */ 121280ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 121380ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 121480ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, 0); 121580ee5cbfSDavid du Colombier if(cp){ 121680ee5cbfSDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 121780ee5cbfSDavid du Colombier mf->reply[mf->nreply++] = cp; 121880ee5cbfSDavid du Colombier rv++; 121980ee5cbfSDavid du Colombier } 122080ee5cbfSDavid du Colombier } 122180ee5cbfSDavid du Colombier ndbfree(nt); 122280ee5cbfSDavid du Colombier return rv; 12233e12c5d1SDavid du Colombier } else { 12243e12c5d1SDavid du Colombier /* 1225219b2ee8SDavid du Colombier * not a known network, don't translate host or service 12263e12c5d1SDavid du Colombier */ 122780ee5cbfSDavid du Colombier if(mf->serv) 12287dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s", 122980ee5cbfSDavid du Colombier mntpt, mf->net, mf->host, mf->serv); 1230bd389b36SDavid du Colombier else 12317dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s", 123280ee5cbfSDavid du Colombier mntpt, mf->net, mf->host); 1233219b2ee8SDavid du Colombier mf->reply[0] = strdup(reply); 1234219b2ee8SDavid du Colombier mf->replylen[0] = strlen(reply); 1235219b2ee8SDavid du Colombier mf->nreply = 1; 123680ee5cbfSDavid du Colombier return 1; 12373e12c5d1SDavid du Colombier } 12383e12c5d1SDavid du Colombier } 12393e12c5d1SDavid du Colombier 12403e12c5d1SDavid du Colombier /* 12413e12c5d1SDavid du Colombier * translate an ip service name into a port number. If it's a numeric port 12423e12c5d1SDavid du Colombier * number, look for restricted access. 12433e12c5d1SDavid du Colombier * 12443e12c5d1SDavid du Colombier * the service '*' needs no translation. 12453e12c5d1SDavid du Colombier */ 12463e12c5d1SDavid du Colombier char* 12473e12c5d1SDavid du Colombier ipserv(Network *np, char *name, char *buf) 12483e12c5d1SDavid du Colombier { 12493e12c5d1SDavid du Colombier char *p; 12503e12c5d1SDavid du Colombier int alpha = 0; 12513e12c5d1SDavid du Colombier int restr = 0; 12523e12c5d1SDavid du Colombier char port[Ndbvlen]; 12533e12c5d1SDavid du Colombier Ndbtuple *t, *nt; 12543e12c5d1SDavid du Colombier Ndbs s; 12553e12c5d1SDavid du Colombier 12563e12c5d1SDavid du Colombier /* '*' means any service */ 12573e12c5d1SDavid du Colombier if(strcmp(name, "*")==0){ 12583e12c5d1SDavid du Colombier strcpy(buf, name); 12593e12c5d1SDavid du Colombier return buf; 12603e12c5d1SDavid du Colombier } 12613e12c5d1SDavid du Colombier 12623e12c5d1SDavid du Colombier /* see if it's numeric or symbolic */ 12633e12c5d1SDavid du Colombier port[0] = 0; 12643e12c5d1SDavid du Colombier for(p = name; *p; p++){ 12653e12c5d1SDavid du Colombier if(isdigit(*p)) 12669a747e4fSDavid du Colombier {} 12673e12c5d1SDavid du Colombier else if(isalpha(*p) || *p == '-' || *p == '$') 12683e12c5d1SDavid du Colombier alpha = 1; 12693e12c5d1SDavid du Colombier else 12703e12c5d1SDavid du Colombier return 0; 12713e12c5d1SDavid du Colombier } 12723e12c5d1SDavid du Colombier if(alpha){ 12733e12c5d1SDavid du Colombier t = ndbgetval(db, &s, np->net, name, "port", port); 12743e12c5d1SDavid du Colombier if(t == 0) 12753e12c5d1SDavid du Colombier return 0; 12763e12c5d1SDavid du Colombier } else { 1277*3cc1eb97SDavid du Colombier /* look up only for tcp ports < 1024 to get the restricted 1278*3cc1eb97SDavid du Colombier * attribute 1279*3cc1eb97SDavid du Colombier */ 1280*3cc1eb97SDavid du Colombier t = nil; 1281*3cc1eb97SDavid du Colombier if(atoi(name) < 1024 && strcmp(np->net, "tcp") == 0) 12823e12c5d1SDavid du Colombier t = ndbgetval(db, &s, "port", name, "port", port); 1283*3cc1eb97SDavid du Colombier if(t == nil){ 12843e12c5d1SDavid du Colombier strncpy(port, name, sizeof(port)); 12853e12c5d1SDavid du Colombier port[sizeof(port)-1] = 0; 12863e12c5d1SDavid du Colombier } 12873e12c5d1SDavid du Colombier } 12883e12c5d1SDavid du Colombier 12893e12c5d1SDavid du Colombier if(t){ 12903e12c5d1SDavid du Colombier for(nt = t; nt; nt = nt->entry) 12913e12c5d1SDavid du Colombier if(strcmp(nt->attr, "restricted") == 0) 12923e12c5d1SDavid du Colombier restr = 1; 12933e12c5d1SDavid du Colombier ndbfree(t); 12943e12c5d1SDavid du Colombier } 12953e12c5d1SDavid du Colombier sprint(buf, "%s%s", port, restr ? "!r" : ""); 12963e12c5d1SDavid du Colombier return buf; 12973e12c5d1SDavid du Colombier } 12983e12c5d1SDavid du Colombier 12993e12c5d1SDavid du Colombier /* 13007dd7cddfSDavid du Colombier * lookup an ip attribute 13013e12c5d1SDavid du Colombier */ 13027dd7cddfSDavid du Colombier int 13037dd7cddfSDavid du Colombier ipattrlookup(Ndb *db, char *ipa, char *attr, char *val) 13043e12c5d1SDavid du Colombier { 13053e12c5d1SDavid du Colombier 13067dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13077dd7cddfSDavid du Colombier char *alist[2]; 13083e12c5d1SDavid du Colombier 13097dd7cddfSDavid du Colombier alist[0] = attr; 13107dd7cddfSDavid du Colombier t = ndbipinfo(db, "ip", ipa, alist, 1); 13117dd7cddfSDavid du Colombier if(t == nil) 13127dd7cddfSDavid du Colombier return 0; 13139a747e4fSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 13147dd7cddfSDavid du Colombier if(strcmp(nt->attr, attr) == 0){ 13157dd7cddfSDavid du Colombier strcpy(val, nt->val); 13163e12c5d1SDavid du Colombier ndbfree(t); 13177dd7cddfSDavid du Colombier return 1; 1318219b2ee8SDavid du Colombier } 13199a747e4fSDavid du Colombier } 13203e12c5d1SDavid du Colombier 13217dd7cddfSDavid du Colombier /* we shouldn't get here */ 13223e12c5d1SDavid du Colombier ndbfree(t); 13237dd7cddfSDavid du Colombier return 0; 13243e12c5d1SDavid du Colombier } 13253e12c5d1SDavid du Colombier 13263e12c5d1SDavid du Colombier /* 13273e12c5d1SDavid du Colombier * lookup (and translate) an ip destination 13283e12c5d1SDavid du Colombier */ 1329219b2ee8SDavid du Colombier Ndbtuple* 1330219b2ee8SDavid du Colombier iplookup(Network *np, char *host, char *serv, int nolookup) 13313e12c5d1SDavid du Colombier { 13323e12c5d1SDavid du Colombier char *attr; 13337dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13343e12c5d1SDavid du Colombier Ndbs s; 13353e12c5d1SDavid du Colombier char ts[Ndbvlen+1]; 13363e12c5d1SDavid du Colombier char th[Ndbvlen+1]; 13373e12c5d1SDavid du Colombier char dollar[Ndbvlen+1]; 13387dd7cddfSDavid du Colombier uchar ip[IPaddrlen]; 13397dd7cddfSDavid du Colombier uchar net[IPaddrlen]; 13407dd7cddfSDavid du Colombier uchar tnet[IPaddrlen]; 13417dd7cddfSDavid du Colombier Ipifc *ifc; 13429a747e4fSDavid du Colombier Iplifc *lifc; 13433e12c5d1SDavid du Colombier 1344219b2ee8SDavid du Colombier USED(nolookup); 1345219b2ee8SDavid du Colombier 13463e12c5d1SDavid du Colombier /* 13473e12c5d1SDavid du Colombier * start with the service since it's the most likely to fail 13483e12c5d1SDavid du Colombier * and costs the least 13493e12c5d1SDavid du Colombier */ 13507dd7cddfSDavid du Colombier werrstr("can't translate address"); 1351271b8d73SDavid du Colombier if(serv==0 || ipserv(np, serv, ts) == 0){ 1352271b8d73SDavid du Colombier werrstr("can't translate service"); 1353219b2ee8SDavid du Colombier return 0; 13547dd7cddfSDavid du Colombier } 13553e12c5d1SDavid du Colombier 13563e12c5d1SDavid du Colombier /* for dial strings with no host */ 1357219b2ee8SDavid du Colombier if(strcmp(host, "*") == 0) 1358219b2ee8SDavid du Colombier return mktuple("ip", "*"); 13593e12c5d1SDavid du Colombier 13603e12c5d1SDavid du Colombier /* 13617dd7cddfSDavid du Colombier * hack till we go v6 :: = 0.0.0.0 13627dd7cddfSDavid du Colombier */ 13637dd7cddfSDavid du Colombier if(strcmp("::", host) == 0) 13647dd7cddfSDavid du Colombier return mktuple("ip", "*"); 13657dd7cddfSDavid du Colombier 13667dd7cddfSDavid du Colombier /* 13673e12c5d1SDavid du Colombier * '$' means the rest of the name is an attribute that we 13683e12c5d1SDavid du Colombier * need to search for 13693e12c5d1SDavid du Colombier */ 13703e12c5d1SDavid du Colombier if(*host == '$'){ 13717dd7cddfSDavid du Colombier if(ipattrlookup(db, ipaddr, host+1, dollar)) 13723e12c5d1SDavid du Colombier host = dollar; 13733e12c5d1SDavid du Colombier } 13743e12c5d1SDavid du Colombier 13753e12c5d1SDavid du Colombier /* 13767dd7cddfSDavid du Colombier * turn '[ip address]' into just 'ip address' 13777dd7cddfSDavid du Colombier */ 13787dd7cddfSDavid du Colombier if(*host == '[' && host[strlen(host)-1] == ']'){ 13797dd7cddfSDavid du Colombier host++; 13807dd7cddfSDavid du Colombier host[strlen(host)-1] = 0; 13817dd7cddfSDavid du Colombier } 13827dd7cddfSDavid du Colombier 13837dd7cddfSDavid du Colombier /* 13843e12c5d1SDavid du Colombier * just accept addresses 13853e12c5d1SDavid du Colombier */ 1386219b2ee8SDavid du Colombier attr = ipattr(host); 1387219b2ee8SDavid du Colombier if(strcmp(attr, "ip") == 0) 1388219b2ee8SDavid du Colombier return mktuple("ip", host); 13893e12c5d1SDavid du Colombier 13903e12c5d1SDavid du Colombier /* 13913e12c5d1SDavid du Colombier * give the domain name server the first opportunity to 1392bd389b36SDavid du Colombier * resolve domain names. if that fails try the database. 13933e12c5d1SDavid du Colombier */ 13943e12c5d1SDavid du Colombier t = 0; 1395271b8d73SDavid du Colombier werrstr("can't translate address"); 13963e12c5d1SDavid du Colombier if(strcmp(attr, "dom") == 0) 13977dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 13983e12c5d1SDavid du Colombier if(t == 0) 13993e12c5d1SDavid du Colombier t = ndbgetval(db, &s, attr, host, "ip", th); 14003e12c5d1SDavid du Colombier if(t == 0) 14017dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 14027dd7cddfSDavid du Colombier if(t == 0 && strcmp(attr, "dom") != 0) 14037dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 14047dd7cddfSDavid du Colombier if(t == 0) 1405219b2ee8SDavid du Colombier return 0; 1406bd389b36SDavid du Colombier 1407bd389b36SDavid du Colombier /* 1408bd389b36SDavid du Colombier * reorder the tuple to have the matched line first and 1409bd389b36SDavid du Colombier * save that in the request structure. 1410bd389b36SDavid du Colombier */ 14117dd7cddfSDavid du Colombier t = reorder(t, s.t); 14127dd7cddfSDavid du Colombier 14137dd7cddfSDavid du Colombier /* 14147dd7cddfSDavid du Colombier * reorder according to our interfaces 14157dd7cddfSDavid du Colombier */ 14167dd7cddfSDavid du Colombier lock(&ipifclock); 14179a747e4fSDavid du Colombier for(ifc = ipifcs; ifc != nil; ifc = ifc->next){ 14189a747e4fSDavid du Colombier for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ 14199a747e4fSDavid du Colombier maskip(lifc->ip, lifc->mask, net); 14207dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry){ 14217dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0) 14227dd7cddfSDavid du Colombier continue; 14237dd7cddfSDavid du Colombier parseip(ip, nt->val); 14249a747e4fSDavid du Colombier maskip(ip, lifc->mask, tnet); 14257dd7cddfSDavid du Colombier if(memcmp(net, tnet, IPaddrlen) == 0){ 14267dd7cddfSDavid du Colombier t = reorder(t, nt); 14277dd7cddfSDavid du Colombier unlock(&ipifclock); 14287dd7cddfSDavid du Colombier return t; 14297dd7cddfSDavid du Colombier } 14307dd7cddfSDavid du Colombier } 14317dd7cddfSDavid du Colombier } 14329a747e4fSDavid du Colombier } 14337dd7cddfSDavid du Colombier unlock(&ipifclock); 14347dd7cddfSDavid du Colombier 14357dd7cddfSDavid du Colombier return t; 14363e12c5d1SDavid du Colombier } 14373e12c5d1SDavid du Colombier 14383e12c5d1SDavid du Colombier /* 14393e12c5d1SDavid du Colombier * translate an ip address 14403e12c5d1SDavid du Colombier */ 1441219b2ee8SDavid du Colombier char* 144280ee5cbfSDavid du Colombier iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack) 14433e12c5d1SDavid du Colombier { 14443e12c5d1SDavid du Colombier char ts[Ndbvlen+1]; 1445219b2ee8SDavid du Colombier char reply[Maxreply]; 14467dd7cddfSDavid du Colombier char x[Ndbvlen+1]; 14473e12c5d1SDavid du Colombier 1448219b2ee8SDavid du Colombier if(strcmp(t->attr, "ip") != 0) 14493e12c5d1SDavid du Colombier return 0; 1450219b2ee8SDavid du Colombier 1451271b8d73SDavid du Colombier if(serv == 0 || ipserv(np, serv, ts) == 0){ 1452271b8d73SDavid du Colombier werrstr("can't translate service"); 1453219b2ee8SDavid du Colombier return 0; 1454271b8d73SDavid du Colombier } 14557dd7cddfSDavid du Colombier if(rem != nil) 14567dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 14577dd7cddfSDavid du Colombier else 14587dd7cddfSDavid du Colombier *x = 0; 145980ee5cbfSDavid du Colombier 1460219b2ee8SDavid du Colombier if(*t->val == '*') 14617dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", 14627dd7cddfSDavid du Colombier mntpt, np->net, ts, x); 1463219b2ee8SDavid du Colombier else 146480ee5cbfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s%s", 146580ee5cbfSDavid du Colombier mntpt, np->net, t->val, ts, x, hack?"!fasttimeout":""); 1466219b2ee8SDavid du Colombier 1467219b2ee8SDavid du Colombier return strdup(reply); 14683e12c5d1SDavid du Colombier } 14693e12c5d1SDavid du Colombier 1470219b2ee8SDavid du Colombier /* 1471219b2ee8SDavid du Colombier * lookup a telephone number 1472219b2ee8SDavid du Colombier */ 1473219b2ee8SDavid du Colombier Ndbtuple* 1474219b2ee8SDavid du Colombier telcolookup(Network *np, char *host, char *serv, int nolookup) 1475219b2ee8SDavid du Colombier { 1476219b2ee8SDavid du Colombier Ndbtuple *t; 1477219b2ee8SDavid du Colombier Ndbs s; 1478219b2ee8SDavid du Colombier char th[Ndbvlen+1]; 1479219b2ee8SDavid du Colombier 1480219b2ee8SDavid du Colombier USED(np, nolookup, serv); 1481219b2ee8SDavid du Colombier 1482271b8d73SDavid du Colombier werrstr("can't translate address"); 1483219b2ee8SDavid du Colombier t = ndbgetval(db, &s, "sys", host, "telco", th); 1484219b2ee8SDavid du Colombier if(t == 0) 1485219b2ee8SDavid du Colombier return mktuple("telco", host); 1486219b2ee8SDavid du Colombier 1487219b2ee8SDavid du Colombier return reorder(t, s.t); 1488219b2ee8SDavid du Colombier } 1489219b2ee8SDavid du Colombier 1490219b2ee8SDavid du Colombier /* 1491219b2ee8SDavid du Colombier * translate a telephone address 1492219b2ee8SDavid du Colombier */ 1493219b2ee8SDavid du Colombier char* 149480ee5cbfSDavid du Colombier telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int) 1495219b2ee8SDavid du Colombier { 1496219b2ee8SDavid du Colombier char reply[Maxreply]; 14977dd7cddfSDavid du Colombier char x[Ndbvlen+1]; 1498219b2ee8SDavid du Colombier 1499219b2ee8SDavid du Colombier if(strcmp(t->attr, "telco") != 0) 1500219b2ee8SDavid du Colombier return 0; 1501219b2ee8SDavid du Colombier 15027dd7cddfSDavid du Colombier if(rem != nil) 15037dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 1504219b2ee8SDavid du Colombier else 15057dd7cddfSDavid du Colombier *x = 0; 15067dd7cddfSDavid du Colombier if(serv) 15077dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s", mntpt, np->net, 15087dd7cddfSDavid du Colombier t->val, serv, x); 15097dd7cddfSDavid du Colombier else 15107dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net, 15117dd7cddfSDavid du Colombier t->val, x); 1512219b2ee8SDavid du Colombier return strdup(reply); 1513219b2ee8SDavid du Colombier } 15143e12c5d1SDavid du Colombier 15153e12c5d1SDavid du Colombier /* 15163e12c5d1SDavid du Colombier * reorder the tuple to put x's line first in the entry 15173e12c5d1SDavid du Colombier */ 15183e12c5d1SDavid du Colombier Ndbtuple* 15193e12c5d1SDavid du Colombier reorder(Ndbtuple *t, Ndbtuple *x) 15203e12c5d1SDavid du Colombier { 15213e12c5d1SDavid du Colombier Ndbtuple *nt; 15223e12c5d1SDavid du Colombier Ndbtuple *line; 15233e12c5d1SDavid du Colombier 1524219b2ee8SDavid du Colombier /* find start of this entry's line */ 1525219b2ee8SDavid du Colombier for(line = x; line->entry == line->line; line = line->line) 15263e12c5d1SDavid du Colombier ; 1527219b2ee8SDavid du Colombier line = line->line; 1528219b2ee8SDavid du Colombier if(line == t) 1529219b2ee8SDavid du Colombier return t; /* already the first line */ 15303e12c5d1SDavid du Colombier 1531219b2ee8SDavid du Colombier /* remove this line and everything after it from the entry */ 1532219b2ee8SDavid du Colombier for(nt = t; nt->entry != line; nt = nt->entry) 1533219b2ee8SDavid du Colombier ; 1534219b2ee8SDavid du Colombier nt->entry = 0; 15353e12c5d1SDavid du Colombier 1536219b2ee8SDavid du Colombier /* make that the start of the entry */ 1537219b2ee8SDavid du Colombier for(nt = line; nt->entry; nt = nt->entry) 1538219b2ee8SDavid du Colombier ; 15393e12c5d1SDavid du Colombier nt->entry = t; 15403e12c5d1SDavid du Colombier return line; 15413e12c5d1SDavid du Colombier } 15423e12c5d1SDavid du Colombier 15433e12c5d1SDavid du Colombier /* 15443e12c5d1SDavid du Colombier * create a slave process to handle a request to avoid one request blocking 15457dd7cddfSDavid du Colombier * another. parent returns to job loop. 15463e12c5d1SDavid du Colombier */ 15473e12c5d1SDavid du Colombier void 15483e12c5d1SDavid du Colombier slave(void) 15493e12c5d1SDavid du Colombier { 15503e12c5d1SDavid du Colombier if(*isslave) 15513e12c5d1SDavid du Colombier return; /* we're already a slave process */ 15523e12c5d1SDavid du Colombier 15533e12c5d1SDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 15543e12c5d1SDavid du Colombier case -1: 15553e12c5d1SDavid du Colombier break; 15563e12c5d1SDavid du Colombier case 0: 1557219b2ee8SDavid du Colombier if(debug) 1558219b2ee8SDavid du Colombier syslog(0, logfile, "slave %d", getpid()); 15593e12c5d1SDavid du Colombier *isslave = 1; 15603e12c5d1SDavid du Colombier break; 15613e12c5d1SDavid du Colombier default: 15623e12c5d1SDavid du Colombier longjmp(masterjmp, 1); 15633e12c5d1SDavid du Colombier } 15643e12c5d1SDavid du Colombier 1565219b2ee8SDavid du Colombier } 1566219b2ee8SDavid du Colombier 15673e12c5d1SDavid du Colombier /* 15683e12c5d1SDavid du Colombier * call the dns process and have it try to translate a name 15693e12c5d1SDavid du Colombier */ 15703e12c5d1SDavid du Colombier Ndbtuple* 15717dd7cddfSDavid du Colombier dnsiplookup(char *host, Ndbs *s) 15723e12c5d1SDavid du Colombier { 15733e12c5d1SDavid du Colombier char buf[Ndbvlen + 4]; 15747dd7cddfSDavid du Colombier Ndbtuple *t; 15753e12c5d1SDavid du Colombier 1576bd389b36SDavid du Colombier unlock(&dblock); 1577bd389b36SDavid du Colombier 15783e12c5d1SDavid du Colombier /* save the name before starting a slave */ 15797dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s", host); 15803e12c5d1SDavid du Colombier 15813e12c5d1SDavid du Colombier slave(); 15823e12c5d1SDavid du Colombier 15837dd7cddfSDavid du Colombier if(strcmp(ipattr(buf), "ip") == 0) 15847dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ptr"); 15857dd7cddfSDavid du Colombier else 15867dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ip"); 15873e12c5d1SDavid du Colombier s->t = t; 15887dd7cddfSDavid du Colombier 1589271b8d73SDavid du Colombier if(t == nil){ 1590271b8d73SDavid du Colombier rerrstr(buf, sizeof buf); 1591271b8d73SDavid du Colombier if(strstr(buf, "exist")) 1592271b8d73SDavid du Colombier werrstr("can't translate address: %s", buf); 1593271b8d73SDavid du Colombier else if(strstr(buf, "dns failure")) 1594271b8d73SDavid du Colombier werrstr("temporary problem: %s", buf); 1595271b8d73SDavid du Colombier } 1596271b8d73SDavid du Colombier 1597bd389b36SDavid du Colombier lock(&dblock); 15983e12c5d1SDavid du Colombier return t; 15993e12c5d1SDavid du Colombier } 1600219b2ee8SDavid du Colombier 1601219b2ee8SDavid du Colombier int 1602219b2ee8SDavid du Colombier qmatch(Ndbtuple *t, char **attr, char **val, int n) 1603219b2ee8SDavid du Colombier { 1604219b2ee8SDavid du Colombier int i, found; 1605219b2ee8SDavid du Colombier Ndbtuple *nt; 1606219b2ee8SDavid du Colombier 1607219b2ee8SDavid du Colombier for(i = 1; i < n; i++){ 1608219b2ee8SDavid du Colombier found = 0; 1609219b2ee8SDavid du Colombier for(nt = t; nt; nt = nt->entry) 1610219b2ee8SDavid du Colombier if(strcmp(attr[i], nt->attr) == 0) 1611219b2ee8SDavid du Colombier if(strcmp(val[i], "*") == 0 1612219b2ee8SDavid du Colombier || strcmp(val[i], nt->val) == 0){ 1613219b2ee8SDavid du Colombier found = 1; 1614219b2ee8SDavid du Colombier break; 1615219b2ee8SDavid du Colombier } 1616219b2ee8SDavid du Colombier if(found == 0) 1617219b2ee8SDavid du Colombier break; 1618219b2ee8SDavid du Colombier } 1619219b2ee8SDavid du Colombier return i == n; 1620219b2ee8SDavid du Colombier } 1621219b2ee8SDavid du Colombier 1622219b2ee8SDavid du Colombier void 1623219b2ee8SDavid du Colombier qreply(Mfile *mf, Ndbtuple *t) 1624219b2ee8SDavid du Colombier { 1625219b2ee8SDavid du Colombier int i; 1626219b2ee8SDavid du Colombier Ndbtuple *nt; 16277dd7cddfSDavid du Colombier char buf[2048]; 1628219b2ee8SDavid du Colombier 1629219b2ee8SDavid du Colombier buf[0] = 0; 1630219b2ee8SDavid du Colombier for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){ 1631219b2ee8SDavid du Colombier strcat(buf, nt->attr); 1632219b2ee8SDavid du Colombier strcat(buf, "="); 1633219b2ee8SDavid du Colombier strcat(buf, nt->val); 1634219b2ee8SDavid du Colombier i = strlen(buf); 1635219b2ee8SDavid du Colombier if(nt->line != nt->entry || sizeof(buf) - i < 2*Ndbvlen+2){ 1636219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(buf); 1637219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = strdup(buf); 1638219b2ee8SDavid du Colombier buf[0] = 0; 1639219b2ee8SDavid du Colombier } else 1640219b2ee8SDavid du Colombier strcat(buf, " "); 1641219b2ee8SDavid du Colombier } 1642219b2ee8SDavid du Colombier } 1643219b2ee8SDavid du Colombier 16447dd7cddfSDavid du Colombier enum 16457dd7cddfSDavid du Colombier { 16467dd7cddfSDavid du Colombier Maxattr= 32, 16477dd7cddfSDavid du Colombier }; 16487dd7cddfSDavid du Colombier 1649219b2ee8SDavid du Colombier /* 16507dd7cddfSDavid du Colombier * generic query lookup. The query is of one of the following 16517dd7cddfSDavid du Colombier * forms: 16527dd7cddfSDavid du Colombier * 16537dd7cddfSDavid du Colombier * attr1=val1 attr2=val2 attr3=val3 ... 16547dd7cddfSDavid du Colombier * 16557dd7cddfSDavid du Colombier * returns the matching tuple 16567dd7cddfSDavid du Colombier * 16577dd7cddfSDavid du Colombier * ipinfo attr=val attr1 attr2 attr3 ... 16587dd7cddfSDavid du Colombier * 16597dd7cddfSDavid du Colombier * is like ipinfo and returns the attr{1-n} 16607dd7cddfSDavid du Colombier * associated with the ip address. 1661219b2ee8SDavid du Colombier */ 1662219b2ee8SDavid du Colombier char* 1663219b2ee8SDavid du Colombier genquery(Mfile *mf, char *query) 1664219b2ee8SDavid du Colombier { 1665219b2ee8SDavid du Colombier int i, n; 1666219b2ee8SDavid du Colombier char *p; 16677dd7cddfSDavid du Colombier char *attr[Maxattr]; 16687dd7cddfSDavid du Colombier char *val[Maxattr]; 1669219b2ee8SDavid du Colombier Ndbtuple *t; 1670219b2ee8SDavid du Colombier Ndbs s; 1671219b2ee8SDavid du Colombier 16727dd7cddfSDavid du Colombier n = getfields(query, attr, 32, 1, " "); 1673219b2ee8SDavid du Colombier if(n == 0) 1674219b2ee8SDavid du Colombier return "bad query"; 1675219b2ee8SDavid du Colombier 16767dd7cddfSDavid du Colombier if(strcmp(attr[0], "ipinfo") == 0) 16777dd7cddfSDavid du Colombier return ipinfoquery(mf, attr, n); 16787dd7cddfSDavid du Colombier 1679219b2ee8SDavid du Colombier /* parse pairs */ 1680219b2ee8SDavid du Colombier for(i = 0; i < n; i++){ 1681219b2ee8SDavid du Colombier p = strchr(attr[i], '='); 1682219b2ee8SDavid du Colombier if(p == 0) 1683219b2ee8SDavid du Colombier return "bad query"; 1684219b2ee8SDavid du Colombier *p++ = 0; 1685219b2ee8SDavid du Colombier val[i] = p; 1686219b2ee8SDavid du Colombier } 1687219b2ee8SDavid du Colombier 1688219b2ee8SDavid du Colombier /* give dns a chance */ 1689219b2ee8SDavid du Colombier if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){ 16907dd7cddfSDavid du Colombier t = dnsiplookup(val[0], &s); 1691219b2ee8SDavid du Colombier if(t){ 1692219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1693219b2ee8SDavid du Colombier qreply(mf, t); 1694219b2ee8SDavid du Colombier ndbfree(t); 1695219b2ee8SDavid du Colombier return 0; 1696219b2ee8SDavid du Colombier } 1697219b2ee8SDavid du Colombier ndbfree(t); 1698219b2ee8SDavid du Colombier } 1699219b2ee8SDavid du Colombier } 1700219b2ee8SDavid du Colombier 1701219b2ee8SDavid du Colombier /* first pair is always the key. It can't be a '*' */ 1702219b2ee8SDavid du Colombier t = ndbsearch(db, &s, attr[0], val[0]); 1703219b2ee8SDavid du Colombier 1704219b2ee8SDavid du Colombier /* search is the and of all the pairs */ 1705219b2ee8SDavid du Colombier while(t){ 1706219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1707219b2ee8SDavid du Colombier qreply(mf, t); 1708219b2ee8SDavid du Colombier ndbfree(t); 1709219b2ee8SDavid du Colombier return 0; 1710219b2ee8SDavid du Colombier } 1711219b2ee8SDavid du Colombier 1712219b2ee8SDavid du Colombier ndbfree(t); 1713219b2ee8SDavid du Colombier t = ndbsnext(&s, attr[0], val[0]); 1714219b2ee8SDavid du Colombier } 1715219b2ee8SDavid du Colombier 1716219b2ee8SDavid du Colombier return "no match"; 1717219b2ee8SDavid du Colombier } 17187dd7cddfSDavid du Colombier 17197dd7cddfSDavid du Colombier /* 17207dd7cddfSDavid du Colombier * resolve an ip address 17217dd7cddfSDavid du Colombier */ 17227dd7cddfSDavid du Colombier static Ndbtuple* 17237dd7cddfSDavid du Colombier ipresolve(char *attr, char *host) 17247dd7cddfSDavid du Colombier { 17257dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17267dd7cddfSDavid du Colombier 17277dd7cddfSDavid du Colombier t = iplookup(&network[Ntcp], host, "*", 0); 17287dd7cddfSDavid du Colombier for(l = &t; *l != nil; ){ 17297dd7cddfSDavid du Colombier nt = *l; 17307dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0){ 17317dd7cddfSDavid du Colombier *l = nt->entry; 17327dd7cddfSDavid du Colombier nt->entry = nil; 17337dd7cddfSDavid du Colombier ndbfree(nt); 17347dd7cddfSDavid du Colombier continue; 17357dd7cddfSDavid du Colombier } 17367dd7cddfSDavid du Colombier strcpy(nt->attr, attr); 17377dd7cddfSDavid du Colombier l = &nt->entry; 17387dd7cddfSDavid du Colombier } 17397dd7cddfSDavid du Colombier return t; 17407dd7cddfSDavid du Colombier } 17417dd7cddfSDavid du Colombier 17427dd7cddfSDavid du Colombier char* 17437dd7cddfSDavid du Colombier ipinfoquery(Mfile *mf, char **list, int n) 17447dd7cddfSDavid du Colombier { 17457dd7cddfSDavid du Colombier int i, nresolve; 17467dd7cddfSDavid du Colombier int resolve[Maxattr]; 17477dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17487dd7cddfSDavid du Colombier char *attr, *val; 17497dd7cddfSDavid du Colombier 17507dd7cddfSDavid du Colombier /* skip 'ipinfo' */ 17517dd7cddfSDavid du Colombier list++; n--; 17527dd7cddfSDavid du Colombier 17537dd7cddfSDavid du Colombier if(n < 2) 17547dd7cddfSDavid du Colombier return "bad query"; 17557dd7cddfSDavid du Colombier 17567dd7cddfSDavid du Colombier /* get search attribute=value */ 17577dd7cddfSDavid du Colombier attr = *list++; n--; 17587dd7cddfSDavid du Colombier val = strchr(attr, '='); 17597dd7cddfSDavid du Colombier if(val == nil) 17607dd7cddfSDavid du Colombier return "bad query"; 17617dd7cddfSDavid du Colombier *val++ = 0; 17627dd7cddfSDavid du Colombier 17637dd7cddfSDavid du Colombier /* 17647dd7cddfSDavid du Colombier * don't let ndbipinfo resolve the addresses, we're 17657dd7cddfSDavid du Colombier * better at it. 17667dd7cddfSDavid du Colombier */ 17677dd7cddfSDavid du Colombier nresolve = 0; 17687dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 17697dd7cddfSDavid du Colombier if(*list[i] == '@'){ 17707dd7cddfSDavid du Colombier list[i]++; 17717dd7cddfSDavid du Colombier resolve[i] = 1; 17727dd7cddfSDavid du Colombier nresolve++; 17737dd7cddfSDavid du Colombier } else 17747dd7cddfSDavid du Colombier resolve[i] = 0; 17757dd7cddfSDavid du Colombier 17767dd7cddfSDavid du Colombier t = ndbipinfo(db, attr, val, list, n); 17777dd7cddfSDavid du Colombier if(t == nil) 17787dd7cddfSDavid du Colombier return "no match"; 17797dd7cddfSDavid du Colombier 17807dd7cddfSDavid du Colombier if(nresolve != 0){ 17817dd7cddfSDavid du Colombier for(l = &t; *l != nil;){ 17827dd7cddfSDavid du Colombier nt = *l; 17837dd7cddfSDavid du Colombier 17847dd7cddfSDavid du Colombier /* already an address? */ 17857dd7cddfSDavid du Colombier if(strcmp(ipattr(nt->val), "ip") == 0){ 17867dd7cddfSDavid du Colombier l = &(*l)->entry; 17877dd7cddfSDavid du Colombier continue; 17887dd7cddfSDavid du Colombier } 17897dd7cddfSDavid du Colombier 17907dd7cddfSDavid du Colombier /* user wants it resolved? */ 17917dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 17927dd7cddfSDavid du Colombier if(strcmp(list[i], nt->attr) == 0) 17937dd7cddfSDavid du Colombier break; 17947dd7cddfSDavid du Colombier if(i >= n || resolve[i] == 0){ 17957dd7cddfSDavid du Colombier l = &(*l)->entry; 17967dd7cddfSDavid du Colombier continue; 17977dd7cddfSDavid du Colombier } 17987dd7cddfSDavid du Colombier 17997dd7cddfSDavid du Colombier /* resolve address and replace entry */ 18007dd7cddfSDavid du Colombier *l = ipresolve(nt->attr, nt->val); 18017dd7cddfSDavid du Colombier while(*l != nil) 18027dd7cddfSDavid du Colombier l = &(*l)->entry; 18037dd7cddfSDavid du Colombier *l = nt->entry; 18047dd7cddfSDavid du Colombier 18057dd7cddfSDavid du Colombier nt->entry = nil; 18067dd7cddfSDavid du Colombier ndbfree(nt); 18077dd7cddfSDavid du Colombier } 18087dd7cddfSDavid du Colombier } 18097dd7cddfSDavid du Colombier 18107dd7cddfSDavid du Colombier /* make it all one line */ 18117dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 18127dd7cddfSDavid du Colombier if(nt->entry == nil) 18137dd7cddfSDavid du Colombier nt->line = t; 18147dd7cddfSDavid du Colombier else 18157dd7cddfSDavid du Colombier nt->line = nt->entry; 18167dd7cddfSDavid du Colombier } 18177dd7cddfSDavid du Colombier 18187dd7cddfSDavid du Colombier qreply(mf, t); 18197dd7cddfSDavid du Colombier 18207dd7cddfSDavid du Colombier return nil; 18217dd7cddfSDavid du Colombier } 18227dd7cddfSDavid du Colombier 18237dd7cddfSDavid du Colombier void* 18247dd7cddfSDavid du Colombier emalloc(int size) 18257dd7cddfSDavid du Colombier { 18267dd7cddfSDavid du Colombier void *x; 18277dd7cddfSDavid du Colombier 18287dd7cddfSDavid du Colombier x = malloc(size); 18297dd7cddfSDavid du Colombier if(x == nil) 18307dd7cddfSDavid du Colombier abort(); 18317dd7cddfSDavid du Colombier memset(x, 0, size); 18327dd7cddfSDavid du Colombier return x; 18337dd7cddfSDavid du Colombier } 18349a747e4fSDavid du Colombier 18359a747e4fSDavid du Colombier char* 18369a747e4fSDavid du Colombier estrdup(char *s) 18379a747e4fSDavid du Colombier { 18389a747e4fSDavid du Colombier int size; 18399a747e4fSDavid du Colombier char *p; 18409a747e4fSDavid du Colombier 18419a747e4fSDavid du Colombier size = strlen(s)+1; 18429a747e4fSDavid du Colombier p = malloc(size); 18439a747e4fSDavid du Colombier if(p == nil) 18449a747e4fSDavid du Colombier abort(); 18459a747e4fSDavid du Colombier memmove(p, s, size); 18469a747e4fSDavid du Colombier return p; 18479a747e4fSDavid du Colombier } 1848