cs.c 32 KB

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