cs.c 32 KB

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