cs.c 36 KB

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