10f74e101Schristos /* 20f74e101Schristos * Copyright (C) 1998 and 1999 WIDE Project. 30f74e101Schristos * All rights reserved. 40f74e101Schristos * 50f74e101Schristos * Redistribution and use in source and binary forms, with or without 60f74e101Schristos * modification, are permitted provided that the following conditions 70f74e101Schristos * are met: 80f74e101Schristos * 1. Redistributions of source code must retain the above copyright 90f74e101Schristos * notice, this list of conditions and the following disclaimer. 100f74e101Schristos * 2. Redistributions in binary form must reproduce the above copyright 110f74e101Schristos * notice, this list of conditions and the following disclaimer in the 120f74e101Schristos * documentation and/or other materials provided with the distribution. 130f74e101Schristos * 3. Neither the name of the project nor the names of its contributors 140f74e101Schristos * may be used to endorse or promote products derived from this software 150f74e101Schristos * without specific prior written permission. 160f74e101Schristos * 170f74e101Schristos * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 180f74e101Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 190f74e101Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 200f74e101Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 210f74e101Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 220f74e101Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 230f74e101Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 240f74e101Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 250f74e101Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 260f74e101Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 270f74e101Schristos * SUCH DAMAGE. 280f74e101Schristos */ 29dc860a36Sspz 30dc860a36Sspz /* \summary: IPv6 DHCP printer */ 31dc860a36Sspz 320f74e101Schristos /* 330f74e101Schristos * RFC3315: DHCPv6 340f74e101Schristos * supported DHCPv6 options: 35870189d2Schristos * RFC3319: Session Initiation Protocol (SIP) Servers options, 36870189d2Schristos * RFC3633: IPv6 Prefix options, 37870189d2Schristos * RFC3646: DNS Configuration options, 38870189d2Schristos * RFC3898: Network Information Service (NIS) Configuration options, 39870189d2Schristos * RFC4075: Simple Network Time Protocol (SNTP) Configuration option, 40870189d2Schristos * RFC4242: Information Refresh Time option, 41870189d2Schristos * RFC4280: Broadcast and Multicast Control Servers options, 42870189d2Schristos * RFC5908: Network Time Protocol (NTP) Server Option for DHCPv6 43870189d2Schristos * RFC6334: Dual-Stack Lite option, 440f74e101Schristos */ 450f74e101Schristos 4611b3aaa1Schristos #include <sys/cdefs.h> 470f74e101Schristos #ifndef lint 48*26ba0b50Schristos __RCSID("$NetBSD: print-dhcp6.c,v 1.10 2024/09/02 16:15:31 christos Exp $"); 490f74e101Schristos #endif 500f74e101Schristos 51c74ad251Schristos #include <config.h> 520f74e101Schristos 53c74ad251Schristos #include "netdissect-stdinc.h" 540f74e101Schristos 55fdccd7e4Schristos #include "netdissect.h" 560f74e101Schristos #include "addrtoname.h" 570f74e101Schristos #include "extract.h" 580f74e101Schristos 590f74e101Schristos /* lease duration */ 60b3a00663Schristos #define DHCP6_DURATION_INFINITE 0xffffffff 610f74e101Schristos 620f74e101Schristos /* Error Values */ 630f74e101Schristos #define DH6ERR_FAILURE 16 640f74e101Schristos #define DH6ERR_AUTHFAIL 17 650f74e101Schristos #define DH6ERR_POORLYFORMED 18 660f74e101Schristos #define DH6ERR_UNAVAIL 19 670f74e101Schristos #define DH6ERR_OPTUNAVAIL 20 680f74e101Schristos 690f74e101Schristos /* Message type */ 700f74e101Schristos #define DH6_SOLICIT 1 710f74e101Schristos #define DH6_ADVERTISE 2 720f74e101Schristos #define DH6_REQUEST 3 730f74e101Schristos #define DH6_CONFIRM 4 740f74e101Schristos #define DH6_RENEW 5 750f74e101Schristos #define DH6_REBIND 6 760f74e101Schristos #define DH6_REPLY 7 770f74e101Schristos #define DH6_RELEASE 8 780f74e101Schristos #define DH6_DECLINE 9 790f74e101Schristos #define DH6_RECONFIGURE 10 800f74e101Schristos #define DH6_INFORM_REQ 11 810f74e101Schristos #define DH6_RELAY_FORW 12 820f74e101Schristos #define DH6_RELAY_REPLY 13 830f74e101Schristos #define DH6_LEASEQUERY 14 840f74e101Schristos #define DH6_LQ_REPLY 15 850f74e101Schristos 86b3a00663Schristos static const struct tok dh6_msgtype_str[] = { 87b3a00663Schristos { DH6_SOLICIT, "solicit" }, 88b3a00663Schristos { DH6_ADVERTISE, "advertise" }, 89b3a00663Schristos { DH6_REQUEST, "request" }, 90b3a00663Schristos { DH6_CONFIRM, "confirm" }, 91b3a00663Schristos { DH6_RENEW, "renew" }, 92b3a00663Schristos { DH6_REBIND, "rebind" }, 93b3a00663Schristos { DH6_REPLY, "reply" }, 94b3a00663Schristos { DH6_RELEASE, "release" }, 95b3a00663Schristos { DH6_DECLINE, "decline" }, 96b3a00663Schristos { DH6_RECONFIGURE, "reconfigure" }, 97b3a00663Schristos { DH6_INFORM_REQ, "inf-req" }, 98b3a00663Schristos { DH6_RELAY_FORW, "relay-fwd" }, 99b3a00663Schristos { DH6_RELAY_REPLY, "relay-reply" }, 100b3a00663Schristos { DH6_LEASEQUERY, "leasequery" }, 101b3a00663Schristos { DH6_LQ_REPLY, "leasequery-reply" }, 102b3a00663Schristos { 0, NULL } 103b3a00663Schristos }; 104b3a00663Schristos 1050f74e101Schristos /* DHCP6 base packet format */ 1060f74e101Schristos struct dhcp6 { 1070f74e101Schristos union { 108c74ad251Schristos nd_uint8_t msgtype; 109c74ad251Schristos nd_uint32_t xid; 1100f74e101Schristos } dh6_msgtypexid; 1110f74e101Schristos /* options follow */ 1120f74e101Schristos }; 1130f74e101Schristos #define DH6_XIDMASK 0x00ffffff 1140f74e101Schristos 1150f74e101Schristos /* DHCPv6 relay messages */ 1160f74e101Schristos struct dhcp6_relay { 117dc860a36Sspz nd_uint8_t dh6relay_msgtype; 118dc860a36Sspz nd_uint8_t dh6relay_hcnt; 119c74ad251Schristos nd_ipv6 dh6relay_linkaddr; /* XXX: badly aligned */ 120c74ad251Schristos nd_ipv6 dh6relay_peeraddr; 1210f74e101Schristos /* options follow */ 1220f74e101Schristos }; 1230f74e101Schristos 1240f74e101Schristos /* options */ 1250f74e101Schristos #define DH6OPT_CLIENTID 1 1260f74e101Schristos #define DH6OPT_SERVERID 2 127*26ba0b50Schristos # define DUID_LLT 1 /* RFC8415 */ 128*26ba0b50Schristos # define DUID_EN 2 /* RFC8415 */ 129*26ba0b50Schristos # define DUID_LL 3 /* RFC8415 */ 130*26ba0b50Schristos # define DUID_UUID 4 /* RFC6355 */ 1310f74e101Schristos #define DH6OPT_IA_NA 3 1320f74e101Schristos #define DH6OPT_IA_TA 4 1330f74e101Schristos #define DH6OPT_IA_ADDR 5 1340f74e101Schristos #define DH6OPT_ORO 6 1350f74e101Schristos #define DH6OPT_PREFERENCE 7 1360f74e101Schristos # define DH6OPT_PREF_MAX 255 1370f74e101Schristos #define DH6OPT_ELAPSED_TIME 8 1380f74e101Schristos #define DH6OPT_RELAY_MSG 9 1390f74e101Schristos /*#define DH6OPT_SERVER_MSG 10 deprecated */ 1400f74e101Schristos #define DH6OPT_AUTH 11 1410f74e101Schristos # define DH6OPT_AUTHPROTO_DELAYED 2 1420f74e101Schristos # define DH6OPT_AUTHPROTO_RECONFIG 3 1430f74e101Schristos # define DH6OPT_AUTHALG_HMACMD5 1 1440f74e101Schristos # define DH6OPT_AUTHRDM_MONOCOUNTER 0 1450f74e101Schristos # define DH6OPT_AUTHRECONFIG_KEY 1 1460f74e101Schristos # define DH6OPT_AUTHRECONFIG_HMACMD5 2 1470f74e101Schristos #define DH6OPT_UNICAST 12 1480f74e101Schristos #define DH6OPT_STATUS_CODE 13 1490f74e101Schristos # define DH6OPT_STCODE_SUCCESS 0 1500f74e101Schristos # define DH6OPT_STCODE_UNSPECFAIL 1 1510f74e101Schristos # define DH6OPT_STCODE_NOADDRAVAIL 2 1520f74e101Schristos # define DH6OPT_STCODE_NOBINDING 3 1530f74e101Schristos # define DH6OPT_STCODE_NOTONLINK 4 1540f74e101Schristos # define DH6OPT_STCODE_USEMULTICAST 5 1550f74e101Schristos # define DH6OPT_STCODE_NOPREFIXAVAIL 6 1560f74e101Schristos # define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7 1570f74e101Schristos # define DH6OPT_STCODE_MALFORMEDQUERY 8 1580f74e101Schristos # define DH6OPT_STCODE_NOTCONFIGURED 9 1590f74e101Schristos # define DH6OPT_STCODE_NOTALLOWED 10 1600f74e101Schristos #define DH6OPT_RAPID_COMMIT 14 1610f74e101Schristos #define DH6OPT_USER_CLASS 15 1620f74e101Schristos #define DH6OPT_VENDOR_CLASS 16 1630f74e101Schristos #define DH6OPT_VENDOR_OPTS 17 1640f74e101Schristos #define DH6OPT_INTERFACE_ID 18 1650f74e101Schristos #define DH6OPT_RECONF_MSG 19 1660f74e101Schristos #define DH6OPT_RECONF_ACCEPT 20 1670f74e101Schristos #define DH6OPT_SIP_SERVER_D 21 1680f74e101Schristos #define DH6OPT_SIP_SERVER_A 22 169870189d2Schristos #define DH6OPT_DNS_SERVERS 23 170870189d2Schristos #define DH6OPT_DOMAIN_LIST 24 1710f74e101Schristos #define DH6OPT_IA_PD 25 1720f74e101Schristos #define DH6OPT_IA_PD_PREFIX 26 1730f74e101Schristos #define DH6OPT_NIS_SERVERS 27 1740f74e101Schristos #define DH6OPT_NISP_SERVERS 28 1750f74e101Schristos #define DH6OPT_NIS_NAME 29 1760f74e101Schristos #define DH6OPT_NISP_NAME 30 177870189d2Schristos #define DH6OPT_SNTP_SERVERS 31 1780f74e101Schristos #define DH6OPT_LIFETIME 32 1790f74e101Schristos #define DH6OPT_BCMCS_SERVER_D 33 1800f74e101Schristos #define DH6OPT_BCMCS_SERVER_A 34 1810f74e101Schristos #define DH6OPT_GEOCONF_CIVIC 36 1820f74e101Schristos #define DH6OPT_REMOTE_ID 37 1830f74e101Schristos #define DH6OPT_SUBSCRIBER_ID 38 1840f74e101Schristos #define DH6OPT_CLIENT_FQDN 39 1850f74e101Schristos #define DH6OPT_PANA_AGENT 40 1860f74e101Schristos #define DH6OPT_NEW_POSIX_TIMEZONE 41 1870f74e101Schristos #define DH6OPT_NEW_TZDB_TIMEZONE 42 1880f74e101Schristos #define DH6OPT_ERO 43 1890f74e101Schristos #define DH6OPT_LQ_QUERY 44 1900f74e101Schristos #define DH6OPT_CLIENT_DATA 45 1910f74e101Schristos #define DH6OPT_CLT_TIME 46 1920f74e101Schristos #define DH6OPT_LQ_RELAY_DATA 47 1930f74e101Schristos #define DH6OPT_LQ_CLIENT_LINK 48 194870189d2Schristos #define DH6OPT_NTP_SERVER 56 195870189d2Schristos # define DH6OPT_NTP_SUBOPTION_SRV_ADDR 1 196870189d2Schristos # define DH6OPT_NTP_SUBOPTION_MC_ADDR 2 197870189d2Schristos # define DH6OPT_NTP_SUBOPTION_SRV_FQDN 3 198*26ba0b50Schristos #define DH6OPT_BOOTFILE_URL 59 /* RFC5970 */ 199870189d2Schristos #define DH6OPT_AFTR_NAME 64 200dc860a36Sspz #define DH6OPT_MUDURL 112 201*26ba0b50Schristos #define DH6OPT_SZTP_REDIRECT 136 /* RFC8572 */ 2020f74e101Schristos 203b3a00663Schristos static const struct tok dh6opt_str[] = { 204b3a00663Schristos { DH6OPT_CLIENTID, "client-ID" }, 205b3a00663Schristos { DH6OPT_SERVERID, "server-ID" }, 206b3a00663Schristos { DH6OPT_IA_NA, "IA_NA" }, 207b3a00663Schristos { DH6OPT_IA_TA, "IA_TA" }, 208b3a00663Schristos { DH6OPT_IA_ADDR, "IA_ADDR" }, 209b3a00663Schristos { DH6OPT_ORO, "option-request" }, 210b3a00663Schristos { DH6OPT_PREFERENCE, "preference" }, 211b3a00663Schristos { DH6OPT_ELAPSED_TIME, "elapsed-time" }, 212b3a00663Schristos { DH6OPT_RELAY_MSG, "relay-message" }, 213b3a00663Schristos { DH6OPT_AUTH, "authentication" }, 214b3a00663Schristos { DH6OPT_UNICAST, "server-unicast" }, 215b3a00663Schristos { DH6OPT_STATUS_CODE, "status-code" }, 216b3a00663Schristos { DH6OPT_RAPID_COMMIT, "rapid-commit" }, 217b3a00663Schristos { DH6OPT_USER_CLASS, "user-class" }, 218b3a00663Schristos { DH6OPT_VENDOR_CLASS, "vendor-class" }, 219b3a00663Schristos { DH6OPT_VENDOR_OPTS, "vendor-specific-info" }, 220b3a00663Schristos { DH6OPT_INTERFACE_ID, "interface-ID" }, 221b3a00663Schristos { DH6OPT_RECONF_MSG, "reconfigure-message" }, 222b3a00663Schristos { DH6OPT_RECONF_ACCEPT, "reconfigure-accept" }, 223b3a00663Schristos { DH6OPT_SIP_SERVER_D, "SIP-servers-domain" }, 224b3a00663Schristos { DH6OPT_SIP_SERVER_A, "SIP-servers-address" }, 225b3a00663Schristos { DH6OPT_DNS_SERVERS, "DNS-server" }, 226b3a00663Schristos { DH6OPT_DOMAIN_LIST, "DNS-search-list" }, 227b3a00663Schristos { DH6OPT_IA_PD, "IA_PD" }, 228b3a00663Schristos { DH6OPT_IA_PD_PREFIX, "IA_PD-prefix" }, 229b3a00663Schristos { DH6OPT_SNTP_SERVERS, "SNTP-servers" }, 230b3a00663Schristos { DH6OPT_LIFETIME, "lifetime" }, 231b3a00663Schristos { DH6OPT_NIS_SERVERS, "NIS-server" }, 232b3a00663Schristos { DH6OPT_NISP_SERVERS, "NIS+-server" }, 233b3a00663Schristos { DH6OPT_NIS_NAME, "NIS-domain-name" }, 234b3a00663Schristos { DH6OPT_NISP_NAME, "NIS+-domain-name" }, 235b3a00663Schristos { DH6OPT_BCMCS_SERVER_D, "BCMCS-domain-name" }, 236b3a00663Schristos { DH6OPT_BCMCS_SERVER_A, "BCMCS-server" }, 237b3a00663Schristos { DH6OPT_GEOCONF_CIVIC, "Geoconf-Civic" }, 238b3a00663Schristos { DH6OPT_REMOTE_ID, "Remote-ID" }, 239b3a00663Schristos { DH6OPT_SUBSCRIBER_ID, "Subscriber-ID" }, 240b3a00663Schristos { DH6OPT_CLIENT_FQDN, "Client-FQDN" }, 241b3a00663Schristos { DH6OPT_PANA_AGENT, "PANA-agent" }, 242b3a00663Schristos { DH6OPT_NEW_POSIX_TIMEZONE, "POSIX-timezone" }, 243b3a00663Schristos { DH6OPT_NEW_TZDB_TIMEZONE, "POSIX-tz-database" }, 244b3a00663Schristos { DH6OPT_ERO, "Echo-request-option" }, 245b3a00663Schristos { DH6OPT_LQ_QUERY, "Lease-query" }, 246b3a00663Schristos { DH6OPT_CLIENT_DATA, "LQ-client-data" }, 247b3a00663Schristos { DH6OPT_CLT_TIME, "Clt-time" }, 248b3a00663Schristos { DH6OPT_LQ_RELAY_DATA, "LQ-relay-data" }, 249b3a00663Schristos { DH6OPT_LQ_CLIENT_LINK, "LQ-client-link" }, 250b3a00663Schristos { DH6OPT_NTP_SERVER, "NTP-server" }, 251*26ba0b50Schristos { DH6OPT_BOOTFILE_URL, "Bootfile-URL" }, 252b3a00663Schristos { DH6OPT_AFTR_NAME, "AFTR-Name" }, 253dc860a36Sspz { DH6OPT_MUDURL, "MUD-URL" }, 254*26ba0b50Schristos { DH6OPT_SZTP_REDIRECT, "SZTP-redirect" }, 255b3a00663Schristos { 0, NULL } 256b3a00663Schristos }; 257b3a00663Schristos 258b3a00663Schristos static const struct tok dh6opt_stcode_str[] = { 259fdccd7e4Schristos { DH6OPT_STCODE_SUCCESS, "Success" }, /* RFC3315 */ 260fdccd7e4Schristos { DH6OPT_STCODE_UNSPECFAIL, "UnspecFail" }, /* RFC3315 */ 261fdccd7e4Schristos { DH6OPT_STCODE_NOADDRAVAIL, "NoAddrsAvail" }, /* RFC3315 */ 262fdccd7e4Schristos { DH6OPT_STCODE_NOBINDING, "NoBinding" }, /* RFC3315 */ 263fdccd7e4Schristos { DH6OPT_STCODE_NOTONLINK, "NotOnLink" }, /* RFC3315 */ 264fdccd7e4Schristos { DH6OPT_STCODE_USEMULTICAST, "UseMulticast" }, /* RFC3315 */ 265fdccd7e4Schristos { DH6OPT_STCODE_NOPREFIXAVAIL, "NoPrefixAvail" }, /* RFC3633 */ 266fdccd7e4Schristos { DH6OPT_STCODE_UNKNOWNQUERYTYPE, "UnknownQueryType" }, /* RFC5007 */ 267fdccd7e4Schristos { DH6OPT_STCODE_MALFORMEDQUERY, "MalformedQuery" }, /* RFC5007 */ 268fdccd7e4Schristos { DH6OPT_STCODE_NOTCONFIGURED, "NotConfigured" }, /* RFC5007 */ 269fdccd7e4Schristos { DH6OPT_STCODE_NOTALLOWED, "NotAllowed" }, /* RFC5007 */ 270b3a00663Schristos { 0, NULL } 271b3a00663Schristos }; 272b3a00663Schristos 2730f74e101Schristos struct dhcp6opt { 274dc860a36Sspz nd_uint16_t dh6opt_type; 275dc860a36Sspz nd_uint16_t dh6opt_len; 2760f74e101Schristos /* type-dependent data follows */ 2770f74e101Schristos }; 2780f74e101Schristos 2790f74e101Schristos static const char * 280b3a00663Schristos dhcp6stcode(const uint16_t code) 2810f74e101Schristos { 282b3a00663Schristos return code > 255 ? "INVALID code" : tok2str(dh6opt_stcode_str, "code%u", code); 2830f74e101Schristos } 2840f74e101Schristos 2850f74e101Schristos static void 286b3a00663Schristos dhcp6opt_print(netdissect_options *ndo, 287b3a00663Schristos const u_char *cp, const u_char *ep) 2880f74e101Schristos { 289870189d2Schristos const struct dhcp6opt *dh6o; 290870189d2Schristos const u_char *tp; 291c74ad251Schristos u_int i; 292b3a00663Schristos uint16_t opttype; 293c74ad251Schristos uint16_t optlen; 294b3a00663Schristos uint8_t auth_proto; 295c74ad251Schristos uint8_t auth_alg; 296c74ad251Schristos uint8_t auth_rdm; 2970f74e101Schristos u_int authinfolen, authrealmlen; 298c74ad251Schristos u_int remain_len; /* Length of remaining options */ 299c74ad251Schristos u_int label_len; /* Label length */ 300b3a00663Schristos uint16_t subopt_code; 301b3a00663Schristos uint16_t subopt_len; 302c74ad251Schristos uint8_t dh6_reconf_type; 303c74ad251Schristos uint8_t dh6_lq_query_type; 304*26ba0b50Schristos u_int first_list_value; 305*26ba0b50Schristos uint16_t remainder_len; 3060f74e101Schristos 3070f74e101Schristos if (cp == ep) 3080f74e101Schristos return; 3090f74e101Schristos while (cp < ep) { 3100f74e101Schristos if (ep < cp + sizeof(*dh6o)) 3110f74e101Schristos goto trunc; 312fdccd7e4Schristos dh6o = (const struct dhcp6opt *)cp; 313c74ad251Schristos ND_TCHECK_SIZE(dh6o); 314c74ad251Schristos optlen = GET_BE_U_2(dh6o->dh6opt_len); 3150f74e101Schristos if (ep < cp + sizeof(*dh6o) + optlen) 3160f74e101Schristos goto trunc; 317c74ad251Schristos opttype = GET_BE_U_2(dh6o->dh6opt_type); 318c74ad251Schristos ND_PRINT(" (%s", tok2str(dh6opt_str, "opt_%u", opttype)); 319c74ad251Schristos ND_TCHECK_LEN(cp + sizeof(*dh6o), optlen); 3200f74e101Schristos switch (opttype) { 3210f74e101Schristos case DH6OPT_CLIENTID: 3220f74e101Schristos case DH6OPT_SERVERID: 3230f74e101Schristos if (optlen < 2) { 3240f74e101Schristos /*(*/ 325c74ad251Schristos ND_PRINT(" ?)"); 3260f74e101Schristos break; 3270f74e101Schristos } 328fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 329c74ad251Schristos switch (GET_BE_U_2(tp)) { 330*26ba0b50Schristos case DUID_LLT: 3310f74e101Schristos if (optlen >= 2 + 6) { 332c74ad251Schristos ND_PRINT(" hwaddr/time type %u time %u ", 333c74ad251Schristos GET_BE_U_2(tp + 2), 334c74ad251Schristos GET_BE_U_4(tp + 4)); 3350f74e101Schristos for (i = 8; i < optlen; i++) 336c74ad251Schristos ND_PRINT("%02x", 337c74ad251Schristos GET_U_1(tp + i)); 3380f74e101Schristos /*(*/ 339c74ad251Schristos ND_PRINT(")"); 3400f74e101Schristos } else { 3410f74e101Schristos /*(*/ 342c74ad251Schristos ND_PRINT(" ?)"); 3430f74e101Schristos } 3440f74e101Schristos break; 345*26ba0b50Schristos case DUID_EN: 346*26ba0b50Schristos if (optlen >= 2 + 4) { 347*26ba0b50Schristos ND_PRINT(" enterprise %u ", GET_BE_U_4(tp + 2)); 348*26ba0b50Schristos for (i = 2 + 4; i < optlen; i++) 349c74ad251Schristos ND_PRINT("%02x", 350c74ad251Schristos GET_U_1(tp + i)); 3510f74e101Schristos /*(*/ 352c74ad251Schristos ND_PRINT(")"); 3530f74e101Schristos } else { 3540f74e101Schristos /*(*/ 355c74ad251Schristos ND_PRINT(" ?)"); 3560f74e101Schristos } 3570f74e101Schristos break; 358*26ba0b50Schristos case DUID_LL: 3590f74e101Schristos if (optlen >= 2 + 2) { 360c74ad251Schristos ND_PRINT(" hwaddr type %u ", 361c74ad251Schristos GET_BE_U_2(tp + 2)); 3620f74e101Schristos for (i = 4; i < optlen; i++) 363c74ad251Schristos ND_PRINT("%02x", 364c74ad251Schristos GET_U_1(tp + i)); 3650f74e101Schristos /*(*/ 366c74ad251Schristos ND_PRINT(")"); 3670f74e101Schristos } else { 3680f74e101Schristos /*(*/ 369c74ad251Schristos ND_PRINT(" ?)"); 3700f74e101Schristos } 3710f74e101Schristos break; 372*26ba0b50Schristos case DUID_UUID: 373*26ba0b50Schristos ND_PRINT(" uuid "); 374*26ba0b50Schristos if (optlen == 2 + 16) { 375*26ba0b50Schristos for (i = 2; i < optlen; i++) 376*26ba0b50Schristos ND_PRINT("%02x", 377*26ba0b50Schristos GET_U_1(tp + i)); 378*26ba0b50Schristos /*(*/ 379*26ba0b50Schristos ND_PRINT(")"); 380*26ba0b50Schristos } else { 381*26ba0b50Schristos /*(*/ 382*26ba0b50Schristos ND_PRINT(" ?)"); 383*26ba0b50Schristos } 384*26ba0b50Schristos break; 3850f74e101Schristos default: 386c74ad251Schristos ND_PRINT(" type %u)", GET_BE_U_2(tp)); 3870f74e101Schristos break; 3880f74e101Schristos } 3890f74e101Schristos break; 3900f74e101Schristos case DH6OPT_IA_ADDR: 3910f74e101Schristos if (optlen < 24) { 3920f74e101Schristos /*(*/ 393c74ad251Schristos ND_PRINT(" ?)"); 3940f74e101Schristos break; 3950f74e101Schristos } 396fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 397c74ad251Schristos ND_PRINT(" %s", GET_IP6ADDR_STRING(tp)); 398c74ad251Schristos ND_PRINT(" pltime:%u vltime:%u", 399c74ad251Schristos GET_BE_U_4(tp + 16), 400c74ad251Schristos GET_BE_U_4(tp + 20)); 4010f74e101Schristos if (optlen > 24) { 4020f74e101Schristos /* there are sub-options */ 403b3a00663Schristos dhcp6opt_print(ndo, tp + 24, tp + optlen); 4040f74e101Schristos } 405c74ad251Schristos ND_PRINT(")"); 4060f74e101Schristos break; 4070f74e101Schristos case DH6OPT_ORO: 4080f74e101Schristos case DH6OPT_ERO: 4090f74e101Schristos if (optlen % 2) { 410c74ad251Schristos ND_PRINT(" ?)"); 4110f74e101Schristos break; 4120f74e101Schristos } 413fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 4140f74e101Schristos for (i = 0; i < optlen; i += 2) { 415c74ad251Schristos ND_PRINT(" %s", 416c74ad251Schristos tok2str(dh6opt_str, "opt_%u", GET_BE_U_2(tp + i))); 4170f74e101Schristos } 418c74ad251Schristos ND_PRINT(")"); 4190f74e101Schristos break; 4200f74e101Schristos case DH6OPT_PREFERENCE: 4210f74e101Schristos if (optlen != 1) { 422c74ad251Schristos ND_PRINT(" ?)"); 4230f74e101Schristos break; 4240f74e101Schristos } 425fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 426c74ad251Schristos ND_PRINT(" %u)", GET_U_1(tp)); 4270f74e101Schristos break; 4280f74e101Schristos case DH6OPT_ELAPSED_TIME: 4290f74e101Schristos if (optlen != 2) { 430c74ad251Schristos ND_PRINT(" ?)"); 4310f74e101Schristos break; 4320f74e101Schristos } 433fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 434c74ad251Schristos ND_PRINT(" %u)", GET_BE_U_2(tp)); 4350f74e101Schristos break; 4360f74e101Schristos case DH6OPT_RELAY_MSG: 437c74ad251Schristos { 438c74ad251Schristos const u_char *snapend_save; 439c74ad251Schristos 440c74ad251Schristos ND_PRINT(" ("); 441fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 442c74ad251Schristos /* 443c74ad251Schristos * Update the snapend to the end of the option before 444c74ad251Schristos * calling recursively dhcp6_print() for the nested 445c74ad251Schristos * packet. Other options may be present after the 446c74ad251Schristos * nested DHCPv6 packet. This prevents that, in 447c74ad251Schristos * dhcp6_print(), for the nested DHCPv6 packet, the 448c74ad251Schristos * remaining length < remaining caplen. 449c74ad251Schristos */ 450c74ad251Schristos snapend_save = ndo->ndo_snapend; 451c74ad251Schristos ndo->ndo_snapend = ND_MIN(tp + optlen, ndo->ndo_snapend); 452b3a00663Schristos dhcp6_print(ndo, tp, optlen); 453c74ad251Schristos ndo->ndo_snapend = snapend_save; 454c74ad251Schristos ND_PRINT(")"); 4550f74e101Schristos break; 456c74ad251Schristos } 4570f74e101Schristos case DH6OPT_AUTH: 4580f74e101Schristos if (optlen < 11) { 459c74ad251Schristos ND_PRINT(" ?)"); 4600f74e101Schristos break; 4610f74e101Schristos } 462fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 463c74ad251Schristos auth_proto = GET_U_1(tp); 4640f74e101Schristos switch (auth_proto) { 4650f74e101Schristos case DH6OPT_AUTHPROTO_DELAYED: 466c74ad251Schristos ND_PRINT(" proto: delayed"); 4670f74e101Schristos break; 4680f74e101Schristos case DH6OPT_AUTHPROTO_RECONFIG: 469c74ad251Schristos ND_PRINT(" proto: reconfigure"); 4700f74e101Schristos break; 4710f74e101Schristos default: 472c74ad251Schristos ND_PRINT(" proto: %u", auth_proto); 4730f74e101Schristos break; 4740f74e101Schristos } 4750f74e101Schristos tp++; 476c74ad251Schristos auth_alg = GET_U_1(tp); 477c74ad251Schristos switch (auth_alg) { 4780f74e101Schristos case DH6OPT_AUTHALG_HMACMD5: 4790f74e101Schristos /* XXX: may depend on the protocol */ 480c74ad251Schristos ND_PRINT(", alg: HMAC-MD5"); 4810f74e101Schristos break; 4820f74e101Schristos default: 483c74ad251Schristos ND_PRINT(", alg: %u", auth_alg); 4840f74e101Schristos break; 4850f74e101Schristos } 4860f74e101Schristos tp++; 487c74ad251Schristos auth_rdm = GET_U_1(tp); 488c74ad251Schristos switch (auth_rdm) { 4890f74e101Schristos case DH6OPT_AUTHRDM_MONOCOUNTER: 490c74ad251Schristos ND_PRINT(", RDM: mono"); 4910f74e101Schristos break; 4920f74e101Schristos default: 493c74ad251Schristos ND_PRINT(", RDM: %u", auth_rdm); 4940f74e101Schristos break; 4950f74e101Schristos } 4960f74e101Schristos tp++; 497c74ad251Schristos ND_PRINT(", RD:"); 4980f74e101Schristos for (i = 0; i < 4; i++, tp += 2) 499c74ad251Schristos ND_PRINT(" %04x", GET_BE_U_2(tp)); 5000f74e101Schristos 5010f74e101Schristos /* protocol dependent part */ 5020f74e101Schristos authinfolen = optlen - 11; 5030f74e101Schristos switch (auth_proto) { 5040f74e101Schristos case DH6OPT_AUTHPROTO_DELAYED: 5050f74e101Schristos if (authinfolen == 0) 5060f74e101Schristos break; 5070f74e101Schristos if (authinfolen < 20) { 508c74ad251Schristos ND_PRINT(" ??"); 5090f74e101Schristos break; 5100f74e101Schristos } 5110f74e101Schristos authrealmlen = authinfolen - 20; 5120f74e101Schristos if (authrealmlen > 0) { 513c74ad251Schristos ND_PRINT(", realm: "); 5140f74e101Schristos } 5150f74e101Schristos for (i = 0; i < authrealmlen; i++, tp++) 516c74ad251Schristos ND_PRINT("%02x", GET_U_1(tp)); 517c74ad251Schristos ND_PRINT(", key ID: %08x", GET_BE_U_4(tp)); 5180f74e101Schristos tp += 4; 519c74ad251Schristos ND_PRINT(", HMAC-MD5:"); 5200f74e101Schristos for (i = 0; i < 4; i++, tp+= 4) 521c74ad251Schristos ND_PRINT(" %08x", GET_BE_U_4(tp)); 5220f74e101Schristos break; 5230f74e101Schristos case DH6OPT_AUTHPROTO_RECONFIG: 5240f74e101Schristos if (authinfolen != 17) { 525c74ad251Schristos ND_PRINT(" ??"); 5260f74e101Schristos break; 5270f74e101Schristos } 528c74ad251Schristos switch (GET_U_1(tp)) { 5290f74e101Schristos case DH6OPT_AUTHRECONFIG_KEY: 530c74ad251Schristos ND_PRINT(" reconfig-key"); 5310f74e101Schristos break; 5320f74e101Schristos case DH6OPT_AUTHRECONFIG_HMACMD5: 533c74ad251Schristos ND_PRINT(" type: HMAC-MD5"); 5340f74e101Schristos break; 5350f74e101Schristos default: 536c74ad251Schristos ND_PRINT(" type: ??"); 5370f74e101Schristos break; 5380f74e101Schristos } 539c74ad251Schristos tp++; 540c74ad251Schristos ND_PRINT(" value:"); 5410f74e101Schristos for (i = 0; i < 4; i++, tp+= 4) 542c74ad251Schristos ND_PRINT(" %08x", GET_BE_U_4(tp)); 5430f74e101Schristos break; 5440f74e101Schristos default: 545c74ad251Schristos ND_PRINT(" ??"); 5460f74e101Schristos break; 5470f74e101Schristos } 5480f74e101Schristos 549c74ad251Schristos ND_PRINT(")"); 5500f74e101Schristos break; 5510f74e101Schristos case DH6OPT_RAPID_COMMIT: /* nothing todo */ 552c74ad251Schristos ND_PRINT(")"); 5530f74e101Schristos break; 5540f74e101Schristos case DH6OPT_INTERFACE_ID: 5550f74e101Schristos case DH6OPT_SUBSCRIBER_ID: 5560f74e101Schristos /* 5570f74e101Schristos * Since we cannot predict the encoding, print hex dump 5580f74e101Schristos * at most 10 characters. 5590f74e101Schristos */ 560fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 561c74ad251Schristos ND_PRINT(" "); 5620f74e101Schristos for (i = 0; i < optlen && i < 10; i++) 563c74ad251Schristos ND_PRINT("%02x", GET_U_1(tp + i)); 564c74ad251Schristos ND_PRINT("...)"); 5650f74e101Schristos break; 5660f74e101Schristos case DH6OPT_RECONF_MSG: 56772c96ff3Schristos if (optlen != 1) { 568c74ad251Schristos ND_PRINT(" ?)"); 56972c96ff3Schristos break; 57072c96ff3Schristos } 571fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 572c74ad251Schristos dh6_reconf_type = GET_U_1(tp); 573c74ad251Schristos switch (dh6_reconf_type) { 5740f74e101Schristos case DH6_RENEW: 575c74ad251Schristos ND_PRINT(" for renew)"); 5760f74e101Schristos break; 5770f74e101Schristos case DH6_INFORM_REQ: 578c74ad251Schristos ND_PRINT(" for inf-req)"); 5790f74e101Schristos break; 5800f74e101Schristos default: 581c74ad251Schristos ND_PRINT(" for ?\?\?(%02x))", dh6_reconf_type); 5820f74e101Schristos break; 5830f74e101Schristos } 5840f74e101Schristos break; 5850f74e101Schristos case DH6OPT_RECONF_ACCEPT: /* nothing todo */ 586c74ad251Schristos ND_PRINT(")"); 5870f74e101Schristos break; 5880f74e101Schristos case DH6OPT_SIP_SERVER_A: 589870189d2Schristos case DH6OPT_DNS_SERVERS: 590870189d2Schristos case DH6OPT_SNTP_SERVERS: 5910f74e101Schristos case DH6OPT_NIS_SERVERS: 5920f74e101Schristos case DH6OPT_NISP_SERVERS: 5930f74e101Schristos case DH6OPT_BCMCS_SERVER_A: 5940f74e101Schristos case DH6OPT_PANA_AGENT: 5950f74e101Schristos case DH6OPT_LQ_CLIENT_LINK: 5960f74e101Schristos if (optlen % 16) { 597c74ad251Schristos ND_PRINT(" ?)"); 5980f74e101Schristos break; 5990f74e101Schristos } 600fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 6010f74e101Schristos for (i = 0; i < optlen; i += 16) 602c74ad251Schristos ND_PRINT(" %s", GET_IP6ADDR_STRING(tp + i)); 603c74ad251Schristos ND_PRINT(")"); 6040f74e101Schristos break; 605870189d2Schristos case DH6OPT_SIP_SERVER_D: 606870189d2Schristos case DH6OPT_DOMAIN_LIST: 607fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 608870189d2Schristos while (tp < cp + sizeof(*dh6o) + optlen) { 609c74ad251Schristos ND_PRINT(" "); 610c74ad251Schristos if ((tp = fqdn_print(ndo, tp, cp + sizeof(*dh6o) + optlen)) == NULL) 611870189d2Schristos goto trunc; 612870189d2Schristos } 613c74ad251Schristos ND_PRINT(")"); 614870189d2Schristos break; 6150f74e101Schristos case DH6OPT_STATUS_CODE: 6160f74e101Schristos if (optlen < 2) { 617c74ad251Schristos ND_PRINT(" ?)"); 6180f74e101Schristos break; 6190f74e101Schristos } 620fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 621c74ad251Schristos ND_PRINT(" %s)", dhcp6stcode(GET_BE_U_2(tp))); 6220f74e101Schristos break; 6230f74e101Schristos case DH6OPT_IA_NA: 6240f74e101Schristos case DH6OPT_IA_PD: 6250f74e101Schristos if (optlen < 12) { 626c74ad251Schristos ND_PRINT(" ?)"); 6270f74e101Schristos break; 6280f74e101Schristos } 629fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 630c74ad251Schristos ND_PRINT(" IAID:%u T1:%u T2:%u", 631c74ad251Schristos GET_BE_U_4(tp), 632c74ad251Schristos GET_BE_U_4(tp + 4), 633c74ad251Schristos GET_BE_U_4(tp + 8)); 6340f74e101Schristos if (optlen > 12) { 6350f74e101Schristos /* there are sub-options */ 636b3a00663Schristos dhcp6opt_print(ndo, tp + 12, tp + optlen); 6370f74e101Schristos } 638c74ad251Schristos ND_PRINT(")"); 6390f74e101Schristos break; 6400f74e101Schristos case DH6OPT_IA_TA: 6410f74e101Schristos if (optlen < 4) { 642c74ad251Schristos ND_PRINT(" ?)"); 6430f74e101Schristos break; 6440f74e101Schristos } 645fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 646c74ad251Schristos ND_PRINT(" IAID:%u", GET_BE_U_4(tp)); 6470f74e101Schristos if (optlen > 4) { 6480f74e101Schristos /* there are sub-options */ 649b3a00663Schristos dhcp6opt_print(ndo, tp + 4, tp + optlen); 6500f74e101Schristos } 651c74ad251Schristos ND_PRINT(")"); 6520f74e101Schristos break; 6530f74e101Schristos case DH6OPT_IA_PD_PREFIX: 6540f74e101Schristos if (optlen < 25) { 655c74ad251Schristos ND_PRINT(" ?)"); 6560f74e101Schristos break; 6570f74e101Schristos } 658fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 659c74ad251Schristos ND_PRINT(" %s/%u", GET_IP6ADDR_STRING(tp + 9), 660c74ad251Schristos GET_U_1(tp + 8)); 661c74ad251Schristos ND_PRINT(" pltime:%u vltime:%u", 662c74ad251Schristos GET_BE_U_4(tp), 663c74ad251Schristos GET_BE_U_4(tp + 4)); 6640f74e101Schristos if (optlen > 25) { 6650f74e101Schristos /* there are sub-options */ 666b3a00663Schristos dhcp6opt_print(ndo, tp + 25, tp + optlen); 6670f74e101Schristos } 668c74ad251Schristos ND_PRINT(")"); 6690f74e101Schristos break; 6700f74e101Schristos case DH6OPT_LIFETIME: 6710f74e101Schristos case DH6OPT_CLT_TIME: 6720f74e101Schristos if (optlen != 4) { 673c74ad251Schristos ND_PRINT(" ?)"); 6740f74e101Schristos break; 6750f74e101Schristos } 676fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 677c74ad251Schristos ND_PRINT(" %u)", GET_BE_U_4(tp)); 6780f74e101Schristos break; 6790f74e101Schristos case DH6OPT_REMOTE_ID: 6800f74e101Schristos if (optlen < 4) { 681c74ad251Schristos ND_PRINT(" ?)"); 6820f74e101Schristos break; 6830f74e101Schristos } 684fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 685c74ad251Schristos ND_PRINT(" %u ", GET_BE_U_4(tp)); 6860f74e101Schristos /* 6870f74e101Schristos * Print hex dump first 10 characters. 6880f74e101Schristos */ 6890f74e101Schristos for (i = 4; i < optlen && i < 14; i++) 690c74ad251Schristos ND_PRINT("%02x", GET_U_1(tp + i)); 691c74ad251Schristos ND_PRINT("...)"); 6920f74e101Schristos break; 6930f74e101Schristos case DH6OPT_LQ_QUERY: 6940f74e101Schristos if (optlen < 17) { 695c74ad251Schristos ND_PRINT(" ?)"); 6960f74e101Schristos break; 6970f74e101Schristos } 698fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 699c74ad251Schristos dh6_lq_query_type = GET_U_1(tp); 700c74ad251Schristos switch (dh6_lq_query_type) { 7010f74e101Schristos case 1: 702c74ad251Schristos ND_PRINT(" by-address"); 7030f74e101Schristos break; 7040f74e101Schristos case 2: 705c74ad251Schristos ND_PRINT(" by-clientID"); 7060f74e101Schristos break; 7070f74e101Schristos default: 708c74ad251Schristos ND_PRINT(" type_%u", dh6_lq_query_type); 7090f74e101Schristos break; 7100f74e101Schristos } 711c74ad251Schristos ND_PRINT(" %s", GET_IP6ADDR_STRING(tp + 1)); 7120f74e101Schristos if (optlen > 17) { 7130f74e101Schristos /* there are query-options */ 714b3a00663Schristos dhcp6opt_print(ndo, tp + 17, tp + optlen); 7150f74e101Schristos } 716c74ad251Schristos ND_PRINT(")"); 7170f74e101Schristos break; 7180f74e101Schristos case DH6OPT_CLIENT_DATA: 719fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 7200f74e101Schristos if (optlen > 0) { 7210f74e101Schristos /* there are encapsulated options */ 722b3a00663Schristos dhcp6opt_print(ndo, tp, tp + optlen); 7230f74e101Schristos } 724c74ad251Schristos ND_PRINT(")"); 7250f74e101Schristos break; 7260f74e101Schristos case DH6OPT_LQ_RELAY_DATA: 7270f74e101Schristos if (optlen < 16) { 728c74ad251Schristos ND_PRINT(" ?)"); 7290f74e101Schristos break; 7300f74e101Schristos } 731fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 732c74ad251Schristos ND_PRINT(" %s ", GET_IP6ADDR_STRING(tp)); 7330f74e101Schristos /* 7340f74e101Schristos * Print hex dump first 10 characters. 7350f74e101Schristos */ 7360f74e101Schristos for (i = 16; i < optlen && i < 26; i++) 737c74ad251Schristos ND_PRINT("%02x", GET_U_1(tp + i)); 738c74ad251Schristos ND_PRINT("...)"); 7390f74e101Schristos break; 740870189d2Schristos case DH6OPT_NTP_SERVER: 741870189d2Schristos if (optlen < 4) { 742c74ad251Schristos ND_PRINT(" ?)"); 743870189d2Schristos break; 744870189d2Schristos } 745fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 746870189d2Schristos while (tp < cp + sizeof(*dh6o) + optlen - 4) { 747c74ad251Schristos subopt_code = GET_BE_U_2(tp); 748870189d2Schristos tp += 2; 749c74ad251Schristos subopt_len = GET_BE_U_2(tp); 750870189d2Schristos tp += 2; 751870189d2Schristos if (tp + subopt_len > cp + sizeof(*dh6o) + optlen) 752870189d2Schristos goto trunc; 753c74ad251Schristos ND_PRINT(" subopt:%u", subopt_code); 754870189d2Schristos switch (subopt_code) { 755870189d2Schristos case DH6OPT_NTP_SUBOPTION_SRV_ADDR: 756870189d2Schristos case DH6OPT_NTP_SUBOPTION_MC_ADDR: 757870189d2Schristos if (subopt_len != 16) { 758c74ad251Schristos ND_PRINT(" ?"); 759870189d2Schristos break; 760870189d2Schristos } 761c74ad251Schristos ND_PRINT(" %s", GET_IP6ADDR_STRING(tp)); 762870189d2Schristos break; 763870189d2Schristos case DH6OPT_NTP_SUBOPTION_SRV_FQDN: 764c74ad251Schristos ND_PRINT(" "); 765c74ad251Schristos if (fqdn_print(ndo, tp, tp + subopt_len) == NULL) 766870189d2Schristos goto trunc; 767870189d2Schristos break; 768870189d2Schristos default: 769c74ad251Schristos ND_PRINT(" ?"); 770870189d2Schristos break; 771870189d2Schristos } 772870189d2Schristos tp += subopt_len; 773870189d2Schristos } 774c74ad251Schristos ND_PRINT(")"); 775870189d2Schristos break; 776870189d2Schristos case DH6OPT_AFTR_NAME: 777870189d2Schristos if (optlen < 3) { 778c74ad251Schristos ND_PRINT(" ?)"); 779870189d2Schristos break; 780870189d2Schristos } 781fdccd7e4Schristos tp = (const u_char *)(dh6o + 1); 782870189d2Schristos remain_len = optlen; 783c74ad251Schristos ND_PRINT(" "); 784870189d2Schristos /* Encoding is described in section 3.1 of RFC 1035 */ 785c74ad251Schristos while (remain_len && GET_U_1(tp)) { 786c74ad251Schristos label_len = GET_U_1(tp); 787c74ad251Schristos tp++; 788870189d2Schristos if (label_len < remain_len - 1) { 789c74ad251Schristos nd_printjnp(ndo, tp, label_len); 790870189d2Schristos tp += label_len; 791870189d2Schristos remain_len -= (label_len + 1); 792c74ad251Schristos if(GET_U_1(tp)) ND_PRINT("."); 793870189d2Schristos } else { 794c74ad251Schristos ND_PRINT(" ?"); 795870189d2Schristos break; 796870189d2Schristos } 797870189d2Schristos } 798c74ad251Schristos ND_PRINT(")"); 799870189d2Schristos break; 800dc860a36Sspz case DH6OPT_NEW_POSIX_TIMEZONE: /* all three of these options */ 801dc860a36Sspz case DH6OPT_NEW_TZDB_TIMEZONE: /* are encoded similarly */ 802dc860a36Sspz case DH6OPT_MUDURL: /* although GMT might not work */ 803dc860a36Sspz if (optlen < 5) { 804c74ad251Schristos ND_PRINT(" ?)"); 805dc860a36Sspz break; 806dc860a36Sspz } 807dc860a36Sspz tp = (const u_char *)(dh6o + 1); 808c74ad251Schristos ND_PRINT(" "); 809c74ad251Schristos nd_printjnp(ndo, tp, optlen); 810c74ad251Schristos ND_PRINT(")"); 811dc860a36Sspz break; 812dc860a36Sspz 813*26ba0b50Schristos case DH6OPT_BOOTFILE_URL: 814*26ba0b50Schristos tp = (const u_char *)(dh6o + 1); 815*26ba0b50Schristos ND_PRINT(" "); 816*26ba0b50Schristos nd_printjn(ndo, tp, optlen); 817*26ba0b50Schristos ND_PRINT(")"); 818*26ba0b50Schristos break; 819*26ba0b50Schristos 820*26ba0b50Schristos case DH6OPT_SZTP_REDIRECT: 821*26ba0b50Schristos case DH6OPT_USER_CLASS: 822*26ba0b50Schristos ND_PRINT(" "); 823*26ba0b50Schristos tp = (const u_char *)(dh6o + 1); 824*26ba0b50Schristos first_list_value = TRUE; 825*26ba0b50Schristos remainder_len = optlen; 826*26ba0b50Schristos while (remainder_len >= 2) { 827*26ba0b50Schristos if (first_list_value == FALSE) { 828*26ba0b50Schristos ND_PRINT(","); 829*26ba0b50Schristos } 830*26ba0b50Schristos first_list_value = FALSE; 831*26ba0b50Schristos subopt_len = GET_BE_U_2(tp); 832*26ba0b50Schristos if (subopt_len > remainder_len-2) { 833*26ba0b50Schristos break; 834*26ba0b50Schristos } 835*26ba0b50Schristos tp += 2; 836*26ba0b50Schristos nd_printjn(ndo, tp, subopt_len); 837*26ba0b50Schristos tp += subopt_len; 838*26ba0b50Schristos remainder_len -= (subopt_len+2); 839*26ba0b50Schristos } 840*26ba0b50Schristos if (remainder_len != 0 ) { 841*26ba0b50Schristos ND_PRINT(" ?"); 842*26ba0b50Schristos } 843*26ba0b50Schristos ND_PRINT(")"); 844*26ba0b50Schristos break; 845*26ba0b50Schristos 8460f74e101Schristos default: 847c74ad251Schristos ND_PRINT(")"); 8480f74e101Schristos break; 8490f74e101Schristos } 8500f74e101Schristos 8510f74e101Schristos cp += sizeof(*dh6o) + optlen; 8520f74e101Schristos } 8530f74e101Schristos return; 8540f74e101Schristos 8550f74e101Schristos trunc: 856c74ad251Schristos nd_print_trunc(ndo); 8570f74e101Schristos } 8580f74e101Schristos 8590f74e101Schristos /* 8600f74e101Schristos * Print dhcp6 packets 8610f74e101Schristos */ 8620f74e101Schristos void 863b3a00663Schristos dhcp6_print(netdissect_options *ndo, 864b3a00663Schristos const u_char *cp, u_int length) 8650f74e101Schristos { 866fdccd7e4Schristos const struct dhcp6 *dh6; 867fdccd7e4Schristos const struct dhcp6_relay *dh6relay; 868c74ad251Schristos uint8_t msgtype; 8690f74e101Schristos const u_char *ep; 870fdccd7e4Schristos const u_char *extp; 8710f74e101Schristos const char *name; 8720f74e101Schristos 873c74ad251Schristos ndo->ndo_protocol = "dhcp6"; 874c74ad251Schristos ND_PRINT("dhcp6"); 8750f74e101Schristos 876c74ad251Schristos ep = ndo->ndo_snapend; 8770f74e101Schristos if (cp + length < ep) 8780f74e101Schristos ep = cp + length; 8790f74e101Schristos 880fdccd7e4Schristos dh6 = (const struct dhcp6 *)cp; 881fdccd7e4Schristos dh6relay = (const struct dhcp6_relay *)cp; 882c74ad251Schristos ND_TCHECK_4(dh6->dh6_msgtypexid.xid); 883c74ad251Schristos msgtype = GET_U_1(dh6->dh6_msgtypexid.msgtype); 884c74ad251Schristos name = tok2str(dh6_msgtype_str, "msgtype-%u", msgtype); 8850f74e101Schristos 886b3a00663Schristos if (!ndo->ndo_vflag) { 887c74ad251Schristos ND_PRINT(" %s", name); 8880f74e101Schristos return; 8890f74e101Schristos } 8900f74e101Schristos 8910f74e101Schristos /* XXX relay agent messages have to be handled differently */ 8920f74e101Schristos 893c74ad251Schristos ND_PRINT(" %s (", name); /*)*/ 894c74ad251Schristos if (msgtype != DH6_RELAY_FORW && msgtype != DH6_RELAY_REPLY) { 895c74ad251Schristos ND_PRINT("xid=%x", 896c74ad251Schristos GET_BE_U_4(dh6->dh6_msgtypexid.xid) & DH6_XIDMASK); 897fdccd7e4Schristos extp = (const u_char *)(dh6 + 1); 898b3a00663Schristos dhcp6opt_print(ndo, extp, ep); 8990f74e101Schristos } else { /* relay messages */ 900c74ad251Schristos ND_PRINT("linkaddr=%s", GET_IP6ADDR_STRING(dh6relay->dh6relay_linkaddr)); 9010f74e101Schristos 902c74ad251Schristos ND_PRINT(" peeraddr=%s", GET_IP6ADDR_STRING(dh6relay->dh6relay_peeraddr)); 9030f74e101Schristos 904fdccd7e4Schristos dhcp6opt_print(ndo, (const u_char *)(dh6relay + 1), ep); 9050f74e101Schristos } 9060f74e101Schristos /*(*/ 907c74ad251Schristos ND_PRINT(")"); 9080f74e101Schristos return; 9090f74e101Schristos 9100f74e101Schristos trunc: 911c74ad251Schristos nd_print_trunc(ndo); 9120f74e101Schristos } 913