cs.c 34 KB

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