print-hncp.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. /*
  2. * Copyright (c) 2016 Antonin Décimo, Jean-Raphaël Gaglione
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * 3. Neither the name of the project nor the names of its contributors
  13. * may be used to endorse or promote products derived from this software
  14. * without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  20. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. */
  28. /* \summary: Home Networking Control Protocol (HNCP) printer */
  29. #ifdef HAVE_CONFIG_H
  30. #include "config.h"
  31. #endif
  32. #include <netdissect-stdinc.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include "netdissect.h"
  36. #include "addrtoname.h"
  37. #include "extract.h"
  38. static void
  39. hncp_print_rec(netdissect_options *ndo,
  40. const u_char *cp, u_int length, int indent);
  41. void
  42. hncp_print(netdissect_options *ndo,
  43. const u_char *cp, u_int length)
  44. {
  45. ND_PRINT((ndo, "hncp (%d)", length));
  46. hncp_print_rec(ndo, cp, length, 1);
  47. }
  48. /* RFC7787 */
  49. #define DNCP_REQUEST_NETWORK_STATE 1
  50. #define DNCP_REQUEST_NODE_STATE 2
  51. #define DNCP_NODE_ENDPOINT 3
  52. #define DNCP_NETWORK_STATE 4
  53. #define DNCP_NODE_STATE 5
  54. #define DNCP_PEER 8
  55. #define DNCP_KEEP_ALIVE_INTERVAL 9
  56. #define DNCP_TRUST_VERDICT 10
  57. /* RFC7788 */
  58. #define HNCP_HNCP_VERSION 32
  59. #define HNCP_EXTERNAL_CONNECTION 33
  60. #define HNCP_DELEGATED_PREFIX 34
  61. #define HNCP_PREFIX_POLICY 43
  62. #define HNCP_DHCPV4_DATA 37
  63. #define HNCP_DHCPV6_DATA 38
  64. #define HNCP_ASSIGNED_PREFIX 35
  65. #define HNCP_NODE_ADDRESS 36
  66. #define HNCP_DNS_DELEGATED_ZONE 39
  67. #define HNCP_DOMAIN_NAME 40
  68. #define HNCP_NODE_NAME 41
  69. #define HNCP_MANAGED_PSK 42
  70. /* See type_mask in hncp_print_rec below */
  71. #define RANGE_DNCP_RESERVED 0x10000
  72. #define RANGE_HNCP_UNASSIGNED 0x10001
  73. #define RANGE_DNCP_PRIVATE_USE 0x10002
  74. #define RANGE_DNCP_FUTURE_USE 0x10003
  75. static const struct tok type_values[] = {
  76. { DNCP_REQUEST_NETWORK_STATE, "Request network state" },
  77. { DNCP_REQUEST_NODE_STATE, "Request node state" },
  78. { DNCP_NODE_ENDPOINT, "Node endpoint" },
  79. { DNCP_NETWORK_STATE, "Network state" },
  80. { DNCP_NODE_STATE, "Node state" },
  81. { DNCP_PEER, "Peer" },
  82. { DNCP_KEEP_ALIVE_INTERVAL, "Keep-alive interval" },
  83. { DNCP_TRUST_VERDICT, "Trust-Verdict" },
  84. { HNCP_HNCP_VERSION, "HNCP-Version" },
  85. { HNCP_EXTERNAL_CONNECTION, "External-Connection" },
  86. { HNCP_DELEGATED_PREFIX, "Delegated-Prefix" },
  87. { HNCP_PREFIX_POLICY, "Prefix-Policy" },
  88. { HNCP_DHCPV4_DATA, "DHCPv4-Data" },
  89. { HNCP_DHCPV6_DATA, "DHCPv6-Data" },
  90. { HNCP_ASSIGNED_PREFIX, "Assigned-Prefix" },
  91. { HNCP_NODE_ADDRESS, "Node-Address" },
  92. { HNCP_DNS_DELEGATED_ZONE, "DNS-Delegated-Zone" },
  93. { HNCP_DOMAIN_NAME, "Domain-Name" },
  94. { HNCP_NODE_NAME, "Node-Name" },
  95. { HNCP_MANAGED_PSK, "Managed-PSK" },
  96. { RANGE_DNCP_RESERVED, "Reserved" },
  97. { RANGE_HNCP_UNASSIGNED, "Unassigned" },
  98. { RANGE_DNCP_PRIVATE_USE, "Private use" },
  99. { RANGE_DNCP_FUTURE_USE, "Future use" },
  100. { 0, NULL}
  101. };
  102. #define DH4OPT_DNS_SERVERS 6 /* RFC2132 */
  103. #define DH4OPT_NTP_SERVERS 42 /* RFC2132 */
  104. #define DH4OPT_DOMAIN_SEARCH 119 /* RFC3397 */
  105. static const struct tok dh4opt_str[] = {
  106. { DH4OPT_DNS_SERVERS, "DNS-server" },
  107. { DH4OPT_NTP_SERVERS, "NTP-server"},
  108. { DH4OPT_DOMAIN_SEARCH, "DNS-search" },
  109. { 0, NULL }
  110. };
  111. #define DH6OPT_DNS_SERVERS 23 /* RFC3646 */
  112. #define DH6OPT_DOMAIN_LIST 24 /* RFC3646 */
  113. #define DH6OPT_SNTP_SERVERS 31 /* RFC4075 */
  114. static const struct tok dh6opt_str[] = {
  115. { DH6OPT_DNS_SERVERS, "DNS-server" },
  116. { DH6OPT_DOMAIN_LIST, "DNS-search-list" },
  117. { DH6OPT_SNTP_SERVERS, "SNTP-servers" },
  118. { 0, NULL }
  119. };
  120. /*
  121. * For IPv4-mapped IPv6 addresses, length of the prefix that precedes
  122. * the 4 bytes of IPv4 address at the end of the IPv6 address.
  123. */
  124. #define IPV4_MAPPED_HEADING_LEN 12
  125. /*
  126. * Is an IPv6 address an IPv4-mapped address?
  127. */
  128. static inline int
  129. is_ipv4_mapped_address(const u_char *addr)
  130. {
  131. /* The value of the prefix */
  132. static const u_char ipv4_mapped_heading[IPV4_MAPPED_HEADING_LEN] =
  133. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
  134. return memcmp(addr, ipv4_mapped_heading, IPV4_MAPPED_HEADING_LEN) == 0;
  135. }
  136. static const char *
  137. format_nid(const u_char *data)
  138. {
  139. static char buf[4][11+5];
  140. static int i = 0;
  141. i = (i + 1) % 4;
  142. snprintf(buf[i], 16, "%02x:%02x:%02x:%02x",
  143. data[0], data[1], data[2], data[3]);
  144. return buf[i];
  145. }
  146. static const char *
  147. format_256(const u_char *data)
  148. {
  149. static char buf[4][64+5];
  150. static int i = 0;
  151. i = (i + 1) % 4;
  152. snprintf(buf[i], 28, "%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "%016" PRIx64,
  153. EXTRACT_64BITS(data),
  154. EXTRACT_64BITS(data + 8),
  155. EXTRACT_64BITS(data + 16),
  156. EXTRACT_64BITS(data + 24)
  157. );
  158. return buf[i];
  159. }
  160. static const char *
  161. format_interval(const uint32_t n)
  162. {
  163. static char buf[4][sizeof("0000000.000s")];
  164. static int i = 0;
  165. i = (i + 1) % 4;
  166. snprintf(buf[i], sizeof(buf[i]), "%u.%03us", n / 1000, n % 1000);
  167. return buf[i];
  168. }
  169. static const char *
  170. format_ip6addr(netdissect_options *ndo, const u_char *cp)
  171. {
  172. if (is_ipv4_mapped_address(cp))
  173. return ipaddr_string(ndo, cp + IPV4_MAPPED_HEADING_LEN);
  174. else
  175. return ip6addr_string(ndo, cp);
  176. }
  177. static int
  178. print_prefix(netdissect_options *ndo, const u_char *prefix, u_int max_length)
  179. {
  180. int plenbytes;
  181. char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx::/128")];
  182. if (prefix[0] >= 96 && max_length >= IPV4_MAPPED_HEADING_LEN + 1 &&
  183. is_ipv4_mapped_address(&prefix[1])) {
  184. struct in_addr addr;
  185. u_int plen;
  186. plen = prefix[0]-96;
  187. if (32 < plen)
  188. return -1;
  189. max_length -= 1;
  190. memset(&addr, 0, sizeof(addr));
  191. plenbytes = (plen + 7) / 8;
  192. if (max_length < (u_int)plenbytes + IPV4_MAPPED_HEADING_LEN)
  193. return -3;
  194. memcpy(&addr, &prefix[1 + IPV4_MAPPED_HEADING_LEN], plenbytes);
  195. if (plen % 8) {
  196. ((u_char *)&addr)[plenbytes - 1] &=
  197. ((0xff00 >> (plen % 8)) & 0xff);
  198. }
  199. snprintf(buf, sizeof(buf), "%s/%d", ipaddr_string(ndo, &addr), plen);
  200. plenbytes += 1 + IPV4_MAPPED_HEADING_LEN;
  201. } else {
  202. plenbytes = decode_prefix6(ndo, prefix, max_length, buf, sizeof(buf));
  203. }
  204. ND_PRINT((ndo, "%s", buf));
  205. return plenbytes;
  206. }
  207. static int
  208. print_dns_label(netdissect_options *ndo,
  209. const u_char *cp, u_int max_length, int print)
  210. {
  211. u_int length = 0;
  212. while (length < max_length) {
  213. u_int lab_length = cp[length++];
  214. if (lab_length == 0)
  215. return (int)length;
  216. if (length > 1 && print)
  217. safeputchar(ndo, '.');
  218. if (length+lab_length > max_length) {
  219. if (print)
  220. safeputs(ndo, cp+length, max_length-length);
  221. break;
  222. }
  223. if (print)
  224. safeputs(ndo, cp+length, lab_length);
  225. length += lab_length;
  226. }
  227. if (print)
  228. ND_PRINT((ndo, "[|DNS]"));
  229. return -1;
  230. }
  231. static int
  232. dhcpv4_print(netdissect_options *ndo,
  233. const u_char *cp, u_int length, int indent)
  234. {
  235. u_int i, t;
  236. const u_char *tlv, *value;
  237. uint8_t type, optlen;
  238. i = 0;
  239. while (i < length) {
  240. if (i + 2 > length)
  241. return -1;
  242. tlv = cp + i;
  243. type = (uint8_t)tlv[0];
  244. optlen = (uint8_t)tlv[1];
  245. value = tlv + 2;
  246. ND_PRINT((ndo, "\n"));
  247. for (t = indent; t > 0; t--)
  248. ND_PRINT((ndo, "\t"));
  249. ND_PRINT((ndo, "%s", tok2str(dh4opt_str, "Unknown", type)));
  250. ND_PRINT((ndo," (%u)", optlen + 2 ));
  251. if (i + 2 + optlen > length)
  252. return -1;
  253. switch (type) {
  254. case DH4OPT_DNS_SERVERS:
  255. case DH4OPT_NTP_SERVERS: {
  256. if (optlen < 4 || optlen % 4 != 0) {
  257. return -1;
  258. }
  259. for (t = 0; t < optlen; t += 4)
  260. ND_PRINT((ndo, " %s", ipaddr_string(ndo, value + t)));
  261. }
  262. break;
  263. case DH4OPT_DOMAIN_SEARCH: {
  264. const u_char *tp = value;
  265. while (tp < value + optlen) {
  266. ND_PRINT((ndo, " "));
  267. if ((tp = ns_nprint(ndo, tp, value + optlen)) == NULL)
  268. return -1;
  269. }
  270. }
  271. break;
  272. }
  273. i += 2 + optlen;
  274. }
  275. return 0;
  276. }
  277. static int
  278. dhcpv6_print(netdissect_options *ndo,
  279. const u_char *cp, u_int length, int indent)
  280. {
  281. u_int i, t;
  282. const u_char *tlv, *value;
  283. uint16_t type, optlen;
  284. i = 0;
  285. while (i < length) {
  286. if (i + 4 > length)
  287. return -1;
  288. tlv = cp + i;
  289. type = EXTRACT_16BITS(tlv);
  290. optlen = EXTRACT_16BITS(tlv + 2);
  291. value = tlv + 4;
  292. ND_PRINT((ndo, "\n"));
  293. for (t = indent; t > 0; t--)
  294. ND_PRINT((ndo, "\t"));
  295. ND_PRINT((ndo, "%s", tok2str(dh6opt_str, "Unknown", type)));
  296. ND_PRINT((ndo," (%u)", optlen + 4 ));
  297. if (i + 4 + optlen > length)
  298. return -1;
  299. switch (type) {
  300. case DH6OPT_DNS_SERVERS:
  301. case DH6OPT_SNTP_SERVERS: {
  302. if (optlen % 16 != 0) {
  303. ND_PRINT((ndo, " %s", istr));
  304. return -1;
  305. }
  306. for (t = 0; t < optlen; t += 16)
  307. ND_PRINT((ndo, " %s", ip6addr_string(ndo, value + t)));
  308. }
  309. break;
  310. case DH6OPT_DOMAIN_LIST: {
  311. const u_char *tp = value;
  312. while (tp < value + optlen) {
  313. ND_PRINT((ndo, " "));
  314. if ((tp = ns_nprint(ndo, tp, value + optlen)) == NULL)
  315. return -1;
  316. }
  317. }
  318. break;
  319. }
  320. i += 4 + optlen;
  321. }
  322. return 0;
  323. }
  324. /* Determine in-line mode */
  325. static int
  326. is_in_line(netdissect_options *ndo, int indent)
  327. {
  328. return indent - 1 >= ndo->ndo_vflag && ndo->ndo_vflag < 3;
  329. }
  330. static void
  331. print_type_in_line(netdissect_options *ndo,
  332. uint32_t type, int count, int indent, int *first_one)
  333. {
  334. if (count > 0) {
  335. if (*first_one) {
  336. *first_one = 0;
  337. if (indent > 1) {
  338. u_int t;
  339. ND_PRINT((ndo, "\n"));
  340. for (t = indent; t > 0; t--)
  341. ND_PRINT((ndo, "\t"));
  342. } else {
  343. ND_PRINT((ndo, " "));
  344. }
  345. } else {
  346. ND_PRINT((ndo, ", "));
  347. }
  348. ND_PRINT((ndo, "%s", tok2str(type_values, "Easter Egg", type)));
  349. if (count > 1)
  350. ND_PRINT((ndo, " (x%d)", count));
  351. }
  352. }
  353. void
  354. hncp_print_rec(netdissect_options *ndo,
  355. const u_char *cp, u_int length, int indent)
  356. {
  357. const int in_line = is_in_line(ndo, indent);
  358. int first_one = 1;
  359. u_int i, t;
  360. uint32_t last_type_mask = 0xffffffffU;
  361. int last_type_count = -1;
  362. const u_char *tlv, *value;
  363. uint16_t type, bodylen;
  364. uint32_t type_mask;
  365. i = 0;
  366. while (i < length) {
  367. tlv = cp + i;
  368. if (!in_line) {
  369. ND_PRINT((ndo, "\n"));
  370. for (t = indent; t > 0; t--)
  371. ND_PRINT((ndo, "\t"));
  372. }
  373. ND_TCHECK2(*tlv, 4);
  374. if (i + 4 > length)
  375. goto invalid;
  376. type = EXTRACT_16BITS(tlv);
  377. bodylen = EXTRACT_16BITS(tlv + 2);
  378. value = tlv + 4;
  379. ND_TCHECK2(*value, bodylen);
  380. if (i + bodylen + 4 > length)
  381. goto invalid;
  382. type_mask =
  383. (type == 0) ? RANGE_DNCP_RESERVED:
  384. (44 <= type && type <= 511) ? RANGE_HNCP_UNASSIGNED:
  385. (768 <= type && type <= 1023) ? RANGE_DNCP_PRIVATE_USE:
  386. RANGE_DNCP_FUTURE_USE;
  387. if (type == 6 || type == 7)
  388. type_mask = RANGE_DNCP_FUTURE_USE;
  389. /* defined types */
  390. {
  391. t = 0;
  392. while (1) {
  393. u_int key = type_values[t++].v;
  394. if (key > 0xffff)
  395. break;
  396. if (key == type) {
  397. type_mask = type;
  398. break;
  399. }
  400. }
  401. }
  402. if (in_line) {
  403. if (last_type_mask == type_mask) {
  404. last_type_count++;
  405. } else {
  406. print_type_in_line(ndo, last_type_mask, last_type_count, indent, &first_one);
  407. last_type_mask = type_mask;
  408. last_type_count = 1;
  409. }
  410. goto skip_multiline;
  411. }
  412. ND_PRINT((ndo,"%s", tok2str(type_values, "Easter Egg (42)", type_mask) ));
  413. if (type_mask > 0xffff)
  414. ND_PRINT((ndo,": type=%u", type ));
  415. ND_PRINT((ndo," (%u)", bodylen + 4 ));
  416. switch (type_mask) {
  417. case DNCP_REQUEST_NETWORK_STATE: {
  418. if (bodylen != 0)
  419. ND_PRINT((ndo, " %s", istr));
  420. }
  421. break;
  422. case DNCP_REQUEST_NODE_STATE: {
  423. const char *node_identifier;
  424. if (bodylen != 4) {
  425. ND_PRINT((ndo, " %s", istr));
  426. break;
  427. }
  428. node_identifier = format_nid(value);
  429. ND_PRINT((ndo, " NID: %s", node_identifier));
  430. }
  431. break;
  432. case DNCP_NODE_ENDPOINT: {
  433. const char *node_identifier;
  434. uint32_t endpoint_identifier;
  435. if (bodylen != 8) {
  436. ND_PRINT((ndo, " %s", istr));
  437. break;
  438. }
  439. node_identifier = format_nid(value);
  440. endpoint_identifier = EXTRACT_32BITS(value + 4);
  441. ND_PRINT((ndo, " NID: %s EPID: %08x",
  442. node_identifier,
  443. endpoint_identifier
  444. ));
  445. }
  446. break;
  447. case DNCP_NETWORK_STATE: {
  448. uint64_t hash;
  449. if (bodylen != 8) {
  450. ND_PRINT((ndo, " %s", istr));
  451. break;
  452. }
  453. hash = EXTRACT_64BITS(value);
  454. ND_PRINT((ndo, " hash: %016" PRIx64, hash));
  455. }
  456. break;
  457. case DNCP_NODE_STATE: {
  458. const char *node_identifier, *interval;
  459. uint32_t sequence_number;
  460. uint64_t hash;
  461. if (bodylen < 20) {
  462. ND_PRINT((ndo, " %s", istr));
  463. break;
  464. }
  465. node_identifier = format_nid(value);
  466. sequence_number = EXTRACT_32BITS(value + 4);
  467. interval = format_interval(EXTRACT_32BITS(value + 8));
  468. hash = EXTRACT_64BITS(value + 12);
  469. ND_PRINT((ndo, " NID: %s seqno: %u %s hash: %016" PRIx64,
  470. node_identifier,
  471. sequence_number,
  472. interval,
  473. hash
  474. ));
  475. hncp_print_rec(ndo, value+20, bodylen-20, indent+1);
  476. }
  477. break;
  478. case DNCP_PEER: {
  479. const char *peer_node_identifier;
  480. uint32_t peer_endpoint_identifier, endpoint_identifier;
  481. if (bodylen != 12) {
  482. ND_PRINT((ndo, " %s", istr));
  483. break;
  484. }
  485. peer_node_identifier = format_nid(value);
  486. peer_endpoint_identifier = EXTRACT_32BITS(value + 4);
  487. endpoint_identifier = EXTRACT_32BITS(value + 8);
  488. ND_PRINT((ndo, " Peer-NID: %s Peer-EPID: %08x Local-EPID: %08x",
  489. peer_node_identifier,
  490. peer_endpoint_identifier,
  491. endpoint_identifier
  492. ));
  493. }
  494. break;
  495. case DNCP_KEEP_ALIVE_INTERVAL: {
  496. uint32_t endpoint_identifier;
  497. const char *interval;
  498. if (bodylen < 8) {
  499. ND_PRINT((ndo, " %s", istr));
  500. break;
  501. }
  502. endpoint_identifier = EXTRACT_32BITS(value);
  503. interval = format_interval(EXTRACT_32BITS(value + 4));
  504. ND_PRINT((ndo, " EPID: %08x Interval: %s",
  505. endpoint_identifier,
  506. interval
  507. ));
  508. }
  509. break;
  510. case DNCP_TRUST_VERDICT: {
  511. if (bodylen <= 36) {
  512. ND_PRINT((ndo, " %s", istr));
  513. break;
  514. }
  515. ND_PRINT((ndo, " Verdict: %u Fingerprint: %s Common Name: ",
  516. *value,
  517. format_256(value + 4)));
  518. safeputs(ndo, value + 36, bodylen - 36);
  519. }
  520. break;
  521. case HNCP_HNCP_VERSION: {
  522. uint16_t capabilities;
  523. uint8_t M, P, H, L;
  524. if (bodylen < 5) {
  525. ND_PRINT((ndo, " %s", istr));
  526. break;
  527. }
  528. capabilities = EXTRACT_16BITS(value + 2);
  529. M = (uint8_t)((capabilities >> 12) & 0xf);
  530. P = (uint8_t)((capabilities >> 8) & 0xf);
  531. H = (uint8_t)((capabilities >> 4) & 0xf);
  532. L = (uint8_t)(capabilities & 0xf);
  533. ND_PRINT((ndo, " M: %u P: %u H: %u L: %u User-agent: ",
  534. M, P, H, L
  535. ));
  536. safeputs(ndo, value + 4, bodylen - 4);
  537. }
  538. break;
  539. case HNCP_EXTERNAL_CONNECTION: {
  540. /* Container TLV */
  541. hncp_print_rec(ndo, value, bodylen, indent+1);
  542. }
  543. break;
  544. case HNCP_DELEGATED_PREFIX: {
  545. int l;
  546. if (bodylen < 9 || bodylen < 9 + (value[8] + 7) / 8) {
  547. ND_PRINT((ndo, " %s", istr));
  548. break;
  549. }
  550. ND_PRINT((ndo, " VLSO: %s PLSO: %s Prefix: ",
  551. format_interval(EXTRACT_32BITS(value)),
  552. format_interval(EXTRACT_32BITS(value + 4))
  553. ));
  554. l = print_prefix(ndo, value + 8, bodylen - 8);
  555. if (l == -1) {
  556. ND_PRINT((ndo, "(length is invalid)"));
  557. break;
  558. }
  559. if (l < 0) {
  560. /*
  561. * We've already checked that we've captured the
  562. * entire TLV, based on its length, so this will
  563. * either be -1, meaning "the prefix length is
  564. * greater than the longest possible address of
  565. * that type" (i.e., > 32 for IPv4 or > 128 for
  566. * IPv6", or -3, meaning "the prefix runs past
  567. * the end of the TLV".
  568. */
  569. ND_PRINT((ndo, " %s", istr));
  570. break;
  571. }
  572. l += 8 + (-l & 3);
  573. if (bodylen >= l)
  574. hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
  575. }
  576. break;
  577. case HNCP_PREFIX_POLICY: {
  578. uint8_t policy;
  579. int l;
  580. if (bodylen < 1) {
  581. ND_PRINT((ndo, " %s", istr));
  582. break;
  583. }
  584. policy = value[0];
  585. ND_PRINT((ndo, " type: "));
  586. if (policy == 0) {
  587. if (bodylen != 1) {
  588. ND_PRINT((ndo, " %s", istr));
  589. break;
  590. }
  591. ND_PRINT((ndo, "Internet connectivity"));
  592. } else if (policy >= 1 && policy <= 128) {
  593. ND_PRINT((ndo, "Dest-Prefix: "));
  594. l = print_prefix(ndo, value, bodylen);
  595. if (l == -1) {
  596. ND_PRINT((ndo, "(length is invalid)"));
  597. break;
  598. }
  599. if (l < 0) {
  600. /*
  601. * We've already checked that we've captured the
  602. * entire TLV, based on its length, so this will
  603. * either be -1, meaning "the prefix length is
  604. * greater than the longest possible address of
  605. * that type" (i.e., > 32 for IPv4 or > 128 for
  606. * IPv6", or -3, meaning "the prefix runs past
  607. * the end of the TLV".
  608. */
  609. ND_PRINT((ndo, " %s", istr));
  610. break;
  611. }
  612. } else if (policy == 129) {
  613. ND_PRINT((ndo, "DNS domain: "));
  614. print_dns_label(ndo, value+1, bodylen-1, 1);
  615. } else if (policy == 130) {
  616. ND_PRINT((ndo, "Opaque UTF-8: "));
  617. safeputs(ndo, value + 1, bodylen - 1);
  618. } else if (policy == 131) {
  619. if (bodylen != 1) {
  620. ND_PRINT((ndo, " %s", istr));
  621. break;
  622. }
  623. ND_PRINT((ndo, "Restrictive assignment"));
  624. } else if (policy >= 132) {
  625. ND_PRINT((ndo, "Unknown (%u)", policy)); /* Reserved for future additions */
  626. }
  627. }
  628. break;
  629. case HNCP_DHCPV4_DATA: {
  630. if (bodylen == 0) {
  631. ND_PRINT((ndo, " %s", istr));
  632. break;
  633. }
  634. if (dhcpv4_print(ndo, value, bodylen, indent+1) != 0)
  635. goto invalid;
  636. }
  637. break;
  638. case HNCP_DHCPV6_DATA: {
  639. if (bodylen == 0) {
  640. ND_PRINT((ndo, " %s", istr));
  641. break;
  642. }
  643. if (dhcpv6_print(ndo, value, bodylen, indent+1) != 0) {
  644. ND_PRINT((ndo, " %s", istr));
  645. break;
  646. }
  647. }
  648. break;
  649. case HNCP_ASSIGNED_PREFIX: {
  650. uint8_t prty;
  651. int l;
  652. if (bodylen < 6 || bodylen < 6 + (value[5] + 7) / 8) {
  653. ND_PRINT((ndo, " %s", istr));
  654. break;
  655. }
  656. prty = (uint8_t)(value[4] & 0xf);
  657. ND_PRINT((ndo, " EPID: %08x Prty: %u",
  658. EXTRACT_32BITS(value),
  659. prty
  660. ));
  661. ND_PRINT((ndo, " Prefix: "));
  662. if ((l = print_prefix(ndo, value + 5, bodylen - 5)) < 0) {
  663. ND_PRINT((ndo, " %s", istr));
  664. break;
  665. }
  666. l += 5;
  667. l += -l & 3;
  668. if (bodylen >= l)
  669. hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
  670. }
  671. break;
  672. case HNCP_NODE_ADDRESS: {
  673. uint32_t endpoint_identifier;
  674. const char *ip_address;
  675. if (bodylen < 20) {
  676. ND_PRINT((ndo, " %s", istr));
  677. break;
  678. }
  679. endpoint_identifier = EXTRACT_32BITS(value);
  680. ip_address = format_ip6addr(ndo, value + 4);
  681. ND_PRINT((ndo, " EPID: %08x IP Address: %s",
  682. endpoint_identifier,
  683. ip_address
  684. ));
  685. hncp_print_rec(ndo, value + 20, bodylen - 20, indent+1);
  686. }
  687. break;
  688. case HNCP_DNS_DELEGATED_ZONE: {
  689. const char *ip_address;
  690. int len;
  691. if (bodylen < 17) {
  692. ND_PRINT((ndo, " %s", istr));
  693. break;
  694. }
  695. ip_address = format_ip6addr(ndo, value);
  696. ND_PRINT((ndo, " IP-Address: %s %c%c%c ",
  697. ip_address,
  698. (value[16] & 4) ? 'l' : '-',
  699. (value[16] & 2) ? 'b' : '-',
  700. (value[16] & 1) ? 's' : '-'
  701. ));
  702. len = print_dns_label(ndo, value+17, bodylen-17, 1);
  703. if (len < 0) {
  704. ND_PRINT((ndo, " %s", istr));
  705. break;
  706. }
  707. len += 17;
  708. len += -len & 3;
  709. if (bodylen >= len)
  710. hncp_print_rec(ndo, value+len, bodylen-len, indent+1);
  711. }
  712. break;
  713. case HNCP_DOMAIN_NAME: {
  714. if (bodylen == 0) {
  715. ND_PRINT((ndo, " %s", istr));
  716. break;
  717. }
  718. ND_PRINT((ndo, " Domain: "));
  719. print_dns_label(ndo, value, bodylen, 1);
  720. }
  721. break;
  722. case HNCP_NODE_NAME: {
  723. u_int l;
  724. if (bodylen < 17) {
  725. ND_PRINT((ndo, " %s", istr));
  726. break;
  727. }
  728. l = value[16];
  729. if (bodylen < 17 + l) {
  730. ND_PRINT((ndo, " %s", istr));
  731. break;
  732. }
  733. ND_PRINT((ndo, " IP-Address: %s Name: ",
  734. format_ip6addr(ndo, value)
  735. ));
  736. if (l < 64) {
  737. safeputchar(ndo, '"');
  738. safeputs(ndo, value + 17, l);
  739. safeputchar(ndo, '"');
  740. } else {
  741. ND_PRINT((ndo, "%s", istr));
  742. }
  743. l += 17;
  744. l += -l & 3;
  745. if (bodylen >= l)
  746. hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
  747. }
  748. break;
  749. case HNCP_MANAGED_PSK: {
  750. if (bodylen < 32) {
  751. ND_PRINT((ndo, " %s", istr));
  752. break;
  753. }
  754. ND_PRINT((ndo, " PSK: %s", format_256(value)));
  755. hncp_print_rec(ndo, value + 32, bodylen - 32, indent+1);
  756. }
  757. break;
  758. case RANGE_DNCP_RESERVED:
  759. case RANGE_HNCP_UNASSIGNED:
  760. case RANGE_DNCP_PRIVATE_USE:
  761. case RANGE_DNCP_FUTURE_USE:
  762. break;
  763. }
  764. skip_multiline:
  765. i += 4 + bodylen + (-bodylen & 3);
  766. }
  767. print_type_in_line(ndo, last_type_mask, last_type_count, indent, &first_one);
  768. return;
  769. trunc:
  770. ND_PRINT((ndo, "%s", "[|hncp]"));
  771. return;
  772. invalid:
  773. ND_PRINT((ndo, "%s", istr));
  774. return;
  775. }