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 65*244672c5SDavid du Colombier /* 66*244672c5SDavid du Colombier * active requests 67*244672c5SDavid 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 Ntcp, 154*244672c5SDavid du Colombier // Nilfast, 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 /* 164*244672c5SDavid du Colombier * net doesn't apply to (r)udp, icmp(v6), or telco (for speed). 165*244672c5SDavid du Colombier * there should be no gaps in this table, as a zero entry terminates 166*244672c5SDavid du Colombier * the "net!" search. 16780ee5cbfSDavid du Colombier */ 16880ee5cbfSDavid du Colombier Network network[] = { 16980ee5cbfSDavid du Colombier [Ntcp] { "tcp", iplookup, iptrans, 0, 0 }, 170*244672c5SDavid du Colombier // [Nilfast] { "il", iplookup, iptrans, 0, 1 }, 17180ee5cbfSDavid du Colombier [Nil] { "il", iplookup, iptrans, 0, 0 }, 17280ee5cbfSDavid du Colombier [Nudp] { "udp", iplookup, iptrans, 1, 0 }, 17380ee5cbfSDavid du Colombier [Nicmp] { "icmp", iplookup, iptrans, 1, 0 }, 17495a264b3SDavid du Colombier [Nicmpv6] { "icmpv6", iplookup, iptrans, 1, 0 }, 17580ee5cbfSDavid du Colombier [Nrudp] { "rudp", iplookup, iptrans, 1, 0 }, 17680ee5cbfSDavid du Colombier [Ntelco] { "telco", telcolookup, telcotrans, 1, 0 }, 17780ee5cbfSDavid du Colombier { 0 }, 17880ee5cbfSDavid du Colombier }; 17980ee5cbfSDavid du Colombier 18080ee5cbfSDavid du Colombier Lock ipifclock; 18180ee5cbfSDavid du Colombier Ipifc *ipifcs; 18280ee5cbfSDavid du Colombier 18395a264b3SDavid du Colombier char eaddr[16]; /* ascii ethernet address */ 18495a264b3SDavid du Colombier char ipaddr[64]; /* ascii internet address */ 18580ee5cbfSDavid du Colombier uchar ipa[IPaddrlen]; /* binary internet address */ 18695a264b3SDavid du Colombier char *mysysname; 18780ee5cbfSDavid du Colombier 18880ee5cbfSDavid du Colombier Network *netlist; /* networks ordered by preference */ 18980ee5cbfSDavid du Colombier Network *last; 19080ee5cbfSDavid du Colombier 19195a264b3SDavid du Colombier static void 19295a264b3SDavid du Colombier nstrcpy(char *to, char *from, int len) 19395a264b3SDavid du Colombier { 19495a264b3SDavid du Colombier strncpy(to, from, len); 19595a264b3SDavid du Colombier to[len-1] = 0; 19695a264b3SDavid du Colombier } 19795a264b3SDavid du Colombier 1987dd7cddfSDavid du Colombier void 1997dd7cddfSDavid du Colombier usage(void) 2007dd7cddfSDavid du Colombier { 2017dd7cddfSDavid du Colombier fprint(2, "usage: %s [-d] [-f ndb-file] [-x netmtpt] [-n]\n", argv0); 2027dd7cddfSDavid du Colombier exits("usage"); 2037dd7cddfSDavid du Colombier } 204219b2ee8SDavid du Colombier 2053e12c5d1SDavid du Colombier void 2063e12c5d1SDavid du Colombier main(int argc, char *argv[]) 2073e12c5d1SDavid du Colombier { 2087dd7cddfSDavid du Colombier char servefile[Maxpath]; 209219b2ee8SDavid du Colombier int justsetname; 2107dd7cddfSDavid du Colombier char *p; 2117dd7cddfSDavid du Colombier char ext[Maxpath]; 2123e12c5d1SDavid du Colombier 213219b2ee8SDavid du Colombier justsetname = 0; 2147dd7cddfSDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), nil); 2157dd7cddfSDavid du Colombier ext[0] = 0; 2163e12c5d1SDavid du Colombier ARGBEGIN{ 2173e12c5d1SDavid du Colombier case 'd': 2183e12c5d1SDavid du Colombier debug = 1; 2193e12c5d1SDavid du Colombier break; 220bd389b36SDavid du Colombier case 'f': 2217dd7cddfSDavid du Colombier p = ARGF(); 2227dd7cddfSDavid du Colombier if(p == nil) 2237dd7cddfSDavid du Colombier usage(); 2247dd7cddfSDavid du Colombier dbfile = p; 2257dd7cddfSDavid du Colombier break; 2267dd7cddfSDavid du Colombier case 'x': 2277dd7cddfSDavid du Colombier p = ARGF(); 2287dd7cddfSDavid du Colombier if(p == nil) 2297dd7cddfSDavid du Colombier usage(); 2307dd7cddfSDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), p); 2317dd7cddfSDavid du Colombier setext(ext, sizeof(ext), mntpt); 232bd389b36SDavid du Colombier break; 233219b2ee8SDavid du Colombier case 'n': 234219b2ee8SDavid du Colombier justsetname = 1; 235219b2ee8SDavid du Colombier break; 2363e12c5d1SDavid du Colombier }ARGEND 2373e12c5d1SDavid du Colombier USED(argc); 2383e12c5d1SDavid du Colombier USED(argv); 2393e12c5d1SDavid du Colombier 2407dd7cddfSDavid du Colombier rfork(RFREND|RFNOTEG); 2417dd7cddfSDavid du Colombier 2427dd7cddfSDavid du Colombier snprint(servefile, sizeof(servefile), "#s/cs%s", ext); 2437dd7cddfSDavid du Colombier snprint(netndb, sizeof(netndb), "%s/ndb", mntpt); 2447dd7cddfSDavid du Colombier unmount(servefile, mntpt); 2457dd7cddfSDavid du Colombier remove(servefile); 2467dd7cddfSDavid du Colombier 2479a747e4fSDavid du Colombier fmtinstall('E', eipfmt); 2489a747e4fSDavid du Colombier fmtinstall('I', eipfmt); 2499a747e4fSDavid du Colombier fmtinstall('M', eipfmt); 2509a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 2517dd7cddfSDavid du Colombier 2527dd7cddfSDavid du Colombier ndbinit(); 2537dd7cddfSDavid du Colombier netinit(0); 2547dd7cddfSDavid du Colombier 2557dd7cddfSDavid du Colombier if(!justsetname){ 2567dd7cddfSDavid du Colombier mountinit(servefile, mntpt); 2577dd7cddfSDavid du Colombier io(); 2587dd7cddfSDavid du Colombier } 259219b2ee8SDavid du Colombier exits(0); 260219b2ee8SDavid du Colombier } 261219b2ee8SDavid du Colombier 2627dd7cddfSDavid du Colombier /* 2637dd7cddfSDavid du Colombier * if a mount point is specified, set the cs extention to be the mount point 2647dd7cddfSDavid du Colombier * with '_'s replacing '/'s 2657dd7cddfSDavid du Colombier */ 2667dd7cddfSDavid du Colombier void 2677dd7cddfSDavid du Colombier setext(char *ext, int n, char *p) 2687dd7cddfSDavid du Colombier { 2697dd7cddfSDavid du Colombier int i, c; 2703e12c5d1SDavid du Colombier 2717dd7cddfSDavid du Colombier n--; 2727dd7cddfSDavid du Colombier for(i = 0; i < n; i++){ 2737dd7cddfSDavid du Colombier c = p[i]; 2747dd7cddfSDavid du Colombier if(c == 0) 2757dd7cddfSDavid du Colombier break; 2767dd7cddfSDavid du Colombier if(c == '/') 2777dd7cddfSDavid du Colombier c = '_'; 2787dd7cddfSDavid du Colombier ext[i] = c; 2797dd7cddfSDavid du Colombier } 2807dd7cddfSDavid du Colombier ext[i] = 0; 2813e12c5d1SDavid du Colombier } 2823e12c5d1SDavid du Colombier 2833e12c5d1SDavid du Colombier void 2847dd7cddfSDavid du Colombier mountinit(char *service, char *mntpt) 2853e12c5d1SDavid du Colombier { 2863e12c5d1SDavid du Colombier int f; 2873e12c5d1SDavid du Colombier int p[2]; 2883e12c5d1SDavid du Colombier char buf[32]; 2893e12c5d1SDavid du Colombier 2903e12c5d1SDavid du Colombier if(pipe(p) < 0) 2913e12c5d1SDavid du Colombier error("pipe failed"); 292a9f680aeSDavid du Colombier 293a9f680aeSDavid du Colombier /* 294a9f680aeSDavid du Colombier * make a /srv/cs 295a9f680aeSDavid du Colombier */ 296a9f680aeSDavid du Colombier f = create(service, OWRITE|ORCLOSE, 0666); 297a9f680aeSDavid du Colombier if(f < 0) 298a9f680aeSDavid du Colombier error(service); 299a9f680aeSDavid du Colombier snprint(buf, sizeof(buf), "%d", p[1]); 300a9f680aeSDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf)) 301a9f680aeSDavid du Colombier error("write /srv/cs"); 302a9f680aeSDavid du Colombier 303219b2ee8SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG)){ 3043e12c5d1SDavid du Colombier case 0: 305219b2ee8SDavid du Colombier close(p[1]); 3063e12c5d1SDavid du Colombier break; 3073e12c5d1SDavid du Colombier case -1: 3083e12c5d1SDavid du Colombier error("fork failed\n"); 3093e12c5d1SDavid du Colombier default: 3103e12c5d1SDavid du Colombier /* 3113e12c5d1SDavid du Colombier * put ourselves into the file system 3123e12c5d1SDavid du Colombier */ 313219b2ee8SDavid du Colombier close(p[0]); 3149a747e4fSDavid du Colombier if(mount(p[1], -1, mntpt, MAFTER, "") < 0) 3153e12c5d1SDavid du Colombier error("mount failed\n"); 316219b2ee8SDavid du Colombier _exits(0); 3173e12c5d1SDavid du Colombier } 3183e12c5d1SDavid du Colombier mfd[0] = mfd[1] = p[0]; 3193e12c5d1SDavid du Colombier } 3203e12c5d1SDavid du Colombier 3217dd7cddfSDavid du Colombier void 3227dd7cddfSDavid du Colombier ndbinit(void) 3237dd7cddfSDavid du Colombier { 3247dd7cddfSDavid du Colombier db = ndbopen(dbfile); 3257dd7cddfSDavid du Colombier if(db == nil) 3267dd7cddfSDavid du Colombier error("can't open network database"); 3277dd7cddfSDavid du Colombier 3287dd7cddfSDavid du Colombier netdb = ndbopen(netndb); 3297dd7cddfSDavid du Colombier if(netdb != nil){ 3307dd7cddfSDavid du Colombier netdb->nohash = 1; 3317dd7cddfSDavid du Colombier db = ndbcat(netdb, db); 3327dd7cddfSDavid du Colombier } 3337dd7cddfSDavid du Colombier } 3347dd7cddfSDavid du Colombier 3353e12c5d1SDavid du Colombier Mfile* 3363e12c5d1SDavid du Colombier newfid(int fid) 3373e12c5d1SDavid du Colombier { 338219b2ee8SDavid du Colombier Mlist *f, *ff; 3393e12c5d1SDavid du Colombier Mfile *mf; 3403e12c5d1SDavid du Colombier 341219b2ee8SDavid du Colombier ff = 0; 342219b2ee8SDavid du Colombier for(f = mlist; f; f = f->next) 343219b2ee8SDavid du Colombier if(f->mf.busy && f->mf.fid == fid) 344219b2ee8SDavid du Colombier return &f->mf; 345219b2ee8SDavid du Colombier else if(!ff && !f->mf.busy) 346219b2ee8SDavid du Colombier ff = f; 347219b2ee8SDavid du Colombier if(ff == 0){ 3487dd7cddfSDavid du Colombier ff = emalloc(sizeof *f); 349219b2ee8SDavid du Colombier ff->next = mlist; 350219b2ee8SDavid du Colombier mlist = ff; 3513e12c5d1SDavid du Colombier } 352219b2ee8SDavid du Colombier mf = &ff->mf; 353219b2ee8SDavid du Colombier memset(mf, 0, sizeof *mf); 3543e12c5d1SDavid du Colombier mf->fid = fid; 3553e12c5d1SDavid du Colombier return mf; 3563e12c5d1SDavid du Colombier } 3573e12c5d1SDavid du Colombier 3587dd7cddfSDavid du Colombier Job* 3597dd7cddfSDavid du Colombier newjob(void) 3607dd7cddfSDavid du Colombier { 3617dd7cddfSDavid du Colombier Job *job; 3627dd7cddfSDavid du Colombier 3637dd7cddfSDavid du Colombier job = mallocz(sizeof(Job), 1); 3647dd7cddfSDavid du Colombier lock(&joblock); 3657dd7cddfSDavid du Colombier job->next = joblist; 3667dd7cddfSDavid du Colombier joblist = job; 3677dd7cddfSDavid du Colombier job->request.tag = -1; 3687dd7cddfSDavid du Colombier unlock(&joblock); 3697dd7cddfSDavid du Colombier return job; 3707dd7cddfSDavid du Colombier } 3717dd7cddfSDavid du Colombier 3727dd7cddfSDavid du Colombier void 3737dd7cddfSDavid du Colombier freejob(Job *job) 3747dd7cddfSDavid du Colombier { 3757dd7cddfSDavid du Colombier Job **l; 3767dd7cddfSDavid du Colombier 3777dd7cddfSDavid du Colombier lock(&joblock); 3787dd7cddfSDavid du Colombier for(l = &joblist; *l; l = &(*l)->next){ 3797dd7cddfSDavid du Colombier if((*l) == job){ 3807dd7cddfSDavid du Colombier *l = job->next; 3817dd7cddfSDavid du Colombier free(job); 3827dd7cddfSDavid du Colombier break; 3837dd7cddfSDavid du Colombier } 3847dd7cddfSDavid du Colombier } 3857dd7cddfSDavid du Colombier unlock(&joblock); 3867dd7cddfSDavid du Colombier } 3877dd7cddfSDavid du Colombier 3887dd7cddfSDavid du Colombier void 3897dd7cddfSDavid du Colombier flushjob(int tag) 3907dd7cddfSDavid du Colombier { 3917dd7cddfSDavid du Colombier Job *job; 3927dd7cddfSDavid du Colombier 3937dd7cddfSDavid du Colombier lock(&joblock); 3947dd7cddfSDavid du Colombier for(job = joblist; job; job = job->next){ 3957dd7cddfSDavid du Colombier if(job->request.tag == tag && job->request.type != Tflush){ 3967dd7cddfSDavid du Colombier job->flushed = 1; 3977dd7cddfSDavid du Colombier break; 3987dd7cddfSDavid du Colombier } 3997dd7cddfSDavid du Colombier } 4007dd7cddfSDavid du Colombier unlock(&joblock); 4017dd7cddfSDavid du Colombier } 4027dd7cddfSDavid du Colombier 4033e12c5d1SDavid du Colombier void 4043e12c5d1SDavid du Colombier io(void) 4053e12c5d1SDavid du Colombier { 4063e12c5d1SDavid du Colombier long n; 4073e12c5d1SDavid du Colombier Mfile *mf; 4083e12c5d1SDavid du Colombier int slaveflag; 4099a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 4107dd7cddfSDavid du Colombier Job *job; 4113e12c5d1SDavid du Colombier 4123e12c5d1SDavid du Colombier /* 4133e12c5d1SDavid du Colombier * if we ask dns to fulfill requests, 4143e12c5d1SDavid du Colombier * a slave process is created to wait for replies. The 4159a747e4fSDavid du Colombier * master process returns immediately via a longjmp 4163e12c5d1SDavid du Colombier * through 'masterjmp'. 4173e12c5d1SDavid du Colombier * 4183e12c5d1SDavid du Colombier * *isslave is a pointer into the call stack to a variable 4193e12c5d1SDavid du Colombier * that tells whether or not the current process is a slave. 4203e12c5d1SDavid du Colombier */ 4213e12c5d1SDavid du Colombier slaveflag = 0; /* init slave variable */ 4223e12c5d1SDavid du Colombier isslave = &slaveflag; 4233e12c5d1SDavid du Colombier setjmp(masterjmp); 4243e12c5d1SDavid du Colombier 4253e12c5d1SDavid du Colombier for(;;){ 4269a747e4fSDavid du Colombier n = read9pmsg(mfd[0], mdata, sizeof mdata); 4273e12c5d1SDavid du Colombier if(n<=0) 4283e12c5d1SDavid du Colombier error("mount read"); 4297dd7cddfSDavid du Colombier job = newjob(); 4309a747e4fSDavid du Colombier if(convM2S(mdata, n, &job->request) != n){ 431271b8d73SDavid du Colombier syslog(1, logfile, "format error %ux %ux %ux %ux %ux", 432271b8d73SDavid du Colombier mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]); 4337dd7cddfSDavid du Colombier freejob(job); 4343e12c5d1SDavid du Colombier continue; 4353e12c5d1SDavid du Colombier } 436bd389b36SDavid du Colombier lock(&dblock); 4377dd7cddfSDavid du Colombier mf = newfid(job->request.fid); 438219b2ee8SDavid du Colombier if(debug) 4397dd7cddfSDavid du Colombier syslog(0, logfile, "%F", &job->request); 4403e12c5d1SDavid du Colombier 4413e12c5d1SDavid du Colombier 4427dd7cddfSDavid du Colombier switch(job->request.type){ 4433e12c5d1SDavid du Colombier default: 4447dd7cddfSDavid du Colombier syslog(1, logfile, "unknown request type %d", job->request.type); 4453e12c5d1SDavid du Colombier break; 4469a747e4fSDavid du Colombier case Tversion: 4479a747e4fSDavid du Colombier rversion(job); 4483e12c5d1SDavid du Colombier break; 4499a747e4fSDavid du Colombier case Tauth: 4509a747e4fSDavid du Colombier rauth(job); 4513e12c5d1SDavid du Colombier break; 4523e12c5d1SDavid du Colombier case Tflush: 4537dd7cddfSDavid du Colombier rflush(job); 4543e12c5d1SDavid du Colombier break; 4553e12c5d1SDavid du Colombier case Tattach: 4567dd7cddfSDavid du Colombier rattach(job, mf); 4573e12c5d1SDavid du Colombier break; 4583e12c5d1SDavid du Colombier case Twalk: 4597dd7cddfSDavid du Colombier rwalk(job, mf); 4603e12c5d1SDavid du Colombier break; 4613e12c5d1SDavid du Colombier case Topen: 4627dd7cddfSDavid du Colombier ropen(job, mf); 4633e12c5d1SDavid du Colombier break; 4643e12c5d1SDavid du Colombier case Tcreate: 4657dd7cddfSDavid du Colombier rcreate(job, mf); 4663e12c5d1SDavid du Colombier break; 4673e12c5d1SDavid du Colombier case Tread: 4687dd7cddfSDavid du Colombier rread(job, mf); 4693e12c5d1SDavid du Colombier break; 4703e12c5d1SDavid du Colombier case Twrite: 4717dd7cddfSDavid du Colombier rwrite(job, mf); 4723e12c5d1SDavid du Colombier break; 4733e12c5d1SDavid du Colombier case Tclunk: 4747dd7cddfSDavid du Colombier rclunk(job, mf); 4753e12c5d1SDavid du Colombier break; 4763e12c5d1SDavid du Colombier case Tremove: 4777dd7cddfSDavid du Colombier rremove(job, mf); 4783e12c5d1SDavid du Colombier break; 4793e12c5d1SDavid du Colombier case Tstat: 4807dd7cddfSDavid du Colombier rstat(job, mf); 4813e12c5d1SDavid du Colombier break; 4823e12c5d1SDavid du Colombier case Twstat: 4837dd7cddfSDavid du Colombier rwstat(job, mf); 4843e12c5d1SDavid du Colombier break; 4853e12c5d1SDavid du Colombier } 486bd389b36SDavid du Colombier unlock(&dblock); 4877dd7cddfSDavid du Colombier 4887dd7cddfSDavid du Colombier freejob(job); 4897dd7cddfSDavid du Colombier 4903e12c5d1SDavid du Colombier /* 4913e12c5d1SDavid du Colombier * slave processes die after replying 4923e12c5d1SDavid du Colombier */ 493219b2ee8SDavid du Colombier if(*isslave){ 494219b2ee8SDavid du Colombier if(debug) 495219b2ee8SDavid du Colombier syslog(0, logfile, "slave death %d", getpid()); 4963e12c5d1SDavid du Colombier _exits(0); 4973e12c5d1SDavid du Colombier } 4983e12c5d1SDavid du Colombier } 499219b2ee8SDavid du Colombier } 500219b2ee8SDavid du Colombier 501219b2ee8SDavid du Colombier void 5029a747e4fSDavid du Colombier rversion(Job *job) 503219b2ee8SDavid du Colombier { 5049a747e4fSDavid du Colombier if(job->request.msize > IOHDRSZ + Maxfdata) 5059a747e4fSDavid du Colombier job->reply.msize = IOHDRSZ + Maxfdata; 5069a747e4fSDavid du Colombier else 5079a747e4fSDavid du Colombier job->reply.msize = job->request.msize; 5089a747e4fSDavid du Colombier if(strncmp(job->request.version, "9P2000", 6) != 0) 5099a747e4fSDavid du Colombier sendmsg(job, "unknown 9P version"); 5109a747e4fSDavid du Colombier else{ 5119a747e4fSDavid du Colombier job->reply.version = "9P2000"; 5127dd7cddfSDavid du Colombier sendmsg(job, 0); 513219b2ee8SDavid du Colombier } 5149a747e4fSDavid du Colombier } 5153e12c5d1SDavid du Colombier 5163e12c5d1SDavid du Colombier void 5179a747e4fSDavid du Colombier rauth(Job *job) 5183e12c5d1SDavid du Colombier { 5193ff48bf5SDavid du Colombier sendmsg(job, "cs: authentication not required"); 5207dd7cddfSDavid du Colombier } 5217dd7cddfSDavid du Colombier 5227dd7cddfSDavid du Colombier /* 5237dd7cddfSDavid du Colombier * don't flush till all the slaves are done 5247dd7cddfSDavid du Colombier */ 5257dd7cddfSDavid du Colombier void 5267dd7cddfSDavid du Colombier rflush(Job *job) 5277dd7cddfSDavid du Colombier { 5287dd7cddfSDavid du Colombier flushjob(job->request.oldtag); 5297dd7cddfSDavid du Colombier sendmsg(job, 0); 5303e12c5d1SDavid du Colombier } 5313e12c5d1SDavid du Colombier 5323e12c5d1SDavid du Colombier void 5337dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf) 5343e12c5d1SDavid du Colombier { 5353e12c5d1SDavid du Colombier if(mf->busy == 0){ 5363e12c5d1SDavid du Colombier mf->busy = 1; 5379a747e4fSDavid du Colombier mf->user = estrdup(job->request.uname); 5383e12c5d1SDavid du Colombier } 5393e12c5d1SDavid du Colombier mf->qid.vers = vers++; 5409a747e4fSDavid du Colombier mf->qid.type = QTDIR; 5419a747e4fSDavid du Colombier mf->qid.path = 0LL; 5427dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 5437dd7cddfSDavid du Colombier sendmsg(job, 0); 5443e12c5d1SDavid du Colombier } 5453e12c5d1SDavid du Colombier 5463e12c5d1SDavid du Colombier 5473e12c5d1SDavid du Colombier char* 5487dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf) 5493e12c5d1SDavid du Colombier { 5503e12c5d1SDavid du Colombier char *err; 5519a747e4fSDavid du Colombier char **elems; 5529a747e4fSDavid du Colombier int nelems; 5539a747e4fSDavid du Colombier int i; 5549a747e4fSDavid du Colombier Mfile *nmf; 5559a747e4fSDavid du Colombier Qid qid; 5563e12c5d1SDavid du Colombier 5573e12c5d1SDavid du Colombier err = 0; 5589a747e4fSDavid du Colombier nmf = nil; 5599a747e4fSDavid du Colombier elems = job->request.wname; 5609a747e4fSDavid du Colombier nelems = job->request.nwname; 5619a747e4fSDavid du Colombier job->reply.nwqid = 0; 5629a747e4fSDavid du Colombier 5639a747e4fSDavid du Colombier if(job->request.newfid != job->request.fid){ 5649a747e4fSDavid du Colombier /* clone fid */ 5659a747e4fSDavid du Colombier nmf = newfid(job->request.newfid); 5669a747e4fSDavid du Colombier if(nmf->busy){ 5679a747e4fSDavid du Colombier nmf = nil; 5689a747e4fSDavid du Colombier err = "clone to used channel"; 5699a747e4fSDavid du Colombier goto send; 5709a747e4fSDavid du Colombier } 5719a747e4fSDavid du Colombier *nmf = *mf; 5729a747e4fSDavid du Colombier nmf->user = estrdup(mf->user); 5739a747e4fSDavid du Colombier nmf->fid = job->request.newfid; 5749a747e4fSDavid du Colombier nmf->qid.vers = vers++; 5759a747e4fSDavid du Colombier mf = nmf; 5769a747e4fSDavid du Colombier } 5779a747e4fSDavid du Colombier /* else nmf will be nil */ 5789a747e4fSDavid du Colombier 5799a747e4fSDavid du Colombier qid = mf->qid; 5809a747e4fSDavid du Colombier if(nelems > 0){ 5819a747e4fSDavid du Colombier /* walk fid */ 5829a747e4fSDavid du Colombier for(i=0; i<nelems && i<MAXWELEM; i++){ 5839a747e4fSDavid du Colombier if((qid.type & QTDIR) == 0){ 5843e12c5d1SDavid du Colombier err = "not a directory"; 5859a747e4fSDavid du Colombier break; 5863e12c5d1SDavid du Colombier } 5879a747e4fSDavid du Colombier if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){ 5889a747e4fSDavid du Colombier qid.type = QTDIR; 5899a747e4fSDavid du Colombier qid.path = Qdir; 5909a747e4fSDavid du Colombier Found: 5919a747e4fSDavid du Colombier job->reply.wqid[i] = qid; 5929a747e4fSDavid du Colombier job->reply.nwqid++; 5939a747e4fSDavid du Colombier continue; 5943e12c5d1SDavid du Colombier } 5959a747e4fSDavid du Colombier if(strcmp(elems[i], "cs") == 0){ 5969a747e4fSDavid du Colombier qid.type = QTFILE; 5979a747e4fSDavid du Colombier qid.path = Qcs; 5989a747e4fSDavid du Colombier goto Found; 5993e12c5d1SDavid du Colombier } 6009a747e4fSDavid du Colombier err = "file does not exist"; 6019a747e4fSDavid du Colombier break; 6029a747e4fSDavid du Colombier } 6039a747e4fSDavid du Colombier } 6049a747e4fSDavid du Colombier 6053e12c5d1SDavid du Colombier send: 6069a747e4fSDavid du Colombier if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)){ 607a9f680aeSDavid du Colombier cleanmf(nmf); 608a9f680aeSDavid du Colombier free(nmf->user); 609a9f680aeSDavid du Colombier nmf->user = 0; 6109a747e4fSDavid du Colombier nmf->busy = 0; 6119a747e4fSDavid du Colombier nmf->fid = 0; 6129a747e4fSDavid du Colombier } 6139a747e4fSDavid du Colombier if(err == nil) 6149a747e4fSDavid du Colombier mf->qid = qid; 6157dd7cddfSDavid du Colombier sendmsg(job, err); 6163e12c5d1SDavid du Colombier return err; 6173e12c5d1SDavid du Colombier } 6183e12c5d1SDavid du Colombier 6193e12c5d1SDavid du Colombier void 6207dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf) 6213e12c5d1SDavid du Colombier { 6223e12c5d1SDavid du Colombier int mode; 6233e12c5d1SDavid du Colombier char *err; 6243e12c5d1SDavid du Colombier 6253e12c5d1SDavid du Colombier err = 0; 6267dd7cddfSDavid du Colombier mode = job->request.mode; 6279a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6283e12c5d1SDavid du Colombier if(mode) 6293e12c5d1SDavid du Colombier err = "permission denied"; 6309a747e4fSDavid du Colombier } 6317dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 6329a747e4fSDavid du Colombier job->reply.iounit = 0; 6337dd7cddfSDavid du Colombier sendmsg(job, err); 6343e12c5d1SDavid du Colombier } 6353e12c5d1SDavid du Colombier 6363e12c5d1SDavid du Colombier void 6377dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf) 6383e12c5d1SDavid du Colombier { 6393e12c5d1SDavid du Colombier USED(mf); 6407dd7cddfSDavid du Colombier sendmsg(job, "creation permission denied"); 6413e12c5d1SDavid du Colombier } 6423e12c5d1SDavid du Colombier 6433e12c5d1SDavid du Colombier void 6447dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf) 6453e12c5d1SDavid du Colombier { 646219b2ee8SDavid du Colombier int i, n, cnt; 647219b2ee8SDavid du Colombier long off, toff, clock; 6483e12c5d1SDavid du Colombier Dir dir; 6499a747e4fSDavid du Colombier uchar buf[Maxfdata]; 6503e12c5d1SDavid du Colombier char *err; 6513e12c5d1SDavid du Colombier 6523e12c5d1SDavid du Colombier n = 0; 6533e12c5d1SDavid du Colombier err = 0; 6547dd7cddfSDavid du Colombier off = job->request.offset; 6557dd7cddfSDavid du Colombier cnt = job->request.count; 6569a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6573e12c5d1SDavid du Colombier clock = time(0); 6583e12c5d1SDavid du Colombier if(off == 0){ 6599a747e4fSDavid du Colombier dir.name = "cs"; 6609a747e4fSDavid du Colombier dir.qid.type = QTFILE; 6613e12c5d1SDavid du Colombier dir.qid.vers = vers; 6623e12c5d1SDavid du Colombier dir.qid.path = Qcs; 6633e12c5d1SDavid du Colombier dir.mode = 0666; 6643e12c5d1SDavid du Colombier dir.length = 0; 6659a747e4fSDavid du Colombier dir.uid = mf->user; 6669a747e4fSDavid du Colombier dir.gid = mf->user; 6679a747e4fSDavid du Colombier dir.muid = mf->user; 6683e12c5d1SDavid du Colombier dir.atime = clock; /* wrong */ 6693e12c5d1SDavid du Colombier dir.mtime = clock; /* wrong */ 6709a747e4fSDavid du Colombier n = convD2M(&dir, buf, sizeof buf); 6713e12c5d1SDavid du Colombier } 6729a747e4fSDavid du Colombier job->reply.data = (char*)buf; 6733e12c5d1SDavid du Colombier } else { 67480ee5cbfSDavid du Colombier for(;;){ 67580ee5cbfSDavid du Colombier /* look for an answer at the right offset */ 676219b2ee8SDavid du Colombier toff = 0; 677219b2ee8SDavid du Colombier for(i = 0; mf->reply[i] && i < mf->nreply; i++){ 678219b2ee8SDavid du Colombier n = mf->replylen[i]; 679219b2ee8SDavid du Colombier if(off < toff + n) 680219b2ee8SDavid du Colombier break; 681219b2ee8SDavid du Colombier toff += n; 6823e12c5d1SDavid du Colombier } 68380ee5cbfSDavid du Colombier if(i < mf->nreply) 68480ee5cbfSDavid du Colombier break; /* got something to return */ 68580ee5cbfSDavid du Colombier 68680ee5cbfSDavid du Colombier /* try looking up more answers */ 68780ee5cbfSDavid du Colombier if(lookup(mf) == 0){ 68880ee5cbfSDavid du Colombier /* no more */ 689219b2ee8SDavid du Colombier n = 0; 690219b2ee8SDavid du Colombier goto send; 691219b2ee8SDavid du Colombier } 69280ee5cbfSDavid du Colombier } 69380ee5cbfSDavid du Colombier 69480ee5cbfSDavid du Colombier /* give back a single reply (or part of one) */ 6957dd7cddfSDavid du Colombier job->reply.data = mf->reply[i] + (off - toff); 696219b2ee8SDavid du Colombier if(cnt > toff - off + n) 697219b2ee8SDavid du Colombier n = toff - off + n; 698219b2ee8SDavid du Colombier else 699219b2ee8SDavid du Colombier n = cnt; 7003e12c5d1SDavid du Colombier } 7013e12c5d1SDavid du Colombier send: 7027dd7cddfSDavid du Colombier job->reply.count = n; 7037dd7cddfSDavid du Colombier sendmsg(job, err); 7047dd7cddfSDavid du Colombier } 70580ee5cbfSDavid du Colombier void 70680ee5cbfSDavid du Colombier cleanmf(Mfile *mf) 7077dd7cddfSDavid du Colombier { 7087dd7cddfSDavid du Colombier int i; 7097dd7cddfSDavid du Colombier 7109a747e4fSDavid du Colombier if(mf->net != nil){ 71180ee5cbfSDavid du Colombier free(mf->net); 71280ee5cbfSDavid du Colombier mf->net = nil; 7139a747e4fSDavid du Colombier } 7149a747e4fSDavid du Colombier if(mf->host != nil){ 71580ee5cbfSDavid du Colombier free(mf->host); 71680ee5cbfSDavid du Colombier mf->host = nil; 7179a747e4fSDavid du Colombier } 7189a747e4fSDavid du Colombier if(mf->serv != nil){ 71980ee5cbfSDavid du Colombier free(mf->serv); 72080ee5cbfSDavid du Colombier mf->serv = nil; 7219a747e4fSDavid du Colombier } 7229a747e4fSDavid du Colombier if(mf->rem != nil){ 72380ee5cbfSDavid du Colombier free(mf->rem); 72480ee5cbfSDavid du Colombier mf->rem = nil; 7259a747e4fSDavid du Colombier } 72680ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++){ 72780ee5cbfSDavid du Colombier free(mf->reply[i]); 72880ee5cbfSDavid du Colombier mf->reply[i] = nil; 72980ee5cbfSDavid du Colombier mf->replylen[i] = 0; 7307dd7cddfSDavid du Colombier } 73180ee5cbfSDavid du Colombier mf->nreply = 0; 73280ee5cbfSDavid du Colombier mf->nextnet = netlist; 7333e12c5d1SDavid du Colombier } 7343e12c5d1SDavid du Colombier 7353e12c5d1SDavid du Colombier void 7367dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf) 7373e12c5d1SDavid du Colombier { 7383e12c5d1SDavid du Colombier int cnt, n; 73980ee5cbfSDavid du Colombier char *err; 7407dd7cddfSDavid du Colombier char *field[4]; 741271b8d73SDavid du Colombier char curerr[64]; 7423e12c5d1SDavid du Colombier 7433e12c5d1SDavid du Colombier err = 0; 7447dd7cddfSDavid du Colombier cnt = job->request.count; 7459a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 7463e12c5d1SDavid du Colombier err = "can't write directory"; 7473e12c5d1SDavid du Colombier goto send; 7483e12c5d1SDavid du Colombier } 7493e12c5d1SDavid du Colombier if(cnt >= Maxrequest){ 7503e12c5d1SDavid du Colombier err = "request too long"; 7513e12c5d1SDavid du Colombier goto send; 7523e12c5d1SDavid du Colombier } 7537dd7cddfSDavid du Colombier job->request.data[cnt] = 0; 7543e12c5d1SDavid du Colombier 7553e12c5d1SDavid du Colombier /* 756219b2ee8SDavid du Colombier * toggle debugging 757219b2ee8SDavid du Colombier */ 7587dd7cddfSDavid du Colombier if(strncmp(job->request.data, "debug", 5)==0){ 759219b2ee8SDavid du Colombier debug ^= 1; 760219b2ee8SDavid du Colombier syslog(1, logfile, "debug %d", debug); 761219b2ee8SDavid du Colombier goto send; 762219b2ee8SDavid du Colombier } 763219b2ee8SDavid du Colombier 764219b2ee8SDavid du Colombier /* 7657dd7cddfSDavid du Colombier * toggle debugging 7667dd7cddfSDavid du Colombier */ 7677dd7cddfSDavid du Colombier if(strncmp(job->request.data, "paranoia", 8)==0){ 7687dd7cddfSDavid du Colombier paranoia ^= 1; 7697dd7cddfSDavid du Colombier syslog(1, logfile, "paranoia %d", paranoia); 7707dd7cddfSDavid du Colombier goto send; 7717dd7cddfSDavid du Colombier } 7727dd7cddfSDavid du Colombier 7737dd7cddfSDavid du Colombier /* 7743e12c5d1SDavid du Colombier * add networks to the default list 7753e12c5d1SDavid du Colombier */ 7767dd7cddfSDavid du Colombier if(strncmp(job->request.data, "add ", 4)==0){ 7777dd7cddfSDavid du Colombier if(job->request.data[cnt-1] == '\n') 7787dd7cddfSDavid du Colombier job->request.data[cnt-1] = 0; 7797dd7cddfSDavid du Colombier netadd(job->request.data+4); 7807dd7cddfSDavid du Colombier readipinterfaces(); 7817dd7cddfSDavid du Colombier goto send; 7827dd7cddfSDavid du Colombier } 7837dd7cddfSDavid du Colombier 7847dd7cddfSDavid du Colombier /* 7857dd7cddfSDavid du Colombier * refresh all state 7867dd7cddfSDavid du Colombier */ 7877dd7cddfSDavid du Colombier if(strncmp(job->request.data, "refresh", 7)==0){ 7887dd7cddfSDavid du Colombier netinit(1); 7893e12c5d1SDavid du Colombier goto send; 7903e12c5d1SDavid du Colombier } 7913e12c5d1SDavid du Colombier 79280ee5cbfSDavid du Colombier /* start transaction with a clean slate */ 79380ee5cbfSDavid du Colombier cleanmf(mf); 79480ee5cbfSDavid du Colombier 7953e12c5d1SDavid du Colombier /* 796219b2ee8SDavid du Colombier * look for a general query 797219b2ee8SDavid du Colombier */ 7987dd7cddfSDavid du Colombier if(*job->request.data == '!'){ 7997dd7cddfSDavid du Colombier err = genquery(mf, job->request.data+1); 800219b2ee8SDavid du Colombier goto send; 801219b2ee8SDavid du Colombier } 802219b2ee8SDavid du Colombier 8037dd7cddfSDavid du Colombier if(debug) 8047dd7cddfSDavid du Colombier syslog(0, logfile, "write %s", job->request.data); 8057dd7cddfSDavid du Colombier if(paranoia) 8067dd7cddfSDavid du Colombier syslog(0, paranoiafile, "write %s by %s", job->request.data, mf->user); 8077dd7cddfSDavid du Colombier 808219b2ee8SDavid du Colombier /* 8093e12c5d1SDavid du Colombier * break up name 8103e12c5d1SDavid du Colombier */ 8117dd7cddfSDavid du Colombier n = getfields(job->request.data, field, 4, 1, "!"); 8123e12c5d1SDavid du Colombier switch(n){ 8133e12c5d1SDavid du Colombier case 1: 81480ee5cbfSDavid du Colombier mf->net = strdup("net"); 81580ee5cbfSDavid du Colombier mf->host = strdup(field[0]); 8167dd7cddfSDavid du Colombier break; 8177dd7cddfSDavid du Colombier case 4: 81880ee5cbfSDavid du Colombier mf->rem = strdup(field[3]); 81980ee5cbfSDavid du Colombier /* fall through */ 82080ee5cbfSDavid du Colombier case 3: 82180ee5cbfSDavid du Colombier mf->serv = strdup(field[2]); 82280ee5cbfSDavid du Colombier /* fall through */ 82380ee5cbfSDavid du Colombier case 2: 82480ee5cbfSDavid du Colombier mf->host = strdup(field[1]); 82580ee5cbfSDavid du Colombier mf->net = strdup(field[0]); 8263e12c5d1SDavid du Colombier break; 8273e12c5d1SDavid du Colombier } 8283e12c5d1SDavid du Colombier 82980ee5cbfSDavid du Colombier /* 83080ee5cbfSDavid du Colombier * do the first net worth of lookup 83180ee5cbfSDavid du Colombier */ 832271b8d73SDavid du Colombier if(lookup(mf) == 0){ 833271b8d73SDavid du Colombier rerrstr(curerr, sizeof curerr); 834271b8d73SDavid du Colombier err = curerr; 835271b8d73SDavid du Colombier } 8363e12c5d1SDavid du Colombier send: 8377dd7cddfSDavid du Colombier job->reply.count = cnt; 8387dd7cddfSDavid du Colombier sendmsg(job, err); 8393e12c5d1SDavid du Colombier } 8403e12c5d1SDavid du Colombier 8413e12c5d1SDavid du Colombier void 8427dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf) 8433e12c5d1SDavid du Colombier { 84480ee5cbfSDavid du Colombier cleanmf(mf); 845a9f680aeSDavid du Colombier free(mf->user); 846a9f680aeSDavid du Colombier mf->user = 0; 8473e12c5d1SDavid du Colombier mf->busy = 0; 8483e12c5d1SDavid du Colombier mf->fid = 0; 8497dd7cddfSDavid du Colombier sendmsg(job, 0); 8503e12c5d1SDavid du Colombier } 8513e12c5d1SDavid du Colombier 8523e12c5d1SDavid du Colombier void 8537dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf) 8543e12c5d1SDavid du Colombier { 8553e12c5d1SDavid du Colombier USED(mf); 8567dd7cddfSDavid du Colombier sendmsg(job, "remove permission denied"); 8573e12c5d1SDavid du Colombier } 8583e12c5d1SDavid du Colombier 8593e12c5d1SDavid du Colombier void 8607dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf) 8613e12c5d1SDavid du Colombier { 8623e12c5d1SDavid du Colombier Dir dir; 8639a747e4fSDavid du Colombier uchar buf[IOHDRSZ+Maxfdata]; 8643e12c5d1SDavid du Colombier 8659a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 8669a747e4fSDavid du Colombier dir.name = "."; 8679a747e4fSDavid du Colombier dir.mode = DMDIR|0555; 868219b2ee8SDavid du Colombier } else { 8699a747e4fSDavid du Colombier dir.name = "cs"; 8703e12c5d1SDavid du Colombier dir.mode = 0666; 871219b2ee8SDavid du Colombier } 872219b2ee8SDavid du Colombier dir.qid = mf->qid; 8733e12c5d1SDavid du Colombier dir.length = 0; 8749a747e4fSDavid du Colombier dir.uid = mf->user; 8759a747e4fSDavid du Colombier dir.gid = mf->user; 8769a747e4fSDavid du Colombier dir.muid = mf->user; 8773e12c5d1SDavid du Colombier dir.atime = dir.mtime = time(0); 8789a747e4fSDavid du Colombier job->reply.nstat = convD2M(&dir, buf, sizeof buf); 8799a747e4fSDavid du Colombier job->reply.stat = buf; 8807dd7cddfSDavid du Colombier sendmsg(job, 0); 8813e12c5d1SDavid du Colombier } 8823e12c5d1SDavid du Colombier 8833e12c5d1SDavid du Colombier void 8847dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf) 8853e12c5d1SDavid du Colombier { 8863e12c5d1SDavid du Colombier USED(mf); 8877dd7cddfSDavid du Colombier sendmsg(job, "wstat permission denied"); 8883e12c5d1SDavid du Colombier } 8893e12c5d1SDavid du Colombier 8903e12c5d1SDavid du Colombier void 8917dd7cddfSDavid du Colombier sendmsg(Job *job, char *err) 8923e12c5d1SDavid du Colombier { 8933e12c5d1SDavid du Colombier int n; 8949a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 8959a747e4fSDavid du Colombier char ename[ERRMAX]; 8963e12c5d1SDavid du Colombier 8973e12c5d1SDavid du Colombier if(err){ 8987dd7cddfSDavid du Colombier job->reply.type = Rerror; 8999a747e4fSDavid du Colombier snprint(ename, sizeof(ename), "cs: %s", err); 9009a747e4fSDavid du Colombier job->reply.ename = ename; 9013e12c5d1SDavid du Colombier }else{ 9027dd7cddfSDavid du Colombier job->reply.type = job->request.type+1; 9033e12c5d1SDavid du Colombier } 9047dd7cddfSDavid du Colombier job->reply.tag = job->request.tag; 9059a747e4fSDavid du Colombier n = convS2M(&job->reply, mdata, sizeof mdata); 906219b2ee8SDavid du Colombier if(n == 0){ 9077dd7cddfSDavid du Colombier syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply); 908219b2ee8SDavid du Colombier abort(); 909219b2ee8SDavid du Colombier } 9107dd7cddfSDavid du Colombier lock(&joblock); 9117dd7cddfSDavid du Colombier if(job->flushed == 0) 9129a747e4fSDavid du Colombier if(write(mfd[1], mdata, n)!=n) 9133e12c5d1SDavid du Colombier error("mount write"); 9147dd7cddfSDavid du Colombier unlock(&joblock); 915219b2ee8SDavid du Colombier if(debug) 9167dd7cddfSDavid du Colombier syslog(0, logfile, "%F %d", &job->reply, n); 9173e12c5d1SDavid du Colombier } 9183e12c5d1SDavid du Colombier 9193e12c5d1SDavid du Colombier void 9203e12c5d1SDavid du Colombier error(char *s) 9213e12c5d1SDavid du Colombier { 922bd389b36SDavid du Colombier syslog(1, "cs", "%s: %r", s); 923bd389b36SDavid du Colombier _exits(0); 9243e12c5d1SDavid du Colombier } 9253e12c5d1SDavid du Colombier 9267dd7cddfSDavid du Colombier static int 9277dd7cddfSDavid du Colombier isvalidip(uchar *ip) 9287dd7cddfSDavid du Colombier { 9297dd7cddfSDavid du Colombier return ipcmp(ip, IPnoaddr) != 0 && ipcmp(ip, v4prefix) != 0; 9307dd7cddfSDavid du Colombier } 9313e12c5d1SDavid du Colombier 9320103620dSDavid du Colombier static uchar loopbacknet[IPaddrlen] = { 9330103620dSDavid du Colombier 0, 0, 0, 0, 9340103620dSDavid du Colombier 0, 0, 0, 0, 9350103620dSDavid du Colombier 0, 0, 0xff, 0xff, 9360103620dSDavid du Colombier 127, 0, 0, 0 9370103620dSDavid du Colombier }; 9380103620dSDavid du Colombier static uchar loopbackmask[IPaddrlen] = { 9390103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9400103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9410103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9420103620dSDavid du Colombier 0xff, 0, 0, 0 9430103620dSDavid du Colombier }; 9440103620dSDavid du Colombier 9457dd7cddfSDavid du Colombier void 9467dd7cddfSDavid du Colombier readipinterfaces(void) 9477dd7cddfSDavid du Colombier { 9480103620dSDavid du Colombier if(myipaddr(ipa, mntpt) != 0) 9490103620dSDavid du Colombier ipmove(ipa, IPnoaddr); 9507dd7cddfSDavid du Colombier sprint(ipaddr, "%I", ipa); 9517dd7cddfSDavid du Colombier if (debug) 9527dd7cddfSDavid du Colombier syslog(0, "dns", "ipaddr is %s\n", ipaddr); 9537dd7cddfSDavid du Colombier } 9543e12c5d1SDavid du Colombier 9553e12c5d1SDavid du Colombier /* 9567dd7cddfSDavid du Colombier * get the system name 9573e12c5d1SDavid du Colombier */ 9583e12c5d1SDavid du Colombier void 9593e12c5d1SDavid du Colombier ipid(void) 9603e12c5d1SDavid du Colombier { 9613e12c5d1SDavid du Colombier uchar addr[6]; 962a9f680aeSDavid du Colombier Ndbtuple *t, *tt; 963219b2ee8SDavid du Colombier char *p, *attr; 9643e12c5d1SDavid du Colombier Ndbs s; 9653e12c5d1SDavid du Colombier int f; 9667dd7cddfSDavid du Colombier char buf[Maxpath]; 9673e12c5d1SDavid du Colombier 968219b2ee8SDavid du Colombier /* use environment, ether addr, or ipaddr to get system name */ 96995a264b3SDavid du Colombier if(mysysname == 0){ 9707dd7cddfSDavid du Colombier /* 9717dd7cddfSDavid du Colombier * environment has priority. 9727dd7cddfSDavid du Colombier * 9737dd7cddfSDavid du Colombier * on the sgi power the default system name 9747dd7cddfSDavid du Colombier * is the ip address. ignore that. 9757dd7cddfSDavid du Colombier * 9767dd7cddfSDavid du Colombier */ 977219b2ee8SDavid du Colombier p = getenv("sysname"); 978447d6a7dSDavid du Colombier if(p && *p){ 979219b2ee8SDavid du Colombier attr = ipattr(p); 980219b2ee8SDavid du Colombier if(strcmp(attr, "ip") != 0) 98195a264b3SDavid du Colombier mysysname = strdup(p); 9823e12c5d1SDavid du Colombier } 9833e12c5d1SDavid du Colombier 9843e12c5d1SDavid du Colombier /* 9857dd7cddfSDavid du Colombier * the /net/ndb contains what the network 9867dd7cddfSDavid du Colombier * figured out from DHCP. use that name if 9877dd7cddfSDavid du Colombier * there is one. 9883e12c5d1SDavid du Colombier */ 98995a264b3SDavid du Colombier if(mysysname == 0 && netdb != nil){ 9907dd7cddfSDavid du Colombier ndbreopen(netdb); 991a9f680aeSDavid du Colombier for(tt = t = ndbparse(netdb); t != nil; t = t->entry){ 9927dd7cddfSDavid du Colombier if(strcmp(t->attr, "sys") == 0){ 99395a264b3SDavid du Colombier mysysname = strdup(t->val); 9943e12c5d1SDavid du Colombier break; 9953e12c5d1SDavid du Colombier } 9967dd7cddfSDavid du Colombier } 997a9f680aeSDavid du Colombier ndbfree(tt); 9987dd7cddfSDavid du Colombier } 9997dd7cddfSDavid du Colombier 10007dd7cddfSDavid du Colombier /* next network database, ip address, and ether address to find a name */ 100195a264b3SDavid du Colombier if(mysysname == 0){ 10027dd7cddfSDavid du Colombier t = nil; 10037dd7cddfSDavid du Colombier if(isvalidip(ipa)) 100457837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "ip", ipaddr, "sys", &t)); 100595a264b3SDavid du Colombier if(t == nil){ 10067dd7cddfSDavid du Colombier for(f = 0; f < 3; f++){ 10077dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/ether%d", mntpt, f); 10087dd7cddfSDavid du Colombier if(myetheraddr(addr, buf) >= 0){ 10097dd7cddfSDavid du Colombier snprint(eaddr, sizeof(eaddr), "%E", addr); 101057837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "ether", eaddr, "sys", &t)); 10117dd7cddfSDavid du Colombier if(t != nil) 10127dd7cddfSDavid du Colombier break; 10137dd7cddfSDavid du Colombier } 10147dd7cddfSDavid du Colombier } 10157dd7cddfSDavid du Colombier } 1016b7327ca2SDavid du Colombier for(tt = t; tt != nil; tt = tt->entry){ 1017b7327ca2SDavid du Colombier if(strcmp(tt->attr, "sys") == 0){ 1018b7327ca2SDavid du Colombier mysysname = strdup(tt->val); 101995a264b3SDavid du Colombier break; 102095a264b3SDavid du Colombier } 1021b7327ca2SDavid du Colombier } 10227dd7cddfSDavid du Colombier ndbfree(t); 10237dd7cddfSDavid du Colombier } 10247dd7cddfSDavid du Colombier 102580ee5cbfSDavid du Colombier /* nothing else worked, use the ip address */ 102695a264b3SDavid du Colombier if(mysysname == 0 && isvalidip(ipa)) 102795a264b3SDavid du Colombier mysysname = strdup(ipaddr); 102880ee5cbfSDavid du Colombier 102980ee5cbfSDavid du Colombier 1030dc5a79c1SDavid du Colombier /* set /dev/sysname if we now know it */ 103195a264b3SDavid du Colombier if(mysysname){ 10327dd7cddfSDavid du Colombier f = open("/dev/sysname", OWRITE); 10337dd7cddfSDavid du Colombier if(f >= 0){ 10347dd7cddfSDavid du Colombier write(f, mysysname, strlen(mysysname)); 10353e12c5d1SDavid du Colombier close(f); 10363e12c5d1SDavid du Colombier } 10373e12c5d1SDavid du Colombier } 10383e12c5d1SDavid du Colombier } 10393e12c5d1SDavid du Colombier } 10403e12c5d1SDavid du Colombier 10413e12c5d1SDavid du Colombier /* 10423e12c5d1SDavid du Colombier * Set up a list of default networks by looking for 10433e12c5d1SDavid du Colombier * /net/ * /clone. 10443e12c5d1SDavid du Colombier */ 10453e12c5d1SDavid du Colombier void 10467dd7cddfSDavid du Colombier netinit(int background) 10473e12c5d1SDavid du Colombier { 10487dd7cddfSDavid du Colombier char clone[Maxpath]; 10493e12c5d1SDavid du Colombier Network *np; 10507dd7cddfSDavid du Colombier static int working; 10517dd7cddfSDavid du Colombier 10527dd7cddfSDavid du Colombier if(background){ 10537dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 10547dd7cddfSDavid du Colombier case 0: 10557dd7cddfSDavid du Colombier break; 10567dd7cddfSDavid du Colombier default: 10577dd7cddfSDavid du Colombier return; 10587dd7cddfSDavid du Colombier } 10597dd7cddfSDavid du Colombier lock(&netlock); 10607dd7cddfSDavid du Colombier } 10613e12c5d1SDavid du Colombier 10623e12c5d1SDavid du Colombier /* add the mounted networks to the default list */ 10633e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 10647dd7cddfSDavid du Colombier if(np->considered) 10657dd7cddfSDavid du Colombier continue; 10667dd7cddfSDavid du Colombier snprint(clone, sizeof(clone), "%s/%s/clone", mntpt, np->net); 10679a747e4fSDavid du Colombier if(access(clone, AEXIST) < 0) 10683e12c5d1SDavid du Colombier continue; 10693e12c5d1SDavid du Colombier if(netlist) 10703e12c5d1SDavid du Colombier last->next = np; 10713e12c5d1SDavid du Colombier else 10723e12c5d1SDavid du Colombier netlist = np; 10733e12c5d1SDavid du Colombier last = np; 10743e12c5d1SDavid du Colombier np->next = 0; 10757dd7cddfSDavid du Colombier np->considered = 1; 10763e12c5d1SDavid du Colombier } 10773e12c5d1SDavid du Colombier 10787dd7cddfSDavid du Colombier /* find out what our ip address is */ 10797dd7cddfSDavid du Colombier readipinterfaces(); 10803e12c5d1SDavid du Colombier 10817dd7cddfSDavid du Colombier /* set the system name if we need to, these says ip is all we have */ 10823e12c5d1SDavid du Colombier ipid(); 10833e12c5d1SDavid du Colombier 1084219b2ee8SDavid du Colombier if(debug) 10857dd7cddfSDavid du Colombier syslog(0, logfile, "mysysname %s eaddr %s ipaddr %s ipa %I\n", 108695a264b3SDavid du Colombier mysysname?mysysname:"???", eaddr, ipaddr, ipa); 10877dd7cddfSDavid du Colombier 10887dd7cddfSDavid du Colombier if(background){ 10897dd7cddfSDavid du Colombier unlock(&netlock); 10907dd7cddfSDavid du Colombier _exits(0); 10917dd7cddfSDavid du Colombier } 10923e12c5d1SDavid du Colombier } 10933e12c5d1SDavid du Colombier 10943e12c5d1SDavid du Colombier /* 10953e12c5d1SDavid du Colombier * add networks to the standard list 10963e12c5d1SDavid du Colombier */ 10973e12c5d1SDavid du Colombier void 10983e12c5d1SDavid du Colombier netadd(char *p) 10993e12c5d1SDavid du Colombier { 11003e12c5d1SDavid du Colombier Network *np; 11013e12c5d1SDavid du Colombier char *field[12]; 11023e12c5d1SDavid du Colombier int i, n; 11033e12c5d1SDavid du Colombier 11047dd7cddfSDavid du Colombier n = getfields(p, field, 12, 1, " "); 11053e12c5d1SDavid du Colombier for(i = 0; i < n; i++){ 11063e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 11073e12c5d1SDavid du Colombier if(strcmp(field[i], np->net) != 0) 11083e12c5d1SDavid du Colombier continue; 11097dd7cddfSDavid du Colombier if(np->considered) 11103e12c5d1SDavid du Colombier break; 11113e12c5d1SDavid du Colombier if(netlist) 11123e12c5d1SDavid du Colombier last->next = np; 11133e12c5d1SDavid du Colombier else 11143e12c5d1SDavid du Colombier netlist = np; 11153e12c5d1SDavid du Colombier last = np; 11163e12c5d1SDavid du Colombier np->next = 0; 11177dd7cddfSDavid du Colombier np->considered = 1; 11183e12c5d1SDavid du Colombier } 11193e12c5d1SDavid du Colombier } 11203e12c5d1SDavid du Colombier } 11213e12c5d1SDavid du Colombier 112280ee5cbfSDavid du Colombier int 112380ee5cbfSDavid du Colombier lookforproto(Ndbtuple *t, char *proto) 112480ee5cbfSDavid du Colombier { 112580ee5cbfSDavid du Colombier for(; t != nil; t = t->entry) 112680ee5cbfSDavid du Colombier if(strcmp(t->attr, "proto") == 0 && strcmp(t->val, proto) == 0) 112780ee5cbfSDavid du Colombier return 1; 112880ee5cbfSDavid du Colombier return 0; 112980ee5cbfSDavid du Colombier } 113080ee5cbfSDavid du Colombier 1131219b2ee8SDavid du Colombier /* 11323e12c5d1SDavid du Colombier * lookup a request. the network "net" means we should pick the 11333e12c5d1SDavid du Colombier * best network to get there. 11343e12c5d1SDavid du Colombier */ 11353e12c5d1SDavid du Colombier int 113680ee5cbfSDavid du Colombier lookup(Mfile *mf) 11373e12c5d1SDavid du Colombier { 113880ee5cbfSDavid du Colombier Network *np; 1139219b2ee8SDavid du Colombier char *cp; 1140219b2ee8SDavid du Colombier Ndbtuple *nt, *t; 1141219b2ee8SDavid du Colombier char reply[Maxreply]; 114280ee5cbfSDavid du Colombier int i, rv; 114380ee5cbfSDavid du Colombier int hack; 11443e12c5d1SDavid du Colombier 11453e12c5d1SDavid du Colombier /* open up the standard db files */ 11463e12c5d1SDavid du Colombier if(db == 0) 11477dd7cddfSDavid du Colombier ndbinit(); 11483e12c5d1SDavid du Colombier if(db == 0) 114980ee5cbfSDavid du Colombier error("can't open mf->network database\n"); 11503e12c5d1SDavid du Colombier 115180ee5cbfSDavid du Colombier rv = 0; 115280ee5cbfSDavid du Colombier 115380ee5cbfSDavid du Colombier if(mf->net == nil) 115480ee5cbfSDavid du Colombier return 0; /* must have been a genquery */ 115580ee5cbfSDavid du Colombier 115680ee5cbfSDavid du Colombier if(strcmp(mf->net, "net") == 0){ 11573e12c5d1SDavid du Colombier /* 11583e12c5d1SDavid du Colombier * go through set of default nets 11593e12c5d1SDavid du Colombier */ 116080ee5cbfSDavid du Colombier for(np = mf->nextnet; np; np = np->next){ 116180ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 116280ee5cbfSDavid du Colombier if(nt == nil) 1163219b2ee8SDavid du Colombier continue; 116480ee5cbfSDavid du Colombier hack = np->fasttimeouthack && !lookforproto(nt, np->net); 116580ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 116680ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, hack); 1167219b2ee8SDavid du Colombier if(cp){ 116880ee5cbfSDavid du Colombier /* avoid duplicates */ 116980ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++) 117080ee5cbfSDavid du Colombier if(strcmp(mf->reply[i], cp) == 0) 117180ee5cbfSDavid du Colombier break; 117280ee5cbfSDavid du Colombier if(i == mf->nreply){ 117380ee5cbfSDavid du Colombier /* save the reply */ 1174219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 1175219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = cp; 117680ee5cbfSDavid du Colombier rv++; 1177219b2ee8SDavid du Colombier } 1178219b2ee8SDavid du Colombier } 1179219b2ee8SDavid du Colombier } 1180219b2ee8SDavid du Colombier ndbfree(nt); 118180ee5cbfSDavid du Colombier np = np->next; 118280ee5cbfSDavid du Colombier break; 118380ee5cbfSDavid du Colombier } 118480ee5cbfSDavid du Colombier mf->nextnet = np; 118580ee5cbfSDavid du Colombier return rv; 118680ee5cbfSDavid du Colombier } 118780ee5cbfSDavid du Colombier 118880ee5cbfSDavid du Colombier /* 118980ee5cbfSDavid du Colombier * if not /net, we only get one lookup 119080ee5cbfSDavid du Colombier */ 119180ee5cbfSDavid du Colombier if(mf->nreply != 0) 1192219b2ee8SDavid du Colombier return 0; 119380ee5cbfSDavid du Colombier /* 119480ee5cbfSDavid du Colombier * look for a specific network 119580ee5cbfSDavid du Colombier */ 119695a264b3SDavid du Colombier for(np = netlist; np && np->net != nil; np++){ 119780ee5cbfSDavid du Colombier if(np->fasttimeouthack) 119880ee5cbfSDavid du Colombier continue; 119980ee5cbfSDavid du Colombier if(strcmp(np->net, mf->net) == 0) 120080ee5cbfSDavid du Colombier break; 120180ee5cbfSDavid du Colombier } 120280ee5cbfSDavid du Colombier 120395a264b3SDavid du Colombier if(np && np->net != nil){ 120480ee5cbfSDavid du Colombier /* 120580ee5cbfSDavid du Colombier * known network 120680ee5cbfSDavid du Colombier */ 120780ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 120880ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 120980ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, 0); 121080ee5cbfSDavid du Colombier if(cp){ 121180ee5cbfSDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 121280ee5cbfSDavid du Colombier mf->reply[mf->nreply++] = cp; 121380ee5cbfSDavid du Colombier rv++; 121480ee5cbfSDavid du Colombier } 121580ee5cbfSDavid du Colombier } 121680ee5cbfSDavid du Colombier ndbfree(nt); 121780ee5cbfSDavid du Colombier return rv; 12183e12c5d1SDavid du Colombier } else { 12193e12c5d1SDavid du Colombier /* 1220219b2ee8SDavid du Colombier * not a known network, don't translate host or service 12213e12c5d1SDavid du Colombier */ 122280ee5cbfSDavid du Colombier if(mf->serv) 12237dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s", 122480ee5cbfSDavid du Colombier mntpt, mf->net, mf->host, mf->serv); 1225bd389b36SDavid du Colombier else 12267dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s", 122780ee5cbfSDavid du Colombier mntpt, mf->net, mf->host); 1228219b2ee8SDavid du Colombier mf->reply[0] = strdup(reply); 1229219b2ee8SDavid du Colombier mf->replylen[0] = strlen(reply); 1230219b2ee8SDavid du Colombier mf->nreply = 1; 123180ee5cbfSDavid du Colombier return 1; 12323e12c5d1SDavid du Colombier } 12333e12c5d1SDavid du Colombier } 12343e12c5d1SDavid du Colombier 12353e12c5d1SDavid du Colombier /* 12363e12c5d1SDavid du Colombier * translate an ip service name into a port number. If it's a numeric port 12373e12c5d1SDavid du Colombier * number, look for restricted access. 12383e12c5d1SDavid du Colombier * 12393e12c5d1SDavid du Colombier * the service '*' needs no translation. 12403e12c5d1SDavid du Colombier */ 12413e12c5d1SDavid du Colombier char* 124295a264b3SDavid du Colombier ipserv(Network *np, char *name, char *buf, int blen) 12433e12c5d1SDavid du Colombier { 12443e12c5d1SDavid du Colombier char *p; 12453e12c5d1SDavid du Colombier int alpha = 0; 12463e12c5d1SDavid du Colombier int restr = 0; 124795a264b3SDavid du Colombier char port[10]; 12483e12c5d1SDavid du Colombier Ndbtuple *t, *nt; 12493e12c5d1SDavid du Colombier Ndbs s; 12503e12c5d1SDavid du Colombier 12513e12c5d1SDavid du Colombier /* '*' means any service */ 12523e12c5d1SDavid du Colombier if(strcmp(name, "*")==0){ 12533e12c5d1SDavid du Colombier strcpy(buf, name); 12543e12c5d1SDavid du Colombier return buf; 12553e12c5d1SDavid du Colombier } 12563e12c5d1SDavid du Colombier 12573e12c5d1SDavid du Colombier /* see if it's numeric or symbolic */ 12583e12c5d1SDavid du Colombier port[0] = 0; 12593e12c5d1SDavid du Colombier for(p = name; *p; p++){ 12603e12c5d1SDavid du Colombier if(isdigit(*p)) 12619a747e4fSDavid du Colombier {} 12623e12c5d1SDavid du Colombier else if(isalpha(*p) || *p == '-' || *p == '$') 12633e12c5d1SDavid du Colombier alpha = 1; 12643e12c5d1SDavid du Colombier else 12653e12c5d1SDavid du Colombier return 0; 12663e12c5d1SDavid du Colombier } 126757837e0bSDavid du Colombier t = nil; 126857837e0bSDavid du Colombier p = nil; 12693e12c5d1SDavid du Colombier if(alpha){ 127057837e0bSDavid du Colombier p = ndbgetvalue(db, &s, np->net, name, "port", &t); 1271b7327ca2SDavid du Colombier if(p == nil) 1272b7327ca2SDavid du Colombier return 0; 12733e12c5d1SDavid du Colombier } else { 12743cc1eb97SDavid du Colombier /* look up only for tcp ports < 1024 to get the restricted 12753cc1eb97SDavid du Colombier * attribute 12763cc1eb97SDavid du Colombier */ 12773cc1eb97SDavid du Colombier if(atoi(name) < 1024 && strcmp(np->net, "tcp") == 0) 127857837e0bSDavid du Colombier p = ndbgetvalue(db, &s, "port", name, "port", &t); 127957837e0bSDavid du Colombier if(p == nil) 128057837e0bSDavid du Colombier p = strdup(name); 12813e12c5d1SDavid du Colombier } 12823e12c5d1SDavid du Colombier 12833e12c5d1SDavid du Colombier if(t){ 12843e12c5d1SDavid du Colombier for(nt = t; nt; nt = nt->entry) 12853e12c5d1SDavid du Colombier if(strcmp(nt->attr, "restricted") == 0) 12863e12c5d1SDavid du Colombier restr = 1; 12873e12c5d1SDavid du Colombier ndbfree(t); 12883e12c5d1SDavid du Colombier } 128957837e0bSDavid du Colombier snprint(buf, blen, "%s%s", p, restr ? "!r" : ""); 129057837e0bSDavid du Colombier free(p); 129157837e0bSDavid du Colombier 12923e12c5d1SDavid du Colombier return buf; 12933e12c5d1SDavid du Colombier } 12943e12c5d1SDavid du Colombier 12953e12c5d1SDavid du Colombier /* 12967dd7cddfSDavid du Colombier * lookup an ip attribute 12973e12c5d1SDavid du Colombier */ 12987dd7cddfSDavid du Colombier int 129995a264b3SDavid du Colombier ipattrlookup(Ndb *db, char *ipa, char *attr, char *val, int vlen) 13003e12c5d1SDavid du Colombier { 13013e12c5d1SDavid du Colombier 13027dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13037dd7cddfSDavid du Colombier char *alist[2]; 13043e12c5d1SDavid du Colombier 13057dd7cddfSDavid du Colombier alist[0] = attr; 13067dd7cddfSDavid du Colombier t = ndbipinfo(db, "ip", ipa, alist, 1); 13077dd7cddfSDavid du Colombier if(t == nil) 13087dd7cddfSDavid du Colombier return 0; 13099a747e4fSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 13107dd7cddfSDavid du Colombier if(strcmp(nt->attr, attr) == 0){ 131195a264b3SDavid du Colombier nstrcpy(val, nt->val, vlen); 13123e12c5d1SDavid du Colombier ndbfree(t); 13137dd7cddfSDavid du Colombier return 1; 1314219b2ee8SDavid du Colombier } 13159a747e4fSDavid du Colombier } 13163e12c5d1SDavid du Colombier 13177dd7cddfSDavid du Colombier /* we shouldn't get here */ 13183e12c5d1SDavid du Colombier ndbfree(t); 13197dd7cddfSDavid du Colombier return 0; 13203e12c5d1SDavid du Colombier } 13213e12c5d1SDavid du Colombier 13223e12c5d1SDavid du Colombier /* 13233e12c5d1SDavid du Colombier * lookup (and translate) an ip destination 13243e12c5d1SDavid du Colombier */ 1325219b2ee8SDavid du Colombier Ndbtuple* 1326219b2ee8SDavid du Colombier iplookup(Network *np, char *host, char *serv, int nolookup) 13273e12c5d1SDavid du Colombier { 13289dfc0cb2SDavid du Colombier char *attr, *dnsname; 13297dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13303e12c5d1SDavid du Colombier Ndbs s; 133195a264b3SDavid du Colombier char ts[Maxservice]; 133295a264b3SDavid du Colombier char dollar[Maxhost]; 13337dd7cddfSDavid du Colombier uchar ip[IPaddrlen]; 13347dd7cddfSDavid du Colombier uchar net[IPaddrlen]; 13357dd7cddfSDavid du Colombier uchar tnet[IPaddrlen]; 13367dd7cddfSDavid du Colombier Ipifc *ifc; 13379a747e4fSDavid du Colombier Iplifc *lifc; 13383e12c5d1SDavid du Colombier 1339219b2ee8SDavid du Colombier USED(nolookup); 1340219b2ee8SDavid du Colombier 13413e12c5d1SDavid du Colombier /* 13423e12c5d1SDavid du Colombier * start with the service since it's the most likely to fail 13433e12c5d1SDavid du Colombier * and costs the least 13443e12c5d1SDavid du Colombier */ 13457dd7cddfSDavid du Colombier werrstr("can't translate address"); 134695a264b3SDavid du Colombier if(serv==0 || ipserv(np, serv, ts, sizeof ts) == 0){ 1347271b8d73SDavid du Colombier werrstr("can't translate service"); 1348219b2ee8SDavid du Colombier return 0; 13497dd7cddfSDavid du Colombier } 13503e12c5d1SDavid du Colombier 13513e12c5d1SDavid du Colombier /* for dial strings with no host */ 1352219b2ee8SDavid du Colombier if(strcmp(host, "*") == 0) 135395a264b3SDavid du Colombier return ndbnew("ip", "*"); 13543e12c5d1SDavid du Colombier 13553e12c5d1SDavid du Colombier /* 13567dd7cddfSDavid du Colombier * hack till we go v6 :: = 0.0.0.0 13577dd7cddfSDavid du Colombier */ 13587dd7cddfSDavid du Colombier if(strcmp("::", host) == 0) 135995a264b3SDavid du Colombier return ndbnew("ip", "*"); 13607dd7cddfSDavid du Colombier 13617dd7cddfSDavid du Colombier /* 13623e12c5d1SDavid du Colombier * '$' means the rest of the name is an attribute that we 13633e12c5d1SDavid du Colombier * need to search for 13643e12c5d1SDavid du Colombier */ 13653e12c5d1SDavid du Colombier if(*host == '$'){ 136695a264b3SDavid du Colombier if(ipattrlookup(db, ipaddr, host+1, dollar, sizeof dollar)) 13673e12c5d1SDavid du Colombier host = dollar; 13683e12c5d1SDavid du Colombier } 13693e12c5d1SDavid du Colombier 13703e12c5d1SDavid du Colombier /* 13717dd7cddfSDavid du Colombier * turn '[ip address]' into just 'ip address' 13727dd7cddfSDavid du Colombier */ 13737dd7cddfSDavid du Colombier if(*host == '[' && host[strlen(host)-1] == ']'){ 13747dd7cddfSDavid du Colombier host++; 13757dd7cddfSDavid du Colombier host[strlen(host)-1] = 0; 13767dd7cddfSDavid du Colombier } 13777dd7cddfSDavid du Colombier 13787dd7cddfSDavid du Colombier /* 13793e12c5d1SDavid du Colombier * just accept addresses 13803e12c5d1SDavid du Colombier */ 1381219b2ee8SDavid du Colombier attr = ipattr(host); 1382219b2ee8SDavid du Colombier if(strcmp(attr, "ip") == 0) 138395a264b3SDavid du Colombier return ndbnew("ip", host); 13843e12c5d1SDavid du Colombier 13853e12c5d1SDavid du Colombier /* 13863e12c5d1SDavid du Colombier * give the domain name server the first opportunity to 1387bd389b36SDavid du Colombier * resolve domain names. if that fails try the database. 13883e12c5d1SDavid du Colombier */ 13893e12c5d1SDavid du Colombier t = 0; 1390271b8d73SDavid du Colombier werrstr("can't translate address"); 13913e12c5d1SDavid du Colombier if(strcmp(attr, "dom") == 0) 13927dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 13933e12c5d1SDavid du Colombier if(t == 0) 139457837e0bSDavid du Colombier free(ndbgetvalue(db, &s, attr, host, "ip", &t)); 13959dfc0cb2SDavid du Colombier if(t == 0){ 13969dfc0cb2SDavid du Colombier dnsname = ndbgetvalue(db, &s, attr, host, "dom", nil); 13979dfc0cb2SDavid du Colombier if(dnsname){ 13989dfc0cb2SDavid du Colombier t = dnsiplookup(dnsname, &s); 13999dfc0cb2SDavid du Colombier free(dnsname); 14009dfc0cb2SDavid du Colombier } 14019dfc0cb2SDavid du Colombier } 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 17528a2c5ad0SDavid du Colombier if(n < 1) 17537dd7cddfSDavid du Colombier return "bad query"; 17547dd7cddfSDavid du Colombier 17558a2c5ad0SDavid du Colombier /* get search attribute=value, or assume ip=myipaddr */ 17568a2c5ad0SDavid du Colombier attr = *list; 17578a2c5ad0SDavid du Colombier if((val = strchr(attr, '=')) != nil){ 17587dd7cddfSDavid du Colombier *val++ = 0; 17598a2c5ad0SDavid du Colombier list++; 17608a2c5ad0SDavid du Colombier n--; 17618a2c5ad0SDavid du Colombier }else{ 17628a2c5ad0SDavid du Colombier attr = "ip"; 17638a2c5ad0SDavid du Colombier val = ipaddr; 17648a2c5ad0SDavid du Colombier } 17658a2c5ad0SDavid du Colombier 17668a2c5ad0SDavid du Colombier if(n < 1) 17678a2c5ad0SDavid du Colombier return "bad query"; 17687dd7cddfSDavid du Colombier 17697dd7cddfSDavid du Colombier /* 17707dd7cddfSDavid du Colombier * don't let ndbipinfo resolve the addresses, we're 17717dd7cddfSDavid du Colombier * better at it. 17727dd7cddfSDavid du Colombier */ 17737dd7cddfSDavid du Colombier nresolve = 0; 17747dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 1775107aedb4SDavid du Colombier if(*list[i] == '@'){ /* @attr=val ? */ 17767dd7cddfSDavid du Colombier list[i]++; 1777107aedb4SDavid du Colombier resolve[i] = 1; /* we'll resolve it */ 17787dd7cddfSDavid du Colombier nresolve++; 17797dd7cddfSDavid du Colombier } else 17807dd7cddfSDavid du Colombier resolve[i] = 0; 17817dd7cddfSDavid du Colombier 17827dd7cddfSDavid du Colombier t = ndbipinfo(db, attr, val, list, n); 17837dd7cddfSDavid du Colombier if(t == nil) 17847dd7cddfSDavid du Colombier return "no match"; 17857dd7cddfSDavid du Colombier 17867dd7cddfSDavid du Colombier if(nresolve != 0){ 17877dd7cddfSDavid du Colombier for(l = &t; *l != nil;){ 17887dd7cddfSDavid du Colombier nt = *l; 17897dd7cddfSDavid du Colombier 17907dd7cddfSDavid du Colombier /* already an address? */ 17917dd7cddfSDavid du Colombier if(strcmp(ipattr(nt->val), "ip") == 0){ 17927dd7cddfSDavid du Colombier l = &(*l)->entry; 17937dd7cddfSDavid du Colombier continue; 17947dd7cddfSDavid du Colombier } 17957dd7cddfSDavid du Colombier 17967dd7cddfSDavid du Colombier /* user wants it resolved? */ 17977dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 17987dd7cddfSDavid du Colombier if(strcmp(list[i], nt->attr) == 0) 17997dd7cddfSDavid du Colombier break; 18007dd7cddfSDavid du Colombier if(i >= n || resolve[i] == 0){ 18017dd7cddfSDavid du Colombier l = &(*l)->entry; 18027dd7cddfSDavid du Colombier continue; 18037dd7cddfSDavid du Colombier } 18047dd7cddfSDavid du Colombier 18057dd7cddfSDavid du Colombier /* resolve address and replace entry */ 18067dd7cddfSDavid du Colombier *l = ipresolve(nt->attr, nt->val); 18077dd7cddfSDavid du Colombier while(*l != nil) 18087dd7cddfSDavid du Colombier l = &(*l)->entry; 18097dd7cddfSDavid du Colombier *l = nt->entry; 18107dd7cddfSDavid du Colombier 18117dd7cddfSDavid du Colombier nt->entry = nil; 18127dd7cddfSDavid du Colombier ndbfree(nt); 18137dd7cddfSDavid du Colombier } 18147dd7cddfSDavid du Colombier } 18157dd7cddfSDavid du Colombier 18167dd7cddfSDavid du Colombier /* make it all one line */ 18177dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 18187dd7cddfSDavid du Colombier if(nt->entry == nil) 18197dd7cddfSDavid du Colombier nt->line = t; 18207dd7cddfSDavid du Colombier else 18217dd7cddfSDavid du Colombier nt->line = nt->entry; 18227dd7cddfSDavid du Colombier } 18237dd7cddfSDavid du Colombier 18247dd7cddfSDavid du Colombier qreply(mf, t); 18257dd7cddfSDavid du Colombier 18267dd7cddfSDavid du Colombier return nil; 18277dd7cddfSDavid du Colombier } 18287dd7cddfSDavid du Colombier 18297dd7cddfSDavid du Colombier void* 18307dd7cddfSDavid du Colombier emalloc(int size) 18317dd7cddfSDavid du Colombier { 18327dd7cddfSDavid du Colombier void *x; 18337dd7cddfSDavid du Colombier 18347dd7cddfSDavid du Colombier x = malloc(size); 18357dd7cddfSDavid du Colombier if(x == nil) 18367dd7cddfSDavid du Colombier abort(); 18377dd7cddfSDavid du Colombier memset(x, 0, size); 18387dd7cddfSDavid du Colombier return x; 18397dd7cddfSDavid du Colombier } 18409a747e4fSDavid du Colombier 18419a747e4fSDavid du Colombier char* 18429a747e4fSDavid du Colombier estrdup(char *s) 18439a747e4fSDavid du Colombier { 18449a747e4fSDavid du Colombier int size; 18459a747e4fSDavid du Colombier char *p; 18469a747e4fSDavid du Colombier 18479a747e4fSDavid du Colombier size = strlen(s)+1; 18489a747e4fSDavid du Colombier p = malloc(size); 18499a747e4fSDavid du Colombier if(p == nil) 18509a747e4fSDavid du Colombier abort(); 18519a747e4fSDavid du Colombier memmove(p, s, size); 18529a747e4fSDavid du Colombier return p; 18539a747e4fSDavid du Colombier } 1854