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