dhcpd.c 34 KB

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