print-dhcp6.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. /*
  2. * Copyright (C) 1998 and 1999 WIDE Project.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the project nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /* \summary: IPv6 DHCP printer */
  30. /*
  31. * RFC3315: DHCPv6
  32. * supported DHCPv6 options:
  33. * RFC3319: Session Initiation Protocol (SIP) Servers options,
  34. * RFC3633: IPv6 Prefix options,
  35. * RFC3646: DNS Configuration options,
  36. * RFC3898: Network Information Service (NIS) Configuration options,
  37. * RFC4075: Simple Network Time Protocol (SNTP) Configuration option,
  38. * RFC4242: Information Refresh Time option,
  39. * RFC4280: Broadcast and Multicast Control Servers options,
  40. * RFC5908: Network Time Protocol (NTP) Server Option for DHCPv6
  41. * RFC6334: Dual-Stack Lite option,
  42. */
  43. #ifdef HAVE_CONFIG_H
  44. #include "config.h"
  45. #endif
  46. #include <netdissect-stdinc.h>
  47. #include <stdio.h>
  48. #include <string.h>
  49. #include "netdissect.h"
  50. #include "addrtoname.h"
  51. #include "extract.h"
  52. /* lease duration */
  53. #define DHCP6_DURATION_INFINITE 0xffffffff
  54. /* Error Values */
  55. #define DH6ERR_FAILURE 16
  56. #define DH6ERR_AUTHFAIL 17
  57. #define DH6ERR_POORLYFORMED 18
  58. #define DH6ERR_UNAVAIL 19
  59. #define DH6ERR_OPTUNAVAIL 20
  60. /* Message type */
  61. #define DH6_SOLICIT 1
  62. #define DH6_ADVERTISE 2
  63. #define DH6_REQUEST 3
  64. #define DH6_CONFIRM 4
  65. #define DH6_RENEW 5
  66. #define DH6_REBIND 6
  67. #define DH6_REPLY 7
  68. #define DH6_RELEASE 8
  69. #define DH6_DECLINE 9
  70. #define DH6_RECONFIGURE 10
  71. #define DH6_INFORM_REQ 11
  72. #define DH6_RELAY_FORW 12
  73. #define DH6_RELAY_REPLY 13
  74. #define DH6_LEASEQUERY 14
  75. #define DH6_LQ_REPLY 15
  76. static const struct tok dh6_msgtype_str[] = {
  77. { DH6_SOLICIT, "solicit" },
  78. { DH6_ADVERTISE, "advertise" },
  79. { DH6_REQUEST, "request" },
  80. { DH6_CONFIRM, "confirm" },
  81. { DH6_RENEW, "renew" },
  82. { DH6_REBIND, "rebind" },
  83. { DH6_REPLY, "reply" },
  84. { DH6_RELEASE, "release" },
  85. { DH6_DECLINE, "decline" },
  86. { DH6_RECONFIGURE, "reconfigure" },
  87. { DH6_INFORM_REQ, "inf-req" },
  88. { DH6_RELAY_FORW, "relay-fwd" },
  89. { DH6_RELAY_REPLY, "relay-reply" },
  90. { DH6_LEASEQUERY, "leasequery" },
  91. { DH6_LQ_REPLY, "leasequery-reply" },
  92. { 0, NULL }
  93. };
  94. /* DHCP6 base packet format */
  95. struct dhcp6 {
  96. union {
  97. nd_uint8_t m;
  98. nd_uint32_t x;
  99. } dh6_msgtypexid;
  100. /* options follow */
  101. };
  102. #define dh6_msgtype dh6_msgtypexid.m
  103. #define dh6_xid dh6_msgtypexid.x
  104. #define DH6_XIDMASK 0x00ffffff
  105. /* DHCPv6 relay messages */
  106. struct dhcp6_relay {
  107. nd_uint8_t dh6relay_msgtype;
  108. nd_uint8_t dh6relay_hcnt;
  109. nd_uint8_t dh6relay_linkaddr[16]; /* XXX: badly aligned */
  110. nd_uint8_t dh6relay_peeraddr[16];
  111. /* options follow */
  112. };
  113. /* options */
  114. #define DH6OPT_CLIENTID 1
  115. #define DH6OPT_SERVERID 2
  116. #define DH6OPT_IA_NA 3
  117. #define DH6OPT_IA_TA 4
  118. #define DH6OPT_IA_ADDR 5
  119. #define DH6OPT_ORO 6
  120. #define DH6OPT_PREFERENCE 7
  121. # define DH6OPT_PREF_MAX 255
  122. #define DH6OPT_ELAPSED_TIME 8
  123. #define DH6OPT_RELAY_MSG 9
  124. /*#define DH6OPT_SERVER_MSG 10 deprecated */
  125. #define DH6OPT_AUTH 11
  126. # define DH6OPT_AUTHPROTO_DELAYED 2
  127. # define DH6OPT_AUTHPROTO_RECONFIG 3
  128. # define DH6OPT_AUTHALG_HMACMD5 1
  129. # define DH6OPT_AUTHRDM_MONOCOUNTER 0
  130. # define DH6OPT_AUTHRECONFIG_KEY 1
  131. # define DH6OPT_AUTHRECONFIG_HMACMD5 2
  132. #define DH6OPT_UNICAST 12
  133. #define DH6OPT_STATUS_CODE 13
  134. # define DH6OPT_STCODE_SUCCESS 0
  135. # define DH6OPT_STCODE_UNSPECFAIL 1
  136. # define DH6OPT_STCODE_NOADDRAVAIL 2
  137. # define DH6OPT_STCODE_NOBINDING 3
  138. # define DH6OPT_STCODE_NOTONLINK 4
  139. # define DH6OPT_STCODE_USEMULTICAST 5
  140. # define DH6OPT_STCODE_NOPREFIXAVAIL 6
  141. # define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7
  142. # define DH6OPT_STCODE_MALFORMEDQUERY 8
  143. # define DH6OPT_STCODE_NOTCONFIGURED 9
  144. # define DH6OPT_STCODE_NOTALLOWED 10
  145. #define DH6OPT_RAPID_COMMIT 14
  146. #define DH6OPT_USER_CLASS 15
  147. #define DH6OPT_VENDOR_CLASS 16
  148. #define DH6OPT_VENDOR_OPTS 17
  149. #define DH6OPT_INTERFACE_ID 18
  150. #define DH6OPT_RECONF_MSG 19
  151. #define DH6OPT_RECONF_ACCEPT 20
  152. #define DH6OPT_SIP_SERVER_D 21
  153. #define DH6OPT_SIP_SERVER_A 22
  154. #define DH6OPT_DNS_SERVERS 23
  155. #define DH6OPT_DOMAIN_LIST 24
  156. #define DH6OPT_IA_PD 25
  157. #define DH6OPT_IA_PD_PREFIX 26
  158. #define DH6OPT_NIS_SERVERS 27
  159. #define DH6OPT_NISP_SERVERS 28
  160. #define DH6OPT_NIS_NAME 29
  161. #define DH6OPT_NISP_NAME 30
  162. #define DH6OPT_SNTP_SERVERS 31
  163. #define DH6OPT_LIFETIME 32
  164. #define DH6OPT_BCMCS_SERVER_D 33
  165. #define DH6OPT_BCMCS_SERVER_A 34
  166. #define DH6OPT_GEOCONF_CIVIC 36
  167. #define DH6OPT_REMOTE_ID 37
  168. #define DH6OPT_SUBSCRIBER_ID 38
  169. #define DH6OPT_CLIENT_FQDN 39
  170. #define DH6OPT_PANA_AGENT 40
  171. #define DH6OPT_NEW_POSIX_TIMEZONE 41
  172. #define DH6OPT_NEW_TZDB_TIMEZONE 42
  173. #define DH6OPT_ERO 43
  174. #define DH6OPT_LQ_QUERY 44
  175. #define DH6OPT_CLIENT_DATA 45
  176. #define DH6OPT_CLT_TIME 46
  177. #define DH6OPT_LQ_RELAY_DATA 47
  178. #define DH6OPT_LQ_CLIENT_LINK 48
  179. #define DH6OPT_NTP_SERVER 56
  180. # define DH6OPT_NTP_SUBOPTION_SRV_ADDR 1
  181. # define DH6OPT_NTP_SUBOPTION_MC_ADDR 2
  182. # define DH6OPT_NTP_SUBOPTION_SRV_FQDN 3
  183. #define DH6OPT_AFTR_NAME 64
  184. #define DH6OPT_MUDURL 112
  185. static const struct tok dh6opt_str[] = {
  186. { DH6OPT_CLIENTID, "client-ID" },
  187. { DH6OPT_SERVERID, "server-ID" },
  188. { DH6OPT_IA_NA, "IA_NA" },
  189. { DH6OPT_IA_TA, "IA_TA" },
  190. { DH6OPT_IA_ADDR, "IA_ADDR" },
  191. { DH6OPT_ORO, "option-request" },
  192. { DH6OPT_PREFERENCE, "preference" },
  193. { DH6OPT_ELAPSED_TIME, "elapsed-time" },
  194. { DH6OPT_RELAY_MSG, "relay-message" },
  195. { DH6OPT_AUTH, "authentication" },
  196. { DH6OPT_UNICAST, "server-unicast" },
  197. { DH6OPT_STATUS_CODE, "status-code" },
  198. { DH6OPT_RAPID_COMMIT, "rapid-commit" },
  199. { DH6OPT_USER_CLASS, "user-class" },
  200. { DH6OPT_VENDOR_CLASS, "vendor-class" },
  201. { DH6OPT_VENDOR_OPTS, "vendor-specific-info" },
  202. { DH6OPT_INTERFACE_ID, "interface-ID" },
  203. { DH6OPT_RECONF_MSG, "reconfigure-message" },
  204. { DH6OPT_RECONF_ACCEPT, "reconfigure-accept" },
  205. { DH6OPT_SIP_SERVER_D, "SIP-servers-domain" },
  206. { DH6OPT_SIP_SERVER_A, "SIP-servers-address" },
  207. { DH6OPT_DNS_SERVERS, "DNS-server" },
  208. { DH6OPT_DOMAIN_LIST, "DNS-search-list" },
  209. { DH6OPT_IA_PD, "IA_PD" },
  210. { DH6OPT_IA_PD_PREFIX, "IA_PD-prefix" },
  211. { DH6OPT_SNTP_SERVERS, "SNTP-servers" },
  212. { DH6OPT_LIFETIME, "lifetime" },
  213. { DH6OPT_NIS_SERVERS, "NIS-server" },
  214. { DH6OPT_NISP_SERVERS, "NIS+-server" },
  215. { DH6OPT_NIS_NAME, "NIS-domain-name" },
  216. { DH6OPT_NISP_NAME, "NIS+-domain-name" },
  217. { DH6OPT_BCMCS_SERVER_D, "BCMCS-domain-name" },
  218. { DH6OPT_BCMCS_SERVER_A, "BCMCS-server" },
  219. { DH6OPT_GEOCONF_CIVIC, "Geoconf-Civic" },
  220. { DH6OPT_REMOTE_ID, "Remote-ID" },
  221. { DH6OPT_SUBSCRIBER_ID, "Subscriber-ID" },
  222. { DH6OPT_CLIENT_FQDN, "Client-FQDN" },
  223. { DH6OPT_PANA_AGENT, "PANA-agent" },
  224. { DH6OPT_NEW_POSIX_TIMEZONE, "POSIX-timezone" },
  225. { DH6OPT_NEW_TZDB_TIMEZONE, "POSIX-tz-database" },
  226. { DH6OPT_ERO, "Echo-request-option" },
  227. { DH6OPT_LQ_QUERY, "Lease-query" },
  228. { DH6OPT_CLIENT_DATA, "LQ-client-data" },
  229. { DH6OPT_CLT_TIME, "Clt-time" },
  230. { DH6OPT_LQ_RELAY_DATA, "LQ-relay-data" },
  231. { DH6OPT_LQ_CLIENT_LINK, "LQ-client-link" },
  232. { DH6OPT_NTP_SERVER, "NTP-server" },
  233. { DH6OPT_AFTR_NAME, "AFTR-Name" },
  234. { DH6OPT_MUDURL, "MUD-URL" },
  235. { 0, NULL }
  236. };
  237. static const struct tok dh6opt_stcode_str[] = {
  238. { DH6OPT_STCODE_SUCCESS, "Success" }, /* RFC3315 */
  239. { DH6OPT_STCODE_UNSPECFAIL, "UnspecFail" }, /* RFC3315 */
  240. { DH6OPT_STCODE_NOADDRAVAIL, "NoAddrsAvail" }, /* RFC3315 */
  241. { DH6OPT_STCODE_NOBINDING, "NoBinding" }, /* RFC3315 */
  242. { DH6OPT_STCODE_NOTONLINK, "NotOnLink" }, /* RFC3315 */
  243. { DH6OPT_STCODE_USEMULTICAST, "UseMulticast" }, /* RFC3315 */
  244. { DH6OPT_STCODE_NOPREFIXAVAIL, "NoPrefixAvail" }, /* RFC3633 */
  245. { DH6OPT_STCODE_UNKNOWNQUERYTYPE, "UnknownQueryType" }, /* RFC5007 */
  246. { DH6OPT_STCODE_MALFORMEDQUERY, "MalformedQuery" }, /* RFC5007 */
  247. { DH6OPT_STCODE_NOTCONFIGURED, "NotConfigured" }, /* RFC5007 */
  248. { DH6OPT_STCODE_NOTALLOWED, "NotAllowed" }, /* RFC5007 */
  249. { 0, NULL }
  250. };
  251. struct dhcp6opt {
  252. nd_uint16_t dh6opt_type;
  253. nd_uint16_t dh6opt_len;
  254. /* type-dependent data follows */
  255. };
  256. static const char *
  257. dhcp6stcode(const uint16_t code)
  258. {
  259. return code > 255 ? "INVALID code" : tok2str(dh6opt_stcode_str, "code%u", code);
  260. }
  261. static void
  262. dhcp6opt_print(netdissect_options *ndo,
  263. const u_char *cp, const u_char *ep)
  264. {
  265. const struct dhcp6opt *dh6o;
  266. const u_char *tp;
  267. size_t i;
  268. uint16_t opttype;
  269. size_t optlen;
  270. uint8_t auth_proto;
  271. u_int authinfolen, authrealmlen;
  272. int remain_len; /* Length of remaining options */
  273. int label_len; /* Label length */
  274. uint16_t subopt_code;
  275. uint16_t subopt_len;
  276. if (cp == ep)
  277. return;
  278. while (cp < ep) {
  279. if (ep < cp + sizeof(*dh6o))
  280. goto trunc;
  281. dh6o = (const struct dhcp6opt *)cp;
  282. ND_TCHECK(*dh6o);
  283. optlen = EXTRACT_16BITS(&dh6o->dh6opt_len);
  284. if (ep < cp + sizeof(*dh6o) + optlen)
  285. goto trunc;
  286. opttype = EXTRACT_16BITS(&dh6o->dh6opt_type);
  287. ND_PRINT((ndo, " (%s", tok2str(dh6opt_str, "opt_%u", opttype)));
  288. ND_TCHECK2(*(cp + sizeof(*dh6o)), optlen);
  289. switch (opttype) {
  290. case DH6OPT_CLIENTID:
  291. case DH6OPT_SERVERID:
  292. if (optlen < 2) {
  293. /*(*/
  294. ND_PRINT((ndo, " ?)"));
  295. break;
  296. }
  297. tp = (const u_char *)(dh6o + 1);
  298. switch (EXTRACT_16BITS(tp)) {
  299. case 1:
  300. if (optlen >= 2 + 6) {
  301. ND_PRINT((ndo, " hwaddr/time type %u time %u ",
  302. EXTRACT_16BITS(&tp[2]),
  303. EXTRACT_32BITS(&tp[4])));
  304. for (i = 8; i < optlen; i++)
  305. ND_PRINT((ndo, "%02x", tp[i]));
  306. /*(*/
  307. ND_PRINT((ndo, ")"));
  308. } else {
  309. /*(*/
  310. ND_PRINT((ndo, " ?)"));
  311. }
  312. break;
  313. case 2:
  314. if (optlen >= 2 + 8) {
  315. ND_PRINT((ndo, " vid "));
  316. for (i = 2; i < 2 + 8; i++)
  317. ND_PRINT((ndo, "%02x", tp[i]));
  318. /*(*/
  319. ND_PRINT((ndo, ")"));
  320. } else {
  321. /*(*/
  322. ND_PRINT((ndo, " ?)"));
  323. }
  324. break;
  325. case 3:
  326. if (optlen >= 2 + 2) {
  327. ND_PRINT((ndo, " hwaddr type %u ",
  328. EXTRACT_16BITS(&tp[2])));
  329. for (i = 4; i < optlen; i++)
  330. ND_PRINT((ndo, "%02x", tp[i]));
  331. /*(*/
  332. ND_PRINT((ndo, ")"));
  333. } else {
  334. /*(*/
  335. ND_PRINT((ndo, " ?)"));
  336. }
  337. break;
  338. default:
  339. ND_PRINT((ndo, " type %d)", EXTRACT_16BITS(tp)));
  340. break;
  341. }
  342. break;
  343. case DH6OPT_IA_ADDR:
  344. if (optlen < 24) {
  345. /*(*/
  346. ND_PRINT((ndo, " ?)"));
  347. break;
  348. }
  349. tp = (const u_char *)(dh6o + 1);
  350. ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[0])));
  351. ND_PRINT((ndo, " pltime:%u vltime:%u",
  352. EXTRACT_32BITS(&tp[16]),
  353. EXTRACT_32BITS(&tp[20])));
  354. if (optlen > 24) {
  355. /* there are sub-options */
  356. dhcp6opt_print(ndo, tp + 24, tp + optlen);
  357. }
  358. ND_PRINT((ndo, ")"));
  359. break;
  360. case DH6OPT_ORO:
  361. case DH6OPT_ERO:
  362. if (optlen % 2) {
  363. ND_PRINT((ndo, " ?)"));
  364. break;
  365. }
  366. tp = (const u_char *)(dh6o + 1);
  367. for (i = 0; i < optlen; i += 2) {
  368. ND_PRINT((ndo, " %s",
  369. tok2str(dh6opt_str, "opt_%u", EXTRACT_16BITS(&tp[i]))));
  370. }
  371. ND_PRINT((ndo, ")"));
  372. break;
  373. case DH6OPT_PREFERENCE:
  374. if (optlen != 1) {
  375. ND_PRINT((ndo, " ?)"));
  376. break;
  377. }
  378. tp = (const u_char *)(dh6o + 1);
  379. ND_PRINT((ndo, " %d)", *tp));
  380. break;
  381. case DH6OPT_ELAPSED_TIME:
  382. if (optlen != 2) {
  383. ND_PRINT((ndo, " ?)"));
  384. break;
  385. }
  386. tp = (const u_char *)(dh6o + 1);
  387. ND_PRINT((ndo, " %d)", EXTRACT_16BITS(tp)));
  388. break;
  389. case DH6OPT_RELAY_MSG:
  390. ND_PRINT((ndo, " ("));
  391. tp = (const u_char *)(dh6o + 1);
  392. dhcp6_print(ndo, tp, optlen);
  393. ND_PRINT((ndo, ")"));
  394. break;
  395. case DH6OPT_AUTH:
  396. if (optlen < 11) {
  397. ND_PRINT((ndo, " ?)"));
  398. break;
  399. }
  400. tp = (const u_char *)(dh6o + 1);
  401. auth_proto = *tp;
  402. switch (auth_proto) {
  403. case DH6OPT_AUTHPROTO_DELAYED:
  404. ND_PRINT((ndo, " proto: delayed"));
  405. break;
  406. case DH6OPT_AUTHPROTO_RECONFIG:
  407. ND_PRINT((ndo, " proto: reconfigure"));
  408. break;
  409. default:
  410. ND_PRINT((ndo, " proto: %d", auth_proto));
  411. break;
  412. }
  413. tp++;
  414. switch (*tp) {
  415. case DH6OPT_AUTHALG_HMACMD5:
  416. /* XXX: may depend on the protocol */
  417. ND_PRINT((ndo, ", alg: HMAC-MD5"));
  418. break;
  419. default:
  420. ND_PRINT((ndo, ", alg: %d", *tp));
  421. break;
  422. }
  423. tp++;
  424. switch (*tp) {
  425. case DH6OPT_AUTHRDM_MONOCOUNTER:
  426. ND_PRINT((ndo, ", RDM: mono"));
  427. break;
  428. default:
  429. ND_PRINT((ndo, ", RDM: %d", *tp));
  430. break;
  431. }
  432. tp++;
  433. ND_PRINT((ndo, ", RD:"));
  434. for (i = 0; i < 4; i++, tp += 2)
  435. ND_PRINT((ndo, " %04x", EXTRACT_16BITS(tp)));
  436. /* protocol dependent part */
  437. authinfolen = optlen - 11;
  438. switch (auth_proto) {
  439. case DH6OPT_AUTHPROTO_DELAYED:
  440. if (authinfolen == 0)
  441. break;
  442. if (authinfolen < 20) {
  443. ND_PRINT((ndo, " ??"));
  444. break;
  445. }
  446. authrealmlen = authinfolen - 20;
  447. if (authrealmlen > 0) {
  448. ND_PRINT((ndo, ", realm: "));
  449. }
  450. for (i = 0; i < authrealmlen; i++, tp++)
  451. ND_PRINT((ndo, "%02x", *tp));
  452. ND_PRINT((ndo, ", key ID: %08x", EXTRACT_32BITS(tp)));
  453. tp += 4;
  454. ND_PRINT((ndo, ", HMAC-MD5:"));
  455. for (i = 0; i < 4; i++, tp+= 4)
  456. ND_PRINT((ndo, " %08x", EXTRACT_32BITS(tp)));
  457. break;
  458. case DH6OPT_AUTHPROTO_RECONFIG:
  459. if (authinfolen != 17) {
  460. ND_PRINT((ndo, " ??"));
  461. break;
  462. }
  463. switch (*tp++) {
  464. case DH6OPT_AUTHRECONFIG_KEY:
  465. ND_PRINT((ndo, " reconfig-key"));
  466. break;
  467. case DH6OPT_AUTHRECONFIG_HMACMD5:
  468. ND_PRINT((ndo, " type: HMAC-MD5"));
  469. break;
  470. default:
  471. ND_PRINT((ndo, " type: ??"));
  472. break;
  473. }
  474. ND_PRINT((ndo, " value:"));
  475. for (i = 0; i < 4; i++, tp+= 4)
  476. ND_PRINT((ndo, " %08x", EXTRACT_32BITS(tp)));
  477. break;
  478. default:
  479. ND_PRINT((ndo, " ??"));
  480. break;
  481. }
  482. ND_PRINT((ndo, ")"));
  483. break;
  484. case DH6OPT_RAPID_COMMIT: /* nothing todo */
  485. ND_PRINT((ndo, ")"));
  486. break;
  487. case DH6OPT_INTERFACE_ID:
  488. case DH6OPT_SUBSCRIBER_ID:
  489. /*
  490. * Since we cannot predict the encoding, print hex dump
  491. * at most 10 characters.
  492. */
  493. tp = (const u_char *)(dh6o + 1);
  494. ND_PRINT((ndo, " "));
  495. for (i = 0; i < optlen && i < 10; i++)
  496. ND_PRINT((ndo, "%02x", tp[i]));
  497. ND_PRINT((ndo, "...)"));
  498. break;
  499. case DH6OPT_RECONF_MSG:
  500. if (optlen != 1) {
  501. ND_PRINT((ndo, " ?)"));
  502. break;
  503. }
  504. tp = (const u_char *)(dh6o + 1);
  505. switch (*tp) {
  506. case DH6_RENEW:
  507. ND_PRINT((ndo, " for renew)"));
  508. break;
  509. case DH6_INFORM_REQ:
  510. ND_PRINT((ndo, " for inf-req)"));
  511. break;
  512. default:
  513. ND_PRINT((ndo, " for ?\?\?(%02x))", *tp));
  514. break;
  515. }
  516. break;
  517. case DH6OPT_RECONF_ACCEPT: /* nothing todo */
  518. ND_PRINT((ndo, ")"));
  519. break;
  520. case DH6OPT_SIP_SERVER_A:
  521. case DH6OPT_DNS_SERVERS:
  522. case DH6OPT_SNTP_SERVERS:
  523. case DH6OPT_NIS_SERVERS:
  524. case DH6OPT_NISP_SERVERS:
  525. case DH6OPT_BCMCS_SERVER_A:
  526. case DH6OPT_PANA_AGENT:
  527. case DH6OPT_LQ_CLIENT_LINK:
  528. if (optlen % 16) {
  529. ND_PRINT((ndo, " ?)"));
  530. break;
  531. }
  532. tp = (const u_char *)(dh6o + 1);
  533. for (i = 0; i < optlen; i += 16)
  534. ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[i])));
  535. ND_PRINT((ndo, ")"));
  536. break;
  537. case DH6OPT_SIP_SERVER_D:
  538. case DH6OPT_DOMAIN_LIST:
  539. tp = (const u_char *)(dh6o + 1);
  540. while (tp < cp + sizeof(*dh6o) + optlen) {
  541. ND_PRINT((ndo, " "));
  542. if ((tp = ns_nprint(ndo, tp, cp + sizeof(*dh6o) + optlen)) == NULL)
  543. goto trunc;
  544. }
  545. ND_PRINT((ndo, ")"));
  546. break;
  547. case DH6OPT_STATUS_CODE:
  548. if (optlen < 2) {
  549. ND_PRINT((ndo, " ?)"));
  550. break;
  551. }
  552. tp = (const u_char *)(dh6o + 1);
  553. ND_PRINT((ndo, " %s)", dhcp6stcode(EXTRACT_16BITS(&tp[0]))));
  554. break;
  555. case DH6OPT_IA_NA:
  556. case DH6OPT_IA_PD:
  557. if (optlen < 12) {
  558. ND_PRINT((ndo, " ?)"));
  559. break;
  560. }
  561. tp = (const u_char *)(dh6o + 1);
  562. ND_PRINT((ndo, " IAID:%u T1:%u T2:%u",
  563. EXTRACT_32BITS(&tp[0]),
  564. EXTRACT_32BITS(&tp[4]),
  565. EXTRACT_32BITS(&tp[8])));
  566. if (optlen > 12) {
  567. /* there are sub-options */
  568. dhcp6opt_print(ndo, tp + 12, tp + optlen);
  569. }
  570. ND_PRINT((ndo, ")"));
  571. break;
  572. case DH6OPT_IA_TA:
  573. if (optlen < 4) {
  574. ND_PRINT((ndo, " ?)"));
  575. break;
  576. }
  577. tp = (const u_char *)(dh6o + 1);
  578. ND_PRINT((ndo, " IAID:%u", EXTRACT_32BITS(tp)));
  579. if (optlen > 4) {
  580. /* there are sub-options */
  581. dhcp6opt_print(ndo, tp + 4, tp + optlen);
  582. }
  583. ND_PRINT((ndo, ")"));
  584. break;
  585. case DH6OPT_IA_PD_PREFIX:
  586. if (optlen < 25) {
  587. ND_PRINT((ndo, " ?)"));
  588. break;
  589. }
  590. tp = (const u_char *)(dh6o + 1);
  591. ND_PRINT((ndo, " %s/%d", ip6addr_string(ndo, &tp[9]), tp[8]));
  592. ND_PRINT((ndo, " pltime:%u vltime:%u",
  593. EXTRACT_32BITS(&tp[0]),
  594. EXTRACT_32BITS(&tp[4])));
  595. if (optlen > 25) {
  596. /* there are sub-options */
  597. dhcp6opt_print(ndo, tp + 25, tp + optlen);
  598. }
  599. ND_PRINT((ndo, ")"));
  600. break;
  601. case DH6OPT_LIFETIME:
  602. case DH6OPT_CLT_TIME:
  603. if (optlen != 4) {
  604. ND_PRINT((ndo, " ?)"));
  605. break;
  606. }
  607. tp = (const u_char *)(dh6o + 1);
  608. ND_PRINT((ndo, " %d)", EXTRACT_32BITS(tp)));
  609. break;
  610. case DH6OPT_REMOTE_ID:
  611. if (optlen < 4) {
  612. ND_PRINT((ndo, " ?)"));
  613. break;
  614. }
  615. tp = (const u_char *)(dh6o + 1);
  616. ND_PRINT((ndo, " %d ", EXTRACT_32BITS(tp)));
  617. /*
  618. * Print hex dump first 10 characters.
  619. */
  620. for (i = 4; i < optlen && i < 14; i++)
  621. ND_PRINT((ndo, "%02x", tp[i]));
  622. ND_PRINT((ndo, "...)"));
  623. break;
  624. case DH6OPT_LQ_QUERY:
  625. if (optlen < 17) {
  626. ND_PRINT((ndo, " ?)"));
  627. break;
  628. }
  629. tp = (const u_char *)(dh6o + 1);
  630. switch (*tp) {
  631. case 1:
  632. ND_PRINT((ndo, " by-address"));
  633. break;
  634. case 2:
  635. ND_PRINT((ndo, " by-clientID"));
  636. break;
  637. default:
  638. ND_PRINT((ndo, " type_%d", (int)*tp));
  639. break;
  640. }
  641. ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[1])));
  642. if (optlen > 17) {
  643. /* there are query-options */
  644. dhcp6opt_print(ndo, tp + 17, tp + optlen);
  645. }
  646. ND_PRINT((ndo, ")"));
  647. break;
  648. case DH6OPT_CLIENT_DATA:
  649. tp = (const u_char *)(dh6o + 1);
  650. if (optlen > 0) {
  651. /* there are encapsulated options */
  652. dhcp6opt_print(ndo, tp, tp + optlen);
  653. }
  654. ND_PRINT((ndo, ")"));
  655. break;
  656. case DH6OPT_LQ_RELAY_DATA:
  657. if (optlen < 16) {
  658. ND_PRINT((ndo, " ?)"));
  659. break;
  660. }
  661. tp = (const u_char *)(dh6o + 1);
  662. ND_PRINT((ndo, " %s ", ip6addr_string(ndo, &tp[0])));
  663. /*
  664. * Print hex dump first 10 characters.
  665. */
  666. for (i = 16; i < optlen && i < 26; i++)
  667. ND_PRINT((ndo, "%02x", tp[i]));
  668. ND_PRINT((ndo, "...)"));
  669. break;
  670. case DH6OPT_NTP_SERVER:
  671. if (optlen < 4) {
  672. ND_PRINT((ndo, " ?)"));
  673. break;
  674. }
  675. tp = (const u_char *)(dh6o + 1);
  676. while (tp < cp + sizeof(*dh6o) + optlen - 4) {
  677. subopt_code = EXTRACT_16BITS(tp);
  678. tp += 2;
  679. subopt_len = EXTRACT_16BITS(tp);
  680. tp += 2;
  681. if (tp + subopt_len > cp + sizeof(*dh6o) + optlen)
  682. goto trunc;
  683. ND_PRINT((ndo, " subopt:%d", subopt_code));
  684. switch (subopt_code) {
  685. case DH6OPT_NTP_SUBOPTION_SRV_ADDR:
  686. case DH6OPT_NTP_SUBOPTION_MC_ADDR:
  687. if (subopt_len != 16) {
  688. ND_PRINT((ndo, " ?"));
  689. break;
  690. }
  691. ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[0])));
  692. break;
  693. case DH6OPT_NTP_SUBOPTION_SRV_FQDN:
  694. ND_PRINT((ndo, " "));
  695. if (ns_nprint(ndo, tp, tp + subopt_len) == NULL)
  696. goto trunc;
  697. break;
  698. default:
  699. ND_PRINT((ndo, " ?"));
  700. break;
  701. }
  702. tp += subopt_len;
  703. }
  704. ND_PRINT((ndo, ")"));
  705. break;
  706. case DH6OPT_AFTR_NAME:
  707. if (optlen < 3) {
  708. ND_PRINT((ndo, " ?)"));
  709. break;
  710. }
  711. tp = (const u_char *)(dh6o + 1);
  712. remain_len = optlen;
  713. ND_PRINT((ndo, " "));
  714. /* Encoding is described in section 3.1 of RFC 1035 */
  715. while (remain_len && *tp) {
  716. label_len = *tp++;
  717. if (label_len < remain_len - 1) {
  718. (void)fn_printn(ndo, tp, label_len, NULL);
  719. tp += label_len;
  720. remain_len -= (label_len + 1);
  721. if(*tp) ND_PRINT((ndo, "."));
  722. } else {
  723. ND_PRINT((ndo, " ?"));
  724. break;
  725. }
  726. }
  727. ND_PRINT((ndo, ")"));
  728. break;
  729. case DH6OPT_NEW_POSIX_TIMEZONE: /* all three of these options */
  730. case DH6OPT_NEW_TZDB_TIMEZONE: /* are encoded similarly */
  731. case DH6OPT_MUDURL: /* although GMT might not work */
  732. if (optlen < 5) {
  733. ND_PRINT((ndo, " ?)"));
  734. break;
  735. }
  736. tp = (const u_char *)(dh6o + 1);
  737. ND_PRINT((ndo, "="));
  738. (void)fn_printn(ndo, tp, (u_int)optlen, NULL);
  739. ND_PRINT((ndo, ")"));
  740. break;
  741. default:
  742. ND_PRINT((ndo, ")"));
  743. break;
  744. }
  745. cp += sizeof(*dh6o) + optlen;
  746. }
  747. return;
  748. trunc:
  749. ND_PRINT((ndo, "[|dhcp6ext]"));
  750. }
  751. /*
  752. * Print dhcp6 packets
  753. */
  754. void
  755. dhcp6_print(netdissect_options *ndo,
  756. const u_char *cp, u_int length)
  757. {
  758. const struct dhcp6 *dh6;
  759. const struct dhcp6_relay *dh6relay;
  760. const u_char *ep;
  761. const u_char *extp;
  762. const char *name;
  763. ND_PRINT((ndo, "dhcp6"));
  764. ep = (const u_char *)ndo->ndo_snapend;
  765. if (cp + length < ep)
  766. ep = cp + length;
  767. dh6 = (const struct dhcp6 *)cp;
  768. dh6relay = (const struct dhcp6_relay *)cp;
  769. ND_TCHECK(dh6->dh6_xid);
  770. name = tok2str(dh6_msgtype_str, "msgtype-%u", dh6->dh6_msgtype);
  771. if (!ndo->ndo_vflag) {
  772. ND_PRINT((ndo, " %s", name));
  773. return;
  774. }
  775. /* XXX relay agent messages have to be handled differently */
  776. ND_PRINT((ndo, " %s (", name)); /*)*/
  777. if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
  778. dh6->dh6_msgtype != DH6_RELAY_REPLY) {
  779. ND_PRINT((ndo, "xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK));
  780. extp = (const u_char *)(dh6 + 1);
  781. dhcp6opt_print(ndo, extp, ep);
  782. } else { /* relay messages */
  783. struct in6_addr addr6;
  784. ND_TCHECK(dh6relay->dh6relay_peeraddr);
  785. memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6));
  786. ND_PRINT((ndo, "linkaddr=%s", ip6addr_string(ndo, &addr6)));
  787. memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6));
  788. ND_PRINT((ndo, " peeraddr=%s", ip6addr_string(ndo, &addr6)));
  789. dhcp6opt_print(ndo, (const u_char *)(dh6relay + 1), ep);
  790. }
  791. /*(*/
  792. ND_PRINT((ndo, ")"));
  793. return;
  794. trunc:
  795. ND_PRINT((ndo, "[|dhcp6]"));
  796. }