cs.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <fcall.h>
  5. #include <bio.h>
  6. #include <ctype.h>
  7. #include <ndb.h>
  8. #include <ip.h>
  9. enum
  10. {
  11. Nreply= 20,
  12. Maxreply= 256,
  13. Maxrequest= 128,
  14. Maxpath= 128,
  15. Maxfdata= 8192,
  16. Qdir= 0,
  17. Qcs= 1,
  18. };
  19. typedef struct Mfile Mfile;
  20. typedef struct Mlist Mlist;
  21. typedef struct Network Network;
  22. typedef struct Flushreq Flushreq;
  23. typedef struct Job Job;
  24. int vers; /* incremented each clone/attach */
  25. struct Mfile
  26. {
  27. int busy;
  28. char *user;
  29. Qid qid;
  30. int fid;
  31. /*
  32. * current request
  33. */
  34. char *net;
  35. char *host;
  36. char *serv;
  37. char *rem;
  38. /*
  39. * result of the last lookup
  40. */
  41. Network *nextnet;
  42. int nreply;
  43. char *reply[Nreply];
  44. int replylen[Nreply];
  45. };
  46. struct Mlist
  47. {
  48. Mlist *next;
  49. Mfile mf;
  50. };
  51. //
  52. // active requests
  53. //
  54. struct Job
  55. {
  56. Job *next;
  57. int flushed;
  58. Fcall request;
  59. Fcall reply;
  60. };
  61. Lock joblock;
  62. Job *joblist;
  63. Mlist *mlist;
  64. int mfd[2];
  65. int debug;
  66. int paranoia;
  67. jmp_buf masterjmp; /* return through here after a slave process has been created */
  68. int *isslave; /* *isslave non-zero means this is a slave process */
  69. char *dbfile;
  70. Ndb *db, *netdb;
  71. void rversion(Job*);
  72. void rflush(Job*);
  73. void rattach(Job*, Mfile*);
  74. char* rwalk(Job*, Mfile*);
  75. void ropen(Job*, Mfile*);
  76. void rcreate(Job*, Mfile*);
  77. void rread(Job*, Mfile*);
  78. void rwrite(Job*, Mfile*);
  79. void rclunk(Job*, Mfile*);
  80. void rremove(Job*, Mfile*);
  81. void rstat(Job*, Mfile*);
  82. void rwstat(Job*, Mfile*);
  83. void rauth(Job*);
  84. void sendmsg(Job*, char*);
  85. void error(char*);
  86. void mountinit(char*, char*);
  87. void io(void);
  88. void ndbinit(void);
  89. void netinit(int);
  90. void netadd(char*);
  91. char *genquery(Mfile*, char*);
  92. char* ipinfoquery(Mfile*, char**, int);
  93. int needproto(Network*, Ndbtuple*);
  94. int lookup(Mfile*);
  95. Ndbtuple* reorder(Ndbtuple*, Ndbtuple*);
  96. void ipid(void);
  97. void readipinterfaces(void);
  98. void* emalloc(int);
  99. char* estrdup(char*);
  100. Job* newjob(void);
  101. void freejob(Job*);
  102. void setext(char*, int, char*);
  103. void cleanmf(Mfile*);
  104. extern void paralloc(void);
  105. Lock dblock; /* mutex on database operations */
  106. Lock netlock; /* mutex for netinit() */
  107. char *logfile = "cs";
  108. char *paranoiafile = "cs.paranoia";
  109. char mntpt[Maxpath];
  110. char netndb[Maxpath];
  111. /*
  112. * Network specific translators
  113. */
  114. Ndbtuple* iplookup(Network*, char*, char*, int);
  115. char* iptrans(Ndbtuple*, Network*, char*, char*, int);
  116. Ndbtuple* telcolookup(Network*, char*, char*, int);
  117. char* telcotrans(Ndbtuple*, Network*, char*, char*, int);
  118. Ndbtuple* dnsiplookup(char*, Ndbs*);
  119. struct Network
  120. {
  121. char *net;
  122. Ndbtuple *(*lookup)(Network*, char*, char*, int);
  123. char *(*trans)(Ndbtuple*, Network*, char*, char*, int);
  124. int considered;
  125. int fasttimeouthack;
  126. Network *next;
  127. };
  128. enum
  129. {
  130. Nilfast,
  131. Ntcp,
  132. Nil,
  133. Nudp,
  134. Nicmp,
  135. Nrudp,
  136. Ntelco,
  137. };
  138. /*
  139. * net doesn't apply to udp, icmp, or telco (for speed)
  140. */
  141. Network network[] = {
  142. [Nilfast] { "il", iplookup, iptrans, 0, 1 },
  143. [Ntcp] { "tcp", iplookup, iptrans, 0, 0 },
  144. [Nil] { "il", iplookup, iptrans, 0, 0 },
  145. [Nudp] { "udp", iplookup, iptrans, 1, 0 },
  146. [Nicmp] { "icmp", iplookup, iptrans, 1, 0 },
  147. [Nrudp] { "rudp", iplookup, iptrans, 1, 0 },
  148. [Ntelco] { "telco", telcolookup, telcotrans, 1, 0 },
  149. { 0 },
  150. };
  151. Lock ipifclock;
  152. Ipifc *ipifcs;
  153. char eaddr[Ndbvlen]; /* ascii ethernet address */
  154. char ipaddr[Ndbvlen]; /* ascii internet address */
  155. uchar ipa[IPaddrlen]; /* binary internet address */
  156. char mysysname[Ndbvlen];
  157. Network *netlist; /* networks ordered by preference */
  158. Network *last;
  159. void
  160. usage(void)
  161. {
  162. fprint(2, "usage: %s [-d] [-f ndb-file] [-x netmtpt] [-n]\n", argv0);
  163. exits("usage");
  164. }
  165. void
  166. main(int argc, char *argv[])
  167. {
  168. char servefile[Maxpath];
  169. int justsetname;
  170. char *p;
  171. char ext[Maxpath];
  172. justsetname = 0;
  173. setnetmtpt(mntpt, sizeof(mntpt), nil);
  174. ext[0] = 0;
  175. ARGBEGIN{
  176. case 'd':
  177. debug = 1;
  178. break;
  179. case 'f':
  180. p = ARGF();
  181. if(p == nil)
  182. usage();
  183. dbfile = p;
  184. break;
  185. case 'x':
  186. p = ARGF();
  187. if(p == nil)
  188. usage();
  189. setnetmtpt(mntpt, sizeof(mntpt), p);
  190. setext(ext, sizeof(ext), mntpt);
  191. break;
  192. case 'n':
  193. justsetname = 1;
  194. break;
  195. }ARGEND
  196. USED(argc);
  197. USED(argv);
  198. rfork(RFREND|RFNOTEG);
  199. snprint(servefile, sizeof(servefile), "#s/cs%s", ext);
  200. snprint(netndb, sizeof(netndb), "%s/ndb", mntpt);
  201. unmount(servefile, mntpt);
  202. remove(servefile);
  203. fmtinstall('E', eipfmt);
  204. fmtinstall('I', eipfmt);
  205. fmtinstall('M', eipfmt);
  206. fmtinstall('F', fcallfmt);
  207. ndbinit();
  208. netinit(0);
  209. if(!justsetname){
  210. mountinit(servefile, mntpt);
  211. io();
  212. }
  213. exits(0);
  214. }
  215. /*
  216. * if a mount point is specified, set the cs extention to be the mount point
  217. * with '_'s replacing '/'s
  218. */
  219. void
  220. setext(char *ext, int n, char *p)
  221. {
  222. int i, c;
  223. n--;
  224. for(i = 0; i < n; i++){
  225. c = p[i];
  226. if(c == 0)
  227. break;
  228. if(c == '/')
  229. c = '_';
  230. ext[i] = c;
  231. }
  232. ext[i] = 0;
  233. }
  234. void
  235. mountinit(char *service, char *mntpt)
  236. {
  237. int f;
  238. int p[2];
  239. char buf[32];
  240. if(pipe(p) < 0)
  241. error("pipe failed");
  242. switch(rfork(RFFDG|RFPROC|RFNAMEG)){
  243. case 0:
  244. close(p[1]);
  245. break;
  246. case -1:
  247. error("fork failed\n");
  248. default:
  249. /*
  250. * make a /srv/cs
  251. */
  252. f = create(service, 1, 0666);
  253. if(f < 0)
  254. error(service);
  255. snprint(buf, sizeof(buf), "%d", p[1]);
  256. if(write(f, buf, strlen(buf)) != strlen(buf))
  257. error("write /srv/cs");
  258. close(f);
  259. /*
  260. * put ourselves into the file system
  261. */
  262. close(p[0]);
  263. if(mount(p[1], -1, mntpt, MAFTER, "") < 0)
  264. error("mount failed\n");
  265. _exits(0);
  266. }
  267. mfd[0] = mfd[1] = p[0];
  268. }
  269. void
  270. ndbinit(void)
  271. {
  272. db = ndbopen(dbfile);
  273. if(db == nil)
  274. error("can't open network database");
  275. netdb = ndbopen(netndb);
  276. if(netdb != nil){
  277. netdb->nohash = 1;
  278. db = ndbcat(netdb, db);
  279. }
  280. }
  281. Mfile*
  282. newfid(int fid)
  283. {
  284. Mlist *f, *ff;
  285. Mfile *mf;
  286. ff = 0;
  287. for(f = mlist; f; f = f->next)
  288. if(f->mf.busy && f->mf.fid == fid)
  289. return &f->mf;
  290. else if(!ff && !f->mf.busy)
  291. ff = f;
  292. if(ff == 0){
  293. ff = emalloc(sizeof *f);
  294. ff->next = mlist;
  295. mlist = ff;
  296. }
  297. mf = &ff->mf;
  298. memset(mf, 0, sizeof *mf);
  299. mf->fid = fid;
  300. return mf;
  301. }
  302. Job*
  303. newjob(void)
  304. {
  305. Job *job;
  306. job = mallocz(sizeof(Job), 1);
  307. lock(&joblock);
  308. job->next = joblist;
  309. joblist = job;
  310. job->request.tag = -1;
  311. unlock(&joblock);
  312. return job;
  313. }
  314. void
  315. freejob(Job *job)
  316. {
  317. Job **l;
  318. lock(&joblock);
  319. for(l = &joblist; *l; l = &(*l)->next){
  320. if((*l) == job){
  321. *l = job->next;
  322. free(job);
  323. break;
  324. }
  325. }
  326. unlock(&joblock);
  327. }
  328. void
  329. flushjob(int tag)
  330. {
  331. Job *job;
  332. lock(&joblock);
  333. for(job = joblist; job; job = job->next){
  334. if(job->request.tag == tag && job->request.type != Tflush){
  335. job->flushed = 1;
  336. break;
  337. }
  338. }
  339. unlock(&joblock);
  340. }
  341. void
  342. io(void)
  343. {
  344. long n;
  345. Mfile *mf;
  346. int slaveflag;
  347. uchar mdata[IOHDRSZ + Maxfdata];
  348. Job *job;
  349. /*
  350. * if we ask dns to fulfill requests,
  351. * a slave process is created to wait for replies. The
  352. * master process returns immediately via a longjmp
  353. * through 'masterjmp'.
  354. *
  355. * *isslave is a pointer into the call stack to a variable
  356. * that tells whether or not the current process is a slave.
  357. */
  358. slaveflag = 0; /* init slave variable */
  359. isslave = &slaveflag;
  360. setjmp(masterjmp);
  361. for(;;){
  362. n = read9pmsg(mfd[0], mdata, sizeof mdata);
  363. if(n<=0)
  364. error("mount read");
  365. job = newjob();
  366. if(convM2S(mdata, n, &job->request) != n){
  367. syslog(1, logfile, "format error %ux %ux %ux %ux %ux", mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]);
  368. freejob(job);
  369. continue;
  370. }
  371. if(job->request.fid<0)
  372. error("fid out of range");
  373. lock(&dblock);
  374. mf = newfid(job->request.fid);
  375. if(debug)
  376. syslog(0, logfile, "%F", &job->request);
  377. switch(job->request.type){
  378. default:
  379. syslog(1, logfile, "unknown request type %d", job->request.type);
  380. break;
  381. case Tversion:
  382. rversion(job);
  383. break;
  384. case Tauth:
  385. rauth(job);
  386. break;
  387. case Tflush:
  388. rflush(job);
  389. break;
  390. case Tattach:
  391. rattach(job, mf);
  392. break;
  393. case Twalk:
  394. rwalk(job, mf);
  395. break;
  396. case Topen:
  397. ropen(job, mf);
  398. break;
  399. case Tcreate:
  400. rcreate(job, mf);
  401. break;
  402. case Tread:
  403. rread(job, mf);
  404. break;
  405. case Twrite:
  406. rwrite(job, mf);
  407. break;
  408. case Tclunk:
  409. rclunk(job, mf);
  410. break;
  411. case Tremove:
  412. rremove(job, mf);
  413. break;
  414. case Tstat:
  415. rstat(job, mf);
  416. break;
  417. case Twstat:
  418. rwstat(job, mf);
  419. break;
  420. }
  421. unlock(&dblock);
  422. freejob(job);
  423. /*
  424. * slave processes die after replying
  425. */
  426. if(*isslave){
  427. if(debug)
  428. syslog(0, logfile, "slave death %d", getpid());
  429. _exits(0);
  430. }
  431. }
  432. }
  433. void
  434. rversion(Job *job)
  435. {
  436. if(job->request.msize > IOHDRSZ + Maxfdata)
  437. job->reply.msize = IOHDRSZ + Maxfdata;
  438. else
  439. job->reply.msize = job->request.msize;
  440. if(strncmp(job->request.version, "9P2000", 6) != 0)
  441. sendmsg(job, "unknown 9P version");
  442. else{
  443. job->reply.version = "9P2000";
  444. sendmsg(job, 0);
  445. }
  446. }
  447. void
  448. rauth(Job *job)
  449. {
  450. sendmsg(job, "cs: authentication not required");
  451. }
  452. /*
  453. * don't flush till all the slaves are done
  454. */
  455. void
  456. rflush(Job *job)
  457. {
  458. flushjob(job->request.oldtag);
  459. sendmsg(job, 0);
  460. }
  461. void
  462. rattach(Job *job, Mfile *mf)
  463. {
  464. if(mf->busy == 0){
  465. mf->busy = 1;
  466. mf->user = estrdup(job->request.uname);
  467. }
  468. mf->qid.vers = vers++;
  469. mf->qid.type = QTDIR;
  470. mf->qid.path = 0LL;
  471. job->reply.qid = mf->qid;
  472. sendmsg(job, 0);
  473. }
  474. char*
  475. rwalk(Job *job, Mfile *mf)
  476. {
  477. char *err;
  478. char **elems;
  479. int nelems;
  480. int i;
  481. Mfile *nmf;
  482. Qid qid;
  483. err = 0;
  484. nmf = nil;
  485. elems = job->request.wname;
  486. nelems = job->request.nwname;
  487. job->reply.nwqid = 0;
  488. if(job->request.newfid != job->request.fid){
  489. /* clone fid */
  490. if(job->request.newfid<0){
  491. err = "clone newfid out of range";
  492. goto send;
  493. }
  494. nmf = newfid(job->request.newfid);
  495. if(nmf->busy){
  496. nmf = nil;
  497. err = "clone to used channel";
  498. goto send;
  499. }
  500. *nmf = *mf;
  501. nmf->user = estrdup(mf->user);
  502. nmf->fid = job->request.newfid;
  503. nmf->qid.vers = vers++;
  504. mf = nmf;
  505. }
  506. /* else nmf will be nil */
  507. qid = mf->qid;
  508. if(nelems > 0){
  509. /* walk fid */
  510. for(i=0; i<nelems && i<MAXWELEM; i++){
  511. if((qid.type & QTDIR) == 0){
  512. err = "not a directory";
  513. break;
  514. }
  515. if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){
  516. qid.type = QTDIR;
  517. qid.path = Qdir;
  518. Found:
  519. job->reply.wqid[i] = qid;
  520. job->reply.nwqid++;
  521. continue;
  522. }
  523. if(strcmp(elems[i], "cs") == 0){
  524. qid.type = QTFILE;
  525. qid.path = Qcs;
  526. goto Found;
  527. }
  528. err = "file does not exist";
  529. break;
  530. }
  531. }
  532. send:
  533. if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)){
  534. nmf->busy = 0;
  535. nmf->fid = 0;
  536. }
  537. if(err == nil)
  538. mf->qid = qid;
  539. sendmsg(job, err);
  540. return err;
  541. }
  542. void
  543. ropen(Job *job, Mfile *mf)
  544. {
  545. int mode;
  546. char *err;
  547. err = 0;
  548. mode = job->request.mode;
  549. if(mf->qid.type & QTDIR){
  550. if(mode)
  551. err = "permission denied";
  552. }
  553. job->reply.qid = mf->qid;
  554. job->reply.iounit = 0;
  555. sendmsg(job, err);
  556. }
  557. void
  558. rcreate(Job *job, Mfile *mf)
  559. {
  560. USED(mf);
  561. sendmsg(job, "creation permission denied");
  562. }
  563. void
  564. rread(Job *job, Mfile *mf)
  565. {
  566. int i, n, cnt;
  567. long off, toff, clock;
  568. Dir dir;
  569. uchar buf[Maxfdata];
  570. char *err;
  571. n = 0;
  572. err = 0;
  573. off = job->request.offset;
  574. cnt = job->request.count;
  575. if(mf->qid.type & QTDIR){
  576. clock = time(0);
  577. if(off == 0){
  578. dir.name = "cs";
  579. dir.qid.type = QTFILE;
  580. dir.qid.vers = vers;
  581. dir.qid.path = Qcs;
  582. dir.mode = 0666;
  583. dir.length = 0;
  584. dir.uid = mf->user;
  585. dir.gid = mf->user;
  586. dir.muid = mf->user;
  587. dir.atime = clock; /* wrong */
  588. dir.mtime = clock; /* wrong */
  589. n = convD2M(&dir, buf, sizeof buf);
  590. }
  591. job->reply.data = (char*)buf;
  592. } else {
  593. for(;;){
  594. /* look for an answer at the right offset */
  595. toff = 0;
  596. for(i = 0; mf->reply[i] && i < mf->nreply; i++){
  597. n = mf->replylen[i];
  598. if(off < toff + n)
  599. break;
  600. toff += n;
  601. }
  602. if(i < mf->nreply)
  603. break; /* got something to return */
  604. /* try looking up more answers */
  605. if(lookup(mf) == 0){
  606. /* no more */
  607. n = 0;
  608. goto send;
  609. }
  610. }
  611. /* give back a single reply (or part of one) */
  612. job->reply.data = mf->reply[i] + (off - toff);
  613. if(cnt > toff - off + n)
  614. n = toff - off + n;
  615. else
  616. n = cnt;
  617. }
  618. send:
  619. job->reply.count = n;
  620. sendmsg(job, err);
  621. }
  622. void
  623. cleanmf(Mfile *mf)
  624. {
  625. int i;
  626. if(mf->net != nil){
  627. free(mf->net);
  628. mf->net = nil;
  629. }
  630. if(mf->host != nil){
  631. free(mf->host);
  632. mf->host = nil;
  633. }
  634. if(mf->serv != nil){
  635. free(mf->serv);
  636. mf->serv = nil;
  637. }
  638. if(mf->rem != nil){
  639. free(mf->rem);
  640. mf->rem = nil;
  641. }
  642. if(mf->user != nil){
  643. free(mf->user);
  644. mf->user = nil;
  645. }
  646. for(i = 0; i < mf->nreply; i++){
  647. free(mf->reply[i]);
  648. mf->reply[i] = nil;
  649. mf->replylen[i] = 0;
  650. }
  651. mf->nreply = 0;
  652. mf->nextnet = netlist;
  653. }
  654. void
  655. rwrite(Job *job, Mfile *mf)
  656. {
  657. int cnt, n;
  658. char *err;
  659. char *field[4];
  660. err = 0;
  661. cnt = job->request.count;
  662. if(mf->qid.type & QTDIR){
  663. err = "can't write directory";
  664. goto send;
  665. }
  666. if(cnt >= Maxrequest){
  667. err = "request too long";
  668. goto send;
  669. }
  670. job->request.data[cnt] = 0;
  671. /*
  672. * toggle debugging
  673. */
  674. if(strncmp(job->request.data, "debug", 5)==0){
  675. debug ^= 1;
  676. syslog(1, logfile, "debug %d", debug);
  677. goto send;
  678. }
  679. /*
  680. * toggle debugging
  681. */
  682. if(strncmp(job->request.data, "paranoia", 8)==0){
  683. paranoia ^= 1;
  684. syslog(1, logfile, "paranoia %d", paranoia);
  685. goto send;
  686. }
  687. /*
  688. * add networks to the default list
  689. */
  690. if(strncmp(job->request.data, "add ", 4)==0){
  691. if(job->request.data[cnt-1] == '\n')
  692. job->request.data[cnt-1] = 0;
  693. netadd(job->request.data+4);
  694. readipinterfaces();
  695. goto send;
  696. }
  697. /*
  698. * refresh all state
  699. */
  700. if(strncmp(job->request.data, "refresh", 7)==0){
  701. netinit(1);
  702. goto send;
  703. }
  704. /* start transaction with a clean slate */
  705. cleanmf(mf);
  706. /*
  707. * look for a general query
  708. */
  709. if(*job->request.data == '!'){
  710. err = genquery(mf, job->request.data+1);
  711. goto send;
  712. }
  713. if(debug)
  714. syslog(0, logfile, "write %s", job->request.data);
  715. if(paranoia)
  716. syslog(0, paranoiafile, "write %s by %s", job->request.data, mf->user);
  717. /*
  718. * break up name
  719. */
  720. n = getfields(job->request.data, field, 4, 1, "!");
  721. switch(n){
  722. case 1:
  723. mf->net = strdup("net");
  724. mf->host = strdup(field[0]);
  725. break;
  726. case 4:
  727. mf->rem = strdup(field[3]);
  728. /* fall through */
  729. case 3:
  730. mf->serv = strdup(field[2]);
  731. /* fall through */
  732. case 2:
  733. mf->host = strdup(field[1]);
  734. mf->net = strdup(field[0]);
  735. break;
  736. }
  737. /*
  738. * do the first net worth of lookup
  739. */
  740. if(lookup(mf) == 0)
  741. err = "can't translate address";
  742. send:
  743. job->reply.count = cnt;
  744. sendmsg(job, err);
  745. }
  746. void
  747. rclunk(Job *job, Mfile *mf)
  748. {
  749. cleanmf(mf);
  750. mf->busy = 0;
  751. mf->fid = 0;
  752. sendmsg(job, 0);
  753. }
  754. void
  755. rremove(Job *job, Mfile *mf)
  756. {
  757. USED(mf);
  758. sendmsg(job, "remove permission denied");
  759. }
  760. void
  761. rstat(Job *job, Mfile *mf)
  762. {
  763. Dir dir;
  764. uchar buf[IOHDRSZ+Maxfdata];
  765. if(mf->qid.type & QTDIR){
  766. dir.name = ".";
  767. dir.mode = DMDIR|0555;
  768. } else {
  769. dir.name = "cs";
  770. dir.mode = 0666;
  771. }
  772. dir.qid = mf->qid;
  773. dir.length = 0;
  774. dir.uid = mf->user;
  775. dir.gid = mf->user;
  776. dir.muid = mf->user;
  777. dir.atime = dir.mtime = time(0);
  778. job->reply.nstat = convD2M(&dir, buf, sizeof buf);
  779. job->reply.stat = buf;
  780. sendmsg(job, 0);
  781. }
  782. void
  783. rwstat(Job *job, Mfile *mf)
  784. {
  785. USED(mf);
  786. sendmsg(job, "wstat permission denied");
  787. }
  788. void
  789. sendmsg(Job *job, char *err)
  790. {
  791. int n;
  792. uchar mdata[IOHDRSZ + Maxfdata];
  793. char ename[ERRMAX];
  794. if(err){
  795. job->reply.type = Rerror;
  796. snprint(ename, sizeof(ename), "cs: %s", err);
  797. job->reply.ename = ename;
  798. }else{
  799. job->reply.type = job->request.type+1;
  800. }
  801. job->reply.tag = job->request.tag;
  802. n = convS2M(&job->reply, mdata, sizeof mdata);
  803. if(n == 0){
  804. syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply);
  805. abort();
  806. }
  807. lock(&joblock);
  808. if(job->flushed == 0)
  809. if(write(mfd[1], mdata, n)!=n)
  810. error("mount write");
  811. unlock(&joblock);
  812. if(debug)
  813. syslog(0, logfile, "%F %d", &job->reply, n);
  814. }
  815. void
  816. error(char *s)
  817. {
  818. syslog(1, "cs", "%s: %r", s);
  819. _exits(0);
  820. }
  821. static int
  822. isvalidip(uchar *ip)
  823. {
  824. return ipcmp(ip, IPnoaddr) != 0 && ipcmp(ip, v4prefix) != 0;
  825. }
  826. void
  827. readipinterfaces(void)
  828. {
  829. Ipifc *nifc;
  830. Iplifc *lifc;
  831. ipifcs = readipifc(mntpt, ipifcs, -1);
  832. for(nifc = ipifcs; nifc; nifc = nifc->next)
  833. for(lifc = nifc->lifc; lifc; lifc = lifc->next)
  834. if(ipcmp(lifc->ip, IPnoaddr) != 0){
  835. ipmove(ipa, lifc->ip);
  836. sprint(ipaddr, "%I", ipa);
  837. if(debug)
  838. syslog(0, "dns", "ipaddr is %s\n", ipaddr);
  839. return;
  840. }
  841. ipmove(ipa, IPnoaddr);
  842. }
  843. /*
  844. * get the system name
  845. */
  846. void
  847. ipid(void)
  848. {
  849. uchar addr[6];
  850. Ndbtuple *t;
  851. char *p, *attr;
  852. Ndbs s;
  853. int f;
  854. char buf[Maxpath];
  855. /* use environment, ether addr, or ipaddr to get system name */
  856. if(*mysysname == 0){
  857. /*
  858. * environment has priority.
  859. *
  860. * on the sgi power the default system name
  861. * is the ip address. ignore that.
  862. *
  863. */
  864. p = getenv("sysname");
  865. if(p){
  866. attr = ipattr(p);
  867. if(strcmp(attr, "ip") != 0)
  868. strcpy(mysysname, p);
  869. }
  870. /*
  871. * the /net/ndb contains what the network
  872. * figured out from DHCP. use that name if
  873. * there is one.
  874. */
  875. if(*mysysname == 0 && netdb != nil){
  876. ndbreopen(netdb);
  877. for(t = ndbparse(netdb); t != nil; t = t->entry){
  878. if(strcmp(t->attr, "sys") == 0){
  879. strcpy(mysysname, t->val);
  880. break;
  881. }
  882. }
  883. ndbfree(t);
  884. }
  885. /* next network database, ip address, and ether address to find a name */
  886. if(*mysysname == 0){
  887. t = nil;
  888. if(isvalidip(ipa))
  889. t = ndbgetval(db, &s, "ip", ipaddr, "sys", mysysname);
  890. else {
  891. for(f = 0; f < 3; f++){
  892. snprint(buf, sizeof buf, "%s/ether%d", mntpt, f);
  893. if(myetheraddr(addr, buf) >= 0){
  894. snprint(eaddr, sizeof(eaddr), "%E", addr);
  895. t = ndbgetval(db, &s, "ether", eaddr, "sys",
  896. mysysname);
  897. if(t != nil)
  898. break;
  899. }
  900. }
  901. }
  902. ndbfree(t);
  903. }
  904. /* nothing else worked, use the ip address */
  905. if(*mysysname == 0 && isvalidip(ipa))
  906. strcpy(mysysname, ipaddr);
  907. /* set /dev/mysysname if we now know it */
  908. if(*mysysname){
  909. f = open("/dev/sysname", OWRITE);
  910. if(f >= 0){
  911. write(f, mysysname, strlen(mysysname));
  912. close(f);
  913. }
  914. }
  915. }
  916. }
  917. /*
  918. * Set up a list of default networks by looking for
  919. * /net/ * /clone.
  920. */
  921. void
  922. netinit(int background)
  923. {
  924. char clone[Maxpath];
  925. Network *np;
  926. static int working;
  927. if(background){
  928. switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){
  929. case 0:
  930. break;
  931. default:
  932. return;
  933. }
  934. lock(&netlock);
  935. }
  936. /* add the mounted networks to the default list */
  937. for(np = network; np->net; np++){
  938. if(np->considered)
  939. continue;
  940. snprint(clone, sizeof(clone), "%s/%s/clone", mntpt, np->net);
  941. if(access(clone, AEXIST) < 0)
  942. continue;
  943. if(netlist)
  944. last->next = np;
  945. else
  946. netlist = np;
  947. last = np;
  948. np->next = 0;
  949. np->considered = 1;
  950. }
  951. /* find out what our ip address is */
  952. readipinterfaces();
  953. /* set the system name if we need to, these says ip is all we have */
  954. ipid();
  955. if(debug)
  956. syslog(0, logfile, "mysysname %s eaddr %s ipaddr %s ipa %I\n",
  957. mysysname, eaddr, ipaddr, ipa);
  958. if(background){
  959. unlock(&netlock);
  960. _exits(0);
  961. }
  962. }
  963. /*
  964. * add networks to the standard list
  965. */
  966. void
  967. netadd(char *p)
  968. {
  969. Network *np;
  970. char *field[12];
  971. int i, n;
  972. n = getfields(p, field, 12, 1, " ");
  973. for(i = 0; i < n; i++){
  974. for(np = network; np->net; np++){
  975. if(strcmp(field[i], np->net) != 0)
  976. continue;
  977. if(np->considered)
  978. break;
  979. if(netlist)
  980. last->next = np;
  981. else
  982. netlist = np;
  983. last = np;
  984. np->next = 0;
  985. np->considered = 1;
  986. }
  987. }
  988. }
  989. /*
  990. * make a tuple
  991. */
  992. Ndbtuple*
  993. mktuple(char *attr, char *val)
  994. {
  995. Ndbtuple *t;
  996. t = emalloc(sizeof(Ndbtuple));
  997. strcpy(t->attr, attr);
  998. strncpy(t->val, val, sizeof(t->val));
  999. t->val[sizeof(t->val)-1] = 0;
  1000. t->line = t;
  1001. t->entry = 0;
  1002. return t;
  1003. }
  1004. int
  1005. lookforproto(Ndbtuple *t, char *proto)
  1006. {
  1007. for(; t != nil; t = t->entry)
  1008. if(strcmp(t->attr, "proto") == 0 && strcmp(t->val, proto) == 0)
  1009. return 1;
  1010. return 0;
  1011. }
  1012. /*
  1013. * lookup a request. the network "net" means we should pick the
  1014. * best network to get there.
  1015. */
  1016. int
  1017. lookup(Mfile *mf)
  1018. {
  1019. Network *np;
  1020. char *cp;
  1021. Ndbtuple *nt, *t;
  1022. char reply[Maxreply];
  1023. int i, rv;
  1024. int hack;
  1025. /* open up the standard db files */
  1026. if(db == 0)
  1027. ndbinit();
  1028. if(db == 0)
  1029. error("can't open mf->network database\n");
  1030. rv = 0;
  1031. if(mf->net == nil)
  1032. return 0; /* must have been a genquery */
  1033. if(strcmp(mf->net, "net") == 0){
  1034. /*
  1035. * go through set of default nets
  1036. */
  1037. for(np = mf->nextnet; np; np = np->next){
  1038. nt = (*np->lookup)(np, mf->host, mf->serv, 1);
  1039. if(nt == nil)
  1040. continue;
  1041. hack = np->fasttimeouthack && !lookforproto(nt, np->net);
  1042. for(t = nt; mf->nreply < Nreply && t; t = t->entry){
  1043. cp = (*np->trans)(t, np, mf->serv, mf->rem, hack);
  1044. if(cp){
  1045. /* avoid duplicates */
  1046. for(i = 0; i < mf->nreply; i++)
  1047. if(strcmp(mf->reply[i], cp) == 0)
  1048. break;
  1049. if(i == mf->nreply){
  1050. /* save the reply */
  1051. mf->replylen[mf->nreply] = strlen(cp);
  1052. mf->reply[mf->nreply++] = cp;
  1053. rv++;
  1054. }
  1055. }
  1056. }
  1057. ndbfree(nt);
  1058. np = np->next;
  1059. break;
  1060. }
  1061. mf->nextnet = np;
  1062. return rv;
  1063. }
  1064. /*
  1065. * if not /net, we only get one lookup
  1066. */
  1067. if(mf->nreply != 0)
  1068. return 0;
  1069. /*
  1070. * look for a specific network
  1071. */
  1072. for(np = netlist; np->net != nil; np++){
  1073. if(np->fasttimeouthack)
  1074. continue;
  1075. if(strcmp(np->net, mf->net) == 0)
  1076. break;
  1077. }
  1078. if(np->net != nil){
  1079. /*
  1080. * known network
  1081. */
  1082. nt = (*np->lookup)(np, mf->host, mf->serv, 1);
  1083. for(t = nt; mf->nreply < Nreply && t; t = t->entry){
  1084. cp = (*np->trans)(t, np, mf->serv, mf->rem, 0);
  1085. if(cp){
  1086. mf->replylen[mf->nreply] = strlen(cp);
  1087. mf->reply[mf->nreply++] = cp;
  1088. rv++;
  1089. }
  1090. }
  1091. ndbfree(nt);
  1092. return rv;
  1093. } else {
  1094. /*
  1095. * not a known network, don't translate host or service
  1096. */
  1097. if(mf->serv)
  1098. snprint(reply, sizeof(reply), "%s/%s/clone %s!%s",
  1099. mntpt, mf->net, mf->host, mf->serv);
  1100. else
  1101. snprint(reply, sizeof(reply), "%s/%s/clone %s",
  1102. mntpt, mf->net, mf->host);
  1103. mf->reply[0] = strdup(reply);
  1104. mf->replylen[0] = strlen(reply);
  1105. mf->nreply = 1;
  1106. return 1;
  1107. }
  1108. }
  1109. /*
  1110. * translate an ip service name into a port number. If it's a numeric port
  1111. * number, look for restricted access.
  1112. *
  1113. * the service '*' needs no translation.
  1114. */
  1115. char*
  1116. ipserv(Network *np, char *name, char *buf)
  1117. {
  1118. char *p;
  1119. int alpha = 0;
  1120. int restr = 0;
  1121. char port[Ndbvlen];
  1122. Ndbtuple *t, *nt;
  1123. Ndbs s;
  1124. /* '*' means any service */
  1125. if(strcmp(name, "*")==0){
  1126. strcpy(buf, name);
  1127. return buf;
  1128. }
  1129. /* see if it's numeric or symbolic */
  1130. port[0] = 0;
  1131. for(p = name; *p; p++){
  1132. if(isdigit(*p))
  1133. {}
  1134. else if(isalpha(*p) || *p == '-' || *p == '$')
  1135. alpha = 1;
  1136. else
  1137. return 0;
  1138. }
  1139. if(alpha){
  1140. t = ndbgetval(db, &s, np->net, name, "port", port);
  1141. if(t == 0)
  1142. return 0;
  1143. } else {
  1144. t = ndbgetval(db, &s, "port", name, "port", port);
  1145. if(t == 0){
  1146. strncpy(port, name, sizeof(port));
  1147. port[sizeof(port)-1] = 0;
  1148. }
  1149. }
  1150. if(t){
  1151. for(nt = t; nt; nt = nt->entry)
  1152. if(strcmp(nt->attr, "restricted") == 0)
  1153. restr = 1;
  1154. ndbfree(t);
  1155. }
  1156. sprint(buf, "%s%s", port, restr ? "!r" : "");
  1157. return buf;
  1158. }
  1159. /*
  1160. * lookup an ip attribute
  1161. */
  1162. int
  1163. ipattrlookup(Ndb *db, char *ipa, char *attr, char *val)
  1164. {
  1165. Ndbtuple *t, *nt;
  1166. char *alist[2];
  1167. alist[0] = attr;
  1168. t = ndbipinfo(db, "ip", ipa, alist, 1);
  1169. if(t == nil)
  1170. return 0;
  1171. for(nt = t; nt != nil; nt = nt->entry){
  1172. if(strcmp(nt->attr, attr) == 0){
  1173. strcpy(val, nt->val);
  1174. ndbfree(t);
  1175. return 1;
  1176. }
  1177. }
  1178. /* we shouldn't get here */
  1179. ndbfree(t);
  1180. return 0;
  1181. }
  1182. /*
  1183. * lookup (and translate) an ip destination
  1184. */
  1185. Ndbtuple*
  1186. iplookup(Network *np, char *host, char *serv, int nolookup)
  1187. {
  1188. char *attr;
  1189. Ndbtuple *t, *nt;
  1190. Ndbs s;
  1191. char ts[Ndbvlen+1];
  1192. char th[Ndbvlen+1];
  1193. char dollar[Ndbvlen+1];
  1194. uchar ip[IPaddrlen];
  1195. uchar net[IPaddrlen];
  1196. uchar tnet[IPaddrlen];
  1197. Ipifc *ifc;
  1198. Iplifc *lifc;
  1199. USED(nolookup);
  1200. /*
  1201. * start with the service since it's the most likely to fail
  1202. * and costs the least
  1203. */
  1204. if(serv==0 || ipserv(np, serv, ts) == 0){
  1205. werrstr("can't translate address");
  1206. return 0;
  1207. }
  1208. /* for dial strings with no host */
  1209. if(strcmp(host, "*") == 0)
  1210. return mktuple("ip", "*");
  1211. /*
  1212. * hack till we go v6 :: = 0.0.0.0
  1213. */
  1214. if(strcmp("::", host) == 0)
  1215. return mktuple("ip", "*");
  1216. /*
  1217. * '$' means the rest of the name is an attribute that we
  1218. * need to search for
  1219. */
  1220. if(*host == '$'){
  1221. if(ipattrlookup(db, ipaddr, host+1, dollar))
  1222. host = dollar;
  1223. }
  1224. /*
  1225. * turn '[ip address]' into just 'ip address'
  1226. */
  1227. if(*host == '[' && host[strlen(host)-1] == ']'){
  1228. host++;
  1229. host[strlen(host)-1] = 0;
  1230. }
  1231. /*
  1232. * just accept addresses
  1233. */
  1234. attr = ipattr(host);
  1235. if(strcmp(attr, "ip") == 0)
  1236. return mktuple("ip", host);
  1237. /*
  1238. * give the domain name server the first opportunity to
  1239. * resolve domain names. if that fails try the database.
  1240. */
  1241. t = 0;
  1242. if(strcmp(attr, "dom") == 0)
  1243. t = dnsiplookup(host, &s);
  1244. if(t == 0)
  1245. t = ndbgetval(db, &s, attr, host, "ip", th);
  1246. if(t == 0)
  1247. t = dnsiplookup(host, &s);
  1248. if(t == 0 && strcmp(attr, "dom") != 0)
  1249. t = dnsiplookup(host, &s);
  1250. if(t == 0)
  1251. return 0;
  1252. /*
  1253. * reorder the tuple to have the matched line first and
  1254. * save that in the request structure.
  1255. */
  1256. t = reorder(t, s.t);
  1257. /*
  1258. * reorder according to our interfaces
  1259. */
  1260. lock(&ipifclock);
  1261. for(ifc = ipifcs; ifc != nil; ifc = ifc->next){
  1262. for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
  1263. maskip(lifc->ip, lifc->mask, net);
  1264. for(nt = t; nt; nt = nt->entry){
  1265. if(strcmp(nt->attr, "ip") != 0)
  1266. continue;
  1267. parseip(ip, nt->val);
  1268. maskip(ip, lifc->mask, tnet);
  1269. if(memcmp(net, tnet, IPaddrlen) == 0){
  1270. t = reorder(t, nt);
  1271. unlock(&ipifclock);
  1272. return t;
  1273. }
  1274. }
  1275. }
  1276. }
  1277. unlock(&ipifclock);
  1278. return t;
  1279. }
  1280. /*
  1281. * translate an ip address
  1282. */
  1283. char*
  1284. iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack)
  1285. {
  1286. char ts[Ndbvlen+1];
  1287. char reply[Maxreply];
  1288. char x[Ndbvlen+1];
  1289. if(strcmp(t->attr, "ip") != 0)
  1290. return 0;
  1291. if(serv == 0 || ipserv(np, serv, ts) == 0)
  1292. return 0;
  1293. if(rem != nil)
  1294. snprint(x, sizeof(x), "!%s", rem);
  1295. else
  1296. *x = 0;
  1297. if(*t->val == '*')
  1298. snprint(reply, sizeof(reply), "%s/%s/clone %s%s",
  1299. mntpt, np->net, ts, x);
  1300. else
  1301. snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s%s",
  1302. mntpt, np->net, t->val, ts, x, hack?"!fasttimeout":"");
  1303. return strdup(reply);
  1304. }
  1305. /*
  1306. * lookup a telephone number
  1307. */
  1308. Ndbtuple*
  1309. telcolookup(Network *np, char *host, char *serv, int nolookup)
  1310. {
  1311. Ndbtuple *t;
  1312. Ndbs s;
  1313. char th[Ndbvlen+1];
  1314. USED(np, nolookup, serv);
  1315. t = ndbgetval(db, &s, "sys", host, "telco", th);
  1316. if(t == 0)
  1317. return mktuple("telco", host);
  1318. return reorder(t, s.t);
  1319. }
  1320. /*
  1321. * translate a telephone address
  1322. */
  1323. char*
  1324. telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int)
  1325. {
  1326. char reply[Maxreply];
  1327. char x[Ndbvlen+1];
  1328. if(strcmp(t->attr, "telco") != 0)
  1329. return 0;
  1330. if(rem != nil)
  1331. snprint(x, sizeof(x), "!%s", rem);
  1332. else
  1333. *x = 0;
  1334. if(serv)
  1335. snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s", mntpt, np->net,
  1336. t->val, serv, x);
  1337. else
  1338. snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net,
  1339. t->val, x);
  1340. return strdup(reply);
  1341. }
  1342. /*
  1343. * reorder the tuple to put x's line first in the entry
  1344. */
  1345. Ndbtuple*
  1346. reorder(Ndbtuple *t, Ndbtuple *x)
  1347. {
  1348. Ndbtuple *nt;
  1349. Ndbtuple *line;
  1350. /* find start of this entry's line */
  1351. for(line = x; line->entry == line->line; line = line->line)
  1352. ;
  1353. line = line->line;
  1354. if(line == t)
  1355. return t; /* already the first line */
  1356. /* remove this line and everything after it from the entry */
  1357. for(nt = t; nt->entry != line; nt = nt->entry)
  1358. ;
  1359. nt->entry = 0;
  1360. /* make that the start of the entry */
  1361. for(nt = line; nt->entry; nt = nt->entry)
  1362. ;
  1363. nt->entry = t;
  1364. return line;
  1365. }
  1366. /*
  1367. * create a slave process to handle a request to avoid one request blocking
  1368. * another. parent returns to job loop.
  1369. */
  1370. void
  1371. slave(void)
  1372. {
  1373. if(*isslave)
  1374. return; /* we're already a slave process */
  1375. switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){
  1376. case -1:
  1377. break;
  1378. case 0:
  1379. if(debug)
  1380. syslog(0, logfile, "slave %d", getpid());
  1381. *isslave = 1;
  1382. break;
  1383. default:
  1384. longjmp(masterjmp, 1);
  1385. }
  1386. }
  1387. /*
  1388. * call the dns process and have it try to translate a name
  1389. */
  1390. Ndbtuple*
  1391. dnsiplookup(char *host, Ndbs *s)
  1392. {
  1393. char buf[Ndbvlen + 4];
  1394. Ndbtuple *t;
  1395. unlock(&dblock);
  1396. /* save the name before starting a slave */
  1397. snprint(buf, sizeof(buf), "%s", host);
  1398. slave();
  1399. if(strcmp(ipattr(buf), "ip") == 0)
  1400. t = dnsquery(mntpt, buf, "ptr");
  1401. else
  1402. t = dnsquery(mntpt, buf, "ip");
  1403. s->t = t;
  1404. lock(&dblock);
  1405. return t;
  1406. }
  1407. int
  1408. qmatch(Ndbtuple *t, char **attr, char **val, int n)
  1409. {
  1410. int i, found;
  1411. Ndbtuple *nt;
  1412. for(i = 1; i < n; i++){
  1413. found = 0;
  1414. for(nt = t; nt; nt = nt->entry)
  1415. if(strcmp(attr[i], nt->attr) == 0)
  1416. if(strcmp(val[i], "*") == 0
  1417. || strcmp(val[i], nt->val) == 0){
  1418. found = 1;
  1419. break;
  1420. }
  1421. if(found == 0)
  1422. break;
  1423. }
  1424. return i == n;
  1425. }
  1426. void
  1427. qreply(Mfile *mf, Ndbtuple *t)
  1428. {
  1429. int i;
  1430. Ndbtuple *nt;
  1431. char buf[2048];
  1432. buf[0] = 0;
  1433. for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){
  1434. strcat(buf, nt->attr);
  1435. strcat(buf, "=");
  1436. strcat(buf, nt->val);
  1437. i = strlen(buf);
  1438. if(nt->line != nt->entry || sizeof(buf) - i < 2*Ndbvlen+2){
  1439. mf->replylen[mf->nreply] = strlen(buf);
  1440. mf->reply[mf->nreply++] = strdup(buf);
  1441. buf[0] = 0;
  1442. } else
  1443. strcat(buf, " ");
  1444. }
  1445. }
  1446. enum
  1447. {
  1448. Maxattr= 32,
  1449. };
  1450. /*
  1451. * generic query lookup. The query is of one of the following
  1452. * forms:
  1453. *
  1454. * attr1=val1 attr2=val2 attr3=val3 ...
  1455. *
  1456. * returns the matching tuple
  1457. *
  1458. * ipinfo attr=val attr1 attr2 attr3 ...
  1459. *
  1460. * is like ipinfo and returns the attr{1-n}
  1461. * associated with the ip address.
  1462. */
  1463. char*
  1464. genquery(Mfile *mf, char *query)
  1465. {
  1466. int i, n;
  1467. char *p;
  1468. char *attr[Maxattr];
  1469. char *val[Maxattr];
  1470. Ndbtuple *t;
  1471. Ndbs s;
  1472. n = getfields(query, attr, 32, 1, " ");
  1473. if(n == 0)
  1474. return "bad query";
  1475. if(strcmp(attr[0], "ipinfo") == 0)
  1476. return ipinfoquery(mf, attr, n);
  1477. /* parse pairs */
  1478. for(i = 0; i < n; i++){
  1479. p = strchr(attr[i], '=');
  1480. if(p == 0)
  1481. return "bad query";
  1482. *p++ = 0;
  1483. val[i] = p;
  1484. }
  1485. /* give dns a chance */
  1486. if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){
  1487. t = dnsiplookup(val[0], &s);
  1488. if(t){
  1489. if(qmatch(t, attr, val, n)){
  1490. qreply(mf, t);
  1491. ndbfree(t);
  1492. return 0;
  1493. }
  1494. ndbfree(t);
  1495. }
  1496. }
  1497. /* first pair is always the key. It can't be a '*' */
  1498. t = ndbsearch(db, &s, attr[0], val[0]);
  1499. /* search is the and of all the pairs */
  1500. while(t){
  1501. if(qmatch(t, attr, val, n)){
  1502. qreply(mf, t);
  1503. ndbfree(t);
  1504. return 0;
  1505. }
  1506. ndbfree(t);
  1507. t = ndbsnext(&s, attr[0], val[0]);
  1508. }
  1509. return "no match";
  1510. }
  1511. /*
  1512. * resolve an ip address
  1513. */
  1514. static Ndbtuple*
  1515. ipresolve(char *attr, char *host)
  1516. {
  1517. Ndbtuple *t, *nt, **l;
  1518. t = iplookup(&network[Ntcp], host, "*", 0);
  1519. for(l = &t; *l != nil; ){
  1520. nt = *l;
  1521. if(strcmp(nt->attr, "ip") != 0){
  1522. *l = nt->entry;
  1523. nt->entry = nil;
  1524. ndbfree(nt);
  1525. continue;
  1526. }
  1527. strcpy(nt->attr, attr);
  1528. l = &nt->entry;
  1529. }
  1530. return t;
  1531. }
  1532. char*
  1533. ipinfoquery(Mfile *mf, char **list, int n)
  1534. {
  1535. int i, nresolve;
  1536. int resolve[Maxattr];
  1537. Ndbtuple *t, *nt, **l;
  1538. char *attr, *val;
  1539. /* skip 'ipinfo' */
  1540. list++; n--;
  1541. if(n < 2)
  1542. return "bad query";
  1543. /* get search attribute=value */
  1544. attr = *list++; n--;
  1545. val = strchr(attr, '=');
  1546. if(val == nil)
  1547. return "bad query";
  1548. *val++ = 0;
  1549. /*
  1550. * don't let ndbipinfo resolve the addresses, we're
  1551. * better at it.
  1552. */
  1553. nresolve = 0;
  1554. for(i = 0; i < n; i++)
  1555. if(*list[i] == '@'){
  1556. list[i]++;
  1557. resolve[i] = 1;
  1558. nresolve++;
  1559. } else
  1560. resolve[i] = 0;
  1561. t = ndbipinfo(db, attr, val, list, n);
  1562. if(t == nil)
  1563. return "no match";
  1564. if(nresolve != 0){
  1565. for(l = &t; *l != nil;){
  1566. nt = *l;
  1567. /* already an address? */
  1568. if(strcmp(ipattr(nt->val), "ip") == 0){
  1569. l = &(*l)->entry;
  1570. continue;
  1571. }
  1572. /* user wants it resolved? */
  1573. for(i = 0; i < n; i++)
  1574. if(strcmp(list[i], nt->attr) == 0)
  1575. break;
  1576. if(i >= n || resolve[i] == 0){
  1577. l = &(*l)->entry;
  1578. continue;
  1579. }
  1580. /* resolve address and replace entry */
  1581. *l = ipresolve(nt->attr, nt->val);
  1582. while(*l != nil)
  1583. l = &(*l)->entry;
  1584. *l = nt->entry;
  1585. nt->entry = nil;
  1586. ndbfree(nt);
  1587. }
  1588. }
  1589. /* make it all one line */
  1590. for(nt = t; nt != nil; nt = nt->entry){
  1591. if(nt->entry == nil)
  1592. nt->line = t;
  1593. else
  1594. nt->line = nt->entry;
  1595. }
  1596. qreply(mf, t);
  1597. return nil;
  1598. }
  1599. void*
  1600. emalloc(int size)
  1601. {
  1602. void *x;
  1603. x = malloc(size);
  1604. if(x == nil)
  1605. abort();
  1606. memset(x, 0, size);
  1607. return x;
  1608. }
  1609. char*
  1610. estrdup(char *s)
  1611. {
  1612. int size;
  1613. char *p;
  1614. size = strlen(s)+1;
  1615. p = malloc(size);
  1616. if(p == nil)
  1617. abort();
  1618. memmove(p, s, size);
  1619. return p;
  1620. }