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"); 983447d6a7dSDavid du Colombier if(p && *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 } 1021b7327ca2SDavid du Colombier for(tt = t; tt != nil; tt = tt->entry){ 1022b7327ca2SDavid du Colombier if(strcmp(tt->attr, "sys") == 0){ 1023b7327ca2SDavid du Colombier mysysname = strdup(tt->val); 102495a264b3SDavid du Colombier break; 102595a264b3SDavid du Colombier } 1026b7327ca2SDavid 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 */ 121280ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 121380ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 121480ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, 0); 121580ee5cbfSDavid du Colombier if(cp){ 121680ee5cbfSDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 121780ee5cbfSDavid du Colombier mf->reply[mf->nreply++] = cp; 121880ee5cbfSDavid du Colombier rv++; 121980ee5cbfSDavid du Colombier } 122080ee5cbfSDavid du Colombier } 122180ee5cbfSDavid du Colombier ndbfree(nt); 122280ee5cbfSDavid du Colombier return rv; 12233e12c5d1SDavid du Colombier } else { 12243e12c5d1SDavid du Colombier /* 1225219b2ee8SDavid du Colombier * not a known network, don't translate host or service 12263e12c5d1SDavid du Colombier */ 122780ee5cbfSDavid du Colombier if(mf->serv) 12287dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s", 122980ee5cbfSDavid du Colombier mntpt, mf->net, mf->host, mf->serv); 1230bd389b36SDavid du Colombier else 12317dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s", 123280ee5cbfSDavid du Colombier mntpt, mf->net, mf->host); 1233219b2ee8SDavid du Colombier mf->reply[0] = strdup(reply); 1234219b2ee8SDavid du Colombier mf->replylen[0] = strlen(reply); 1235219b2ee8SDavid du Colombier mf->nreply = 1; 123680ee5cbfSDavid du Colombier return 1; 12373e12c5d1SDavid du Colombier } 12383e12c5d1SDavid du Colombier } 12393e12c5d1SDavid du Colombier 12403e12c5d1SDavid du Colombier /* 12413e12c5d1SDavid du Colombier * translate an ip service name into a port number. If it's a numeric port 12423e12c5d1SDavid du Colombier * number, look for restricted access. 12433e12c5d1SDavid du Colombier * 12443e12c5d1SDavid du Colombier * the service '*' needs no translation. 12453e12c5d1SDavid du Colombier */ 12463e12c5d1SDavid du Colombier char* 124795a264b3SDavid du Colombier ipserv(Network *np, char *name, char *buf, int blen) 12483e12c5d1SDavid du Colombier { 12493e12c5d1SDavid du Colombier char *p; 12503e12c5d1SDavid du Colombier int alpha = 0; 12513e12c5d1SDavid du Colombier int restr = 0; 125295a264b3SDavid du Colombier char port[10]; 12533e12c5d1SDavid du Colombier Ndbtuple *t, *nt; 12543e12c5d1SDavid du Colombier Ndbs s; 12553e12c5d1SDavid du Colombier 12563e12c5d1SDavid du Colombier /* '*' means any service */ 12573e12c5d1SDavid du Colombier if(strcmp(name, "*")==0){ 12583e12c5d1SDavid du Colombier strcpy(buf, name); 12593e12c5d1SDavid du Colombier return buf; 12603e12c5d1SDavid du Colombier } 12613e12c5d1SDavid du Colombier 12623e12c5d1SDavid du Colombier /* see if it's numeric or symbolic */ 12633e12c5d1SDavid du Colombier port[0] = 0; 12643e12c5d1SDavid du Colombier for(p = name; *p; p++){ 12653e12c5d1SDavid du Colombier if(isdigit(*p)) 12669a747e4fSDavid du Colombier {} 12673e12c5d1SDavid du Colombier else if(isalpha(*p) || *p == '-' || *p == '$') 12683e12c5d1SDavid du Colombier alpha = 1; 12693e12c5d1SDavid du Colombier else 12703e12c5d1SDavid du Colombier return 0; 12713e12c5d1SDavid du Colombier } 127257837e0bSDavid du Colombier t = nil; 127357837e0bSDavid du Colombier p = nil; 12743e12c5d1SDavid du Colombier if(alpha){ 127557837e0bSDavid du Colombier p = ndbgetvalue(db, &s, np->net, name, "port", &t); 1276b7327ca2SDavid du Colombier if(p == nil) 1277b7327ca2SDavid du Colombier return 0; 12783e12c5d1SDavid du Colombier } else { 12793cc1eb97SDavid du Colombier /* look up only for tcp ports < 1024 to get the restricted 12803cc1eb97SDavid du Colombier * attribute 12813cc1eb97SDavid du Colombier */ 12823cc1eb97SDavid du Colombier if(atoi(name) < 1024 && strcmp(np->net, "tcp") == 0) 128357837e0bSDavid du Colombier p = ndbgetvalue(db, &s, "port", name, "port", &t); 128457837e0bSDavid du Colombier if(p == nil) 128557837e0bSDavid du Colombier p = strdup(name); 12863e12c5d1SDavid du Colombier } 12873e12c5d1SDavid du Colombier 12883e12c5d1SDavid du Colombier if(t){ 12893e12c5d1SDavid du Colombier for(nt = t; nt; nt = nt->entry) 12903e12c5d1SDavid du Colombier if(strcmp(nt->attr, "restricted") == 0) 12913e12c5d1SDavid du Colombier restr = 1; 12923e12c5d1SDavid du Colombier ndbfree(t); 12933e12c5d1SDavid du Colombier } 129457837e0bSDavid du Colombier snprint(buf, blen, "%s%s", p, restr ? "!r" : ""); 129557837e0bSDavid du Colombier free(p); 129657837e0bSDavid du Colombier 12973e12c5d1SDavid du Colombier return buf; 12983e12c5d1SDavid du Colombier } 12993e12c5d1SDavid du Colombier 13003e12c5d1SDavid du Colombier /* 13017dd7cddfSDavid du Colombier * lookup an ip attribute 13023e12c5d1SDavid du Colombier */ 13037dd7cddfSDavid du Colombier int 130495a264b3SDavid du Colombier ipattrlookup(Ndb *db, char *ipa, char *attr, char *val, int vlen) 13053e12c5d1SDavid du Colombier { 13063e12c5d1SDavid du Colombier 13077dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13087dd7cddfSDavid du Colombier char *alist[2]; 13093e12c5d1SDavid du Colombier 13107dd7cddfSDavid du Colombier alist[0] = attr; 13117dd7cddfSDavid du Colombier t = ndbipinfo(db, "ip", ipa, alist, 1); 13127dd7cddfSDavid du Colombier if(t == nil) 13137dd7cddfSDavid du Colombier return 0; 13149a747e4fSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 13157dd7cddfSDavid du Colombier if(strcmp(nt->attr, attr) == 0){ 131695a264b3SDavid du Colombier nstrcpy(val, nt->val, vlen); 13173e12c5d1SDavid du Colombier ndbfree(t); 13187dd7cddfSDavid du Colombier return 1; 1319219b2ee8SDavid du Colombier } 13209a747e4fSDavid du Colombier } 13213e12c5d1SDavid du Colombier 13227dd7cddfSDavid du Colombier /* we shouldn't get here */ 13233e12c5d1SDavid du Colombier ndbfree(t); 13247dd7cddfSDavid du Colombier return 0; 13253e12c5d1SDavid du Colombier } 13263e12c5d1SDavid du Colombier 13273e12c5d1SDavid du Colombier /* 13283e12c5d1SDavid du Colombier * lookup (and translate) an ip destination 13293e12c5d1SDavid du Colombier */ 1330219b2ee8SDavid du Colombier Ndbtuple* 1331219b2ee8SDavid du Colombier iplookup(Network *np, char *host, char *serv, int nolookup) 13323e12c5d1SDavid du Colombier { 1333*9dfc0cb2SDavid du Colombier char *attr, *dnsname; 13347dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13353e12c5d1SDavid du Colombier Ndbs s; 133695a264b3SDavid du Colombier char ts[Maxservice]; 133795a264b3SDavid du Colombier char dollar[Maxhost]; 13387dd7cddfSDavid du Colombier uchar ip[IPaddrlen]; 13397dd7cddfSDavid du Colombier uchar net[IPaddrlen]; 13407dd7cddfSDavid du Colombier uchar tnet[IPaddrlen]; 13417dd7cddfSDavid du Colombier Ipifc *ifc; 13429a747e4fSDavid du Colombier Iplifc *lifc; 13433e12c5d1SDavid du Colombier 1344219b2ee8SDavid du Colombier USED(nolookup); 1345219b2ee8SDavid du Colombier 13463e12c5d1SDavid du Colombier /* 13473e12c5d1SDavid du Colombier * start with the service since it's the most likely to fail 13483e12c5d1SDavid du Colombier * and costs the least 13493e12c5d1SDavid du Colombier */ 13507dd7cddfSDavid du Colombier werrstr("can't translate address"); 135195a264b3SDavid du Colombier if(serv==0 || ipserv(np, serv, ts, sizeof ts) == 0){ 1352271b8d73SDavid du Colombier werrstr("can't translate service"); 1353219b2ee8SDavid du Colombier return 0; 13547dd7cddfSDavid du Colombier } 13553e12c5d1SDavid du Colombier 13563e12c5d1SDavid du Colombier /* for dial strings with no host */ 1357219b2ee8SDavid du Colombier if(strcmp(host, "*") == 0) 135895a264b3SDavid du Colombier return ndbnew("ip", "*"); 13593e12c5d1SDavid du Colombier 13603e12c5d1SDavid du Colombier /* 13617dd7cddfSDavid du Colombier * hack till we go v6 :: = 0.0.0.0 13627dd7cddfSDavid du Colombier */ 13637dd7cddfSDavid du Colombier if(strcmp("::", host) == 0) 136495a264b3SDavid du Colombier return ndbnew("ip", "*"); 13657dd7cddfSDavid du Colombier 13667dd7cddfSDavid du Colombier /* 13673e12c5d1SDavid du Colombier * '$' means the rest of the name is an attribute that we 13683e12c5d1SDavid du Colombier * need to search for 13693e12c5d1SDavid du Colombier */ 13703e12c5d1SDavid du Colombier if(*host == '$'){ 137195a264b3SDavid du Colombier if(ipattrlookup(db, ipaddr, host+1, dollar, sizeof dollar)) 13723e12c5d1SDavid du Colombier host = dollar; 13733e12c5d1SDavid du Colombier } 13743e12c5d1SDavid du Colombier 13753e12c5d1SDavid du Colombier /* 13767dd7cddfSDavid du Colombier * turn '[ip address]' into just 'ip address' 13777dd7cddfSDavid du Colombier */ 13787dd7cddfSDavid du Colombier if(*host == '[' && host[strlen(host)-1] == ']'){ 13797dd7cddfSDavid du Colombier host++; 13807dd7cddfSDavid du Colombier host[strlen(host)-1] = 0; 13817dd7cddfSDavid du Colombier } 13827dd7cddfSDavid du Colombier 13837dd7cddfSDavid du Colombier /* 13843e12c5d1SDavid du Colombier * just accept addresses 13853e12c5d1SDavid du Colombier */ 1386219b2ee8SDavid du Colombier attr = ipattr(host); 1387219b2ee8SDavid du Colombier if(strcmp(attr, "ip") == 0) 138895a264b3SDavid du Colombier return ndbnew("ip", host); 13893e12c5d1SDavid du Colombier 13903e12c5d1SDavid du Colombier /* 13913e12c5d1SDavid du Colombier * give the domain name server the first opportunity to 1392bd389b36SDavid du Colombier * resolve domain names. if that fails try the database. 13933e12c5d1SDavid du Colombier */ 13943e12c5d1SDavid du Colombier t = 0; 1395271b8d73SDavid du Colombier werrstr("can't translate address"); 13963e12c5d1SDavid du Colombier if(strcmp(attr, "dom") == 0) 13977dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 13983e12c5d1SDavid du Colombier if(t == 0) 139957837e0bSDavid du Colombier free(ndbgetvalue(db, &s, attr, host, "ip", &t)); 1400*9dfc0cb2SDavid du Colombier if(t == 0){ 1401*9dfc0cb2SDavid du Colombier dnsname = ndbgetvalue(db, &s, attr, host, "dom", nil); 1402*9dfc0cb2SDavid du Colombier if(dnsname){ 1403*9dfc0cb2SDavid du Colombier t = dnsiplookup(dnsname, &s); 1404*9dfc0cb2SDavid du Colombier free(dnsname); 1405*9dfc0cb2SDavid du Colombier } 1406*9dfc0cb2SDavid du Colombier } 14073e12c5d1SDavid du Colombier if(t == 0) 14087dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 14097dd7cddfSDavid du Colombier if(t == 0) 1410219b2ee8SDavid du Colombier return 0; 1411bd389b36SDavid du Colombier 1412bd389b36SDavid du Colombier /* 1413bd389b36SDavid du Colombier * reorder the tuple to have the matched line first and 1414bd389b36SDavid du Colombier * save that in the request structure. 1415bd389b36SDavid du Colombier */ 14167dd7cddfSDavid du Colombier t = reorder(t, s.t); 14177dd7cddfSDavid du Colombier 14187dd7cddfSDavid du Colombier /* 14197dd7cddfSDavid du Colombier * reorder according to our interfaces 14207dd7cddfSDavid du Colombier */ 14217dd7cddfSDavid du Colombier lock(&ipifclock); 14229a747e4fSDavid du Colombier for(ifc = ipifcs; ifc != nil; ifc = ifc->next){ 14239a747e4fSDavid du Colombier for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ 14249a747e4fSDavid du Colombier maskip(lifc->ip, lifc->mask, net); 14257dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry){ 14267dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0) 14277dd7cddfSDavid du Colombier continue; 14287dd7cddfSDavid du Colombier parseip(ip, nt->val); 14299a747e4fSDavid du Colombier maskip(ip, lifc->mask, tnet); 14307dd7cddfSDavid du Colombier if(memcmp(net, tnet, IPaddrlen) == 0){ 14317dd7cddfSDavid du Colombier t = reorder(t, nt); 14327dd7cddfSDavid du Colombier unlock(&ipifclock); 14337dd7cddfSDavid du Colombier return t; 14347dd7cddfSDavid du Colombier } 14357dd7cddfSDavid du Colombier } 14367dd7cddfSDavid du Colombier } 14379a747e4fSDavid du Colombier } 14387dd7cddfSDavid du Colombier unlock(&ipifclock); 14397dd7cddfSDavid du Colombier 14407dd7cddfSDavid du Colombier return t; 14413e12c5d1SDavid du Colombier } 14423e12c5d1SDavid du Colombier 14433e12c5d1SDavid du Colombier /* 14443e12c5d1SDavid du Colombier * translate an ip address 14453e12c5d1SDavid du Colombier */ 1446219b2ee8SDavid du Colombier char* 144780ee5cbfSDavid du Colombier iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack) 14483e12c5d1SDavid du Colombier { 144995a264b3SDavid du Colombier char ts[Maxservice]; 1450219b2ee8SDavid du Colombier char reply[Maxreply]; 145195a264b3SDavid du Colombier char x[Maxservice]; 14523e12c5d1SDavid du Colombier 1453219b2ee8SDavid du Colombier if(strcmp(t->attr, "ip") != 0) 14543e12c5d1SDavid du Colombier return 0; 1455219b2ee8SDavid du Colombier 145695a264b3SDavid du Colombier if(serv == 0 || ipserv(np, serv, ts, sizeof ts) == 0){ 1457271b8d73SDavid du Colombier werrstr("can't translate service"); 1458219b2ee8SDavid du Colombier return 0; 1459271b8d73SDavid du Colombier } 14607dd7cddfSDavid du Colombier if(rem != nil) 14617dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 14627dd7cddfSDavid du Colombier else 14637dd7cddfSDavid du Colombier *x = 0; 146480ee5cbfSDavid du Colombier 1465219b2ee8SDavid du Colombier if(*t->val == '*') 14667dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", 14677dd7cddfSDavid du Colombier mntpt, np->net, ts, x); 1468219b2ee8SDavid du Colombier else 146980ee5cbfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s%s", 147080ee5cbfSDavid du Colombier mntpt, np->net, t->val, ts, x, hack?"!fasttimeout":""); 1471219b2ee8SDavid du Colombier 1472219b2ee8SDavid du Colombier return strdup(reply); 14733e12c5d1SDavid du Colombier } 14743e12c5d1SDavid du Colombier 1475219b2ee8SDavid du Colombier /* 1476219b2ee8SDavid du Colombier * lookup a telephone number 1477219b2ee8SDavid du Colombier */ 1478219b2ee8SDavid du Colombier Ndbtuple* 1479219b2ee8SDavid du Colombier telcolookup(Network *np, char *host, char *serv, int nolookup) 1480219b2ee8SDavid du Colombier { 1481219b2ee8SDavid du Colombier Ndbtuple *t; 1482219b2ee8SDavid du Colombier Ndbs s; 1483219b2ee8SDavid du Colombier 1484219b2ee8SDavid du Colombier USED(np, nolookup, serv); 1485219b2ee8SDavid du Colombier 1486271b8d73SDavid du Colombier werrstr("can't translate address"); 148757837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "sys", host, "telco", &t)); 1488219b2ee8SDavid du Colombier if(t == 0) 148995a264b3SDavid du Colombier return ndbnew("telco", host); 1490219b2ee8SDavid du Colombier 1491219b2ee8SDavid du Colombier return reorder(t, s.t); 1492219b2ee8SDavid du Colombier } 1493219b2ee8SDavid du Colombier 1494219b2ee8SDavid du Colombier /* 1495219b2ee8SDavid du Colombier * translate a telephone address 1496219b2ee8SDavid du Colombier */ 1497219b2ee8SDavid du Colombier char* 149880ee5cbfSDavid du Colombier telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int) 1499219b2ee8SDavid du Colombier { 1500219b2ee8SDavid du Colombier char reply[Maxreply]; 150195a264b3SDavid du Colombier char x[Maxservice]; 1502219b2ee8SDavid du Colombier 1503219b2ee8SDavid du Colombier if(strcmp(t->attr, "telco") != 0) 1504219b2ee8SDavid du Colombier return 0; 1505219b2ee8SDavid du Colombier 15067dd7cddfSDavid du Colombier if(rem != nil) 15077dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 1508219b2ee8SDavid du Colombier else 15097dd7cddfSDavid du Colombier *x = 0; 15107dd7cddfSDavid du Colombier if(serv) 15117dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s", mntpt, np->net, 15127dd7cddfSDavid du Colombier t->val, serv, x); 15137dd7cddfSDavid du Colombier else 15147dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net, 15157dd7cddfSDavid du Colombier t->val, x); 1516219b2ee8SDavid du Colombier return strdup(reply); 1517219b2ee8SDavid du Colombier } 15183e12c5d1SDavid du Colombier 15193e12c5d1SDavid du Colombier /* 15203e12c5d1SDavid du Colombier * reorder the tuple to put x's line first in the entry 15213e12c5d1SDavid du Colombier */ 15223e12c5d1SDavid du Colombier Ndbtuple* 15233e12c5d1SDavid du Colombier reorder(Ndbtuple *t, Ndbtuple *x) 15243e12c5d1SDavid du Colombier { 15253e12c5d1SDavid du Colombier Ndbtuple *nt; 15263e12c5d1SDavid du Colombier Ndbtuple *line; 15273e12c5d1SDavid du Colombier 1528219b2ee8SDavid du Colombier /* find start of this entry's line */ 1529219b2ee8SDavid du Colombier for(line = x; line->entry == line->line; line = line->line) 15303e12c5d1SDavid du Colombier ; 1531219b2ee8SDavid du Colombier line = line->line; 1532219b2ee8SDavid du Colombier if(line == t) 1533219b2ee8SDavid du Colombier return t; /* already the first line */ 15343e12c5d1SDavid du Colombier 1535219b2ee8SDavid du Colombier /* remove this line and everything after it from the entry */ 1536219b2ee8SDavid du Colombier for(nt = t; nt->entry != line; nt = nt->entry) 1537219b2ee8SDavid du Colombier ; 1538219b2ee8SDavid du Colombier nt->entry = 0; 15393e12c5d1SDavid du Colombier 1540219b2ee8SDavid du Colombier /* make that the start of the entry */ 1541219b2ee8SDavid du Colombier for(nt = line; nt->entry; nt = nt->entry) 1542219b2ee8SDavid du Colombier ; 15433e12c5d1SDavid du Colombier nt->entry = t; 15443e12c5d1SDavid du Colombier return line; 15453e12c5d1SDavid du Colombier } 15463e12c5d1SDavid du Colombier 15473e12c5d1SDavid du Colombier /* 15483e12c5d1SDavid du Colombier * create a slave process to handle a request to avoid one request blocking 15497dd7cddfSDavid du Colombier * another. parent returns to job loop. 15503e12c5d1SDavid du Colombier */ 15513e12c5d1SDavid du Colombier void 15523e12c5d1SDavid du Colombier slave(void) 15533e12c5d1SDavid du Colombier { 15543e12c5d1SDavid du Colombier if(*isslave) 15553e12c5d1SDavid du Colombier return; /* we're already a slave process */ 15563e12c5d1SDavid du Colombier 15573e12c5d1SDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 15583e12c5d1SDavid du Colombier case -1: 15593e12c5d1SDavid du Colombier break; 15603e12c5d1SDavid du Colombier case 0: 1561219b2ee8SDavid du Colombier if(debug) 1562219b2ee8SDavid du Colombier syslog(0, logfile, "slave %d", getpid()); 15633e12c5d1SDavid du Colombier *isslave = 1; 15643e12c5d1SDavid du Colombier break; 15653e12c5d1SDavid du Colombier default: 15663e12c5d1SDavid du Colombier longjmp(masterjmp, 1); 15673e12c5d1SDavid du Colombier } 15683e12c5d1SDavid du Colombier 1569219b2ee8SDavid du Colombier } 1570219b2ee8SDavid du Colombier 15713e12c5d1SDavid du Colombier /* 15723e12c5d1SDavid du Colombier * call the dns process and have it try to translate a name 15733e12c5d1SDavid du Colombier */ 15743e12c5d1SDavid du Colombier Ndbtuple* 15757dd7cddfSDavid du Colombier dnsiplookup(char *host, Ndbs *s) 15763e12c5d1SDavid du Colombier { 157795a264b3SDavid du Colombier char buf[Maxreply]; 15787dd7cddfSDavid du Colombier Ndbtuple *t; 15793e12c5d1SDavid du Colombier 1580bd389b36SDavid du Colombier unlock(&dblock); 1581bd389b36SDavid du Colombier 15823e12c5d1SDavid du Colombier /* save the name before starting a slave */ 15837dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s", host); 15843e12c5d1SDavid du Colombier 15853e12c5d1SDavid du Colombier slave(); 15863e12c5d1SDavid du Colombier 15877dd7cddfSDavid du Colombier if(strcmp(ipattr(buf), "ip") == 0) 15887dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ptr"); 15897dd7cddfSDavid du Colombier else 15907dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ip"); 15913e12c5d1SDavid du Colombier s->t = t; 15927dd7cddfSDavid du Colombier 1593271b8d73SDavid du Colombier if(t == nil){ 1594271b8d73SDavid du Colombier rerrstr(buf, sizeof buf); 1595271b8d73SDavid du Colombier if(strstr(buf, "exist")) 1596271b8d73SDavid du Colombier werrstr("can't translate address: %s", buf); 1597271b8d73SDavid du Colombier else if(strstr(buf, "dns failure")) 1598271b8d73SDavid du Colombier werrstr("temporary problem: %s", buf); 1599271b8d73SDavid du Colombier } 1600271b8d73SDavid du Colombier 1601bd389b36SDavid du Colombier lock(&dblock); 16023e12c5d1SDavid du Colombier return t; 16033e12c5d1SDavid du Colombier } 1604219b2ee8SDavid du Colombier 1605219b2ee8SDavid du Colombier int 1606219b2ee8SDavid du Colombier qmatch(Ndbtuple *t, char **attr, char **val, int n) 1607219b2ee8SDavid du Colombier { 1608219b2ee8SDavid du Colombier int i, found; 1609219b2ee8SDavid du Colombier Ndbtuple *nt; 1610219b2ee8SDavid du Colombier 1611219b2ee8SDavid du Colombier for(i = 1; i < n; i++){ 1612219b2ee8SDavid du Colombier found = 0; 1613219b2ee8SDavid du Colombier for(nt = t; nt; nt = nt->entry) 1614219b2ee8SDavid du Colombier if(strcmp(attr[i], nt->attr) == 0) 1615219b2ee8SDavid du Colombier if(strcmp(val[i], "*") == 0 1616219b2ee8SDavid du Colombier || strcmp(val[i], nt->val) == 0){ 1617219b2ee8SDavid du Colombier found = 1; 1618219b2ee8SDavid du Colombier break; 1619219b2ee8SDavid du Colombier } 1620219b2ee8SDavid du Colombier if(found == 0) 1621219b2ee8SDavid du Colombier break; 1622219b2ee8SDavid du Colombier } 1623219b2ee8SDavid du Colombier return i == n; 1624219b2ee8SDavid du Colombier } 1625219b2ee8SDavid du Colombier 1626219b2ee8SDavid du Colombier void 1627219b2ee8SDavid du Colombier qreply(Mfile *mf, Ndbtuple *t) 1628219b2ee8SDavid du Colombier { 1629219b2ee8SDavid du Colombier Ndbtuple *nt; 163095a264b3SDavid du Colombier String *s; 1631219b2ee8SDavid du Colombier 163295a264b3SDavid du Colombier s = s_new(); 1633219b2ee8SDavid du Colombier for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){ 163495a264b3SDavid du Colombier s_append(s, nt->attr); 163595a264b3SDavid du Colombier s_append(s, "="); 163695a264b3SDavid du Colombier s_append(s, nt->val); 163795a264b3SDavid du Colombier 163895a264b3SDavid du Colombier if(nt->line != nt->entry){ 163995a264b3SDavid du Colombier mf->replylen[mf->nreply] = s_len(s); 164095a264b3SDavid du Colombier mf->reply[mf->nreply++] = strdup(s_to_c(s)); 164195a264b3SDavid du Colombier s_restart(s); 1642219b2ee8SDavid du Colombier } else 164395a264b3SDavid du Colombier s_append(s, " "); 1644219b2ee8SDavid du Colombier } 164595a264b3SDavid du Colombier s_free(s); 1646219b2ee8SDavid du Colombier } 1647219b2ee8SDavid du Colombier 16487dd7cddfSDavid du Colombier enum 16497dd7cddfSDavid du Colombier { 16507dd7cddfSDavid du Colombier Maxattr= 32, 16517dd7cddfSDavid du Colombier }; 16527dd7cddfSDavid du Colombier 1653219b2ee8SDavid du Colombier /* 16547dd7cddfSDavid du Colombier * generic query lookup. The query is of one of the following 16557dd7cddfSDavid du Colombier * forms: 16567dd7cddfSDavid du Colombier * 16577dd7cddfSDavid du Colombier * attr1=val1 attr2=val2 attr3=val3 ... 16587dd7cddfSDavid du Colombier * 16597dd7cddfSDavid du Colombier * returns the matching tuple 16607dd7cddfSDavid du Colombier * 16617dd7cddfSDavid du Colombier * ipinfo attr=val attr1 attr2 attr3 ... 16627dd7cddfSDavid du Colombier * 16637dd7cddfSDavid du Colombier * is like ipinfo and returns the attr{1-n} 16647dd7cddfSDavid du Colombier * associated with the ip address. 1665219b2ee8SDavid du Colombier */ 1666219b2ee8SDavid du Colombier char* 1667219b2ee8SDavid du Colombier genquery(Mfile *mf, char *query) 1668219b2ee8SDavid du Colombier { 1669219b2ee8SDavid du Colombier int i, n; 1670219b2ee8SDavid du Colombier char *p; 16717dd7cddfSDavid du Colombier char *attr[Maxattr]; 16727dd7cddfSDavid du Colombier char *val[Maxattr]; 1673219b2ee8SDavid du Colombier Ndbtuple *t; 1674219b2ee8SDavid du Colombier Ndbs s; 1675219b2ee8SDavid du Colombier 16767dd7cddfSDavid du Colombier n = getfields(query, attr, 32, 1, " "); 1677219b2ee8SDavid du Colombier if(n == 0) 1678219b2ee8SDavid du Colombier return "bad query"; 1679219b2ee8SDavid du Colombier 16807dd7cddfSDavid du Colombier if(strcmp(attr[0], "ipinfo") == 0) 16817dd7cddfSDavid du Colombier return ipinfoquery(mf, attr, n); 16827dd7cddfSDavid du Colombier 1683219b2ee8SDavid du Colombier /* parse pairs */ 1684219b2ee8SDavid du Colombier for(i = 0; i < n; i++){ 1685219b2ee8SDavid du Colombier p = strchr(attr[i], '='); 1686219b2ee8SDavid du Colombier if(p == 0) 1687219b2ee8SDavid du Colombier return "bad query"; 1688219b2ee8SDavid du Colombier *p++ = 0; 1689219b2ee8SDavid du Colombier val[i] = p; 1690219b2ee8SDavid du Colombier } 1691219b2ee8SDavid du Colombier 1692219b2ee8SDavid du Colombier /* give dns a chance */ 1693219b2ee8SDavid du Colombier if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){ 16947dd7cddfSDavid du Colombier t = dnsiplookup(val[0], &s); 1695219b2ee8SDavid du Colombier if(t){ 1696219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1697219b2ee8SDavid du Colombier qreply(mf, t); 1698219b2ee8SDavid du Colombier ndbfree(t); 1699219b2ee8SDavid du Colombier return 0; 1700219b2ee8SDavid du Colombier } 1701219b2ee8SDavid du Colombier ndbfree(t); 1702219b2ee8SDavid du Colombier } 1703219b2ee8SDavid du Colombier } 1704219b2ee8SDavid du Colombier 1705219b2ee8SDavid du Colombier /* first pair is always the key. It can't be a '*' */ 1706219b2ee8SDavid du Colombier t = ndbsearch(db, &s, attr[0], val[0]); 1707219b2ee8SDavid du Colombier 1708219b2ee8SDavid du Colombier /* search is the and of all the pairs */ 1709219b2ee8SDavid du Colombier while(t){ 1710219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1711219b2ee8SDavid du Colombier qreply(mf, t); 1712219b2ee8SDavid du Colombier ndbfree(t); 1713219b2ee8SDavid du Colombier return 0; 1714219b2ee8SDavid du Colombier } 1715219b2ee8SDavid du Colombier 1716219b2ee8SDavid du Colombier ndbfree(t); 1717219b2ee8SDavid du Colombier t = ndbsnext(&s, attr[0], val[0]); 1718219b2ee8SDavid du Colombier } 1719219b2ee8SDavid du Colombier 1720219b2ee8SDavid du Colombier return "no match"; 1721219b2ee8SDavid du Colombier } 17227dd7cddfSDavid du Colombier 17237dd7cddfSDavid du Colombier /* 17247dd7cddfSDavid du Colombier * resolve an ip address 17257dd7cddfSDavid du Colombier */ 17267dd7cddfSDavid du Colombier static Ndbtuple* 17277dd7cddfSDavid du Colombier ipresolve(char *attr, char *host) 17287dd7cddfSDavid du Colombier { 17297dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17307dd7cddfSDavid du Colombier 17317dd7cddfSDavid du Colombier t = iplookup(&network[Ntcp], host, "*", 0); 17327dd7cddfSDavid du Colombier for(l = &t; *l != nil; ){ 17337dd7cddfSDavid du Colombier nt = *l; 17347dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0){ 17357dd7cddfSDavid du Colombier *l = nt->entry; 17367dd7cddfSDavid du Colombier nt->entry = nil; 17377dd7cddfSDavid du Colombier ndbfree(nt); 17387dd7cddfSDavid du Colombier continue; 17397dd7cddfSDavid du Colombier } 17407dd7cddfSDavid du Colombier strcpy(nt->attr, attr); 17417dd7cddfSDavid du Colombier l = &nt->entry; 17427dd7cddfSDavid du Colombier } 17437dd7cddfSDavid du Colombier return t; 17447dd7cddfSDavid du Colombier } 17457dd7cddfSDavid du Colombier 17467dd7cddfSDavid du Colombier char* 17477dd7cddfSDavid du Colombier ipinfoquery(Mfile *mf, char **list, int n) 17487dd7cddfSDavid du Colombier { 17497dd7cddfSDavid du Colombier int i, nresolve; 17507dd7cddfSDavid du Colombier int resolve[Maxattr]; 17517dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17527dd7cddfSDavid du Colombier char *attr, *val; 17537dd7cddfSDavid du Colombier 17547dd7cddfSDavid du Colombier /* skip 'ipinfo' */ 17557dd7cddfSDavid du Colombier list++; n--; 17567dd7cddfSDavid du Colombier 17578a2c5ad0SDavid du Colombier if(n < 1) 17587dd7cddfSDavid du Colombier return "bad query"; 17597dd7cddfSDavid du Colombier 17608a2c5ad0SDavid du Colombier /* get search attribute=value, or assume ip=myipaddr */ 17618a2c5ad0SDavid du Colombier attr = *list; 17628a2c5ad0SDavid du Colombier if((val = strchr(attr, '=')) != nil){ 17637dd7cddfSDavid du Colombier *val++ = 0; 17648a2c5ad0SDavid du Colombier list++; 17658a2c5ad0SDavid du Colombier n--; 17668a2c5ad0SDavid du Colombier }else{ 17678a2c5ad0SDavid du Colombier attr = "ip"; 17688a2c5ad0SDavid du Colombier val = ipaddr; 17698a2c5ad0SDavid du Colombier } 17708a2c5ad0SDavid du Colombier 17718a2c5ad0SDavid du Colombier if(n < 1) 17728a2c5ad0SDavid du Colombier return "bad query"; 17737dd7cddfSDavid du Colombier 17747dd7cddfSDavid du Colombier /* 17757dd7cddfSDavid du Colombier * don't let ndbipinfo resolve the addresses, we're 17767dd7cddfSDavid du Colombier * better at it. 17777dd7cddfSDavid du Colombier */ 17787dd7cddfSDavid du Colombier nresolve = 0; 17797dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 17807dd7cddfSDavid du Colombier if(*list[i] == '@'){ 17817dd7cddfSDavid du Colombier list[i]++; 17827dd7cddfSDavid du Colombier resolve[i] = 1; 17837dd7cddfSDavid du Colombier nresolve++; 17847dd7cddfSDavid du Colombier } else 17857dd7cddfSDavid du Colombier resolve[i] = 0; 17867dd7cddfSDavid du Colombier 17877dd7cddfSDavid du Colombier t = ndbipinfo(db, attr, val, list, n); 17887dd7cddfSDavid du Colombier if(t == nil) 17897dd7cddfSDavid du Colombier return "no match"; 17907dd7cddfSDavid du Colombier 17917dd7cddfSDavid du Colombier if(nresolve != 0){ 17927dd7cddfSDavid du Colombier for(l = &t; *l != nil;){ 17937dd7cddfSDavid du Colombier nt = *l; 17947dd7cddfSDavid du Colombier 17957dd7cddfSDavid du Colombier /* already an address? */ 17967dd7cddfSDavid du Colombier if(strcmp(ipattr(nt->val), "ip") == 0){ 17977dd7cddfSDavid du Colombier l = &(*l)->entry; 17987dd7cddfSDavid du Colombier continue; 17997dd7cddfSDavid du Colombier } 18007dd7cddfSDavid du Colombier 18017dd7cddfSDavid du Colombier /* user wants it resolved? */ 18027dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 18037dd7cddfSDavid du Colombier if(strcmp(list[i], nt->attr) == 0) 18047dd7cddfSDavid du Colombier break; 18057dd7cddfSDavid du Colombier if(i >= n || resolve[i] == 0){ 18067dd7cddfSDavid du Colombier l = &(*l)->entry; 18077dd7cddfSDavid du Colombier continue; 18087dd7cddfSDavid du Colombier } 18097dd7cddfSDavid du Colombier 18107dd7cddfSDavid du Colombier /* resolve address and replace entry */ 18117dd7cddfSDavid du Colombier *l = ipresolve(nt->attr, nt->val); 18127dd7cddfSDavid du Colombier while(*l != nil) 18137dd7cddfSDavid du Colombier l = &(*l)->entry; 18147dd7cddfSDavid du Colombier *l = nt->entry; 18157dd7cddfSDavid du Colombier 18167dd7cddfSDavid du Colombier nt->entry = nil; 18177dd7cddfSDavid du Colombier ndbfree(nt); 18187dd7cddfSDavid du Colombier } 18197dd7cddfSDavid du Colombier } 18207dd7cddfSDavid du Colombier 18217dd7cddfSDavid du Colombier /* make it all one line */ 18227dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 18237dd7cddfSDavid du Colombier if(nt->entry == nil) 18247dd7cddfSDavid du Colombier nt->line = t; 18257dd7cddfSDavid du Colombier else 18267dd7cddfSDavid du Colombier nt->line = nt->entry; 18277dd7cddfSDavid du Colombier } 18287dd7cddfSDavid du Colombier 18297dd7cddfSDavid du Colombier qreply(mf, t); 18307dd7cddfSDavid du Colombier 18317dd7cddfSDavid du Colombier return nil; 18327dd7cddfSDavid du Colombier } 18337dd7cddfSDavid du Colombier 18347dd7cddfSDavid du Colombier void* 18357dd7cddfSDavid du Colombier emalloc(int size) 18367dd7cddfSDavid du Colombier { 18377dd7cddfSDavid du Colombier void *x; 18387dd7cddfSDavid du Colombier 18397dd7cddfSDavid du Colombier x = malloc(size); 18407dd7cddfSDavid du Colombier if(x == nil) 18417dd7cddfSDavid du Colombier abort(); 18427dd7cddfSDavid du Colombier memset(x, 0, size); 18437dd7cddfSDavid du Colombier return x; 18447dd7cddfSDavid du Colombier } 18459a747e4fSDavid du Colombier 18469a747e4fSDavid du Colombier char* 18479a747e4fSDavid du Colombier estrdup(char *s) 18489a747e4fSDavid du Colombier { 18499a747e4fSDavid du Colombier int size; 18509a747e4fSDavid du Colombier char *p; 18519a747e4fSDavid du Colombier 18529a747e4fSDavid du Colombier size = strlen(s)+1; 18539a747e4fSDavid du Colombier p = malloc(size); 18549a747e4fSDavid du Colombier if(p == nil) 18559a747e4fSDavid du Colombier abort(); 18569a747e4fSDavid du Colombier memmove(p, s, size); 18579a747e4fSDavid du Colombier return p; 18589a747e4fSDavid du Colombier } 1859