13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3219b2ee8SDavid du Colombier #include <auth.h> 43e12c5d1SDavid du Colombier #include <fcall.h> 53e12c5d1SDavid du Colombier #include <bio.h> 63e12c5d1SDavid du Colombier #include <ctype.h> 73e12c5d1SDavid du Colombier #include <ndb.h> 83e12c5d1SDavid du Colombier #include <ip.h> 995a264b3SDavid du Colombier #include <String.h> 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier enum 123e12c5d1SDavid du Colombier { 1380ee5cbfSDavid du Colombier Nreply= 20, 143e12c5d1SDavid du Colombier Maxreply= 256, 157dd7cddfSDavid du Colombier Maxrequest= 128, 167dd7cddfSDavid du Colombier Maxpath= 128, 179a747e4fSDavid du Colombier Maxfdata= 8192, 1895a264b3SDavid du Colombier Maxhost= 64, /* maximum host name size */ 1995a264b3SDavid du Colombier Maxservice= 64, /* maximum service name size */ 203e12c5d1SDavid du Colombier 219a747e4fSDavid du Colombier Qdir= 0, 223e12c5d1SDavid du Colombier Qcs= 1, 233e12c5d1SDavid du Colombier }; 243e12c5d1SDavid du Colombier 253e12c5d1SDavid du Colombier typedef struct Mfile Mfile; 26219b2ee8SDavid du Colombier typedef struct Mlist Mlist; 273e12c5d1SDavid du Colombier typedef struct Network Network; 287dd7cddfSDavid du Colombier typedef struct Flushreq Flushreq; 297dd7cddfSDavid du Colombier typedef struct Job Job; 303e12c5d1SDavid du Colombier 313e12c5d1SDavid du Colombier int vers; /* incremented each clone/attach */ 323e12c5d1SDavid du Colombier 333e12c5d1SDavid du Colombier struct Mfile 343e12c5d1SDavid du Colombier { 353e12c5d1SDavid du Colombier int busy; 36219b2ee8SDavid du Colombier 379a747e4fSDavid du Colombier char *user; 383e12c5d1SDavid du Colombier Qid qid; 393e12c5d1SDavid du Colombier int fid; 403e12c5d1SDavid du Colombier 4180ee5cbfSDavid du Colombier /* 4280ee5cbfSDavid du Colombier * current request 4380ee5cbfSDavid du Colombier */ 4480ee5cbfSDavid du Colombier char *net; 4580ee5cbfSDavid du Colombier char *host; 4680ee5cbfSDavid du Colombier char *serv; 4780ee5cbfSDavid du Colombier char *rem; 4880ee5cbfSDavid du Colombier 4980ee5cbfSDavid du Colombier /* 5080ee5cbfSDavid du Colombier * result of the last lookup 5180ee5cbfSDavid du Colombier */ 5280ee5cbfSDavid du Colombier Network *nextnet; 53219b2ee8SDavid du Colombier int nreply; 54219b2ee8SDavid du Colombier char *reply[Nreply]; 55219b2ee8SDavid du Colombier int replylen[Nreply]; 56219b2ee8SDavid du Colombier }; 57219b2ee8SDavid du Colombier 58219b2ee8SDavid du Colombier struct Mlist 59219b2ee8SDavid du Colombier { 60219b2ee8SDavid du Colombier Mlist *next; 61219b2ee8SDavid du Colombier Mfile mf; 623e12c5d1SDavid du Colombier }; 633e12c5d1SDavid du Colombier 649a747e4fSDavid du Colombier 65244672c5SDavid du Colombier /* 66244672c5SDavid du Colombier * active requests 67244672c5SDavid du Colombier */ 687dd7cddfSDavid du Colombier struct Job 697dd7cddfSDavid du Colombier { 707dd7cddfSDavid du Colombier Job *next; 717dd7cddfSDavid du Colombier int flushed; 727dd7cddfSDavid du Colombier Fcall request; 737dd7cddfSDavid du Colombier Fcall reply; 747dd7cddfSDavid du Colombier }; 757dd7cddfSDavid du Colombier Lock joblock; 767dd7cddfSDavid du Colombier Job *joblist; 777dd7cddfSDavid du Colombier 78219b2ee8SDavid du Colombier Mlist *mlist; 793e12c5d1SDavid du Colombier int mfd[2]; 803e12c5d1SDavid du Colombier int debug; 817dd7cddfSDavid du Colombier int paranoia; 823e12c5d1SDavid du Colombier jmp_buf masterjmp; /* return through here after a slave process has been created */ 833e12c5d1SDavid du Colombier int *isslave; /* *isslave non-zero means this is a slave process */ 84bd389b36SDavid du Colombier char *dbfile; 857dd7cddfSDavid du Colombier Ndb *db, *netdb; 863e12c5d1SDavid du Colombier 879a747e4fSDavid du Colombier void rversion(Job*); 887dd7cddfSDavid du Colombier void rflush(Job*); 897dd7cddfSDavid du Colombier void rattach(Job*, Mfile*); 907dd7cddfSDavid du Colombier char* rwalk(Job*, Mfile*); 917dd7cddfSDavid du Colombier void ropen(Job*, Mfile*); 927dd7cddfSDavid du Colombier void rcreate(Job*, Mfile*); 937dd7cddfSDavid du Colombier void rread(Job*, Mfile*); 947dd7cddfSDavid du Colombier void rwrite(Job*, Mfile*); 957dd7cddfSDavid du Colombier void rclunk(Job*, Mfile*); 967dd7cddfSDavid du Colombier void rremove(Job*, Mfile*); 977dd7cddfSDavid du Colombier void rstat(Job*, Mfile*); 987dd7cddfSDavid du Colombier void rwstat(Job*, Mfile*); 999a747e4fSDavid du Colombier void rauth(Job*); 1007dd7cddfSDavid du Colombier void sendmsg(Job*, char*); 1013e12c5d1SDavid du Colombier void error(char*); 1027dd7cddfSDavid du Colombier void mountinit(char*, char*); 1033e12c5d1SDavid du Colombier void io(void); 1047dd7cddfSDavid du Colombier void ndbinit(void); 1057dd7cddfSDavid du Colombier void netinit(int); 1063e12c5d1SDavid du Colombier void netadd(char*); 107219b2ee8SDavid du Colombier char *genquery(Mfile*, char*); 1087dd7cddfSDavid du Colombier char* ipinfoquery(Mfile*, char**, int); 109bd389b36SDavid du Colombier int needproto(Network*, Ndbtuple*); 1109a747e4fSDavid du Colombier int lookup(Mfile*); 1113e12c5d1SDavid du Colombier Ndbtuple* reorder(Ndbtuple*, Ndbtuple*); 1127dd7cddfSDavid du Colombier void ipid(void); 1137dd7cddfSDavid du Colombier void readipinterfaces(void); 1147dd7cddfSDavid du Colombier void* emalloc(int); 1159a747e4fSDavid du Colombier char* estrdup(char*); 1167dd7cddfSDavid du Colombier Job* newjob(void); 1177dd7cddfSDavid du Colombier void freejob(Job*); 1187dd7cddfSDavid du Colombier void setext(char*, int, char*); 11980ee5cbfSDavid du Colombier void cleanmf(Mfile*); 1203e12c5d1SDavid du Colombier 121bd389b36SDavid du Colombier extern void paralloc(void); 122bd389b36SDavid du Colombier 123bd389b36SDavid du Colombier Lock dblock; /* mutex on database operations */ 1247dd7cddfSDavid du Colombier Lock netlock; /* mutex for netinit() */ 125bd389b36SDavid du Colombier 126219b2ee8SDavid du Colombier char *logfile = "cs"; 1277dd7cddfSDavid du Colombier char *paranoiafile = "cs.paranoia"; 128219b2ee8SDavid du Colombier 1297dd7cddfSDavid du Colombier char mntpt[Maxpath]; 1307dd7cddfSDavid du Colombier char netndb[Maxpath]; 1317dd7cddfSDavid du Colombier 13280ee5cbfSDavid du Colombier /* 13380ee5cbfSDavid du Colombier * Network specific translators 13480ee5cbfSDavid du Colombier */ 13580ee5cbfSDavid du Colombier Ndbtuple* iplookup(Network*, char*, char*, int); 13680ee5cbfSDavid du Colombier char* iptrans(Ndbtuple*, Network*, char*, char*, int); 13780ee5cbfSDavid du Colombier Ndbtuple* telcolookup(Network*, char*, char*, int); 13880ee5cbfSDavid du Colombier char* telcotrans(Ndbtuple*, Network*, char*, char*, int); 13980ee5cbfSDavid du Colombier Ndbtuple* dnsiplookup(char*, Ndbs*); 14080ee5cbfSDavid du Colombier 14180ee5cbfSDavid du Colombier struct Network 14280ee5cbfSDavid du Colombier { 14380ee5cbfSDavid du Colombier char *net; 14480ee5cbfSDavid du Colombier Ndbtuple *(*lookup)(Network*, char*, char*, int); 14580ee5cbfSDavid du Colombier char *(*trans)(Ndbtuple*, Network*, char*, char*, int); 146617c0e1eSDavid du Colombier int considered; /* flag: ignored for "net!"? */ 147617c0e1eSDavid du Colombier int fasttimeouthack; /* flag. was for IL */ 14880ee5cbfSDavid du Colombier Network *next; 14980ee5cbfSDavid du Colombier }; 15080ee5cbfSDavid du Colombier 15180ee5cbfSDavid du Colombier enum 15280ee5cbfSDavid du Colombier { 15375766116SDavid du Colombier Ntcp = 0, 15480ee5cbfSDavid du Colombier }; 15580ee5cbfSDavid du Colombier 15680ee5cbfSDavid du Colombier /* 157244672c5SDavid du Colombier * net doesn't apply to (r)udp, icmp(v6), or telco (for speed). 15880ee5cbfSDavid du Colombier */ 15980ee5cbfSDavid du Colombier Network network[] = { 160617c0e1eSDavid du Colombier [Ntcp] { "tcp", iplookup, iptrans, 0 }, 161617c0e1eSDavid du Colombier { "udp", iplookup, iptrans, 1 }, 162617c0e1eSDavid du Colombier { "icmp", iplookup, iptrans, 1 }, 163617c0e1eSDavid du Colombier { "icmpv6", iplookup, iptrans, 1 }, 164617c0e1eSDavid du Colombier { "rudp", iplookup, iptrans, 1 }, 165617c0e1eSDavid du Colombier { "telco", telcolookup, telcotrans, 1 }, 16680ee5cbfSDavid du Colombier { 0 }, 16780ee5cbfSDavid du Colombier }; 16880ee5cbfSDavid du Colombier 16980ee5cbfSDavid du Colombier Lock ipifclock; 17080ee5cbfSDavid du Colombier Ipifc *ipifcs; 17180ee5cbfSDavid du Colombier 17295a264b3SDavid du Colombier char eaddr[16]; /* ascii ethernet address */ 17395a264b3SDavid du Colombier char ipaddr[64]; /* ascii internet address */ 17480ee5cbfSDavid du Colombier uchar ipa[IPaddrlen]; /* binary internet address */ 17595a264b3SDavid du Colombier char *mysysname; 17680ee5cbfSDavid du Colombier 17780ee5cbfSDavid du Colombier Network *netlist; /* networks ordered by preference */ 17880ee5cbfSDavid du Colombier Network *last; 17980ee5cbfSDavid du Colombier 18095a264b3SDavid du Colombier static void 18195a264b3SDavid du Colombier nstrcpy(char *to, char *from, int len) 18295a264b3SDavid du Colombier { 18395a264b3SDavid du Colombier strncpy(to, from, len); 18495a264b3SDavid du Colombier to[len-1] = 0; 18595a264b3SDavid du Colombier } 18695a264b3SDavid du Colombier 1877dd7cddfSDavid du Colombier void 1887dd7cddfSDavid du Colombier usage(void) 1897dd7cddfSDavid du Colombier { 19075766116SDavid du Colombier fprint(2, "usage: %s [-dn] [-f ndb-file] [-x netmtpt]\n", argv0); 1917dd7cddfSDavid du Colombier exits("usage"); 1927dd7cddfSDavid du Colombier } 193219b2ee8SDavid du Colombier 194*254fe3d3SDavid du Colombier /* 195*254fe3d3SDavid du Colombier * based on libthread's threadsetname, but drags in less library code. 196*254fe3d3SDavid du Colombier * actually just sets the arguments displayed. 197*254fe3d3SDavid du Colombier */ 198*254fe3d3SDavid du Colombier void 199*254fe3d3SDavid du Colombier procsetname(char *fmt, ...) 200*254fe3d3SDavid du Colombier { 201*254fe3d3SDavid du Colombier int fd; 202*254fe3d3SDavid du Colombier char *cmdname; 203*254fe3d3SDavid du Colombier char buf[128]; 204*254fe3d3SDavid du Colombier va_list arg; 205*254fe3d3SDavid du Colombier 206*254fe3d3SDavid du Colombier va_start(arg, fmt); 207*254fe3d3SDavid du Colombier cmdname = vsmprint(fmt, arg); 208*254fe3d3SDavid du Colombier va_end(arg); 209*254fe3d3SDavid du Colombier if (cmdname == nil) 210*254fe3d3SDavid du Colombier return; 211*254fe3d3SDavid du Colombier snprint(buf, sizeof buf, "#p/%d/args", getpid()); 212*254fe3d3SDavid du Colombier if((fd = open(buf, OWRITE)) >= 0){ 213*254fe3d3SDavid du Colombier write(fd, cmdname, strlen(cmdname)+1); 214*254fe3d3SDavid du Colombier close(fd); 215*254fe3d3SDavid du Colombier } 216*254fe3d3SDavid du Colombier free(cmdname); 217*254fe3d3SDavid du Colombier } 218*254fe3d3SDavid du Colombier 2193e12c5d1SDavid du Colombier void 2203e12c5d1SDavid du Colombier main(int argc, char *argv[]) 2213e12c5d1SDavid du Colombier { 222219b2ee8SDavid du Colombier int justsetname; 22375766116SDavid du Colombier char ext[Maxpath], servefile[Maxpath]; 2243e12c5d1SDavid du Colombier 225219b2ee8SDavid du Colombier justsetname = 0; 2267dd7cddfSDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), nil); 2277dd7cddfSDavid du Colombier ext[0] = 0; 2283e12c5d1SDavid du Colombier ARGBEGIN{ 2293e12c5d1SDavid du Colombier case 'd': 2303e12c5d1SDavid du Colombier debug = 1; 2313e12c5d1SDavid du Colombier break; 232bd389b36SDavid du Colombier case 'f': 23375766116SDavid du Colombier dbfile = EARGF(usage()); 234bd389b36SDavid du Colombier break; 235219b2ee8SDavid du Colombier case 'n': 236219b2ee8SDavid du Colombier justsetname = 1; 237219b2ee8SDavid du Colombier break; 23875766116SDavid du Colombier case 'x': 23975766116SDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), EARGF(usage())); 24075766116SDavid du Colombier setext(ext, sizeof(ext), mntpt); 24175766116SDavid du Colombier break; 2423e12c5d1SDavid du Colombier }ARGEND 2433e12c5d1SDavid du Colombier USED(argc); 2443e12c5d1SDavid du Colombier USED(argv); 2453e12c5d1SDavid du Colombier 2467dd7cddfSDavid du Colombier rfork(RFREND|RFNOTEG); 2477dd7cddfSDavid du Colombier 2487dd7cddfSDavid du Colombier snprint(servefile, sizeof(servefile), "#s/cs%s", ext); 2497dd7cddfSDavid du Colombier snprint(netndb, sizeof(netndb), "%s/ndb", mntpt); 2507dd7cddfSDavid du Colombier unmount(servefile, mntpt); 2517dd7cddfSDavid du Colombier remove(servefile); 2527dd7cddfSDavid du Colombier 2539a747e4fSDavid du Colombier fmtinstall('E', eipfmt); 2549a747e4fSDavid du Colombier fmtinstall('I', eipfmt); 2559a747e4fSDavid du Colombier fmtinstall('M', eipfmt); 2569a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 2577dd7cddfSDavid du Colombier 2587dd7cddfSDavid du Colombier ndbinit(); 2597dd7cddfSDavid du Colombier netinit(0); 2607dd7cddfSDavid du Colombier 2617dd7cddfSDavid du Colombier if(!justsetname){ 2627dd7cddfSDavid du Colombier mountinit(servefile, mntpt); 2637dd7cddfSDavid du Colombier io(); 2647dd7cddfSDavid du Colombier } 265219b2ee8SDavid du Colombier exits(0); 266219b2ee8SDavid du Colombier } 267219b2ee8SDavid du Colombier 2687dd7cddfSDavid du Colombier /* 2697dd7cddfSDavid du Colombier * if a mount point is specified, set the cs extention to be the mount point 2707dd7cddfSDavid du Colombier * with '_'s replacing '/'s 2717dd7cddfSDavid du Colombier */ 2727dd7cddfSDavid du Colombier void 2737dd7cddfSDavid du Colombier setext(char *ext, int n, char *p) 2747dd7cddfSDavid du Colombier { 2757dd7cddfSDavid du Colombier int i, c; 2763e12c5d1SDavid du Colombier 2777dd7cddfSDavid du Colombier n--; 2787dd7cddfSDavid du Colombier for(i = 0; i < n; i++){ 2797dd7cddfSDavid du Colombier c = p[i]; 2807dd7cddfSDavid du Colombier if(c == 0) 2817dd7cddfSDavid du Colombier break; 2827dd7cddfSDavid du Colombier if(c == '/') 2837dd7cddfSDavid du Colombier c = '_'; 2847dd7cddfSDavid du Colombier ext[i] = c; 2857dd7cddfSDavid du Colombier } 2867dd7cddfSDavid du Colombier ext[i] = 0; 2873e12c5d1SDavid du Colombier } 2883e12c5d1SDavid du Colombier 2893e12c5d1SDavid du Colombier void 2907dd7cddfSDavid du Colombier mountinit(char *service, char *mntpt) 2913e12c5d1SDavid du Colombier { 2923e12c5d1SDavid du Colombier int f; 2933e12c5d1SDavid du Colombier int p[2]; 2943e12c5d1SDavid du Colombier char buf[32]; 2953e12c5d1SDavid du Colombier 2963e12c5d1SDavid du Colombier if(pipe(p) < 0) 2973e12c5d1SDavid du Colombier error("pipe failed"); 298a9f680aeSDavid du Colombier 299a9f680aeSDavid du Colombier /* 300a9f680aeSDavid du Colombier * make a /srv/cs 301a9f680aeSDavid du Colombier */ 302a9f680aeSDavid du Colombier f = create(service, OWRITE|ORCLOSE, 0666); 303a9f680aeSDavid du Colombier if(f < 0) 304a9f680aeSDavid du Colombier error(service); 305a9f680aeSDavid du Colombier snprint(buf, sizeof(buf), "%d", p[1]); 306a9f680aeSDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf)) 307a9f680aeSDavid du Colombier error("write /srv/cs"); 308a9f680aeSDavid du Colombier 309219b2ee8SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG)){ 3103e12c5d1SDavid du Colombier case 0: 311219b2ee8SDavid du Colombier close(p[1]); 312*254fe3d3SDavid du Colombier procsetname("%s", mntpt); 3133e12c5d1SDavid du Colombier break; 3143e12c5d1SDavid du Colombier case -1: 3153e12c5d1SDavid du Colombier error("fork failed\n"); 3163e12c5d1SDavid du Colombier default: 3173e12c5d1SDavid du Colombier /* 3183e12c5d1SDavid du Colombier * put ourselves into the file system 3193e12c5d1SDavid du Colombier */ 320219b2ee8SDavid du Colombier close(p[0]); 3219a747e4fSDavid du Colombier if(mount(p[1], -1, mntpt, MAFTER, "") < 0) 3223e12c5d1SDavid du Colombier error("mount failed\n"); 323219b2ee8SDavid du Colombier _exits(0); 3243e12c5d1SDavid du Colombier } 3253e12c5d1SDavid du Colombier mfd[0] = mfd[1] = p[0]; 3263e12c5d1SDavid du Colombier } 3273e12c5d1SDavid du Colombier 3287dd7cddfSDavid du Colombier void 3297dd7cddfSDavid du Colombier ndbinit(void) 3307dd7cddfSDavid du Colombier { 3317dd7cddfSDavid du Colombier db = ndbopen(dbfile); 3327dd7cddfSDavid du Colombier if(db == nil) 3337dd7cddfSDavid du Colombier error("can't open network database"); 3347dd7cddfSDavid du Colombier 3357dd7cddfSDavid du Colombier netdb = ndbopen(netndb); 3367dd7cddfSDavid du Colombier if(netdb != nil){ 3377dd7cddfSDavid du Colombier netdb->nohash = 1; 3387dd7cddfSDavid du Colombier db = ndbcat(netdb, db); 3397dd7cddfSDavid du Colombier } 3407dd7cddfSDavid du Colombier } 3417dd7cddfSDavid du Colombier 3423e12c5d1SDavid du Colombier Mfile* 3433e12c5d1SDavid du Colombier newfid(int fid) 3443e12c5d1SDavid du Colombier { 345219b2ee8SDavid du Colombier Mlist *f, *ff; 3463e12c5d1SDavid du Colombier Mfile *mf; 3473e12c5d1SDavid du Colombier 348219b2ee8SDavid du Colombier ff = 0; 349219b2ee8SDavid du Colombier for(f = mlist; f; f = f->next) 350219b2ee8SDavid du Colombier if(f->mf.busy && f->mf.fid == fid) 351219b2ee8SDavid du Colombier return &f->mf; 352219b2ee8SDavid du Colombier else if(!ff && !f->mf.busy) 353219b2ee8SDavid du Colombier ff = f; 354219b2ee8SDavid du Colombier if(ff == 0){ 3557dd7cddfSDavid du Colombier ff = emalloc(sizeof *f); 356219b2ee8SDavid du Colombier ff->next = mlist; 357219b2ee8SDavid du Colombier mlist = ff; 3583e12c5d1SDavid du Colombier } 359219b2ee8SDavid du Colombier mf = &ff->mf; 360219b2ee8SDavid du Colombier memset(mf, 0, sizeof *mf); 3613e12c5d1SDavid du Colombier mf->fid = fid; 3623e12c5d1SDavid du Colombier return mf; 3633e12c5d1SDavid du Colombier } 3643e12c5d1SDavid du Colombier 3657dd7cddfSDavid du Colombier Job* 3667dd7cddfSDavid du Colombier newjob(void) 3677dd7cddfSDavid du Colombier { 3687dd7cddfSDavid du Colombier Job *job; 3697dd7cddfSDavid du Colombier 3707dd7cddfSDavid du Colombier job = mallocz(sizeof(Job), 1); 3717dd7cddfSDavid du Colombier lock(&joblock); 3727dd7cddfSDavid du Colombier job->next = joblist; 3737dd7cddfSDavid du Colombier joblist = job; 3747dd7cddfSDavid du Colombier job->request.tag = -1; 3757dd7cddfSDavid du Colombier unlock(&joblock); 3767dd7cddfSDavid du Colombier return job; 3777dd7cddfSDavid du Colombier } 3787dd7cddfSDavid du Colombier 3797dd7cddfSDavid du Colombier void 3807dd7cddfSDavid du Colombier freejob(Job *job) 3817dd7cddfSDavid du Colombier { 3827dd7cddfSDavid du Colombier Job **l; 3837dd7cddfSDavid du Colombier 3847dd7cddfSDavid du Colombier lock(&joblock); 3857dd7cddfSDavid du Colombier for(l = &joblist; *l; l = &(*l)->next){ 3867dd7cddfSDavid du Colombier if((*l) == job){ 3877dd7cddfSDavid du Colombier *l = job->next; 3887dd7cddfSDavid du Colombier free(job); 3897dd7cddfSDavid du Colombier break; 3907dd7cddfSDavid du Colombier } 3917dd7cddfSDavid du Colombier } 3927dd7cddfSDavid du Colombier unlock(&joblock); 3937dd7cddfSDavid du Colombier } 3947dd7cddfSDavid du Colombier 3957dd7cddfSDavid du Colombier void 3967dd7cddfSDavid du Colombier flushjob(int tag) 3977dd7cddfSDavid du Colombier { 3987dd7cddfSDavid du Colombier Job *job; 3997dd7cddfSDavid du Colombier 4007dd7cddfSDavid du Colombier lock(&joblock); 4017dd7cddfSDavid du Colombier for(job = joblist; job; job = job->next){ 4027dd7cddfSDavid du Colombier if(job->request.tag == tag && job->request.type != Tflush){ 4037dd7cddfSDavid du Colombier job->flushed = 1; 4047dd7cddfSDavid du Colombier break; 4057dd7cddfSDavid du Colombier } 4067dd7cddfSDavid du Colombier } 4077dd7cddfSDavid du Colombier unlock(&joblock); 4087dd7cddfSDavid du Colombier } 4097dd7cddfSDavid du Colombier 4103e12c5d1SDavid du Colombier void 4113e12c5d1SDavid du Colombier io(void) 4123e12c5d1SDavid du Colombier { 4133e12c5d1SDavid du Colombier long n; 4143e12c5d1SDavid du Colombier Mfile *mf; 4153e12c5d1SDavid du Colombier int slaveflag; 4169a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 4177dd7cddfSDavid du Colombier Job *job; 4183e12c5d1SDavid du Colombier 4193e12c5d1SDavid du Colombier /* 4203e12c5d1SDavid du Colombier * if we ask dns to fulfill requests, 4213e12c5d1SDavid du Colombier * a slave process is created to wait for replies. The 4229a747e4fSDavid du Colombier * master process returns immediately via a longjmp 4233e12c5d1SDavid du Colombier * through 'masterjmp'. 4243e12c5d1SDavid du Colombier * 4253e12c5d1SDavid du Colombier * *isslave is a pointer into the call stack to a variable 4263e12c5d1SDavid du Colombier * that tells whether or not the current process is a slave. 4273e12c5d1SDavid du Colombier */ 4283e12c5d1SDavid du Colombier slaveflag = 0; /* init slave variable */ 4293e12c5d1SDavid du Colombier isslave = &slaveflag; 4303e12c5d1SDavid du Colombier setjmp(masterjmp); 4313e12c5d1SDavid du Colombier 4323e12c5d1SDavid du Colombier for(;;){ 4339a747e4fSDavid du Colombier n = read9pmsg(mfd[0], mdata, sizeof mdata); 4343e12c5d1SDavid du Colombier if(n<=0) 4353e12c5d1SDavid du Colombier error("mount read"); 4367dd7cddfSDavid du Colombier job = newjob(); 4379a747e4fSDavid du Colombier if(convM2S(mdata, n, &job->request) != n){ 438271b8d73SDavid du Colombier syslog(1, logfile, "format error %ux %ux %ux %ux %ux", 439271b8d73SDavid du Colombier mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]); 4407dd7cddfSDavid du Colombier freejob(job); 4413e12c5d1SDavid du Colombier continue; 4423e12c5d1SDavid du Colombier } 443bd389b36SDavid du Colombier lock(&dblock); 4447dd7cddfSDavid du Colombier mf = newfid(job->request.fid); 445219b2ee8SDavid du Colombier if(debug) 4467dd7cddfSDavid du Colombier syslog(0, logfile, "%F", &job->request); 4473e12c5d1SDavid du Colombier 4483e12c5d1SDavid du Colombier 4497dd7cddfSDavid du Colombier switch(job->request.type){ 4503e12c5d1SDavid du Colombier default: 4517dd7cddfSDavid du Colombier syslog(1, logfile, "unknown request type %d", job->request.type); 4523e12c5d1SDavid du Colombier break; 4539a747e4fSDavid du Colombier case Tversion: 4549a747e4fSDavid du Colombier rversion(job); 4553e12c5d1SDavid du Colombier break; 4569a747e4fSDavid du Colombier case Tauth: 4579a747e4fSDavid du Colombier rauth(job); 4583e12c5d1SDavid du Colombier break; 4593e12c5d1SDavid du Colombier case Tflush: 4607dd7cddfSDavid du Colombier rflush(job); 4613e12c5d1SDavid du Colombier break; 4623e12c5d1SDavid du Colombier case Tattach: 4637dd7cddfSDavid du Colombier rattach(job, mf); 4643e12c5d1SDavid du Colombier break; 4653e12c5d1SDavid du Colombier case Twalk: 4667dd7cddfSDavid du Colombier rwalk(job, mf); 4673e12c5d1SDavid du Colombier break; 4683e12c5d1SDavid du Colombier case Topen: 4697dd7cddfSDavid du Colombier ropen(job, mf); 4703e12c5d1SDavid du Colombier break; 4713e12c5d1SDavid du Colombier case Tcreate: 4727dd7cddfSDavid du Colombier rcreate(job, mf); 4733e12c5d1SDavid du Colombier break; 4743e12c5d1SDavid du Colombier case Tread: 4757dd7cddfSDavid du Colombier rread(job, mf); 4763e12c5d1SDavid du Colombier break; 4773e12c5d1SDavid du Colombier case Twrite: 4787dd7cddfSDavid du Colombier rwrite(job, mf); 4793e12c5d1SDavid du Colombier break; 4803e12c5d1SDavid du Colombier case Tclunk: 4817dd7cddfSDavid du Colombier rclunk(job, mf); 4823e12c5d1SDavid du Colombier break; 4833e12c5d1SDavid du Colombier case Tremove: 4847dd7cddfSDavid du Colombier rremove(job, mf); 4853e12c5d1SDavid du Colombier break; 4863e12c5d1SDavid du Colombier case Tstat: 4877dd7cddfSDavid du Colombier rstat(job, mf); 4883e12c5d1SDavid du Colombier break; 4893e12c5d1SDavid du Colombier case Twstat: 4907dd7cddfSDavid du Colombier rwstat(job, mf); 4913e12c5d1SDavid du Colombier break; 4923e12c5d1SDavid du Colombier } 493bd389b36SDavid du Colombier unlock(&dblock); 4947dd7cddfSDavid du Colombier 4957dd7cddfSDavid du Colombier freejob(job); 4967dd7cddfSDavid du Colombier 4973e12c5d1SDavid du Colombier /* 4983e12c5d1SDavid du Colombier * slave processes die after replying 4993e12c5d1SDavid du Colombier */ 500219b2ee8SDavid du Colombier if(*isslave){ 501219b2ee8SDavid du Colombier if(debug) 502219b2ee8SDavid du Colombier syslog(0, logfile, "slave death %d", getpid()); 5033e12c5d1SDavid du Colombier _exits(0); 5043e12c5d1SDavid du Colombier } 5053e12c5d1SDavid du Colombier } 506219b2ee8SDavid du Colombier } 507219b2ee8SDavid du Colombier 508219b2ee8SDavid du Colombier void 5099a747e4fSDavid du Colombier rversion(Job *job) 510219b2ee8SDavid du Colombier { 5119a747e4fSDavid du Colombier if(job->request.msize > IOHDRSZ + Maxfdata) 5129a747e4fSDavid du Colombier job->reply.msize = IOHDRSZ + Maxfdata; 5139a747e4fSDavid du Colombier else 5149a747e4fSDavid du Colombier job->reply.msize = job->request.msize; 5159a747e4fSDavid du Colombier if(strncmp(job->request.version, "9P2000", 6) != 0) 5169a747e4fSDavid du Colombier sendmsg(job, "unknown 9P version"); 5179a747e4fSDavid du Colombier else{ 5189a747e4fSDavid du Colombier job->reply.version = "9P2000"; 5197dd7cddfSDavid du Colombier sendmsg(job, 0); 520219b2ee8SDavid du Colombier } 5219a747e4fSDavid du Colombier } 5223e12c5d1SDavid du Colombier 5233e12c5d1SDavid du Colombier void 5249a747e4fSDavid du Colombier rauth(Job *job) 5253e12c5d1SDavid du Colombier { 5263ff48bf5SDavid du Colombier sendmsg(job, "cs: authentication not required"); 5277dd7cddfSDavid du Colombier } 5287dd7cddfSDavid du Colombier 5297dd7cddfSDavid du Colombier /* 5307dd7cddfSDavid du Colombier * don't flush till all the slaves are done 5317dd7cddfSDavid du Colombier */ 5327dd7cddfSDavid du Colombier void 5337dd7cddfSDavid du Colombier rflush(Job *job) 5347dd7cddfSDavid du Colombier { 5357dd7cddfSDavid du Colombier flushjob(job->request.oldtag); 5367dd7cddfSDavid du Colombier sendmsg(job, 0); 5373e12c5d1SDavid du Colombier } 5383e12c5d1SDavid du Colombier 5393e12c5d1SDavid du Colombier void 5407dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf) 5413e12c5d1SDavid du Colombier { 5423e12c5d1SDavid du Colombier if(mf->busy == 0){ 5433e12c5d1SDavid du Colombier mf->busy = 1; 5449a747e4fSDavid du Colombier mf->user = estrdup(job->request.uname); 5453e12c5d1SDavid du Colombier } 5463e12c5d1SDavid du Colombier mf->qid.vers = vers++; 5479a747e4fSDavid du Colombier mf->qid.type = QTDIR; 5489a747e4fSDavid du Colombier mf->qid.path = 0LL; 5497dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 5507dd7cddfSDavid du Colombier sendmsg(job, 0); 5513e12c5d1SDavid du Colombier } 5523e12c5d1SDavid du Colombier 5533e12c5d1SDavid du Colombier 5543e12c5d1SDavid du Colombier char* 5557dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf) 5563e12c5d1SDavid du Colombier { 5573e12c5d1SDavid du Colombier char *err; 5589a747e4fSDavid du Colombier char **elems; 5599a747e4fSDavid du Colombier int nelems; 5609a747e4fSDavid du Colombier int i; 5619a747e4fSDavid du Colombier Mfile *nmf; 5629a747e4fSDavid du Colombier Qid qid; 5633e12c5d1SDavid du Colombier 5643e12c5d1SDavid du Colombier err = 0; 5659a747e4fSDavid du Colombier nmf = nil; 5669a747e4fSDavid du Colombier elems = job->request.wname; 5679a747e4fSDavid du Colombier nelems = job->request.nwname; 5689a747e4fSDavid du Colombier job->reply.nwqid = 0; 5699a747e4fSDavid du Colombier 5709a747e4fSDavid du Colombier if(job->request.newfid != job->request.fid){ 5719a747e4fSDavid du Colombier /* clone fid */ 5729a747e4fSDavid du Colombier nmf = newfid(job->request.newfid); 5739a747e4fSDavid du Colombier if(nmf->busy){ 5749a747e4fSDavid du Colombier nmf = nil; 5759a747e4fSDavid du Colombier err = "clone to used channel"; 5769a747e4fSDavid du Colombier goto send; 5779a747e4fSDavid du Colombier } 5789a747e4fSDavid du Colombier *nmf = *mf; 5799a747e4fSDavid du Colombier nmf->user = estrdup(mf->user); 5809a747e4fSDavid du Colombier nmf->fid = job->request.newfid; 5819a747e4fSDavid du Colombier nmf->qid.vers = vers++; 5829a747e4fSDavid du Colombier mf = nmf; 5839a747e4fSDavid du Colombier } 5849a747e4fSDavid du Colombier /* else nmf will be nil */ 5859a747e4fSDavid du Colombier 5869a747e4fSDavid du Colombier qid = mf->qid; 5879a747e4fSDavid du Colombier if(nelems > 0){ 5889a747e4fSDavid du Colombier /* walk fid */ 5899a747e4fSDavid du Colombier for(i=0; i<nelems && i<MAXWELEM; i++){ 5909a747e4fSDavid du Colombier if((qid.type & QTDIR) == 0){ 5913e12c5d1SDavid du Colombier err = "not a directory"; 5929a747e4fSDavid du Colombier break; 5933e12c5d1SDavid du Colombier } 5949a747e4fSDavid du Colombier if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){ 5959a747e4fSDavid du Colombier qid.type = QTDIR; 5969a747e4fSDavid du Colombier qid.path = Qdir; 5979a747e4fSDavid du Colombier Found: 5989a747e4fSDavid du Colombier job->reply.wqid[i] = qid; 5999a747e4fSDavid du Colombier job->reply.nwqid++; 6009a747e4fSDavid du Colombier continue; 6013e12c5d1SDavid du Colombier } 6029a747e4fSDavid du Colombier if(strcmp(elems[i], "cs") == 0){ 6039a747e4fSDavid du Colombier qid.type = QTFILE; 6049a747e4fSDavid du Colombier qid.path = Qcs; 6059a747e4fSDavid du Colombier goto Found; 6063e12c5d1SDavid du Colombier } 6079a747e4fSDavid du Colombier err = "file does not exist"; 6089a747e4fSDavid du Colombier break; 6099a747e4fSDavid du Colombier } 6109a747e4fSDavid du Colombier } 6119a747e4fSDavid du Colombier 6123e12c5d1SDavid du Colombier send: 6139a747e4fSDavid du Colombier if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)){ 614a9f680aeSDavid du Colombier cleanmf(nmf); 615a9f680aeSDavid du Colombier free(nmf->user); 616a9f680aeSDavid du Colombier nmf->user = 0; 6179a747e4fSDavid du Colombier nmf->busy = 0; 6189a747e4fSDavid du Colombier nmf->fid = 0; 6199a747e4fSDavid du Colombier } 6209a747e4fSDavid du Colombier if(err == nil) 6219a747e4fSDavid du Colombier mf->qid = qid; 6227dd7cddfSDavid du Colombier sendmsg(job, err); 6233e12c5d1SDavid du Colombier return err; 6243e12c5d1SDavid du Colombier } 6253e12c5d1SDavid du Colombier 6263e12c5d1SDavid du Colombier void 6277dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf) 6283e12c5d1SDavid du Colombier { 6293e12c5d1SDavid du Colombier int mode; 6303e12c5d1SDavid du Colombier char *err; 6313e12c5d1SDavid du Colombier 6323e12c5d1SDavid du Colombier err = 0; 6337dd7cddfSDavid du Colombier mode = job->request.mode; 6349a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6353e12c5d1SDavid du Colombier if(mode) 6363e12c5d1SDavid du Colombier err = "permission denied"; 6379a747e4fSDavid du Colombier } 6387dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 6399a747e4fSDavid du Colombier job->reply.iounit = 0; 6407dd7cddfSDavid du Colombier sendmsg(job, err); 6413e12c5d1SDavid du Colombier } 6423e12c5d1SDavid du Colombier 6433e12c5d1SDavid du Colombier void 6447dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf) 6453e12c5d1SDavid du Colombier { 6463e12c5d1SDavid du Colombier USED(mf); 6477dd7cddfSDavid du Colombier sendmsg(job, "creation permission denied"); 6483e12c5d1SDavid du Colombier } 6493e12c5d1SDavid du Colombier 6503e12c5d1SDavid du Colombier void 6517dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf) 6523e12c5d1SDavid du Colombier { 653219b2ee8SDavid du Colombier int i, n, cnt; 654219b2ee8SDavid du Colombier long off, toff, clock; 6553e12c5d1SDavid du Colombier Dir dir; 656*254fe3d3SDavid du Colombier uchar buf[Maxfdata]; 6573e12c5d1SDavid du Colombier char *err; 6583e12c5d1SDavid du Colombier 6593e12c5d1SDavid du Colombier n = 0; 6603e12c5d1SDavid du Colombier err = 0; 6617dd7cddfSDavid du Colombier off = job->request.offset; 6627dd7cddfSDavid du Colombier cnt = job->request.count; 6639a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6643e12c5d1SDavid du Colombier clock = time(0); 6653e12c5d1SDavid du Colombier if(off == 0){ 6666aaebd7dSDavid du Colombier memset(&dir, 0, sizeof dir); 6679a747e4fSDavid du Colombier dir.name = "cs"; 6689a747e4fSDavid du Colombier dir.qid.type = QTFILE; 6693e12c5d1SDavid du Colombier dir.qid.vers = vers; 6703e12c5d1SDavid du Colombier dir.qid.path = Qcs; 6713e12c5d1SDavid du Colombier dir.mode = 0666; 6723e12c5d1SDavid du Colombier dir.length = 0; 6739a747e4fSDavid du Colombier dir.uid = mf->user; 6749a747e4fSDavid du Colombier dir.gid = mf->user; 6759a747e4fSDavid du Colombier dir.muid = mf->user; 6763e12c5d1SDavid du Colombier dir.atime = clock; /* wrong */ 6773e12c5d1SDavid du Colombier dir.mtime = clock; /* wrong */ 6789a747e4fSDavid du Colombier n = convD2M(&dir, buf, sizeof buf); 6793e12c5d1SDavid du Colombier } 6809a747e4fSDavid du Colombier job->reply.data = (char*)buf; 6813e12c5d1SDavid du Colombier } else { 68280ee5cbfSDavid du Colombier for(;;){ 68380ee5cbfSDavid du Colombier /* look for an answer at the right offset */ 684219b2ee8SDavid du Colombier toff = 0; 685219b2ee8SDavid du Colombier for(i = 0; mf->reply[i] && i < mf->nreply; i++){ 686219b2ee8SDavid du Colombier n = mf->replylen[i]; 687219b2ee8SDavid du Colombier if(off < toff + n) 688219b2ee8SDavid du Colombier break; 689219b2ee8SDavid du Colombier toff += n; 6903e12c5d1SDavid du Colombier } 69180ee5cbfSDavid du Colombier if(i < mf->nreply) 69280ee5cbfSDavid du Colombier break; /* got something to return */ 69380ee5cbfSDavid du Colombier 69480ee5cbfSDavid du Colombier /* try looking up more answers */ 69580ee5cbfSDavid du Colombier if(lookup(mf) == 0){ 69680ee5cbfSDavid du Colombier /* no more */ 697219b2ee8SDavid du Colombier n = 0; 698219b2ee8SDavid du Colombier goto send; 699219b2ee8SDavid du Colombier } 70080ee5cbfSDavid du Colombier } 70180ee5cbfSDavid du Colombier 70280ee5cbfSDavid du Colombier /* give back a single reply (or part of one) */ 7037dd7cddfSDavid du Colombier job->reply.data = mf->reply[i] + (off - toff); 704219b2ee8SDavid du Colombier if(cnt > toff - off + n) 705219b2ee8SDavid du Colombier n = toff - off + n; 706219b2ee8SDavid du Colombier else 707219b2ee8SDavid du Colombier n = cnt; 7083e12c5d1SDavid du Colombier } 7093e12c5d1SDavid du Colombier send: 7107dd7cddfSDavid du Colombier job->reply.count = n; 7117dd7cddfSDavid du Colombier sendmsg(job, err); 7127dd7cddfSDavid du Colombier } 71380ee5cbfSDavid du Colombier void 71480ee5cbfSDavid du Colombier cleanmf(Mfile *mf) 7157dd7cddfSDavid du Colombier { 7167dd7cddfSDavid du Colombier int i; 7177dd7cddfSDavid du Colombier 7189a747e4fSDavid du Colombier if(mf->net != nil){ 71980ee5cbfSDavid du Colombier free(mf->net); 72080ee5cbfSDavid du Colombier mf->net = nil; 7219a747e4fSDavid du Colombier } 7229a747e4fSDavid du Colombier if(mf->host != nil){ 72380ee5cbfSDavid du Colombier free(mf->host); 72480ee5cbfSDavid du Colombier mf->host = nil; 7259a747e4fSDavid du Colombier } 7269a747e4fSDavid du Colombier if(mf->serv != nil){ 72780ee5cbfSDavid du Colombier free(mf->serv); 72880ee5cbfSDavid du Colombier mf->serv = nil; 7299a747e4fSDavid du Colombier } 7309a747e4fSDavid du Colombier if(mf->rem != nil){ 73180ee5cbfSDavid du Colombier free(mf->rem); 73280ee5cbfSDavid du Colombier mf->rem = nil; 7339a747e4fSDavid du Colombier } 73480ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++){ 73580ee5cbfSDavid du Colombier free(mf->reply[i]); 73680ee5cbfSDavid du Colombier mf->reply[i] = nil; 73780ee5cbfSDavid du Colombier mf->replylen[i] = 0; 7387dd7cddfSDavid du Colombier } 73980ee5cbfSDavid du Colombier mf->nreply = 0; 74080ee5cbfSDavid du Colombier mf->nextnet = netlist; 7413e12c5d1SDavid du Colombier } 7423e12c5d1SDavid du Colombier 7433e12c5d1SDavid du Colombier void 7447dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf) 7453e12c5d1SDavid du Colombier { 7463e12c5d1SDavid du Colombier int cnt, n; 74780ee5cbfSDavid du Colombier char *err; 7487dd7cddfSDavid du Colombier char *field[4]; 749271b8d73SDavid du Colombier char curerr[64]; 7503e12c5d1SDavid du Colombier 7513e12c5d1SDavid du Colombier err = 0; 7527dd7cddfSDavid du Colombier cnt = job->request.count; 7539a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 7543e12c5d1SDavid du Colombier err = "can't write directory"; 7553e12c5d1SDavid du Colombier goto send; 7563e12c5d1SDavid du Colombier } 7573e12c5d1SDavid du Colombier if(cnt >= Maxrequest){ 7583e12c5d1SDavid du Colombier err = "request too long"; 7593e12c5d1SDavid du Colombier goto send; 7603e12c5d1SDavid du Colombier } 7617dd7cddfSDavid du Colombier job->request.data[cnt] = 0; 7623e12c5d1SDavid du Colombier 7633e12c5d1SDavid du Colombier /* 764219b2ee8SDavid du Colombier * toggle debugging 765219b2ee8SDavid du Colombier */ 7667dd7cddfSDavid du Colombier if(strncmp(job->request.data, "debug", 5)==0){ 767219b2ee8SDavid du Colombier debug ^= 1; 768219b2ee8SDavid du Colombier syslog(1, logfile, "debug %d", debug); 769219b2ee8SDavid du Colombier goto send; 770219b2ee8SDavid du Colombier } 771219b2ee8SDavid du Colombier 772219b2ee8SDavid du Colombier /* 7737dd7cddfSDavid du Colombier * toggle debugging 7747dd7cddfSDavid du Colombier */ 7757dd7cddfSDavid du Colombier if(strncmp(job->request.data, "paranoia", 8)==0){ 7767dd7cddfSDavid du Colombier paranoia ^= 1; 7777dd7cddfSDavid du Colombier syslog(1, logfile, "paranoia %d", paranoia); 7787dd7cddfSDavid du Colombier goto send; 7797dd7cddfSDavid du Colombier } 7807dd7cddfSDavid du Colombier 7817dd7cddfSDavid du Colombier /* 7823e12c5d1SDavid du Colombier * add networks to the default list 7833e12c5d1SDavid du Colombier */ 7847dd7cddfSDavid du Colombier if(strncmp(job->request.data, "add ", 4)==0){ 7857dd7cddfSDavid du Colombier if(job->request.data[cnt-1] == '\n') 7867dd7cddfSDavid du Colombier job->request.data[cnt-1] = 0; 7877dd7cddfSDavid du Colombier netadd(job->request.data+4); 7887dd7cddfSDavid du Colombier readipinterfaces(); 7897dd7cddfSDavid du Colombier goto send; 7907dd7cddfSDavid du Colombier } 7917dd7cddfSDavid du Colombier 7927dd7cddfSDavid du Colombier /* 7937dd7cddfSDavid du Colombier * refresh all state 7947dd7cddfSDavid du Colombier */ 7957dd7cddfSDavid du Colombier if(strncmp(job->request.data, "refresh", 7)==0){ 7967dd7cddfSDavid du Colombier netinit(1); 7973e12c5d1SDavid du Colombier goto send; 7983e12c5d1SDavid du Colombier } 7993e12c5d1SDavid du Colombier 80080ee5cbfSDavid du Colombier /* start transaction with a clean slate */ 80180ee5cbfSDavid du Colombier cleanmf(mf); 80280ee5cbfSDavid du Colombier 8033e12c5d1SDavid du Colombier /* 804219b2ee8SDavid du Colombier * look for a general query 805219b2ee8SDavid du Colombier */ 8067dd7cddfSDavid du Colombier if(*job->request.data == '!'){ 8077dd7cddfSDavid du Colombier err = genquery(mf, job->request.data+1); 808219b2ee8SDavid du Colombier goto send; 809219b2ee8SDavid du Colombier } 810219b2ee8SDavid du Colombier 8117dd7cddfSDavid du Colombier if(debug) 8127dd7cddfSDavid du Colombier syslog(0, logfile, "write %s", job->request.data); 8137dd7cddfSDavid du Colombier if(paranoia) 8147dd7cddfSDavid du Colombier syslog(0, paranoiafile, "write %s by %s", job->request.data, mf->user); 8157dd7cddfSDavid du Colombier 816219b2ee8SDavid du Colombier /* 8173e12c5d1SDavid du Colombier * break up name 8183e12c5d1SDavid du Colombier */ 8197dd7cddfSDavid du Colombier n = getfields(job->request.data, field, 4, 1, "!"); 8203e12c5d1SDavid du Colombier switch(n){ 8213e12c5d1SDavid du Colombier case 1: 82280ee5cbfSDavid du Colombier mf->net = strdup("net"); 82380ee5cbfSDavid du Colombier mf->host = strdup(field[0]); 8247dd7cddfSDavid du Colombier break; 8257dd7cddfSDavid du Colombier case 4: 82680ee5cbfSDavid du Colombier mf->rem = strdup(field[3]); 82780ee5cbfSDavid du Colombier /* fall through */ 82880ee5cbfSDavid du Colombier case 3: 82980ee5cbfSDavid du Colombier mf->serv = strdup(field[2]); 83080ee5cbfSDavid du Colombier /* fall through */ 83180ee5cbfSDavid du Colombier case 2: 83280ee5cbfSDavid du Colombier mf->host = strdup(field[1]); 83380ee5cbfSDavid du Colombier mf->net = strdup(field[0]); 8343e12c5d1SDavid du Colombier break; 8353e12c5d1SDavid du Colombier } 8363e12c5d1SDavid du Colombier 83780ee5cbfSDavid du Colombier /* 83880ee5cbfSDavid du Colombier * do the first net worth of lookup 83980ee5cbfSDavid du Colombier */ 840271b8d73SDavid du Colombier if(lookup(mf) == 0){ 841271b8d73SDavid du Colombier rerrstr(curerr, sizeof curerr); 842271b8d73SDavid du Colombier err = curerr; 843271b8d73SDavid du Colombier } 8443e12c5d1SDavid du Colombier send: 8457dd7cddfSDavid du Colombier job->reply.count = cnt; 8467dd7cddfSDavid du Colombier sendmsg(job, err); 8473e12c5d1SDavid du Colombier } 8483e12c5d1SDavid du Colombier 8493e12c5d1SDavid du Colombier void 8507dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf) 8513e12c5d1SDavid du Colombier { 85280ee5cbfSDavid du Colombier cleanmf(mf); 853a9f680aeSDavid du Colombier free(mf->user); 854a9f680aeSDavid du Colombier mf->user = 0; 8553e12c5d1SDavid du Colombier mf->busy = 0; 8563e12c5d1SDavid du Colombier mf->fid = 0; 8577dd7cddfSDavid du Colombier sendmsg(job, 0); 8583e12c5d1SDavid du Colombier } 8593e12c5d1SDavid du Colombier 8603e12c5d1SDavid du Colombier void 8617dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf) 8623e12c5d1SDavid du Colombier { 8633e12c5d1SDavid du Colombier USED(mf); 8647dd7cddfSDavid du Colombier sendmsg(job, "remove permission denied"); 8653e12c5d1SDavid du Colombier } 8663e12c5d1SDavid du Colombier 8673e12c5d1SDavid du Colombier void 8687dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf) 8693e12c5d1SDavid du Colombier { 8703e12c5d1SDavid du Colombier Dir dir; 8719a747e4fSDavid du Colombier uchar buf[IOHDRSZ+Maxfdata]; 8723e12c5d1SDavid du Colombier 8736aaebd7dSDavid du Colombier memset(&dir, 0, sizeof dir); 8749a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 8759a747e4fSDavid du Colombier dir.name = "."; 8769a747e4fSDavid du Colombier dir.mode = DMDIR|0555; 877219b2ee8SDavid du Colombier } else { 8789a747e4fSDavid du Colombier dir.name = "cs"; 8793e12c5d1SDavid du Colombier dir.mode = 0666; 880219b2ee8SDavid du Colombier } 881219b2ee8SDavid du Colombier dir.qid = mf->qid; 8823e12c5d1SDavid du Colombier dir.length = 0; 8839a747e4fSDavid du Colombier dir.uid = mf->user; 8849a747e4fSDavid du Colombier dir.gid = mf->user; 8859a747e4fSDavid du Colombier dir.muid = mf->user; 8863e12c5d1SDavid du Colombier dir.atime = dir.mtime = time(0); 8879a747e4fSDavid du Colombier job->reply.nstat = convD2M(&dir, buf, sizeof buf); 8889a747e4fSDavid du Colombier job->reply.stat = buf; 8897dd7cddfSDavid du Colombier sendmsg(job, 0); 8903e12c5d1SDavid du Colombier } 8913e12c5d1SDavid du Colombier 8923e12c5d1SDavid du Colombier void 8937dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf) 8943e12c5d1SDavid du Colombier { 8953e12c5d1SDavid du Colombier USED(mf); 8967dd7cddfSDavid du Colombier sendmsg(job, "wstat permission denied"); 8973e12c5d1SDavid du Colombier } 8983e12c5d1SDavid du Colombier 8993e12c5d1SDavid du Colombier void 9007dd7cddfSDavid du Colombier sendmsg(Job *job, char *err) 9013e12c5d1SDavid du Colombier { 9023e12c5d1SDavid du Colombier int n; 9039a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 9049a747e4fSDavid du Colombier char ename[ERRMAX]; 9053e12c5d1SDavid du Colombier 9063e12c5d1SDavid du Colombier if(err){ 9077dd7cddfSDavid du Colombier job->reply.type = Rerror; 9089a747e4fSDavid du Colombier snprint(ename, sizeof(ename), "cs: %s", err); 9099a747e4fSDavid du Colombier job->reply.ename = ename; 9103e12c5d1SDavid du Colombier }else{ 9117dd7cddfSDavid du Colombier job->reply.type = job->request.type+1; 9123e12c5d1SDavid du Colombier } 9137dd7cddfSDavid du Colombier job->reply.tag = job->request.tag; 9149a747e4fSDavid du Colombier n = convS2M(&job->reply, mdata, sizeof mdata); 915219b2ee8SDavid du Colombier if(n == 0){ 9167dd7cddfSDavid du Colombier syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply); 917219b2ee8SDavid du Colombier abort(); 918219b2ee8SDavid du Colombier } 9197dd7cddfSDavid du Colombier lock(&joblock); 9207dd7cddfSDavid du Colombier if(job->flushed == 0) 9219a747e4fSDavid du Colombier if(write(mfd[1], mdata, n)!=n) 9223e12c5d1SDavid du Colombier error("mount write"); 9237dd7cddfSDavid du Colombier unlock(&joblock); 924219b2ee8SDavid du Colombier if(debug) 9257dd7cddfSDavid du Colombier syslog(0, logfile, "%F %d", &job->reply, n); 9263e12c5d1SDavid du Colombier } 9273e12c5d1SDavid du Colombier 9283e12c5d1SDavid du Colombier void 9293e12c5d1SDavid du Colombier error(char *s) 9303e12c5d1SDavid du Colombier { 931bd389b36SDavid du Colombier syslog(1, "cs", "%s: %r", s); 932bd389b36SDavid du Colombier _exits(0); 9333e12c5d1SDavid du Colombier } 9343e12c5d1SDavid du Colombier 9357dd7cddfSDavid du Colombier static int 9367dd7cddfSDavid du Colombier isvalidip(uchar *ip) 9377dd7cddfSDavid du Colombier { 9387dd7cddfSDavid du Colombier return ipcmp(ip, IPnoaddr) != 0 && ipcmp(ip, v4prefix) != 0; 9397dd7cddfSDavid du Colombier } 9403e12c5d1SDavid du Colombier 9410103620dSDavid du Colombier static uchar loopbacknet[IPaddrlen] = { 9420103620dSDavid du Colombier 0, 0, 0, 0, 9430103620dSDavid du Colombier 0, 0, 0, 0, 9440103620dSDavid du Colombier 0, 0, 0xff, 0xff, 9450103620dSDavid du Colombier 127, 0, 0, 0 9460103620dSDavid du Colombier }; 9470103620dSDavid du Colombier static uchar loopbackmask[IPaddrlen] = { 9480103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9490103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9500103620dSDavid du Colombier 0xff, 0xff, 0xff, 0xff, 9510103620dSDavid du Colombier 0xff, 0, 0, 0 9520103620dSDavid du Colombier }; 9530103620dSDavid du Colombier 9547dd7cddfSDavid du Colombier void 9557dd7cddfSDavid du Colombier readipinterfaces(void) 9567dd7cddfSDavid du Colombier { 9570103620dSDavid du Colombier if(myipaddr(ipa, mntpt) != 0) 9580103620dSDavid du Colombier ipmove(ipa, IPnoaddr); 9597dd7cddfSDavid du Colombier sprint(ipaddr, "%I", ipa); 9607dd7cddfSDavid du Colombier if (debug) 9617dd7cddfSDavid du Colombier syslog(0, "dns", "ipaddr is %s\n", ipaddr); 9627dd7cddfSDavid du Colombier } 9633e12c5d1SDavid du Colombier 9643e12c5d1SDavid du Colombier /* 9657dd7cddfSDavid du Colombier * get the system name 9663e12c5d1SDavid du Colombier */ 9673e12c5d1SDavid du Colombier void 9683e12c5d1SDavid du Colombier ipid(void) 9693e12c5d1SDavid du Colombier { 9703e12c5d1SDavid du Colombier uchar addr[6]; 971a9f680aeSDavid du Colombier Ndbtuple *t, *tt; 972219b2ee8SDavid du Colombier char *p, *attr; 9733e12c5d1SDavid du Colombier Ndbs s; 9743e12c5d1SDavid du Colombier int f; 9757dd7cddfSDavid du Colombier char buf[Maxpath]; 9763e12c5d1SDavid du Colombier 977219b2ee8SDavid du Colombier /* use environment, ether addr, or ipaddr to get system name */ 97895a264b3SDavid du Colombier if(mysysname == 0){ 9797dd7cddfSDavid du Colombier /* 9807dd7cddfSDavid du Colombier * environment has priority. 9817dd7cddfSDavid du Colombier * 9827dd7cddfSDavid du Colombier * on the sgi power the default system name 9837dd7cddfSDavid du Colombier * is the ip address. ignore that. 9847dd7cddfSDavid du Colombier * 9857dd7cddfSDavid du Colombier */ 986219b2ee8SDavid du Colombier p = getenv("sysname"); 987447d6a7dSDavid du Colombier if(p && *p){ 988219b2ee8SDavid du Colombier attr = ipattr(p); 989219b2ee8SDavid du Colombier if(strcmp(attr, "ip") != 0) 99095a264b3SDavid du Colombier mysysname = strdup(p); 9913e12c5d1SDavid du Colombier } 9923e12c5d1SDavid du Colombier 9933e12c5d1SDavid du Colombier /* 9947dd7cddfSDavid du Colombier * the /net/ndb contains what the network 9957dd7cddfSDavid du Colombier * figured out from DHCP. use that name if 9967dd7cddfSDavid du Colombier * there is one. 9973e12c5d1SDavid du Colombier */ 99895a264b3SDavid du Colombier if(mysysname == 0 && netdb != nil){ 9997dd7cddfSDavid du Colombier ndbreopen(netdb); 1000a9f680aeSDavid du Colombier for(tt = t = ndbparse(netdb); t != nil; t = t->entry){ 10017dd7cddfSDavid du Colombier if(strcmp(t->attr, "sys") == 0){ 100295a264b3SDavid du Colombier mysysname = strdup(t->val); 10033e12c5d1SDavid du Colombier break; 10043e12c5d1SDavid du Colombier } 10057dd7cddfSDavid du Colombier } 1006a9f680aeSDavid du Colombier ndbfree(tt); 10077dd7cddfSDavid du Colombier } 10087dd7cddfSDavid du Colombier 10097dd7cddfSDavid du Colombier /* next network database, ip address, and ether address to find a name */ 101095a264b3SDavid du Colombier if(mysysname == 0){ 10117dd7cddfSDavid du Colombier t = nil; 10127dd7cddfSDavid du Colombier if(isvalidip(ipa)) 101357837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "ip", ipaddr, "sys", &t)); 101495a264b3SDavid du Colombier if(t == nil){ 10157dd7cddfSDavid du Colombier for(f = 0; f < 3; f++){ 10167dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/ether%d", mntpt, f); 10177dd7cddfSDavid du Colombier if(myetheraddr(addr, buf) >= 0){ 10187dd7cddfSDavid du Colombier snprint(eaddr, sizeof(eaddr), "%E", addr); 101957837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "ether", eaddr, "sys", &t)); 10207dd7cddfSDavid du Colombier if(t != nil) 10217dd7cddfSDavid du Colombier break; 10227dd7cddfSDavid du Colombier } 10237dd7cddfSDavid du Colombier } 10247dd7cddfSDavid du Colombier } 1025b7327ca2SDavid du Colombier for(tt = t; tt != nil; tt = tt->entry){ 1026b7327ca2SDavid du Colombier if(strcmp(tt->attr, "sys") == 0){ 1027b7327ca2SDavid du Colombier mysysname = strdup(tt->val); 102895a264b3SDavid du Colombier break; 102995a264b3SDavid du Colombier } 1030b7327ca2SDavid du Colombier } 10317dd7cddfSDavid du Colombier ndbfree(t); 10327dd7cddfSDavid du Colombier } 10337dd7cddfSDavid du Colombier 103480ee5cbfSDavid du Colombier /* nothing else worked, use the ip address */ 103595a264b3SDavid du Colombier if(mysysname == 0 && isvalidip(ipa)) 103695a264b3SDavid du Colombier mysysname = strdup(ipaddr); 103780ee5cbfSDavid du Colombier 103880ee5cbfSDavid du Colombier 1039dc5a79c1SDavid du Colombier /* set /dev/sysname if we now know it */ 104095a264b3SDavid du Colombier if(mysysname){ 10417dd7cddfSDavid du Colombier f = open("/dev/sysname", OWRITE); 10427dd7cddfSDavid du Colombier if(f >= 0){ 10437dd7cddfSDavid du Colombier write(f, mysysname, strlen(mysysname)); 10443e12c5d1SDavid du Colombier close(f); 10453e12c5d1SDavid du Colombier } 10463e12c5d1SDavid du Colombier } 10473e12c5d1SDavid du Colombier } 10483e12c5d1SDavid du Colombier } 10493e12c5d1SDavid du Colombier 10503e12c5d1SDavid du Colombier /* 10513e12c5d1SDavid du Colombier * Set up a list of default networks by looking for 1052*254fe3d3SDavid du Colombier * /net/^*^/clone. 10533e12c5d1SDavid du Colombier */ 10543e12c5d1SDavid du Colombier void 10557dd7cddfSDavid du Colombier netinit(int background) 10563e12c5d1SDavid du Colombier { 10577dd7cddfSDavid du Colombier char clone[Maxpath]; 10583e12c5d1SDavid du Colombier Network *np; 10597dd7cddfSDavid du Colombier static int working; 10607dd7cddfSDavid du Colombier 10617dd7cddfSDavid du Colombier if(background){ 10627dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 10637dd7cddfSDavid du Colombier case 0: 10647dd7cddfSDavid du Colombier break; 10657dd7cddfSDavid du Colombier default: 10667dd7cddfSDavid du Colombier return; 10677dd7cddfSDavid du Colombier } 10687dd7cddfSDavid du Colombier lock(&netlock); 10697dd7cddfSDavid du Colombier } 10703e12c5d1SDavid du Colombier 10713e12c5d1SDavid du Colombier /* add the mounted networks to the default list */ 10723e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 10737dd7cddfSDavid du Colombier if(np->considered) 10747dd7cddfSDavid du Colombier continue; 10757dd7cddfSDavid du Colombier snprint(clone, sizeof(clone), "%s/%s/clone", mntpt, np->net); 10769a747e4fSDavid du Colombier if(access(clone, AEXIST) < 0) 10773e12c5d1SDavid du Colombier continue; 10783e12c5d1SDavid du Colombier if(netlist) 10793e12c5d1SDavid du Colombier last->next = np; 10803e12c5d1SDavid du Colombier else 10813e12c5d1SDavid du Colombier netlist = np; 10823e12c5d1SDavid du Colombier last = np; 10833e12c5d1SDavid du Colombier np->next = 0; 10847dd7cddfSDavid du Colombier np->considered = 1; 10853e12c5d1SDavid du Colombier } 10863e12c5d1SDavid du Colombier 10877dd7cddfSDavid du Colombier /* find out what our ip address is */ 10887dd7cddfSDavid du Colombier readipinterfaces(); 10893e12c5d1SDavid du Colombier 10907dd7cddfSDavid du Colombier /* set the system name if we need to, these says ip is all we have */ 10913e12c5d1SDavid du Colombier ipid(); 10923e12c5d1SDavid du Colombier 1093219b2ee8SDavid du Colombier if(debug) 10947dd7cddfSDavid du Colombier syslog(0, logfile, "mysysname %s eaddr %s ipaddr %s ipa %I\n", 109595a264b3SDavid du Colombier mysysname?mysysname:"???", eaddr, ipaddr, ipa); 10967dd7cddfSDavid du Colombier 10977dd7cddfSDavid du Colombier if(background){ 10987dd7cddfSDavid du Colombier unlock(&netlock); 10997dd7cddfSDavid du Colombier _exits(0); 11007dd7cddfSDavid du Colombier } 11013e12c5d1SDavid du Colombier } 11023e12c5d1SDavid du Colombier 11033e12c5d1SDavid du Colombier /* 11043e12c5d1SDavid du Colombier * add networks to the standard list 11053e12c5d1SDavid du Colombier */ 11063e12c5d1SDavid du Colombier void 11073e12c5d1SDavid du Colombier netadd(char *p) 11083e12c5d1SDavid du Colombier { 11093e12c5d1SDavid du Colombier Network *np; 11103e12c5d1SDavid du Colombier char *field[12]; 11113e12c5d1SDavid du Colombier int i, n; 11123e12c5d1SDavid du Colombier 11137dd7cddfSDavid du Colombier n = getfields(p, field, 12, 1, " "); 11143e12c5d1SDavid du Colombier for(i = 0; i < n; i++){ 11153e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 11163e12c5d1SDavid du Colombier if(strcmp(field[i], np->net) != 0) 11173e12c5d1SDavid du Colombier continue; 11187dd7cddfSDavid du Colombier if(np->considered) 11193e12c5d1SDavid du Colombier break; 11203e12c5d1SDavid du Colombier if(netlist) 11213e12c5d1SDavid du Colombier last->next = np; 11223e12c5d1SDavid du Colombier else 11233e12c5d1SDavid du Colombier netlist = np; 11243e12c5d1SDavid du Colombier last = np; 11253e12c5d1SDavid du Colombier np->next = 0; 11267dd7cddfSDavid du Colombier np->considered = 1; 11273e12c5d1SDavid du Colombier } 11283e12c5d1SDavid du Colombier } 11293e12c5d1SDavid du Colombier } 11303e12c5d1SDavid du Colombier 113180ee5cbfSDavid du Colombier int 113280ee5cbfSDavid du Colombier lookforproto(Ndbtuple *t, char *proto) 113380ee5cbfSDavid du Colombier { 113480ee5cbfSDavid du Colombier for(; t != nil; t = t->entry) 113580ee5cbfSDavid du Colombier if(strcmp(t->attr, "proto") == 0 && strcmp(t->val, proto) == 0) 113680ee5cbfSDavid du Colombier return 1; 113780ee5cbfSDavid du Colombier return 0; 113880ee5cbfSDavid du Colombier } 113980ee5cbfSDavid du Colombier 1140219b2ee8SDavid du Colombier /* 11413e12c5d1SDavid du Colombier * lookup a request. the network "net" means we should pick the 11423e12c5d1SDavid du Colombier * best network to get there. 11433e12c5d1SDavid du Colombier */ 11443e12c5d1SDavid du Colombier int 114580ee5cbfSDavid du Colombier lookup(Mfile *mf) 11463e12c5d1SDavid du Colombier { 114780ee5cbfSDavid du Colombier Network *np; 1148219b2ee8SDavid du Colombier char *cp; 1149219b2ee8SDavid du Colombier Ndbtuple *nt, *t; 1150219b2ee8SDavid du Colombier char reply[Maxreply]; 115180ee5cbfSDavid du Colombier int i, rv; 115280ee5cbfSDavid du Colombier int hack; 11533e12c5d1SDavid du Colombier 11543e12c5d1SDavid du Colombier /* open up the standard db files */ 11553e12c5d1SDavid du Colombier if(db == 0) 11567dd7cddfSDavid du Colombier ndbinit(); 11573e12c5d1SDavid du Colombier if(db == 0) 115880ee5cbfSDavid du Colombier error("can't open mf->network database\n"); 11593e12c5d1SDavid du Colombier 116080ee5cbfSDavid du Colombier rv = 0; 116180ee5cbfSDavid du Colombier 116280ee5cbfSDavid du Colombier if(mf->net == nil) 116380ee5cbfSDavid du Colombier return 0; /* must have been a genquery */ 116480ee5cbfSDavid du Colombier 116580ee5cbfSDavid du Colombier if(strcmp(mf->net, "net") == 0){ 11663e12c5d1SDavid du Colombier /* 11673e12c5d1SDavid du Colombier * go through set of default nets 11683e12c5d1SDavid du Colombier */ 116980ee5cbfSDavid du Colombier for(np = mf->nextnet; np; np = np->next){ 117080ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 117180ee5cbfSDavid du Colombier if(nt == nil) 1172219b2ee8SDavid du Colombier continue; 117380ee5cbfSDavid du Colombier hack = np->fasttimeouthack && !lookforproto(nt, np->net); 117480ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 117580ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, hack); 1176219b2ee8SDavid du Colombier if(cp){ 117780ee5cbfSDavid du Colombier /* avoid duplicates */ 117880ee5cbfSDavid du Colombier for(i = 0; i < mf->nreply; i++) 117980ee5cbfSDavid du Colombier if(strcmp(mf->reply[i], cp) == 0) 118080ee5cbfSDavid du Colombier break; 118180ee5cbfSDavid du Colombier if(i == mf->nreply){ 118280ee5cbfSDavid du Colombier /* save the reply */ 1183219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 1184219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = cp; 118580ee5cbfSDavid du Colombier rv++; 1186219b2ee8SDavid du Colombier } 1187219b2ee8SDavid du Colombier } 1188219b2ee8SDavid du Colombier } 1189219b2ee8SDavid du Colombier ndbfree(nt); 119080ee5cbfSDavid du Colombier np = np->next; 119180ee5cbfSDavid du Colombier break; 119280ee5cbfSDavid du Colombier } 119380ee5cbfSDavid du Colombier mf->nextnet = np; 119480ee5cbfSDavid du Colombier return rv; 119580ee5cbfSDavid du Colombier } 119680ee5cbfSDavid du Colombier 119780ee5cbfSDavid du Colombier /* 119880ee5cbfSDavid du Colombier * if not /net, we only get one lookup 119980ee5cbfSDavid du Colombier */ 120080ee5cbfSDavid du Colombier if(mf->nreply != 0) 1201219b2ee8SDavid du Colombier return 0; 120280ee5cbfSDavid du Colombier /* 120380ee5cbfSDavid du Colombier * look for a specific network 120480ee5cbfSDavid du Colombier */ 120595a264b3SDavid du Colombier for(np = netlist; np && np->net != nil; np++){ 120680ee5cbfSDavid du Colombier if(np->fasttimeouthack) 120780ee5cbfSDavid du Colombier continue; 120880ee5cbfSDavid du Colombier if(strcmp(np->net, mf->net) == 0) 120980ee5cbfSDavid du Colombier break; 121080ee5cbfSDavid du Colombier } 121180ee5cbfSDavid du Colombier 121295a264b3SDavid du Colombier if(np && np->net != nil){ 121380ee5cbfSDavid du Colombier /* 121480ee5cbfSDavid du Colombier * known network 121580ee5cbfSDavid du Colombier */ 121680ee5cbfSDavid du Colombier nt = (*np->lookup)(np, mf->host, mf->serv, 1); 121780ee5cbfSDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 121880ee5cbfSDavid du Colombier cp = (*np->trans)(t, np, mf->serv, mf->rem, 0); 121980ee5cbfSDavid du Colombier if(cp){ 122080ee5cbfSDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 122180ee5cbfSDavid du Colombier mf->reply[mf->nreply++] = cp; 122280ee5cbfSDavid du Colombier rv++; 122380ee5cbfSDavid du Colombier } 122480ee5cbfSDavid du Colombier } 122580ee5cbfSDavid du Colombier ndbfree(nt); 122680ee5cbfSDavid du Colombier return rv; 12273e12c5d1SDavid du Colombier } else { 12283e12c5d1SDavid du Colombier /* 1229219b2ee8SDavid du Colombier * not a known network, don't translate host or service 12303e12c5d1SDavid du Colombier */ 123180ee5cbfSDavid du Colombier if(mf->serv) 12327dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s", 123380ee5cbfSDavid du Colombier mntpt, mf->net, mf->host, mf->serv); 1234bd389b36SDavid du Colombier else 12357dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s", 123680ee5cbfSDavid du Colombier mntpt, mf->net, mf->host); 1237219b2ee8SDavid du Colombier mf->reply[0] = strdup(reply); 1238219b2ee8SDavid du Colombier mf->replylen[0] = strlen(reply); 1239219b2ee8SDavid du Colombier mf->nreply = 1; 124080ee5cbfSDavid du Colombier return 1; 12413e12c5d1SDavid du Colombier } 12423e12c5d1SDavid du Colombier } 12433e12c5d1SDavid du Colombier 12443e12c5d1SDavid du Colombier /* 12453e12c5d1SDavid du Colombier * translate an ip service name into a port number. If it's a numeric port 12463e12c5d1SDavid du Colombier * number, look for restricted access. 12473e12c5d1SDavid du Colombier * 12483e12c5d1SDavid du Colombier * the service '*' needs no translation. 12493e12c5d1SDavid du Colombier */ 12503e12c5d1SDavid du Colombier char* 125195a264b3SDavid du Colombier ipserv(Network *np, char *name, char *buf, int blen) 12523e12c5d1SDavid du Colombier { 12533e12c5d1SDavid du Colombier char *p; 12543e12c5d1SDavid du Colombier int alpha = 0; 12553e12c5d1SDavid du Colombier int restr = 0; 125695a264b3SDavid du Colombier char port[10]; 12573e12c5d1SDavid du Colombier Ndbtuple *t, *nt; 12583e12c5d1SDavid du Colombier Ndbs s; 12593e12c5d1SDavid du Colombier 12603e12c5d1SDavid du Colombier /* '*' means any service */ 12613e12c5d1SDavid du Colombier if(strcmp(name, "*")==0){ 12623e12c5d1SDavid du Colombier strcpy(buf, name); 12633e12c5d1SDavid du Colombier return buf; 12643e12c5d1SDavid du Colombier } 12653e12c5d1SDavid du Colombier 12663e12c5d1SDavid du Colombier /* see if it's numeric or symbolic */ 12673e12c5d1SDavid du Colombier port[0] = 0; 12683e12c5d1SDavid du Colombier for(p = name; *p; p++){ 12693e12c5d1SDavid du Colombier if(isdigit(*p)) 12709a747e4fSDavid du Colombier {} 12713e12c5d1SDavid du Colombier else if(isalpha(*p) || *p == '-' || *p == '$') 12723e12c5d1SDavid du Colombier alpha = 1; 12733e12c5d1SDavid du Colombier else 12743e12c5d1SDavid du Colombier return 0; 12753e12c5d1SDavid du Colombier } 127657837e0bSDavid du Colombier t = nil; 127757837e0bSDavid du Colombier p = nil; 12783e12c5d1SDavid du Colombier if(alpha){ 127957837e0bSDavid du Colombier p = ndbgetvalue(db, &s, np->net, name, "port", &t); 1280b7327ca2SDavid du Colombier if(p == nil) 1281b7327ca2SDavid du Colombier return 0; 12823e12c5d1SDavid du Colombier } else { 12833cc1eb97SDavid du Colombier /* look up only for tcp ports < 1024 to get the restricted 12843cc1eb97SDavid du Colombier * attribute 12853cc1eb97SDavid du Colombier */ 12863cc1eb97SDavid du Colombier if(atoi(name) < 1024 && strcmp(np->net, "tcp") == 0) 128757837e0bSDavid du Colombier p = ndbgetvalue(db, &s, "port", name, "port", &t); 128857837e0bSDavid du Colombier if(p == nil) 128957837e0bSDavid du Colombier p = strdup(name); 12903e12c5d1SDavid du Colombier } 12913e12c5d1SDavid du Colombier 12923e12c5d1SDavid du Colombier if(t){ 12933e12c5d1SDavid du Colombier for(nt = t; nt; nt = nt->entry) 12943e12c5d1SDavid du Colombier if(strcmp(nt->attr, "restricted") == 0) 12953e12c5d1SDavid du Colombier restr = 1; 12963e12c5d1SDavid du Colombier ndbfree(t); 12973e12c5d1SDavid du Colombier } 129857837e0bSDavid du Colombier snprint(buf, blen, "%s%s", p, restr ? "!r" : ""); 129957837e0bSDavid du Colombier free(p); 130057837e0bSDavid du Colombier 13013e12c5d1SDavid du Colombier return buf; 13023e12c5d1SDavid du Colombier } 13033e12c5d1SDavid du Colombier 13043e12c5d1SDavid du Colombier /* 13057dd7cddfSDavid du Colombier * lookup an ip attribute 13063e12c5d1SDavid du Colombier */ 13077dd7cddfSDavid du Colombier int 130895a264b3SDavid du Colombier ipattrlookup(Ndb *db, char *ipa, char *attr, char *val, int vlen) 13093e12c5d1SDavid du Colombier { 13103e12c5d1SDavid du Colombier 13117dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13127dd7cddfSDavid du Colombier char *alist[2]; 13133e12c5d1SDavid du Colombier 13147dd7cddfSDavid du Colombier alist[0] = attr; 13157dd7cddfSDavid du Colombier t = ndbipinfo(db, "ip", ipa, alist, 1); 13167dd7cddfSDavid du Colombier if(t == nil) 13177dd7cddfSDavid du Colombier return 0; 13189a747e4fSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 13197dd7cddfSDavid du Colombier if(strcmp(nt->attr, attr) == 0){ 132095a264b3SDavid du Colombier nstrcpy(val, nt->val, vlen); 13213e12c5d1SDavid du Colombier ndbfree(t); 13227dd7cddfSDavid du Colombier return 1; 1323219b2ee8SDavid du Colombier } 13249a747e4fSDavid du Colombier } 13253e12c5d1SDavid du Colombier 13267dd7cddfSDavid du Colombier /* we shouldn't get here */ 13273e12c5d1SDavid du Colombier ndbfree(t); 13287dd7cddfSDavid du Colombier return 0; 13293e12c5d1SDavid du Colombier } 13303e12c5d1SDavid du Colombier 13313e12c5d1SDavid du Colombier /* 13323e12c5d1SDavid du Colombier * lookup (and translate) an ip destination 13333e12c5d1SDavid du Colombier */ 1334219b2ee8SDavid du Colombier Ndbtuple* 1335219b2ee8SDavid du Colombier iplookup(Network *np, char *host, char *serv, int nolookup) 13363e12c5d1SDavid du Colombier { 13379dfc0cb2SDavid du Colombier char *attr, *dnsname; 13387dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13393e12c5d1SDavid du Colombier Ndbs s; 134095a264b3SDavid du Colombier char ts[Maxservice]; 134195a264b3SDavid du Colombier char dollar[Maxhost]; 13427dd7cddfSDavid du Colombier uchar ip[IPaddrlen]; 13437dd7cddfSDavid du Colombier uchar net[IPaddrlen]; 13447dd7cddfSDavid du Colombier uchar tnet[IPaddrlen]; 13457dd7cddfSDavid du Colombier Ipifc *ifc; 13469a747e4fSDavid du Colombier Iplifc *lifc; 13473e12c5d1SDavid du Colombier 1348219b2ee8SDavid du Colombier USED(nolookup); 1349219b2ee8SDavid du Colombier 13503e12c5d1SDavid du Colombier /* 13513e12c5d1SDavid du Colombier * start with the service since it's the most likely to fail 13523e12c5d1SDavid du Colombier * and costs the least 13533e12c5d1SDavid du Colombier */ 13547dd7cddfSDavid du Colombier werrstr("can't translate address"); 135595a264b3SDavid du Colombier if(serv==0 || ipserv(np, serv, ts, sizeof ts) == 0){ 1356271b8d73SDavid du Colombier werrstr("can't translate service"); 1357219b2ee8SDavid du Colombier return 0; 13587dd7cddfSDavid du Colombier } 13593e12c5d1SDavid du Colombier 13603e12c5d1SDavid du Colombier /* for dial strings with no host */ 1361219b2ee8SDavid du Colombier if(strcmp(host, "*") == 0) 136295a264b3SDavid du Colombier return ndbnew("ip", "*"); 13633e12c5d1SDavid du Colombier 13643e12c5d1SDavid du Colombier /* 13657dd7cddfSDavid du Colombier * hack till we go v6 :: = 0.0.0.0 13667dd7cddfSDavid du Colombier */ 13677dd7cddfSDavid du Colombier if(strcmp("::", host) == 0) 136895a264b3SDavid du Colombier return ndbnew("ip", "*"); 13697dd7cddfSDavid du Colombier 13707dd7cddfSDavid du Colombier /* 13713e12c5d1SDavid du Colombier * '$' means the rest of the name is an attribute that we 13723e12c5d1SDavid du Colombier * need to search for 13733e12c5d1SDavid du Colombier */ 13743e12c5d1SDavid du Colombier if(*host == '$'){ 137595a264b3SDavid du Colombier if(ipattrlookup(db, ipaddr, host+1, dollar, sizeof dollar)) 13763e12c5d1SDavid du Colombier host = dollar; 13773e12c5d1SDavid du Colombier } 13783e12c5d1SDavid du Colombier 13793e12c5d1SDavid du Colombier /* 13807dd7cddfSDavid du Colombier * turn '[ip address]' into just 'ip address' 13817dd7cddfSDavid du Colombier */ 13827dd7cddfSDavid du Colombier if(*host == '[' && host[strlen(host)-1] == ']'){ 13837dd7cddfSDavid du Colombier host++; 13847dd7cddfSDavid du Colombier host[strlen(host)-1] = 0; 13857dd7cddfSDavid du Colombier } 13867dd7cddfSDavid du Colombier 13877dd7cddfSDavid du Colombier /* 13883e12c5d1SDavid du Colombier * just accept addresses 13893e12c5d1SDavid du Colombier */ 1390219b2ee8SDavid du Colombier attr = ipattr(host); 1391219b2ee8SDavid du Colombier if(strcmp(attr, "ip") == 0) 139295a264b3SDavid du Colombier return ndbnew("ip", host); 13933e12c5d1SDavid du Colombier 13943e12c5d1SDavid du Colombier /* 13953e12c5d1SDavid du Colombier * give the domain name server the first opportunity to 1396bd389b36SDavid du Colombier * resolve domain names. if that fails try the database. 13973e12c5d1SDavid du Colombier */ 13983e12c5d1SDavid du Colombier t = 0; 1399271b8d73SDavid du Colombier werrstr("can't translate address"); 14003e12c5d1SDavid du Colombier if(strcmp(attr, "dom") == 0) 14017dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 14023e12c5d1SDavid du Colombier if(t == 0) 140357837e0bSDavid du Colombier free(ndbgetvalue(db, &s, attr, host, "ip", &t)); 14049dfc0cb2SDavid du Colombier if(t == 0){ 14059dfc0cb2SDavid du Colombier dnsname = ndbgetvalue(db, &s, attr, host, "dom", nil); 14069dfc0cb2SDavid du Colombier if(dnsname){ 14079dfc0cb2SDavid du Colombier t = dnsiplookup(dnsname, &s); 14089dfc0cb2SDavid du Colombier free(dnsname); 14099dfc0cb2SDavid du Colombier } 14109dfc0cb2SDavid du Colombier } 14113e12c5d1SDavid du Colombier if(t == 0) 14127dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 14137dd7cddfSDavid du Colombier if(t == 0) 1414219b2ee8SDavid du Colombier return 0; 1415bd389b36SDavid du Colombier 1416bd389b36SDavid du Colombier /* 1417bd389b36SDavid du Colombier * reorder the tuple to have the matched line first and 1418bd389b36SDavid du Colombier * save that in the request structure. 1419bd389b36SDavid du Colombier */ 14207dd7cddfSDavid du Colombier t = reorder(t, s.t); 14217dd7cddfSDavid du Colombier 14227dd7cddfSDavid du Colombier /* 14237dd7cddfSDavid du Colombier * reorder according to our interfaces 14247dd7cddfSDavid du Colombier */ 14257dd7cddfSDavid du Colombier lock(&ipifclock); 14269a747e4fSDavid du Colombier for(ifc = ipifcs; ifc != nil; ifc = ifc->next){ 14279a747e4fSDavid du Colombier for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ 14289a747e4fSDavid du Colombier maskip(lifc->ip, lifc->mask, net); 14297dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry){ 14307dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0) 14317dd7cddfSDavid du Colombier continue; 14327dd7cddfSDavid du Colombier parseip(ip, nt->val); 14339a747e4fSDavid du Colombier maskip(ip, lifc->mask, tnet); 14347dd7cddfSDavid du Colombier if(memcmp(net, tnet, IPaddrlen) == 0){ 14357dd7cddfSDavid du Colombier t = reorder(t, nt); 14367dd7cddfSDavid du Colombier unlock(&ipifclock); 14377dd7cddfSDavid du Colombier return t; 14387dd7cddfSDavid du Colombier } 14397dd7cddfSDavid du Colombier } 14407dd7cddfSDavid du Colombier } 14419a747e4fSDavid du Colombier } 14427dd7cddfSDavid du Colombier unlock(&ipifclock); 14437dd7cddfSDavid du Colombier 14447dd7cddfSDavid du Colombier return t; 14453e12c5d1SDavid du Colombier } 14463e12c5d1SDavid du Colombier 14473e12c5d1SDavid du Colombier /* 14483e12c5d1SDavid du Colombier * translate an ip address 14493e12c5d1SDavid du Colombier */ 1450219b2ee8SDavid du Colombier char* 145180ee5cbfSDavid du Colombier iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack) 14523e12c5d1SDavid du Colombier { 145395a264b3SDavid du Colombier char ts[Maxservice]; 1454219b2ee8SDavid du Colombier char reply[Maxreply]; 145595a264b3SDavid du Colombier char x[Maxservice]; 14563e12c5d1SDavid du Colombier 1457219b2ee8SDavid du Colombier if(strcmp(t->attr, "ip") != 0) 14583e12c5d1SDavid du Colombier return 0; 1459219b2ee8SDavid du Colombier 146095a264b3SDavid du Colombier if(serv == 0 || ipserv(np, serv, ts, sizeof ts) == 0){ 1461271b8d73SDavid du Colombier werrstr("can't translate service"); 1462219b2ee8SDavid du Colombier return 0; 1463271b8d73SDavid du Colombier } 14647dd7cddfSDavid du Colombier if(rem != nil) 14657dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 14667dd7cddfSDavid du Colombier else 14677dd7cddfSDavid du Colombier *x = 0; 146880ee5cbfSDavid du Colombier 1469219b2ee8SDavid du Colombier if(*t->val == '*') 14707dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", 14717dd7cddfSDavid du Colombier mntpt, np->net, ts, x); 1472219b2ee8SDavid du Colombier else 147380ee5cbfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s%s", 147480ee5cbfSDavid du Colombier mntpt, np->net, t->val, ts, x, hack? "!fasttimeout": ""); 1475219b2ee8SDavid du Colombier 1476219b2ee8SDavid du Colombier return strdup(reply); 14773e12c5d1SDavid du Colombier } 14783e12c5d1SDavid du Colombier 1479219b2ee8SDavid du Colombier /* 1480219b2ee8SDavid du Colombier * lookup a telephone number 1481219b2ee8SDavid du Colombier */ 1482219b2ee8SDavid du Colombier Ndbtuple* 1483219b2ee8SDavid du Colombier telcolookup(Network *np, char *host, char *serv, int nolookup) 1484219b2ee8SDavid du Colombier { 1485219b2ee8SDavid du Colombier Ndbtuple *t; 1486219b2ee8SDavid du Colombier Ndbs s; 1487219b2ee8SDavid du Colombier 1488219b2ee8SDavid du Colombier USED(np, nolookup, serv); 1489219b2ee8SDavid du Colombier 1490271b8d73SDavid du Colombier werrstr("can't translate address"); 149157837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "sys", host, "telco", &t)); 1492219b2ee8SDavid du Colombier if(t == 0) 149395a264b3SDavid du Colombier return ndbnew("telco", host); 1494219b2ee8SDavid du Colombier 1495219b2ee8SDavid du Colombier return reorder(t, s.t); 1496219b2ee8SDavid du Colombier } 1497219b2ee8SDavid du Colombier 1498219b2ee8SDavid du Colombier /* 1499219b2ee8SDavid du Colombier * translate a telephone address 1500219b2ee8SDavid du Colombier */ 1501219b2ee8SDavid du Colombier char* 150280ee5cbfSDavid du Colombier telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int) 1503219b2ee8SDavid du Colombier { 1504219b2ee8SDavid du Colombier char reply[Maxreply]; 150595a264b3SDavid du Colombier char x[Maxservice]; 1506219b2ee8SDavid du Colombier 1507219b2ee8SDavid du Colombier if(strcmp(t->attr, "telco") != 0) 1508219b2ee8SDavid du Colombier return 0; 1509219b2ee8SDavid du Colombier 15107dd7cddfSDavid du Colombier if(rem != nil) 15117dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 1512219b2ee8SDavid du Colombier else 15137dd7cddfSDavid du Colombier *x = 0; 15147dd7cddfSDavid du Colombier if(serv) 15157dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s", mntpt, np->net, 15167dd7cddfSDavid du Colombier t->val, serv, x); 15177dd7cddfSDavid du Colombier else 15187dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net, 15197dd7cddfSDavid du Colombier t->val, x); 1520219b2ee8SDavid du Colombier return strdup(reply); 1521219b2ee8SDavid du Colombier } 15223e12c5d1SDavid du Colombier 15233e12c5d1SDavid du Colombier /* 15243e12c5d1SDavid du Colombier * reorder the tuple to put x's line first in the entry 15253e12c5d1SDavid du Colombier */ 15263e12c5d1SDavid du Colombier Ndbtuple* 15273e12c5d1SDavid du Colombier reorder(Ndbtuple *t, Ndbtuple *x) 15283e12c5d1SDavid du Colombier { 15293e12c5d1SDavid du Colombier Ndbtuple *nt; 15303e12c5d1SDavid du Colombier Ndbtuple *line; 15313e12c5d1SDavid du Colombier 1532219b2ee8SDavid du Colombier /* find start of this entry's line */ 1533219b2ee8SDavid du Colombier for(line = x; line->entry == line->line; line = line->line) 15343e12c5d1SDavid du Colombier ; 1535219b2ee8SDavid du Colombier line = line->line; 1536219b2ee8SDavid du Colombier if(line == t) 1537219b2ee8SDavid du Colombier return t; /* already the first line */ 15383e12c5d1SDavid du Colombier 1539219b2ee8SDavid du Colombier /* remove this line and everything after it from the entry */ 1540219b2ee8SDavid du Colombier for(nt = t; nt->entry != line; nt = nt->entry) 1541219b2ee8SDavid du Colombier ; 1542219b2ee8SDavid du Colombier nt->entry = 0; 15433e12c5d1SDavid du Colombier 1544219b2ee8SDavid du Colombier /* make that the start of the entry */ 1545219b2ee8SDavid du Colombier for(nt = line; nt->entry; nt = nt->entry) 1546219b2ee8SDavid du Colombier ; 15473e12c5d1SDavid du Colombier nt->entry = t; 15483e12c5d1SDavid du Colombier return line; 15493e12c5d1SDavid du Colombier } 15503e12c5d1SDavid du Colombier 15513e12c5d1SDavid du Colombier /* 15523e12c5d1SDavid du Colombier * create a slave process to handle a request to avoid one request blocking 15537dd7cddfSDavid du Colombier * another. parent returns to job loop. 15543e12c5d1SDavid du Colombier */ 15553e12c5d1SDavid du Colombier void 1556*254fe3d3SDavid du Colombier slave(char *host) 15573e12c5d1SDavid du Colombier { 15583e12c5d1SDavid du Colombier if(*isslave) 15593e12c5d1SDavid du Colombier return; /* we're already a slave process */ 15603e12c5d1SDavid du Colombier 15613e12c5d1SDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 15623e12c5d1SDavid du Colombier case -1: 15633e12c5d1SDavid du Colombier break; 15643e12c5d1SDavid du Colombier case 0: 1565219b2ee8SDavid du Colombier if(debug) 1566219b2ee8SDavid du Colombier syslog(0, logfile, "slave %d", getpid()); 1567*254fe3d3SDavid du Colombier procsetname("%s", host); 15683e12c5d1SDavid du Colombier *isslave = 1; 15693e12c5d1SDavid du Colombier break; 15703e12c5d1SDavid du Colombier default: 15713e12c5d1SDavid du Colombier longjmp(masterjmp, 1); 15723e12c5d1SDavid du Colombier } 15733e12c5d1SDavid du Colombier 1574219b2ee8SDavid du Colombier } 1575219b2ee8SDavid du Colombier 15763e12c5d1SDavid du Colombier /* 15773e12c5d1SDavid du Colombier * call the dns process and have it try to translate a name 15783e12c5d1SDavid du Colombier */ 15793e12c5d1SDavid du Colombier Ndbtuple* 15807dd7cddfSDavid du Colombier dnsiplookup(char *host, Ndbs *s) 15813e12c5d1SDavid du Colombier { 158295a264b3SDavid du Colombier char buf[Maxreply]; 15837dd7cddfSDavid du Colombier Ndbtuple *t; 15843e12c5d1SDavid du Colombier 1585bd389b36SDavid du Colombier unlock(&dblock); 1586bd389b36SDavid du Colombier 15873e12c5d1SDavid du Colombier /* save the name before starting a slave */ 15887dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s", host); 15893e12c5d1SDavid du Colombier 1590*254fe3d3SDavid du Colombier slave(host); 15913e12c5d1SDavid du Colombier 15927dd7cddfSDavid du Colombier if(strcmp(ipattr(buf), "ip") == 0) 15937dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ptr"); 15947dd7cddfSDavid du Colombier else 15957dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ip"); 15963e12c5d1SDavid du Colombier s->t = t; 15977dd7cddfSDavid du Colombier 1598271b8d73SDavid du Colombier if(t == nil){ 1599271b8d73SDavid du Colombier rerrstr(buf, sizeof buf); 1600271b8d73SDavid du Colombier if(strstr(buf, "exist")) 1601271b8d73SDavid du Colombier werrstr("can't translate address: %s", buf); 1602271b8d73SDavid du Colombier else if(strstr(buf, "dns failure")) 1603271b8d73SDavid du Colombier werrstr("temporary problem: %s", buf); 1604271b8d73SDavid du Colombier } 1605271b8d73SDavid du Colombier 1606bd389b36SDavid du Colombier lock(&dblock); 16073e12c5d1SDavid du Colombier return t; 16083e12c5d1SDavid du Colombier } 1609219b2ee8SDavid du Colombier 1610219b2ee8SDavid du Colombier int 1611219b2ee8SDavid du Colombier qmatch(Ndbtuple *t, char **attr, char **val, int n) 1612219b2ee8SDavid du Colombier { 1613219b2ee8SDavid du Colombier int i, found; 1614219b2ee8SDavid du Colombier Ndbtuple *nt; 1615219b2ee8SDavid du Colombier 1616219b2ee8SDavid du Colombier for(i = 1; i < n; i++){ 1617219b2ee8SDavid du Colombier found = 0; 1618219b2ee8SDavid du Colombier for(nt = t; nt; nt = nt->entry) 1619219b2ee8SDavid du Colombier if(strcmp(attr[i], nt->attr) == 0) 1620219b2ee8SDavid du Colombier if(strcmp(val[i], "*") == 0 1621219b2ee8SDavid du Colombier || strcmp(val[i], nt->val) == 0){ 1622219b2ee8SDavid du Colombier found = 1; 1623219b2ee8SDavid du Colombier break; 1624219b2ee8SDavid du Colombier } 1625219b2ee8SDavid du Colombier if(found == 0) 1626219b2ee8SDavid du Colombier break; 1627219b2ee8SDavid du Colombier } 1628219b2ee8SDavid du Colombier return i == n; 1629219b2ee8SDavid du Colombier } 1630219b2ee8SDavid du Colombier 1631219b2ee8SDavid du Colombier void 1632219b2ee8SDavid du Colombier qreply(Mfile *mf, Ndbtuple *t) 1633219b2ee8SDavid du Colombier { 1634219b2ee8SDavid du Colombier Ndbtuple *nt; 163595a264b3SDavid du Colombier String *s; 1636219b2ee8SDavid du Colombier 163795a264b3SDavid du Colombier s = s_new(); 1638219b2ee8SDavid du Colombier for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){ 163995a264b3SDavid du Colombier s_append(s, nt->attr); 164095a264b3SDavid du Colombier s_append(s, "="); 164195a264b3SDavid du Colombier s_append(s, nt->val); 164295a264b3SDavid du Colombier 164395a264b3SDavid du Colombier if(nt->line != nt->entry){ 164495a264b3SDavid du Colombier mf->replylen[mf->nreply] = s_len(s); 164595a264b3SDavid du Colombier mf->reply[mf->nreply++] = strdup(s_to_c(s)); 164695a264b3SDavid du Colombier s_restart(s); 1647219b2ee8SDavid du Colombier } else 164895a264b3SDavid du Colombier s_append(s, " "); 1649219b2ee8SDavid du Colombier } 165095a264b3SDavid du Colombier s_free(s); 1651219b2ee8SDavid du Colombier } 1652219b2ee8SDavid du Colombier 16537dd7cddfSDavid du Colombier enum 16547dd7cddfSDavid du Colombier { 16557dd7cddfSDavid du Colombier Maxattr= 32, 16567dd7cddfSDavid du Colombier }; 16577dd7cddfSDavid du Colombier 1658219b2ee8SDavid du Colombier /* 16597dd7cddfSDavid du Colombier * generic query lookup. The query is of one of the following 16607dd7cddfSDavid du Colombier * forms: 16617dd7cddfSDavid du Colombier * 16627dd7cddfSDavid du Colombier * attr1=val1 attr2=val2 attr3=val3 ... 16637dd7cddfSDavid du Colombier * 16647dd7cddfSDavid du Colombier * returns the matching tuple 16657dd7cddfSDavid du Colombier * 16667dd7cddfSDavid du Colombier * ipinfo attr=val attr1 attr2 attr3 ... 16677dd7cddfSDavid du Colombier * 16687dd7cddfSDavid du Colombier * is like ipinfo and returns the attr{1-n} 16697dd7cddfSDavid du Colombier * associated with the ip address. 1670219b2ee8SDavid du Colombier */ 1671219b2ee8SDavid du Colombier char* 1672219b2ee8SDavid du Colombier genquery(Mfile *mf, char *query) 1673219b2ee8SDavid du Colombier { 1674219b2ee8SDavid du Colombier int i, n; 1675219b2ee8SDavid du Colombier char *p; 16767dd7cddfSDavid du Colombier char *attr[Maxattr]; 16777dd7cddfSDavid du Colombier char *val[Maxattr]; 1678219b2ee8SDavid du Colombier Ndbtuple *t; 1679219b2ee8SDavid du Colombier Ndbs s; 1680219b2ee8SDavid du Colombier 16817dd7cddfSDavid du Colombier n = getfields(query, attr, 32, 1, " "); 1682219b2ee8SDavid du Colombier if(n == 0) 1683219b2ee8SDavid du Colombier return "bad query"; 1684219b2ee8SDavid du Colombier 16857dd7cddfSDavid du Colombier if(strcmp(attr[0], "ipinfo") == 0) 16867dd7cddfSDavid du Colombier return ipinfoquery(mf, attr, n); 16877dd7cddfSDavid du Colombier 1688219b2ee8SDavid du Colombier /* parse pairs */ 1689219b2ee8SDavid du Colombier for(i = 0; i < n; i++){ 1690219b2ee8SDavid du Colombier p = strchr(attr[i], '='); 1691219b2ee8SDavid du Colombier if(p == 0) 1692219b2ee8SDavid du Colombier return "bad query"; 1693219b2ee8SDavid du Colombier *p++ = 0; 1694219b2ee8SDavid du Colombier val[i] = p; 1695219b2ee8SDavid du Colombier } 1696219b2ee8SDavid du Colombier 1697219b2ee8SDavid du Colombier /* give dns a chance */ 1698219b2ee8SDavid du Colombier if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){ 16997dd7cddfSDavid du Colombier t = dnsiplookup(val[0], &s); 1700219b2ee8SDavid du Colombier if(t){ 1701219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1702219b2ee8SDavid du Colombier qreply(mf, t); 1703219b2ee8SDavid du Colombier ndbfree(t); 1704219b2ee8SDavid du Colombier return 0; 1705219b2ee8SDavid du Colombier } 1706219b2ee8SDavid du Colombier ndbfree(t); 1707219b2ee8SDavid du Colombier } 1708219b2ee8SDavid du Colombier } 1709219b2ee8SDavid du Colombier 1710219b2ee8SDavid du Colombier /* first pair is always the key. It can't be a '*' */ 1711219b2ee8SDavid du Colombier t = ndbsearch(db, &s, attr[0], val[0]); 1712219b2ee8SDavid du Colombier 1713219b2ee8SDavid du Colombier /* search is the and of all the pairs */ 1714219b2ee8SDavid du Colombier while(t){ 1715219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1716219b2ee8SDavid du Colombier qreply(mf, t); 1717219b2ee8SDavid du Colombier ndbfree(t); 1718219b2ee8SDavid du Colombier return 0; 1719219b2ee8SDavid du Colombier } 1720219b2ee8SDavid du Colombier 1721219b2ee8SDavid du Colombier ndbfree(t); 1722219b2ee8SDavid du Colombier t = ndbsnext(&s, attr[0], val[0]); 1723219b2ee8SDavid du Colombier } 1724219b2ee8SDavid du Colombier 1725219b2ee8SDavid du Colombier return "no match"; 1726219b2ee8SDavid du Colombier } 17277dd7cddfSDavid du Colombier 17287dd7cddfSDavid du Colombier /* 17297dd7cddfSDavid du Colombier * resolve an ip address 17307dd7cddfSDavid du Colombier */ 17317dd7cddfSDavid du Colombier static Ndbtuple* 17327dd7cddfSDavid du Colombier ipresolve(char *attr, char *host) 17337dd7cddfSDavid du Colombier { 17347dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17357dd7cddfSDavid du Colombier 17367dd7cddfSDavid du Colombier t = iplookup(&network[Ntcp], host, "*", 0); 17377dd7cddfSDavid du Colombier for(l = &t; *l != nil; ){ 17387dd7cddfSDavid du Colombier nt = *l; 17397dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0){ 17407dd7cddfSDavid du Colombier *l = nt->entry; 17417dd7cddfSDavid du Colombier nt->entry = nil; 17427dd7cddfSDavid du Colombier ndbfree(nt); 17437dd7cddfSDavid du Colombier continue; 17447dd7cddfSDavid du Colombier } 17457dd7cddfSDavid du Colombier strcpy(nt->attr, attr); 17467dd7cddfSDavid du Colombier l = &nt->entry; 17477dd7cddfSDavid du Colombier } 17487dd7cddfSDavid du Colombier return t; 17497dd7cddfSDavid du Colombier } 17507dd7cddfSDavid du Colombier 17517dd7cddfSDavid du Colombier char* 17527dd7cddfSDavid du Colombier ipinfoquery(Mfile *mf, char **list, int n) 17537dd7cddfSDavid du Colombier { 17547dd7cddfSDavid du Colombier int i, nresolve; 17557dd7cddfSDavid du Colombier int resolve[Maxattr]; 17567dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 17577dd7cddfSDavid du Colombier char *attr, *val; 17587dd7cddfSDavid du Colombier 17597dd7cddfSDavid du Colombier /* skip 'ipinfo' */ 17607dd7cddfSDavid du Colombier list++; n--; 17617dd7cddfSDavid du Colombier 17628a2c5ad0SDavid du Colombier if(n < 1) 17637dd7cddfSDavid du Colombier return "bad query"; 17647dd7cddfSDavid du Colombier 17658a2c5ad0SDavid du Colombier /* get search attribute=value, or assume ip=myipaddr */ 17668a2c5ad0SDavid du Colombier attr = *list; 17678a2c5ad0SDavid du Colombier if((val = strchr(attr, '=')) != nil){ 17687dd7cddfSDavid du Colombier *val++ = 0; 17698a2c5ad0SDavid du Colombier list++; 17708a2c5ad0SDavid du Colombier n--; 17718a2c5ad0SDavid du Colombier }else{ 17728a2c5ad0SDavid du Colombier attr = "ip"; 17738a2c5ad0SDavid du Colombier val = ipaddr; 17748a2c5ad0SDavid du Colombier } 17758a2c5ad0SDavid du Colombier 17768a2c5ad0SDavid du Colombier if(n < 1) 17778a2c5ad0SDavid du Colombier return "bad query"; 17787dd7cddfSDavid du Colombier 17797dd7cddfSDavid du Colombier /* 17807dd7cddfSDavid du Colombier * don't let ndbipinfo resolve the addresses, we're 17817dd7cddfSDavid du Colombier * better at it. 17827dd7cddfSDavid du Colombier */ 17837dd7cddfSDavid du Colombier nresolve = 0; 17847dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 1785107aedb4SDavid du Colombier if(*list[i] == '@'){ /* @attr=val ? */ 17867dd7cddfSDavid du Colombier list[i]++; 1787107aedb4SDavid du Colombier resolve[i] = 1; /* we'll resolve it */ 17887dd7cddfSDavid du Colombier nresolve++; 17897dd7cddfSDavid du Colombier } else 17907dd7cddfSDavid du Colombier resolve[i] = 0; 17917dd7cddfSDavid du Colombier 17927dd7cddfSDavid du Colombier t = ndbipinfo(db, attr, val, list, n); 17937dd7cddfSDavid du Colombier if(t == nil) 17947dd7cddfSDavid du Colombier return "no match"; 17957dd7cddfSDavid du Colombier 17967dd7cddfSDavid du Colombier if(nresolve != 0){ 17977dd7cddfSDavid du Colombier for(l = &t; *l != nil;){ 17987dd7cddfSDavid du Colombier nt = *l; 17997dd7cddfSDavid du Colombier 18007dd7cddfSDavid du Colombier /* already an address? */ 18017dd7cddfSDavid du Colombier if(strcmp(ipattr(nt->val), "ip") == 0){ 18027dd7cddfSDavid du Colombier l = &(*l)->entry; 18037dd7cddfSDavid du Colombier continue; 18047dd7cddfSDavid du Colombier } 18057dd7cddfSDavid du Colombier 18067dd7cddfSDavid du Colombier /* user wants it resolved? */ 18077dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 18087dd7cddfSDavid du Colombier if(strcmp(list[i], nt->attr) == 0) 18097dd7cddfSDavid du Colombier break; 18107dd7cddfSDavid du Colombier if(i >= n || resolve[i] == 0){ 18117dd7cddfSDavid du Colombier l = &(*l)->entry; 18127dd7cddfSDavid du Colombier continue; 18137dd7cddfSDavid du Colombier } 18147dd7cddfSDavid du Colombier 18157dd7cddfSDavid du Colombier /* resolve address and replace entry */ 18167dd7cddfSDavid du Colombier *l = ipresolve(nt->attr, nt->val); 18177dd7cddfSDavid du Colombier while(*l != nil) 18187dd7cddfSDavid du Colombier l = &(*l)->entry; 18197dd7cddfSDavid du Colombier *l = nt->entry; 18207dd7cddfSDavid du Colombier 18217dd7cddfSDavid du Colombier nt->entry = nil; 18227dd7cddfSDavid du Colombier ndbfree(nt); 18237dd7cddfSDavid du Colombier } 18247dd7cddfSDavid du Colombier } 18257dd7cddfSDavid du Colombier 18267dd7cddfSDavid du Colombier /* make it all one line */ 18277dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 18287dd7cddfSDavid du Colombier if(nt->entry == nil) 18297dd7cddfSDavid du Colombier nt->line = t; 18307dd7cddfSDavid du Colombier else 18317dd7cddfSDavid du Colombier nt->line = nt->entry; 18327dd7cddfSDavid du Colombier } 18337dd7cddfSDavid du Colombier 18347dd7cddfSDavid du Colombier qreply(mf, t); 18357dd7cddfSDavid du Colombier 18367dd7cddfSDavid du Colombier return nil; 18377dd7cddfSDavid du Colombier } 18387dd7cddfSDavid du Colombier 18397dd7cddfSDavid du Colombier void* 18407dd7cddfSDavid du Colombier emalloc(int size) 18417dd7cddfSDavid du Colombier { 18427dd7cddfSDavid du Colombier void *x; 18437dd7cddfSDavid du Colombier 18447dd7cddfSDavid du Colombier x = malloc(size); 18457dd7cddfSDavid du Colombier if(x == nil) 18467dd7cddfSDavid du Colombier abort(); 18477dd7cddfSDavid du Colombier memset(x, 0, size); 18487dd7cddfSDavid du Colombier return x; 18497dd7cddfSDavid du Colombier } 18509a747e4fSDavid du Colombier 18519a747e4fSDavid du Colombier char* 18529a747e4fSDavid du Colombier estrdup(char *s) 18539a747e4fSDavid du Colombier { 18549a747e4fSDavid du Colombier int size; 18559a747e4fSDavid du Colombier char *p; 18569a747e4fSDavid du Colombier 18579a747e4fSDavid du Colombier size = strlen(s)+1; 18589a747e4fSDavid du Colombier p = malloc(size); 18599a747e4fSDavid du Colombier if(p == nil) 18609a747e4fSDavid du Colombier abort(); 18619a747e4fSDavid du Colombier memmove(p, s, size); 18629a747e4fSDavid du Colombier return p; 18639a747e4fSDavid du Colombier } 1864