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> 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier enum 113e12c5d1SDavid du Colombier { 12219b2ee8SDavid du Colombier Nreply= 8, 133e12c5d1SDavid du Colombier Maxreply= 256, 14*7dd7cddfSDavid du Colombier Maxrequest= 128, 15*7dd7cddfSDavid du Colombier Maxpath= 128, 16*7dd7cddfSDavid du Colombier Ncache= 8, /* size of cache */ 17*7dd7cddfSDavid du Colombier Secvalid= 120, /* seconds a cache entry is valid */ 183e12c5d1SDavid du Colombier 193e12c5d1SDavid du Colombier Qcs= 1, 203e12c5d1SDavid du Colombier }; 213e12c5d1SDavid du Colombier 223e12c5d1SDavid du Colombier typedef struct Mfile Mfile; 23219b2ee8SDavid du Colombier typedef struct Mlist Mlist; 243e12c5d1SDavid du Colombier typedef struct Network Network; 25*7dd7cddfSDavid du Colombier typedef struct Flushreq Flushreq; 26*7dd7cddfSDavid du Colombier typedef struct CacheEntry CacheEntry; 27*7dd7cddfSDavid du Colombier typedef struct Job Job; 283e12c5d1SDavid du Colombier 293e12c5d1SDavid du Colombier int vers; /* incremented each clone/attach */ 303e12c5d1SDavid du Colombier 313e12c5d1SDavid du Colombier struct Mfile 323e12c5d1SDavid du Colombier { 333e12c5d1SDavid du Colombier int busy; 34219b2ee8SDavid du Colombier 353e12c5d1SDavid du Colombier char user[NAMELEN]; 363e12c5d1SDavid du Colombier Qid qid; 373e12c5d1SDavid du Colombier int fid; 383e12c5d1SDavid du Colombier 39219b2ee8SDavid du Colombier int nreply; 40219b2ee8SDavid du Colombier char *reply[Nreply]; 41219b2ee8SDavid du Colombier int replylen[Nreply]; 42219b2ee8SDavid du Colombier }; 43219b2ee8SDavid du Colombier 44219b2ee8SDavid du Colombier struct Mlist 45219b2ee8SDavid du Colombier { 46219b2ee8SDavid du Colombier Mlist *next; 47219b2ee8SDavid du Colombier Mfile mf; 483e12c5d1SDavid du Colombier }; 493e12c5d1SDavid du Colombier 50*7dd7cddfSDavid du Colombier struct CacheEntry 51*7dd7cddfSDavid du Colombier { 52*7dd7cddfSDavid du Colombier ulong expire; 53*7dd7cddfSDavid du Colombier char *question; 54*7dd7cddfSDavid du Colombier char err[ERRLEN]; 55*7dd7cddfSDavid du Colombier int nreply; 56*7dd7cddfSDavid du Colombier char *reply[Nreply]; 57*7dd7cddfSDavid du Colombier int replylen[Nreply]; 58*7dd7cddfSDavid du Colombier }; 59*7dd7cddfSDavid du Colombier struct { 60*7dd7cddfSDavid du Colombier Lock; 61*7dd7cddfSDavid du Colombier CacheEntry e[Ncache]; 62*7dd7cddfSDavid du Colombier int next; /* next cache entry to use */ 63*7dd7cddfSDavid du Colombier } cache; 64*7dd7cddfSDavid du Colombier 65*7dd7cddfSDavid du Colombier // 66*7dd7cddfSDavid du Colombier // active requests 67*7dd7cddfSDavid du Colombier // 68*7dd7cddfSDavid du Colombier struct Job 69*7dd7cddfSDavid du Colombier { 70*7dd7cddfSDavid du Colombier Job *next; 71*7dd7cddfSDavid du Colombier int flushed; 72*7dd7cddfSDavid du Colombier Fcall request; 73*7dd7cddfSDavid du Colombier Fcall reply; 74*7dd7cddfSDavid du Colombier }; 75*7dd7cddfSDavid du Colombier Lock joblock; 76*7dd7cddfSDavid du Colombier Job *joblist; 77*7dd7cddfSDavid du Colombier 78219b2ee8SDavid du Colombier Mlist *mlist; 793e12c5d1SDavid du Colombier int mfd[2]; 803e12c5d1SDavid du Colombier char user[NAMELEN]; 813e12c5d1SDavid du Colombier int debug; 82*7dd7cddfSDavid du Colombier int paranoia; 833e12c5d1SDavid du Colombier jmp_buf masterjmp; /* return through here after a slave process has been created */ 843e12c5d1SDavid du Colombier int *isslave; /* *isslave non-zero means this is a slave process */ 85bd389b36SDavid du Colombier char *dbfile; 86*7dd7cddfSDavid du Colombier Ndb *db, *netdb; 873e12c5d1SDavid du Colombier 88*7dd7cddfSDavid du Colombier void rsession(Job*); 89*7dd7cddfSDavid du Colombier void rnop(Job*); 90*7dd7cddfSDavid du Colombier void rflush(Job*); 91*7dd7cddfSDavid du Colombier void rattach(Job*, Mfile*); 92*7dd7cddfSDavid du Colombier void rclone(Job*, Mfile*); 93*7dd7cddfSDavid du Colombier char* rwalk(Job*, Mfile*); 94*7dd7cddfSDavid du Colombier void rclwalk(Job*, Mfile*); 95*7dd7cddfSDavid du Colombier void ropen(Job*, Mfile*); 96*7dd7cddfSDavid du Colombier void rcreate(Job*, Mfile*); 97*7dd7cddfSDavid du Colombier void rread(Job*, Mfile*); 98*7dd7cddfSDavid du Colombier void rwrite(Job*, Mfile*); 99*7dd7cddfSDavid du Colombier void rclunk(Job*, Mfile*); 100*7dd7cddfSDavid du Colombier void rremove(Job*, Mfile*); 101*7dd7cddfSDavid du Colombier void rstat(Job*, Mfile*); 102*7dd7cddfSDavid du Colombier void rwstat(Job*, Mfile*); 1033e12c5d1SDavid du Colombier void rauth(void); 104*7dd7cddfSDavid du Colombier void sendmsg(Job*, char*); 1053e12c5d1SDavid du Colombier void error(char*); 106*7dd7cddfSDavid du Colombier void mountinit(char*, char*); 1073e12c5d1SDavid du Colombier void io(void); 108*7dd7cddfSDavid du Colombier void ndbinit(void); 109*7dd7cddfSDavid du Colombier void netinit(int); 1103e12c5d1SDavid du Colombier void netadd(char*); 111*7dd7cddfSDavid du Colombier int lookup(Mfile*, char*, char*, char*, char*); 112219b2ee8SDavid du Colombier char *genquery(Mfile*, char*); 113*7dd7cddfSDavid du Colombier char* ipinfoquery(Mfile*, char**, int); 114bd389b36SDavid du Colombier int needproto(Network*, Ndbtuple*); 1153e12c5d1SDavid du Colombier Ndbtuple* lookval(Ndbtuple*, Ndbtuple*, char*, char*); 1163e12c5d1SDavid du Colombier Ndbtuple* reorder(Ndbtuple*, Ndbtuple*); 117*7dd7cddfSDavid du Colombier void ipid(void); 118*7dd7cddfSDavid du Colombier void readipinterfaces(void); 119*7dd7cddfSDavid du Colombier void* emalloc(int); 120*7dd7cddfSDavid du Colombier Job* newjob(void); 121*7dd7cddfSDavid du Colombier void freejob(Job*); 122*7dd7cddfSDavid du Colombier void setext(char*, int, char*); 1233e12c5d1SDavid du Colombier 124bd389b36SDavid du Colombier extern void paralloc(void); 125bd389b36SDavid du Colombier 1263e12c5d1SDavid du Colombier char *mname[]={ 1273e12c5d1SDavid du Colombier [Tnop] "Tnop", 1283e12c5d1SDavid du Colombier [Tsession] "Tsession", 1293e12c5d1SDavid du Colombier [Tflush] "Tflush", 1303e12c5d1SDavid du Colombier [Tattach] "Tattach", 1313e12c5d1SDavid du Colombier [Tclone] "Tclone", 1323e12c5d1SDavid du Colombier [Twalk] "Twalk", 1333e12c5d1SDavid du Colombier [Topen] "Topen", 1343e12c5d1SDavid du Colombier [Tcreate] "Tcreate", 1353e12c5d1SDavid du Colombier [Tclunk] "Tclunk", 1363e12c5d1SDavid du Colombier [Tread] "Tread", 1373e12c5d1SDavid du Colombier [Twrite] "Twrite", 1383e12c5d1SDavid du Colombier [Tremove] "Tremove", 1393e12c5d1SDavid du Colombier [Tstat] "Tstat", 1403e12c5d1SDavid du Colombier [Twstat] "Twstat", 1413e12c5d1SDavid du Colombier 0, 1423e12c5d1SDavid du Colombier }; 1433e12c5d1SDavid du Colombier 144bd389b36SDavid du Colombier Lock dblock; /* mutex on database operations */ 145*7dd7cddfSDavid du Colombier Lock netlock; /* mutex for netinit() */ 146bd389b36SDavid du Colombier 147219b2ee8SDavid du Colombier char *logfile = "cs"; 148*7dd7cddfSDavid du Colombier char *paranoiafile = "cs.paranoia"; 149219b2ee8SDavid du Colombier 150*7dd7cddfSDavid du Colombier char mntpt[Maxpath]; 151*7dd7cddfSDavid du Colombier char netndb[Maxpath]; 152*7dd7cddfSDavid du Colombier 153*7dd7cddfSDavid du Colombier void 154*7dd7cddfSDavid du Colombier usage(void) 155*7dd7cddfSDavid du Colombier { 156*7dd7cddfSDavid du Colombier fprint(2, "usage: %s [-d] [-f ndb-file] [-x netmtpt] [-n]\n", argv0); 157*7dd7cddfSDavid du Colombier exits("usage"); 158*7dd7cddfSDavid du Colombier } 159219b2ee8SDavid du Colombier 1603e12c5d1SDavid du Colombier void 1613e12c5d1SDavid du Colombier main(int argc, char *argv[]) 1623e12c5d1SDavid du Colombier { 163*7dd7cddfSDavid du Colombier char servefile[Maxpath]; 164219b2ee8SDavid du Colombier int justsetname; 165*7dd7cddfSDavid du Colombier char *p; 166*7dd7cddfSDavid du Colombier char ext[Maxpath]; 1673e12c5d1SDavid du Colombier 168219b2ee8SDavid du Colombier justsetname = 0; 169*7dd7cddfSDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), nil); 170*7dd7cddfSDavid du Colombier ext[0] = 0; 1713e12c5d1SDavid du Colombier ARGBEGIN{ 1723e12c5d1SDavid du Colombier case 'd': 1733e12c5d1SDavid du Colombier debug = 1; 1743e12c5d1SDavid du Colombier break; 175bd389b36SDavid du Colombier case 'f': 176*7dd7cddfSDavid du Colombier p = ARGF(); 177*7dd7cddfSDavid du Colombier if(p == nil) 178*7dd7cddfSDavid du Colombier usage(); 179*7dd7cddfSDavid du Colombier dbfile = p; 180*7dd7cddfSDavid du Colombier break; 181*7dd7cddfSDavid du Colombier case 'x': 182*7dd7cddfSDavid du Colombier p = ARGF(); 183*7dd7cddfSDavid du Colombier if(p == nil) 184*7dd7cddfSDavid du Colombier usage(); 185*7dd7cddfSDavid du Colombier setnetmtpt(mntpt, sizeof(mntpt), p); 186*7dd7cddfSDavid du Colombier setext(ext, sizeof(ext), mntpt); 187bd389b36SDavid du Colombier break; 188219b2ee8SDavid du Colombier case 'n': 189219b2ee8SDavid du Colombier justsetname = 1; 190219b2ee8SDavid du Colombier break; 1913e12c5d1SDavid du Colombier }ARGEND 1923e12c5d1SDavid du Colombier USED(argc); 1933e12c5d1SDavid du Colombier USED(argv); 1943e12c5d1SDavid du Colombier 195*7dd7cddfSDavid du Colombier rfork(RFREND|RFNOTEG); 196*7dd7cddfSDavid du Colombier 197*7dd7cddfSDavid du Colombier snprint(servefile, sizeof(servefile), "#s/cs%s", ext); 198*7dd7cddfSDavid du Colombier snprint(netndb, sizeof(netndb), "%s/ndb", mntpt); 199*7dd7cddfSDavid du Colombier unmount(servefile, mntpt); 200*7dd7cddfSDavid du Colombier remove(servefile); 201*7dd7cddfSDavid du Colombier 202*7dd7cddfSDavid du Colombier fmtinstall('E', eipconv); 203*7dd7cddfSDavid du Colombier fmtinstall('I', eipconv); 204*7dd7cddfSDavid du Colombier fmtinstall('M', eipconv); 205*7dd7cddfSDavid du Colombier fmtinstall('F', fcallconv); 206*7dd7cddfSDavid du Colombier 207*7dd7cddfSDavid du Colombier ndbinit(); 208*7dd7cddfSDavid du Colombier netinit(0); 209*7dd7cddfSDavid du Colombier 210*7dd7cddfSDavid du Colombier if(!justsetname){ 211*7dd7cddfSDavid du Colombier mountinit(servefile, mntpt); 212*7dd7cddfSDavid du Colombier io(); 213*7dd7cddfSDavid du Colombier } 214219b2ee8SDavid du Colombier exits(0); 215219b2ee8SDavid du Colombier } 216219b2ee8SDavid du Colombier 217*7dd7cddfSDavid du Colombier /* 218*7dd7cddfSDavid du Colombier * if a mount point is specified, set the cs extention to be the mount point 219*7dd7cddfSDavid du Colombier * with '_'s replacing '/'s 220*7dd7cddfSDavid du Colombier */ 221*7dd7cddfSDavid du Colombier void 222*7dd7cddfSDavid du Colombier setext(char *ext, int n, char *p) 223*7dd7cddfSDavid du Colombier { 224*7dd7cddfSDavid du Colombier int i, c; 2253e12c5d1SDavid du Colombier 226*7dd7cddfSDavid du Colombier n--; 227*7dd7cddfSDavid du Colombier for(i = 0; i < n; i++){ 228*7dd7cddfSDavid du Colombier c = p[i]; 229*7dd7cddfSDavid du Colombier if(c == 0) 230*7dd7cddfSDavid du Colombier break; 231*7dd7cddfSDavid du Colombier if(c == '/') 232*7dd7cddfSDavid du Colombier c = '_'; 233*7dd7cddfSDavid du Colombier ext[i] = c; 234*7dd7cddfSDavid du Colombier } 235*7dd7cddfSDavid du Colombier ext[i] = 0; 2363e12c5d1SDavid du Colombier } 2373e12c5d1SDavid du Colombier 2383e12c5d1SDavid du Colombier void 239*7dd7cddfSDavid du Colombier mountinit(char *service, char *mntpt) 2403e12c5d1SDavid du Colombier { 2413e12c5d1SDavid du Colombier int f; 2423e12c5d1SDavid du Colombier int p[2]; 2433e12c5d1SDavid du Colombier char buf[32]; 2443e12c5d1SDavid du Colombier 2453e12c5d1SDavid du Colombier if(pipe(p) < 0) 2463e12c5d1SDavid du Colombier error("pipe failed"); 247219b2ee8SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG)){ 2483e12c5d1SDavid du Colombier case 0: 249219b2ee8SDavid du Colombier close(p[1]); 2503e12c5d1SDavid du Colombier break; 2513e12c5d1SDavid du Colombier case -1: 2523e12c5d1SDavid du Colombier error("fork failed\n"); 2533e12c5d1SDavid du Colombier default: 2543e12c5d1SDavid du Colombier /* 2553e12c5d1SDavid du Colombier * make a /srv/cs 2563e12c5d1SDavid du Colombier */ 2573e12c5d1SDavid du Colombier f = create(service, 1, 0666); 2583e12c5d1SDavid du Colombier if(f < 0) 2593e12c5d1SDavid du Colombier error(service); 260bd389b36SDavid du Colombier snprint(buf, sizeof(buf), "%d", p[1]); 2613e12c5d1SDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf)) 262219b2ee8SDavid du Colombier error("write /srv/cs"); 2633e12c5d1SDavid du Colombier close(f); 2643e12c5d1SDavid du Colombier 2653e12c5d1SDavid du Colombier /* 2663e12c5d1SDavid du Colombier * put ourselves into the file system 2673e12c5d1SDavid du Colombier */ 268219b2ee8SDavid du Colombier close(p[0]); 269*7dd7cddfSDavid du Colombier if(mount(p[1], mntpt, MAFTER, "") < 0) 2703e12c5d1SDavid du Colombier error("mount failed\n"); 271219b2ee8SDavid du Colombier _exits(0); 2723e12c5d1SDavid du Colombier } 2733e12c5d1SDavid du Colombier mfd[0] = mfd[1] = p[0]; 2743e12c5d1SDavid du Colombier } 2753e12c5d1SDavid du Colombier 276*7dd7cddfSDavid du Colombier void 277*7dd7cddfSDavid du Colombier ndbinit(void) 278*7dd7cddfSDavid du Colombier { 279*7dd7cddfSDavid du Colombier db = ndbopen(dbfile); 280*7dd7cddfSDavid du Colombier if(db == nil) 281*7dd7cddfSDavid du Colombier error("can't open network database"); 282*7dd7cddfSDavid du Colombier 283*7dd7cddfSDavid du Colombier netdb = ndbopen(netndb); 284*7dd7cddfSDavid du Colombier if(netdb != nil){ 285*7dd7cddfSDavid du Colombier netdb->nohash = 1; 286*7dd7cddfSDavid du Colombier db = ndbcat(netdb, db); 287*7dd7cddfSDavid du Colombier } 288*7dd7cddfSDavid du Colombier } 289*7dd7cddfSDavid du Colombier 2903e12c5d1SDavid du Colombier Mfile* 2913e12c5d1SDavid du Colombier newfid(int fid) 2923e12c5d1SDavid du Colombier { 293219b2ee8SDavid du Colombier Mlist *f, *ff; 2943e12c5d1SDavid du Colombier Mfile *mf; 2953e12c5d1SDavid du Colombier 296219b2ee8SDavid du Colombier ff = 0; 297219b2ee8SDavid du Colombier for(f = mlist; f; f = f->next) 298219b2ee8SDavid du Colombier if(f->mf.busy && f->mf.fid == fid) 299219b2ee8SDavid du Colombier return &f->mf; 300219b2ee8SDavid du Colombier else if(!ff && !f->mf.busy) 301219b2ee8SDavid du Colombier ff = f; 302219b2ee8SDavid du Colombier if(ff == 0){ 303*7dd7cddfSDavid du Colombier ff = emalloc(sizeof *f); 304219b2ee8SDavid du Colombier ff->next = mlist; 305219b2ee8SDavid du Colombier mlist = ff; 3063e12c5d1SDavid du Colombier } 307219b2ee8SDavid du Colombier mf = &ff->mf; 308219b2ee8SDavid du Colombier memset(mf, 0, sizeof *mf); 3093e12c5d1SDavid du Colombier mf->fid = fid; 3103e12c5d1SDavid du Colombier return mf; 3113e12c5d1SDavid du Colombier } 3123e12c5d1SDavid du Colombier 313*7dd7cddfSDavid du Colombier Job* 314*7dd7cddfSDavid du Colombier newjob(void) 315*7dd7cddfSDavid du Colombier { 316*7dd7cddfSDavid du Colombier Job *job; 317*7dd7cddfSDavid du Colombier 318*7dd7cddfSDavid du Colombier job = mallocz(sizeof(Job), 1); 319*7dd7cddfSDavid du Colombier lock(&joblock); 320*7dd7cddfSDavid du Colombier job->next = joblist; 321*7dd7cddfSDavid du Colombier joblist = job; 322*7dd7cddfSDavid du Colombier job->request.tag = -1; 323*7dd7cddfSDavid du Colombier unlock(&joblock); 324*7dd7cddfSDavid du Colombier return job; 325*7dd7cddfSDavid du Colombier } 326*7dd7cddfSDavid du Colombier 327*7dd7cddfSDavid du Colombier void 328*7dd7cddfSDavid du Colombier freejob(Job *job) 329*7dd7cddfSDavid du Colombier { 330*7dd7cddfSDavid du Colombier Job **l; 331*7dd7cddfSDavid du Colombier 332*7dd7cddfSDavid du Colombier lock(&joblock); 333*7dd7cddfSDavid du Colombier for(l = &joblist; *l; l = &(*l)->next){ 334*7dd7cddfSDavid du Colombier if((*l) == job){ 335*7dd7cddfSDavid du Colombier *l = job->next; 336*7dd7cddfSDavid du Colombier free(job); 337*7dd7cddfSDavid du Colombier break; 338*7dd7cddfSDavid du Colombier } 339*7dd7cddfSDavid du Colombier } 340*7dd7cddfSDavid du Colombier unlock(&joblock); 341*7dd7cddfSDavid du Colombier } 342*7dd7cddfSDavid du Colombier 343*7dd7cddfSDavid du Colombier void 344*7dd7cddfSDavid du Colombier flushjob(int tag) 345*7dd7cddfSDavid du Colombier { 346*7dd7cddfSDavid du Colombier Job *job; 347*7dd7cddfSDavid du Colombier 348*7dd7cddfSDavid du Colombier lock(&joblock); 349*7dd7cddfSDavid du Colombier for(job = joblist; job; job = job->next){ 350*7dd7cddfSDavid du Colombier if(job->request.tag == tag && job->request.type != Tflush){ 351*7dd7cddfSDavid du Colombier job->flushed = 1; 352*7dd7cddfSDavid du Colombier break; 353*7dd7cddfSDavid du Colombier } 354*7dd7cddfSDavid du Colombier } 355*7dd7cddfSDavid du Colombier unlock(&joblock); 356*7dd7cddfSDavid du Colombier } 357*7dd7cddfSDavid du Colombier 3583e12c5d1SDavid du Colombier void 3593e12c5d1SDavid du Colombier io(void) 3603e12c5d1SDavid du Colombier { 3613e12c5d1SDavid du Colombier long n; 3623e12c5d1SDavid du Colombier Mfile *mf; 3633e12c5d1SDavid du Colombier int slaveflag; 3643e12c5d1SDavid du Colombier char mdata[MAXFDATA + MAXMSG]; 365*7dd7cddfSDavid du Colombier Job *job; 3663e12c5d1SDavid du Colombier 3673e12c5d1SDavid du Colombier /* 3683e12c5d1SDavid du Colombier * if we ask dns to fulfill requests, 3693e12c5d1SDavid du Colombier * a slave process is created to wait for replies. The 3703e12c5d1SDavid du Colombier * master process returns immediately via a longjmp's 3713e12c5d1SDavid du Colombier * through 'masterjmp'. 3723e12c5d1SDavid du Colombier * 3733e12c5d1SDavid du Colombier * *isslave is a pointer into the call stack to a variable 3743e12c5d1SDavid du Colombier * that tells whether or not the current process is a slave. 3753e12c5d1SDavid du Colombier */ 3763e12c5d1SDavid du Colombier slaveflag = 0; /* init slave variable */ 3773e12c5d1SDavid du Colombier isslave = &slaveflag; 3783e12c5d1SDavid du Colombier setjmp(masterjmp); 3793e12c5d1SDavid du Colombier 3803e12c5d1SDavid du Colombier for(;;){ 381219b2ee8SDavid du Colombier n = read9p(mfd[0], mdata, sizeof mdata); 3823e12c5d1SDavid du Colombier if(n<=0) 3833e12c5d1SDavid du Colombier error("mount read"); 384*7dd7cddfSDavid du Colombier job = newjob(); 385*7dd7cddfSDavid du Colombier if(convM2S(mdata, &job->request, n) == 0){ 386219b2ee8SDavid du Colombier syslog(1, logfile, "format error %ux %ux %ux %ux %ux", mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]); 387*7dd7cddfSDavid du Colombier freejob(job); 3883e12c5d1SDavid du Colombier continue; 3893e12c5d1SDavid du Colombier } 390*7dd7cddfSDavid du Colombier if(job->request.fid<0) 3913e12c5d1SDavid du Colombier error("fid out of range"); 392bd389b36SDavid du Colombier lock(&dblock); 393*7dd7cddfSDavid du Colombier mf = newfid(job->request.fid); 394219b2ee8SDavid du Colombier if(debug) 395*7dd7cddfSDavid du Colombier syslog(0, logfile, "%F", &job->request); 3963e12c5d1SDavid du Colombier 3973e12c5d1SDavid du Colombier 398*7dd7cddfSDavid du Colombier switch(job->request.type){ 3993e12c5d1SDavid du Colombier default: 400*7dd7cddfSDavid du Colombier syslog(1, logfile, "unknown request type %d", job->request.type); 4013e12c5d1SDavid du Colombier break; 4023e12c5d1SDavid du Colombier case Tsession: 403*7dd7cddfSDavid du Colombier rsession(job); 4043e12c5d1SDavid du Colombier break; 4053e12c5d1SDavid du Colombier case Tnop: 406*7dd7cddfSDavid du Colombier rnop(job); 4073e12c5d1SDavid du Colombier break; 4083e12c5d1SDavid du Colombier case Tflush: 409*7dd7cddfSDavid du Colombier rflush(job); 4103e12c5d1SDavid du Colombier break; 4113e12c5d1SDavid du Colombier case Tattach: 412*7dd7cddfSDavid du Colombier rattach(job, mf); 4133e12c5d1SDavid du Colombier break; 4143e12c5d1SDavid du Colombier case Tclone: 415*7dd7cddfSDavid du Colombier rclone(job, mf); 4163e12c5d1SDavid du Colombier break; 4173e12c5d1SDavid du Colombier case Twalk: 418*7dd7cddfSDavid du Colombier rwalk(job, mf); 4193e12c5d1SDavid du Colombier break; 4203e12c5d1SDavid du Colombier case Tclwalk: 421*7dd7cddfSDavid du Colombier rclwalk(job, mf); 4223e12c5d1SDavid du Colombier break; 4233e12c5d1SDavid du Colombier case Topen: 424*7dd7cddfSDavid du Colombier ropen(job, mf); 4253e12c5d1SDavid du Colombier break; 4263e12c5d1SDavid du Colombier case Tcreate: 427*7dd7cddfSDavid du Colombier rcreate(job, mf); 4283e12c5d1SDavid du Colombier break; 4293e12c5d1SDavid du Colombier case Tread: 430*7dd7cddfSDavid du Colombier rread(job, mf); 4313e12c5d1SDavid du Colombier break; 4323e12c5d1SDavid du Colombier case Twrite: 433*7dd7cddfSDavid du Colombier rwrite(job, mf); 4343e12c5d1SDavid du Colombier break; 4353e12c5d1SDavid du Colombier case Tclunk: 436*7dd7cddfSDavid du Colombier rclunk(job, mf); 4373e12c5d1SDavid du Colombier break; 4383e12c5d1SDavid du Colombier case Tremove: 439*7dd7cddfSDavid du Colombier rremove(job, mf); 4403e12c5d1SDavid du Colombier break; 4413e12c5d1SDavid du Colombier case Tstat: 442*7dd7cddfSDavid du Colombier rstat(job, mf); 4433e12c5d1SDavid du Colombier break; 4443e12c5d1SDavid du Colombier case Twstat: 445*7dd7cddfSDavid du Colombier rwstat(job, mf); 4463e12c5d1SDavid du Colombier break; 4473e12c5d1SDavid du Colombier } 448bd389b36SDavid du Colombier unlock(&dblock); 449*7dd7cddfSDavid du Colombier 450*7dd7cddfSDavid du Colombier freejob(job); 451*7dd7cddfSDavid du Colombier 4523e12c5d1SDavid du Colombier /* 4533e12c5d1SDavid du Colombier * slave processes die after replying 4543e12c5d1SDavid du Colombier */ 455219b2ee8SDavid du Colombier if(*isslave){ 456219b2ee8SDavid du Colombier if(debug) 457219b2ee8SDavid du Colombier syslog(0, logfile, "slave death %d", getpid()); 4583e12c5d1SDavid du Colombier _exits(0); 4593e12c5d1SDavid du Colombier } 4603e12c5d1SDavid du Colombier } 461219b2ee8SDavid du Colombier } 462219b2ee8SDavid du Colombier 463219b2ee8SDavid du Colombier void 464*7dd7cddfSDavid du Colombier rsession(Job *job) 465219b2ee8SDavid du Colombier { 466*7dd7cddfSDavid du Colombier memset(job->reply.authid, 0, sizeof(job->reply.authid)); 467*7dd7cddfSDavid du Colombier memset(job->reply.authdom, 0, sizeof(job->reply.authdom)); 468*7dd7cddfSDavid du Colombier memset(job->reply.chal, 0, sizeof(job->reply.chal)); 469*7dd7cddfSDavid du Colombier sendmsg(job, 0); 470219b2ee8SDavid du Colombier } 4713e12c5d1SDavid du Colombier 4723e12c5d1SDavid du Colombier void 473*7dd7cddfSDavid du Colombier rnop(Job *job) 4743e12c5d1SDavid du Colombier { 475*7dd7cddfSDavid du Colombier sendmsg(job, 0); 476*7dd7cddfSDavid du Colombier } 477*7dd7cddfSDavid du Colombier 478*7dd7cddfSDavid du Colombier /* 479*7dd7cddfSDavid du Colombier * don't flush till all the slaves are done 480*7dd7cddfSDavid du Colombier */ 481*7dd7cddfSDavid du Colombier void 482*7dd7cddfSDavid du Colombier rflush(Job *job) 483*7dd7cddfSDavid du Colombier { 484*7dd7cddfSDavid du Colombier flushjob(job->request.oldtag); 485*7dd7cddfSDavid du Colombier sendmsg(job, 0); 4863e12c5d1SDavid du Colombier } 4873e12c5d1SDavid du Colombier 4883e12c5d1SDavid du Colombier void 489*7dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf) 4903e12c5d1SDavid du Colombier { 4913e12c5d1SDavid du Colombier if(mf->busy == 0){ 4923e12c5d1SDavid du Colombier mf->busy = 1; 493*7dd7cddfSDavid du Colombier strcpy(mf->user, job->request.uname); 4943e12c5d1SDavid du Colombier } 4953e12c5d1SDavid du Colombier mf->qid.vers = vers++; 4963e12c5d1SDavid du Colombier mf->qid.path = CHDIR; 497*7dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 498*7dd7cddfSDavid du Colombier sendmsg(job, 0); 4993e12c5d1SDavid du Colombier } 5003e12c5d1SDavid du Colombier 5013e12c5d1SDavid du Colombier void 502*7dd7cddfSDavid du Colombier rclone(Job *job, Mfile *mf) 5033e12c5d1SDavid du Colombier { 5043e12c5d1SDavid du Colombier Mfile *nmf; 5053e12c5d1SDavid du Colombier char *err=0; 5063e12c5d1SDavid du Colombier 507*7dd7cddfSDavid du Colombier if(job->request.newfid<0){ 5083e12c5d1SDavid du Colombier err = "clone nfid out of range"; 5093e12c5d1SDavid du Colombier goto send; 5103e12c5d1SDavid du Colombier } 511*7dd7cddfSDavid du Colombier nmf = newfid(job->request.newfid); 5123e12c5d1SDavid du Colombier if(nmf->busy){ 5133e12c5d1SDavid du Colombier err = "clone to used channel"; 5143e12c5d1SDavid du Colombier goto send; 5153e12c5d1SDavid du Colombier } 5163e12c5d1SDavid du Colombier *nmf = *mf; 517*7dd7cddfSDavid du Colombier nmf->fid = job->request.newfid; 5183e12c5d1SDavid du Colombier nmf->qid.vers = vers++; 5193e12c5d1SDavid du Colombier send: 520*7dd7cddfSDavid du Colombier sendmsg(job, err); 5213e12c5d1SDavid du Colombier } 5223e12c5d1SDavid du Colombier 5233e12c5d1SDavid du Colombier void 524*7dd7cddfSDavid du Colombier rclwalk(Job *job, Mfile *mf) 5253e12c5d1SDavid du Colombier { 5263e12c5d1SDavid du Colombier Mfile *nmf; 5273e12c5d1SDavid du Colombier 528*7dd7cddfSDavid du Colombier if(job->request.newfid<0){ 529*7dd7cddfSDavid du Colombier sendmsg(job, "clone nfid out of range"); 5303e12c5d1SDavid du Colombier return; 5313e12c5d1SDavid du Colombier } 532*7dd7cddfSDavid du Colombier nmf = newfid(job->request.newfid); 5333e12c5d1SDavid du Colombier if(nmf->busy){ 534*7dd7cddfSDavid du Colombier sendmsg(job, "clone to used channel"); 5353e12c5d1SDavid du Colombier return; 5363e12c5d1SDavid du Colombier } 5373e12c5d1SDavid du Colombier *nmf = *mf; 538*7dd7cddfSDavid du Colombier nmf->fid = job->request.newfid; 539*7dd7cddfSDavid du Colombier job->request.fid = job->request.newfid; 5403e12c5d1SDavid du Colombier nmf->qid.vers = vers++; 541*7dd7cddfSDavid du Colombier if(rwalk(job, nmf)) 5423e12c5d1SDavid du Colombier nmf->busy = 0; 5433e12c5d1SDavid du Colombier } 5443e12c5d1SDavid du Colombier 5453e12c5d1SDavid du Colombier char* 546*7dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf) 5473e12c5d1SDavid du Colombier { 5483e12c5d1SDavid du Colombier char *err; 5493e12c5d1SDavid du Colombier char *name; 5503e12c5d1SDavid du Colombier 5513e12c5d1SDavid du Colombier err = 0; 552*7dd7cddfSDavid du Colombier name = job->request.name; 5533e12c5d1SDavid du Colombier if((mf->qid.path & CHDIR) == 0){ 5543e12c5d1SDavid du Colombier err = "not a directory"; 5553e12c5d1SDavid du Colombier goto send; 5563e12c5d1SDavid du Colombier } 5573e12c5d1SDavid du Colombier if(strcmp(name, ".") == 0){ 5583e12c5d1SDavid du Colombier mf->qid.path = CHDIR; 5593e12c5d1SDavid du Colombier goto send; 5603e12c5d1SDavid du Colombier } 5613e12c5d1SDavid du Colombier if(strcmp(name, "cs") == 0){ 5623e12c5d1SDavid du Colombier mf->qid.path = Qcs; 5633e12c5d1SDavid du Colombier goto send; 5643e12c5d1SDavid du Colombier } 5653e12c5d1SDavid du Colombier err = "nonexistent file"; 5663e12c5d1SDavid du Colombier send: 567*7dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 568*7dd7cddfSDavid du Colombier sendmsg(job, err); 5693e12c5d1SDavid du Colombier return err; 5703e12c5d1SDavid du Colombier } 5713e12c5d1SDavid du Colombier 5723e12c5d1SDavid du Colombier void 573*7dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf) 5743e12c5d1SDavid du Colombier { 5753e12c5d1SDavid du Colombier int mode; 5763e12c5d1SDavid du Colombier char *err; 5773e12c5d1SDavid du Colombier 5783e12c5d1SDavid du Colombier err = 0; 579*7dd7cddfSDavid du Colombier mode = job->request.mode; 5803e12c5d1SDavid du Colombier if(mf->qid.path & CHDIR){ 5813e12c5d1SDavid du Colombier if(mode) 5823e12c5d1SDavid du Colombier err = "permission denied"; 5833e12c5d1SDavid du Colombier } 584*7dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 585*7dd7cddfSDavid du Colombier sendmsg(job, err); 5863e12c5d1SDavid du Colombier } 5873e12c5d1SDavid du Colombier 5883e12c5d1SDavid du Colombier void 589*7dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf) 5903e12c5d1SDavid du Colombier { 5913e12c5d1SDavid du Colombier USED(mf); 592*7dd7cddfSDavid du Colombier sendmsg(job, "creation permission denied"); 5933e12c5d1SDavid du Colombier } 5943e12c5d1SDavid du Colombier 5953e12c5d1SDavid du Colombier void 596*7dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf) 5973e12c5d1SDavid du Colombier { 598219b2ee8SDavid du Colombier int i, n, cnt; 599219b2ee8SDavid du Colombier long off, toff, clock; 6003e12c5d1SDavid du Colombier Dir dir; 6013e12c5d1SDavid du Colombier char buf[MAXFDATA]; 6023e12c5d1SDavid du Colombier char *err; 6033e12c5d1SDavid du Colombier 6043e12c5d1SDavid du Colombier n = 0; 6053e12c5d1SDavid du Colombier err = 0; 606*7dd7cddfSDavid du Colombier off = job->request.offset; 607*7dd7cddfSDavid du Colombier cnt = job->request.count; 6083e12c5d1SDavid du Colombier if(mf->qid.path & CHDIR){ 6093e12c5d1SDavid du Colombier if(off%DIRLEN || cnt%DIRLEN){ 6103e12c5d1SDavid du Colombier err = "bad offset"; 6113e12c5d1SDavid du Colombier goto send; 6123e12c5d1SDavid du Colombier } 6133e12c5d1SDavid du Colombier clock = time(0); 6143e12c5d1SDavid du Colombier if(off == 0){ 6153e12c5d1SDavid du Colombier memmove(dir.name, "cs", NAMELEN); 6163e12c5d1SDavid du Colombier dir.qid.vers = vers; 6173e12c5d1SDavid du Colombier dir.qid.path = Qcs; 6183e12c5d1SDavid du Colombier dir.mode = 0666; 6193e12c5d1SDavid du Colombier dir.length = 0; 6203e12c5d1SDavid du Colombier strcpy(dir.uid, mf->user); 6213e12c5d1SDavid du Colombier strcpy(dir.gid, mf->user); 6223e12c5d1SDavid du Colombier dir.atime = clock; /* wrong */ 6233e12c5d1SDavid du Colombier dir.mtime = clock; /* wrong */ 6243e12c5d1SDavid du Colombier convD2M(&dir, buf+n); 6253e12c5d1SDavid du Colombier n += DIRLEN; 6263e12c5d1SDavid du Colombier } 627*7dd7cddfSDavid du Colombier job->reply.data = buf; 6283e12c5d1SDavid du Colombier } else { 629219b2ee8SDavid du Colombier toff = 0; 630219b2ee8SDavid du Colombier for(i = 0; mf->reply[i] && i < mf->nreply; i++){ 631219b2ee8SDavid du Colombier n = mf->replylen[i]; 632219b2ee8SDavid du Colombier if(off < toff + n) 633219b2ee8SDavid du Colombier break; 634219b2ee8SDavid du Colombier toff += n; 6353e12c5d1SDavid du Colombier } 636219b2ee8SDavid du Colombier if(i >= mf->nreply){ 637219b2ee8SDavid du Colombier n = 0; 638219b2ee8SDavid du Colombier goto send; 639219b2ee8SDavid du Colombier } 640*7dd7cddfSDavid du Colombier job->reply.data = mf->reply[i] + (off - toff); 641219b2ee8SDavid du Colombier if(cnt > toff - off + n) 642219b2ee8SDavid du Colombier n = toff - off + n; 643219b2ee8SDavid du Colombier else 644219b2ee8SDavid du Colombier n = cnt; 6453e12c5d1SDavid du Colombier } 6463e12c5d1SDavid du Colombier send: 647*7dd7cddfSDavid du Colombier job->reply.count = n; 648*7dd7cddfSDavid du Colombier sendmsg(job, err); 649*7dd7cddfSDavid du Colombier } 650*7dd7cddfSDavid du Colombier 651*7dd7cddfSDavid du Colombier CacheEntry* 652*7dd7cddfSDavid du Colombier nextcache(char *question, ulong now) 653*7dd7cddfSDavid du Colombier { 654*7dd7cddfSDavid du Colombier CacheEntry *cp; 655*7dd7cddfSDavid du Colombier int i; 656*7dd7cddfSDavid du Colombier 657*7dd7cddfSDavid du Colombier cp = &cache.e[cache.next]; 658*7dd7cddfSDavid du Colombier cache.next = (cache.next + 1)%Ncache; 659*7dd7cddfSDavid du Colombier cp->expire = now + 120; 660*7dd7cddfSDavid du Colombier 661*7dd7cddfSDavid du Colombier /* out with the old air */ 662*7dd7cddfSDavid du Colombier if(cp->question){ 663*7dd7cddfSDavid du Colombier free(cp->question); 664*7dd7cddfSDavid du Colombier cp->question = 0; 665*7dd7cddfSDavid du Colombier } 666*7dd7cddfSDavid du Colombier for(i = 0; i < cp->nreply; i++) 667*7dd7cddfSDavid du Colombier free(cp->reply[i]); 668*7dd7cddfSDavid du Colombier cp->err[0] = 0; 669*7dd7cddfSDavid du Colombier cp->nreply = 0; 670*7dd7cddfSDavid du Colombier 671*7dd7cddfSDavid du Colombier /* in with the new */ 672*7dd7cddfSDavid du Colombier cp->question = question; 673*7dd7cddfSDavid du Colombier return cp; 674*7dd7cddfSDavid du Colombier } 675*7dd7cddfSDavid du Colombier 676*7dd7cddfSDavid du Colombier CacheEntry* 677*7dd7cddfSDavid du Colombier searchcache(char *question, ulong now) 678*7dd7cddfSDavid du Colombier { 679*7dd7cddfSDavid du Colombier CacheEntry *cp; 680*7dd7cddfSDavid du Colombier 681*7dd7cddfSDavid du Colombier for(cp = cache.e; cp < &cache.e[Ncache]; cp++){ 682*7dd7cddfSDavid du Colombier if(cp->expire > now) 683*7dd7cddfSDavid du Colombier if(strcmp(question, cp->question) == 0) 684*7dd7cddfSDavid du Colombier return cp; 685*7dd7cddfSDavid du Colombier } 686*7dd7cddfSDavid du Colombier return 0; 6873e12c5d1SDavid du Colombier } 6883e12c5d1SDavid du Colombier 6893e12c5d1SDavid du Colombier void 690*7dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf) 6913e12c5d1SDavid du Colombier { 6923e12c5d1SDavid du Colombier int cnt, n; 693*7dd7cddfSDavid du Colombier char *question, *err, errbuf[ERRLEN]; 694*7dd7cddfSDavid du Colombier char *field[4]; 695*7dd7cddfSDavid du Colombier int i, rv; 696*7dd7cddfSDavid du Colombier ulong now; 697*7dd7cddfSDavid du Colombier CacheEntry *cp; 6983e12c5d1SDavid du Colombier 699*7dd7cddfSDavid du Colombier now = time(0); 7003e12c5d1SDavid du Colombier err = 0; 701*7dd7cddfSDavid du Colombier cnt = job->request.count; 7023e12c5d1SDavid du Colombier if(mf->qid.path & CHDIR){ 7033e12c5d1SDavid du Colombier err = "can't write directory"; 7043e12c5d1SDavid du Colombier goto send; 7053e12c5d1SDavid du Colombier } 7063e12c5d1SDavid du Colombier if(cnt >= Maxrequest){ 7073e12c5d1SDavid du Colombier err = "request too long"; 7083e12c5d1SDavid du Colombier goto send; 7093e12c5d1SDavid du Colombier } 710*7dd7cddfSDavid du Colombier job->request.data[cnt] = 0; 7113e12c5d1SDavid du Colombier 7123e12c5d1SDavid du Colombier /* 713219b2ee8SDavid du Colombier * toggle debugging 714219b2ee8SDavid du Colombier */ 715*7dd7cddfSDavid du Colombier if(strncmp(job->request.data, "debug", 5)==0){ 716219b2ee8SDavid du Colombier debug ^= 1; 717219b2ee8SDavid du Colombier syslog(1, logfile, "debug %d", debug); 718219b2ee8SDavid du Colombier goto send; 719219b2ee8SDavid du Colombier } 720219b2ee8SDavid du Colombier 721219b2ee8SDavid du Colombier /* 722*7dd7cddfSDavid du Colombier * toggle debugging 723*7dd7cddfSDavid du Colombier */ 724*7dd7cddfSDavid du Colombier if(strncmp(job->request.data, "paranoia", 8)==0){ 725*7dd7cddfSDavid du Colombier paranoia ^= 1; 726*7dd7cddfSDavid du Colombier syslog(1, logfile, "paranoia %d", paranoia); 727*7dd7cddfSDavid du Colombier goto send; 728*7dd7cddfSDavid du Colombier } 729*7dd7cddfSDavid du Colombier 730*7dd7cddfSDavid du Colombier /* 7313e12c5d1SDavid du Colombier * add networks to the default list 7323e12c5d1SDavid du Colombier */ 733*7dd7cddfSDavid du Colombier if(strncmp(job->request.data, "add ", 4)==0){ 734*7dd7cddfSDavid du Colombier if(job->request.data[cnt-1] == '\n') 735*7dd7cddfSDavid du Colombier job->request.data[cnt-1] = 0; 736*7dd7cddfSDavid du Colombier netadd(job->request.data+4); 737*7dd7cddfSDavid du Colombier readipinterfaces(); 738*7dd7cddfSDavid du Colombier goto send; 739*7dd7cddfSDavid du Colombier } 740*7dd7cddfSDavid du Colombier 741*7dd7cddfSDavid du Colombier /* 742*7dd7cddfSDavid du Colombier * refresh all state 743*7dd7cddfSDavid du Colombier */ 744*7dd7cddfSDavid du Colombier if(strncmp(job->request.data, "refresh", 7)==0){ 745*7dd7cddfSDavid du Colombier netinit(1); 746*7dd7cddfSDavid du Colombier for(i = 0; i < Ncache; i++) 747*7dd7cddfSDavid du Colombier cache.e[i].expire = 0; 7483e12c5d1SDavid du Colombier goto send; 7493e12c5d1SDavid du Colombier } 7503e12c5d1SDavid du Colombier 7513e12c5d1SDavid du Colombier /* 752219b2ee8SDavid du Colombier * look for a general query 753219b2ee8SDavid du Colombier */ 754*7dd7cddfSDavid du Colombier if(*job->request.data == '!'){ 755*7dd7cddfSDavid du Colombier err = genquery(mf, job->request.data+1); 756219b2ee8SDavid du Colombier goto send; 757219b2ee8SDavid du Colombier } 758219b2ee8SDavid du Colombier 759*7dd7cddfSDavid du Colombier /* start transaction with a clean slate */ 760*7dd7cddfSDavid du Colombier for(i = 0; i < Nreply; i++){ 761*7dd7cddfSDavid du Colombier if(mf->reply[i]) 762*7dd7cddfSDavid du Colombier free(mf->reply[i]); 763*7dd7cddfSDavid du Colombier mf->reply[i] = 0; 764*7dd7cddfSDavid du Colombier mf->replylen[i] = 0; 765*7dd7cddfSDavid du Colombier } 766*7dd7cddfSDavid du Colombier mf->nreply = 0; 767*7dd7cddfSDavid du Colombier 768*7dd7cddfSDavid du Colombier if(debug) 769*7dd7cddfSDavid du Colombier syslog(0, logfile, "write %s", job->request.data); 770*7dd7cddfSDavid du Colombier if(paranoia) 771*7dd7cddfSDavid du Colombier syslog(0, paranoiafile, "write %s by %s", job->request.data, mf->user); 772*7dd7cddfSDavid du Colombier 773*7dd7cddfSDavid du Colombier /* first try cache */ 774*7dd7cddfSDavid du Colombier lock(&cache); 775*7dd7cddfSDavid du Colombier cp = searchcache(job->request.data, now); 776*7dd7cddfSDavid du Colombier if(cp){ 777*7dd7cddfSDavid du Colombier if(cp->err[0]){ 778*7dd7cddfSDavid du Colombier memmove(errbuf, cp->err, ERRLEN); 779*7dd7cddfSDavid du Colombier err = errbuf; 780*7dd7cddfSDavid du Colombier } else { 781*7dd7cddfSDavid du Colombier for(i = 0; i < cp->nreply; i++){ 782*7dd7cddfSDavid du Colombier mf->reply[i] = strdup(cp->reply[i]); 783*7dd7cddfSDavid du Colombier mf->replylen[i] = strlen(cp->reply[i]); 784*7dd7cddfSDavid du Colombier } 785*7dd7cddfSDavid du Colombier mf->nreply = cp->nreply; 786*7dd7cddfSDavid du Colombier } 787*7dd7cddfSDavid du Colombier unlock(&cache); 788*7dd7cddfSDavid du Colombier goto send; 789*7dd7cddfSDavid du Colombier } 790*7dd7cddfSDavid du Colombier unlock(&cache); 791*7dd7cddfSDavid du Colombier 792219b2ee8SDavid du Colombier /* 7933e12c5d1SDavid du Colombier * break up name 7943e12c5d1SDavid du Colombier */ 795*7dd7cddfSDavid du Colombier question = strdup(job->request.data); 796*7dd7cddfSDavid du Colombier n = getfields(job->request.data, field, 4, 1, "!"); 7973e12c5d1SDavid du Colombier rv = -1; 7983e12c5d1SDavid du Colombier switch(n){ 7993e12c5d1SDavid du Colombier case 1: 800*7dd7cddfSDavid du Colombier rv = lookup(mf, "net", field[0], 0, 0); 8013e12c5d1SDavid du Colombier break; 8023e12c5d1SDavid du Colombier case 2: 803*7dd7cddfSDavid du Colombier rv = lookup(mf, field[0], field[1], 0, 0); 8043e12c5d1SDavid du Colombier break; 8053e12c5d1SDavid du Colombier case 3: 806*7dd7cddfSDavid du Colombier rv = lookup(mf, field[0], field[1], field[2], 0); 807*7dd7cddfSDavid du Colombier break; 808*7dd7cddfSDavid du Colombier case 4: 809*7dd7cddfSDavid du Colombier rv = lookup(mf, field[0], field[1], field[2], field[3]); 8103e12c5d1SDavid du Colombier break; 8113e12c5d1SDavid du Colombier } 8123e12c5d1SDavid du Colombier 813*7dd7cddfSDavid du Colombier lock(&cache); 814*7dd7cddfSDavid du Colombier cp = nextcache(question, now); 815*7dd7cddfSDavid du Colombier if(rv < 0){ 8163e12c5d1SDavid du Colombier err = "can't translate address"; 817*7dd7cddfSDavid du Colombier errstr(errbuf); 818*7dd7cddfSDavid du Colombier if(strstr(errbuf, "dns:")) 819*7dd7cddfSDavid du Colombier err = errbuf; 820*7dd7cddfSDavid du Colombier strncpy(cp->err, err, ERRLEN); 821*7dd7cddfSDavid du Colombier } else { 822*7dd7cddfSDavid du Colombier for(i = 0; i < mf->nreply; i++) 823*7dd7cddfSDavid du Colombier cp->reply[i] = strdup(mf->reply[i]); 824*7dd7cddfSDavid du Colombier cp->nreply = mf->nreply; 825*7dd7cddfSDavid du Colombier } 826*7dd7cddfSDavid du Colombier unlock(&cache); 8273e12c5d1SDavid du Colombier 8283e12c5d1SDavid du Colombier send: 829*7dd7cddfSDavid du Colombier job->reply.count = cnt; 830*7dd7cddfSDavid du Colombier sendmsg(job, err); 8313e12c5d1SDavid du Colombier } 8323e12c5d1SDavid du Colombier 8333e12c5d1SDavid du Colombier void 834*7dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf) 8353e12c5d1SDavid du Colombier { 836219b2ee8SDavid du Colombier int i; 837219b2ee8SDavid du Colombier 838219b2ee8SDavid du Colombier for(i = 0; i < mf->nreply; i++) 839219b2ee8SDavid du Colombier free(mf->reply[i]); 840*7dd7cddfSDavid du Colombier mf->nreply = 0; 841*7dd7cddfSDavid du Colombier 8423e12c5d1SDavid du Colombier mf->busy = 0; 8433e12c5d1SDavid du Colombier mf->fid = 0; 844*7dd7cddfSDavid du Colombier sendmsg(job, 0); 8453e12c5d1SDavid du Colombier } 8463e12c5d1SDavid du Colombier 8473e12c5d1SDavid du Colombier void 848*7dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf) 8493e12c5d1SDavid du Colombier { 8503e12c5d1SDavid du Colombier USED(mf); 851*7dd7cddfSDavid du Colombier sendmsg(job, "remove permission denied"); 8523e12c5d1SDavid du Colombier } 8533e12c5d1SDavid du Colombier 8543e12c5d1SDavid du Colombier void 855*7dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf) 8563e12c5d1SDavid du Colombier { 8573e12c5d1SDavid du Colombier Dir dir; 8583e12c5d1SDavid du Colombier 859219b2ee8SDavid du Colombier if(mf->qid.path & CHDIR){ 860219b2ee8SDavid du Colombier strcpy(dir.name, "."); 861219b2ee8SDavid du Colombier dir.mode = CHDIR|0555; 862219b2ee8SDavid du Colombier } else { 863219b2ee8SDavid du Colombier strcpy(dir.name, "cs"); 8643e12c5d1SDavid du Colombier dir.mode = 0666; 865219b2ee8SDavid du Colombier } 866219b2ee8SDavid du Colombier dir.qid = mf->qid; 8673e12c5d1SDavid du Colombier dir.length = 0; 8683e12c5d1SDavid du Colombier strcpy(dir.uid, mf->user); 8693e12c5d1SDavid du Colombier strcpy(dir.gid, mf->user); 8703e12c5d1SDavid du Colombier dir.atime = dir.mtime = time(0); 871*7dd7cddfSDavid du Colombier convD2M(&dir, (char*)job->reply.stat); 872*7dd7cddfSDavid du Colombier sendmsg(job, 0); 8733e12c5d1SDavid du Colombier } 8743e12c5d1SDavid du Colombier 8753e12c5d1SDavid du Colombier void 876*7dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf) 8773e12c5d1SDavid du Colombier { 8783e12c5d1SDavid du Colombier USED(mf); 879*7dd7cddfSDavid du Colombier sendmsg(job, "wstat permission denied"); 8803e12c5d1SDavid du Colombier } 8813e12c5d1SDavid du Colombier 8823e12c5d1SDavid du Colombier void 883*7dd7cddfSDavid du Colombier sendmsg(Job *job, char *err) 8843e12c5d1SDavid du Colombier { 8853e12c5d1SDavid du Colombier int n; 8863e12c5d1SDavid du Colombier char mdata[MAXFDATA + MAXMSG]; 8873e12c5d1SDavid du Colombier 8883e12c5d1SDavid du Colombier if(err){ 889*7dd7cddfSDavid du Colombier job->reply.type = Rerror; 890*7dd7cddfSDavid du Colombier snprint(job->reply.ename, sizeof(job->reply.ename), "cs: %s", err); 8913e12c5d1SDavid du Colombier }else{ 892*7dd7cddfSDavid du Colombier job->reply.type = job->request.type+1; 893*7dd7cddfSDavid du Colombier job->reply.fid = job->request.fid; 8943e12c5d1SDavid du Colombier } 895*7dd7cddfSDavid du Colombier job->reply.tag = job->request.tag; 896*7dd7cddfSDavid du Colombier n = convS2M(&job->reply, mdata); 897219b2ee8SDavid du Colombier if(n == 0){ 898*7dd7cddfSDavid du Colombier syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply); 899219b2ee8SDavid du Colombier abort(); 900219b2ee8SDavid du Colombier } 901*7dd7cddfSDavid du Colombier lock(&joblock); 902*7dd7cddfSDavid du Colombier if(job->flushed == 0) 903219b2ee8SDavid du Colombier if(write9p(mfd[1], mdata, n)!=n) 9043e12c5d1SDavid du Colombier error("mount write"); 905*7dd7cddfSDavid du Colombier unlock(&joblock); 906219b2ee8SDavid du Colombier if(debug) 907*7dd7cddfSDavid du Colombier syslog(0, logfile, "%F %d", &job->reply, n); 9083e12c5d1SDavid du Colombier } 9093e12c5d1SDavid du Colombier 9103e12c5d1SDavid du Colombier void 9113e12c5d1SDavid du Colombier error(char *s) 9123e12c5d1SDavid du Colombier { 913bd389b36SDavid du Colombier syslog(1, "cs", "%s: %r", s); 914bd389b36SDavid du Colombier _exits(0); 9153e12c5d1SDavid du Colombier } 9163e12c5d1SDavid du Colombier 9173e12c5d1SDavid du Colombier /* 9183e12c5d1SDavid du Colombier * Network specific translators 9193e12c5d1SDavid du Colombier */ 920219b2ee8SDavid du Colombier Ndbtuple* iplookup(Network*, char*, char*, int); 921*7dd7cddfSDavid du Colombier char* iptrans(Ndbtuple*, Network*, char*, char*); 922219b2ee8SDavid du Colombier Ndbtuple* telcolookup(Network*, char*, char*, int); 923*7dd7cddfSDavid du Colombier char* telcotrans(Ndbtuple*, Network*, char*, char*); 924*7dd7cddfSDavid du Colombier Ndbtuple* dnsiplookup(char*, Ndbs*); 9253e12c5d1SDavid du Colombier 9263e12c5d1SDavid du Colombier struct Network 9273e12c5d1SDavid du Colombier { 9283e12c5d1SDavid du Colombier char *net; 9293e12c5d1SDavid du Colombier int nolookup; 930219b2ee8SDavid du Colombier Ndbtuple *(*lookup)(Network*, char*, char*, int); 931*7dd7cddfSDavid du Colombier char *(*trans)(Ndbtuple*, Network*, char*, char*); 9323e12c5d1SDavid du Colombier int needproto; 9333e12c5d1SDavid du Colombier Network *next; 934*7dd7cddfSDavid du Colombier int considered; 9353e12c5d1SDavid du Colombier }; 9363e12c5d1SDavid du Colombier 937*7dd7cddfSDavid du Colombier enum 938*7dd7cddfSDavid du Colombier { 939*7dd7cddfSDavid du Colombier Nil, 940*7dd7cddfSDavid du Colombier Ntcp, 941*7dd7cddfSDavid du Colombier Nudp, 942*7dd7cddfSDavid du Colombier Nicmp, 943*7dd7cddfSDavid du Colombier Nrudp, 944*7dd7cddfSDavid du Colombier Ntelco, 9453e12c5d1SDavid du Colombier }; 9463e12c5d1SDavid du Colombier 947*7dd7cddfSDavid du Colombier /* 948*7dd7cddfSDavid du Colombier * net doesn't apply to udp, icmp, or telco (for speed) 949*7dd7cddfSDavid du Colombier */ 950*7dd7cddfSDavid du Colombier Network network[] = { 951*7dd7cddfSDavid du Colombier [Nil] { "il", 0, iplookup, iptrans, 1, 0, 0, }, 952*7dd7cddfSDavid du Colombier [Ntcp] { "tcp", 0, iplookup, iptrans, 0, 0, 0, }, 953*7dd7cddfSDavid du Colombier [Nudp] { "udp", 0, iplookup, iptrans, 0, 0, 1, }, 954*7dd7cddfSDavid du Colombier [Nicmp] { "icmp", 0, iplookup, iptrans, 0, 0, 1, }, 955*7dd7cddfSDavid du Colombier [Nrudp] { "rudp", 0, iplookup, iptrans, 0, 0, 1, }, 956*7dd7cddfSDavid du Colombier [Ntelco] { "telco", 0, telcolookup, telcotrans, 0, 0, 1, }, 957*7dd7cddfSDavid du Colombier { 0, 0, 0, 0, 0, 0, 0, }, 958*7dd7cddfSDavid du Colombier }; 959*7dd7cddfSDavid du Colombier 960*7dd7cddfSDavid du Colombier Lock ipifclock; 961*7dd7cddfSDavid du Colombier Ipifc *ipifcs; 962*7dd7cddfSDavid du Colombier 9633e12c5d1SDavid du Colombier char eaddr[Ndbvlen]; /* ascii ethernet address */ 9643e12c5d1SDavid du Colombier char ipaddr[Ndbvlen]; /* ascii internet address */ 965*7dd7cddfSDavid du Colombier uchar ipa[IPaddrlen]; /* binary internet address */ 966*7dd7cddfSDavid du Colombier char mysysname[Ndbvlen]; 9673e12c5d1SDavid du Colombier 9683e12c5d1SDavid du Colombier Network *netlist; /* networks ordered by preference */ 9693e12c5d1SDavid du Colombier Network *last; 9703e12c5d1SDavid du Colombier 971*7dd7cddfSDavid du Colombier static int 972*7dd7cddfSDavid du Colombier isvalidip(uchar *ip) 973*7dd7cddfSDavid du Colombier { 974*7dd7cddfSDavid du Colombier return ipcmp(ip, IPnoaddr) != 0 && ipcmp(ip, v4prefix) != 0; 975*7dd7cddfSDavid du Colombier } 9763e12c5d1SDavid du Colombier 977*7dd7cddfSDavid du Colombier void 978*7dd7cddfSDavid du Colombier readipinterfaces(void) 979*7dd7cddfSDavid du Colombier { 980*7dd7cddfSDavid du Colombier Ipifc *ifc; 981*7dd7cddfSDavid du Colombier 982*7dd7cddfSDavid du Colombier lock(&ipifclock); 983*7dd7cddfSDavid du Colombier ipifcs = readipifc(mntpt, ipifcs); 984*7dd7cddfSDavid du Colombier unlock(&ipifclock); 985*7dd7cddfSDavid du Colombier for(ifc = ipifcs; ifc; ifc = ifc->next){ 986*7dd7cddfSDavid du Colombier if(isvalidip(ifc->ip)){ 987*7dd7cddfSDavid du Colombier ipmove(ipa, ifc->ip); 988*7dd7cddfSDavid du Colombier sprint(ipaddr, "%I", ipa); 989*7dd7cddfSDavid du Colombier if(debug) 990*7dd7cddfSDavid du Colombier syslog(0, "dns", "ipaddr is %s\n", ipaddr); 991*7dd7cddfSDavid du Colombier break; 992*7dd7cddfSDavid du Colombier } 993*7dd7cddfSDavid du Colombier } 994*7dd7cddfSDavid du Colombier } 9953e12c5d1SDavid du Colombier 9963e12c5d1SDavid du Colombier /* 997*7dd7cddfSDavid du Colombier * get the system name 9983e12c5d1SDavid du Colombier */ 9993e12c5d1SDavid du Colombier void 10003e12c5d1SDavid du Colombier ipid(void) 10013e12c5d1SDavid du Colombier { 10023e12c5d1SDavid du Colombier uchar addr[6]; 10033e12c5d1SDavid du Colombier Ndbtuple *t; 1004219b2ee8SDavid du Colombier char *p, *attr; 10053e12c5d1SDavid du Colombier Ndbs s; 10063e12c5d1SDavid du Colombier int f; 1007*7dd7cddfSDavid du Colombier char buf[Maxpath]; 10083e12c5d1SDavid du Colombier 10093e12c5d1SDavid du Colombier 1010219b2ee8SDavid du Colombier /* use environment, ether addr, or ipaddr to get system name */ 1011*7dd7cddfSDavid du Colombier if(*mysysname == 0){ 1012*7dd7cddfSDavid du Colombier /* 1013*7dd7cddfSDavid du Colombier * environment has priority. 1014*7dd7cddfSDavid du Colombier * 1015*7dd7cddfSDavid du Colombier * on the sgi power the default system name 1016*7dd7cddfSDavid du Colombier * is the ip address. ignore that. 1017*7dd7cddfSDavid du Colombier * 1018*7dd7cddfSDavid du Colombier */ 1019219b2ee8SDavid du Colombier p = getenv("sysname"); 1020219b2ee8SDavid du Colombier if(p){ 1021219b2ee8SDavid du Colombier attr = ipattr(p); 1022219b2ee8SDavid du Colombier if(strcmp(attr, "ip") != 0) 1023*7dd7cddfSDavid du Colombier strcpy(mysysname, p); 10243e12c5d1SDavid du Colombier } 10253e12c5d1SDavid du Colombier 10263e12c5d1SDavid du Colombier /* 1027*7dd7cddfSDavid du Colombier * the /net/ndb contains what the network 1028*7dd7cddfSDavid du Colombier * figured out from DHCP. use that name if 1029*7dd7cddfSDavid du Colombier * there is one. 10303e12c5d1SDavid du Colombier */ 1031*7dd7cddfSDavid du Colombier if(*mysysname == 0 && netdb != nil){ 1032*7dd7cddfSDavid du Colombier ndbreopen(netdb); 1033*7dd7cddfSDavid du Colombier for(t = ndbparse(netdb); t != nil; t = t->entry){ 1034*7dd7cddfSDavid du Colombier if(strcmp(t->attr, "sys") == 0){ 1035*7dd7cddfSDavid du Colombier strcpy(mysysname, t->val); 10363e12c5d1SDavid du Colombier break; 10373e12c5d1SDavid du Colombier } 1038*7dd7cddfSDavid du Colombier } 1039*7dd7cddfSDavid du Colombier ndbfree(t); 1040*7dd7cddfSDavid du Colombier } 1041*7dd7cddfSDavid du Colombier 1042*7dd7cddfSDavid du Colombier /* next network database, ip address, and ether address to find a name */ 1043*7dd7cddfSDavid du Colombier if(*mysysname == 0){ 1044*7dd7cddfSDavid du Colombier t = nil; 1045*7dd7cddfSDavid du Colombier if(isvalidip(ipa)) 1046*7dd7cddfSDavid du Colombier t = ndbgetval(db, &s, "ip", ipaddr, "sys", mysysname); 1047*7dd7cddfSDavid du Colombier else { 1048*7dd7cddfSDavid du Colombier for(f = 0; f < 3; f++){ 1049*7dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/ether%d", mntpt, f); 1050*7dd7cddfSDavid du Colombier if(myetheraddr(addr, buf) >= 0){ 1051*7dd7cddfSDavid du Colombier snprint(eaddr, sizeof(eaddr), "%E", addr); 1052*7dd7cddfSDavid du Colombier t = ndbgetval(db, &s, "ether", eaddr, "sys", 1053*7dd7cddfSDavid du Colombier mysysname); 1054*7dd7cddfSDavid du Colombier if(t != nil) 1055*7dd7cddfSDavid du Colombier break; 1056*7dd7cddfSDavid du Colombier } 1057*7dd7cddfSDavid du Colombier } 1058*7dd7cddfSDavid du Colombier } 1059*7dd7cddfSDavid du Colombier ndbfree(t); 1060*7dd7cddfSDavid du Colombier } 1061*7dd7cddfSDavid du Colombier 1062*7dd7cddfSDavid du Colombier /* set /dev/mysysname if we now know it */ 1063*7dd7cddfSDavid du Colombier if(*mysysname){ 1064*7dd7cddfSDavid du Colombier f = open("/dev/sysname", OWRITE); 1065*7dd7cddfSDavid du Colombier if(f >= 0){ 1066*7dd7cddfSDavid du Colombier write(f, mysysname, strlen(mysysname)); 10673e12c5d1SDavid du Colombier close(f); 10683e12c5d1SDavid du Colombier } 10693e12c5d1SDavid du Colombier } 10703e12c5d1SDavid du Colombier } 10713e12c5d1SDavid du Colombier } 10723e12c5d1SDavid du Colombier 10733e12c5d1SDavid du Colombier /* 10743e12c5d1SDavid du Colombier * Set up a list of default networks by looking for 10753e12c5d1SDavid du Colombier * /net/ * /clone. 10763e12c5d1SDavid du Colombier */ 10773e12c5d1SDavid du Colombier void 1078*7dd7cddfSDavid du Colombier netinit(int background) 10793e12c5d1SDavid du Colombier { 1080*7dd7cddfSDavid du Colombier char clone[Maxpath]; 10813e12c5d1SDavid du Colombier Dir d; 10823e12c5d1SDavid du Colombier Network *np; 1083*7dd7cddfSDavid du Colombier static int working; 1084*7dd7cddfSDavid du Colombier 1085*7dd7cddfSDavid du Colombier if(background){ 1086*7dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 1087*7dd7cddfSDavid du Colombier case 0: 1088*7dd7cddfSDavid du Colombier break; 1089*7dd7cddfSDavid du Colombier default: 1090*7dd7cddfSDavid du Colombier return; 1091*7dd7cddfSDavid du Colombier } 1092*7dd7cddfSDavid du Colombier lock(&netlock); 1093*7dd7cddfSDavid du Colombier } 10943e12c5d1SDavid du Colombier 10953e12c5d1SDavid du Colombier /* add the mounted networks to the default list */ 10963e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 1097*7dd7cddfSDavid du Colombier if(np->considered) 1098*7dd7cddfSDavid du Colombier continue; 1099*7dd7cddfSDavid du Colombier snprint(clone, sizeof(clone), "%s/%s/clone", mntpt, np->net); 11003e12c5d1SDavid du Colombier if(dirstat(clone, &d) < 0) 11013e12c5d1SDavid du Colombier continue; 11023e12c5d1SDavid du Colombier if(netlist) 11033e12c5d1SDavid du Colombier last->next = np; 11043e12c5d1SDavid du Colombier else 11053e12c5d1SDavid du Colombier netlist = np; 11063e12c5d1SDavid du Colombier last = np; 11073e12c5d1SDavid du Colombier np->next = 0; 1108*7dd7cddfSDavid du Colombier np->considered = 1; 11093e12c5d1SDavid du Colombier } 11103e12c5d1SDavid du Colombier 1111*7dd7cddfSDavid du Colombier /* find out what our ip address is */ 1112*7dd7cddfSDavid du Colombier readipinterfaces(); 11133e12c5d1SDavid du Colombier 1114*7dd7cddfSDavid du Colombier /* set the system name if we need to, these says ip is all we have */ 11153e12c5d1SDavid du Colombier ipid(); 11163e12c5d1SDavid du Colombier 1117219b2ee8SDavid du Colombier if(debug) 1118*7dd7cddfSDavid du Colombier syslog(0, logfile, "mysysname %s eaddr %s ipaddr %s ipa %I\n", 1119*7dd7cddfSDavid du Colombier mysysname, eaddr, ipaddr, ipa); 1120*7dd7cddfSDavid du Colombier 1121*7dd7cddfSDavid du Colombier if(background){ 1122*7dd7cddfSDavid du Colombier unlock(&netlock); 1123*7dd7cddfSDavid du Colombier _exits(0); 1124*7dd7cddfSDavid du Colombier } 11253e12c5d1SDavid du Colombier } 11263e12c5d1SDavid du Colombier 11273e12c5d1SDavid du Colombier /* 11283e12c5d1SDavid du Colombier * add networks to the standard list 11293e12c5d1SDavid du Colombier */ 11303e12c5d1SDavid du Colombier void 11313e12c5d1SDavid du Colombier netadd(char *p) 11323e12c5d1SDavid du Colombier { 11333e12c5d1SDavid du Colombier Network *np; 11343e12c5d1SDavid du Colombier char *field[12]; 11353e12c5d1SDavid du Colombier int i, n; 11363e12c5d1SDavid du Colombier 1137*7dd7cddfSDavid du Colombier n = getfields(p, field, 12, 1, " "); 11383e12c5d1SDavid du Colombier for(i = 0; i < n; i++){ 11393e12c5d1SDavid du Colombier for(np = network; np->net; np++){ 11403e12c5d1SDavid du Colombier if(strcmp(field[i], np->net) != 0) 11413e12c5d1SDavid du Colombier continue; 1142*7dd7cddfSDavid du Colombier if(np->considered) 11433e12c5d1SDavid du Colombier break; 11443e12c5d1SDavid du Colombier if(netlist) 11453e12c5d1SDavid du Colombier last->next = np; 11463e12c5d1SDavid du Colombier else 11473e12c5d1SDavid du Colombier netlist = np; 11483e12c5d1SDavid du Colombier last = np; 11493e12c5d1SDavid du Colombier np->next = 0; 1150*7dd7cddfSDavid du Colombier np->considered = 1; 11513e12c5d1SDavid du Colombier } 11523e12c5d1SDavid du Colombier } 11533e12c5d1SDavid du Colombier } 11543e12c5d1SDavid du Colombier 11553e12c5d1SDavid du Colombier /* 1156219b2ee8SDavid du Colombier * make a tuple 1157219b2ee8SDavid du Colombier */ 1158219b2ee8SDavid du Colombier Ndbtuple* 1159219b2ee8SDavid du Colombier mktuple(char *attr, char *val) 1160219b2ee8SDavid du Colombier { 1161219b2ee8SDavid du Colombier Ndbtuple *t; 1162219b2ee8SDavid du Colombier 1163*7dd7cddfSDavid du Colombier t = emalloc(sizeof(Ndbtuple)); 1164219b2ee8SDavid du Colombier strcpy(t->attr, attr); 1165219b2ee8SDavid du Colombier strncpy(t->val, val, sizeof(t->val)); 1166219b2ee8SDavid du Colombier t->val[sizeof(t->val)-1] = 0; 1167219b2ee8SDavid du Colombier t->line = t; 1168219b2ee8SDavid du Colombier t->entry = 0; 1169219b2ee8SDavid du Colombier return t; 1170219b2ee8SDavid du Colombier } 1171219b2ee8SDavid du Colombier 1172219b2ee8SDavid du Colombier /* 11733e12c5d1SDavid du Colombier * lookup a request. the network "net" means we should pick the 11743e12c5d1SDavid du Colombier * best network to get there. 11753e12c5d1SDavid du Colombier */ 11763e12c5d1SDavid du Colombier int 1177*7dd7cddfSDavid du Colombier lookup(Mfile *mf, char *net, char *host, char *serv, char *rem) 11783e12c5d1SDavid du Colombier { 1179219b2ee8SDavid du Colombier Network *np, *p; 1180219b2ee8SDavid du Colombier char *cp; 1181219b2ee8SDavid du Colombier Ndbtuple *nt, *t; 1182219b2ee8SDavid du Colombier char reply[Maxreply]; 11833e12c5d1SDavid du Colombier 11843e12c5d1SDavid du Colombier /* open up the standard db files */ 11853e12c5d1SDavid du Colombier if(db == 0) 1186*7dd7cddfSDavid du Colombier ndbinit(); 11873e12c5d1SDavid du Colombier if(db == 0) 11883e12c5d1SDavid du Colombier error("can't open network database\n"); 11893e12c5d1SDavid du Colombier 1190219b2ee8SDavid du Colombier nt = 0; 11913e12c5d1SDavid du Colombier if(strcmp(net, "net") == 0){ 11923e12c5d1SDavid du Colombier /* 11933e12c5d1SDavid du Colombier * go through set of default nets 11943e12c5d1SDavid du Colombier */ 11953e12c5d1SDavid du Colombier for(np = netlist; np; np = np->next){ 1196219b2ee8SDavid du Colombier nt = (*np->lookup)(np, host, serv, 0); 1197219b2ee8SDavid du Colombier if(nt){ 1198219b2ee8SDavid du Colombier if(needproto(np, nt) == 0) 1199219b2ee8SDavid du Colombier break; 1200219b2ee8SDavid du Colombier ndbfree(nt); 1201219b2ee8SDavid du Colombier nt = 0; 1202bd389b36SDavid du Colombier } 12033e12c5d1SDavid du Colombier } 12043e12c5d1SDavid du Colombier 12053e12c5d1SDavid du Colombier /* 12063e12c5d1SDavid du Colombier * try first net that requires no table lookup 12073e12c5d1SDavid du Colombier */ 1208219b2ee8SDavid du Colombier if(nt == 0) 12093e12c5d1SDavid du Colombier for(np = netlist; np; np = np->next){ 12103e12c5d1SDavid du Colombier if(np->nolookup && *host != '$'){ 1211219b2ee8SDavid du Colombier nt = (*np->lookup)(np, host, serv, 1); 1212219b2ee8SDavid du Colombier if(nt) 12133e12c5d1SDavid du Colombier break; 12143e12c5d1SDavid du Colombier } 12153e12c5d1SDavid du Colombier } 12163e12c5d1SDavid du Colombier 1217219b2ee8SDavid du Colombier if(nt == 0) 12183e12c5d1SDavid du Colombier return -1; 1219219b2ee8SDavid du Colombier 1220219b2ee8SDavid du Colombier /* 1221219b2ee8SDavid du Colombier * create replies 1222219b2ee8SDavid du Colombier */ 1223219b2ee8SDavid du Colombier for(p = np; p; p = p->next){ 1224219b2ee8SDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 1225219b2ee8SDavid du Colombier if(needproto(p, nt) < 0) 1226219b2ee8SDavid du Colombier continue; 1227*7dd7cddfSDavid du Colombier cp = (*p->trans)(t, p, serv, rem); 1228219b2ee8SDavid du Colombier if(cp){ 1229219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 1230219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = cp; 1231219b2ee8SDavid du Colombier } 1232219b2ee8SDavid du Colombier } 1233219b2ee8SDavid du Colombier } 1234219b2ee8SDavid du Colombier for(p = netlist; mf->nreply < Nreply && p != np; p = p->next){ 1235219b2ee8SDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 1236219b2ee8SDavid du Colombier if(needproto(p, nt) < 0) 1237219b2ee8SDavid du Colombier continue; 1238*7dd7cddfSDavid du Colombier cp = (*p->trans)(t, p, serv, rem); 1239219b2ee8SDavid du Colombier if(cp){ 1240219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 1241219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = cp; 1242219b2ee8SDavid du Colombier } 1243219b2ee8SDavid du Colombier } 1244219b2ee8SDavid du Colombier } 1245219b2ee8SDavid du Colombier ndbfree(nt); 1246219b2ee8SDavid du Colombier return 0; 12473e12c5d1SDavid du Colombier } else { 12483e12c5d1SDavid du Colombier /* 12493e12c5d1SDavid du Colombier * look on a specific network 12503e12c5d1SDavid du Colombier */ 1251219b2ee8SDavid du Colombier for(p = network; p->net; p++){ 1252219b2ee8SDavid du Colombier if(strcmp(p->net, net) == 0){ 1253219b2ee8SDavid du Colombier nt = (*p->lookup)(p, host, serv, 1); 1254219b2ee8SDavid du Colombier if (nt == 0) 1255219b2ee8SDavid du Colombier return -1; 1256219b2ee8SDavid du Colombier 1257219b2ee8SDavid du Colombier /* create replies */ 1258219b2ee8SDavid du Colombier for(t = nt; mf->nreply < Nreply && t; t = t->entry){ 1259*7dd7cddfSDavid du Colombier cp = (*p->trans)(t, p, serv, rem); 1260219b2ee8SDavid du Colombier if(cp){ 1261219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(cp); 1262219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = cp; 1263219b2ee8SDavid du Colombier } 1264219b2ee8SDavid du Colombier } 1265219b2ee8SDavid du Colombier ndbfree(nt); 1266219b2ee8SDavid du Colombier return 0; 12673e12c5d1SDavid du Colombier } 12683e12c5d1SDavid du Colombier } 12693e12c5d1SDavid du Colombier } 12703e12c5d1SDavid du Colombier 12713e12c5d1SDavid du Colombier /* 1272219b2ee8SDavid du Colombier * not a known network, don't translate host or service 12733e12c5d1SDavid du Colombier */ 12743e12c5d1SDavid du Colombier if(serv) 1275*7dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s", 1276*7dd7cddfSDavid du Colombier mntpt, net, host, serv); 1277bd389b36SDavid du Colombier else 1278*7dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s", 1279*7dd7cddfSDavid du Colombier mntpt, net, host); 1280219b2ee8SDavid du Colombier mf->reply[0] = strdup(reply); 1281219b2ee8SDavid du Colombier mf->replylen[0] = strlen(reply); 1282219b2ee8SDavid du Colombier mf->nreply = 1; 12833e12c5d1SDavid du Colombier return 0; 12843e12c5d1SDavid du Colombier } 12853e12c5d1SDavid du Colombier 12863e12c5d1SDavid du Colombier /* 12873e12c5d1SDavid du Colombier * see if we can use this protocol 12883e12c5d1SDavid du Colombier */ 12893e12c5d1SDavid du Colombier int 12903e12c5d1SDavid du Colombier needproto(Network *np, Ndbtuple *t) 12913e12c5d1SDavid du Colombier { 12923e12c5d1SDavid du Colombier if(np->needproto == 0) 12933e12c5d1SDavid du Colombier return 0; 12943e12c5d1SDavid du Colombier for(; t; t = t->entry) 12953e12c5d1SDavid du Colombier if(strcmp(t->attr, "proto")==0 && strcmp(t->val, np->net)==0) 12963e12c5d1SDavid du Colombier return 0; 12973e12c5d1SDavid du Colombier return -1; 12983e12c5d1SDavid du Colombier } 12993e12c5d1SDavid du Colombier 13003e12c5d1SDavid du Colombier /* 13013e12c5d1SDavid du Colombier * translate an ip service name into a port number. If it's a numeric port 13023e12c5d1SDavid du Colombier * number, look for restricted access. 13033e12c5d1SDavid du Colombier * 13043e12c5d1SDavid du Colombier * the service '*' needs no translation. 13053e12c5d1SDavid du Colombier */ 13063e12c5d1SDavid du Colombier char* 13073e12c5d1SDavid du Colombier ipserv(Network *np, char *name, char *buf) 13083e12c5d1SDavid du Colombier { 13093e12c5d1SDavid du Colombier char *p; 13103e12c5d1SDavid du Colombier int alpha = 0; 13113e12c5d1SDavid du Colombier int restr = 0; 13123e12c5d1SDavid du Colombier char port[Ndbvlen]; 13133e12c5d1SDavid du Colombier Ndbtuple *t, *nt; 13143e12c5d1SDavid du Colombier Ndbs s; 13153e12c5d1SDavid du Colombier 13163e12c5d1SDavid du Colombier /* '*' means any service */ 13173e12c5d1SDavid du Colombier if(strcmp(name, "*")==0){ 13183e12c5d1SDavid du Colombier strcpy(buf, name); 13193e12c5d1SDavid du Colombier return buf; 13203e12c5d1SDavid du Colombier } 13213e12c5d1SDavid du Colombier 13223e12c5d1SDavid du Colombier /* see if it's numeric or symbolic */ 13233e12c5d1SDavid du Colombier port[0] = 0; 13243e12c5d1SDavid du Colombier for(p = name; *p; p++){ 13253e12c5d1SDavid du Colombier if(isdigit(*p)) 13263e12c5d1SDavid du Colombier ; 13273e12c5d1SDavid du Colombier else if(isalpha(*p) || *p == '-' || *p == '$') 13283e12c5d1SDavid du Colombier alpha = 1; 13293e12c5d1SDavid du Colombier else 13303e12c5d1SDavid du Colombier return 0; 13313e12c5d1SDavid du Colombier } 13323e12c5d1SDavid du Colombier if(alpha){ 13333e12c5d1SDavid du Colombier t = ndbgetval(db, &s, np->net, name, "port", port); 13343e12c5d1SDavid du Colombier if(t == 0) 13353e12c5d1SDavid du Colombier return 0; 13363e12c5d1SDavid du Colombier } else { 13373e12c5d1SDavid du Colombier t = ndbgetval(db, &s, "port", name, "port", port); 13383e12c5d1SDavid du Colombier if(t == 0){ 13393e12c5d1SDavid du Colombier strncpy(port, name, sizeof(port)); 13403e12c5d1SDavid du Colombier port[sizeof(port)-1] = 0; 13413e12c5d1SDavid du Colombier } 13423e12c5d1SDavid du Colombier } 13433e12c5d1SDavid du Colombier 13443e12c5d1SDavid du Colombier if(t){ 13453e12c5d1SDavid du Colombier for(nt = t; nt; nt = nt->entry) 13463e12c5d1SDavid du Colombier if(strcmp(nt->attr, "restricted") == 0) 13473e12c5d1SDavid du Colombier restr = 1; 13483e12c5d1SDavid du Colombier ndbfree(t); 13493e12c5d1SDavid du Colombier } 13503e12c5d1SDavid du Colombier sprint(buf, "%s%s", port, restr ? "!r" : ""); 13513e12c5d1SDavid du Colombier return buf; 13523e12c5d1SDavid du Colombier } 13533e12c5d1SDavid du Colombier 13543e12c5d1SDavid du Colombier /* 1355*7dd7cddfSDavid du Colombier * lookup an ip attribute 13563e12c5d1SDavid du Colombier */ 1357*7dd7cddfSDavid du Colombier int 1358*7dd7cddfSDavid du Colombier ipattrlookup(Ndb *db, char *ipa, char *attr, char *val) 13593e12c5d1SDavid du Colombier { 13603e12c5d1SDavid du Colombier 1361*7dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 1362*7dd7cddfSDavid du Colombier char *alist[2]; 13633e12c5d1SDavid du Colombier 1364*7dd7cddfSDavid du Colombier alist[0] = attr; 1365*7dd7cddfSDavid du Colombier t = ndbipinfo(db, "ip", ipa, alist, 1); 1366*7dd7cddfSDavid du Colombier if(t == nil) 1367*7dd7cddfSDavid du Colombier return 0; 1368*7dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry) 1369*7dd7cddfSDavid du Colombier if(strcmp(nt->attr, attr) == 0){ 1370*7dd7cddfSDavid du Colombier strcpy(val, nt->val); 13713e12c5d1SDavid du Colombier ndbfree(t); 1372*7dd7cddfSDavid du Colombier return 1; 1373219b2ee8SDavid du Colombier } 13743e12c5d1SDavid du Colombier 1375*7dd7cddfSDavid du Colombier /* we shouldn't get here */ 13763e12c5d1SDavid du Colombier ndbfree(t); 1377*7dd7cddfSDavid du Colombier return 0; 13783e12c5d1SDavid du Colombier } 13793e12c5d1SDavid du Colombier 13803e12c5d1SDavid du Colombier /* 13813e12c5d1SDavid du Colombier * lookup (and translate) an ip destination 13823e12c5d1SDavid du Colombier */ 1383219b2ee8SDavid du Colombier Ndbtuple* 1384219b2ee8SDavid du Colombier iplookup(Network *np, char *host, char *serv, int nolookup) 13853e12c5d1SDavid du Colombier { 13863e12c5d1SDavid du Colombier char *attr; 1387*7dd7cddfSDavid du Colombier Ndbtuple *t, *nt; 13883e12c5d1SDavid du Colombier Ndbs s; 13893e12c5d1SDavid du Colombier char ts[Ndbvlen+1]; 13903e12c5d1SDavid du Colombier char th[Ndbvlen+1]; 13913e12c5d1SDavid du Colombier char dollar[Ndbvlen+1]; 1392*7dd7cddfSDavid du Colombier uchar ip[IPaddrlen]; 1393*7dd7cddfSDavid du Colombier uchar net[IPaddrlen]; 1394*7dd7cddfSDavid du Colombier uchar tnet[IPaddrlen]; 1395*7dd7cddfSDavid du Colombier Ipifc *ifc; 13963e12c5d1SDavid du Colombier 1397219b2ee8SDavid du Colombier USED(nolookup); 1398219b2ee8SDavid du Colombier 13993e12c5d1SDavid du Colombier /* 14003e12c5d1SDavid du Colombier * start with the service since it's the most likely to fail 14013e12c5d1SDavid du Colombier * and costs the least 14023e12c5d1SDavid du Colombier */ 1403*7dd7cddfSDavid du Colombier if(serv==0 || ipserv(np, serv, ts) == 0){ 1404*7dd7cddfSDavid du Colombier werrstr("can't translate address"); 1405219b2ee8SDavid du Colombier return 0; 1406*7dd7cddfSDavid du Colombier } 14073e12c5d1SDavid du Colombier 14083e12c5d1SDavid du Colombier /* for dial strings with no host */ 1409219b2ee8SDavid du Colombier if(strcmp(host, "*") == 0) 1410219b2ee8SDavid du Colombier return mktuple("ip", "*"); 14113e12c5d1SDavid du Colombier 14123e12c5d1SDavid du Colombier /* 1413*7dd7cddfSDavid du Colombier * hack till we go v6 :: = 0.0.0.0 1414*7dd7cddfSDavid du Colombier */ 1415*7dd7cddfSDavid du Colombier if(strcmp("::", host) == 0) 1416*7dd7cddfSDavid du Colombier return mktuple("ip", "*"); 1417*7dd7cddfSDavid du Colombier 1418*7dd7cddfSDavid du Colombier /* 14193e12c5d1SDavid du Colombier * '$' means the rest of the name is an attribute that we 14203e12c5d1SDavid du Colombier * need to search for 14213e12c5d1SDavid du Colombier */ 14223e12c5d1SDavid du Colombier if(*host == '$'){ 1423*7dd7cddfSDavid du Colombier if(ipattrlookup(db, ipaddr, host+1, dollar)) 14243e12c5d1SDavid du Colombier host = dollar; 14253e12c5d1SDavid du Colombier } 14263e12c5d1SDavid du Colombier 14273e12c5d1SDavid du Colombier /* 1428*7dd7cddfSDavid du Colombier * turn '[ip address]' into just 'ip address' 1429*7dd7cddfSDavid du Colombier */ 1430*7dd7cddfSDavid du Colombier if(*host == '[' && host[strlen(host)-1] == ']'){ 1431*7dd7cddfSDavid du Colombier host++; 1432*7dd7cddfSDavid du Colombier host[strlen(host)-1] = 0; 1433*7dd7cddfSDavid du Colombier } 1434*7dd7cddfSDavid du Colombier 1435*7dd7cddfSDavid du Colombier /* 14363e12c5d1SDavid du Colombier * just accept addresses 14373e12c5d1SDavid du Colombier */ 1438219b2ee8SDavid du Colombier attr = ipattr(host); 1439219b2ee8SDavid du Colombier if(strcmp(attr, "ip") == 0) 1440219b2ee8SDavid du Colombier return mktuple("ip", host); 14413e12c5d1SDavid du Colombier 14423e12c5d1SDavid du Colombier /* 14433e12c5d1SDavid du Colombier * give the domain name server the first opportunity to 1444bd389b36SDavid du Colombier * resolve domain names. if that fails try the database. 14453e12c5d1SDavid du Colombier */ 14463e12c5d1SDavid du Colombier t = 0; 14473e12c5d1SDavid du Colombier if(strcmp(attr, "dom") == 0) 1448*7dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 14493e12c5d1SDavid du Colombier if(t == 0) 14503e12c5d1SDavid du Colombier t = ndbgetval(db, &s, attr, host, "ip", th); 14513e12c5d1SDavid du Colombier if(t == 0) 1452*7dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 1453*7dd7cddfSDavid du Colombier if(t == 0 && strcmp(attr, "dom") != 0) 1454*7dd7cddfSDavid du Colombier t = dnsiplookup(host, &s); 1455*7dd7cddfSDavid du Colombier if(t == 0) 1456219b2ee8SDavid du Colombier return 0; 1457bd389b36SDavid du Colombier 1458bd389b36SDavid du Colombier /* 1459bd389b36SDavid du Colombier * reorder the tuple to have the matched line first and 1460bd389b36SDavid du Colombier * save that in the request structure. 1461bd389b36SDavid du Colombier */ 1462*7dd7cddfSDavid du Colombier t = reorder(t, s.t); 1463*7dd7cddfSDavid du Colombier 1464*7dd7cddfSDavid du Colombier /* 1465*7dd7cddfSDavid du Colombier * reorder according to our interfaces 1466*7dd7cddfSDavid du Colombier */ 1467*7dd7cddfSDavid du Colombier lock(&ipifclock); 1468*7dd7cddfSDavid du Colombier for(ifc = ipifcs; ifc; ifc = ifc->next){ 1469*7dd7cddfSDavid du Colombier maskip(ifc->ip, ifc->mask, net); 1470*7dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry){ 1471*7dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0) 1472*7dd7cddfSDavid du Colombier continue; 1473*7dd7cddfSDavid du Colombier parseip(ip, nt->val); 1474*7dd7cddfSDavid du Colombier maskip(ip, ifc->mask, tnet); 1475*7dd7cddfSDavid du Colombier if(memcmp(net, tnet, IPaddrlen) == 0){ 1476*7dd7cddfSDavid du Colombier t = reorder(t, nt); 1477*7dd7cddfSDavid du Colombier unlock(&ipifclock); 1478*7dd7cddfSDavid du Colombier return t; 1479*7dd7cddfSDavid du Colombier } 1480*7dd7cddfSDavid du Colombier } 1481*7dd7cddfSDavid du Colombier } 1482*7dd7cddfSDavid du Colombier unlock(&ipifclock); 1483*7dd7cddfSDavid du Colombier 1484*7dd7cddfSDavid du Colombier return t; 14853e12c5d1SDavid du Colombier } 14863e12c5d1SDavid du Colombier 14873e12c5d1SDavid du Colombier /* 14883e12c5d1SDavid du Colombier * translate an ip address 14893e12c5d1SDavid du Colombier */ 1490219b2ee8SDavid du Colombier char* 1491*7dd7cddfSDavid du Colombier iptrans(Ndbtuple *t, Network *np, char *serv, char *rem) 14923e12c5d1SDavid du Colombier { 14933e12c5d1SDavid du Colombier char ts[Ndbvlen+1]; 1494219b2ee8SDavid du Colombier char reply[Maxreply]; 1495*7dd7cddfSDavid du Colombier char x[Ndbvlen+1]; 14963e12c5d1SDavid du Colombier 1497219b2ee8SDavid du Colombier if(strcmp(t->attr, "ip") != 0) 14983e12c5d1SDavid du Colombier return 0; 1499219b2ee8SDavid du Colombier 1500219b2ee8SDavid du Colombier if(serv == 0 || ipserv(np, serv, ts) == 0) 1501219b2ee8SDavid du Colombier return 0; 1502219b2ee8SDavid du Colombier 1503*7dd7cddfSDavid du Colombier if(rem != nil) 1504*7dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 1505*7dd7cddfSDavid du Colombier else 1506*7dd7cddfSDavid du Colombier *x = 0; 1507219b2ee8SDavid du Colombier if(*t->val == '*') 1508*7dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", 1509*7dd7cddfSDavid du Colombier mntpt, np->net, ts, x); 1510219b2ee8SDavid du Colombier else 1511*7dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s", 1512*7dd7cddfSDavid du Colombier mntpt, np->net, t->val, ts, x); 1513219b2ee8SDavid du Colombier 1514219b2ee8SDavid du Colombier return strdup(reply); 15153e12c5d1SDavid du Colombier } 15163e12c5d1SDavid du Colombier 15173e12c5d1SDavid du Colombier 1518219b2ee8SDavid du Colombier /* 1519219b2ee8SDavid du Colombier * lookup a telephone number 1520219b2ee8SDavid du Colombier */ 1521219b2ee8SDavid du Colombier Ndbtuple* 1522219b2ee8SDavid du Colombier telcolookup(Network *np, char *host, char *serv, int nolookup) 1523219b2ee8SDavid du Colombier { 1524219b2ee8SDavid du Colombier Ndbtuple *t; 1525219b2ee8SDavid du Colombier Ndbs s; 1526219b2ee8SDavid du Colombier char th[Ndbvlen+1]; 1527219b2ee8SDavid du Colombier 1528219b2ee8SDavid du Colombier USED(np, nolookup, serv); 1529219b2ee8SDavid du Colombier 1530219b2ee8SDavid du Colombier t = ndbgetval(db, &s, "sys", host, "telco", th); 1531219b2ee8SDavid du Colombier if(t == 0) 1532219b2ee8SDavid du Colombier return mktuple("telco", host); 1533219b2ee8SDavid du Colombier 1534219b2ee8SDavid du Colombier return reorder(t, s.t); 1535219b2ee8SDavid du Colombier } 1536219b2ee8SDavid du Colombier 1537219b2ee8SDavid du Colombier /* 1538219b2ee8SDavid du Colombier * translate a telephone address 1539219b2ee8SDavid du Colombier */ 1540219b2ee8SDavid du Colombier char* 1541*7dd7cddfSDavid du Colombier telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem) 1542219b2ee8SDavid du Colombier { 1543219b2ee8SDavid du Colombier char reply[Maxreply]; 1544*7dd7cddfSDavid du Colombier char x[Ndbvlen+1]; 1545219b2ee8SDavid du Colombier 1546219b2ee8SDavid du Colombier if(strcmp(t->attr, "telco") != 0) 1547219b2ee8SDavid du Colombier return 0; 1548219b2ee8SDavid du Colombier 1549*7dd7cddfSDavid du Colombier if(rem != nil) 1550*7dd7cddfSDavid du Colombier snprint(x, sizeof(x), "!%s", rem); 1551219b2ee8SDavid du Colombier else 1552*7dd7cddfSDavid du Colombier *x = 0; 1553*7dd7cddfSDavid du Colombier if(serv) 1554*7dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s", mntpt, np->net, 1555*7dd7cddfSDavid du Colombier t->val, serv, x); 1556*7dd7cddfSDavid du Colombier else 1557*7dd7cddfSDavid du Colombier snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net, 1558*7dd7cddfSDavid du Colombier t->val, x); 1559219b2ee8SDavid du Colombier return strdup(reply); 1560219b2ee8SDavid du Colombier } 15613e12c5d1SDavid du Colombier 15623e12c5d1SDavid du Colombier /* 15633e12c5d1SDavid du Colombier * reorder the tuple to put x's line first in the entry 15643e12c5d1SDavid du Colombier */ 15653e12c5d1SDavid du Colombier Ndbtuple* 15663e12c5d1SDavid du Colombier reorder(Ndbtuple *t, Ndbtuple *x) 15673e12c5d1SDavid du Colombier { 15683e12c5d1SDavid du Colombier Ndbtuple *nt; 15693e12c5d1SDavid du Colombier Ndbtuple *line; 15703e12c5d1SDavid du Colombier 1571219b2ee8SDavid du Colombier /* find start of this entry's line */ 1572219b2ee8SDavid du Colombier for(line = x; line->entry == line->line; line = line->line) 15733e12c5d1SDavid du Colombier ; 1574219b2ee8SDavid du Colombier line = line->line; 1575219b2ee8SDavid du Colombier if(line == t) 1576219b2ee8SDavid du Colombier return t; /* already the first line */ 15773e12c5d1SDavid du Colombier 1578219b2ee8SDavid du Colombier /* remove this line and everything after it from the entry */ 1579219b2ee8SDavid du Colombier for(nt = t; nt->entry != line; nt = nt->entry) 1580219b2ee8SDavid du Colombier ; 1581219b2ee8SDavid du Colombier nt->entry = 0; 15823e12c5d1SDavid du Colombier 1583219b2ee8SDavid du Colombier /* make that the start of the entry */ 1584219b2ee8SDavid du Colombier for(nt = line; nt->entry; nt = nt->entry) 1585219b2ee8SDavid du Colombier ; 15863e12c5d1SDavid du Colombier nt->entry = t; 15873e12c5d1SDavid du Colombier return line; 15883e12c5d1SDavid du Colombier } 15893e12c5d1SDavid du Colombier 15903e12c5d1SDavid du Colombier /* 15913e12c5d1SDavid du Colombier * create a slave process to handle a request to avoid one request blocking 1592*7dd7cddfSDavid du Colombier * another. parent returns to job loop. 15933e12c5d1SDavid du Colombier */ 15943e12c5d1SDavid du Colombier void 15953e12c5d1SDavid du Colombier slave(void) 15963e12c5d1SDavid du Colombier { 15973e12c5d1SDavid du Colombier if(*isslave) 15983e12c5d1SDavid du Colombier return; /* we're already a slave process */ 15993e12c5d1SDavid du Colombier 16003e12c5d1SDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 16013e12c5d1SDavid du Colombier case -1: 16023e12c5d1SDavid du Colombier break; 16033e12c5d1SDavid du Colombier case 0: 1604219b2ee8SDavid du Colombier if(debug) 1605219b2ee8SDavid du Colombier syslog(0, logfile, "slave %d", getpid()); 16063e12c5d1SDavid du Colombier *isslave = 1; 16073e12c5d1SDavid du Colombier break; 16083e12c5d1SDavid du Colombier default: 16093e12c5d1SDavid du Colombier longjmp(masterjmp, 1); 16103e12c5d1SDavid du Colombier } 16113e12c5d1SDavid du Colombier 1612219b2ee8SDavid du Colombier } 1613219b2ee8SDavid du Colombier 16143e12c5d1SDavid du Colombier /* 16153e12c5d1SDavid du Colombier * call the dns process and have it try to translate a name 16163e12c5d1SDavid du Colombier */ 16173e12c5d1SDavid du Colombier Ndbtuple* 1618*7dd7cddfSDavid du Colombier dnsiplookup(char *host, Ndbs *s) 16193e12c5d1SDavid du Colombier { 16203e12c5d1SDavid du Colombier char buf[Ndbvlen + 4]; 1621*7dd7cddfSDavid du Colombier Ndbtuple *t; 16223e12c5d1SDavid du Colombier 1623bd389b36SDavid du Colombier unlock(&dblock); 1624bd389b36SDavid du Colombier 16253e12c5d1SDavid du Colombier /* save the name before starting a slave */ 1626*7dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s", host); 16273e12c5d1SDavid du Colombier 16283e12c5d1SDavid du Colombier slave(); 16293e12c5d1SDavid du Colombier 1630*7dd7cddfSDavid du Colombier if(strcmp(ipattr(buf), "ip") == 0) 1631*7dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ptr"); 1632*7dd7cddfSDavid du Colombier else 1633*7dd7cddfSDavid du Colombier t = dnsquery(mntpt, buf, "ip"); 16343e12c5d1SDavid du Colombier s->t = t; 1635*7dd7cddfSDavid du Colombier 1636bd389b36SDavid du Colombier lock(&dblock); 16373e12c5d1SDavid du Colombier return t; 16383e12c5d1SDavid du Colombier } 1639219b2ee8SDavid du Colombier 1640219b2ee8SDavid du Colombier int 1641219b2ee8SDavid du Colombier qmatch(Ndbtuple *t, char **attr, char **val, int n) 1642219b2ee8SDavid du Colombier { 1643219b2ee8SDavid du Colombier int i, found; 1644219b2ee8SDavid du Colombier Ndbtuple *nt; 1645219b2ee8SDavid du Colombier 1646219b2ee8SDavid du Colombier for(i = 1; i < n; i++){ 1647219b2ee8SDavid du Colombier found = 0; 1648219b2ee8SDavid du Colombier for(nt = t; nt; nt = nt->entry) 1649219b2ee8SDavid du Colombier if(strcmp(attr[i], nt->attr) == 0) 1650219b2ee8SDavid du Colombier if(strcmp(val[i], "*") == 0 1651219b2ee8SDavid du Colombier || strcmp(val[i], nt->val) == 0){ 1652219b2ee8SDavid du Colombier found = 1; 1653219b2ee8SDavid du Colombier break; 1654219b2ee8SDavid du Colombier } 1655219b2ee8SDavid du Colombier if(found == 0) 1656219b2ee8SDavid du Colombier break; 1657219b2ee8SDavid du Colombier } 1658219b2ee8SDavid du Colombier return i == n; 1659219b2ee8SDavid du Colombier } 1660219b2ee8SDavid du Colombier 1661219b2ee8SDavid du Colombier void 1662219b2ee8SDavid du Colombier qreply(Mfile *mf, Ndbtuple *t) 1663219b2ee8SDavid du Colombier { 1664219b2ee8SDavid du Colombier int i; 1665219b2ee8SDavid du Colombier Ndbtuple *nt; 1666*7dd7cddfSDavid du Colombier char buf[2048]; 1667219b2ee8SDavid du Colombier 1668219b2ee8SDavid du Colombier buf[0] = 0; 1669219b2ee8SDavid du Colombier for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){ 1670219b2ee8SDavid du Colombier strcat(buf, nt->attr); 1671219b2ee8SDavid du Colombier strcat(buf, "="); 1672219b2ee8SDavid du Colombier strcat(buf, nt->val); 1673219b2ee8SDavid du Colombier i = strlen(buf); 1674219b2ee8SDavid du Colombier if(nt->line != nt->entry || sizeof(buf) - i < 2*Ndbvlen+2){ 1675219b2ee8SDavid du Colombier mf->replylen[mf->nreply] = strlen(buf); 1676219b2ee8SDavid du Colombier mf->reply[mf->nreply++] = strdup(buf); 1677219b2ee8SDavid du Colombier buf[0] = 0; 1678219b2ee8SDavid du Colombier } else 1679219b2ee8SDavid du Colombier strcat(buf, " "); 1680219b2ee8SDavid du Colombier } 1681219b2ee8SDavid du Colombier } 1682219b2ee8SDavid du Colombier 1683*7dd7cddfSDavid du Colombier enum 1684*7dd7cddfSDavid du Colombier { 1685*7dd7cddfSDavid du Colombier Maxattr= 32, 1686*7dd7cddfSDavid du Colombier }; 1687*7dd7cddfSDavid du Colombier 1688219b2ee8SDavid du Colombier /* 1689*7dd7cddfSDavid du Colombier * generic query lookup. The query is of one of the following 1690*7dd7cddfSDavid du Colombier * forms: 1691*7dd7cddfSDavid du Colombier * 1692*7dd7cddfSDavid du Colombier * attr1=val1 attr2=val2 attr3=val3 ... 1693*7dd7cddfSDavid du Colombier * 1694*7dd7cddfSDavid du Colombier * returns the matching tuple 1695*7dd7cddfSDavid du Colombier * 1696*7dd7cddfSDavid du Colombier * ipinfo attr=val attr1 attr2 attr3 ... 1697*7dd7cddfSDavid du Colombier * 1698*7dd7cddfSDavid du Colombier * is like ipinfo and returns the attr{1-n} 1699*7dd7cddfSDavid du Colombier * associated with the ip address. 1700219b2ee8SDavid du Colombier */ 1701219b2ee8SDavid du Colombier char* 1702219b2ee8SDavid du Colombier genquery(Mfile *mf, char *query) 1703219b2ee8SDavid du Colombier { 1704219b2ee8SDavid du Colombier int i, n; 1705219b2ee8SDavid du Colombier char *p; 1706*7dd7cddfSDavid du Colombier char *attr[Maxattr]; 1707*7dd7cddfSDavid du Colombier char *val[Maxattr]; 1708219b2ee8SDavid du Colombier Ndbtuple *t; 1709219b2ee8SDavid du Colombier Ndbs s; 1710219b2ee8SDavid du Colombier 1711*7dd7cddfSDavid du Colombier n = getfields(query, attr, 32, 1, " "); 1712219b2ee8SDavid du Colombier if(n == 0) 1713219b2ee8SDavid du Colombier return "bad query"; 1714219b2ee8SDavid du Colombier 1715*7dd7cddfSDavid du Colombier if(strcmp(attr[0], "ipinfo") == 0) 1716*7dd7cddfSDavid du Colombier return ipinfoquery(mf, attr, n); 1717*7dd7cddfSDavid du Colombier 1718219b2ee8SDavid du Colombier /* parse pairs */ 1719219b2ee8SDavid du Colombier for(i = 0; i < n; i++){ 1720219b2ee8SDavid du Colombier p = strchr(attr[i], '='); 1721219b2ee8SDavid du Colombier if(p == 0) 1722219b2ee8SDavid du Colombier return "bad query"; 1723219b2ee8SDavid du Colombier *p++ = 0; 1724219b2ee8SDavid du Colombier val[i] = p; 1725219b2ee8SDavid du Colombier } 1726219b2ee8SDavid du Colombier 1727219b2ee8SDavid du Colombier /* give dns a chance */ 1728219b2ee8SDavid du Colombier if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){ 1729*7dd7cddfSDavid du Colombier t = dnsiplookup(val[0], &s); 1730219b2ee8SDavid du Colombier if(t){ 1731219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1732219b2ee8SDavid du Colombier qreply(mf, t); 1733219b2ee8SDavid du Colombier ndbfree(t); 1734219b2ee8SDavid du Colombier return 0; 1735219b2ee8SDavid du Colombier } 1736219b2ee8SDavid du Colombier ndbfree(t); 1737219b2ee8SDavid du Colombier } 1738219b2ee8SDavid du Colombier } 1739219b2ee8SDavid du Colombier 1740219b2ee8SDavid du Colombier /* first pair is always the key. It can't be a '*' */ 1741219b2ee8SDavid du Colombier t = ndbsearch(db, &s, attr[0], val[0]); 1742219b2ee8SDavid du Colombier 1743219b2ee8SDavid du Colombier /* search is the and of all the pairs */ 1744219b2ee8SDavid du Colombier while(t){ 1745219b2ee8SDavid du Colombier if(qmatch(t, attr, val, n)){ 1746219b2ee8SDavid du Colombier qreply(mf, t); 1747219b2ee8SDavid du Colombier ndbfree(t); 1748219b2ee8SDavid du Colombier return 0; 1749219b2ee8SDavid du Colombier } 1750219b2ee8SDavid du Colombier 1751219b2ee8SDavid du Colombier ndbfree(t); 1752219b2ee8SDavid du Colombier t = ndbsnext(&s, attr[0], val[0]); 1753219b2ee8SDavid du Colombier } 1754219b2ee8SDavid du Colombier 1755219b2ee8SDavid du Colombier return "no match"; 1756219b2ee8SDavid du Colombier } 1757*7dd7cddfSDavid du Colombier 1758*7dd7cddfSDavid du Colombier /* 1759*7dd7cddfSDavid du Colombier * resolve an ip address 1760*7dd7cddfSDavid du Colombier */ 1761*7dd7cddfSDavid du Colombier static Ndbtuple* 1762*7dd7cddfSDavid du Colombier ipresolve(char *attr, char *host) 1763*7dd7cddfSDavid du Colombier { 1764*7dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 1765*7dd7cddfSDavid du Colombier 1766*7dd7cddfSDavid du Colombier t = iplookup(&network[Ntcp], host, "*", 0); 1767*7dd7cddfSDavid du Colombier for(l = &t; *l != nil; ){ 1768*7dd7cddfSDavid du Colombier nt = *l; 1769*7dd7cddfSDavid du Colombier if(strcmp(nt->attr, "ip") != 0){ 1770*7dd7cddfSDavid du Colombier *l = nt->entry; 1771*7dd7cddfSDavid du Colombier nt->entry = nil; 1772*7dd7cddfSDavid du Colombier ndbfree(nt); 1773*7dd7cddfSDavid du Colombier continue; 1774*7dd7cddfSDavid du Colombier } 1775*7dd7cddfSDavid du Colombier strcpy(nt->attr, attr); 1776*7dd7cddfSDavid du Colombier l = &nt->entry; 1777*7dd7cddfSDavid du Colombier } 1778*7dd7cddfSDavid du Colombier return t; 1779*7dd7cddfSDavid du Colombier } 1780*7dd7cddfSDavid du Colombier 1781*7dd7cddfSDavid du Colombier char* 1782*7dd7cddfSDavid du Colombier ipinfoquery(Mfile *mf, char **list, int n) 1783*7dd7cddfSDavid du Colombier { 1784*7dd7cddfSDavid du Colombier int i, nresolve; 1785*7dd7cddfSDavid du Colombier int resolve[Maxattr]; 1786*7dd7cddfSDavid du Colombier Ndbtuple *t, *nt, **l; 1787*7dd7cddfSDavid du Colombier char *attr, *val; 1788*7dd7cddfSDavid du Colombier 1789*7dd7cddfSDavid du Colombier /* skip 'ipinfo' */ 1790*7dd7cddfSDavid du Colombier list++; n--; 1791*7dd7cddfSDavid du Colombier 1792*7dd7cddfSDavid du Colombier if(n < 2) 1793*7dd7cddfSDavid du Colombier return "bad query"; 1794*7dd7cddfSDavid du Colombier 1795*7dd7cddfSDavid du Colombier /* get search attribute=value */ 1796*7dd7cddfSDavid du Colombier attr = *list++; n--; 1797*7dd7cddfSDavid du Colombier val = strchr(attr, '='); 1798*7dd7cddfSDavid du Colombier if(val == nil) 1799*7dd7cddfSDavid du Colombier return "bad query"; 1800*7dd7cddfSDavid du Colombier *val++ = 0; 1801*7dd7cddfSDavid du Colombier 1802*7dd7cddfSDavid du Colombier /* 1803*7dd7cddfSDavid du Colombier * don't let ndbipinfo resolve the addresses, we're 1804*7dd7cddfSDavid du Colombier * better at it. 1805*7dd7cddfSDavid du Colombier */ 1806*7dd7cddfSDavid du Colombier nresolve = 0; 1807*7dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 1808*7dd7cddfSDavid du Colombier if(*list[i] == '@'){ 1809*7dd7cddfSDavid du Colombier list[i]++; 1810*7dd7cddfSDavid du Colombier resolve[i] = 1; 1811*7dd7cddfSDavid du Colombier nresolve++; 1812*7dd7cddfSDavid du Colombier } else 1813*7dd7cddfSDavid du Colombier resolve[i] = 0; 1814*7dd7cddfSDavid du Colombier 1815*7dd7cddfSDavid du Colombier t = ndbipinfo(db, attr, val, list, n); 1816*7dd7cddfSDavid du Colombier if(t == nil) 1817*7dd7cddfSDavid du Colombier return "no match"; 1818*7dd7cddfSDavid du Colombier 1819*7dd7cddfSDavid du Colombier if(nresolve != 0){ 1820*7dd7cddfSDavid du Colombier for(l = &t; *l != nil;){ 1821*7dd7cddfSDavid du Colombier nt = *l; 1822*7dd7cddfSDavid du Colombier 1823*7dd7cddfSDavid du Colombier /* already an address? */ 1824*7dd7cddfSDavid du Colombier if(strcmp(ipattr(nt->val), "ip") == 0){ 1825*7dd7cddfSDavid du Colombier l = &(*l)->entry; 1826*7dd7cddfSDavid du Colombier continue; 1827*7dd7cddfSDavid du Colombier } 1828*7dd7cddfSDavid du Colombier 1829*7dd7cddfSDavid du Colombier /* user wants it resolved? */ 1830*7dd7cddfSDavid du Colombier for(i = 0; i < n; i++) 1831*7dd7cddfSDavid du Colombier if(strcmp(list[i], nt->attr) == 0) 1832*7dd7cddfSDavid du Colombier break; 1833*7dd7cddfSDavid du Colombier if(i >= n || resolve[i] == 0){ 1834*7dd7cddfSDavid du Colombier l = &(*l)->entry; 1835*7dd7cddfSDavid du Colombier continue; 1836*7dd7cddfSDavid du Colombier } 1837*7dd7cddfSDavid du Colombier 1838*7dd7cddfSDavid du Colombier /* resolve address and replace entry */ 1839*7dd7cddfSDavid du Colombier *l = ipresolve(nt->attr, nt->val); 1840*7dd7cddfSDavid du Colombier while(*l != nil) 1841*7dd7cddfSDavid du Colombier l = &(*l)->entry; 1842*7dd7cddfSDavid du Colombier *l = nt->entry; 1843*7dd7cddfSDavid du Colombier 1844*7dd7cddfSDavid du Colombier nt->entry = nil; 1845*7dd7cddfSDavid du Colombier ndbfree(nt); 1846*7dd7cddfSDavid du Colombier } 1847*7dd7cddfSDavid du Colombier } 1848*7dd7cddfSDavid du Colombier 1849*7dd7cddfSDavid du Colombier /* make it all one line */ 1850*7dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){ 1851*7dd7cddfSDavid du Colombier if(nt->entry == nil) 1852*7dd7cddfSDavid du Colombier nt->line = t; 1853*7dd7cddfSDavid du Colombier else 1854*7dd7cddfSDavid du Colombier nt->line = nt->entry; 1855*7dd7cddfSDavid du Colombier } 1856*7dd7cddfSDavid du Colombier 1857*7dd7cddfSDavid du Colombier qreply(mf, t); 1858*7dd7cddfSDavid du Colombier 1859*7dd7cddfSDavid du Colombier return nil; 1860*7dd7cddfSDavid du Colombier } 1861*7dd7cddfSDavid du Colombier 1862*7dd7cddfSDavid du Colombier void* 1863*7dd7cddfSDavid du Colombier emalloc(int size) 1864*7dd7cddfSDavid du Colombier { 1865*7dd7cddfSDavid du Colombier void *x; 1866*7dd7cddfSDavid du Colombier 1867*7dd7cddfSDavid du Colombier x = malloc(size); 1868*7dd7cddfSDavid du Colombier if(x == nil) 1869*7dd7cddfSDavid du Colombier abort(); 1870*7dd7cddfSDavid du Colombier memset(x, 0, size); 1871*7dd7cddfSDavid du Colombier return x; 1872*7dd7cddfSDavid du Colombier } 1873