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> 995a264b3SDavid du Colombier #include <String.h> 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier enum 123e12c5d1SDavid du Colombier { 1380ee5cbfSDavid du Colombier Nreply= 20, 143e12c5d1SDavid du Colombier Maxreply= 256, 157dd7cddfSDavid du Colombier Maxrequest= 128, 167dd7cddfSDavid du Colombier Maxpath= 128, 179a747e4fSDavid du Colombier Maxfdata= 8192, 1895a264b3SDavid du Colombier Maxhost= 64, /* maximum host name size */ 1995a264b3SDavid du Colombier Maxservice= 64, /* maximum service name size */ 203e12c5d1SDavid du Colombier 219a747e4fSDavid du Colombier Qdir= 0, 223e12c5d1SDavid du Colombier Qcs= 1, 233e12c5d1SDavid du Colombier }; 243e12c5d1SDavid du Colombier 253e12c5d1SDavid du Colombier typedef struct Mfile Mfile; 26219b2ee8SDavid du Colombier typedef struct Mlist Mlist; 273e12c5d1SDavid du Colombier typedef struct Network Network; 287dd7cddfSDavid du Colombier typedef struct Flushreq Flushreq; 297dd7cddfSDavid du Colombier typedef struct Job Job; 303e12c5d1SDavid du Colombier 313e12c5d1SDavid du Colombier int vers; /* incremented each clone/attach */ 323e12c5d1SDavid du Colombier 333e12c5d1SDavid du Colombier struct Mfile 343e12c5d1SDavid du Colombier { 353e12c5d1SDavid du Colombier int busy; 36219b2ee8SDavid du Colombier 379a747e4fSDavid du Colombier char *user; 383e12c5d1SDavid du Colombier Qid qid; 393e12c5d1SDavid du Colombier int fid; 403e12c5d1SDavid du Colombier 4180ee5cbfSDavid du Colombier /* 4280ee5cbfSDavid du Colombier * current request 4380ee5cbfSDavid du Colombier */ 4480ee5cbfSDavid du Colombier char *net; 4580ee5cbfSDavid du Colombier char *host; 4680ee5cbfSDavid du Colombier char *serv; 4780ee5cbfSDavid du Colombier char *rem; 4880ee5cbfSDavid du Colombier 4980ee5cbfSDavid du Colombier /* 5080ee5cbfSDavid du Colombier * result of the last lookup 5180ee5cbfSDavid du Colombier */ 5280ee5cbfSDavid du Colombier Network *nextnet; 53219b2ee8SDavid du Colombier int nreply; 54219b2ee8SDavid du Colombier char *reply[Nreply]; 55219b2ee8SDavid du Colombier int replylen[Nreply]; 56219b2ee8SDavid du Colombier }; 57219b2ee8SDavid du Colombier 58219b2ee8SDavid du Colombier struct Mlist 59219b2ee8SDavid du Colombier { 60219b2ee8SDavid du Colombier Mlist *next; 61219b2ee8SDavid du Colombier Mfile mf; 623e12c5d1SDavid du Colombier }; 633e12c5d1SDavid du Colombier 649a747e4fSDavid du Colombier 65244672c5SDavid du Colombier /* 66244672c5SDavid du Colombier * active requests 67244672c5SDavid du Colombier */ 687dd7cddfSDavid du Colombier struct Job 697dd7cddfSDavid du Colombier { 707dd7cddfSDavid du Colombier Job *next; 717dd7cddfSDavid du Colombier int flushed; 727dd7cddfSDavid du Colombier Fcall request; 737dd7cddfSDavid du Colombier Fcall reply; 747dd7cddfSDavid du Colombier }; 757dd7cddfSDavid du Colombier Lock joblock; 767dd7cddfSDavid du Colombier Job *joblist; 777dd7cddfSDavid du Colombier 78219b2ee8SDavid du Colombier Mlist *mlist; 793e12c5d1SDavid du Colombier int mfd[2]; 803e12c5d1SDavid du Colombier int debug; 817dd7cddfSDavid du Colombier int paranoia; 823e12c5d1SDavid du Colombier jmp_buf masterjmp; /* return through here after a slave process has been created */ 833e12c5d1SDavid du Colombier int *isslave; /* *isslave non-zero means this is a slave process */ 84bd389b36SDavid du Colombier char *dbfile; 857dd7cddfSDavid du Colombier Ndb *db, *netdb; 863e12c5d1SDavid du Colombier 879a747e4fSDavid du Colombier void rversion(Job*); 887dd7cddfSDavid du Colombier void rflush(Job*); 897dd7cddfSDavid du Colombier void rattach(Job*, Mfile*); 907dd7cddfSDavid du Colombier char* rwalk(Job*, Mfile*); 917dd7cddfSDavid du Colombier void ropen(Job*, Mfile*); 927dd7cddfSDavid du Colombier void rcreate(Job*, Mfile*); 937dd7cddfSDavid du Colombier void rread(Job*, Mfile*); 947dd7cddfSDavid du Colombier void rwrite(Job*, Mfile*); 957dd7cddfSDavid du Colombier void rclunk(Job*, Mfile*); 967dd7cddfSDavid du Colombier void rremove(Job*, Mfile*); 977dd7cddfSDavid du Colombier void rstat(Job*, Mfile*); 987dd7cddfSDavid du Colombier void rwstat(Job*, Mfile*); 999a747e4fSDavid du Colombier void rauth(Job*); 1007dd7cddfSDavid du Colombier void sendmsg(Job*, char*); 1013e12c5d1SDavid du Colombier void error(char*); 1027dd7cddfSDavid du Colombier void mountinit(char*, char*); 1033e12c5d1SDavid du Colombier void io(void); 1047dd7cddfSDavid du Colombier void ndbinit(void); 1057dd7cddfSDavid du Colombier void netinit(int); 1063e12c5d1SDavid du Colombier void netadd(char*); 107219b2ee8SDavid du Colombier char *genquery(Mfile*, char*); 1087dd7cddfSDavid du Colombier char* ipinfoquery(Mfile*, char**, int); 109bd389b36SDavid du Colombier int needproto(Network*, Ndbtuple*); 1109a747e4fSDavid du Colombier int lookup(Mfile*); 1113e12c5d1SDavid du Colombier Ndbtuple* reorder(Ndbtuple*, Ndbtuple*); 1127dd7cddfSDavid du Colombier void ipid(void); 1137dd7cddfSDavid du Colombier void readipinterfaces(void); 1147dd7cddfSDavid du Colombier void* emalloc(int); 1159a747e4fSDavid du Colombier char* estrdup(char*); 1167dd7cddfSDavid du Colombier Job* newjob(void); 1177dd7cddfSDavid du Colombier void freejob(Job*); 1187dd7cddfSDavid du Colombier void setext(char*, int, char*); 11980ee5cbfSDavid du Colombier void cleanmf(Mfile*); 1203e12c5d1SDavid du Colombier 121bd389b36SDavid du Colombier extern void paralloc(void); 122bd389b36SDavid du Colombier 123bd389b36SDavid du Colombier Lock dblock; /* mutex on database operations */ 1247dd7cddfSDavid du Colombier Lock netlock; /* mutex for netinit() */ 125bd389b36SDavid du Colombier 126219b2ee8SDavid du Colombier char *logfile = "cs"; 1277dd7cddfSDavid du Colombier char *paranoiafile = "cs.paranoia"; 128219b2ee8SDavid du Colombier 1297dd7cddfSDavid du Colombier char mntpt[Maxpath]; 1307dd7cddfSDavid du Colombier char netndb[Maxpath]; 1317dd7cddfSDavid du Colombier 13280ee5cbfSDavid du Colombier /* 13380ee5cbfSDavid du Colombier * Network specific translators 13480ee5cbfSDavid du Colombier */ 13580ee5cbfSDavid du Colombier Ndbtuple* iplookup(Network*, char*, char*, int); 13680ee5cbfSDavid du Colombier char* iptrans(Ndbtuple*, Network*, char*, char*, int); 13780ee5cbfSDavid du Colombier Ndbtuple* telcolookup(Network*, char*, char*, int); 13880ee5cbfSDavid du Colombier char* telcotrans(Ndbtuple*, Network*, char*, char*, int); 13980ee5cbfSDavid du Colombier Ndbtuple* dnsiplookup(char*, Ndbs*); 14080ee5cbfSDavid du Colombier 14180ee5cbfSDavid du Colombier struct Network 14280ee5cbfSDavid du Colombier { 14380ee5cbfSDavid du Colombier char *net; 14480ee5cbfSDavid du Colombier Ndbtuple *(*lookup)(Network*, char*, char*, int); 14580ee5cbfSDavid du Colombier char *(*trans)(Ndbtuple*, Network*, char*, char*, int); 14680ee5cbfSDavid du Colombier int considered; 14780ee5cbfSDavid du Colombier int fasttimeouthack; 14880ee5cbfSDavid du Colombier Network *next; 14980ee5cbfSDavid du Colombier }; 15080ee5cbfSDavid du Colombier 15180ee5cbfSDavid du Colombier enum 15280ee5cbfSDavid du Colombier { 153*75766116SDavid du Colombier Ntcp = 0, 154244672c5SDavid du Colombier // Nilfast, 155*75766116SDavid du Colombier 156*75766116SDavid du Colombier // Fasttimeout = 1, 15780ee5cbfSDavid du Colombier }; 15880ee5cbfSDavid du Colombier 15980ee5cbfSDavid du Colombier /* 160244672c5SDavid du Colombier * net doesn't apply to (r)udp, icmp(v6), or telco (for speed). 16180ee5cbfSDavid du Colombier */ 16280ee5cbfSDavid du Colombier Network network[] = { 16380ee5cbfSDavid du Colombier [Ntcp] { "tcp", iplookup, iptrans, 0, 0 }, 164*75766116SDavid du Colombier // [Nilfast]{ "il", iplookup, iptrans, 0, Fasttimeout }, 165*75766116SDavid du Colombier { "il", iplookup, iptrans, 0, 0 }, 166*75766116SDavid du Colombier { "udp", iplookup, iptrans, 1, 0 }, 167*75766116SDavid du Colombier { "icmp", iplookup, iptrans, 1, 0 }, 168*75766116SDavid du Colombier { "icmpv6", iplookup, iptrans, 1, 0 }, 169*75766116SDavid du Colombier { "rudp", iplookup, iptrans, 1, 0 }, 170*75766116SDavid du Colombier { "telco", telcolookup, telcotrans, 1, 0 }, 17180ee5cbfSDavid du Colombier { 0 }, 17280ee5cbfSDavid du Colombier }; 17380ee5cbfSDavid du Colombier 17480ee5cbfSDavid du Colombier Lock ipifclock; 17580ee5cbfSDavid du Colombier Ipifc *ipifcs; 17680ee5cbfSDavid du Colombier 17795a264b3SDavid du Colombier char eaddr[16]; /* ascii ethernet address */ 17895a264b3SDavid du Colombier char ipaddr[64]; /* ascii internet address */ 17980ee5cbfSDavid du Colombier uchar ipa[IPaddrlen]; /* binary internet address */ 18095a264b3SDavid du Colombier char *mysysname; 18180ee5cbfSDavid du Colombier 18280ee5cbfSDavid du Colombier Network *netlist; /* networks ordered by preference */ 18380ee5cbfSDavid du Colombier Network *last; 18480ee5cbfSDavid du Colombier 18595a264b3SDavid du Colombier static void 18695a264b3SDavid du Colombier nstrcpy(char *to, char *from, int len) 18795a264b3SDavid du Colombier { 18895a264b3SDavid du Colombier strncpy(to, from, len); 18995a264b3SDavid du Colombier to[len-1] = 0; 19095a264b3SDavid du Colombier } 19195a264b3SDavid du Colombier 1927dd7cddfSDavid du Colombier void 1937dd7cddfSDavid du Colombier usage(void) 1947dd7cddfSDavid du Colombier { 195*75766116SDavid du Colombier fprint(2, "usage: %s [-dn] [-f ndb-file] [-x netmtpt]\n", argv0); 1967dd7cddfSDavid du Colombier exits("usage"); 1977dd7cddfSDavid du Colombier } 198219b2ee8SDavid du Colombier 1993e12c5d1SDavid du Colombier void 2003e12c5d1SDavid du Colombier main(int argc, char *argv[]) 2013e12c5d1SDavid du Colombier { 202219b2ee8SDavid du Colombier int justsetname; 203*75766116SDavid du Colombier char ext[Maxpath], servefile[Maxpath]; 2043e12c5d1SDavid du Colombier 205219b2ee8SDavid du Colombier justsetname = 0; 2067dd7cddfSDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), nil); 2077dd7cddfSDavid du Colombier ext[0] = 0; 2083e12c5d1SDavid du Colombier ARGBEGIN{ 2093e12c5d1SDavid du Colombier case 'd': 2103e12c5d1SDavid du Colombier debug = 1; 2113e12c5d1SDavid du Colombier break; 212bd389b36SDavid du Colombier case 'f': 213*75766116SDavid du Colombier dbfile = EARGF(usage()); 214bd389b36SDavid du Colombier break; 215219b2ee8SDavid du Colombier case 'n': 216219b2ee8SDavid du Colombier justsetname = 1; 217219b2ee8SDavid du Colombier break; 218*75766116SDavid du Colombier case 'x': 219*75766116SDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), EARGF(usage())); 220*75766116SDavid du Colombier setext(ext, sizeof(ext), mntpt); 221*75766116SDavid 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"); 278a9f680aeSDavid du Colombier 279a9f680aeSDavid du Colombier /* 280a9f680aeSDavid du Colombier * make a /srv/cs 281a9f680aeSDavid du Colombier */ 282a9f680aeSDavid du Colombier f = create(service, OWRITE|ORCLOSE, 0666); 283a9f680aeSDavid du Colombier if(f < 0) 284a9f680aeSDavid du Colombier error(service); 285a9f680aeSDavid du Colombier snprint(buf, sizeof(buf), "%d", p[1]); 286a9f680aeSDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf)) 287a9f680aeSDavid du Colombier error("write /srv/cs"); 288a9f680aeSDavid du Colombier 289219b2ee8SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG)){ 2903e12c5d1SDavid du Colombier case 0: 291219b2ee8SDavid du Colombier close(p[1]); 2923e12c5d1SDavid du Colombier break; 2933e12c5d1SDavid du Colombier case -1: 2943e12c5d1SDavid du Colombier error("fork failed\n"); 2953e12c5d1SDavid du Colombier default: 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 } 422bd389b36SDavid du Colombier lock(&dblock); 4237dd7cddfSDavid du Colombier mf = newfid(job->request.fid); 424219b2ee8SDavid du Colombier if(debug) 4257dd7cddfSDavid du Colombier syslog(0, logfile, "%F", &job->request); 4263e12c5d1SDavid du Colombier 4273e12c5d1SDavid du Colombier 4287dd7cddfSDavid du Colombier switch(job->request.type){ 4293e12c5d1SDavid du Colombier default: 4307dd7cddfSDavid du Colombier syslog(1, logfile, "unknown request type %d", job->request.type); 4313e12c5d1SDavid du Colombier break; 4329a747e4fSDavid du Colombier case Tversion: 4339a747e4fSDavid du Colombier rversion(job); 4343e12c5d1SDavid du Colombier break; 4359a747e4fSDavid du Colombier case Tauth: 4369a747e4fSDavid du Colombier rauth(job); 4373e12c5d1SDavid du Colombier break; 4383e12c5d1SDavid du Colombier case Tflush: 4397dd7cddfSDavid du Colombier rflush(job); 4403e12c5d1SDavid du Colombier break; 4413e12c5d1SDavid du Colombier case Tattach: 4427dd7cddfSDavid du Colombier rattach(job, mf); 4433e12c5d1SDavid du Colombier break; 4443e12c5d1SDavid du Colombier case Twalk: 4457dd7cddfSDavid du Colombier rwalk(job, mf); 4463e12c5d1SDavid du Colombier break; 4473e12c5d1SDavid du Colombier case Topen: 4487dd7cddfSDavid du Colombier ropen(job, mf); 4493e12c5d1SDavid du Colombier break; 4503e12c5d1SDavid du Colombier case Tcreate: 4517dd7cddfSDavid du Colombier rcreate(job, mf); 4523e12c5d1SDavid du Colombier break; 4533e12c5d1SDavid du Colombier case Tread: 4547dd7cddfSDavid du Colombier rread(job, mf); 4553e12c5d1SDavid du Colombier break; 4563e12c5d1SDavid du Colombier case Twrite: 4577dd7cddfSDavid du Colombier rwrite(job, mf); 4583e12c5d1SDavid du Colombier break; 4593e12c5d1SDavid du Colombier case Tclunk: 4607dd7cddfSDavid du Colombier rclunk(job, mf); 4613e12c5d1SDavid du Colombier break; 4623e12c5d1SDavid du Colombier case Tremove: 4637dd7cddfSDavid du Colombier rremove(job, mf); 4643e12c5d1SDavid du Colombier break; 4653e12c5d1SDavid du Colombier case Tstat: 4667dd7cddfSDavid du Colombier rstat(job, mf); 4673e12c5d1SDavid du Colombier break; 4683e12c5d1SDavid du Colombier case Twstat: 4697dd7cddfSDavid du Colombier rwstat(job, mf); 4703e12c5d1SDavid du Colombier break; 4713e12c5d1SDavid du Colombier } 472bd389b36SDavid du Colombier unlock(&dblock); 4737dd7cddfSDavid du Colombier 4747dd7cddfSDavid du Colombier freejob(job); 4757dd7cddfSDavid du Colombier 4763e12c5d1SDavid du Colombier /* 4773e12c5d1SDavid du Colombier * slave processes die after replying 4783e12c5d1SDavid du Colombier */ 479219b2ee8SDavid du Colombier if(*isslave){ 480219b2ee8SDavid du Colombier if(debug) 481219b2ee8SDavid du Colombier syslog(0, logfile, "slave death %d", getpid()); 4823e12c5d1SDavid du Colombier _exits(0); 4833e12c5d1SDavid du Colombier } 4843e12c5d1SDavid du Colombier } 485219b2ee8SDavid du Colombier } 486219b2ee8SDavid du Colombier 487219b2ee8SDavid du Colombier void 4889a747e4fSDavid du Colombier rversion(Job *job) 489219b2ee8SDavid du Colombier { 4909a747e4fSDavid du Colombier if(job->request.msize > IOHDRSZ + Maxfdata) 4919a747e4fSDavid du Colombier job->reply.msize = IOHDRSZ + Maxfdata; 4929a747e4fSDavid du Colombier else 4939a747e4fSDavid du Colombier job->reply.msize = job->request.msize; 4949a747e4fSDavid du Colombier if(strncmp(job->request.version, "9P2000", 6) != 0) 4959a747e4fSDavid du Colombier sendmsg(job, "unknown 9P version"); 4969a747e4fSDavid du Colombier else{ 4979a747e4fSDavid du Colombier job->reply.version = "9P2000"; 4987dd7cddfSDavid du Colombier sendmsg(job, 0); 499219b2ee8SDavid du Colombier } 5009a747e4fSDavid du Colombier } 5013e12c5d1SDavid du Colombier 5023e12c5d1SDavid du Colombier void 5039a747e4fSDavid du Colombier rauth(Job *job) 5043e12c5d1SDavid du Colombier { 5053ff48bf5SDavid du Colombier sendmsg(job, "cs: authentication not required"); 5067dd7cddfSDavid du Colombier } 5077dd7cddfSDavid du Colombier 5087dd7cddfSDavid du Colombier /* 5097dd7cddfSDavid du Colombier * don't flush till all the slaves are done 5107dd7cddfSDavid du Colombier */ 5117dd7cddfSDavid du Colombier void 5127dd7cddfSDavid du Colombier rflush(Job *job) 5137dd7cddfSDavid du Colombier { 5147dd7cddfSDavid du Colombier flushjob(job->request.oldtag); 5157dd7cddfSDavid du Colombier sendmsg(job, 0); 5163e12c5d1SDavid du Colombier } 5173e12c5d1SDavid du Colombier 5183e12c5d1SDavid du Colombier void 5197dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf) 5203e12c5d1SDavid du Colombier { 5213e12c5d1SDavid du Colombier if(mf->busy == 0){ 5223e12c5d1SDavid du Colombier mf->busy = 1; 5239a747e4fSDavid du Colombier mf->user = estrdup(job->request.uname); 5243e12c5d1SDavid du Colombier } 5253e12c5d1SDavid du Colombier mf->qid.vers = vers++; 5269a747e4fSDavid du Colombier mf->qid.type = QTDIR; 5279a747e4fSDavid du Colombier mf->qid.path = 0LL; 5287dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 5297dd7cddfSDavid du Colombier sendmsg(job, 0); 5303e12c5d1SDavid du Colombier } 5313e12c5d1SDavid du Colombier 5323e12c5d1SDavid du Colombier 5333e12c5d1SDavid du Colombier char* 5347dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf) 5353e12c5d1SDavid du Colombier { 5363e12c5d1SDavid du Colombier char *err; 5379a747e4fSDavid du Colombier char **elems; 5389a747e4fSDavid du Colombier int nelems; 5399a747e4fSDavid du Colombier int i; 5409a747e4fSDavid du Colombier Mfile *nmf; 5419a747e4fSDavid du Colombier Qid qid; 5423e12c5d1SDavid du Colombier 5433e12c5d1SDavid du Colombier err = 0; 5449a747e4fSDavid du Colombier nmf = nil; 5459a747e4fSDavid du Colombier elems = job->request.wname; 5469a747e4fSDavid du Colombier nelems = job->request.nwname; 5479a747e4fSDavid du Colombier job->reply.nwqid = 0; 5489a747e4fSDavid du Colombier 5499a747e4fSDavid du Colombier if(job->request.newfid != job->request.fid){ 5509a747e4fSDavid du Colombier /* clone fid */ 5519a747e4fSDavid du Colombier nmf = newfid(job->request.newfid); 5529a747e4fSDavid du Colombier if(nmf->busy){ 5539a747e4fSDavid du Colombier nmf = nil; 5549a747e4fSDavid du Colombier err = "clone to used channel"; 5559a747e4fSDavid du Colombier goto send; 5569a747e4fSDavid du Colombier } 5579a747e4fSDavid du Colombier *nmf = *mf; 5589a747e4fSDavid du Colombier nmf->user = estrdup(mf->user); 5599a747e4fSDavid du Colombier nmf->fid = job->request.newfid; 5609a747e4fSDavid du Colombier nmf->qid.vers = vers++; 5619a747e4fSDavid du Colombier mf = nmf; 5629a747e4fSDavid du Colombier } 5639a747e4fSDavid du Colombier /* else nmf will be nil */ 5649a747e4fSDavid du Colombier 5659a747e4fSDavid du Colombier qid = mf->qid; 5669a747e4fSDavid du Colombier if(nelems > 0){ 5679a747e4fSDavid du Colombier /* walk fid */ 5689a747e4fSDavid du Colombier for(i=0; i<nelems && i<MAXWELEM; i++){ 5699a747e4fSDavid du Colombier if((qid.type & QTDIR) == 0){ 5703e12c5d1SDavid du Colombier err = "not a directory"; 5719a747e4fSDavid du Colombier break; 5723e12c5d1SDavid du Colombier } 5739a747e4fSDavid du Colombier if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){ 5749a747e4fSDavid du Colombier qid.type = QTDIR; 5759a747e4fSDavid du Colombier qid.path = Qdir; 5769a747e4fSDavid du Colombier Found: 5779a747e4fSDavid du Colombier job->reply.wqid[i] = qid; 5789a747e4fSDavid du Colombier job->reply.nwqid++; 5799a747e4fSDavid du Colombier continue; 5803e12c5d1SDavid du Colombier } 5819a747e4fSDavid du Colombier if(strcmp(elems[i], "cs") == 0){ 5829a747e4fSDavid du Colombier qid.type = QTFILE; 5839a747e4fSDavid du Colombier qid.path = Qcs; 5849a747e4fSDavid du Colombier goto Found; 5853e12c5d1SDavid du Colombier } 5869a747e4fSDavid du Colombier err = "file does not exist"; 5879a747e4fSDavid du Colombier break; 5889a747e4fSDavid du Colombier } 5899a747e4fSDavid du Colombier } 5909a747e4fSDavid du Colombier 5913e12c5d1SDavid du Colombier send: 5929a747e4fSDavid du Colombier if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)){ 593a9f680aeSDavid du Colombier cleanmf(nmf); 594a9f680aeSDavid du Colombier free(nmf->user); 595a9f680aeSDavid du Colombier nmf->user = 0; 5969a747e4fSDavid du Colombier nmf->busy = 0; 5979a747e4fSDavid du Colombier nmf->fid = 0; 5989a747e4fSDavid du Colombier } 5999a747e4fSDavid du Colombier if(err == nil) 6009a747e4fSDavid du Colombier mf->qid = qid; 6017dd7cddfSDavid du Colombier sendmsg(job, err); 6023e12c5d1SDavid du Colombier return err; 6033e12c5d1SDavid du Colombier } 6043e12c5d1SDavid du Colombier 6053e12c5d1SDavid du Colombier void 6067dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf) 6073e12c5d1SDavid du Colombier { 6083e12c5d1SDavid du Colombier int mode; 6093e12c5d1SDavid du Colombier char *err; 6103e12c5d1SDavid du Colombier 6113e12c5d1SDavid du Colombier err = 0; 6127dd7cddfSDavid du Colombier mode = job->request.mode; 6139a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6143e12c5d1SDavid du Colombier if(mode) 6153e12c5d1SDavid du Colombier err = "permission denied"; 6169a747e4fSDavid du Colombier } 6177dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 6189a747e4fSDavid du Colombier job->reply.iounit = 0; 6197dd7cddfSDavid du Colombier sendmsg(job, err); 6203e12c5d1SDavid du Colombier } 6213e12c5d1SDavid du Colombier 6223e12c5d1SDavid du Colombier void 6237dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf) 6243e12c5d1SDavid du Colombier { 6253e12c5d1SDavid du Colombier USED(mf); 6267dd7cddfSDavid du Colombier sendmsg(job, "creation permission denied"); 6273e12c5d1SDavid du Colombier } 6283e12c5d1SDavid du Colombier 6293e12c5d1SDavid du Colombier void 6307dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf) 6313e12c5d1SDavid du Colombier { 632219b2ee8SDavid du Colombier int i, n, cnt; 633219b2ee8SDavid du Colombier long off, toff, clock; 6343e12c5d1SDavid du Colombier Dir dir; 6359a747e4fSDavid du Colombier uchar buf[Maxfdata]; 6363e12c5d1SDavid du Colombier char *err; 6373e12c5d1SDavid du Colombier 6383e12c5d1SDavid du Colombier n = 0; 6393e12c5d1SDavid du Colombier err = 0; 6407dd7cddfSDavid du Colombier off = job->request.offset; 6417dd7cddfSDavid du Colombier cnt = job->request.count; 6429a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6433e12c5d1SDavid du Colombier clock = time(0); 6443e12c5d1SDavid du Colombier if(off == 0){ 6459a747e4fSDavid du Colombier dir.name = "cs"; 6469a747e4fSDavid du Colombier dir.qid.type = QTFILE; 6473e12c5d1SDavid du Colombier dir.qid.vers = vers; 6483e12c5d1SDavid du Colombier dir.qid.path = Qcs; 6493e12c5d1SDavid du Colombier dir.mode = 0666; 6503e12c5d1SDavid du Colombier dir.length = 0; 6519a747e4fSDavid du Colombier dir.uid = mf->user; 6529a747e4fSDavid du Colombier dir.gid = mf->user; 6539a747e4fSDavid du Colombier dir.muid = mf->user; 6543e12c5d1SDavid du Colombier dir.atime = clock; /* wrong */ 6553e12c5d1SDavid du Colombier dir.mtime = clock; /* wrong */ 6569a747e4fSDavid du Colombier n = convD2M(&dir, buf, sizeof buf); 6573e12c5d1SDavid du Colombier } 6589a747e4fSDavid du Colombier job->reply.data = (char*)buf; 6593e12c5d1SDavid du Colombier } else { 66080ee5cbfSDavid du Colombier for(;;){ 66180ee5cbfSDavid du Colombier /* look for an answer at the right offset */ 662219b2ee8SDavid du Colombier toff = 0; 663219b2ee8SDavid du Colombier for(i = 0; mf->reply[i] && i < mf->nreply; i++){ 664219b2ee8SDavid du Colombier n = mf->replylen[i]; 665219b2ee8SDavid du Colombier if(off < toff + n) 666219b2ee8SDavid du Colombier break; 667219b2ee8SDavid du Colombier toff += n; 6683e12c5d1SDavid du Colombier } 66980ee5cbfSDavid du Colombier if(i < mf->nreply) 67080ee5cbfSDavid du Colombier break; /* got something to return */ 67180ee5cbfSDavid du Colombier 67280ee5cbfSDavid du Colombier /* try looking up more answers */ 67380ee5cbfSDavid du Colombier if(lookup(mf) == 0){ 67480ee5cbfSDavid du Colombier /* no more */ 675219b2ee8SDavid du Colombier n = 0; 676219b2ee8SDavid du Colombier goto send; 677219b2ee8SDavid du Colombier } 67880ee5cbfSDavid du Colombier } 67980ee5cbfSDavid du Colombier 68080ee5cbfSDavid du Colombier /* give back a single reply (or part of one) */ 6817dd7cddfSDavid du Colombier job->reply.data = mf->reply[i] + (off - toff); 682219b2ee8SDavid du Colombier if(cnt > toff - off + n) 683219b2ee8SDavid du Colombier n = toff - off + n; 684219b2ee8SDavid du Colombier else 685219b2ee8SDavid du Colombier n = cnt; 6863e12c5d1SDavid du Colombier } 6873e12c5d1SDavid du Colombier send: 6887dd7cddfSDavid du Colombier job->reply.count = n; 6897dd7cddfSDavid du Colombier sendmsg(job, err); 6907dd7cddfSDavid du Colombier } 69180ee5cbfSDavid du Colombier void 69280ee5cbfSDavid du Colombier cleanmf(Mfile *mf) 6937dd7cddfSDavid du Colombier { 6947dd7cddfSDavid du Colombier int i; 6957dd7cddfSDavid du Colombier 6969a747e4fSDavid du Colombier if(mf->net != nil){ 69780ee5cbfSDavid du Colombier free(mf->net); 69880ee5cbfSDavid du Colombier mf->net = nil; 6999a747e4fSDavid du Colombier } 7009a747e4fSDavid du Colombier if(mf->host != nil){ 70180ee5cbfSDavid du Colombier free(mf->host); 70280ee5cbfSDavid du Colombier mf->host = nil; 7039a747e4fSDavid du Colombier } 7049a747e4fSDavid du Colombier if(mf->serv != nil){ 70580ee5cbfSDavid du Colombier free(mf->serv); 70680ee5cbfSDavid du Colombier mf->serv = nil; 7079a747e4fSDavid du Colombier } 7089a747e4fSDavid du Colombier if(mf->rem != nil){ 70980ee5cbfSDavid du Colombier free(mf->rem); 71080ee5cbfSDavid du Colombier mf->rem = nil; 7119a747e4fSDavid du Colombier } 71280ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++){ 71380ee5cbfSDavid du Colombier free(mf->reply[i]); 71480ee5cbfSDavid du Colombier mf->reply[i] = nil; 71580ee5cbfSDavid du Colombier mf->replylen[i] = 0; 7167dd7cddfSDavid du Colombier } 71780ee5cbfSDavid du Colombier mf->nreply = 0; 71880ee5cbfSDavid du Colombier mf->nextnet = netlist; 7193e12c5d1SDavid du Colombier } 7203e12c5d1SDavid du Colombier 7213e12c5d1SDavid du Colombier void 7227dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf) 7233e12c5d1SDavid du Colombier { 7243e12c5d1SDavid du Colombier int cnt, n; 72580ee5cbfSDavid du Colombier char *err; 7267dd7cddfSDavid du Colombier char *field[4]; 727271b8d73SDavid du Colombier char curerr[64]; 7283e12c5d1SDavid du Colombier 7293e12c5d1SDavid du Colombier err = 0; 7307dd7cddfSDavid du Colombier cnt = job->request.count; 7319a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 7323e12c5d1SDavid du Colombier err = "can't write directory"; 7333e12c5d1SDavid du Colombier goto send; 7343e12c5d1SDavid du Colombier } 7353e12c5d1SDavid du Colombier if(cnt >= Maxrequest){ 7363e12c5d1SDavid du Colombier err = "request too long"; 7373e12c5d1SDavid du Colombier goto send; 7383e12c5d1SDavid du Colombier } 7397dd7cddfSDavid du Colombier job->request.data[cnt] = 0; 7403e12c5d1SDavid du Colombier 7413e12c5d1SDavid du Colombier /* 742219b2ee8SDavid du Colombier * toggle debugging 743219b2ee8SDavid du Colombier */ 7447dd7cddfSDavid du Colombier if(strncmp(job->request.data, "debug", 5)==0){ 745219b2ee8SDavid du Colombier debug ^= 1; 746219b2ee8SDavid du Colombier syslog(1, logfile, "debug %d", debug); 747219b2ee8SDavid du Colombier goto send; 748219b2ee8SDavid du Colombier } 749219b2ee8SDavid du Colombier 750219b2ee8SDavid du Colombier /* 7517dd7cddfSDavid du Colombier * toggle debugging 7527dd7cddfSDavid du Colombier */ 7537dd7cddfSDavid du Colombier if(strncmp(job->request.data, "paranoia", 8)==0){ 7547dd7cddfSDavid du Colombier paranoia ^= 1; 7557dd7cddfSDavid du Colombier syslog(1, logfile, "paranoia %d", paranoia); 7567dd7cddfSDavid du Colombier goto send; 7577dd7cddfSDavid du Colombier } 7587dd7cddfSDavid du Colombier 7597dd7cddfSDavid du Colombier /* 7603e12c5d1SDavid du Colombier * add networks to the default list 7613e12c5d1SDavid du Colombier */ 7627dd7cddfSDavid du Colombier if(strncmp(job->request.data, "add ", 4)==0){ 7637dd7cddfSDavid du Colombier if(job->request.data[cnt-1] == '\n') 7647dd7cddfSDavid du Colombier job->request.data[cnt-1] = 0; 7657dd7cddfSDavid du Colombier netadd(job->request.data+4); 7667dd7cddfSDavid du Colombier readipinterfaces(); 7677dd7cddfSDavid du Colombier goto send; 7687dd7cddfSDavid du Colombier } 7697dd7cddfSDavid du Colombier 7707dd7cddfSDavid du Colombier /* 7717dd7cddfSDavid du Colombier * refresh all state 7727dd7cddfSDavid du Colombier */ 7737dd7cddfSDavid du Colombier if(strncmp(job->request.data, "refresh", 7)==0){ 7747dd7cddfSDavid du Colombier netinit(1); 7753e12c5d1SDavid du Colombier goto send; 7763e12c5d1SDavid du Colombier } 7773e12c5d1SDavid du Colombier 77880ee5cbfSDavid du Colombier /* start transaction with a clean slate */ 77980ee5cbfSDavid du Colombier cleanmf(mf); 78080ee5cbfSDavid du Colombier 7813e12c5d1SDavid du Colombier /* 782219b2ee8SDavid du Colombier * look for a general query 783219b2ee8SDavid du Colombier */ 7847dd7cddfSDavid du Colombier if(*job->request.data == '!'){ 7857dd7cddfSDavid du Colombier err = genquery(mf, job->request.data+1); 786219b2ee8SDavid du Colombier goto send; 787219b2ee8SDavid du Colombier } 788219b2ee8SDavid du Colombier 7897dd7cddfSDavid du Colombier if(debug) 7907dd7cddfSDavid du Colombier syslog(0, logfile, "write %s", job->request.data); 7917dd7cddfSDavid du Colombier if(paranoia) 7927dd7cddfSDavid du Colombier syslog(0, paranoiafile, "write %s by %s", job->request.data, mf->user); 7937dd7cddfSDavid du Colombier 794219b2ee8SDavid du Colombier /* 7953e12c5d1SDavid du Colombier * break up name 7963e12c5d1SDavid du Colombier */ 7977dd7cddfSDavid du Colombier n = getfields(job->request.data, field, 4, 1, "!"); 7983e12c5d1SDavid du Colombier switch(n){ 7993e12c5d1SDavid du Colombier case 1: 80080ee5cbfSDavid du Colombier mf->net = strdup("net"); 80180ee5cbfSDavid du Colombier mf->host = strdup(field[0]); 8027dd7cddfSDavid du Colombier break; 8037dd7cddfSDavid du Colombier case 4: 80480ee5cbfSDavid du Colombier mf->rem = strdup(field[3]); 80580ee5cbfSDavid du Colombier /* fall through */ 80680ee5cbfSDavid du Colombier case 3: 80780ee5cbfSDavid du Colombier mf->serv = strdup(field[2]); 80880ee5cbfSDavid du Colombier /* fall through */ 80980ee5cbfSDavid du Colombier case 2: 81080ee5cbfSDavid du Colombier mf->host = strdup(field[1]); 81180ee5cbfSDavid du Colombier mf->net = strdup(field[0]); 8123e12c5d1SDavid du Colombier break; 8133e12c5d1SDavid du Colombier } 8143e12c5d1SDavid du Colombier 81580ee5cbfSDavid du Colombier /* 81680ee5cbfSDavid du Colombier * do the first net worth of lookup 81780ee5cbfSDavid du Colombier */ 818271b8d73SDavid du Colombier if(lookup(mf) == 0){ 819271b8d73SDavid du Colombier rerrstr(curerr, sizeof curerr); 820271b8d73SDavid du Colombier err = curerr; 821271b8d73SDavid du Colombier } 8223e12c5d1SDavid du Colombier send: 8237dd7cddfSDavid du Colombier job->reply.count = cnt; 8247dd7cddfSDavid du Colombier sendmsg(job, err); 8253e12c5d1SDavid du Colombier } 8263e12c5d1SDavid du Colombier 8273e12c5d1SDavid du Colombier void 8287dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf) 8293e12c5d1SDavid du Colombier { 83080ee5cbfSDavid du Colombier cleanmf(mf); 831a9f680aeSDavid du Colombier free(mf->user); 832a9f680aeSDavid du Colombier mf->user = 0; 8333e12c5d1SDavid du Colombier mf->busy = 0; 8343e12c5d1SDavid du Colombier mf->fid = 0; 8357dd7cddfSDavid du Colombier sendmsg(job, 0); 8363e12c5d1SDavid du Colombier } 8373e12c5d1SDavid du Colombier 8383e12c5d1SDavid du Colombier void 8397dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf) 8403e12c5d1SDavid du Colombier { 8413e12c5d1SDavid du Colombier USED(mf); 8427dd7cddfSDavid du Colombier sendmsg(job, "remove permission denied"); 8433e12c5d1SDavid du Colombier } 8443e12c5d1SDavid du Colombier 8453e12c5d1SDavid du Colombier void 8467dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf) 8473e12c5d1SDavid du Colombier { 8483e12c5d1SDavid du Colombier Dir dir; 8499a747e4fSDavid du Colombier uchar buf[IOHDRSZ+Maxfdata]; 8503e12c5d1SDavid du Colombier 8519a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 8529a747e4fSDavid du Colombier dir.name = "."; 8539a747e4fSDavid du Colombier dir.mode = DMDIR|0555; 854219b2ee8SDavid du Colombier } else { 8559a747e4fSDavid du Colombier dir.name = "cs"; 8563e12c5d1SDavid du Colombier dir.mode = 0666; 857219b2ee8SDavid du Colombier } 858219b2ee8SDavid du Colombier dir.qid = mf->qid; 8593e12c5d1SDavid du Colombier dir.length = 0; 8609a747e4fSDavid du Colombier dir.uid = mf->user; 8619a747e4fSDavid du Colombier dir.gid = mf->user; 8629a747e4fSDavid du Colombier dir.muid = mf->user; 8633e12c5d1SDavid du Colombier dir.atime = dir.mtime = time(0); 8649a747e4fSDavid du Colombier job->reply.nstat = convD2M(&dir, buf, sizeof buf); 8659a747e4fSDavid du Colombier job->reply.stat = buf; 8667dd7cddfSDavid du Colombier sendmsg(job, 0); 8673e12c5d1SDavid du Colombier } 8683e12c5d1SDavid du Colombier 8693e12c5d1SDavid du Colombier void 8707dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf) 8713e12c5d1SDavid du Colombier { 8723e12c5d1SDavid du Colombier USED(mf); 8737dd7cddfSDavid du Colombier sendmsg(job, "wstat permission denied"); 8743e12c5d1SDavid du Colombier } 8753e12c5d1SDavid du Colombier 8763e12c5d1SDavid du Colombier void 8777dd7cddfSDavid du Colombier sendmsg(Job *job, char *err) 8783e12c5d1SDavid du Colombier { 8793e12c5d1SDavid du Colombier int n; 8809a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 8819a747e4fSDavid du Colombier char ename[ERRMAX]; 8823e12c5d1SDavid du Colombier 8833e12c5d1SDavid du Colombier if(err){ 8847dd7cddfSDavid du Colombier job->reply.type = Rerror; 8859a747e4fSDavid du Colombier snprint(ename, sizeof(ename), "cs: %s", err); 8869a747e4fSDavid du Colombier job->reply.ename = ename; 8873e12c5d1SDavid du Colombier }else{ 8887dd7cddfSDavid du Colombier job->reply.type = job->request.type+1; 8893e12c5d1SDavid du Colombier } 8907dd7cddfSDavid du Colombier job->reply.tag = job->request.tag; 8919a747e4fSDavid du Colombier n = convS2M(&job->reply, mdata, sizeof mdata); 892219b2ee8SDavid du Colombier if(n == 0){ 8937dd7cddfSDavid du Colombier syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply); 894219b2ee8SDavid du Colombier abort(); 895219b2ee8SDavid du Colombier } 8967dd7cddfSDavid du Colombier lock(&joblock); 8977dd7cddfSDavid du Colombier if(job->flushed == 0) 8989a747e4fSDavid du Colombier if(write(mfd[1], mdata, n)!=n) 8993e12c5d1SDavid du Colombier error("mount write"); 9007dd7cddfSDavid du Colombier unlock(&joblock); 901219b2ee8SDavid du Colombier if(debug) 9027dd7cddfSDavid du Colombier syslog(0, logfile, "%F %d", &job->reply, n); 9033e12c5d1SDavid du Colombier } 9043e12c5d1SDavid du Colombier 9053e12c5d1SDavid du Colombier void 9063e12c5d1SDavid du Colombier error(char *s) 9073e12c5d1SDavid du Colombier { 908bd389b36SDavid du Colombier syslog(1, "cs", "%s: %r", s); 909bd389b36SDavid du Colombier _exits(0); 9103e12c5d1SDavid du Colombier } 9113e12c5d1SDavid du Colombier 9127dd7cddfSDavid du Colombier static int 9137dd7cddfSDavid du Colombier isvalidip(uchar *ip) 9147dd7cddfSDavid du Colombier { 9157dd7cddfSDavid du Colombier return ipcmp(ip, IPnoaddr) != 0 && ipcmp(ip, v4prefix) != 0; 9167dd7cddfSDavid du Colombier } 9173e12c5d1SDavid du Colombier 9180103620dSDavid du Colombier static uchar loopbacknet[IPaddrlen] = { 9190103620dSDavid du Colombier 0, 0, 0, 0, 9200103620dSDavid du Colombier 0, 0, 0, 0, 9210103620dSDavid du Colombier 0, 0, 0xff, 0xff, 9220103620dSDavid du Colombier 127, 0, 0, 0 9230103620dSDavid du Colombier }; 9240103620dSDavid du Colombier static uchar loopbackmask[IPaddrlen] = { 9250103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9260103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9270103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9280103620dSDavid du Colombier 0xff, 0, 0, 0 9290103620dSDavid du Colombier }; 9300103620dSDavid du Colombier 9317dd7cddfSDavid du Colombier void 9327dd7cddfSDavid du Colombier readipinterfaces(void) 9337dd7cddfSDavid du Colombier { 9340103620dSDavid du Colombier if(myipaddr(ipa, mntpt) != 0) 9350103620dSDavid du Colombier ipmove(ipa, IPnoaddr); 9367dd7cddfSDavid du Colombier sprint(ipaddr, "%I", ipa); 9377dd7cddfSDavid du Colombier if (debug) 9387dd7cddfSDavid du Colombier syslog(0, "dns", "ipaddr is %s\n", ipaddr); 9397dd7cddfSDavid du Colombier } 9403e12c5d1SDavid du Colombier 9413e12c5d1SDavid du Colombier /* 9427dd7cddfSDavid du Colombier * get the system name 9433e12c5d1SDavid du Colombier */ 9443e12c5d1SDavid du Colombier void 9453e12c5d1SDavid du Colombier ipid(void) 9463e12c5d1SDavid du Colombier { 9473e12c5d1SDavid du Colombier uchar addr[6]; 948a9f680aeSDavid du Colombier Ndbtuple *t, *tt; 949219b2ee8SDavid du Colombier char *p, *attr; 9503e12c5d1SDavid du Colombier Ndbs s; 9513e12c5d1SDavid du Colombier int f; 9527dd7cddfSDavid du Colombier char buf[Maxpath]; 9533e12c5d1SDavid du Colombier 954219b2ee8SDavid du Colombier /* use environment, ether addr, or ipaddr to get system name */ 95595a264b3SDavid du Colombier if(mysysname == 0){ 9567dd7cddfSDavid du Colombier /* 9577dd7cddfSDavid du Colombier * environment has priority. 9587dd7cddfSDavid du Colombier * 9597dd7cddfSDavid du Colombier * on the sgi power the default system name 9607dd7cddfSDavid du Colombier * is the ip address. ignore that. 9617dd7cddfSDavid du Colombier * 9627dd7cddfSDavid du Colombier */ 963219b2ee8SDavid du Colombier p = getenv("sysname"); 964447d6a7dSDavid du Colombier if(p && *p){ 965219b2ee8SDavid du Colombier attr = ipattr(p); 966219b2ee8SDavid du Colombier if(strcmp(attr, "ip") != 0) 96795a264b3SDavid du Colombier mysysname = strdup(p); 9683e12c5d1SDavid du Colombier } 9693e12c5d1SDavid du Colombier 9703e12c5d1SDavid du Colombier /* 9717dd7cddfSDavid du Colombier * the /net/ndb contains what the network 9727dd7cddfSDavid du Colombier * figured out from DHCP. use that name if 9737dd7cddfSDavid du Colombier * there is one. 9743e12c5d1SDavid du Colombier */ 97595a264b3SDavid du Colombier if(mysysname == 0 && netdb != nil){ 9767dd7cddfSDavid du Colombier ndbreopen(netdb); 977a9f680aeSDavid du Colombier for(tt = t = ndbparse(netdb); t != nil; t = t->entry){ 9787dd7cddfSDavid du Colombier if(strcmp(t->attr, "sys") == 0){ 97995a264b3SDavid du Colombier mysysname = strdup(t->val); 9803e12c5d1SDavid du Colombier break; 9813e12c5d1SDavid du Colombier } 9827dd7cddfSDavid du Colombier } 983a9f680aeSDavid du Colombier ndbfree(tt); 9847dd7cddfSDavid du Colombier } 9857dd7cddfSDavid du Colombier 9867dd7cddfSDavid du Colombier /* next network database, ip address, and ether address to find a name */ 98795a264b3SDavid du Colombier if(mysysname == 0){ 9887dd7cddfSDavid du Colombier t = nil; 9897dd7cddfSDavid du Colombier if(isvalidip(ipa)) 99057837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "ip", ipaddr, "sys", &t)); 99195a264b3SDavid du Colombier if(t == nil){ 9927dd7cddfSDavid du Colombier for(f = 0; f < 3; f++){ 9937dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/ether%d", mntpt, f); 9947dd7cddfSDavid du Colombier if(myetheraddr(addr, buf) >= 0){ 9957dd7cddfSDavid du Colombier snprint(eaddr, sizeof(eaddr), "%E", addr); 99657837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "ether", eaddr, "sys", &t)); 9977dd7cddfSDavid du Colombier if(t != nil) 9987dd7cddfSDavid du Colombier break; 9997dd7cddfSDavid du Colombier } 10007dd7cddfSDavid du Colombier } 10017dd7cddfSDavid du Colombier } 1002b7327ca2SDavid du Colombier for(tt = t; tt != nil; tt = tt->entry){ 1003b7327ca2SDavid du Colombier if(strcmp(tt->attr, "sys") == 0){ 1004b7327ca2SDavid du Colombier mysysname = strdup(tt->val); 100595a264b3SDavid du Colombier break; 100695a264b3SDavid du Colombier } 1007b7327ca2SDavid du Colombier } 10087dd7cddfSDavid du Colombier ndbfree(t); 10097dd7cddfSDavid du Colombier } 10107dd7cddfSDavid du Colombier 101180ee5cbfSDavid du Colombier /* nothing else worked, use the ip address */ 101295a264b3SDavid du Colombier if(mysysname == 0 && isvalidip(ipa)) 101395a264b3SDavid du Colombier mysysname = strdup(ipaddr); 101480ee5cbfSDavid du Colombier 101580ee5cbfSDavid du Colombier 1016dc5a79c1SDavid du Colombier /* set /dev/sysname if we now know it */ 101795a264b3SDavid du Colombier if(mysysname){ 10187dd7cddfSDavid du Colombier f = open("/dev/sysname", OWRITE); 10197dd7cddfSDavid du Colombier if(f >= 0){ 10207dd7cddfSDavid du Colombier write(f, mysysname, strlen(mysysname)); 10213e12c5d1SDavid du Colombier close(f); 10223e12c5d1SDavid du Colombier } 10233e12c5d1SDavid du Colombier } 10243e12c5d1SDavid du Colombier } 10253e12c5d1SDavid du Colombier } 10263e12c5d1SDavid du Colombier 10273e12c5d1SDavid du Colombier /* 10283e12c5d1SDavid du Colombier * Set up a list of default networks by looking for 10293e12c5d1SDavid du Colombier * /net/ * /clone. 10303e12c5d1SDavid du Colombier */ 10313e12c5d1SDavid du Colombier void 10327dd7cddfSDavid du Colombier netinit(int background) 10333e12c5d1SDavid du Colombier { 10347dd7cddfSDavid du Colombier char clone[Maxpath]; 10353e12c5d1SDavid du Colombier Network *np; 10367dd7cddfSDavid du Colombier static int working; 10377dd7cddfSDavid du Colombier 10387dd7cddfSDavid du Colombier if(background){ 10397dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 10407dd7cddfSDavid du Colombier case 0: 10417dd7cddfSDavid du Colombier break; 10427dd7cddfSDavid du Colombier default: 10437dd7cddfSDavid du Colombier return; 10447dd7cddfSDavid du Colombier } 10457dd7cddfSDavid du Colombier lock(&netlock); 10467dd7cddfSDavid du Colombier } 10473e12c5d1SDavid du Colombier 10483e12c5d1SDavid du Colombier /* add the mounted networks to the default list */ 10493e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 10507dd7cddfSDavid du Colombier if(np->considered) 10517dd7cddfSDavid du Colombier continue; 10527dd7cddfSDavid du Colombier snprint(clone, sizeof(clone), "%s/%s/clone", mntpt, np->net); 10539a747e4fSDavid du Colombier if(access(clone, AEXIST) < 0) 10543e12c5d1SDavid du Colombier continue; 10553e12c5d1SDavid du Colombier if(netlist) 10563e12c5d1SDavid du Colombier last->next = np; 10573e12c5d1SDavid du Colombier else 10583e12c5d1SDavid du Colombier netlist = np; 10593e12c5d1SDavid du Colombier last = np; 10603e12c5d1SDavid du Colombier np->next = 0; 10617dd7cddfSDavid du Colombier np->considered = 1; 10623e12c5d1SDavid du Colombier } 10633e12c5d1SDavid du Colombier 10647dd7cddfSDavid du Colombier /* find out what our ip address is */ 10657dd7cddfSDavid du Colombier readipinterfaces(); 10663e12c5d1SDavid du Colombier 10677dd7cddfSDavid du Colombier /* set the system name if we need to, these says ip is all we have */ 10683e12c5d1SDavid du Colombier ipid(); 10693e12c5d1SDavid du Colombier 1070219b2ee8SDavid du Colombier if(debug) 10717dd7cddfSDavid du Colombier syslog(0, logfile, "mysysname %s eaddr %s ipaddr %s ipa %I\n", 107295a264b3SDavid du Colombier mysysname?mysysname:"???", eaddr, ipaddr, ipa); 10737dd7cddfSDavid du Colombier 10747dd7cddfSDavid du Colombier if(background){ 10757dd7cddfSDavid du Colombier unlock(&netlock); 10767dd7cddfSDavid du Colombier _exits(0); 10777dd7cddfSDavid du Colombier } 10783e12c5d1SDavid du Colombier } 10793e12c5d1SDavid du Colombier 10803e12c5d1SDavid du Colombier /* 10813e12c5d1SDavid du Colombier * add networks to the standard list 10823e12c5d1SDavid du Colombier */ 10833e12c5d1SDavid du Colombier void 10843e12c5d1SDavid du Colombier netadd(char *p) 10853e12c5d1SDavid du Colombier { 10863e12c5d1SDavid du Colombier Network *np; 10873e12c5d1SDavid du Colombier char *field[12]; 10883e12c5d1SDavid du Colombier int i, n; 10893e12c5d1SDavid du Colombier 10907dd7cddfSDavid du Colombier n = getfields(p, field, 12, 1, " "); 10913e12c5d1SDavid du Colombier for(i = 0; i < n; i++){ 10923e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 10933e12c5d1SDavid du Colombier if(strcmp(field[i], np->net) != 0) 10943e12c5d1SDavid du Colombier continue; 10957dd7cddfSDavid du Colombier if(np->considered) 10963e12c5d1SDavid du Colombier break; 10973e12c5d1SDavid du Colombier if(netlist) 10983e12c5d1SDavid du Colombier last->next = np; 10993e12c5d1SDavid du Colombier else 11003e12c5d1SDavid du Colombier netlist = np; 11013e12c5d1SDavid du Colombier last = np; 11023e12c5d1SDavid du Colombier np->next = 0; 11037dd7cddfSDavid du Colombier np->considered = 1; 11043e12c5d1SDavid du Colombier } 11053e12c5d1SDavid du Colombier } 11063e12c5d1SDavid du Colombier } 11073e12c5d1SDavid du Colombier 110880ee5cbfSDavid du Colombier int 110980ee5cbfSDavid du Colombier lookforproto(Ndbtuple *t, char *proto) 111080ee5cbfSDavid du Colombier { 111180ee5cbfSDavid du Colombier for(; t != nil; t = t->entry) 111280ee5cbfSDavid du Colombier if(strcmp(t->attr, "proto") == 0 && strcmp(t->val, proto) == 0) 111380ee5cbfSDavid du Colombier return 1; 111480ee5cbfSDavid du Colombier return 0; 111580ee5cbfSDavid du Colombier } 111680ee5cbfSDavid du Colombier 1117219b2ee8SDavid du Colombier /* 11183e12c5d1SDavid du Colombier * lookup a request. the network "net" means we should pick the 11193e12c5d1SDavid du Colombier * best network to get there. 11203e12c5d1SDavid du Colombier */ 11213e12c5d1SDavid du Colombier int 112280ee5cbfSDavid du Colombier lookup(Mfile *mf) 11233e12c5d1SDavid du Colombier { 112480ee5cbfSDavid du Colombier Network *np; 1125219b2ee8SDavid du Colombier char *cp; 1126219b2ee8SDavid du Colombier Ndbtuple *nt, *t; 1127219b2ee8SDavid du Colombier char reply[Maxreply]; 112880ee5cbfSDavid du Colombier int i, rv; 112980ee5cbfSDavid du Colombier int hack; 11303e12c5d1SDavid du Colombier 11313e12c5d1SDavid du Colombier /* open up the standard db files */ 11323e12c5d1SDavid du Colombier if(db == 0) 11337dd7cddfSDavid du Colombier ndbinit(); 11343e12c5d1SDavid du Colombier if(db == 0) 113580ee5cbfSDavid du Colombier error("can't open mf->network database\n"); 11363e12c5d1SDavid du Colombier 113780ee5cbfSDavid du Colombier rv = 0; 113880ee5cbfSDavid du Colombier 113980ee5cbfSDavid du Colombier if(mf->net == nil) 114080ee5cbfSDavid du Colombier return 0; /* must have been a genquery */ 114180ee5cbfSDavid du Colombier 114280ee5cbfSDavid du Colombier if(strcmp(mf->net, "net") == 0){ 11433e12c5d1SDavid du Colombier /* 11443e12c5d1SDavid du Colombier * go through set of default nets 11453e12c5d1SDavid du Colombier */ 114680ee5cbfSDavid du Colombier for(np = mf->nextnet; np; np = np->next){ 114780ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 114880ee5cbfSDavid du Colombier if(nt == nil) 1149219b2ee8SDavid du Colombier continue; 115080ee5cbfSDavid du Colombier hack = np->fasttimeouthack && !lookforproto(nt, np->net); 115180ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 115280ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, hack); 1153219b2ee8SDavid du Colombier if(cp){ 115480ee5cbfSDavid du Colombier /* avoid duplicates */ 115580ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++) 115680ee5cbfSDavid du Colombier if(strcmp(mf->reply[i], cp) == 0) 115780ee5cbfSDavid du Colombier break; 115880ee5cbfSDavid du Colombier if(i == mf->nreply){ 115980ee5cbfSDavid du Colombier /* save the reply */ 1160219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 1161219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = cp; 116280ee5cbfSDavid du Colombier rv++; 1163219b2ee8SDavid du Colombier } 1164219b2ee8SDavid du Colombier } 1165219b2ee8SDavid du Colombier } 1166219b2ee8SDavid du Colombier ndbfree(nt); 116780ee5cbfSDavid du Colombier np = np->next; 116880ee5cbfSDavid du Colombier break; 116980ee5cbfSDavid du Colombier } 117080ee5cbfSDavid du Colombier mf->nextnet = np; 117180ee5cbfSDavid du Colombier return rv; 117280ee5cbfSDavid du Colombier } 117380ee5cbfSDavid du Colombier 117480ee5cbfSDavid du Colombier /* 117580ee5cbfSDavid du Colombier * if not /net, we only get one lookup 117680ee5cbfSDavid du Colombier */ 117780ee5cbfSDavid du Colombier if(mf->nreply != 0) 1178219b2ee8SDavid du Colombier return 0; 117980ee5cbfSDavid du Colombier /* 118080ee5cbfSDavid du Colombier * look for a specific network 118180ee5cbfSDavid du Colombier */ 118295a264b3SDavid du Colombier for(np = netlist; np && np->net != nil; np++){ 118380ee5cbfSDavid du Colombier if(np->fasttimeouthack) 118480ee5cbfSDavid du Colombier continue; 118580ee5cbfSDavid du Colombier if(strcmp(np->net, mf->net) == 0) 118680ee5cbfSDavid du Colombier break; 118780ee5cbfSDavid du Colombier } 118880ee5cbfSDavid du Colombier 118995a264b3SDavid du Colombier if(np && np->net != nil){ 119080ee5cbfSDavid du Colombier /* 119180ee5cbfSDavid du Colombier * known network 119280ee5cbfSDavid du Colombier */ 119380ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 119480ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 119580ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, 0); 119680ee5cbfSDavid du Colombier if(cp){ 119780ee5cbfSDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 119880ee5cbfSDavid du Colombier mf->reply[mf->nreply++] = cp; 119980ee5cbfSDavid du Colombier rv++; 120080ee5cbfSDavid du Colombier } 120180ee5cbfSDavid du Colombier } 120280ee5cbfSDavid du Colombier ndbfree(nt); 120380ee5cbfSDavid du Colombier return rv; 12043e12c5d1SDavid du Colombier } else { 12053e12c5d1SDavid du Colombier /* 1206219b2ee8SDavid du Colombier * not a known network, don't translate host or service 12073e12c5d1SDavid du Colombier */ 120880ee5cbfSDavid du Colombier if(mf->serv) 12097dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s", 121080ee5cbfSDavid du Colombier mntpt, mf->net, mf->host, mf->serv); 1211bd389b36SDavid du Colombier else 12127dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s", 121380ee5cbfSDavid du Colombier mntpt, mf->net, mf->host); 1214219b2ee8SDavid du Colombier mf->reply[0] = strdup(reply); 1215219b2ee8SDavid du Colombier mf->replylen[0] = strlen(reply); 1216219b2ee8SDavid du Colombier mf->nreply = 1; 121780ee5cbfSDavid du Colombier return 1; 12183e12c5d1SDavid du Colombier } 12193e12c5d1SDavid du Colombier } 12203e12c5d1SDavid du Colombier 12213e12c5d1SDavid du Colombier /* 12223e12c5d1SDavid du Colombier * translate an ip service name into a port number. If it's a numeric port 12233e12c5d1SDavid du Colombier * number, look for restricted access. 12243e12c5d1SDavid du Colombier * 12253e12c5d1SDavid du Colombier * the service '*' needs no translation. 12263e12c5d1SDavid du Colombier */ 12273e12c5d1SDavid du Colombier char* 122895a264b3SDavid du Colombier ipserv(Network *np, char *name, char *buf, int blen) 12293e12c5d1SDavid du Colombier { 12303e12c5d1SDavid du Colombier char *p; 12313e12c5d1SDavid du Colombier int alpha = 0; 12323e12c5d1SDavid du Colombier int restr = 0; 123395a264b3SDavid du Colombier char port[10]; 12343e12c5d1SDavid du Colombier Ndbtuple *t, *nt; 12353e12c5d1SDavid du Colombier Ndbs s; 12363e12c5d1SDavid du Colombier 12373e12c5d1SDavid du Colombier /* '*' means any service */ 12383e12c5d1SDavid du Colombier if(strcmp(name, "*")==0){ 12393e12c5d1SDavid du Colombier strcpy(buf, name); 12403e12c5d1SDavid du Colombier return buf; 12413e12c5d1SDavid du Colombier } 12423e12c5d1SDavid du Colombier 12433e12c5d1SDavid du Colombier /* see if it's numeric or symbolic */ 12443e12c5d1SDavid du Colombier port[0] = 0; 12453e12c5d1SDavid du Colombier for(p = name; *p; p++){ 12463e12c5d1SDavid du Colombier if(isdigit(*p)) 12479a747e4fSDavid du Colombier {} 12483e12c5d1SDavid du Colombier else if(isalpha(*p) || *p == '-' || *p == '$') 12493e12c5d1SDavid du Colombier alpha = 1; 12503e12c5d1SDavid du Colombier else 12513e12c5d1SDavid du Colombier return 0; 12523e12c5d1SDavid du Colombier } 125357837e0bSDavid du Colombier t = nil; 125457837e0bSDavid du Colombier p = nil; 12553e12c5d1SDavid du Colombier if(alpha){ 125657837e0bSDavid du Colombier p = ndbgetvalue(db, &s, np->net, name, "port", &t); 1257b7327ca2SDavid du Colombier if(p == nil) 1258b7327ca2SDavid du Colombier return 0; 12593e12c5d1SDavid du Colombier } else { 12603cc1eb97SDavid du Colombier /* look up only for tcp ports < 1024 to get the restricted 12613cc1eb97SDavid du Colombier * attribute 12623cc1eb97SDavid du Colombier */ 12633cc1eb97SDavid du Colombier if(atoi(name) < 1024 && strcmp(np->net, "tcp") == 0) 126457837e0bSDavid du Colombier p = ndbgetvalue(db, &s, "port", name, "port", &t); 126557837e0bSDavid du Colombier if(p == nil) 126657837e0bSDavid du Colombier p = strdup(name); 12673e12c5d1SDavid du Colombier } 12683e12c5d1SDavid du Colombier 12693e12c5d1SDavid du Colombier if(t){ 12703e12c5d1SDavid du Colombier for(nt = t; nt; nt = nt->entry) 12713e12c5d1SDavid du Colombier if(strcmp(nt->attr, "restricted") == 0) 12723e12c5d1SDavid du Colombier restr = 1; 12733e12c5d1SDavid du Colombier ndbfree(t); 12743e12c5d1SDavid du Colombier } 127557837e0bSDavid du Colombier snprint(buf, blen, "%s%s", p, restr ? "!r" : ""); 127657837e0bSDavid du Colombier free(p); 127757837e0bSDavid du Colombier 12783e12c5d1SDavid du Colombier return buf; 12793e12c5d1SDavid du Colombier } 12803e12c5d1SDavid du Colombier 12813e12c5d1SDavid du Colombier /* 12827dd7cddfSDavid du Colombier * lookup an ip attribute 12833e12c5d1SDavid du Colombier */ 12847dd7cddfSDavid du Colombier int 128595a264b3SDavid du Colombier ipattrlookup(Ndb *db, char *ipa, char *attr, char *val, int vlen) 12863e12c5d1SDavid du Colombier { 12873e12c5d1SDavid du Colombier 12887dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 12897dd7cddfSDavid du Colombier char *alist[2]; 12903e12c5d1SDavid du Colombier 12917dd7cddfSDavid du Colombier alist[0] = attr; 12927dd7cddfSDavid du Colombier t = ndbipinfo(db, "ip", ipa, alist, 1); 12937dd7cddfSDavid du Colombier if(t == nil) 12947dd7cddfSDavid du Colombier return 0; 12959a747e4fSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 12967dd7cddfSDavid du Colombier if(strcmp(nt->attr, attr) == 0){ 129795a264b3SDavid du Colombier nstrcpy(val, nt->val, vlen); 12983e12c5d1SDavid du Colombier ndbfree(t); 12997dd7cddfSDavid du Colombier return 1; 1300219b2ee8SDavid du Colombier } 13019a747e4fSDavid du Colombier } 13023e12c5d1SDavid du Colombier 13037dd7cddfSDavid du Colombier /* we shouldn't get here */ 13043e12c5d1SDavid du Colombier ndbfree(t); 13057dd7cddfSDavid du Colombier return 0; 13063e12c5d1SDavid du Colombier } 13073e12c5d1SDavid du Colombier 13083e12c5d1SDavid du Colombier /* 13093e12c5d1SDavid du Colombier * lookup (and translate) an ip destination 13103e12c5d1SDavid du Colombier */ 1311219b2ee8SDavid du Colombier Ndbtuple* 1312219b2ee8SDavid du Colombier iplookup(Network *np, char *host, char *serv, int nolookup) 13133e12c5d1SDavid du Colombier { 13149dfc0cb2SDavid du Colombier char *attr, *dnsname; 13157dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13163e12c5d1SDavid du Colombier Ndbs s; 131795a264b3SDavid du Colombier char ts[Maxservice]; 131895a264b3SDavid du Colombier char dollar[Maxhost]; 13197dd7cddfSDavid du Colombier uchar ip[IPaddrlen]; 13207dd7cddfSDavid du Colombier uchar net[IPaddrlen]; 13217dd7cddfSDavid du Colombier uchar tnet[IPaddrlen]; 13227dd7cddfSDavid du Colombier Ipifc *ifc; 13239a747e4fSDavid du Colombier Iplifc *lifc; 13243e12c5d1SDavid du Colombier 1325219b2ee8SDavid du Colombier USED(nolookup); 1326219b2ee8SDavid du Colombier 13273e12c5d1SDavid du Colombier /* 13283e12c5d1SDavid du Colombier * start with the service since it's the most likely to fail 13293e12c5d1SDavid du Colombier * and costs the least 13303e12c5d1SDavid du Colombier */ 13317dd7cddfSDavid du Colombier werrstr("can't translate address"); 133295a264b3SDavid du Colombier if(serv==0 || ipserv(np, serv, ts, sizeof ts) == 0){ 1333271b8d73SDavid du Colombier werrstr("can't translate service"); 1334219b2ee8SDavid du Colombier return 0; 13357dd7cddfSDavid du Colombier } 13363e12c5d1SDavid du Colombier 13373e12c5d1SDavid du Colombier /* for dial strings with no host */ 1338219b2ee8SDavid du Colombier if(strcmp(host, "*") == 0) 133995a264b3SDavid du Colombier return ndbnew("ip", "*"); 13403e12c5d1SDavid du Colombier 13413e12c5d1SDavid du Colombier /* 13427dd7cddfSDavid du Colombier * hack till we go v6 :: = 0.0.0.0 13437dd7cddfSDavid du Colombier */ 13447dd7cddfSDavid du Colombier if(strcmp("::", host) == 0) 134595a264b3SDavid du Colombier return ndbnew("ip", "*"); 13467dd7cddfSDavid du Colombier 13477dd7cddfSDavid du Colombier /* 13483e12c5d1SDavid du Colombier * '$' means the rest of the name is an attribute that we 13493e12c5d1SDavid du Colombier * need to search for 13503e12c5d1SDavid du Colombier */ 13513e12c5d1SDavid du Colombier if(*host == '$'){ 135295a264b3SDavid du Colombier if(ipattrlookup(db, ipaddr, host+1, dollar, sizeof dollar)) 13533e12c5d1SDavid du Colombier host = dollar; 13543e12c5d1SDavid du Colombier } 13553e12c5d1SDavid du Colombier 13563e12c5d1SDavid du Colombier /* 13577dd7cddfSDavid du Colombier * turn '[ip address]' into just 'ip address' 13587dd7cddfSDavid du Colombier */ 13597dd7cddfSDavid du Colombier if(*host == '[' && host[strlen(host)-1] == ']'){ 13607dd7cddfSDavid du Colombier host++; 13617dd7cddfSDavid du Colombier host[strlen(host)-1] = 0; 13627dd7cddfSDavid du Colombier } 13637dd7cddfSDavid du Colombier 13647dd7cddfSDavid du Colombier /* 13653e12c5d1SDavid du Colombier * just accept addresses 13663e12c5d1SDavid du Colombier */ 1367219b2ee8SDavid du Colombier attr = ipattr(host); 1368219b2ee8SDavid du Colombier if(strcmp(attr, "ip") == 0) 136995a264b3SDavid du Colombier return ndbnew("ip", host); 13703e12c5d1SDavid du Colombier 13713e12c5d1SDavid du Colombier /* 13723e12c5d1SDavid du Colombier * give the domain name server the first opportunity to 1373bd389b36SDavid du Colombier * resolve domain names. if that fails try the database. 13743e12c5d1SDavid du Colombier */ 13753e12c5d1SDavid du Colombier t = 0; 1376271b8d73SDavid du Colombier werrstr("can't translate address"); 13773e12c5d1SDavid du Colombier if(strcmp(attr, "dom") == 0) 13787dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 13793e12c5d1SDavid du Colombier if(t == 0) 138057837e0bSDavid du Colombier free(ndbgetvalue(db, &s, attr, host, "ip", &t)); 13819dfc0cb2SDavid du Colombier if(t == 0){ 13829dfc0cb2SDavid du Colombier dnsname = ndbgetvalue(db, &s, attr, host, "dom", nil); 13839dfc0cb2SDavid du Colombier if(dnsname){ 13849dfc0cb2SDavid du Colombier t = dnsiplookup(dnsname, &s); 13859dfc0cb2SDavid du Colombier free(dnsname); 13869dfc0cb2SDavid du Colombier } 13879dfc0cb2SDavid du Colombier } 13883e12c5d1SDavid du Colombier if(t == 0) 13897dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 13907dd7cddfSDavid du Colombier if(t == 0) 1391219b2ee8SDavid du Colombier return 0; 1392bd389b36SDavid du Colombier 1393bd389b36SDavid du Colombier /* 1394bd389b36SDavid du Colombier * reorder the tuple to have the matched line first and 1395bd389b36SDavid du Colombier * save that in the request structure. 1396bd389b36SDavid du Colombier */ 13977dd7cddfSDavid du Colombier t = reorder(t, s.t); 13987dd7cddfSDavid du Colombier 13997dd7cddfSDavid du Colombier /* 14007dd7cddfSDavid du Colombier * reorder according to our interfaces 14017dd7cddfSDavid du Colombier */ 14027dd7cddfSDavid du Colombier lock(&ipifclock); 14039a747e4fSDavid du Colombier for(ifc = ipifcs; ifc != nil; ifc = ifc->next){ 14049a747e4fSDavid du Colombier for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ 14059a747e4fSDavid du Colombier maskip(lifc->ip, lifc->mask, net); 14067dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry){ 14077dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0) 14087dd7cddfSDavid du Colombier continue; 14097dd7cddfSDavid du Colombier parseip(ip, nt->val); 14109a747e4fSDavid du Colombier maskip(ip, lifc->mask, tnet); 14117dd7cddfSDavid du Colombier if(memcmp(net, tnet, IPaddrlen) == 0){ 14127dd7cddfSDavid du Colombier t = reorder(t, nt); 14137dd7cddfSDavid du Colombier unlock(&ipifclock); 14147dd7cddfSDavid du Colombier return t; 14157dd7cddfSDavid du Colombier } 14167dd7cddfSDavid du Colombier } 14177dd7cddfSDavid du Colombier } 14189a747e4fSDavid du Colombier } 14197dd7cddfSDavid du Colombier unlock(&ipifclock); 14207dd7cddfSDavid du Colombier 14217dd7cddfSDavid du Colombier return t; 14223e12c5d1SDavid du Colombier } 14233e12c5d1SDavid du Colombier 14243e12c5d1SDavid du Colombier /* 14253e12c5d1SDavid du Colombier * translate an ip address 14263e12c5d1SDavid du Colombier */ 1427219b2ee8SDavid du Colombier char* 142880ee5cbfSDavid du Colombier iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack) 14293e12c5d1SDavid du Colombier { 143095a264b3SDavid du Colombier char ts[Maxservice]; 1431219b2ee8SDavid du Colombier char reply[Maxreply]; 143295a264b3SDavid du Colombier char x[Maxservice]; 14333e12c5d1SDavid du Colombier 1434219b2ee8SDavid du Colombier if(strcmp(t->attr, "ip") != 0) 14353e12c5d1SDavid du Colombier return 0; 1436219b2ee8SDavid du Colombier 143795a264b3SDavid du Colombier if(serv == 0 || ipserv(np, serv, ts, sizeof ts) == 0){ 1438271b8d73SDavid du Colombier werrstr("can't translate service"); 1439219b2ee8SDavid du Colombier return 0; 1440271b8d73SDavid du Colombier } 14417dd7cddfSDavid du Colombier if(rem != nil) 14427dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 14437dd7cddfSDavid du Colombier else 14447dd7cddfSDavid du Colombier *x = 0; 144580ee5cbfSDavid du Colombier 1446219b2ee8SDavid du Colombier if(*t->val == '*') 14477dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", 14487dd7cddfSDavid du Colombier mntpt, np->net, ts, x); 1449219b2ee8SDavid du Colombier else 145080ee5cbfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s%s", 145180ee5cbfSDavid du Colombier mntpt, np->net, t->val, ts, x, hack? "!fasttimeout": ""); 1452219b2ee8SDavid du Colombier 1453219b2ee8SDavid du Colombier return strdup(reply); 14543e12c5d1SDavid du Colombier } 14553e12c5d1SDavid du Colombier 1456219b2ee8SDavid du Colombier /* 1457219b2ee8SDavid du Colombier * lookup a telephone number 1458219b2ee8SDavid du Colombier */ 1459219b2ee8SDavid du Colombier Ndbtuple* 1460219b2ee8SDavid du Colombier telcolookup(Network *np, char *host, char *serv, int nolookup) 1461219b2ee8SDavid du Colombier { 1462219b2ee8SDavid du Colombier Ndbtuple *t; 1463219b2ee8SDavid du Colombier Ndbs s; 1464219b2ee8SDavid du Colombier 1465219b2ee8SDavid du Colombier USED(np, nolookup, serv); 1466219b2ee8SDavid du Colombier 1467271b8d73SDavid du Colombier werrstr("can't translate address"); 146857837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "sys", host, "telco", &t)); 1469219b2ee8SDavid du Colombier if(t == 0) 147095a264b3SDavid du Colombier return ndbnew("telco", host); 1471219b2ee8SDavid du Colombier 1472219b2ee8SDavid du Colombier return reorder(t, s.t); 1473219b2ee8SDavid du Colombier } 1474219b2ee8SDavid du Colombier 1475219b2ee8SDavid du Colombier /* 1476219b2ee8SDavid du Colombier * translate a telephone address 1477219b2ee8SDavid du Colombier */ 1478219b2ee8SDavid du Colombier char* 147980ee5cbfSDavid du Colombier telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int) 1480219b2ee8SDavid du Colombier { 1481219b2ee8SDavid du Colombier char reply[Maxreply]; 148295a264b3SDavid du Colombier char x[Maxservice]; 1483219b2ee8SDavid du Colombier 1484219b2ee8SDavid du Colombier if(strcmp(t->attr, "telco") != 0) 1485219b2ee8SDavid du Colombier return 0; 1486219b2ee8SDavid du Colombier 14877dd7cddfSDavid du Colombier if(rem != nil) 14887dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 1489219b2ee8SDavid du Colombier else 14907dd7cddfSDavid du Colombier *x = 0; 14917dd7cddfSDavid du Colombier if(serv) 14927dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s", mntpt, np->net, 14937dd7cddfSDavid du Colombier t->val, serv, x); 14947dd7cddfSDavid du Colombier else 14957dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net, 14967dd7cddfSDavid du Colombier t->val, x); 1497219b2ee8SDavid du Colombier return strdup(reply); 1498219b2ee8SDavid du Colombier } 14993e12c5d1SDavid du Colombier 15003e12c5d1SDavid du Colombier /* 15013e12c5d1SDavid du Colombier * reorder the tuple to put x's line first in the entry 15023e12c5d1SDavid du Colombier */ 15033e12c5d1SDavid du Colombier Ndbtuple* 15043e12c5d1SDavid du Colombier reorder(Ndbtuple *t, Ndbtuple *x) 15053e12c5d1SDavid du Colombier { 15063e12c5d1SDavid du Colombier Ndbtuple *nt; 15073e12c5d1SDavid du Colombier Ndbtuple *line; 15083e12c5d1SDavid du Colombier 1509219b2ee8SDavid du Colombier /* find start of this entry's line */ 1510219b2ee8SDavid du Colombier for(line = x; line->entry == line->line; line = line->line) 15113e12c5d1SDavid du Colombier ; 1512219b2ee8SDavid du Colombier line = line->line; 1513219b2ee8SDavid du Colombier if(line == t) 1514219b2ee8SDavid du Colombier return t; /* already the first line */ 15153e12c5d1SDavid du Colombier 1516219b2ee8SDavid du Colombier /* remove this line and everything after it from the entry */ 1517219b2ee8SDavid du Colombier for(nt = t; nt->entry != line; nt = nt->entry) 1518219b2ee8SDavid du Colombier ; 1519219b2ee8SDavid du Colombier nt->entry = 0; 15203e12c5d1SDavid du Colombier 1521219b2ee8SDavid du Colombier /* make that the start of the entry */ 1522219b2ee8SDavid du Colombier for(nt = line; nt->entry; nt = nt->entry) 1523219b2ee8SDavid du Colombier ; 15243e12c5d1SDavid du Colombier nt->entry = t; 15253e12c5d1SDavid du Colombier return line; 15263e12c5d1SDavid du Colombier } 15273e12c5d1SDavid du Colombier 15283e12c5d1SDavid du Colombier /* 15293e12c5d1SDavid du Colombier * create a slave process to handle a request to avoid one request blocking 15307dd7cddfSDavid du Colombier * another. parent returns to job loop. 15313e12c5d1SDavid du Colombier */ 15323e12c5d1SDavid du Colombier void 15333e12c5d1SDavid du Colombier slave(void) 15343e12c5d1SDavid du Colombier { 15353e12c5d1SDavid du Colombier if(*isslave) 15363e12c5d1SDavid du Colombier return; /* we're already a slave process */ 15373e12c5d1SDavid du Colombier 15383e12c5d1SDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 15393e12c5d1SDavid du Colombier case -1: 15403e12c5d1SDavid du Colombier break; 15413e12c5d1SDavid du Colombier case 0: 1542219b2ee8SDavid du Colombier if(debug) 1543219b2ee8SDavid du Colombier syslog(0, logfile, "slave %d", getpid()); 15443e12c5d1SDavid du Colombier *isslave = 1; 15453e12c5d1SDavid du Colombier break; 15463e12c5d1SDavid du Colombier default: 15473e12c5d1SDavid du Colombier longjmp(masterjmp, 1); 15483e12c5d1SDavid du Colombier } 15493e12c5d1SDavid du Colombier 1550219b2ee8SDavid du Colombier } 1551219b2ee8SDavid du Colombier 15523e12c5d1SDavid du Colombier /* 15533e12c5d1SDavid du Colombier * call the dns process and have it try to translate a name 15543e12c5d1SDavid du Colombier */ 15553e12c5d1SDavid du Colombier Ndbtuple* 15567dd7cddfSDavid du Colombier dnsiplookup(char *host, Ndbs *s) 15573e12c5d1SDavid du Colombier { 155895a264b3SDavid du Colombier char buf[Maxreply]; 15597dd7cddfSDavid du Colombier Ndbtuple *t; 15603e12c5d1SDavid du Colombier 1561bd389b36SDavid du Colombier unlock(&dblock); 1562bd389b36SDavid du Colombier 15633e12c5d1SDavid du Colombier /* save the name before starting a slave */ 15647dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s", host); 15653e12c5d1SDavid du Colombier 15663e12c5d1SDavid du Colombier slave(); 15673e12c5d1SDavid du Colombier 15687dd7cddfSDavid du Colombier if(strcmp(ipattr(buf), "ip") == 0) 15697dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ptr"); 15707dd7cddfSDavid du Colombier else 15717dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ip"); 15723e12c5d1SDavid du Colombier s->t = t; 15737dd7cddfSDavid du Colombier 1574271b8d73SDavid du Colombier if(t == nil){ 1575271b8d73SDavid du Colombier rerrstr(buf, sizeof buf); 1576271b8d73SDavid du Colombier if(strstr(buf, "exist")) 1577271b8d73SDavid du Colombier werrstr("can't translate address: %s", buf); 1578271b8d73SDavid du Colombier else if(strstr(buf, "dns failure")) 1579271b8d73SDavid du Colombier werrstr("temporary problem: %s", buf); 1580271b8d73SDavid du Colombier } 1581271b8d73SDavid du Colombier 1582bd389b36SDavid du Colombier lock(&dblock); 15833e12c5d1SDavid du Colombier return t; 15843e12c5d1SDavid du Colombier } 1585219b2ee8SDavid du Colombier 1586219b2ee8SDavid du Colombier int 1587219b2ee8SDavid du Colombier qmatch(Ndbtuple *t, char **attr, char **val, int n) 1588219b2ee8SDavid du Colombier { 1589219b2ee8SDavid du Colombier int i, found; 1590219b2ee8SDavid du Colombier Ndbtuple *nt; 1591219b2ee8SDavid du Colombier 1592219b2ee8SDavid du Colombier for(i = 1; i < n; i++){ 1593219b2ee8SDavid du Colombier found = 0; 1594219b2ee8SDavid du Colombier for(nt = t; nt; nt = nt->entry) 1595219b2ee8SDavid du Colombier if(strcmp(attr[i], nt->attr) == 0) 1596219b2ee8SDavid du Colombier if(strcmp(val[i], "*") == 0 1597219b2ee8SDavid du Colombier || strcmp(val[i], nt->val) == 0){ 1598219b2ee8SDavid du Colombier found = 1; 1599219b2ee8SDavid du Colombier break; 1600219b2ee8SDavid du Colombier } 1601219b2ee8SDavid du Colombier if(found == 0) 1602219b2ee8SDavid du Colombier break; 1603219b2ee8SDavid du Colombier } 1604219b2ee8SDavid du Colombier return i == n; 1605219b2ee8SDavid du Colombier } 1606219b2ee8SDavid du Colombier 1607219b2ee8SDavid du Colombier void 1608219b2ee8SDavid du Colombier qreply(Mfile *mf, Ndbtuple *t) 1609219b2ee8SDavid du Colombier { 1610219b2ee8SDavid du Colombier Ndbtuple *nt; 161195a264b3SDavid du Colombier String *s; 1612219b2ee8SDavid du Colombier 161395a264b3SDavid du Colombier s = s_new(); 1614219b2ee8SDavid du Colombier for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){ 161595a264b3SDavid du Colombier s_append(s, nt->attr); 161695a264b3SDavid du Colombier s_append(s, "="); 161795a264b3SDavid du Colombier s_append(s, nt->val); 161895a264b3SDavid du Colombier 161995a264b3SDavid du Colombier if(nt->line != nt->entry){ 162095a264b3SDavid du Colombier mf->replylen[mf->nreply] = s_len(s); 162195a264b3SDavid du Colombier mf->reply[mf->nreply++] = strdup(s_to_c(s)); 162295a264b3SDavid du Colombier s_restart(s); 1623219b2ee8SDavid du Colombier } else 162495a264b3SDavid du Colombier s_append(s, " "); 1625219b2ee8SDavid du Colombier } 162695a264b3SDavid du Colombier s_free(s); 1627219b2ee8SDavid du Colombier } 1628219b2ee8SDavid du Colombier 16297dd7cddfSDavid du Colombier enum 16307dd7cddfSDavid du Colombier { 16317dd7cddfSDavid du Colombier Maxattr= 32, 16327dd7cddfSDavid du Colombier }; 16337dd7cddfSDavid du Colombier 1634219b2ee8SDavid du Colombier /* 16357dd7cddfSDavid du Colombier * generic query lookup. The query is of one of the following 16367dd7cddfSDavid du Colombier * forms: 16377dd7cddfSDavid du Colombier * 16387dd7cddfSDavid du Colombier * attr1=val1 attr2=val2 attr3=val3 ... 16397dd7cddfSDavid du Colombier * 16407dd7cddfSDavid du Colombier * returns the matching tuple 16417dd7cddfSDavid du Colombier * 16427dd7cddfSDavid du Colombier * ipinfo attr=val attr1 attr2 attr3 ... 16437dd7cddfSDavid du Colombier * 16447dd7cddfSDavid du Colombier * is like ipinfo and returns the attr{1-n} 16457dd7cddfSDavid du Colombier * associated with the ip address. 1646219b2ee8SDavid du Colombier */ 1647219b2ee8SDavid du Colombier char* 1648219b2ee8SDavid du Colombier genquery(Mfile *mf, char *query) 1649219b2ee8SDavid du Colombier { 1650219b2ee8SDavid du Colombier int i, n; 1651219b2ee8SDavid du Colombier char *p; 16527dd7cddfSDavid du Colombier char *attr[Maxattr]; 16537dd7cddfSDavid du Colombier char *val[Maxattr]; 1654219b2ee8SDavid du Colombier Ndbtuple *t; 1655219b2ee8SDavid du Colombier Ndbs s; 1656219b2ee8SDavid du Colombier 16577dd7cddfSDavid du Colombier n = getfields(query, attr, 32, 1, " "); 1658219b2ee8SDavid du Colombier if(n == 0) 1659219b2ee8SDavid du Colombier return "bad query"; 1660219b2ee8SDavid du Colombier 16617dd7cddfSDavid du Colombier if(strcmp(attr[0], "ipinfo") == 0) 16627dd7cddfSDavid du Colombier return ipinfoquery(mf, attr, n); 16637dd7cddfSDavid du Colombier 1664219b2ee8SDavid du Colombier /* parse pairs */ 1665219b2ee8SDavid du Colombier for(i = 0; i < n; i++){ 1666219b2ee8SDavid du Colombier p = strchr(attr[i], '='); 1667219b2ee8SDavid du Colombier if(p == 0) 1668219b2ee8SDavid du Colombier return "bad query"; 1669219b2ee8SDavid du Colombier *p++ = 0; 1670219b2ee8SDavid du Colombier val[i] = p; 1671219b2ee8SDavid du Colombier } 1672219b2ee8SDavid du Colombier 1673219b2ee8SDavid du Colombier /* give dns a chance */ 1674219b2ee8SDavid du Colombier if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){ 16757dd7cddfSDavid du Colombier t = dnsiplookup(val[0], &s); 1676219b2ee8SDavid du Colombier if(t){ 1677219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1678219b2ee8SDavid du Colombier qreply(mf, t); 1679219b2ee8SDavid du Colombier ndbfree(t); 1680219b2ee8SDavid du Colombier return 0; 1681219b2ee8SDavid du Colombier } 1682219b2ee8SDavid du Colombier ndbfree(t); 1683219b2ee8SDavid du Colombier } 1684219b2ee8SDavid du Colombier } 1685219b2ee8SDavid du Colombier 1686219b2ee8SDavid du Colombier /* first pair is always the key. It can't be a '*' */ 1687219b2ee8SDavid du Colombier t = ndbsearch(db, &s, attr[0], val[0]); 1688219b2ee8SDavid du Colombier 1689219b2ee8SDavid du Colombier /* search is the and of all the pairs */ 1690219b2ee8SDavid du Colombier while(t){ 1691219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1692219b2ee8SDavid du Colombier qreply(mf, t); 1693219b2ee8SDavid du Colombier ndbfree(t); 1694219b2ee8SDavid du Colombier return 0; 1695219b2ee8SDavid du Colombier } 1696219b2ee8SDavid du Colombier 1697219b2ee8SDavid du Colombier ndbfree(t); 1698219b2ee8SDavid du Colombier t = ndbsnext(&s, attr[0], val[0]); 1699219b2ee8SDavid du Colombier } 1700219b2ee8SDavid du Colombier 1701219b2ee8SDavid du Colombier return "no match"; 1702219b2ee8SDavid du Colombier } 17037dd7cddfSDavid du Colombier 17047dd7cddfSDavid du Colombier /* 17057dd7cddfSDavid du Colombier * resolve an ip address 17067dd7cddfSDavid du Colombier */ 17077dd7cddfSDavid du Colombier static Ndbtuple* 17087dd7cddfSDavid du Colombier ipresolve(char *attr, char *host) 17097dd7cddfSDavid du Colombier { 17107dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17117dd7cddfSDavid du Colombier 17127dd7cddfSDavid du Colombier t = iplookup(&network[Ntcp], host, "*", 0); 17137dd7cddfSDavid du Colombier for(l = &t; *l != nil; ){ 17147dd7cddfSDavid du Colombier nt = *l; 17157dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0){ 17167dd7cddfSDavid du Colombier *l = nt->entry; 17177dd7cddfSDavid du Colombier nt->entry = nil; 17187dd7cddfSDavid du Colombier ndbfree(nt); 17197dd7cddfSDavid du Colombier continue; 17207dd7cddfSDavid du Colombier } 17217dd7cddfSDavid du Colombier strcpy(nt->attr, attr); 17227dd7cddfSDavid du Colombier l = &nt->entry; 17237dd7cddfSDavid du Colombier } 17247dd7cddfSDavid du Colombier return t; 17257dd7cddfSDavid du Colombier } 17267dd7cddfSDavid du Colombier 17277dd7cddfSDavid du Colombier char* 17287dd7cddfSDavid du Colombier ipinfoquery(Mfile *mf, char **list, int n) 17297dd7cddfSDavid du Colombier { 17307dd7cddfSDavid du Colombier int i, nresolve; 17317dd7cddfSDavid du Colombier int resolve[Maxattr]; 17327dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17337dd7cddfSDavid du Colombier char *attr, *val; 17347dd7cddfSDavid du Colombier 17357dd7cddfSDavid du Colombier /* skip 'ipinfo' */ 17367dd7cddfSDavid du Colombier list++; n--; 17377dd7cddfSDavid du Colombier 17388a2c5ad0SDavid du Colombier if(n < 1) 17397dd7cddfSDavid du Colombier return "bad query"; 17407dd7cddfSDavid du Colombier 17418a2c5ad0SDavid du Colombier /* get search attribute=value, or assume ip=myipaddr */ 17428a2c5ad0SDavid du Colombier attr = *list; 17438a2c5ad0SDavid du Colombier if((val = strchr(attr, '=')) != nil){ 17447dd7cddfSDavid du Colombier *val++ = 0; 17458a2c5ad0SDavid du Colombier list++; 17468a2c5ad0SDavid du Colombier n--; 17478a2c5ad0SDavid du Colombier }else{ 17488a2c5ad0SDavid du Colombier attr = "ip"; 17498a2c5ad0SDavid du Colombier val = ipaddr; 17508a2c5ad0SDavid du Colombier } 17518a2c5ad0SDavid du Colombier 17528a2c5ad0SDavid du Colombier if(n < 1) 17538a2c5ad0SDavid du Colombier return "bad query"; 17547dd7cddfSDavid du Colombier 17557dd7cddfSDavid du Colombier /* 17567dd7cddfSDavid du Colombier * don't let ndbipinfo resolve the addresses, we're 17577dd7cddfSDavid du Colombier * better at it. 17587dd7cddfSDavid du Colombier */ 17597dd7cddfSDavid du Colombier nresolve = 0; 17607dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 1761107aedb4SDavid du Colombier if(*list[i] == '@'){ /* @attr=val ? */ 17627dd7cddfSDavid du Colombier list[i]++; 1763107aedb4SDavid du Colombier resolve[i] = 1; /* we'll resolve it */ 17647dd7cddfSDavid du Colombier nresolve++; 17657dd7cddfSDavid du Colombier } else 17667dd7cddfSDavid du Colombier resolve[i] = 0; 17677dd7cddfSDavid du Colombier 17687dd7cddfSDavid du Colombier t = ndbipinfo(db, attr, val, list, n); 17697dd7cddfSDavid du Colombier if(t == nil) 17707dd7cddfSDavid du Colombier return "no match"; 17717dd7cddfSDavid du Colombier 17727dd7cddfSDavid du Colombier if(nresolve != 0){ 17737dd7cddfSDavid du Colombier for(l = &t; *l != nil;){ 17747dd7cddfSDavid du Colombier nt = *l; 17757dd7cddfSDavid du Colombier 17767dd7cddfSDavid du Colombier /* already an address? */ 17777dd7cddfSDavid du Colombier if(strcmp(ipattr(nt->val), "ip") == 0){ 17787dd7cddfSDavid du Colombier l = &(*l)->entry; 17797dd7cddfSDavid du Colombier continue; 17807dd7cddfSDavid du Colombier } 17817dd7cddfSDavid du Colombier 17827dd7cddfSDavid du Colombier /* user wants it resolved? */ 17837dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 17847dd7cddfSDavid du Colombier if(strcmp(list[i], nt->attr) == 0) 17857dd7cddfSDavid du Colombier break; 17867dd7cddfSDavid du Colombier if(i >= n || resolve[i] == 0){ 17877dd7cddfSDavid du Colombier l = &(*l)->entry; 17887dd7cddfSDavid du Colombier continue; 17897dd7cddfSDavid du Colombier } 17907dd7cddfSDavid du Colombier 17917dd7cddfSDavid du Colombier /* resolve address and replace entry */ 17927dd7cddfSDavid du Colombier *l = ipresolve(nt->attr, nt->val); 17937dd7cddfSDavid du Colombier while(*l != nil) 17947dd7cddfSDavid du Colombier l = &(*l)->entry; 17957dd7cddfSDavid du Colombier *l = nt->entry; 17967dd7cddfSDavid du Colombier 17977dd7cddfSDavid du Colombier nt->entry = nil; 17987dd7cddfSDavid du Colombier ndbfree(nt); 17997dd7cddfSDavid du Colombier } 18007dd7cddfSDavid du Colombier } 18017dd7cddfSDavid du Colombier 18027dd7cddfSDavid du Colombier /* make it all one line */ 18037dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 18047dd7cddfSDavid du Colombier if(nt->entry == nil) 18057dd7cddfSDavid du Colombier nt->line = t; 18067dd7cddfSDavid du Colombier else 18077dd7cddfSDavid du Colombier nt->line = nt->entry; 18087dd7cddfSDavid du Colombier } 18097dd7cddfSDavid du Colombier 18107dd7cddfSDavid du Colombier qreply(mf, t); 18117dd7cddfSDavid du Colombier 18127dd7cddfSDavid du Colombier return nil; 18137dd7cddfSDavid du Colombier } 18147dd7cddfSDavid du Colombier 18157dd7cddfSDavid du Colombier void* 18167dd7cddfSDavid du Colombier emalloc(int size) 18177dd7cddfSDavid du Colombier { 18187dd7cddfSDavid du Colombier void *x; 18197dd7cddfSDavid du Colombier 18207dd7cddfSDavid du Colombier x = malloc(size); 18217dd7cddfSDavid du Colombier if(x == nil) 18227dd7cddfSDavid du Colombier abort(); 18237dd7cddfSDavid du Colombier memset(x, 0, size); 18247dd7cddfSDavid du Colombier return x; 18257dd7cddfSDavid du Colombier } 18269a747e4fSDavid du Colombier 18279a747e4fSDavid du Colombier char* 18289a747e4fSDavid du Colombier estrdup(char *s) 18299a747e4fSDavid du Colombier { 18309a747e4fSDavid du Colombier int size; 18319a747e4fSDavid du Colombier char *p; 18329a747e4fSDavid du Colombier 18339a747e4fSDavid du Colombier size = strlen(s)+1; 18349a747e4fSDavid du Colombier p = malloc(size); 18359a747e4fSDavid du Colombier if(p == nil) 18369a747e4fSDavid du Colombier abort(); 18379a747e4fSDavid du Colombier memmove(p, s, size); 18389a747e4fSDavid du Colombier return p; 18399a747e4fSDavid du Colombier } 1840