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 657dd7cddfSDavid du Colombier // 667dd7cddfSDavid du Colombier // active requests 677dd7cddfSDavid 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 { 15380ee5cbfSDavid du Colombier Nilfast, 15480ee5cbfSDavid du Colombier Ntcp, 15580ee5cbfSDavid du Colombier Nil, 15680ee5cbfSDavid du Colombier Nudp, 15780ee5cbfSDavid du Colombier Nicmp, 15895a264b3SDavid du Colombier Nicmpv6, 15980ee5cbfSDavid du Colombier Nrudp, 16080ee5cbfSDavid du Colombier Ntelco, 16180ee5cbfSDavid du Colombier }; 16280ee5cbfSDavid du Colombier 16380ee5cbfSDavid du Colombier /* 16495a264b3SDavid du Colombier > * net doesn't apply to (r)udp, icmp(v6), or telco (for speed) 16580ee5cbfSDavid du Colombier */ 16680ee5cbfSDavid du Colombier Network network[] = { 16780ee5cbfSDavid du Colombier [Nilfast] { "il", iplookup, iptrans, 0, 1 }, 16880ee5cbfSDavid du Colombier [Ntcp] { "tcp", iplookup, iptrans, 0, 0 }, 16980ee5cbfSDavid du Colombier [Nil] { "il", iplookup, iptrans, 0, 0 }, 17080ee5cbfSDavid du Colombier [Nudp] { "udp", iplookup, iptrans, 1, 0 }, 17180ee5cbfSDavid du Colombier [Nicmp] { "icmp", iplookup, iptrans, 1, 0 }, 17295a264b3SDavid du Colombier [Nicmpv6] { "icmpv6", iplookup, iptrans, 1, 0 }, 17380ee5cbfSDavid du Colombier [Nrudp] { "rudp", iplookup, iptrans, 1, 0 }, 17480ee5cbfSDavid du Colombier [Ntelco] { "telco", telcolookup, telcotrans, 1, 0 }, 17580ee5cbfSDavid du Colombier { 0 }, 17680ee5cbfSDavid du Colombier }; 17780ee5cbfSDavid du Colombier 17880ee5cbfSDavid du Colombier Lock ipifclock; 17980ee5cbfSDavid du Colombier Ipifc *ipifcs; 18080ee5cbfSDavid du Colombier 18195a264b3SDavid du Colombier char eaddr[16]; /* ascii ethernet address */ 18295a264b3SDavid du Colombier char ipaddr[64]; /* ascii internet address */ 18380ee5cbfSDavid du Colombier uchar ipa[IPaddrlen]; /* binary internet address */ 18495a264b3SDavid du Colombier char *mysysname; 18580ee5cbfSDavid du Colombier 18680ee5cbfSDavid du Colombier Network *netlist; /* networks ordered by preference */ 18780ee5cbfSDavid du Colombier Network *last; 18880ee5cbfSDavid du Colombier 18995a264b3SDavid du Colombier static void 19095a264b3SDavid du Colombier nstrcpy(char *to, char *from, int len) 19195a264b3SDavid du Colombier { 19295a264b3SDavid du Colombier strncpy(to, from, len); 19395a264b3SDavid du Colombier to[len-1] = 0; 19495a264b3SDavid du Colombier } 19595a264b3SDavid du Colombier 19695a264b3SDavid du Colombier 1977dd7cddfSDavid du Colombier void 1987dd7cddfSDavid du Colombier usage(void) 1997dd7cddfSDavid du Colombier { 2007dd7cddfSDavid du Colombier fprint(2, "usage: %s [-d] [-f ndb-file] [-x netmtpt] [-n]\n", argv0); 2017dd7cddfSDavid du Colombier exits("usage"); 2027dd7cddfSDavid du Colombier } 203219b2ee8SDavid du Colombier 2043e12c5d1SDavid du Colombier void 2053e12c5d1SDavid du Colombier main(int argc, char *argv[]) 2063e12c5d1SDavid du Colombier { 2077dd7cddfSDavid du Colombier char servefile[Maxpath]; 208219b2ee8SDavid du Colombier int justsetname; 2097dd7cddfSDavid du Colombier char *p; 2107dd7cddfSDavid du Colombier char ext[Maxpath]; 2113e12c5d1SDavid du Colombier 212219b2ee8SDavid du Colombier justsetname = 0; 2137dd7cddfSDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), nil); 2147dd7cddfSDavid du Colombier ext[0] = 0; 2153e12c5d1SDavid du Colombier ARGBEGIN{ 2163e12c5d1SDavid du Colombier case 'd': 2173e12c5d1SDavid du Colombier debug = 1; 2183e12c5d1SDavid du Colombier break; 219bd389b36SDavid du Colombier case 'f': 2207dd7cddfSDavid du Colombier p = ARGF(); 2217dd7cddfSDavid du Colombier if(p == nil) 2227dd7cddfSDavid du Colombier usage(); 2237dd7cddfSDavid du Colombier dbfile = p; 2247dd7cddfSDavid du Colombier break; 2257dd7cddfSDavid du Colombier case 'x': 2267dd7cddfSDavid du Colombier p = ARGF(); 2277dd7cddfSDavid du Colombier if(p == nil) 2287dd7cddfSDavid du Colombier usage(); 2297dd7cddfSDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), p); 2307dd7cddfSDavid du Colombier setext(ext, sizeof(ext), mntpt); 231bd389b36SDavid du Colombier break; 232219b2ee8SDavid du Colombier case 'n': 233219b2ee8SDavid du Colombier justsetname = 1; 234219b2ee8SDavid du Colombier break; 2353e12c5d1SDavid du Colombier }ARGEND 2363e12c5d1SDavid du Colombier USED(argc); 2373e12c5d1SDavid du Colombier USED(argv); 2383e12c5d1SDavid du Colombier 2397dd7cddfSDavid du Colombier rfork(RFREND|RFNOTEG); 2407dd7cddfSDavid du Colombier 2417dd7cddfSDavid du Colombier snprint(servefile, sizeof(servefile), "#s/cs%s", ext); 2427dd7cddfSDavid du Colombier snprint(netndb, sizeof(netndb), "%s/ndb", mntpt); 2437dd7cddfSDavid du Colombier unmount(servefile, mntpt); 2447dd7cddfSDavid du Colombier remove(servefile); 2457dd7cddfSDavid du Colombier 2469a747e4fSDavid du Colombier fmtinstall('E', eipfmt); 2479a747e4fSDavid du Colombier fmtinstall('I', eipfmt); 2489a747e4fSDavid du Colombier fmtinstall('M', eipfmt); 2499a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 2507dd7cddfSDavid du Colombier 2517dd7cddfSDavid du Colombier ndbinit(); 2527dd7cddfSDavid du Colombier netinit(0); 2537dd7cddfSDavid du Colombier 2547dd7cddfSDavid du Colombier if(!justsetname){ 2557dd7cddfSDavid du Colombier mountinit(servefile, mntpt); 2567dd7cddfSDavid du Colombier io(); 2577dd7cddfSDavid du Colombier } 258219b2ee8SDavid du Colombier exits(0); 259219b2ee8SDavid du Colombier } 260219b2ee8SDavid du Colombier 2617dd7cddfSDavid du Colombier /* 2627dd7cddfSDavid du Colombier * if a mount point is specified, set the cs extention to be the mount point 2637dd7cddfSDavid du Colombier * with '_'s replacing '/'s 2647dd7cddfSDavid du Colombier */ 2657dd7cddfSDavid du Colombier void 2667dd7cddfSDavid du Colombier setext(char *ext, int n, char *p) 2677dd7cddfSDavid du Colombier { 2687dd7cddfSDavid du Colombier int i, c; 2693e12c5d1SDavid du Colombier 2707dd7cddfSDavid du Colombier n--; 2717dd7cddfSDavid du Colombier for(i = 0; i < n; i++){ 2727dd7cddfSDavid du Colombier c = p[i]; 2737dd7cddfSDavid du Colombier if(c == 0) 2747dd7cddfSDavid du Colombier break; 2757dd7cddfSDavid du Colombier if(c == '/') 2767dd7cddfSDavid du Colombier c = '_'; 2777dd7cddfSDavid du Colombier ext[i] = c; 2787dd7cddfSDavid du Colombier } 2797dd7cddfSDavid du Colombier ext[i] = 0; 2803e12c5d1SDavid du Colombier } 2813e12c5d1SDavid du Colombier 2823e12c5d1SDavid du Colombier void 2837dd7cddfSDavid du Colombier mountinit(char *service, char *mntpt) 2843e12c5d1SDavid du Colombier { 2853e12c5d1SDavid du Colombier int f; 2863e12c5d1SDavid du Colombier int p[2]; 2873e12c5d1SDavid du Colombier char buf[32]; 2883e12c5d1SDavid du Colombier 2893e12c5d1SDavid du Colombier if(pipe(p) < 0) 2903e12c5d1SDavid du Colombier error("pipe failed"); 291a9f680aeSDavid du Colombier 292a9f680aeSDavid du Colombier /* 293a9f680aeSDavid du Colombier * make a /srv/cs 294a9f680aeSDavid du Colombier */ 295a9f680aeSDavid du Colombier f = create(service, OWRITE|ORCLOSE, 0666); 296a9f680aeSDavid du Colombier if(f < 0) 297a9f680aeSDavid du Colombier error(service); 298a9f680aeSDavid du Colombier snprint(buf, sizeof(buf), "%d", p[1]); 299a9f680aeSDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf)) 300a9f680aeSDavid du Colombier error("write /srv/cs"); 301a9f680aeSDavid du Colombier 302219b2ee8SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG)){ 3033e12c5d1SDavid du Colombier case 0: 304219b2ee8SDavid du Colombier close(p[1]); 3053e12c5d1SDavid du Colombier break; 3063e12c5d1SDavid du Colombier case -1: 3073e12c5d1SDavid du Colombier error("fork failed\n"); 3083e12c5d1SDavid du Colombier default: 3093e12c5d1SDavid du Colombier /* 3103e12c5d1SDavid du Colombier * put ourselves into the file system 3113e12c5d1SDavid du Colombier */ 312219b2ee8SDavid du Colombier close(p[0]); 3139a747e4fSDavid du Colombier if(mount(p[1], -1, mntpt, MAFTER, "") < 0) 3143e12c5d1SDavid du Colombier error("mount failed\n"); 315219b2ee8SDavid du Colombier _exits(0); 3163e12c5d1SDavid du Colombier } 3173e12c5d1SDavid du Colombier mfd[0] = mfd[1] = p[0]; 3183e12c5d1SDavid du Colombier } 3193e12c5d1SDavid du Colombier 3207dd7cddfSDavid du Colombier void 3217dd7cddfSDavid du Colombier ndbinit(void) 3227dd7cddfSDavid du Colombier { 3237dd7cddfSDavid du Colombier db = ndbopen(dbfile); 3247dd7cddfSDavid du Colombier if(db == nil) 3257dd7cddfSDavid du Colombier error("can't open network database"); 3267dd7cddfSDavid du Colombier 3277dd7cddfSDavid du Colombier netdb = ndbopen(netndb); 3287dd7cddfSDavid du Colombier if(netdb != nil){ 3297dd7cddfSDavid du Colombier netdb->nohash = 1; 3307dd7cddfSDavid du Colombier db = ndbcat(netdb, db); 3317dd7cddfSDavid du Colombier } 3327dd7cddfSDavid du Colombier } 3337dd7cddfSDavid du Colombier 3343e12c5d1SDavid du Colombier Mfile* 3353e12c5d1SDavid du Colombier newfid(int fid) 3363e12c5d1SDavid du Colombier { 337219b2ee8SDavid du Colombier Mlist *f, *ff; 3383e12c5d1SDavid du Colombier Mfile *mf; 3393e12c5d1SDavid du Colombier 340219b2ee8SDavid du Colombier ff = 0; 341219b2ee8SDavid du Colombier for(f = mlist; f; f = f->next) 342219b2ee8SDavid du Colombier if(f->mf.busy && f->mf.fid == fid) 343219b2ee8SDavid du Colombier return &f->mf; 344219b2ee8SDavid du Colombier else if(!ff && !f->mf.busy) 345219b2ee8SDavid du Colombier ff = f; 346219b2ee8SDavid du Colombier if(ff == 0){ 3477dd7cddfSDavid du Colombier ff = emalloc(sizeof *f); 348219b2ee8SDavid du Colombier ff->next = mlist; 349219b2ee8SDavid du Colombier mlist = ff; 3503e12c5d1SDavid du Colombier } 351219b2ee8SDavid du Colombier mf = &ff->mf; 352219b2ee8SDavid du Colombier memset(mf, 0, sizeof *mf); 3533e12c5d1SDavid du Colombier mf->fid = fid; 3543e12c5d1SDavid du Colombier return mf; 3553e12c5d1SDavid du Colombier } 3563e12c5d1SDavid du Colombier 3577dd7cddfSDavid du Colombier Job* 3587dd7cddfSDavid du Colombier newjob(void) 3597dd7cddfSDavid du Colombier { 3607dd7cddfSDavid du Colombier Job *job; 3617dd7cddfSDavid du Colombier 3627dd7cddfSDavid du Colombier job = mallocz(sizeof(Job), 1); 3637dd7cddfSDavid du Colombier lock(&joblock); 3647dd7cddfSDavid du Colombier job->next = joblist; 3657dd7cddfSDavid du Colombier joblist = job; 3667dd7cddfSDavid du Colombier job->request.tag = -1; 3677dd7cddfSDavid du Colombier unlock(&joblock); 3687dd7cddfSDavid du Colombier return job; 3697dd7cddfSDavid du Colombier } 3707dd7cddfSDavid du Colombier 3717dd7cddfSDavid du Colombier void 3727dd7cddfSDavid du Colombier freejob(Job *job) 3737dd7cddfSDavid du Colombier { 3747dd7cddfSDavid du Colombier Job **l; 3757dd7cddfSDavid du Colombier 3767dd7cddfSDavid du Colombier lock(&joblock); 3777dd7cddfSDavid du Colombier for(l = &joblist; *l; l = &(*l)->next){ 3787dd7cddfSDavid du Colombier if((*l) == job){ 3797dd7cddfSDavid du Colombier *l = job->next; 3807dd7cddfSDavid du Colombier free(job); 3817dd7cddfSDavid du Colombier break; 3827dd7cddfSDavid du Colombier } 3837dd7cddfSDavid du Colombier } 3847dd7cddfSDavid du Colombier unlock(&joblock); 3857dd7cddfSDavid du Colombier } 3867dd7cddfSDavid du Colombier 3877dd7cddfSDavid du Colombier void 3887dd7cddfSDavid du Colombier flushjob(int tag) 3897dd7cddfSDavid du Colombier { 3907dd7cddfSDavid du Colombier Job *job; 3917dd7cddfSDavid du Colombier 3927dd7cddfSDavid du Colombier lock(&joblock); 3937dd7cddfSDavid du Colombier for(job = joblist; job; job = job->next){ 3947dd7cddfSDavid du Colombier if(job->request.tag == tag && job->request.type != Tflush){ 3957dd7cddfSDavid du Colombier job->flushed = 1; 3967dd7cddfSDavid du Colombier break; 3977dd7cddfSDavid du Colombier } 3987dd7cddfSDavid du Colombier } 3997dd7cddfSDavid du Colombier unlock(&joblock); 4007dd7cddfSDavid du Colombier } 4017dd7cddfSDavid du Colombier 4023e12c5d1SDavid du Colombier void 4033e12c5d1SDavid du Colombier io(void) 4043e12c5d1SDavid du Colombier { 4053e12c5d1SDavid du Colombier long n; 4063e12c5d1SDavid du Colombier Mfile *mf; 4073e12c5d1SDavid du Colombier int slaveflag; 4089a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 4097dd7cddfSDavid du Colombier Job *job; 4103e12c5d1SDavid du Colombier 4113e12c5d1SDavid du Colombier /* 4123e12c5d1SDavid du Colombier * if we ask dns to fulfill requests, 4133e12c5d1SDavid du Colombier * a slave process is created to wait for replies. The 4149a747e4fSDavid du Colombier * master process returns immediately via a longjmp 4153e12c5d1SDavid du Colombier * through 'masterjmp'. 4163e12c5d1SDavid du Colombier * 4173e12c5d1SDavid du Colombier * *isslave is a pointer into the call stack to a variable 4183e12c5d1SDavid du Colombier * that tells whether or not the current process is a slave. 4193e12c5d1SDavid du Colombier */ 4203e12c5d1SDavid du Colombier slaveflag = 0; /* init slave variable */ 4213e12c5d1SDavid du Colombier isslave = &slaveflag; 4223e12c5d1SDavid du Colombier setjmp(masterjmp); 4233e12c5d1SDavid du Colombier 4243e12c5d1SDavid du Colombier for(;;){ 4259a747e4fSDavid du Colombier n = read9pmsg(mfd[0], mdata, sizeof mdata); 4263e12c5d1SDavid du Colombier if(n<=0) 4273e12c5d1SDavid du Colombier error("mount read"); 4287dd7cddfSDavid du Colombier job = newjob(); 4299a747e4fSDavid du Colombier if(convM2S(mdata, n, &job->request) != n){ 430271b8d73SDavid du Colombier syslog(1, logfile, "format error %ux %ux %ux %ux %ux", 431271b8d73SDavid du Colombier mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]); 4327dd7cddfSDavid du Colombier freejob(job); 4333e12c5d1SDavid du Colombier continue; 4343e12c5d1SDavid du Colombier } 4357dd7cddfSDavid du Colombier if(job->request.fid<0) 4363e12c5d1SDavid du Colombier error("fid out of range"); 437bd389b36SDavid du Colombier lock(&dblock); 4387dd7cddfSDavid du Colombier mf = newfid(job->request.fid); 439219b2ee8SDavid du Colombier if(debug) 4407dd7cddfSDavid du Colombier syslog(0, logfile, "%F", &job->request); 4413e12c5d1SDavid du Colombier 4423e12c5d1SDavid du Colombier 4437dd7cddfSDavid du Colombier switch(job->request.type){ 4443e12c5d1SDavid du Colombier default: 4457dd7cddfSDavid du Colombier syslog(1, logfile, "unknown request type %d", job->request.type); 4463e12c5d1SDavid du Colombier break; 4479a747e4fSDavid du Colombier case Tversion: 4489a747e4fSDavid du Colombier rversion(job); 4493e12c5d1SDavid du Colombier break; 4509a747e4fSDavid du Colombier case Tauth: 4519a747e4fSDavid du Colombier rauth(job); 4523e12c5d1SDavid du Colombier break; 4533e12c5d1SDavid du Colombier case Tflush: 4547dd7cddfSDavid du Colombier rflush(job); 4553e12c5d1SDavid du Colombier break; 4563e12c5d1SDavid du Colombier case Tattach: 4577dd7cddfSDavid du Colombier rattach(job, mf); 4583e12c5d1SDavid du Colombier break; 4593e12c5d1SDavid du Colombier case Twalk: 4607dd7cddfSDavid du Colombier rwalk(job, mf); 4613e12c5d1SDavid du Colombier break; 4623e12c5d1SDavid du Colombier case Topen: 4637dd7cddfSDavid du Colombier ropen(job, mf); 4643e12c5d1SDavid du Colombier break; 4653e12c5d1SDavid du Colombier case Tcreate: 4667dd7cddfSDavid du Colombier rcreate(job, mf); 4673e12c5d1SDavid du Colombier break; 4683e12c5d1SDavid du Colombier case Tread: 4697dd7cddfSDavid du Colombier rread(job, mf); 4703e12c5d1SDavid du Colombier break; 4713e12c5d1SDavid du Colombier case Twrite: 4727dd7cddfSDavid du Colombier rwrite(job, mf); 4733e12c5d1SDavid du Colombier break; 4743e12c5d1SDavid du Colombier case Tclunk: 4757dd7cddfSDavid du Colombier rclunk(job, mf); 4763e12c5d1SDavid du Colombier break; 4773e12c5d1SDavid du Colombier case Tremove: 4787dd7cddfSDavid du Colombier rremove(job, mf); 4793e12c5d1SDavid du Colombier break; 4803e12c5d1SDavid du Colombier case Tstat: 4817dd7cddfSDavid du Colombier rstat(job, mf); 4823e12c5d1SDavid du Colombier break; 4833e12c5d1SDavid du Colombier case Twstat: 4847dd7cddfSDavid du Colombier rwstat(job, mf); 4853e12c5d1SDavid du Colombier break; 4863e12c5d1SDavid du Colombier } 487bd389b36SDavid du Colombier unlock(&dblock); 4887dd7cddfSDavid du Colombier 4897dd7cddfSDavid du Colombier freejob(job); 4907dd7cddfSDavid du Colombier 4913e12c5d1SDavid du Colombier /* 4923e12c5d1SDavid du Colombier * slave processes die after replying 4933e12c5d1SDavid du Colombier */ 494219b2ee8SDavid du Colombier if(*isslave){ 495219b2ee8SDavid du Colombier if(debug) 496219b2ee8SDavid du Colombier syslog(0, logfile, "slave death %d", getpid()); 4973e12c5d1SDavid du Colombier _exits(0); 4983e12c5d1SDavid du Colombier } 4993e12c5d1SDavid du Colombier } 500219b2ee8SDavid du Colombier } 501219b2ee8SDavid du Colombier 502219b2ee8SDavid du Colombier void 5039a747e4fSDavid du Colombier rversion(Job *job) 504219b2ee8SDavid du Colombier { 5059a747e4fSDavid du Colombier if(job->request.msize > IOHDRSZ + Maxfdata) 5069a747e4fSDavid du Colombier job->reply.msize = IOHDRSZ + Maxfdata; 5079a747e4fSDavid du Colombier else 5089a747e4fSDavid du Colombier job->reply.msize = job->request.msize; 5099a747e4fSDavid du Colombier if(strncmp(job->request.version, "9P2000", 6) != 0) 5109a747e4fSDavid du Colombier sendmsg(job, "unknown 9P version"); 5119a747e4fSDavid du Colombier else{ 5129a747e4fSDavid du Colombier job->reply.version = "9P2000"; 5137dd7cddfSDavid du Colombier sendmsg(job, 0); 514219b2ee8SDavid du Colombier } 5159a747e4fSDavid du Colombier } 5163e12c5d1SDavid du Colombier 5173e12c5d1SDavid du Colombier void 5189a747e4fSDavid du Colombier rauth(Job *job) 5193e12c5d1SDavid du Colombier { 5203ff48bf5SDavid du Colombier sendmsg(job, "cs: authentication not required"); 5217dd7cddfSDavid du Colombier } 5227dd7cddfSDavid du Colombier 5237dd7cddfSDavid du Colombier /* 5247dd7cddfSDavid du Colombier * don't flush till all the slaves are done 5257dd7cddfSDavid du Colombier */ 5267dd7cddfSDavid du Colombier void 5277dd7cddfSDavid du Colombier rflush(Job *job) 5287dd7cddfSDavid du Colombier { 5297dd7cddfSDavid du Colombier flushjob(job->request.oldtag); 5307dd7cddfSDavid du Colombier sendmsg(job, 0); 5313e12c5d1SDavid du Colombier } 5323e12c5d1SDavid du Colombier 5333e12c5d1SDavid du Colombier void 5347dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf) 5353e12c5d1SDavid du Colombier { 5363e12c5d1SDavid du Colombier if(mf->busy == 0){ 5373e12c5d1SDavid du Colombier mf->busy = 1; 5389a747e4fSDavid du Colombier mf->user = estrdup(job->request.uname); 5393e12c5d1SDavid du Colombier } 5403e12c5d1SDavid du Colombier mf->qid.vers = vers++; 5419a747e4fSDavid du Colombier mf->qid.type = QTDIR; 5429a747e4fSDavid du Colombier mf->qid.path = 0LL; 5437dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 5447dd7cddfSDavid du Colombier sendmsg(job, 0); 5453e12c5d1SDavid du Colombier } 5463e12c5d1SDavid du Colombier 5473e12c5d1SDavid du Colombier 5483e12c5d1SDavid du Colombier char* 5497dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf) 5503e12c5d1SDavid du Colombier { 5513e12c5d1SDavid du Colombier char *err; 5529a747e4fSDavid du Colombier char **elems; 5539a747e4fSDavid du Colombier int nelems; 5549a747e4fSDavid du Colombier int i; 5559a747e4fSDavid du Colombier Mfile *nmf; 5569a747e4fSDavid du Colombier Qid qid; 5573e12c5d1SDavid du Colombier 5583e12c5d1SDavid du Colombier err = 0; 5599a747e4fSDavid du Colombier nmf = nil; 5609a747e4fSDavid du Colombier elems = job->request.wname; 5619a747e4fSDavid du Colombier nelems = job->request.nwname; 5629a747e4fSDavid du Colombier job->reply.nwqid = 0; 5639a747e4fSDavid du Colombier 5649a747e4fSDavid du Colombier if(job->request.newfid != job->request.fid){ 5659a747e4fSDavid du Colombier /* clone fid */ 5669a747e4fSDavid du Colombier if(job->request.newfid<0){ 5679a747e4fSDavid du Colombier err = "clone newfid out of range"; 5689a747e4fSDavid du Colombier goto send; 5699a747e4fSDavid du Colombier } 5709a747e4fSDavid du Colombier nmf = newfid(job->request.newfid); 5719a747e4fSDavid du Colombier if(nmf->busy){ 5729a747e4fSDavid du Colombier nmf = nil; 5739a747e4fSDavid du Colombier err = "clone to used channel"; 5749a747e4fSDavid du Colombier goto send; 5759a747e4fSDavid du Colombier } 5769a747e4fSDavid du Colombier *nmf = *mf; 5779a747e4fSDavid du Colombier nmf->user = estrdup(mf->user); 5789a747e4fSDavid du Colombier nmf->fid = job->request.newfid; 5799a747e4fSDavid du Colombier nmf->qid.vers = vers++; 5809a747e4fSDavid du Colombier mf = nmf; 5819a747e4fSDavid du Colombier } 5829a747e4fSDavid du Colombier /* else nmf will be nil */ 5839a747e4fSDavid du Colombier 5849a747e4fSDavid du Colombier qid = mf->qid; 5859a747e4fSDavid du Colombier if(nelems > 0){ 5869a747e4fSDavid du Colombier /* walk fid */ 5879a747e4fSDavid du Colombier for(i=0; i<nelems && i<MAXWELEM; i++){ 5889a747e4fSDavid du Colombier if((qid.type & QTDIR) == 0){ 5893e12c5d1SDavid du Colombier err = "not a directory"; 5909a747e4fSDavid du Colombier break; 5913e12c5d1SDavid du Colombier } 5929a747e4fSDavid du Colombier if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){ 5939a747e4fSDavid du Colombier qid.type = QTDIR; 5949a747e4fSDavid du Colombier qid.path = Qdir; 5959a747e4fSDavid du Colombier Found: 5969a747e4fSDavid du Colombier job->reply.wqid[i] = qid; 5979a747e4fSDavid du Colombier job->reply.nwqid++; 5989a747e4fSDavid du Colombier continue; 5993e12c5d1SDavid du Colombier } 6009a747e4fSDavid du Colombier if(strcmp(elems[i], "cs") == 0){ 6019a747e4fSDavid du Colombier qid.type = QTFILE; 6029a747e4fSDavid du Colombier qid.path = Qcs; 6039a747e4fSDavid du Colombier goto Found; 6043e12c5d1SDavid du Colombier } 6059a747e4fSDavid du Colombier err = "file does not exist"; 6069a747e4fSDavid du Colombier break; 6079a747e4fSDavid du Colombier } 6089a747e4fSDavid du Colombier } 6099a747e4fSDavid du Colombier 6103e12c5d1SDavid du Colombier send: 6119a747e4fSDavid du Colombier if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)){ 612a9f680aeSDavid du Colombier cleanmf(nmf); 613a9f680aeSDavid du Colombier free(nmf->user); 614a9f680aeSDavid du Colombier nmf->user = 0; 6159a747e4fSDavid du Colombier nmf->busy = 0; 6169a747e4fSDavid du Colombier nmf->fid = 0; 6179a747e4fSDavid du Colombier } 6189a747e4fSDavid du Colombier if(err == nil) 6199a747e4fSDavid du Colombier mf->qid = qid; 6207dd7cddfSDavid du Colombier sendmsg(job, err); 6213e12c5d1SDavid du Colombier return err; 6223e12c5d1SDavid du Colombier } 6233e12c5d1SDavid du Colombier 6243e12c5d1SDavid du Colombier void 6257dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf) 6263e12c5d1SDavid du Colombier { 6273e12c5d1SDavid du Colombier int mode; 6283e12c5d1SDavid du Colombier char *err; 6293e12c5d1SDavid du Colombier 6303e12c5d1SDavid du Colombier err = 0; 6317dd7cddfSDavid du Colombier mode = job->request.mode; 6329a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6333e12c5d1SDavid du Colombier if(mode) 6343e12c5d1SDavid du Colombier err = "permission denied"; 6359a747e4fSDavid du Colombier } 6367dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 6379a747e4fSDavid du Colombier job->reply.iounit = 0; 6387dd7cddfSDavid du Colombier sendmsg(job, err); 6393e12c5d1SDavid du Colombier } 6403e12c5d1SDavid du Colombier 6413e12c5d1SDavid du Colombier void 6427dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf) 6433e12c5d1SDavid du Colombier { 6443e12c5d1SDavid du Colombier USED(mf); 6457dd7cddfSDavid du Colombier sendmsg(job, "creation permission denied"); 6463e12c5d1SDavid du Colombier } 6473e12c5d1SDavid du Colombier 6483e12c5d1SDavid du Colombier void 6497dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf) 6503e12c5d1SDavid du Colombier { 651219b2ee8SDavid du Colombier int i, n, cnt; 652219b2ee8SDavid du Colombier long off, toff, clock; 6533e12c5d1SDavid du Colombier Dir dir; 6549a747e4fSDavid du Colombier uchar buf[Maxfdata]; 6553e12c5d1SDavid du Colombier char *err; 6563e12c5d1SDavid du Colombier 6573e12c5d1SDavid du Colombier n = 0; 6583e12c5d1SDavid du Colombier err = 0; 6597dd7cddfSDavid du Colombier off = job->request.offset; 6607dd7cddfSDavid du Colombier cnt = job->request.count; 6619a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6623e12c5d1SDavid du Colombier clock = time(0); 6633e12c5d1SDavid du Colombier if(off == 0){ 6649a747e4fSDavid du Colombier dir.name = "cs"; 6659a747e4fSDavid du Colombier dir.qid.type = QTFILE; 6663e12c5d1SDavid du Colombier dir.qid.vers = vers; 6673e12c5d1SDavid du Colombier dir.qid.path = Qcs; 6683e12c5d1SDavid du Colombier dir.mode = 0666; 6693e12c5d1SDavid du Colombier dir.length = 0; 6709a747e4fSDavid du Colombier dir.uid = mf->user; 6719a747e4fSDavid du Colombier dir.gid = mf->user; 6729a747e4fSDavid du Colombier dir.muid = mf->user; 6733e12c5d1SDavid du Colombier dir.atime = clock; /* wrong */ 6743e12c5d1SDavid du Colombier dir.mtime = clock; /* wrong */ 6759a747e4fSDavid du Colombier n = convD2M(&dir, buf, sizeof buf); 6763e12c5d1SDavid du Colombier } 6779a747e4fSDavid du Colombier job->reply.data = (char*)buf; 6783e12c5d1SDavid du Colombier } else { 67980ee5cbfSDavid du Colombier for(;;){ 68080ee5cbfSDavid du Colombier /* look for an answer at the right offset */ 681219b2ee8SDavid du Colombier toff = 0; 682219b2ee8SDavid du Colombier for(i = 0; mf->reply[i] && i < mf->nreply; i++){ 683219b2ee8SDavid du Colombier n = mf->replylen[i]; 684219b2ee8SDavid du Colombier if(off < toff + n) 685219b2ee8SDavid du Colombier break; 686219b2ee8SDavid du Colombier toff += n; 6873e12c5d1SDavid du Colombier } 68880ee5cbfSDavid du Colombier if(i < mf->nreply) 68980ee5cbfSDavid du Colombier break; /* got something to return */ 69080ee5cbfSDavid du Colombier 69180ee5cbfSDavid du Colombier /* try looking up more answers */ 69280ee5cbfSDavid du Colombier if(lookup(mf) == 0){ 69380ee5cbfSDavid du Colombier /* no more */ 694219b2ee8SDavid du Colombier n = 0; 695219b2ee8SDavid du Colombier goto send; 696219b2ee8SDavid du Colombier } 69780ee5cbfSDavid du Colombier } 69880ee5cbfSDavid du Colombier 69980ee5cbfSDavid du Colombier /* give back a single reply (or part of one) */ 7007dd7cddfSDavid du Colombier job->reply.data = mf->reply[i] + (off - toff); 701219b2ee8SDavid du Colombier if(cnt > toff - off + n) 702219b2ee8SDavid du Colombier n = toff - off + n; 703219b2ee8SDavid du Colombier else 704219b2ee8SDavid du Colombier n = cnt; 7053e12c5d1SDavid du Colombier } 7063e12c5d1SDavid du Colombier send: 7077dd7cddfSDavid du Colombier job->reply.count = n; 7087dd7cddfSDavid du Colombier sendmsg(job, err); 7097dd7cddfSDavid du Colombier } 71080ee5cbfSDavid du Colombier void 71180ee5cbfSDavid du Colombier cleanmf(Mfile *mf) 7127dd7cddfSDavid du Colombier { 7137dd7cddfSDavid du Colombier int i; 7147dd7cddfSDavid du Colombier 7159a747e4fSDavid du Colombier if(mf->net != nil){ 71680ee5cbfSDavid du Colombier free(mf->net); 71780ee5cbfSDavid du Colombier mf->net = nil; 7189a747e4fSDavid du Colombier } 7199a747e4fSDavid du Colombier if(mf->host != nil){ 72080ee5cbfSDavid du Colombier free(mf->host); 72180ee5cbfSDavid du Colombier mf->host = nil; 7229a747e4fSDavid du Colombier } 7239a747e4fSDavid du Colombier if(mf->serv != nil){ 72480ee5cbfSDavid du Colombier free(mf->serv); 72580ee5cbfSDavid du Colombier mf->serv = nil; 7269a747e4fSDavid du Colombier } 7279a747e4fSDavid du Colombier if(mf->rem != nil){ 72880ee5cbfSDavid du Colombier free(mf->rem); 72980ee5cbfSDavid du Colombier mf->rem = nil; 7309a747e4fSDavid du Colombier } 73180ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++){ 73280ee5cbfSDavid du Colombier free(mf->reply[i]); 73380ee5cbfSDavid du Colombier mf->reply[i] = nil; 73480ee5cbfSDavid du Colombier mf->replylen[i] = 0; 7357dd7cddfSDavid du Colombier } 73680ee5cbfSDavid du Colombier mf->nreply = 0; 73780ee5cbfSDavid du Colombier mf->nextnet = netlist; 7383e12c5d1SDavid du Colombier } 7393e12c5d1SDavid du Colombier 7403e12c5d1SDavid du Colombier void 7417dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf) 7423e12c5d1SDavid du Colombier { 7433e12c5d1SDavid du Colombier int cnt, n; 74480ee5cbfSDavid du Colombier char *err; 7457dd7cddfSDavid du Colombier char *field[4]; 746271b8d73SDavid du Colombier char curerr[64]; 7473e12c5d1SDavid du Colombier 7483e12c5d1SDavid du Colombier err = 0; 7497dd7cddfSDavid du Colombier cnt = job->request.count; 7509a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 7513e12c5d1SDavid du Colombier err = "can't write directory"; 7523e12c5d1SDavid du Colombier goto send; 7533e12c5d1SDavid du Colombier } 7543e12c5d1SDavid du Colombier if(cnt >= Maxrequest){ 7553e12c5d1SDavid du Colombier err = "request too long"; 7563e12c5d1SDavid du Colombier goto send; 7573e12c5d1SDavid du Colombier } 7587dd7cddfSDavid du Colombier job->request.data[cnt] = 0; 7593e12c5d1SDavid du Colombier 7603e12c5d1SDavid du Colombier /* 761219b2ee8SDavid du Colombier * toggle debugging 762219b2ee8SDavid du Colombier */ 7637dd7cddfSDavid du Colombier if(strncmp(job->request.data, "debug", 5)==0){ 764219b2ee8SDavid du Colombier debug ^= 1; 765219b2ee8SDavid du Colombier syslog(1, logfile, "debug %d", debug); 766219b2ee8SDavid du Colombier goto send; 767219b2ee8SDavid du Colombier } 768219b2ee8SDavid du Colombier 769219b2ee8SDavid du Colombier /* 7707dd7cddfSDavid du Colombier * toggle debugging 7717dd7cddfSDavid du Colombier */ 7727dd7cddfSDavid du Colombier if(strncmp(job->request.data, "paranoia", 8)==0){ 7737dd7cddfSDavid du Colombier paranoia ^= 1; 7747dd7cddfSDavid du Colombier syslog(1, logfile, "paranoia %d", paranoia); 7757dd7cddfSDavid du Colombier goto send; 7767dd7cddfSDavid du Colombier } 7777dd7cddfSDavid du Colombier 7787dd7cddfSDavid du Colombier /* 7793e12c5d1SDavid du Colombier * add networks to the default list 7803e12c5d1SDavid du Colombier */ 7817dd7cddfSDavid du Colombier if(strncmp(job->request.data, "add ", 4)==0){ 7827dd7cddfSDavid du Colombier if(job->request.data[cnt-1] == '\n') 7837dd7cddfSDavid du Colombier job->request.data[cnt-1] = 0; 7847dd7cddfSDavid du Colombier netadd(job->request.data+4); 7857dd7cddfSDavid du Colombier readipinterfaces(); 7867dd7cddfSDavid du Colombier goto send; 7877dd7cddfSDavid du Colombier } 7887dd7cddfSDavid du Colombier 7897dd7cddfSDavid du Colombier /* 7907dd7cddfSDavid du Colombier * refresh all state 7917dd7cddfSDavid du Colombier */ 7927dd7cddfSDavid du Colombier if(strncmp(job->request.data, "refresh", 7)==0){ 7937dd7cddfSDavid du Colombier netinit(1); 7943e12c5d1SDavid du Colombier goto send; 7953e12c5d1SDavid du Colombier } 7963e12c5d1SDavid du Colombier 79780ee5cbfSDavid du Colombier /* start transaction with a clean slate */ 79880ee5cbfSDavid du Colombier cleanmf(mf); 79980ee5cbfSDavid du Colombier 8003e12c5d1SDavid du Colombier /* 801219b2ee8SDavid du Colombier * look for a general query 802219b2ee8SDavid du Colombier */ 8037dd7cddfSDavid du Colombier if(*job->request.data == '!'){ 8047dd7cddfSDavid du Colombier err = genquery(mf, job->request.data+1); 805219b2ee8SDavid du Colombier goto send; 806219b2ee8SDavid du Colombier } 807219b2ee8SDavid du Colombier 8087dd7cddfSDavid du Colombier if(debug) 8097dd7cddfSDavid du Colombier syslog(0, logfile, "write %s", job->request.data); 8107dd7cddfSDavid du Colombier if(paranoia) 8117dd7cddfSDavid du Colombier syslog(0, paranoiafile, "write %s by %s", job->request.data, mf->user); 8127dd7cddfSDavid du Colombier 813219b2ee8SDavid du Colombier /* 8143e12c5d1SDavid du Colombier * break up name 8153e12c5d1SDavid du Colombier */ 8167dd7cddfSDavid du Colombier n = getfields(job->request.data, field, 4, 1, "!"); 8173e12c5d1SDavid du Colombier switch(n){ 8183e12c5d1SDavid du Colombier case 1: 81980ee5cbfSDavid du Colombier mf->net = strdup("net"); 82080ee5cbfSDavid du Colombier mf->host = strdup(field[0]); 8217dd7cddfSDavid du Colombier break; 8227dd7cddfSDavid du Colombier case 4: 82380ee5cbfSDavid du Colombier mf->rem = strdup(field[3]); 82480ee5cbfSDavid du Colombier /* fall through */ 82580ee5cbfSDavid du Colombier case 3: 82680ee5cbfSDavid du Colombier mf->serv = strdup(field[2]); 82780ee5cbfSDavid du Colombier /* fall through */ 82880ee5cbfSDavid du Colombier case 2: 82980ee5cbfSDavid du Colombier mf->host = strdup(field[1]); 83080ee5cbfSDavid du Colombier mf->net = strdup(field[0]); 8313e12c5d1SDavid du Colombier break; 8323e12c5d1SDavid du Colombier } 8333e12c5d1SDavid du Colombier 83480ee5cbfSDavid du Colombier /* 83580ee5cbfSDavid du Colombier * do the first net worth of lookup 83680ee5cbfSDavid du Colombier */ 837271b8d73SDavid du Colombier if(lookup(mf) == 0){ 838271b8d73SDavid du Colombier rerrstr(curerr, sizeof curerr); 839271b8d73SDavid du Colombier err = curerr; 840271b8d73SDavid du Colombier } 8413e12c5d1SDavid du Colombier send: 8427dd7cddfSDavid du Colombier job->reply.count = cnt; 8437dd7cddfSDavid du Colombier sendmsg(job, err); 8443e12c5d1SDavid du Colombier } 8453e12c5d1SDavid du Colombier 8463e12c5d1SDavid du Colombier void 8477dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf) 8483e12c5d1SDavid du Colombier { 84980ee5cbfSDavid du Colombier cleanmf(mf); 850a9f680aeSDavid du Colombier free(mf->user); 851a9f680aeSDavid du Colombier mf->user = 0; 8523e12c5d1SDavid du Colombier mf->busy = 0; 8533e12c5d1SDavid du Colombier mf->fid = 0; 8547dd7cddfSDavid du Colombier sendmsg(job, 0); 8553e12c5d1SDavid du Colombier } 8563e12c5d1SDavid du Colombier 8573e12c5d1SDavid du Colombier void 8587dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf) 8593e12c5d1SDavid du Colombier { 8603e12c5d1SDavid du Colombier USED(mf); 8617dd7cddfSDavid du Colombier sendmsg(job, "remove permission denied"); 8623e12c5d1SDavid du Colombier } 8633e12c5d1SDavid du Colombier 8643e12c5d1SDavid du Colombier void 8657dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf) 8663e12c5d1SDavid du Colombier { 8673e12c5d1SDavid du Colombier Dir dir; 8689a747e4fSDavid du Colombier uchar buf[IOHDRSZ+Maxfdata]; 8693e12c5d1SDavid du Colombier 8709a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 8719a747e4fSDavid du Colombier dir.name = "."; 8729a747e4fSDavid du Colombier dir.mode = DMDIR|0555; 873219b2ee8SDavid du Colombier } else { 8749a747e4fSDavid du Colombier dir.name = "cs"; 8753e12c5d1SDavid du Colombier dir.mode = 0666; 876219b2ee8SDavid du Colombier } 877219b2ee8SDavid du Colombier dir.qid = mf->qid; 8783e12c5d1SDavid du Colombier dir.length = 0; 8799a747e4fSDavid du Colombier dir.uid = mf->user; 8809a747e4fSDavid du Colombier dir.gid = mf->user; 8819a747e4fSDavid du Colombier dir.muid = mf->user; 8823e12c5d1SDavid du Colombier dir.atime = dir.mtime = time(0); 8839a747e4fSDavid du Colombier job->reply.nstat = convD2M(&dir, buf, sizeof buf); 8849a747e4fSDavid du Colombier job->reply.stat = buf; 8857dd7cddfSDavid du Colombier sendmsg(job, 0); 8863e12c5d1SDavid du Colombier } 8873e12c5d1SDavid du Colombier 8883e12c5d1SDavid du Colombier void 8897dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf) 8903e12c5d1SDavid du Colombier { 8913e12c5d1SDavid du Colombier USED(mf); 8927dd7cddfSDavid du Colombier sendmsg(job, "wstat permission denied"); 8933e12c5d1SDavid du Colombier } 8943e12c5d1SDavid du Colombier 8953e12c5d1SDavid du Colombier void 8967dd7cddfSDavid du Colombier sendmsg(Job *job, char *err) 8973e12c5d1SDavid du Colombier { 8983e12c5d1SDavid du Colombier int n; 8999a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 9009a747e4fSDavid du Colombier char ename[ERRMAX]; 9013e12c5d1SDavid du Colombier 9023e12c5d1SDavid du Colombier if(err){ 9037dd7cddfSDavid du Colombier job->reply.type = Rerror; 9049a747e4fSDavid du Colombier snprint(ename, sizeof(ename), "cs: %s", err); 9059a747e4fSDavid du Colombier job->reply.ename = ename; 9063e12c5d1SDavid du Colombier }else{ 9077dd7cddfSDavid du Colombier job->reply.type = job->request.type+1; 9083e12c5d1SDavid du Colombier } 9097dd7cddfSDavid du Colombier job->reply.tag = job->request.tag; 9109a747e4fSDavid du Colombier n = convS2M(&job->reply, mdata, sizeof mdata); 911219b2ee8SDavid du Colombier if(n == 0){ 9127dd7cddfSDavid du Colombier syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply); 913219b2ee8SDavid du Colombier abort(); 914219b2ee8SDavid du Colombier } 9157dd7cddfSDavid du Colombier lock(&joblock); 9167dd7cddfSDavid du Colombier if(job->flushed == 0) 9179a747e4fSDavid du Colombier if(write(mfd[1], mdata, n)!=n) 9183e12c5d1SDavid du Colombier error("mount write"); 9197dd7cddfSDavid du Colombier unlock(&joblock); 920219b2ee8SDavid du Colombier if(debug) 9217dd7cddfSDavid du Colombier syslog(0, logfile, "%F %d", &job->reply, n); 9223e12c5d1SDavid du Colombier } 9233e12c5d1SDavid du Colombier 9243e12c5d1SDavid du Colombier void 9253e12c5d1SDavid du Colombier error(char *s) 9263e12c5d1SDavid du Colombier { 927bd389b36SDavid du Colombier syslog(1, "cs", "%s: %r", s); 928bd389b36SDavid du Colombier _exits(0); 9293e12c5d1SDavid du Colombier } 9303e12c5d1SDavid du Colombier 9317dd7cddfSDavid du Colombier static int 9327dd7cddfSDavid du Colombier isvalidip(uchar *ip) 9337dd7cddfSDavid du Colombier { 9347dd7cddfSDavid du Colombier return ipcmp(ip, IPnoaddr) != 0 && ipcmp(ip, v4prefix) != 0; 9357dd7cddfSDavid du Colombier } 9363e12c5d1SDavid du Colombier 9370103620dSDavid du Colombier static uchar loopbacknet[IPaddrlen] = { 9380103620dSDavid du Colombier 0, 0, 0, 0, 9390103620dSDavid du Colombier 0, 0, 0, 0, 9400103620dSDavid du Colombier 0, 0, 0xff, 0xff, 9410103620dSDavid du Colombier 127, 0, 0, 0 9420103620dSDavid du Colombier }; 9430103620dSDavid du Colombier static uchar loopbackmask[IPaddrlen] = { 9440103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9450103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9460103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9470103620dSDavid du Colombier 0xff, 0, 0, 0 9480103620dSDavid du Colombier }; 9490103620dSDavid du Colombier 9507dd7cddfSDavid du Colombier void 9517dd7cddfSDavid du Colombier readipinterfaces(void) 9527dd7cddfSDavid du Colombier { 9530103620dSDavid du Colombier if(myipaddr(ipa, mntpt) != 0) 9540103620dSDavid du Colombier ipmove(ipa, IPnoaddr); 9557dd7cddfSDavid du Colombier sprint(ipaddr, "%I", ipa); 9567dd7cddfSDavid du Colombier if (debug) 9577dd7cddfSDavid du Colombier syslog(0, "dns", "ipaddr is %s\n", ipaddr); 9587dd7cddfSDavid du Colombier } 9593e12c5d1SDavid du Colombier 9603e12c5d1SDavid du Colombier /* 9617dd7cddfSDavid du Colombier * get the system name 9623e12c5d1SDavid du Colombier */ 9633e12c5d1SDavid du Colombier void 9643e12c5d1SDavid du Colombier ipid(void) 9653e12c5d1SDavid du Colombier { 9663e12c5d1SDavid du Colombier uchar addr[6]; 967a9f680aeSDavid du Colombier Ndbtuple *t, *tt; 968219b2ee8SDavid du Colombier char *p, *attr; 9693e12c5d1SDavid du Colombier Ndbs s; 9703e12c5d1SDavid du Colombier int f; 9717dd7cddfSDavid du Colombier char buf[Maxpath]; 9723e12c5d1SDavid du Colombier 973219b2ee8SDavid du Colombier /* use environment, ether addr, or ipaddr to get system name */ 97495a264b3SDavid du Colombier if(mysysname == 0){ 9757dd7cddfSDavid du Colombier /* 9767dd7cddfSDavid du Colombier * environment has priority. 9777dd7cddfSDavid du Colombier * 9787dd7cddfSDavid du Colombier * on the sgi power the default system name 9797dd7cddfSDavid du Colombier * is the ip address. ignore that. 9807dd7cddfSDavid du Colombier * 9817dd7cddfSDavid du Colombier */ 982219b2ee8SDavid du Colombier p = getenv("sysname"); 983219b2ee8SDavid du Colombier if(p){ 984219b2ee8SDavid du Colombier attr = ipattr(p); 985219b2ee8SDavid du Colombier if(strcmp(attr, "ip") != 0) 98695a264b3SDavid du Colombier mysysname = strdup(p); 9873e12c5d1SDavid du Colombier } 9883e12c5d1SDavid du Colombier 9893e12c5d1SDavid du Colombier /* 9907dd7cddfSDavid du Colombier * the /net/ndb contains what the network 9917dd7cddfSDavid du Colombier * figured out from DHCP. use that name if 9927dd7cddfSDavid du Colombier * there is one. 9933e12c5d1SDavid du Colombier */ 99495a264b3SDavid du Colombier if(mysysname == 0 && netdb != nil){ 9957dd7cddfSDavid du Colombier ndbreopen(netdb); 996a9f680aeSDavid du Colombier for(tt = t = ndbparse(netdb); t != nil; t = t->entry){ 9977dd7cddfSDavid du Colombier if(strcmp(t->attr, "sys") == 0){ 99895a264b3SDavid du Colombier mysysname = strdup(t->val); 9993e12c5d1SDavid du Colombier break; 10003e12c5d1SDavid du Colombier } 10017dd7cddfSDavid du Colombier } 1002a9f680aeSDavid du Colombier ndbfree(tt); 10037dd7cddfSDavid du Colombier } 10047dd7cddfSDavid du Colombier 10057dd7cddfSDavid du Colombier /* next network database, ip address, and ether address to find a name */ 100695a264b3SDavid du Colombier if(mysysname == 0){ 10077dd7cddfSDavid du Colombier t = nil; 10087dd7cddfSDavid du Colombier if(isvalidip(ipa)) 100957837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "ip", ipaddr, "sys", &t)); 101095a264b3SDavid du Colombier if(t == nil){ 10117dd7cddfSDavid du Colombier for(f = 0; f < 3; f++){ 10127dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/ether%d", mntpt, f); 10137dd7cddfSDavid du Colombier if(myetheraddr(addr, buf) >= 0){ 10147dd7cddfSDavid du Colombier snprint(eaddr, sizeof(eaddr), "%E", addr); 101557837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "ether", eaddr, "sys", &t)); 10167dd7cddfSDavid du Colombier if(t != nil) 10177dd7cddfSDavid du Colombier break; 10187dd7cddfSDavid du Colombier } 10197dd7cddfSDavid du Colombier } 10207dd7cddfSDavid du Colombier } 1021*b7327ca2SDavid du Colombier for(tt = t; tt != nil; tt = tt->entry){ 1022*b7327ca2SDavid du Colombier if(strcmp(tt->attr, "sys") == 0){ 1023*b7327ca2SDavid du Colombier mysysname = strdup(tt->val); 102495a264b3SDavid du Colombier break; 102595a264b3SDavid du Colombier } 1026*b7327ca2SDavid du Colombier } 10277dd7cddfSDavid du Colombier ndbfree(t); 10287dd7cddfSDavid du Colombier } 10297dd7cddfSDavid du Colombier 103080ee5cbfSDavid du Colombier /* nothing else worked, use the ip address */ 103195a264b3SDavid du Colombier if(mysysname == 0 && isvalidip(ipa)) 103295a264b3SDavid du Colombier mysysname = strdup(ipaddr); 103380ee5cbfSDavid du Colombier 103480ee5cbfSDavid du Colombier 1035dc5a79c1SDavid du Colombier /* set /dev/sysname if we now know it */ 103695a264b3SDavid du Colombier if(mysysname){ 10377dd7cddfSDavid du Colombier f = open("/dev/sysname", OWRITE); 10387dd7cddfSDavid du Colombier if(f >= 0){ 10397dd7cddfSDavid du Colombier write(f, mysysname, strlen(mysysname)); 10403e12c5d1SDavid du Colombier close(f); 10413e12c5d1SDavid du Colombier } 10423e12c5d1SDavid du Colombier } 10433e12c5d1SDavid du Colombier } 10443e12c5d1SDavid du Colombier } 10453e12c5d1SDavid du Colombier 10463e12c5d1SDavid du Colombier /* 10473e12c5d1SDavid du Colombier * Set up a list of default networks by looking for 10483e12c5d1SDavid du Colombier * /net/ * /clone. 10493e12c5d1SDavid du Colombier */ 10503e12c5d1SDavid du Colombier void 10517dd7cddfSDavid du Colombier netinit(int background) 10523e12c5d1SDavid du Colombier { 10537dd7cddfSDavid du Colombier char clone[Maxpath]; 10543e12c5d1SDavid du Colombier Network *np; 10557dd7cddfSDavid du Colombier static int working; 10567dd7cddfSDavid du Colombier 10577dd7cddfSDavid du Colombier if(background){ 10587dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 10597dd7cddfSDavid du Colombier case 0: 10607dd7cddfSDavid du Colombier break; 10617dd7cddfSDavid du Colombier default: 10627dd7cddfSDavid du Colombier return; 10637dd7cddfSDavid du Colombier } 10647dd7cddfSDavid du Colombier lock(&netlock); 10657dd7cddfSDavid du Colombier } 10663e12c5d1SDavid du Colombier 10673e12c5d1SDavid du Colombier /* add the mounted networks to the default list */ 10683e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 10697dd7cddfSDavid du Colombier if(np->considered) 10707dd7cddfSDavid du Colombier continue; 10717dd7cddfSDavid du Colombier snprint(clone, sizeof(clone), "%s/%s/clone", mntpt, np->net); 10729a747e4fSDavid du Colombier if(access(clone, AEXIST) < 0) 10733e12c5d1SDavid du Colombier continue; 10743e12c5d1SDavid du Colombier if(netlist) 10753e12c5d1SDavid du Colombier last->next = np; 10763e12c5d1SDavid du Colombier else 10773e12c5d1SDavid du Colombier netlist = np; 10783e12c5d1SDavid du Colombier last = np; 10793e12c5d1SDavid du Colombier np->next = 0; 10807dd7cddfSDavid du Colombier np->considered = 1; 10813e12c5d1SDavid du Colombier } 10823e12c5d1SDavid du Colombier 10837dd7cddfSDavid du Colombier /* find out what our ip address is */ 10847dd7cddfSDavid du Colombier readipinterfaces(); 10853e12c5d1SDavid du Colombier 10867dd7cddfSDavid du Colombier /* set the system name if we need to, these says ip is all we have */ 10873e12c5d1SDavid du Colombier ipid(); 10883e12c5d1SDavid du Colombier 1089219b2ee8SDavid du Colombier if(debug) 10907dd7cddfSDavid du Colombier syslog(0, logfile, "mysysname %s eaddr %s ipaddr %s ipa %I\n", 109195a264b3SDavid du Colombier mysysname?mysysname:"???", eaddr, ipaddr, ipa); 10927dd7cddfSDavid du Colombier 10937dd7cddfSDavid du Colombier if(background){ 10947dd7cddfSDavid du Colombier unlock(&netlock); 10957dd7cddfSDavid du Colombier _exits(0); 10967dd7cddfSDavid du Colombier } 10973e12c5d1SDavid du Colombier } 10983e12c5d1SDavid du Colombier 10993e12c5d1SDavid du Colombier /* 11003e12c5d1SDavid du Colombier * add networks to the standard list 11013e12c5d1SDavid du Colombier */ 11023e12c5d1SDavid du Colombier void 11033e12c5d1SDavid du Colombier netadd(char *p) 11043e12c5d1SDavid du Colombier { 11053e12c5d1SDavid du Colombier Network *np; 11063e12c5d1SDavid du Colombier char *field[12]; 11073e12c5d1SDavid du Colombier int i, n; 11083e12c5d1SDavid du Colombier 11097dd7cddfSDavid du Colombier n = getfields(p, field, 12, 1, " "); 11103e12c5d1SDavid du Colombier for(i = 0; i < n; i++){ 11113e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 11123e12c5d1SDavid du Colombier if(strcmp(field[i], np->net) != 0) 11133e12c5d1SDavid du Colombier continue; 11147dd7cddfSDavid du Colombier if(np->considered) 11153e12c5d1SDavid du Colombier break; 11163e12c5d1SDavid du Colombier if(netlist) 11173e12c5d1SDavid du Colombier last->next = np; 11183e12c5d1SDavid du Colombier else 11193e12c5d1SDavid du Colombier netlist = np; 11203e12c5d1SDavid du Colombier last = np; 11213e12c5d1SDavid du Colombier np->next = 0; 11227dd7cddfSDavid du Colombier np->considered = 1; 11233e12c5d1SDavid du Colombier } 11243e12c5d1SDavid du Colombier } 11253e12c5d1SDavid du Colombier } 11263e12c5d1SDavid du Colombier 112780ee5cbfSDavid du Colombier int 112880ee5cbfSDavid du Colombier lookforproto(Ndbtuple *t, char *proto) 112980ee5cbfSDavid du Colombier { 113080ee5cbfSDavid du Colombier for(; t != nil; t = t->entry) 113180ee5cbfSDavid du Colombier if(strcmp(t->attr, "proto") == 0 && strcmp(t->val, proto) == 0) 113280ee5cbfSDavid du Colombier return 1; 113380ee5cbfSDavid du Colombier return 0; 113480ee5cbfSDavid du Colombier } 113580ee5cbfSDavid du Colombier 1136219b2ee8SDavid du Colombier /* 11373e12c5d1SDavid du Colombier * lookup a request. the network "net" means we should pick the 11383e12c5d1SDavid du Colombier * best network to get there. 11393e12c5d1SDavid du Colombier */ 11403e12c5d1SDavid du Colombier int 114180ee5cbfSDavid du Colombier lookup(Mfile *mf) 11423e12c5d1SDavid du Colombier { 114380ee5cbfSDavid du Colombier Network *np; 1144219b2ee8SDavid du Colombier char *cp; 1145219b2ee8SDavid du Colombier Ndbtuple *nt, *t; 1146219b2ee8SDavid du Colombier char reply[Maxreply]; 114780ee5cbfSDavid du Colombier int i, rv; 114880ee5cbfSDavid du Colombier int hack; 11493e12c5d1SDavid du Colombier 11503e12c5d1SDavid du Colombier /* open up the standard db files */ 11513e12c5d1SDavid du Colombier if(db == 0) 11527dd7cddfSDavid du Colombier ndbinit(); 11533e12c5d1SDavid du Colombier if(db == 0) 115480ee5cbfSDavid du Colombier error("can't open mf->network database\n"); 11553e12c5d1SDavid du Colombier 115680ee5cbfSDavid du Colombier rv = 0; 115780ee5cbfSDavid du Colombier 115880ee5cbfSDavid du Colombier if(mf->net == nil) 115980ee5cbfSDavid du Colombier return 0; /* must have been a genquery */ 116080ee5cbfSDavid du Colombier 116180ee5cbfSDavid du Colombier if(strcmp(mf->net, "net") == 0){ 11623e12c5d1SDavid du Colombier /* 11633e12c5d1SDavid du Colombier * go through set of default nets 11643e12c5d1SDavid du Colombier */ 116580ee5cbfSDavid du Colombier for(np = mf->nextnet; np; np = np->next){ 116680ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 116780ee5cbfSDavid du Colombier if(nt == nil) 1168219b2ee8SDavid du Colombier continue; 116980ee5cbfSDavid du Colombier hack = np->fasttimeouthack && !lookforproto(nt, np->net); 117080ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 117180ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, hack); 1172219b2ee8SDavid du Colombier if(cp){ 117380ee5cbfSDavid du Colombier /* avoid duplicates */ 117480ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++) 117580ee5cbfSDavid du Colombier if(strcmp(mf->reply[i], cp) == 0) 117680ee5cbfSDavid du Colombier break; 117780ee5cbfSDavid du Colombier if(i == mf->nreply){ 117880ee5cbfSDavid du Colombier /* save the reply */ 1179219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 1180219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = cp; 118180ee5cbfSDavid du Colombier rv++; 1182219b2ee8SDavid du Colombier } 1183219b2ee8SDavid du Colombier } 1184219b2ee8SDavid du Colombier } 1185219b2ee8SDavid du Colombier ndbfree(nt); 118680ee5cbfSDavid du Colombier np = np->next; 118780ee5cbfSDavid du Colombier break; 118880ee5cbfSDavid du Colombier } 118980ee5cbfSDavid du Colombier mf->nextnet = np; 119080ee5cbfSDavid du Colombier return rv; 119180ee5cbfSDavid du Colombier } 119280ee5cbfSDavid du Colombier 119380ee5cbfSDavid du Colombier /* 119480ee5cbfSDavid du Colombier * if not /net, we only get one lookup 119580ee5cbfSDavid du Colombier */ 119680ee5cbfSDavid du Colombier if(mf->nreply != 0) 1197219b2ee8SDavid du Colombier return 0; 119880ee5cbfSDavid du Colombier /* 119980ee5cbfSDavid du Colombier * look for a specific network 120080ee5cbfSDavid du Colombier */ 120195a264b3SDavid du Colombier for(np = netlist; np && 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 120895a264b3SDavid du Colombier if(np && np->net != nil){ 120980ee5cbfSDavid du Colombier /* 121080ee5cbfSDavid du Colombier * known network 121180ee5cbfSDavid du Colombier */ 121295a264b3SDavid du Colombier syslog(0, logfile, "specific lookup %s", np->net); 121380ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 121495a264b3SDavid du Colombier syslog(0, logfile, "returned %p", nt); 121580ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 121680ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, 0); 121780ee5cbfSDavid du Colombier if(cp){ 121880ee5cbfSDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 121980ee5cbfSDavid du Colombier mf->reply[mf->nreply++] = cp; 122080ee5cbfSDavid du Colombier rv++; 122180ee5cbfSDavid du Colombier } 122280ee5cbfSDavid du Colombier } 122380ee5cbfSDavid du Colombier ndbfree(nt); 122480ee5cbfSDavid du Colombier return rv; 12253e12c5d1SDavid du Colombier } else { 12263e12c5d1SDavid du Colombier /* 1227219b2ee8SDavid du Colombier * not a known network, don't translate host or service 12283e12c5d1SDavid du Colombier */ 122980ee5cbfSDavid du Colombier if(mf->serv) 12307dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s", 123180ee5cbfSDavid du Colombier mntpt, mf->net, mf->host, mf->serv); 1232bd389b36SDavid du Colombier else 12337dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s", 123480ee5cbfSDavid du Colombier mntpt, mf->net, mf->host); 1235219b2ee8SDavid du Colombier mf->reply[0] = strdup(reply); 1236219b2ee8SDavid du Colombier mf->replylen[0] = strlen(reply); 1237219b2ee8SDavid du Colombier mf->nreply = 1; 123880ee5cbfSDavid du Colombier return 1; 12393e12c5d1SDavid du Colombier } 12403e12c5d1SDavid du Colombier } 12413e12c5d1SDavid du Colombier 12423e12c5d1SDavid du Colombier /* 12433e12c5d1SDavid du Colombier * translate an ip service name into a port number. If it's a numeric port 12443e12c5d1SDavid du Colombier * number, look for restricted access. 12453e12c5d1SDavid du Colombier * 12463e12c5d1SDavid du Colombier * the service '*' needs no translation. 12473e12c5d1SDavid du Colombier */ 12483e12c5d1SDavid du Colombier char* 124995a264b3SDavid du Colombier ipserv(Network *np, char *name, char *buf, int blen) 12503e12c5d1SDavid du Colombier { 12513e12c5d1SDavid du Colombier char *p; 12523e12c5d1SDavid du Colombier int alpha = 0; 12533e12c5d1SDavid du Colombier int restr = 0; 125495a264b3SDavid du Colombier char port[10]; 12553e12c5d1SDavid du Colombier Ndbtuple *t, *nt; 12563e12c5d1SDavid du Colombier Ndbs s; 12573e12c5d1SDavid du Colombier 12583e12c5d1SDavid du Colombier /* '*' means any service */ 12593e12c5d1SDavid du Colombier if(strcmp(name, "*")==0){ 12603e12c5d1SDavid du Colombier strcpy(buf, name); 12613e12c5d1SDavid du Colombier return buf; 12623e12c5d1SDavid du Colombier } 12633e12c5d1SDavid du Colombier 12643e12c5d1SDavid du Colombier /* see if it's numeric or symbolic */ 12653e12c5d1SDavid du Colombier port[0] = 0; 12663e12c5d1SDavid du Colombier for(p = name; *p; p++){ 12673e12c5d1SDavid du Colombier if(isdigit(*p)) 12689a747e4fSDavid du Colombier {} 12693e12c5d1SDavid du Colombier else if(isalpha(*p) || *p == '-' || *p == '$') 12703e12c5d1SDavid du Colombier alpha = 1; 12713e12c5d1SDavid du Colombier else 12723e12c5d1SDavid du Colombier return 0; 12733e12c5d1SDavid du Colombier } 127457837e0bSDavid du Colombier t = nil; 127557837e0bSDavid du Colombier p = nil; 12763e12c5d1SDavid du Colombier if(alpha){ 127757837e0bSDavid du Colombier p = ndbgetvalue(db, &s, np->net, name, "port", &t); 1278*b7327ca2SDavid du Colombier if(p == nil) 1279*b7327ca2SDavid du Colombier return 0; 12803e12c5d1SDavid du Colombier } else { 12813cc1eb97SDavid du Colombier /* look up only for tcp ports < 1024 to get the restricted 12823cc1eb97SDavid du Colombier * attribute 12833cc1eb97SDavid du Colombier */ 12843cc1eb97SDavid du Colombier if(atoi(name) < 1024 && strcmp(np->net, "tcp") == 0) 128557837e0bSDavid du Colombier p = ndbgetvalue(db, &s, "port", name, "port", &t); 128657837e0bSDavid du Colombier if(p == nil) 128757837e0bSDavid du Colombier p = strdup(name); 12883e12c5d1SDavid du Colombier } 12893e12c5d1SDavid du Colombier 12903e12c5d1SDavid du Colombier if(t){ 12913e12c5d1SDavid du Colombier for(nt = t; nt; nt = nt->entry) 12923e12c5d1SDavid du Colombier if(strcmp(nt->attr, "restricted") == 0) 12933e12c5d1SDavid du Colombier restr = 1; 12943e12c5d1SDavid du Colombier ndbfree(t); 12953e12c5d1SDavid du Colombier } 129657837e0bSDavid du Colombier snprint(buf, blen, "%s%s", p, restr ? "!r" : ""); 129757837e0bSDavid du Colombier free(p); 129857837e0bSDavid du Colombier 12993e12c5d1SDavid du Colombier return buf; 13003e12c5d1SDavid du Colombier } 13013e12c5d1SDavid du Colombier 13023e12c5d1SDavid du Colombier /* 13037dd7cddfSDavid du Colombier * lookup an ip attribute 13043e12c5d1SDavid du Colombier */ 13057dd7cddfSDavid du Colombier int 130695a264b3SDavid du Colombier ipattrlookup(Ndb *db, char *ipa, char *attr, char *val, int vlen) 13073e12c5d1SDavid du Colombier { 13083e12c5d1SDavid du Colombier 13097dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13107dd7cddfSDavid du Colombier char *alist[2]; 13113e12c5d1SDavid du Colombier 13127dd7cddfSDavid du Colombier alist[0] = attr; 13137dd7cddfSDavid du Colombier t = ndbipinfo(db, "ip", ipa, alist, 1); 13147dd7cddfSDavid du Colombier if(t == nil) 13157dd7cddfSDavid du Colombier return 0; 13169a747e4fSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 13177dd7cddfSDavid du Colombier if(strcmp(nt->attr, attr) == 0){ 131895a264b3SDavid du Colombier nstrcpy(val, nt->val, vlen); 13193e12c5d1SDavid du Colombier ndbfree(t); 13207dd7cddfSDavid du Colombier return 1; 1321219b2ee8SDavid du Colombier } 13229a747e4fSDavid du Colombier } 13233e12c5d1SDavid du Colombier 13247dd7cddfSDavid du Colombier /* we shouldn't get here */ 13253e12c5d1SDavid du Colombier ndbfree(t); 13267dd7cddfSDavid du Colombier return 0; 13273e12c5d1SDavid du Colombier } 13283e12c5d1SDavid du Colombier 13293e12c5d1SDavid du Colombier /* 13303e12c5d1SDavid du Colombier * lookup (and translate) an ip destination 13313e12c5d1SDavid du Colombier */ 1332219b2ee8SDavid du Colombier Ndbtuple* 1333219b2ee8SDavid du Colombier iplookup(Network *np, char *host, char *serv, int nolookup) 13343e12c5d1SDavid du Colombier { 13353e12c5d1SDavid du Colombier char *attr; 13367dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13373e12c5d1SDavid du Colombier Ndbs s; 133895a264b3SDavid du Colombier char ts[Maxservice]; 133995a264b3SDavid du Colombier char dollar[Maxhost]; 13407dd7cddfSDavid du Colombier uchar ip[IPaddrlen]; 13417dd7cddfSDavid du Colombier uchar net[IPaddrlen]; 13427dd7cddfSDavid du Colombier uchar tnet[IPaddrlen]; 13437dd7cddfSDavid du Colombier Ipifc *ifc; 13449a747e4fSDavid du Colombier Iplifc *lifc; 13453e12c5d1SDavid du Colombier 1346219b2ee8SDavid du Colombier USED(nolookup); 1347219b2ee8SDavid du Colombier 13483e12c5d1SDavid du Colombier /* 13493e12c5d1SDavid du Colombier * start with the service since it's the most likely to fail 13503e12c5d1SDavid du Colombier * and costs the least 13513e12c5d1SDavid du Colombier */ 13527dd7cddfSDavid du Colombier werrstr("can't translate address"); 135395a264b3SDavid du Colombier if(serv==0 || ipserv(np, serv, ts, sizeof ts) == 0){ 1354271b8d73SDavid du Colombier werrstr("can't translate service"); 1355219b2ee8SDavid du Colombier return 0; 13567dd7cddfSDavid du Colombier } 13573e12c5d1SDavid du Colombier 13583e12c5d1SDavid du Colombier /* for dial strings with no host */ 1359219b2ee8SDavid du Colombier if(strcmp(host, "*") == 0) 136095a264b3SDavid du Colombier return ndbnew("ip", "*"); 13613e12c5d1SDavid du Colombier 13623e12c5d1SDavid du Colombier /* 13637dd7cddfSDavid du Colombier * hack till we go v6 :: = 0.0.0.0 13647dd7cddfSDavid du Colombier */ 13657dd7cddfSDavid du Colombier if(strcmp("::", host) == 0) 136695a264b3SDavid du Colombier return ndbnew("ip", "*"); 13677dd7cddfSDavid du Colombier 13687dd7cddfSDavid du Colombier /* 13693e12c5d1SDavid du Colombier * '$' means the rest of the name is an attribute that we 13703e12c5d1SDavid du Colombier * need to search for 13713e12c5d1SDavid du Colombier */ 13723e12c5d1SDavid du Colombier if(*host == '$'){ 137395a264b3SDavid du Colombier if(ipattrlookup(db, ipaddr, host+1, dollar, sizeof dollar)) 13743e12c5d1SDavid du Colombier host = dollar; 13753e12c5d1SDavid du Colombier } 13763e12c5d1SDavid du Colombier 13773e12c5d1SDavid du Colombier /* 13787dd7cddfSDavid du Colombier * turn '[ip address]' into just 'ip address' 13797dd7cddfSDavid du Colombier */ 13807dd7cddfSDavid du Colombier if(*host == '[' && host[strlen(host)-1] == ']'){ 13817dd7cddfSDavid du Colombier host++; 13827dd7cddfSDavid du Colombier host[strlen(host)-1] = 0; 13837dd7cddfSDavid du Colombier } 13847dd7cddfSDavid du Colombier 13857dd7cddfSDavid du Colombier /* 13863e12c5d1SDavid du Colombier * just accept addresses 13873e12c5d1SDavid du Colombier */ 1388219b2ee8SDavid du Colombier attr = ipattr(host); 1389219b2ee8SDavid du Colombier if(strcmp(attr, "ip") == 0) 139095a264b3SDavid du Colombier return ndbnew("ip", host); 13913e12c5d1SDavid du Colombier 13923e12c5d1SDavid du Colombier /* 13933e12c5d1SDavid du Colombier * give the domain name server the first opportunity to 1394bd389b36SDavid du Colombier * resolve domain names. if that fails try the database. 13953e12c5d1SDavid du Colombier */ 13963e12c5d1SDavid du Colombier t = 0; 1397271b8d73SDavid du Colombier werrstr("can't translate address"); 13983e12c5d1SDavid du Colombier if(strcmp(attr, "dom") == 0) 13997dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 14003e12c5d1SDavid du Colombier if(t == 0) 140157837e0bSDavid du Colombier free(ndbgetvalue(db, &s, attr, host, "ip", &t)); 14023e12c5d1SDavid du Colombier if(t == 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 { 144495a264b3SDavid du Colombier char ts[Maxservice]; 1445219b2ee8SDavid du Colombier char reply[Maxreply]; 144695a264b3SDavid du Colombier char x[Maxservice]; 14473e12c5d1SDavid du Colombier 1448219b2ee8SDavid du Colombier if(strcmp(t->attr, "ip") != 0) 14493e12c5d1SDavid du Colombier return 0; 1450219b2ee8SDavid du Colombier 145195a264b3SDavid du Colombier if(serv == 0 || ipserv(np, serv, ts, sizeof 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 1479219b2ee8SDavid du Colombier USED(np, nolookup, serv); 1480219b2ee8SDavid du Colombier 1481271b8d73SDavid du Colombier werrstr("can't translate address"); 148257837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "sys", host, "telco", &t)); 1483219b2ee8SDavid du Colombier if(t == 0) 148495a264b3SDavid du Colombier return ndbnew("telco", host); 1485219b2ee8SDavid du Colombier 1486219b2ee8SDavid du Colombier return reorder(t, s.t); 1487219b2ee8SDavid du Colombier } 1488219b2ee8SDavid du Colombier 1489219b2ee8SDavid du Colombier /* 1490219b2ee8SDavid du Colombier * translate a telephone address 1491219b2ee8SDavid du Colombier */ 1492219b2ee8SDavid du Colombier char* 149380ee5cbfSDavid du Colombier telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int) 1494219b2ee8SDavid du Colombier { 1495219b2ee8SDavid du Colombier char reply[Maxreply]; 149695a264b3SDavid du Colombier char x[Maxservice]; 1497219b2ee8SDavid du Colombier 1498219b2ee8SDavid du Colombier if(strcmp(t->attr, "telco") != 0) 1499219b2ee8SDavid du Colombier return 0; 1500219b2ee8SDavid du Colombier 15017dd7cddfSDavid du Colombier if(rem != nil) 15027dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 1503219b2ee8SDavid du Colombier else 15047dd7cddfSDavid du Colombier *x = 0; 15057dd7cddfSDavid du Colombier if(serv) 15067dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s", mntpt, np->net, 15077dd7cddfSDavid du Colombier t->val, serv, x); 15087dd7cddfSDavid du Colombier else 15097dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net, 15107dd7cddfSDavid du Colombier t->val, x); 1511219b2ee8SDavid du Colombier return strdup(reply); 1512219b2ee8SDavid du Colombier } 15133e12c5d1SDavid du Colombier 15143e12c5d1SDavid du Colombier /* 15153e12c5d1SDavid du Colombier * reorder the tuple to put x's line first in the entry 15163e12c5d1SDavid du Colombier */ 15173e12c5d1SDavid du Colombier Ndbtuple* 15183e12c5d1SDavid du Colombier reorder(Ndbtuple *t, Ndbtuple *x) 15193e12c5d1SDavid du Colombier { 15203e12c5d1SDavid du Colombier Ndbtuple *nt; 15213e12c5d1SDavid du Colombier Ndbtuple *line; 15223e12c5d1SDavid du Colombier 1523219b2ee8SDavid du Colombier /* find start of this entry's line */ 1524219b2ee8SDavid du Colombier for(line = x; line->entry == line->line; line = line->line) 15253e12c5d1SDavid du Colombier ; 1526219b2ee8SDavid du Colombier line = line->line; 1527219b2ee8SDavid du Colombier if(line == t) 1528219b2ee8SDavid du Colombier return t; /* already the first line */ 15293e12c5d1SDavid du Colombier 1530219b2ee8SDavid du Colombier /* remove this line and everything after it from the entry */ 1531219b2ee8SDavid du Colombier for(nt = t; nt->entry != line; nt = nt->entry) 1532219b2ee8SDavid du Colombier ; 1533219b2ee8SDavid du Colombier nt->entry = 0; 15343e12c5d1SDavid du Colombier 1535219b2ee8SDavid du Colombier /* make that the start of the entry */ 1536219b2ee8SDavid du Colombier for(nt = line; nt->entry; nt = nt->entry) 1537219b2ee8SDavid du Colombier ; 15383e12c5d1SDavid du Colombier nt->entry = t; 15393e12c5d1SDavid du Colombier return line; 15403e12c5d1SDavid du Colombier } 15413e12c5d1SDavid du Colombier 15423e12c5d1SDavid du Colombier /* 15433e12c5d1SDavid du Colombier * create a slave process to handle a request to avoid one request blocking 15447dd7cddfSDavid du Colombier * another. parent returns to job loop. 15453e12c5d1SDavid du Colombier */ 15463e12c5d1SDavid du Colombier void 15473e12c5d1SDavid du Colombier slave(void) 15483e12c5d1SDavid du Colombier { 15493e12c5d1SDavid du Colombier if(*isslave) 15503e12c5d1SDavid du Colombier return; /* we're already a slave process */ 15513e12c5d1SDavid du Colombier 15523e12c5d1SDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 15533e12c5d1SDavid du Colombier case -1: 15543e12c5d1SDavid du Colombier break; 15553e12c5d1SDavid du Colombier case 0: 1556219b2ee8SDavid du Colombier if(debug) 1557219b2ee8SDavid du Colombier syslog(0, logfile, "slave %d", getpid()); 15583e12c5d1SDavid du Colombier *isslave = 1; 15593e12c5d1SDavid du Colombier break; 15603e12c5d1SDavid du Colombier default: 15613e12c5d1SDavid du Colombier longjmp(masterjmp, 1); 15623e12c5d1SDavid du Colombier } 15633e12c5d1SDavid du Colombier 1564219b2ee8SDavid du Colombier } 1565219b2ee8SDavid du Colombier 15663e12c5d1SDavid du Colombier /* 15673e12c5d1SDavid du Colombier * call the dns process and have it try to translate a name 15683e12c5d1SDavid du Colombier */ 15693e12c5d1SDavid du Colombier Ndbtuple* 15707dd7cddfSDavid du Colombier dnsiplookup(char *host, Ndbs *s) 15713e12c5d1SDavid du Colombier { 157295a264b3SDavid du Colombier char buf[Maxreply]; 15737dd7cddfSDavid du Colombier Ndbtuple *t; 15743e12c5d1SDavid du Colombier 1575bd389b36SDavid du Colombier unlock(&dblock); 1576bd389b36SDavid du Colombier 15773e12c5d1SDavid du Colombier /* save the name before starting a slave */ 15787dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s", host); 15793e12c5d1SDavid du Colombier 15803e12c5d1SDavid du Colombier slave(); 15813e12c5d1SDavid du Colombier 15827dd7cddfSDavid du Colombier if(strcmp(ipattr(buf), "ip") == 0) 15837dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ptr"); 15847dd7cddfSDavid du Colombier else 15857dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ip"); 15863e12c5d1SDavid du Colombier s->t = t; 15877dd7cddfSDavid du Colombier 1588271b8d73SDavid du Colombier if(t == nil){ 1589271b8d73SDavid du Colombier rerrstr(buf, sizeof buf); 1590271b8d73SDavid du Colombier if(strstr(buf, "exist")) 1591271b8d73SDavid du Colombier werrstr("can't translate address: %s", buf); 1592271b8d73SDavid du Colombier else if(strstr(buf, "dns failure")) 1593271b8d73SDavid du Colombier werrstr("temporary problem: %s", buf); 1594271b8d73SDavid du Colombier } 1595271b8d73SDavid du Colombier 1596bd389b36SDavid du Colombier lock(&dblock); 15973e12c5d1SDavid du Colombier return t; 15983e12c5d1SDavid du Colombier } 1599219b2ee8SDavid du Colombier 1600219b2ee8SDavid du Colombier int 1601219b2ee8SDavid du Colombier qmatch(Ndbtuple *t, char **attr, char **val, int n) 1602219b2ee8SDavid du Colombier { 1603219b2ee8SDavid du Colombier int i, found; 1604219b2ee8SDavid du Colombier Ndbtuple *nt; 1605219b2ee8SDavid du Colombier 1606219b2ee8SDavid du Colombier for(i = 1; i < n; i++){ 1607219b2ee8SDavid du Colombier found = 0; 1608219b2ee8SDavid du Colombier for(nt = t; nt; nt = nt->entry) 1609219b2ee8SDavid du Colombier if(strcmp(attr[i], nt->attr) == 0) 1610219b2ee8SDavid du Colombier if(strcmp(val[i], "*") == 0 1611219b2ee8SDavid du Colombier || strcmp(val[i], nt->val) == 0){ 1612219b2ee8SDavid du Colombier found = 1; 1613219b2ee8SDavid du Colombier break; 1614219b2ee8SDavid du Colombier } 1615219b2ee8SDavid du Colombier if(found == 0) 1616219b2ee8SDavid du Colombier break; 1617219b2ee8SDavid du Colombier } 1618219b2ee8SDavid du Colombier return i == n; 1619219b2ee8SDavid du Colombier } 1620219b2ee8SDavid du Colombier 1621219b2ee8SDavid du Colombier void 1622219b2ee8SDavid du Colombier qreply(Mfile *mf, Ndbtuple *t) 1623219b2ee8SDavid du Colombier { 1624219b2ee8SDavid du Colombier Ndbtuple *nt; 162595a264b3SDavid du Colombier String *s; 1626219b2ee8SDavid du Colombier 162795a264b3SDavid du Colombier s = s_new(); 1628219b2ee8SDavid du Colombier for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){ 162995a264b3SDavid du Colombier s_append(s, nt->attr); 163095a264b3SDavid du Colombier s_append(s, "="); 163195a264b3SDavid du Colombier s_append(s, nt->val); 163295a264b3SDavid du Colombier 163395a264b3SDavid du Colombier if(nt->line != nt->entry){ 163495a264b3SDavid du Colombier mf->replylen[mf->nreply] = s_len(s); 163595a264b3SDavid du Colombier mf->reply[mf->nreply++] = strdup(s_to_c(s)); 163695a264b3SDavid du Colombier s_restart(s); 1637219b2ee8SDavid du Colombier } else 163895a264b3SDavid du Colombier s_append(s, " "); 1639219b2ee8SDavid du Colombier } 164095a264b3SDavid du Colombier s_free(s); 1641219b2ee8SDavid du Colombier } 1642219b2ee8SDavid du Colombier 16437dd7cddfSDavid du Colombier enum 16447dd7cddfSDavid du Colombier { 16457dd7cddfSDavid du Colombier Maxattr= 32, 16467dd7cddfSDavid du Colombier }; 16477dd7cddfSDavid du Colombier 1648219b2ee8SDavid du Colombier /* 16497dd7cddfSDavid du Colombier * generic query lookup. The query is of one of the following 16507dd7cddfSDavid du Colombier * forms: 16517dd7cddfSDavid du Colombier * 16527dd7cddfSDavid du Colombier * attr1=val1 attr2=val2 attr3=val3 ... 16537dd7cddfSDavid du Colombier * 16547dd7cddfSDavid du Colombier * returns the matching tuple 16557dd7cddfSDavid du Colombier * 16567dd7cddfSDavid du Colombier * ipinfo attr=val attr1 attr2 attr3 ... 16577dd7cddfSDavid du Colombier * 16587dd7cddfSDavid du Colombier * is like ipinfo and returns the attr{1-n} 16597dd7cddfSDavid du Colombier * associated with the ip address. 1660219b2ee8SDavid du Colombier */ 1661219b2ee8SDavid du Colombier char* 1662219b2ee8SDavid du Colombier genquery(Mfile *mf, char *query) 1663219b2ee8SDavid du Colombier { 1664219b2ee8SDavid du Colombier int i, n; 1665219b2ee8SDavid du Colombier char *p; 16667dd7cddfSDavid du Colombier char *attr[Maxattr]; 16677dd7cddfSDavid du Colombier char *val[Maxattr]; 1668219b2ee8SDavid du Colombier Ndbtuple *t; 1669219b2ee8SDavid du Colombier Ndbs s; 1670219b2ee8SDavid du Colombier 16717dd7cddfSDavid du Colombier n = getfields(query, attr, 32, 1, " "); 1672219b2ee8SDavid du Colombier if(n == 0) 1673219b2ee8SDavid du Colombier return "bad query"; 1674219b2ee8SDavid du Colombier 16757dd7cddfSDavid du Colombier if(strcmp(attr[0], "ipinfo") == 0) 16767dd7cddfSDavid du Colombier return ipinfoquery(mf, attr, n); 16777dd7cddfSDavid du Colombier 1678219b2ee8SDavid du Colombier /* parse pairs */ 1679219b2ee8SDavid du Colombier for(i = 0; i < n; i++){ 1680219b2ee8SDavid du Colombier p = strchr(attr[i], '='); 1681219b2ee8SDavid du Colombier if(p == 0) 1682219b2ee8SDavid du Colombier return "bad query"; 1683219b2ee8SDavid du Colombier *p++ = 0; 1684219b2ee8SDavid du Colombier val[i] = p; 1685219b2ee8SDavid du Colombier } 1686219b2ee8SDavid du Colombier 1687219b2ee8SDavid du Colombier /* give dns a chance */ 1688219b2ee8SDavid du Colombier if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){ 16897dd7cddfSDavid du Colombier t = dnsiplookup(val[0], &s); 1690219b2ee8SDavid du Colombier if(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 ndbfree(t); 1697219b2ee8SDavid du Colombier } 1698219b2ee8SDavid du Colombier } 1699219b2ee8SDavid du Colombier 1700219b2ee8SDavid du Colombier /* first pair is always the key. It can't be a '*' */ 1701219b2ee8SDavid du Colombier t = ndbsearch(db, &s, attr[0], val[0]); 1702219b2ee8SDavid du Colombier 1703219b2ee8SDavid du Colombier /* search is the and of all the pairs */ 1704219b2ee8SDavid du Colombier while(t){ 1705219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1706219b2ee8SDavid du Colombier qreply(mf, t); 1707219b2ee8SDavid du Colombier ndbfree(t); 1708219b2ee8SDavid du Colombier return 0; 1709219b2ee8SDavid du Colombier } 1710219b2ee8SDavid du Colombier 1711219b2ee8SDavid du Colombier ndbfree(t); 1712219b2ee8SDavid du Colombier t = ndbsnext(&s, attr[0], val[0]); 1713219b2ee8SDavid du Colombier } 1714219b2ee8SDavid du Colombier 1715219b2ee8SDavid du Colombier return "no match"; 1716219b2ee8SDavid du Colombier } 17177dd7cddfSDavid du Colombier 17187dd7cddfSDavid du Colombier /* 17197dd7cddfSDavid du Colombier * resolve an ip address 17207dd7cddfSDavid du Colombier */ 17217dd7cddfSDavid du Colombier static Ndbtuple* 17227dd7cddfSDavid du Colombier ipresolve(char *attr, char *host) 17237dd7cddfSDavid du Colombier { 17247dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17257dd7cddfSDavid du Colombier 17267dd7cddfSDavid du Colombier t = iplookup(&network[Ntcp], host, "*", 0); 17277dd7cddfSDavid du Colombier for(l = &t; *l != nil; ){ 17287dd7cddfSDavid du Colombier nt = *l; 17297dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0){ 17307dd7cddfSDavid du Colombier *l = nt->entry; 17317dd7cddfSDavid du Colombier nt->entry = nil; 17327dd7cddfSDavid du Colombier ndbfree(nt); 17337dd7cddfSDavid du Colombier continue; 17347dd7cddfSDavid du Colombier } 17357dd7cddfSDavid du Colombier strcpy(nt->attr, attr); 17367dd7cddfSDavid du Colombier l = &nt->entry; 17377dd7cddfSDavid du Colombier } 17387dd7cddfSDavid du Colombier return t; 17397dd7cddfSDavid du Colombier } 17407dd7cddfSDavid du Colombier 17417dd7cddfSDavid du Colombier char* 17427dd7cddfSDavid du Colombier ipinfoquery(Mfile *mf, char **list, int n) 17437dd7cddfSDavid du Colombier { 17447dd7cddfSDavid du Colombier int i, nresolve; 17457dd7cddfSDavid du Colombier int resolve[Maxattr]; 17467dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17477dd7cddfSDavid du Colombier char *attr, *val; 17487dd7cddfSDavid du Colombier 17497dd7cddfSDavid du Colombier /* skip 'ipinfo' */ 17507dd7cddfSDavid du Colombier list++; n--; 17517dd7cddfSDavid du Colombier 17527dd7cddfSDavid du Colombier if(n < 2) 17537dd7cddfSDavid du Colombier return "bad query"; 17547dd7cddfSDavid du Colombier 17557dd7cddfSDavid du Colombier /* get search attribute=value */ 17567dd7cddfSDavid du Colombier attr = *list++; n--; 17577dd7cddfSDavid du Colombier val = strchr(attr, '='); 17587dd7cddfSDavid du Colombier if(val == nil) 17597dd7cddfSDavid du Colombier return "bad query"; 17607dd7cddfSDavid du Colombier *val++ = 0; 17617dd7cddfSDavid du Colombier 17627dd7cddfSDavid du Colombier /* 17637dd7cddfSDavid du Colombier * don't let ndbipinfo resolve the addresses, we're 17647dd7cddfSDavid du Colombier * better at it. 17657dd7cddfSDavid du Colombier */ 17667dd7cddfSDavid du Colombier nresolve = 0; 17677dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 17687dd7cddfSDavid du Colombier if(*list[i] == '@'){ 17697dd7cddfSDavid du Colombier list[i]++; 17707dd7cddfSDavid du Colombier resolve[i] = 1; 17717dd7cddfSDavid du Colombier nresolve++; 17727dd7cddfSDavid du Colombier } else 17737dd7cddfSDavid du Colombier resolve[i] = 0; 17747dd7cddfSDavid du Colombier 17757dd7cddfSDavid du Colombier t = ndbipinfo(db, attr, val, list, n); 17767dd7cddfSDavid du Colombier if(t == nil) 17777dd7cddfSDavid du Colombier return "no match"; 17787dd7cddfSDavid du Colombier 17797dd7cddfSDavid du Colombier if(nresolve != 0){ 17807dd7cddfSDavid du Colombier for(l = &t; *l != nil;){ 17817dd7cddfSDavid du Colombier nt = *l; 17827dd7cddfSDavid du Colombier 17837dd7cddfSDavid du Colombier /* already an address? */ 17847dd7cddfSDavid du Colombier if(strcmp(ipattr(nt->val), "ip") == 0){ 17857dd7cddfSDavid du Colombier l = &(*l)->entry; 17867dd7cddfSDavid du Colombier continue; 17877dd7cddfSDavid du Colombier } 17887dd7cddfSDavid du Colombier 17897dd7cddfSDavid du Colombier /* user wants it resolved? */ 17907dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 17917dd7cddfSDavid du Colombier if(strcmp(list[i], nt->attr) == 0) 17927dd7cddfSDavid du Colombier break; 17937dd7cddfSDavid du Colombier if(i >= n || resolve[i] == 0){ 17947dd7cddfSDavid du Colombier l = &(*l)->entry; 17957dd7cddfSDavid du Colombier continue; 17967dd7cddfSDavid du Colombier } 17977dd7cddfSDavid du Colombier 17987dd7cddfSDavid du Colombier /* resolve address and replace entry */ 17997dd7cddfSDavid du Colombier *l = ipresolve(nt->attr, nt->val); 18007dd7cddfSDavid du Colombier while(*l != nil) 18017dd7cddfSDavid du Colombier l = &(*l)->entry; 18027dd7cddfSDavid du Colombier *l = nt->entry; 18037dd7cddfSDavid du Colombier 18047dd7cddfSDavid du Colombier nt->entry = nil; 18057dd7cddfSDavid du Colombier ndbfree(nt); 18067dd7cddfSDavid du Colombier } 18077dd7cddfSDavid du Colombier } 18087dd7cddfSDavid du Colombier 18097dd7cddfSDavid du Colombier /* make it all one line */ 18107dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 18117dd7cddfSDavid du Colombier if(nt->entry == nil) 18127dd7cddfSDavid du Colombier nt->line = t; 18137dd7cddfSDavid du Colombier else 18147dd7cddfSDavid du Colombier nt->line = nt->entry; 18157dd7cddfSDavid du Colombier } 18167dd7cddfSDavid du Colombier 18177dd7cddfSDavid du Colombier qreply(mf, t); 18187dd7cddfSDavid du Colombier 18197dd7cddfSDavid du Colombier return nil; 18207dd7cddfSDavid du Colombier } 18217dd7cddfSDavid du Colombier 18227dd7cddfSDavid du Colombier void* 18237dd7cddfSDavid du Colombier emalloc(int size) 18247dd7cddfSDavid du Colombier { 18257dd7cddfSDavid du Colombier void *x; 18267dd7cddfSDavid du Colombier 18277dd7cddfSDavid du Colombier x = malloc(size); 18287dd7cddfSDavid du Colombier if(x == nil) 18297dd7cddfSDavid du Colombier abort(); 18307dd7cddfSDavid du Colombier memset(x, 0, size); 18317dd7cddfSDavid du Colombier return x; 18327dd7cddfSDavid du Colombier } 18339a747e4fSDavid du Colombier 18349a747e4fSDavid du Colombier char* 18359a747e4fSDavid du Colombier estrdup(char *s) 18369a747e4fSDavid du Colombier { 18379a747e4fSDavid du Colombier int size; 18389a747e4fSDavid du Colombier char *p; 18399a747e4fSDavid du Colombier 18409a747e4fSDavid du Colombier size = strlen(s)+1; 18419a747e4fSDavid du Colombier p = malloc(size); 18429a747e4fSDavid du Colombier if(p == nil) 18439a747e4fSDavid du Colombier abort(); 18449a747e4fSDavid du Colombier memmove(p, s, size); 18459a747e4fSDavid du Colombier return p; 18469a747e4fSDavid du Colombier } 1847