cs.c 33 KB

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