dhcp.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include "dat.h"
  5. #include "protos.h"
  6. enum
  7. {
  8. Maxoptlen= 312-4,
  9. /* dhcp types */
  10. Discover= 1,
  11. Offer= 2,
  12. Request= 3,
  13. Decline= 4,
  14. Ack= 5,
  15. Nak= 6,
  16. Release= 7,
  17. Inform= 8,
  18. /* bootp option types */
  19. OBend= 255,
  20. OBpad= 0,
  21. OBmask= 1,
  22. OBtimeoff= 2,
  23. OBrouter= 3,
  24. OBtimeserver= 4,
  25. OBnameserver= 5,
  26. OBdnserver= 6,
  27. OBlogserver= 7,
  28. OBcookieserver= 8,
  29. OBlprserver= 9,
  30. OBimpressserver= 10,
  31. OBrlserver= 11,
  32. OBhostname= 12, /* 0xc0 */
  33. OBbflen= 13,
  34. OBdumpfile= 14,
  35. OBdomainname= 15,
  36. OBswapserver= 16, /* 0x10 */
  37. OBrootpath= 17,
  38. OBextpath= 18,
  39. OBipforward= 19,
  40. OBnonlocal= 20,
  41. OBpolicyfilter= 21,
  42. OBmaxdatagram= 22,
  43. OBttl= 23,
  44. OBpathtimeout= 24,
  45. OBpathplateau= 25,
  46. OBmtu= 26,
  47. OBsubnetslocal= 27,
  48. OBbaddr= 28,
  49. OBdiscovermask= 29,
  50. OBsupplymask= 30,
  51. OBdiscoverrouter= 31,
  52. OBrsserver= 32, /* 0x20 */
  53. OBstaticroutes= 33,
  54. OBtrailerencap= 34,
  55. OBarptimeout= 35,
  56. OBetherencap= 36,
  57. OBtcpttl= 37,
  58. OBtcpka= 38,
  59. OBtcpkag= 39,
  60. OBnisdomain= 40,
  61. OBniserver= 41,
  62. OBntpserver= 42,
  63. OBvendorinfo= 43, /* 0x2b */
  64. OBnetbiosns= 44,
  65. OBnetbiosdds= 45,
  66. OBnetbiostype= 46,
  67. OBnetbiosscope= 47,
  68. OBxfontserver= 48, /* 0x30 */
  69. OBxdispmanager= 49,
  70. OBnisplusdomain= 64, /* 0x40 */
  71. OBnisplusserver= 65,
  72. OBhomeagent= 68,
  73. OBsmtpserver= 69,
  74. OBpop3server= 70,
  75. OBnntpserver= 71,
  76. OBwwwserver= 72,
  77. OBfingerserver= 73,
  78. OBircserver= 74,
  79. OBstserver= 75,
  80. OBstdaserver= 76,
  81. /* dhcp options */
  82. ODipaddr= 50, /* 0x32 */
  83. ODlease= 51,
  84. ODoverload= 52,
  85. ODtype= 53, /* 0x35 */
  86. ODserverid= 54, /* 0x36 */
  87. ODparams= 55, /* 0x37 */
  88. ODmessage= 56,
  89. ODmaxmsg= 57,
  90. ODrenewaltime= 58,
  91. ODrebindingtime= 59,
  92. ODvendorclass= 60,
  93. ODclientid= 61, /* 0x3d */
  94. ODtftpserver= 66,
  95. ODbootfile= 67,
  96. /* plan9 vendor info options */
  97. OP9fsv4= 128, /* plan9 file servers */
  98. OP9authv4= 129, /* plan9 auth servers */
  99. };
  100. /*
  101. * convert a byte array to hex
  102. */
  103. static char
  104. hex(int x)
  105. {
  106. if(x < 10)
  107. return x + '0';
  108. return x - 10 + 'a';
  109. }
  110. static char*
  111. phex(char *p, char *e, char *tag, uchar *o, int n)
  112. {
  113. p = seprint(p, e, "%s=", tag);
  114. for(; p+2 < e && n > 0; n--){
  115. *p++ = hex(*o >> 4);
  116. *p++ = hex(*o & 0xf);
  117. o++;
  118. }
  119. return p;
  120. }
  121. static char*
  122. pstring(char *p, char *e, char *tag, uchar *o, int n)
  123. {
  124. char msg[256];
  125. if(n > sizeof msg - 1)
  126. n = sizeof msg - 1;
  127. memmove(msg, o, n);
  128. msg[n] = 0;
  129. return seprint(p, e, "%s=%s", tag, msg);
  130. }
  131. static char*
  132. pint(char *p, char *e, char *tag, uchar *o, int n)
  133. {
  134. int x;
  135. x = *(char*)o++;
  136. for(; n > 1; n--)
  137. x = x<<8 | *o++;
  138. return seprint(p, e, "%s=%d", tag, x);
  139. }
  140. static char*
  141. puint(char *p, char *e, char *tag, uchar *o, int n)
  142. {
  143. uint x;
  144. x = *o++;
  145. for(; n > 1; n--)
  146. x = x<<8 | *o++;
  147. return seprint(p, e, "%s=%ud", tag, x);
  148. }
  149. static char*
  150. pserver(char *p, char *e, char *tag, uchar *o, int n)
  151. {
  152. p = seprint(p, e, "%s=(", tag);
  153. while(n >= 4){
  154. p = seprint(p, e, " %V", o);
  155. n -= 4;
  156. o += 4;
  157. }
  158. p = seprint(p, e, ")");
  159. return p;
  160. }
  161. static char *dhcptype[256] =
  162. {
  163. [Discover] "Discover",
  164. [Offer] "Offer",
  165. [Request] "Request",
  166. [Decline] "Decline",
  167. [Ack] "Ack",
  168. [Nak] "Nak",
  169. [Release] "Release",
  170. [Inform] "Inform",
  171. };
  172. static char*
  173. ptype(char *p, char *e, uchar val)
  174. {
  175. char *x;
  176. x = dhcptype[val];
  177. if(x != nil)
  178. return seprint(p, e, "t=%s", x);
  179. else
  180. return seprint(p, e, "t=%d", val);
  181. }
  182. static int
  183. p_seprint(Msg *m)
  184. {
  185. int i, n, code;
  186. uchar *o, *ps;
  187. char *p, *e;
  188. char msg[64];
  189. /* no next proto */
  190. m->pr = nil;
  191. p = m->p;
  192. e = m->e;
  193. ps = m->ps;
  194. while(ps < m->pe){
  195. code = *ps++;
  196. if(code == 255)
  197. break;
  198. if(code == 0)
  199. continue;
  200. /* ignore anything that's too long */
  201. n = *ps++;
  202. o = ps;
  203. ps += n;
  204. if(ps > m->pe)
  205. break;
  206. switch(code){
  207. case ODipaddr: /* requested ip address */
  208. p = pserver(p, e, "ipaddr", o, n);
  209. break;
  210. case ODlease: /* requested lease time */
  211. p = pint(p, e, "lease", o, n);
  212. break;
  213. case ODtype:
  214. p = ptype(p, e, *o);
  215. break;
  216. case ODserverid:
  217. p = pserver(p, e, "serverid", o, n);
  218. break;
  219. case ODmessage:
  220. p = pstring(p, e, "message", o, n);
  221. break;
  222. case ODmaxmsg:
  223. p = puint(p, e, "maxmsg", o, n);
  224. break;
  225. case ODclientid:
  226. p = phex(p, e, "clientid", o, n);
  227. break;
  228. case ODparams:
  229. p = seprint(p, e, " requested=(");
  230. for(i = 0; i < n; i++){
  231. if(i != 0)
  232. p = seprint(p, e, " ");
  233. p = seprint(p, e, "%ud", o[i]);
  234. }
  235. p = seprint(p, e, ")");
  236. break;
  237. case ODvendorclass:
  238. p = pstring(p, e, "vendorclass", o, n);
  239. break;
  240. case OBmask:
  241. p = pserver(p, e, "mask", o, n);
  242. break;
  243. case OBtimeoff:
  244. p = pint(p, e, "timeoff", o, n);
  245. break;
  246. case OBrouter:
  247. p = pserver(p, e, "router", o, n);
  248. break;
  249. case OBtimeserver:
  250. p = pserver(p, e, "timesrv", o, n);
  251. break;
  252. case OBnameserver:
  253. p = pserver(p, e, "namesrv", o, n);
  254. break;
  255. case OBdnserver:
  256. p = pserver(p, e, "dnssrv", o, n);
  257. break;
  258. case OBlogserver:
  259. p = pserver(p, e, "logsrv", o, n);
  260. break;
  261. case OBcookieserver:
  262. p = pserver(p, e, "cookiesrv", o, n);
  263. break;
  264. case OBlprserver:
  265. p = pserver(p, e, "lprsrv", o, n);
  266. break;
  267. case OBimpressserver:
  268. p = pserver(p, e, "impresssrv", o, n);
  269. break;
  270. case OBrlserver:
  271. p = pserver(p, e, "rlsrv", o, n);
  272. break;
  273. case OBhostname:
  274. p = pstring(p, e, "hostname", o, n);
  275. break;
  276. case OBbflen:
  277. break;
  278. case OBdumpfile:
  279. p = pstring(p, e, "dumpfile", o, n);
  280. break;
  281. case OBdomainname:
  282. p = pstring(p, e, "domname", o, n);
  283. break;
  284. case OBswapserver:
  285. p = pserver(p, e, "swapsrv", o, n);
  286. break;
  287. case OBrootpath:
  288. p = pstring(p, e, "rootpath", o, n);
  289. break;
  290. case OBextpath:
  291. p = pstring(p, e, "extpath", o, n);
  292. break;
  293. case OBipforward:
  294. p = phex(p, e, "ipforward", o, n);
  295. break;
  296. case OBnonlocal:
  297. p = phex(p, e, "nonlocal", o, n);
  298. break;
  299. case OBpolicyfilter:
  300. p = phex(p, e, "policyfilter", o, n);
  301. break;
  302. case OBmaxdatagram:
  303. p = phex(p, e, "maxdatagram", o, n);
  304. break;
  305. case OBttl:
  306. p = puint(p, e, "ttl", o, n);
  307. break;
  308. case OBpathtimeout:
  309. p = puint(p, e, "pathtimeout", o, n);
  310. break;
  311. case OBpathplateau:
  312. p = phex(p, e, "pathplateau", o, n);
  313. break;
  314. case OBmtu:
  315. p = puint(p, e, "mtu", o, n);
  316. break;
  317. case OBsubnetslocal:
  318. p = pserver(p, e, "subnet", o, n);
  319. break;
  320. case OBbaddr:
  321. p = pserver(p, e, "baddr", o, n);
  322. break;
  323. case OBdiscovermask:
  324. p = pserver(p, e, "discovermsak", o, n);
  325. break;
  326. case OBsupplymask:
  327. p = pserver(p, e, "rousupplymaskter", o, n);
  328. break;
  329. case OBdiscoverrouter:
  330. p = pserver(p, e, "discoverrouter", o, n);
  331. break;
  332. case OBrsserver:
  333. p = pserver(p, e, "rsrouter", o, n);
  334. break;
  335. case OBstaticroutes:
  336. p = phex(p, e, "staticroutes", o, n);
  337. break;
  338. case OBtrailerencap:
  339. p = phex(p, e, "trailerencap", o, n);
  340. break;
  341. case OBarptimeout:
  342. p = puint(p, e, "arptimeout", o, n);
  343. break;
  344. case OBetherencap:
  345. p = phex(p, e, "etherencap", o, n);
  346. break;
  347. case OBtcpttl:
  348. p = puint(p, e, "tcpttl", o, n);
  349. break;
  350. case OBtcpka:
  351. p = puint(p, e, "tcpka", o, n);
  352. break;
  353. case OBtcpkag:
  354. p = phex(p, e, "tcpkag", o, n);
  355. break;
  356. case OBnisdomain:
  357. p = pstring(p, e, "nisdomain", o, n);
  358. break;
  359. case OBniserver:
  360. p = pserver(p, e, "nisrv", o, n);
  361. break;
  362. case OBntpserver:
  363. p = pserver(p, e, "ntpsrv", o, n);
  364. break;
  365. case OBvendorinfo:
  366. p = phex(p, e, "vendorinfo", o, n);
  367. break;
  368. case OBnetbiosns:
  369. p = pserver(p, e, "biosns", o, n);
  370. break;
  371. case OBnetbiosdds:
  372. p = phex(p, e, "biosdds", o, n);
  373. break;
  374. case OBnetbiostype:
  375. p = phex(p, e, "biostype", o, n);
  376. break;
  377. case OBnetbiosscope:
  378. p = phex(p, e, "biosscope", o, n);
  379. break;
  380. case OBxfontserver:
  381. p = pserver(p, e, "fontsrv", o, n);
  382. break;
  383. case OBxdispmanager:
  384. p = pserver(p, e, "xdispmgr", o, n);
  385. break;
  386. case OBnisplusdomain:
  387. p = pstring(p, e, "nisplusdomain", o, n);
  388. break;
  389. case OBnisplusserver:
  390. p = pserver(p, e, "nisplussrv", o, n);
  391. break;
  392. case OBhomeagent:
  393. p = pserver(p, e, "homeagent", o, n);
  394. break;
  395. case OBsmtpserver:
  396. p = pserver(p, e, "smtpsrv", o, n);
  397. break;
  398. case OBpop3server:
  399. p = pserver(p, e, "pop3srv", o, n);
  400. break;
  401. case OBnntpserver:
  402. p = pserver(p, e, "ntpsrv", o, n);
  403. break;
  404. case OBwwwserver:
  405. p = pserver(p, e, "wwwsrv", o, n);
  406. break;
  407. case OBfingerserver:
  408. p = pserver(p, e, "fingersrv", o, n);
  409. break;
  410. case OBircserver:
  411. p = pserver(p, e, "ircsrv", o, n);
  412. break;
  413. case OBstserver:
  414. p = pserver(p, e, "stsrv", o, n);
  415. break;
  416. case OBstdaserver:
  417. p = pserver(p, e, "stdasrv", o, n);
  418. break;
  419. case OBend:
  420. goto out;
  421. default:
  422. snprint(msg, sizeof msg, " T%ud", code);
  423. p = phex(p, e, msg, o, n);
  424. break;
  425. }
  426. if(*ps != OBend)
  427. p = seprint(p, e, " ");
  428. }
  429. out:
  430. m->p = p;
  431. m->ps = ps;
  432. return 0;
  433. }
  434. Proto dhcp =
  435. {
  436. "dhcp",
  437. nil,
  438. nil,
  439. p_seprint,
  440. nil,
  441. nil,
  442. nil,
  443. defaultframer,
  444. };