dhcpd.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <ip.h>
  12. #include <bio.h>
  13. #include <ndb.h>
  14. #include "dat.h"
  15. /*
  16. * ala rfc2131
  17. */
  18. enum {
  19. Maxloglen = 1024,
  20. };
  21. typedef struct Req Req;
  22. struct Req
  23. {
  24. int fd; /* for reply */
  25. Bootp *bp;
  26. Udphdr *up;
  27. uint8_t *e; /* end of received message */
  28. uint8_t *p; /* options pointer */
  29. uint8_t *max; /* max end of reply */
  30. /* expanded to v6 */
  31. uint8_t ciaddr[IPaddrlen];
  32. uint8_t giaddr[IPaddrlen];
  33. /* parsed options */
  34. int p9request; /* flag: this is a bootp with plan9 options */
  35. int genrequest; /* flag: this is a bootp with generic options */
  36. int broadcast; /* flag: request was broadcast */
  37. int dhcptype; /* dhcp message type */
  38. int leasetime; /* dhcp lease */
  39. uint8_t ip[IPaddrlen]; /* requested address */
  40. uint8_t server[IPaddrlen]; /* server address */
  41. char msg[ERRMAX]; /* error message */
  42. char vci[32]; /* vendor class id */
  43. char *id; /* client id */
  44. uint8_t requested[32]; /* requested params */
  45. uint8_t vendorclass[32];
  46. char cputype[32-3];
  47. Info gii; /* about target network */
  48. Info ii; /* about target system */
  49. int staticbinding;
  50. uint8_t buf[2*1024]; /* message buffer */
  51. };
  52. #define TFTP "/lib/tftpd"
  53. char *blog = "ipboot";
  54. char mysysname[64];
  55. Ipifc *ipifcs;
  56. int debug;
  57. int nobootp;
  58. int32_t now;
  59. int slowstat, slowdyn;
  60. char net[256];
  61. int pptponly; /* only answer request that came from the pptp server */
  62. int mute, mutestat;
  63. int minlease = MinLease;
  64. int staticlease = StaticLease;
  65. uint64_t start;
  66. static int v6opts;
  67. /* option magic */
  68. char plan9opt[4] = { 'p', '9', ' ', ' ' };
  69. char genericopt[4] = { 0x63, 0x82, 0x53, 0x63 };
  70. /* well known addresses */
  71. uint8_t zeros[Maxhwlen];
  72. /* option debug buffer */
  73. char optbuf[1024];
  74. char *op;
  75. char *oe = optbuf + sizeof(optbuf);
  76. char *optname[256] =
  77. {
  78. [OBend] "end",
  79. [OBpad] "pad",
  80. [OBmask] "mask",
  81. [OBtimeoff] "timeoff",
  82. [OBrouter] "router",
  83. [OBtimeserver] "time",
  84. [OBnameserver] "name",
  85. [OBdnserver] "dns",
  86. [OBlogserver] "log",
  87. [OBcookieserver] "cookie",
  88. [OBlprserver] "lpr",
  89. [OBimpressserver] "impress",
  90. [OBrlserver] "rl",
  91. [OBhostname] "host",
  92. [OBbflen] "bflen",
  93. [OBdumpfile] "dumpfile",
  94. [OBdomainname] "dom",
  95. [OBswapserver] "swap",
  96. [OBrootpath] "rootpath",
  97. [OBextpath] "extpath",
  98. [OBipforward] "ipforward",
  99. [OBnonlocal] "nonlocal",
  100. [OBpolicyfilter] "policyfilter",
  101. [OBmaxdatagram] "maxdatagram",
  102. [OBttl] "ttl",
  103. [OBpathtimeout] "pathtimeout",
  104. [OBpathplateau] "pathplateau",
  105. [OBmtu] "mtu",
  106. [OBsubnetslocal] "subnetslocal",
  107. [OBbaddr] "baddr",
  108. [OBdiscovermask] "discovermask",
  109. [OBsupplymask] "supplymask",
  110. [OBdiscoverrouter] "discoverrouter",
  111. [OBrsserver] "rsserver",
  112. [OBstaticroutes] "staticroutes",
  113. [OBtrailerencap] "trailerencap",
  114. [OBarptimeout] "arptimeout",
  115. [OBetherencap] "etherencap",
  116. [OBtcpttl] "tcpttl",
  117. [OBtcpka] "tcpka",
  118. [OBtcpkag] "tcpkag",
  119. [OBnisdomain] "nisdomain",
  120. [OBniserver] "niserver",
  121. [OBntpserver] "ntpserver",
  122. [OBvendorinfo] "vendorinfo",
  123. [OBnetbiosns] "NBns",
  124. [OBnetbiosdds] "NBdds",
  125. [OBnetbiostype] "NBtype",
  126. [OBnetbiosscope] "NBscope",
  127. [OBxfontserver] "xfont",
  128. [OBxdispmanager] "xdisp",
  129. [OBnisplusdomain] "NPdomain",
  130. [OBnisplusserver] "NP",
  131. [OBhomeagent] "homeagent",
  132. [OBsmtpserver] "smtp",
  133. [OBpop3server] "pop3",
  134. [OBnntpserver] "nntp",
  135. [OBwwwserver] "www",
  136. [OBfingerserver] "finger",
  137. [OBircserver] "ircserver",
  138. [OBstserver] "stserver",
  139. [OBstdaserver] "stdaserver",
  140. /* dhcp options */
  141. [ODipaddr] "ip",
  142. [ODlease] "leas",
  143. [ODoverload] "overload",
  144. [ODtype] "typ",
  145. [ODserverid] "sid",
  146. [ODparams] "params",
  147. [ODmessage] "message",
  148. [ODmaxmsg] "maxmsg",
  149. [ODrenewaltime] "renewaltime",
  150. [ODrebindingtime] "rebindingtime",
  151. [ODvendorclass] "vendorclass",
  152. [ODclientid] "cid",
  153. [ODtftpserver] "tftpserver",
  154. [ODbootfile] "bf",
  155. };
  156. void addropt(Req*, int, uint8_t*);
  157. void addrsopt(Req*, int, uint8_t**, int);
  158. void arpenter(uint8_t*, uint8_t*);
  159. void bootp(Req*);
  160. void byteopt(Req*, int, uint8_t);
  161. void dhcp(Req*);
  162. void fatal(int, char*, ...);
  163. void hexopt(Req*, int, char*);
  164. void logdhcp(Req*);
  165. void logdhcpout(Req *, char *);
  166. void longopt(Req*, int, int32_t);
  167. void maskopt(Req*, int, uint8_t*);
  168. void miscoptions(Req*, uint8_t*);
  169. int openlisten(char *net);
  170. void p9addrsopt(Req *rp, int t, uint8_t **ip, int i);
  171. void parseoptions(Req*);
  172. void proto(Req*, int);
  173. void rcvdecline(Req*);
  174. void rcvdiscover(Req*);
  175. void rcvinform(Req*);
  176. void rcvrelease(Req*);
  177. void rcvrequest(Req*);
  178. int readlast(int, uint8_t*, int);
  179. char* readsysname(void);
  180. void remrequested(Req*, int);
  181. void sendack(Req*, uint8_t*, int, int);
  182. void sendnak(Req*, char*);
  183. void sendoffer(Req*, uint8_t*, int);
  184. void stringopt(Req*, int, char*);
  185. void termopt(Req*);
  186. int validip(uint8_t*);
  187. void vectoropt(Req*, int, uint8_t*, int);
  188. void warning(int, char*, ...);
  189. void
  190. timestamp(char *tag)
  191. {
  192. uint64_t t;
  193. t = nsec()/1000;
  194. syslog(0, blog, "%s %lluµs", tag, t - start);
  195. }
  196. void
  197. usage(void)
  198. {
  199. fprint(2, "usage: dhcp [-dmnprsSZ] [-f directory] [-M minlease] "
  200. "[-x netmtpt] [-Z staticlease] addr n [addr n] ...\n");
  201. exits("usage");
  202. }
  203. void
  204. main(int argc, char **argv)
  205. {
  206. int i, n, fd;
  207. uint8_t ip[IPaddrlen];
  208. Req r;
  209. setnetmtpt(net, sizeof net, nil);
  210. fmtinstall('E', eipfmt);
  211. fmtinstall('I', eipfmt);
  212. fmtinstall('V', eipfmt);
  213. fmtinstall('M', eipfmt);
  214. ARGBEGIN {
  215. case '6':
  216. v6opts = 1;
  217. break;
  218. case 'd':
  219. debug = 1;
  220. break;
  221. case 'f':
  222. ndbfile = EARGF(usage());
  223. break;
  224. case 'm':
  225. mute = 1;
  226. break;
  227. case 'M':
  228. minlease = atoi(EARGF(usage()));
  229. if(minlease <= 0)
  230. minlease = MinLease;
  231. break;
  232. case 'n':
  233. nobootp = 1;
  234. break;
  235. case 'p':
  236. pptponly = 1;
  237. break;
  238. case 'r':
  239. mutestat = 1;
  240. break;
  241. case 's':
  242. slowstat = 1;
  243. break;
  244. case 'S':
  245. slowdyn = 1;
  246. break;
  247. case 'x':
  248. setnetmtpt(net, sizeof net, EARGF(usage()));
  249. break;
  250. case 'Z':
  251. staticlease = atoi(EARGF(usage()));
  252. if(staticlease <= 0)
  253. staticlease = StaticLease;
  254. break;
  255. default:
  256. usage();
  257. break;
  258. } ARGEND;
  259. while(argc > 1){
  260. parseip(ip, argv[0]);
  261. if(!validip(ip))
  262. usage();
  263. n = atoi(argv[1]);
  264. if(n <= 0)
  265. usage();
  266. initbinding(ip, n);
  267. argc -= 2;
  268. argv += 2;
  269. }
  270. /* for debugging */
  271. for(i = 0; i < 256; i++)
  272. if(optname[i] == 0)
  273. optname[i] = smprint("%d", i);
  274. /* what is my name? */
  275. strcpy(mysysname, readsysname());
  276. /* put process in background */
  277. if(!debug)
  278. switch(rfork(RFNOTEG|RFPROC|RFFDG)) {
  279. case -1:
  280. fatal(1, "fork");
  281. case 0:
  282. break;
  283. default:
  284. exits(0);
  285. }
  286. if (chdir(TFTP) < 0)
  287. warning(1, "can't change directory to %s", TFTP);
  288. fd = openlisten(net);
  289. for(;;){
  290. memset(&r, 0, sizeof(r));
  291. r.fd = fd;
  292. n = readlast(r.fd, r.buf, sizeof(r.buf));
  293. if(n < Udphdrsize)
  294. fatal(1, "error reading requests");
  295. start = nsec()/1000;
  296. op = optbuf;
  297. *op = 0;
  298. proto(&r, n);
  299. if(r.id != nil)
  300. free(r.id);
  301. }
  302. }
  303. void
  304. proto(Req *rp, int n)
  305. {
  306. uint8_t relip[IPaddrlen];
  307. char buf[64];
  308. now = time(0);
  309. rp->e = rp->buf + n;
  310. rp->bp = (Bootp*)rp->buf;
  311. rp->up = (Udphdr*)rp->buf;
  312. if (ipcmp(rp->up->laddr, IPv4bcast) == 0){
  313. ipmove(rp->up->laddr, rp->up->ifcaddr);
  314. rp->broadcast = 1;
  315. }
  316. rp->max = rp->buf + Udphdrsize + MINSUPPORTED - IPUDPHDRSIZE;
  317. rp->p = rp->bp->optdata;
  318. v4tov6(rp->giaddr, rp->bp->giaddr);
  319. v4tov6(rp->ciaddr, rp->bp->ciaddr);
  320. if(pptponly && rp->bp->htype != 0)
  321. return;
  322. ipifcs = readipifc(net, ipifcs, -1);
  323. if(validip(rp->giaddr))
  324. ipmove(relip, rp->giaddr);
  325. else if(validip(rp->up->raddr))
  326. ipmove(relip, rp->up->raddr);
  327. else
  328. ipmove(relip, rp->up->laddr);
  329. if(rp->e < (uint8_t*)rp->bp->sname){
  330. warning(0, "packet too short");
  331. return;
  332. }
  333. if(rp->bp->op != Bootrequest){
  334. warning(0, "not bootrequest");
  335. return;
  336. }
  337. if(rp->e >= rp->bp->optdata){
  338. if(memcmp(rp->bp->optmagic, plan9opt, sizeof(rp->bp->optmagic)) == 0)
  339. rp->p9request = 1;
  340. if(memcmp(rp->bp->optmagic, genericopt, sizeof(rp->bp->optmagic)) == 0) {
  341. rp->genrequest = 1;
  342. parseoptions(rp);
  343. }
  344. }
  345. rp->p = rp->bp->optdata;
  346. /* If no id is specified, make one from the hardware address
  347. * of the target. We assume all zeros is not a hardware address
  348. * which could be a mistake.
  349. */
  350. if(rp->id == nil){
  351. if(rp->bp->hlen > Maxhwlen){
  352. warning(0, "hlen %d", rp->bp->hlen);
  353. return;
  354. }
  355. if(memcmp(zeros, rp->bp->chaddr, rp->bp->hlen) == 0){
  356. warning(0, "no chaddr");
  357. return;
  358. }
  359. sprint(buf, "hwa%2.2x_", rp->bp->htype);
  360. rp->id = tohex(buf, rp->bp->chaddr, rp->bp->hlen);
  361. }
  362. /* info about gateway */
  363. if(lookupip(relip, &rp->gii, 1) < 0){
  364. warning(0, "lookupip failed");
  365. return;
  366. }
  367. /* info about target system */
  368. if(lookup(rp->bp, &rp->ii, &rp->gii) == 0)
  369. if(rp->ii.indb && rp->ii.dhcpgroup[0] == 0)
  370. rp->staticbinding = 1;
  371. if(rp->dhcptype)
  372. dhcp(rp);
  373. else
  374. bootp(rp);
  375. timestamp("done");
  376. }
  377. /*
  378. * since we are single-threaded, this causes us to effectively
  379. * stop listening while we sleep.
  380. */
  381. static void
  382. slowdelay(Req *rp)
  383. {
  384. if(slowstat && rp->staticbinding || slowdyn && !rp->staticbinding)
  385. sleep(1000);
  386. }
  387. void
  388. dhcp(Req *rp)
  389. {
  390. logdhcp(rp);
  391. switch(rp->dhcptype){
  392. case Discover:
  393. slowdelay(rp);
  394. rcvdiscover(rp);
  395. break;
  396. case Request:
  397. rcvrequest(rp);
  398. break;
  399. case Decline:
  400. rcvdecline(rp);
  401. break;
  402. case Release:
  403. rcvrelease(rp);
  404. break;
  405. case Inform:
  406. rcvinform(rp);
  407. break;
  408. }
  409. }
  410. void
  411. rcvdiscover(Req *rp)
  412. {
  413. Binding *b, *nb;
  414. if(rp->staticbinding){
  415. sendoffer(rp, rp->ii.ipaddr, (staticlease > minlease? staticlease: minlease));
  416. return;
  417. }
  418. /*
  419. * first look for an outstanding offer
  420. */
  421. b = idtooffer(rp->id, &rp->gii);
  422. /*
  423. * rfc2131 says:
  424. * If an address is available, the new address
  425. * SHOULD be chosen as follows:
  426. *
  427. * o The client's current address as recorded in the client's current
  428. * binding, ELSE
  429. *
  430. * o The client's previous address as recorded in the client's (now
  431. * expired or released) binding, if that address is in the server's
  432. * pool of available addresses and not already allocated, ELSE
  433. *
  434. * o The address requested in the 'Requested IP Address' option, if that
  435. * address is valid and not already allocated, ELSE
  436. *
  437. * o A new address allocated from the server's pool of available
  438. * addresses; the address is selected based on the subnet from which
  439. * the message was received (if 'giaddr' is 0) or on the address of
  440. * the relay agent that forwarded the message ('giaddr' when not 0).
  441. */
  442. if(b == nil){
  443. b = idtobinding(rp->id, &rp->gii, 1);
  444. if(b && b->boundto && strcmp(b->boundto, rp->id) != 0)
  445. if(validip(rp->ip) && samenet(rp->ip, &rp->gii)){
  446. nb = iptobinding(rp->ip, 0);
  447. if(nb && nb->lease < now)
  448. b = nb;
  449. }
  450. }
  451. if(b == nil){
  452. warning(0, "!Discover(%s via %I): no binding %I",
  453. rp->id, rp->gii.ipaddr, rp->ip);
  454. return;
  455. }
  456. mkoffer(b, rp->id, rp->leasetime);
  457. sendoffer(rp, b->ip, b->offer);
  458. }
  459. void
  460. rcvrequest(Req *rp)
  461. {
  462. Binding *b;
  463. if(validip(rp->server)){
  464. /* this is a reply to an offer - SELECTING */
  465. /* check for hard assignment */
  466. if(rp->staticbinding){
  467. if(forme(rp->server))
  468. sendack(rp, rp->ii.ipaddr,
  469. (staticlease > minlease? staticlease:
  470. minlease), 1);
  471. else
  472. warning(0, "!Request(%s via %I): for server %I not me",
  473. rp->id, rp->gii.ipaddr, rp->server);
  474. return;
  475. }
  476. b = idtooffer(rp->id, &rp->gii);
  477. /* if we don't have an offer, nak */
  478. if(b == nil){
  479. warning(0, "!Request(%s via %I): no offer",
  480. rp->id, rp->gii.ipaddr);
  481. if(forme(rp->server))
  482. sendnak(rp, "no offer for you");
  483. return;
  484. }
  485. /* if not for me, retract offer */
  486. if(!forme(rp->server)){
  487. b->expoffer = 0;
  488. warning(0, "!Request(%s via %I): for server %I not me",
  489. rp->id, rp->gii.ipaddr, rp->server);
  490. return;
  491. }
  492. /*
  493. * if the client is confused about what we offered, nak.
  494. * client really shouldn't be specifying this when selecting
  495. */
  496. if(validip(rp->ip) && ipcmp(rp->ip, b->ip) != 0){
  497. warning(0, "!Request(%s via %I): requests %I, not %I",
  498. rp->id, rp->gii.ipaddr, rp->ip, b->ip);
  499. sendnak(rp, "bad ip address option");
  500. return;
  501. }
  502. if(commitbinding(b) < 0){
  503. warning(0, "!Request(%s via %I): can't commit %I",
  504. rp->id, rp->gii.ipaddr, b->ip);
  505. sendnak(rp, "can't commit binding");
  506. return;
  507. }
  508. sendack(rp, b->ip, b->offer, 1);
  509. } else if(validip(rp->ip)){
  510. /*
  511. * checking address/net - INIT-REBOOT
  512. *
  513. * This is a rebooting client that remembers its old
  514. * address.
  515. */
  516. /* check for hard assignment */
  517. if(rp->staticbinding){
  518. if(memcmp(rp->ip, rp->ii.ipaddr, IPaddrlen) != 0){
  519. warning(0, "!Request(%s via %I): %I not valid for %E",
  520. rp->id, rp->gii.ipaddr, rp->ip, rp->bp->chaddr);
  521. sendnak(rp, "not valid");
  522. }
  523. sendack(rp, rp->ii.ipaddr, (staticlease > minlease?
  524. staticlease: minlease), 1);
  525. return;
  526. }
  527. /* make sure the network makes sense */
  528. if(!samenet(rp->ip, &rp->gii)){
  529. warning(0, "!Request(%s via %I): bad forward of %I",
  530. rp->id, rp->gii.ipaddr, rp->ip);
  531. sendnak(rp, "wrong network");
  532. return;
  533. }
  534. b = iptobinding(rp->ip, 0);
  535. if(b == nil){
  536. warning(0, "!Request(%s via %I): no binding for %I",
  537. rp->id, rp->gii.ipaddr, rp->ip);
  538. return;
  539. }
  540. if(memcmp(rp->ip, b->ip, IPaddrlen) != 0 || now > b->lease){
  541. warning(0, "!Request(%s via %I): %I not valid",
  542. rp->id, rp->gii.ipaddr, rp->ip);
  543. sendnak(rp, "not valid");
  544. return;
  545. }
  546. b->offer = b->lease - now;
  547. sendack(rp, b->ip, b->offer, 1);
  548. } else if(validip(rp->ciaddr)){
  549. /*
  550. * checking address - RENEWING or REBINDING
  551. *
  552. * these states are indistinguishable in our action. The only
  553. * difference is how close to lease expiration the client is.
  554. * If it is really close, it broadcasts the request hoping that
  555. * some server will answer.
  556. */
  557. /* check for hard assignment */
  558. if(rp->staticbinding){
  559. if(ipcmp(rp->ciaddr, rp->ii.ipaddr) != 0){
  560. warning(0, "!Request(%s via %I): %I not valid",
  561. rp->id, rp->gii.ipaddr, rp->ciaddr);
  562. sendnak(rp, "not valid");
  563. }
  564. sendack(rp, rp->ii.ipaddr, (staticlease > minlease?
  565. staticlease: minlease), 1);
  566. return;
  567. }
  568. /* make sure the network makes sense */
  569. if(!samenet(rp->ciaddr, &rp->gii)){
  570. warning(0, "!Request(%s via %I): bad forward of %I",
  571. rp->id, rp->gii.ipaddr, rp->ip);
  572. sendnak(rp, "wrong network");
  573. return;
  574. }
  575. b = iptobinding(rp->ciaddr, 0);
  576. if(b == nil){
  577. warning(0, "!Request(%s via %I): no binding for %I",
  578. rp->id, rp->gii.ipaddr, rp->ciaddr);
  579. return;
  580. }
  581. if(ipcmp(rp->ciaddr, b->ip) != 0){
  582. warning(0, "!Request(%I via %s): %I not valid",
  583. rp->id, rp->gii.ipaddr, rp->ciaddr);
  584. sendnak(rp, "invalid ip address");
  585. return;
  586. }
  587. mkoffer(b, rp->id, rp->leasetime);
  588. if(commitbinding(b) < 0){
  589. warning(0, "!Request(%s via %I): can't commit %I",
  590. rp->id, rp->gii.ipaddr, b->ip);
  591. sendnak(rp, "can't commit binding");
  592. return;
  593. }
  594. sendack(rp, b->ip, b->offer, 1);
  595. }
  596. }
  597. void
  598. rcvdecline(Req *rp)
  599. {
  600. Binding *b;
  601. char buf[64];
  602. if(rp->staticbinding)
  603. return;
  604. b = idtooffer(rp->id, &rp->gii);
  605. if(b == nil){
  606. warning(0, "!Decline(%s via %I): no binding",
  607. rp->id, rp->gii.ipaddr);
  608. return;
  609. }
  610. /* mark ip address as in use */
  611. snprint(buf, sizeof(buf), "declined by %s", rp->id);
  612. mkoffer(b, buf, 0x7fffffff);
  613. commitbinding(b);
  614. }
  615. void
  616. rcvrelease(Req *rp)
  617. {
  618. Binding *b;
  619. if(rp->staticbinding)
  620. return;
  621. b = idtobinding(rp->id, &rp->gii, 0);
  622. if(b == nil){
  623. warning(0, "!Release(%s via %I): no binding",
  624. rp->id, rp->gii.ipaddr);
  625. return;
  626. }
  627. if(strcmp(rp->id, b->boundto) != 0){
  628. warning(0, "!Release(%s via %I): invalid release of %I",
  629. rp->id, rp->gii.ipaddr, rp->ip);
  630. return;
  631. }
  632. warning(0, "Release(%s via %I): releasing %I", b->boundto, rp->gii.ipaddr, b->ip);
  633. if(releasebinding(b, rp->id) < 0)
  634. warning(0, "release: couldn't release");
  635. }
  636. void
  637. rcvinform(Req *rp)
  638. {
  639. Binding *b;
  640. if(rp->staticbinding){
  641. sendack(rp, rp->ii.ipaddr, 0, 0);
  642. return;
  643. }
  644. b = iptobinding(rp->ciaddr, 0);
  645. if(b == nil){
  646. warning(0, "!Inform(%s via %I): no binding for %I",
  647. rp->id, rp->gii.ipaddr, rp->ip);
  648. return;
  649. }
  650. sendack(rp, b->ip, 0, 0);
  651. }
  652. int
  653. setsiaddr(uint8_t *siaddr, uint8_t *saddr, uint8_t *laddr)
  654. {
  655. if(ipcmp(saddr, IPnoaddr) != 0){
  656. v6tov4(siaddr, saddr);
  657. return 0;
  658. } else {
  659. v6tov4(siaddr, laddr);
  660. return 1;
  661. }
  662. }
  663. int
  664. ismuted(Req *rp)
  665. {
  666. return mute || (mutestat && rp->staticbinding);
  667. }
  668. void
  669. sendoffer(Req *rp, uint8_t *ip, int offer)
  670. {
  671. int n;
  672. uint16_t flags;
  673. Bootp *bp;
  674. Udphdr *up;
  675. bp = rp->bp;
  676. up = rp->up;
  677. /*
  678. * set destination
  679. */
  680. flags = nhgets(bp->flags);
  681. if(validip(rp->giaddr)){
  682. ipmove(up->raddr, rp->giaddr);
  683. hnputs(up->rport, 67);
  684. } else if(flags & Fbroadcast){
  685. ipmove(up->raddr, IPv4bcast);
  686. hnputs(up->rport, 68);
  687. } else {
  688. ipmove(up->raddr, ip);
  689. if(bp->htype == 1)
  690. arpenter(up->raddr, bp->chaddr);
  691. hnputs(up->rport, 68);
  692. }
  693. /*
  694. * fill in standard bootp part
  695. */
  696. bp->op = Bootreply;
  697. bp->hops = 0;
  698. hnputs(bp->secs, 0);
  699. memset(bp->ciaddr, 0, sizeof(bp->ciaddr));
  700. v6tov4(bp->giaddr, rp->giaddr);
  701. v6tov4(bp->yiaddr, ip);
  702. setsiaddr(bp->siaddr, rp->ii.tftp, up->laddr);
  703. strncpy(bp->sname, mysysname, sizeof(bp->sname));
  704. strncpy(bp->file, rp->ii.bootf, sizeof(bp->file));
  705. /*
  706. * set options
  707. */
  708. byteopt(rp, ODtype, Offer);
  709. longopt(rp, ODlease, offer);
  710. addropt(rp, ODserverid, up->laddr);
  711. miscoptions(rp, ip);
  712. termopt(rp);
  713. logdhcpout(rp, "Offer");
  714. /*
  715. * send
  716. */
  717. n = rp->p - rp->buf;
  718. if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)
  719. warning(0, "offer: write failed: %r");
  720. }
  721. void
  722. sendack(Req *rp, uint8_t *ip, int offer, int sendlease)
  723. {
  724. int n;
  725. uint16_t flags;
  726. Bootp *bp;
  727. Udphdr *up;
  728. bp = rp->bp;
  729. up = rp->up;
  730. /*
  731. * set destination
  732. */
  733. flags = nhgets(bp->flags);
  734. if(validip(rp->giaddr)){
  735. ipmove(up->raddr, rp->giaddr);
  736. hnputs(up->rport, 67);
  737. } else if(flags & Fbroadcast){
  738. ipmove(up->raddr, IPv4bcast);
  739. hnputs(up->rport, 68);
  740. } else {
  741. ipmove(up->raddr, ip);
  742. if(bp->htype == 1)
  743. arpenter(up->raddr, bp->chaddr);
  744. hnputs(up->rport, 68);
  745. }
  746. /*
  747. * fill in standard bootp part
  748. */
  749. bp->op = Bootreply;
  750. bp->hops = 0;
  751. hnputs(bp->secs, 0);
  752. v6tov4(bp->giaddr, rp->giaddr);
  753. v6tov4(bp->yiaddr, ip);
  754. setsiaddr(bp->siaddr, rp->ii.tftp, up->laddr);
  755. strncpy(bp->sname, mysysname, sizeof(bp->sname));
  756. strncpy(bp->file, rp->ii.bootf, sizeof(bp->file));
  757. /*
  758. * set options
  759. */
  760. byteopt(rp, ODtype, Ack);
  761. if(sendlease){
  762. longopt(rp, ODlease, offer);
  763. }
  764. addropt(rp, ODserverid, up->laddr);
  765. miscoptions(rp, ip);
  766. termopt(rp);
  767. logdhcpout(rp, "Ack");
  768. /*
  769. * send
  770. */
  771. n = rp->p - rp->buf;
  772. if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)
  773. warning(0, "ack: write failed: %r");
  774. }
  775. void
  776. sendnak(Req *rp, char *msg)
  777. {
  778. int n;
  779. Bootp *bp;
  780. Udphdr *up;
  781. bp = rp->bp;
  782. up = rp->up;
  783. /*
  784. * set destination (always broadcast)
  785. */
  786. if(validip(rp->giaddr)){
  787. ipmove(up->raddr, rp->giaddr);
  788. hnputs(up->rport, 67);
  789. } else {
  790. ipmove(up->raddr, IPv4bcast);
  791. hnputs(up->rport, 68);
  792. }
  793. /*
  794. * fill in standard bootp part
  795. */
  796. bp->op = Bootreply;
  797. bp->hops = 0;
  798. hnputs(bp->secs, 0);
  799. v6tov4(bp->giaddr, rp->giaddr);
  800. memset(bp->ciaddr, 0, sizeof(bp->ciaddr));
  801. memset(bp->yiaddr, 0, sizeof(bp->yiaddr));
  802. memset(bp->siaddr, 0, sizeof(bp->siaddr));
  803. /*
  804. * set options
  805. */
  806. byteopt(rp, ODtype, Nak);
  807. addropt(rp, ODserverid, up->laddr);
  808. if(msg)
  809. stringopt(rp, ODmessage, msg);
  810. if(strncmp(rp->id, "id", 2) == 0)
  811. hexopt(rp, ODclientid, rp->id+2);
  812. termopt(rp);
  813. logdhcpout(rp, "Nak");
  814. /*
  815. * send nak
  816. */
  817. n = rp->p - rp->buf;
  818. if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)
  819. warning(0, "nak: write failed: %r");
  820. }
  821. void
  822. bootp(Req *rp)
  823. {
  824. int n;
  825. Bootp *bp;
  826. Udphdr *up;
  827. uint16_t flags;
  828. Iplifc *lifc;
  829. Info *iip;
  830. warning(0, "bootp %s %I->%I from %s via %I, file %s %s",
  831. rp->genrequest? "generic": (rp->p9request? "p9": ""),
  832. rp->up->raddr, rp->up->laddr,
  833. rp->id, rp->gii.ipaddr,
  834. rp->bp->file, rp->broadcast? "broadcast": "unicast");
  835. if(nobootp)
  836. return;
  837. bp = rp->bp;
  838. up = rp->up;
  839. iip = &rp->ii;
  840. if(rp->staticbinding == 0){
  841. warning(0, "bootp from unknown %s via %I", rp->id, rp->gii.ipaddr);
  842. return;
  843. }
  844. /* ignore if not for us */
  845. if(*bp->sname){
  846. if(strcmp(bp->sname, mysysname) != 0){
  847. bp->sname[20] = 0;
  848. warning(0, "bootp for server %s", bp->sname);
  849. return;
  850. }
  851. } else
  852. slowdelay(rp);
  853. /* ignore if we don't know what file to load */
  854. if(*bp->file == 0){
  855. if(rp->genrequest && *iip->bootf2) /* if not plan 9 & have alternate file... */
  856. strncpy(bp->file, iip->bootf2, sizeof(bp->file));
  857. else if(*iip->bootf)
  858. strncpy(bp->file, iip->bootf, sizeof(bp->file));
  859. else if(*bp->sname) /* if we were asked, respond no matter what */
  860. bp->file[0] = '\0';
  861. else {
  862. warning(0, "no bootfile for %I", iip->ipaddr);
  863. return;
  864. }
  865. }
  866. /* ignore if the file is unreadable */
  867. if((!rp->genrequest) && bp->file[0] && access(bp->file, 4) < 0){
  868. warning(0, "inaccessible bootfile1 %s", bp->file);
  869. return;
  870. }
  871. bp->op = Bootreply;
  872. v6tov4(bp->yiaddr, iip->ipaddr);
  873. if(rp->p9request){
  874. warning(0, "p9bootp: %I", iip->ipaddr);
  875. memmove(bp->optmagic, plan9opt, 4);
  876. if(iip->gwip == 0)
  877. v4tov6(iip->gwip, bp->giaddr);
  878. rp->p += sprint((char*)rp->p, "%V %I %I %I",
  879. iip->ipmask+IPv4off, iip->fsip,
  880. iip->auip, iip->gwip);
  881. sprint(optbuf, "%s", (char*)(bp->optmagic));
  882. } else if(rp->genrequest){
  883. warning(0, "genericbootp: %I", iip->ipaddr);
  884. memmove(bp->optmagic, genericopt, 4);
  885. miscoptions(rp, iip->ipaddr);
  886. termopt(rp);
  887. } else if(iip->vendor[0] != 0) {
  888. warning(0, "bootp vendor field: %s", iip->vendor);
  889. memset(rp->p, 0, 128-4);
  890. rp->p += sprint((char*)bp->optmagic, "%s", iip->vendor);
  891. } else {
  892. memset(rp->p, 0, 128-4);
  893. rp->p += 128-4;
  894. }
  895. /*
  896. * set destination
  897. */
  898. flags = nhgets(bp->flags);
  899. if(validip(rp->giaddr)){
  900. ipmove(up->raddr, rp->giaddr);
  901. hnputs(up->rport, 67);
  902. } else if(flags & Fbroadcast){
  903. ipmove(up->raddr, IPv4bcast);
  904. hnputs(up->rport, 68);
  905. } else {
  906. v4tov6(up->raddr, bp->yiaddr);
  907. if(bp->htype == 1)
  908. arpenter(up->raddr, bp->chaddr);
  909. hnputs(up->rport, 68);
  910. }
  911. /*
  912. * select best local address if destination is directly connected
  913. */
  914. lifc = findlifc(up->raddr);
  915. if(lifc)
  916. ipmove(up->laddr, lifc->ip);
  917. /*
  918. * our identity
  919. */
  920. strncpy(bp->sname, mysysname, sizeof(bp->sname));
  921. /*
  922. * set tftp server
  923. */
  924. setsiaddr(bp->siaddr, iip->tftp, up->laddr);
  925. if(rp->genrequest && *iip->bootf2)
  926. setsiaddr(bp->siaddr, iip->tftp2, up->laddr);
  927. /*
  928. * RFC 1048 says that we must pad vendor field with
  929. * zeros until we have a 64 byte field.
  930. */
  931. n = rp->p - rp->bp->optdata;
  932. if(n < 64-4) {
  933. memset(rp->p, 0, (64-4)-n);
  934. rp->p += (64-4)-n;
  935. }
  936. /*
  937. * send
  938. */
  939. n = rp->p - rp->buf;
  940. if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)
  941. warning(0, "bootp: write failed: %r");
  942. warning(0, "bootp via %I: file %s xid(%x)flag(%x)ci(%V)gi(%V)yi(%V)si(%V) %s",
  943. up->raddr, bp->file, nhgetl(bp->xid), nhgets(bp->flags),
  944. bp->ciaddr, bp->giaddr, bp->yiaddr, bp->siaddr,
  945. optbuf);
  946. }
  947. void
  948. parseoptions(Req *rp)
  949. {
  950. int n, c, code;
  951. uint8_t *o, *p;
  952. p = rp->p;
  953. while(p < rp->e){
  954. code = *p++;
  955. if(code == 255)
  956. break;
  957. if(code == 0)
  958. continue;
  959. /* ignore anything that's too long */
  960. n = *p++;
  961. o = p;
  962. p += n;
  963. if(p > rp->e)
  964. return;
  965. switch(code){
  966. case ODipaddr: /* requested ip address */
  967. if(n == IPv4addrlen)
  968. v4tov6(rp->ip, o);
  969. break;
  970. case ODlease: /* requested lease time */
  971. rp->leasetime = nhgetl(o);
  972. if(rp->leasetime > MaxLease || rp->leasetime < 0)
  973. rp->leasetime = MaxLease;
  974. break;
  975. case ODtype:
  976. c = *o;
  977. if(c < 10 && c > 0)
  978. rp->dhcptype = c;
  979. break;
  980. case ODserverid:
  981. if(n == IPv4addrlen)
  982. v4tov6(rp->server, o);
  983. break;
  984. case ODmessage:
  985. if(n > sizeof rp->msg-1)
  986. n = sizeof rp->msg-1;
  987. memmove(rp->msg, o, n);
  988. rp->msg[n] = 0;
  989. break;
  990. case ODmaxmsg:
  991. c = nhgets(o);
  992. c -= 28;
  993. c += Udphdrsize;
  994. if(c > 0)
  995. rp->max = rp->buf + c;
  996. break;
  997. case ODclientid:
  998. if(n <= 1)
  999. break;
  1000. rp->id = toid( o, n);
  1001. break;
  1002. case ODparams:
  1003. if(n > sizeof(rp->requested))
  1004. n = sizeof(rp->requested);
  1005. memmove(rp->requested, o, n);
  1006. break;
  1007. case ODvendorclass:
  1008. if(n >= sizeof(rp->vendorclass))
  1009. n = sizeof(rp->vendorclass)-1;
  1010. memmove(rp->vendorclass, o, n);
  1011. rp->vendorclass[n] = 0;
  1012. if(strncmp((char*)rp->vendorclass, "p9-", 3) == 0)
  1013. strcpy(rp->cputype,
  1014. (char*)rp->vendorclass+3);
  1015. break;
  1016. case OBend:
  1017. return;
  1018. }
  1019. }
  1020. }
  1021. void
  1022. remrequested(Req *rp, int opt)
  1023. {
  1024. uint8_t *p;
  1025. p = memchr(rp->requested, opt, sizeof(rp->requested));
  1026. if(p != nil)
  1027. *p = OBpad;
  1028. }
  1029. void
  1030. miscoptions(Req *rp, uint8_t *ip)
  1031. {
  1032. int i, j, na;
  1033. uint8_t x[2*IPaddrlen], vopts[Maxoptlen];
  1034. uint8_t *op, *omax;
  1035. uint8_t *addrs[2];
  1036. char *p;
  1037. char *attr[100], **a;
  1038. Ndbtuple *t;
  1039. addrs[0] = x;
  1040. addrs[1] = x+IPaddrlen;
  1041. /* always supply these */
  1042. maskopt(rp, OBmask, rp->gii.ipmask);
  1043. if(validip(rp->gii.gwip)){
  1044. remrequested(rp, OBrouter);
  1045. addropt(rp, OBrouter, rp->gii.gwip);
  1046. } else if(validip(rp->giaddr)){
  1047. remrequested(rp, OBrouter);
  1048. addropt(rp, OBrouter, rp->giaddr);
  1049. }
  1050. /*
  1051. * OBhostname for the HP4000M switches
  1052. * (this causes NT to log infinite errors - tough shit)
  1053. */
  1054. if(*rp->ii.domain){
  1055. remrequested(rp, OBhostname);
  1056. stringopt(rp, OBhostname, rp->ii.domain);
  1057. }
  1058. if(*rp->ii.rootpath)
  1059. stringopt(rp, OBrootpath, rp->ii.rootpath);
  1060. /* figure out what we need to lookup */
  1061. na = 0;
  1062. a = attr;
  1063. if(*rp->ii.domain == 0)
  1064. a[na++] = "dom";
  1065. for(i = 0; i < sizeof(rp->requested); i++)
  1066. switch(rp->requested[i]){
  1067. case OBrouter:
  1068. a[na++] = "@ipgw";
  1069. break;
  1070. case OBdnserver:
  1071. a[na++] = "@dns";
  1072. break;
  1073. case OBnetbiosns:
  1074. a[na++] = "@wins";
  1075. break;
  1076. case OBsmtpserver:
  1077. a[na++] = "@smtp";
  1078. break;
  1079. case OBpop3server:
  1080. a[na++] = "@pop3";
  1081. break;
  1082. case OBwwwserver:
  1083. a[na++] = "@www";
  1084. break;
  1085. case OBntpserver:
  1086. a[na++] = "@ntp";
  1087. break;
  1088. case OBtimeserver:
  1089. a[na++] = "@time";
  1090. break;
  1091. }
  1092. if(strncmp((char*)rp->vendorclass, "plan9_", 6) == 0
  1093. || strncmp((char*)rp->vendorclass, "p9-", 3) == 0){
  1094. a[na++] = "@fs";
  1095. a[na++] = "@auth";
  1096. }
  1097. t = lookupinfo(ip, a, na);
  1098. /* lookup anything we might be missing */
  1099. if(*rp->ii.domain == 0)
  1100. lookupname(rp->ii.domain, t);
  1101. /* add any requested ones that we know about */
  1102. for(i = 0; i < sizeof(rp->requested); i++)
  1103. switch(rp->requested[i]){
  1104. case OBrouter:
  1105. j = lookupserver("ipgw", addrs, t);
  1106. addrsopt(rp, OBrouter, addrs, j);
  1107. break;
  1108. case OBdnserver:
  1109. j = lookupserver("dns", addrs, t);
  1110. addrsopt(rp, OBdnserver, addrs, j);
  1111. break;
  1112. case OBhostname:
  1113. if(*rp->ii.domain)
  1114. stringopt(rp, OBhostname, rp->ii.domain);
  1115. break;
  1116. case OBdomainname:
  1117. p = strchr(rp->ii.domain, '.');
  1118. if(p)
  1119. stringopt(rp, OBdomainname, p+1);
  1120. break;
  1121. case OBnetbiosns:
  1122. j = lookupserver("wins", addrs, t);
  1123. addrsopt(rp, OBnetbiosns, addrs, j);
  1124. break;
  1125. case OBnetbiostype:
  1126. /* p-node: peer to peer WINS queries */
  1127. byteopt(rp, OBnetbiostype, 0x2);
  1128. break;
  1129. case OBsmtpserver:
  1130. j = lookupserver("smtp", addrs, t);
  1131. addrsopt(rp, OBsmtpserver, addrs, j);
  1132. break;
  1133. case OBpop3server:
  1134. j = lookupserver("pop3", addrs, t);
  1135. addrsopt(rp, OBpop3server, addrs, j);
  1136. break;
  1137. case OBwwwserver:
  1138. j = lookupserver("www", addrs, t);
  1139. addrsopt(rp, OBwwwserver, addrs, j);
  1140. break;
  1141. case OBntpserver:
  1142. j = lookupserver("ntp", addrs, t);
  1143. addrsopt(rp, OBntpserver, addrs, j);
  1144. break;
  1145. case OBtimeserver:
  1146. j = lookupserver("time", addrs, t);
  1147. addrsopt(rp, OBtimeserver, addrs, j);
  1148. break;
  1149. case OBttl:
  1150. byteopt(rp, OBttl, 255);
  1151. break;
  1152. }
  1153. /* add plan9 specific options */
  1154. if(strncmp((char*)rp->vendorclass, "plan9_", 6) == 0
  1155. || strncmp((char*)rp->vendorclass, "p9-", 3) == 0){
  1156. /* point to temporary area */
  1157. op = rp->p;
  1158. omax = rp->max;
  1159. /* stash encoded options in vopts */
  1160. rp->p = vopts;
  1161. rp->max = vopts + sizeof(vopts) - 1;
  1162. /* emit old v4 addresses first to make sure that they fit */
  1163. addrsopt(rp, OP9fsv4, addrs, lookupserver("fs", addrs, t));
  1164. addrsopt(rp, OP9authv4, addrs, lookupserver("auth", addrs, t));
  1165. p9addrsopt(rp, OP9fs, addrs, lookupserver("fs", addrs, t));
  1166. p9addrsopt(rp, OP9auth, addrs, lookupserver("auth", addrs, t));
  1167. p9addrsopt(rp, OP9ipaddr, addrs, lookupserver("ip", addrs, t));
  1168. p9addrsopt(rp, OP9ipmask, addrs, lookupserver("ipmask", addrs, t));
  1169. p9addrsopt(rp, OP9ipgw, addrs, lookupserver("ipgw", addrs, t));
  1170. /* point back to packet, encapsulate vopts into packet */
  1171. j = rp->p - vopts;
  1172. rp->p = op;
  1173. rp->max = omax;
  1174. vectoropt(rp, OBvendorinfo, vopts, j);
  1175. }
  1176. ndbfree(t);
  1177. }
  1178. int
  1179. openlisten(char *net)
  1180. {
  1181. int fd, cfd;
  1182. char data[128], devdir[40];
  1183. sprint(data, "%s/udp!*!bootp", net);
  1184. cfd = announce(data, devdir);
  1185. if(cfd < 0)
  1186. fatal(1, "can't announce");
  1187. if(fprint(cfd, "headers") < 0)
  1188. fatal(1, "can't set header mode");
  1189. sprint(data, "%s/data", devdir);
  1190. fd = open(data, ORDWR);
  1191. if(fd < 0)
  1192. fatal(1, "open udp data");
  1193. return fd;
  1194. }
  1195. void
  1196. fatal(int syserr, char *fmt, ...)
  1197. {
  1198. char buf[Maxloglen];
  1199. va_list arg;
  1200. va_start(arg, fmt);
  1201. vseprint(buf, buf+sizeof(buf), fmt, arg);
  1202. va_end(arg);
  1203. if(syserr)
  1204. syslog(1, blog, "%s: %r", buf);
  1205. else
  1206. syslog(1, blog, "%s", buf);
  1207. exits(buf);
  1208. }
  1209. void
  1210. warning(int syserr, char *fmt, ...)
  1211. {
  1212. char buf[Maxloglen];
  1213. va_list arg;
  1214. va_start(arg, fmt);
  1215. vseprint(buf, buf+sizeof(buf), fmt, arg);
  1216. va_end(arg);
  1217. if(syserr){
  1218. syslog(0, blog, "%s: %r", buf);
  1219. if(debug)
  1220. fprint(2, "%s: %r\n", buf);
  1221. } else {
  1222. syslog(0, blog, "%s", buf);
  1223. if(debug)
  1224. fprint(2, "%s\n", buf);
  1225. }
  1226. }
  1227. char*
  1228. readsysname(void)
  1229. {
  1230. static char name[128];
  1231. char *p;
  1232. int n, fd;
  1233. fd = open("/dev/sysname", OREAD);
  1234. if(fd >= 0){
  1235. n = read(fd, name, sizeof(name)-1);
  1236. close(fd);
  1237. if(n > 0){
  1238. name[n] = 0;
  1239. return name;
  1240. }
  1241. }
  1242. p = getenv("sysname");
  1243. if(p == nil || *p == 0)
  1244. return "unknown";
  1245. return p;
  1246. }
  1247. extern int
  1248. validip(uint8_t *ip)
  1249. {
  1250. if(ipcmp(ip, IPnoaddr) == 0)
  1251. return 0;
  1252. if(ipcmp(ip, v4prefix) == 0)
  1253. return 0;
  1254. return 1;
  1255. }
  1256. void
  1257. longopt(Req *rp, int t, int32_t v)
  1258. {
  1259. if(rp->p + 6 > rp->max)
  1260. return;
  1261. *rp->p++ = t;
  1262. *rp->p++ = 4;
  1263. hnputl(rp->p, v);
  1264. rp->p += 4;
  1265. op = seprint(op, oe, "%s(%ld)", optname[t], v);
  1266. }
  1267. void
  1268. addropt(Req *rp, int t, uint8_t *ip)
  1269. {
  1270. if(rp->p + 6 > rp->max)
  1271. return;
  1272. if (!isv4(ip)) {
  1273. if (debug)
  1274. warning(0, "not a v4 %s server: %I", optname[t], ip);
  1275. return;
  1276. }
  1277. *rp->p++ = t;
  1278. *rp->p++ = 4;
  1279. memmove(rp->p, ip+IPv4off, 4);
  1280. rp->p += 4;
  1281. op = seprint(op, oe, "%s(%I)", optname[t], ip);
  1282. }
  1283. void
  1284. maskopt(Req *rp, int t, uint8_t *ip)
  1285. {
  1286. if(rp->p + 6 > rp->max)
  1287. return;
  1288. *rp->p++ = t;
  1289. *rp->p++ = 4;
  1290. memmove(rp->p, ip+IPv4off, 4);
  1291. rp->p += 4;
  1292. op = seprint(op, oe, "%s(%M)", optname[t], ip);
  1293. }
  1294. void
  1295. addrsopt(Req *rp, int t, uint8_t **ip, int i)
  1296. {
  1297. int v4s, n;
  1298. if(i <= 0)
  1299. return;
  1300. if(rp->p + 2 + 4*i > rp->max)
  1301. return;
  1302. v4s = 0;
  1303. for(n = i; n-- > 0; )
  1304. if (isv4(ip[n]))
  1305. v4s++;
  1306. if (v4s <= 0) {
  1307. if (debug)
  1308. warning(0, "no v4 %s servers", optname[t]);
  1309. return;
  1310. }
  1311. *rp->p++ = t;
  1312. *rp->p++ = 4*v4s;
  1313. op = seprint(op, oe, " %s(", optname[t]);
  1314. while(i-- > 0){
  1315. if (!isv4(*ip)) {
  1316. op = seprint(op, oe, " skipping %I ", *ip);
  1317. continue;
  1318. }
  1319. v6tov4(rp->p, *ip);
  1320. rp->p += 4;
  1321. op = seprint(op, oe, "%I", *ip);
  1322. ip++;
  1323. if(i > 0)
  1324. op = seprint(op, oe, " ");
  1325. }
  1326. op = seprint(op, oe, ")");
  1327. }
  1328. void
  1329. p9addrsopt(Req *rp, int t, uint8_t **ip, int i)
  1330. {
  1331. char *pkt, *payload;
  1332. if(i <= 0 || !v6opts)
  1333. return;
  1334. pkt = (char *)rp->p;
  1335. *pkt++ = t; /* option */
  1336. pkt++; /* fill in payload length below */
  1337. payload = pkt;
  1338. *pkt++ = i; /* plan 9 address count */
  1339. op = seprint(op, oe, " %s(", optname[t]);
  1340. while(i-- > 0){
  1341. pkt = seprint(pkt, (char *)rp->max, "%I", *ip);
  1342. if ((uint8_t *)pkt+1 >= rp->max) {
  1343. op = seprint(op, oe, "<out of mem1>)");
  1344. return;
  1345. }
  1346. pkt++; /* leave NUL as terminator */
  1347. op = seprint(op, oe, "%I", *ip);
  1348. ip++;
  1349. if(i > 0)
  1350. op = seprint(op, oe, " ");
  1351. }
  1352. if ((uint8_t *)pkt - rp->p > 0377) {
  1353. op = seprint(op, oe, "<out of mem2>)");
  1354. return;
  1355. }
  1356. op = seprint(op, oe, ")");
  1357. rp->p[1] = pkt - payload; /* payload length */
  1358. rp->p = (uint8_t *)pkt;
  1359. }
  1360. void
  1361. byteopt(Req *rp, int t, uint8_t v)
  1362. {
  1363. if(rp->p + 3 > rp->max)
  1364. return;
  1365. *rp->p++ = t;
  1366. *rp->p++ = 1;
  1367. *rp->p++ = v;
  1368. op = seprint(op, oe, "%s(%d)", optname[t], v);
  1369. }
  1370. void
  1371. termopt(Req *rp)
  1372. {
  1373. if(rp->p + 1 > rp->max)
  1374. return;
  1375. *rp->p++ = OBend;
  1376. }
  1377. void
  1378. stringopt(Req *rp, int t, char *str)
  1379. {
  1380. int n;
  1381. n = strlen(str);
  1382. if(n > 255)
  1383. n = 255;
  1384. if(rp->p+n+2 > rp->max)
  1385. return;
  1386. *rp->p++ = t;
  1387. *rp->p++ = n;
  1388. memmove(rp->p, str, n);
  1389. rp->p += n;
  1390. op = seprint(op, oe, "%s(%s)", optname[t], str);
  1391. }
  1392. void
  1393. vectoropt(Req *rp, int t, uint8_t *v, int n)
  1394. {
  1395. int i;
  1396. if(n > 255) {
  1397. n = 255;
  1398. op = seprint(op, oe, "vectoropt len %d > 255 ", n);
  1399. }
  1400. if(rp->p+n+2 > rp->max)
  1401. return;
  1402. *rp->p++ = t;
  1403. *rp->p++ = n;
  1404. memmove(rp->p, v, n);
  1405. rp->p += n;
  1406. op = seprint(op, oe, "%s(", optname[t]);
  1407. if(n > 0)
  1408. op = seprint(op, oe, "%u", v[0]);
  1409. for(i = 1; i < n; i++)
  1410. op = seprint(op, oe, " %u", v[i]);
  1411. op = seprint(op, oe, ")");
  1412. }
  1413. int
  1414. fromhex(int x)
  1415. {
  1416. if(x >= '0' && x <= '9')
  1417. return x - '0';
  1418. return x - 'a';
  1419. }
  1420. void
  1421. hexopt(Req *rp, int t, char *str)
  1422. {
  1423. int n;
  1424. n = strlen(str);
  1425. n /= 2;
  1426. if(n > 255)
  1427. n = 255;
  1428. if(rp->p+n+2 > rp->max)
  1429. return;
  1430. *rp->p++ = t;
  1431. *rp->p++ = n;
  1432. while(n-- > 0){
  1433. *rp->p++ = (fromhex(str[0])<<4)|fromhex(str[1]);
  1434. str += 2;
  1435. }
  1436. op = seprint(op, oe, "%s(%s)", optname[t], str);
  1437. }
  1438. void
  1439. arpenter(uint8_t *ip, uint8_t *ether)
  1440. {
  1441. int f;
  1442. char buf[256];
  1443. sprint(buf, "%s/arp", net);
  1444. f = open(buf, OWRITE);
  1445. if(f < 0){
  1446. syslog(debug, blog, "open %s: %r", buf);
  1447. return;
  1448. }
  1449. fprint(f, "add ether %I %E", ip, ether);
  1450. close(f);
  1451. }
  1452. char *dhcpmsgname[] =
  1453. {
  1454. [Discover] "Discover",
  1455. [Offer] "Offer",
  1456. [Request] "Request",
  1457. [Decline] "Decline",
  1458. [Ack] "Ack",
  1459. [Nak] "Nak",
  1460. [Release] "Release",
  1461. [Inform] "Inform",
  1462. };
  1463. void
  1464. logdhcp(Req *rp)
  1465. {
  1466. char buf[4096];
  1467. char *p, *e;
  1468. int i;
  1469. p = buf;
  1470. e = buf + sizeof(buf);
  1471. if(rp->dhcptype > 0 && rp->dhcptype <= Inform)
  1472. p = seprint(p, e, "%s(", dhcpmsgname[rp->dhcptype]);
  1473. else
  1474. p = seprint(p, e, "%d(", rp->dhcptype);
  1475. p = seprint(p, e, "%I->%I) xid(%x)flag(%x)", rp->up->raddr, rp->up->laddr,
  1476. nhgetl(rp->bp->xid), nhgets(rp->bp->flags));
  1477. if(rp->bp->htype == 1)
  1478. p = seprint(p, e, "ea(%E)", rp->bp->chaddr);
  1479. if(validip(rp->ciaddr))
  1480. p = seprint(p, e, "ci(%I)", rp->ciaddr);
  1481. if(validip(rp->giaddr))
  1482. p = seprint(p, e, "gi(%I)", rp->giaddr);
  1483. if(validip(rp->ip))
  1484. p = seprint(p, e, "ip(%I)", rp->ip);
  1485. if(rp->id != nil)
  1486. p = seprint(p, e, "id(%s)", rp->id);
  1487. if(rp->leasetime)
  1488. p = seprint(p, e, "leas(%d)", rp->leasetime);
  1489. if(validip(rp->server))
  1490. p = seprint(p, e, "sid(%I)", rp->server);
  1491. p = seprint(p, e, "need(");
  1492. for(i = 0; i < sizeof(rp->requested); i++)
  1493. if(rp->requested[i] != 0)
  1494. p = seprint(p, e, "%s ", optname[rp->requested[i]]);
  1495. p = seprint(p, e, ")");
  1496. p = seprint(p, e, " %s", rp->broadcast? "broadcast": "unicast");
  1497. USED(p);
  1498. syslog(0, blog, "%s", buf);
  1499. }
  1500. void
  1501. logdhcpout(Req *rp, char *type)
  1502. {
  1503. syslog(0, blog, "%s(%I-%I)id(%s)ci(%V)gi(%V)yi(%V)si(%V) %s",
  1504. type, rp->up->laddr, rp->up->raddr, rp->id,
  1505. rp->bp->ciaddr, rp->bp->giaddr, rp->bp->yiaddr, rp->bp->siaddr, optbuf);
  1506. }
  1507. /*
  1508. * if we get behind, it's useless to try answering since the sender
  1509. * will probably have retransmitted with a differnt sequence number.
  1510. * So dump all but the last message in the queue.
  1511. */
  1512. void
  1513. ding(void *v, char *msg)
  1514. {
  1515. if(strstr(msg, "alarm"))
  1516. noted(NCONT);
  1517. else
  1518. noted(NDFLT);
  1519. }
  1520. int
  1521. readlast(int fd, uint8_t *buf, int len)
  1522. {
  1523. int lastn, n;
  1524. notify(ding);
  1525. lastn = 0;
  1526. for(;;){
  1527. alarm(20);
  1528. n = read(fd, buf, len);
  1529. alarm(0);
  1530. if(n < 0){
  1531. if(lastn > 0)
  1532. return lastn;
  1533. break;
  1534. }
  1535. lastn = n;
  1536. }
  1537. return read(fd, buf, len);
  1538. }