156893Sfenner/* 256893Sfenner * Copyright (C) 1998 and 1999 WIDE Project. 356893Sfenner * All rights reserved. 4127668Sbms * 556893Sfenner * Redistribution and use in source and binary forms, with or without 656893Sfenner * modification, are permitted provided that the following conditions 756893Sfenner * are met: 856893Sfenner * 1. Redistributions of source code must retain the above copyright 956893Sfenner * notice, this list of conditions and the following disclaimer. 1056893Sfenner * 2. Redistributions in binary form must reproduce the above copyright 1156893Sfenner * notice, this list of conditions and the following disclaimer in the 1256893Sfenner * documentation and/or other materials provided with the distribution. 1356893Sfenner * 3. Neither the name of the project nor the names of its contributors 1456893Sfenner * may be used to endorse or promote products derived from this software 1556893Sfenner * without specific prior written permission. 16127668Sbms * 1756893Sfenner * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1856893Sfenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1956893Sfenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2056893Sfenner * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2156893Sfenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2256893Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2356893Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2456893Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2556893Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2656893Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2756893Sfenner * SUCH DAMAGE. 2856893Sfenner */ 29111726Sfenner/* 30127668Sbms * RFC3315: DHCPv6 31276788Sdelphij * supported DHCPv6 options: 32251158Sdelphij * RFC3319: Session Initiation Protocol (SIP) Servers options, 33251158Sdelphij * RFC3633: IPv6 Prefix options, 34251158Sdelphij * RFC3646: DNS Configuration options, 35251158Sdelphij * RFC3898: Network Information Service (NIS) Configuration options, 36251158Sdelphij * RFC4075: Simple Network Time Protocol (SNTP) Configuration option, 37251158Sdelphij * RFC4242: Information Refresh Time option, 38251158Sdelphij * RFC4280: Broadcast and Multicast Control Servers options, 39276788Sdelphij * RFC5908: Network Time Protocol (NTP) Server Option for DHCPv6 40251158Sdelphij * RFC6334: Dual-Stack Lite option, 41111726Sfenner */ 4256893Sfenner 43276788Sdelphij#define NETDISSECT_REWORKED 4456893Sfenner#ifdef HAVE_CONFIG_H 4556893Sfenner#include "config.h" 4656893Sfenner#endif 4756893Sfenner 48127668Sbms#include <tcpdump-stdinc.h> 4956893Sfenner 5056893Sfenner#include <stdio.h> 5156893Sfenner#include <string.h> 5256893Sfenner 5356893Sfenner#include "interface.h" 5456893Sfenner#include "addrtoname.h" 55127668Sbms#include "extract.h" 5656893Sfenner 57127668Sbms/* lease duration */ 58276788Sdelphij#define DHCP6_DURATION_INFINITE 0xffffffff 59127668Sbms 60111726Sfenner/* Error Values */ 61111726Sfenner#define DH6ERR_FAILURE 16 62111726Sfenner#define DH6ERR_AUTHFAIL 17 63111726Sfenner#define DH6ERR_POORLYFORMED 18 64111726Sfenner#define DH6ERR_UNAVAIL 19 65111726Sfenner#define DH6ERR_OPTUNAVAIL 20 6656893Sfenner 67111726Sfenner/* Message type */ 68127668Sbms#define DH6_SOLICIT 1 69127668Sbms#define DH6_ADVERTISE 2 70127668Sbms#define DH6_REQUEST 3 71127668Sbms#define DH6_CONFIRM 4 72127668Sbms#define DH6_RENEW 5 73127668Sbms#define DH6_REBIND 6 74111726Sfenner#define DH6_REPLY 7 75127668Sbms#define DH6_RELEASE 8 76127668Sbms#define DH6_DECLINE 9 77127668Sbms#define DH6_RECONFIGURE 10 78111726Sfenner#define DH6_INFORM_REQ 11 79127668Sbms#define DH6_RELAY_FORW 12 80127668Sbms#define DH6_RELAY_REPLY 13 81190207Srpaulo#define DH6_LEASEQUERY 14 82190207Srpaulo#define DH6_LQ_REPLY 15 8356893Sfenner 84276788Sdelphijstatic const struct tok dh6_msgtype_str[] = { 85276788Sdelphij { DH6_SOLICIT, "solicit" }, 86276788Sdelphij { DH6_ADVERTISE, "advertise" }, 87276788Sdelphij { DH6_REQUEST, "request" }, 88276788Sdelphij { DH6_CONFIRM, "confirm" }, 89276788Sdelphij { DH6_RENEW, "renew" }, 90276788Sdelphij { DH6_REBIND, "rebind" }, 91276788Sdelphij { DH6_REPLY, "reply" }, 92276788Sdelphij { DH6_RELEASE, "release" }, 93276788Sdelphij { DH6_DECLINE, "decline" }, 94276788Sdelphij { DH6_RECONFIGURE, "reconfigure" }, 95276788Sdelphij { DH6_INFORM_REQ, "inf-req" }, 96276788Sdelphij { DH6_RELAY_FORW, "relay-fwd" }, 97276788Sdelphij { DH6_RELAY_REPLY, "relay-reply" }, 98276788Sdelphij { DH6_LEASEQUERY, "leasequery" }, 99276788Sdelphij { DH6_LQ_REPLY, "leasequery-reply" }, 100276788Sdelphij { 0, NULL } 101276788Sdelphij}; 102276788Sdelphij 103111726Sfenner/* DHCP6 base packet format */ 104111726Sfennerstruct dhcp6 { 105111726Sfenner union { 106276788Sdelphij uint8_t m; 107276788Sdelphij uint32_t x; 108111726Sfenner } dh6_msgtypexid; 109111726Sfenner /* options follow */ 110127668Sbms}; 111111726Sfenner#define dh6_msgtype dh6_msgtypexid.m 112111726Sfenner#define dh6_xid dh6_msgtypexid.x 113111726Sfenner#define DH6_XIDMASK 0x00ffffff 11456893Sfenner 115127668Sbms/* DHCPv6 relay messages */ 116127668Sbmsstruct dhcp6_relay { 117276788Sdelphij uint8_t dh6relay_msgtype; 118276788Sdelphij uint8_t dh6relay_hcnt; 119276788Sdelphij uint8_t dh6relay_linkaddr[16]; /* XXX: badly aligned */ 120276788Sdelphij uint8_t dh6relay_peeraddr[16]; 121127668Sbms /* options follow */ 122127668Sbms}; 123127668Sbms 124127668Sbms/* options */ 125127668Sbms#define DH6OPT_CLIENTID 1 126127668Sbms#define DH6OPT_SERVERID 2 127127668Sbms#define DH6OPT_IA_NA 3 128172683Smlaier#define DH6OPT_IA_TA 4 129172683Smlaier#define DH6OPT_IA_ADDR 5 130127668Sbms#define DH6OPT_ORO 6 131127668Sbms#define DH6OPT_PREFERENCE 7 132127668Sbms# define DH6OPT_PREF_MAX 255 133127668Sbms#define DH6OPT_ELAPSED_TIME 8 134127668Sbms#define DH6OPT_RELAY_MSG 9 135127668Sbms/*#define DH6OPT_SERVER_MSG 10 deprecated */ 136127668Sbms#define DH6OPT_AUTH 11 137146773Ssam# define DH6OPT_AUTHPROTO_DELAYED 2 138146773Ssam# define DH6OPT_AUTHPROTO_RECONFIG 3 139146773Ssam# define DH6OPT_AUTHALG_HMACMD5 1 140146773Ssam# define DH6OPT_AUTHRDM_MONOCOUNTER 0 141146773Ssam# define DH6OPT_AUTHRECONFIG_KEY 1 142146773Ssam# define DH6OPT_AUTHRECONFIG_HMACMD5 2 143127668Sbms#define DH6OPT_UNICAST 12 144127668Sbms#define DH6OPT_STATUS_CODE 13 145127668Sbms# define DH6OPT_STCODE_SUCCESS 0 146127668Sbms# define DH6OPT_STCODE_UNSPECFAIL 1 147127668Sbms# define DH6OPT_STCODE_NOADDRAVAIL 2 148127668Sbms# define DH6OPT_STCODE_NOBINDING 3 149127668Sbms# define DH6OPT_STCODE_NOTONLINK 4 150127668Sbms# define DH6OPT_STCODE_USEMULTICAST 5 151127668Sbms# define DH6OPT_STCODE_NOPREFIXAVAIL 6 152190207Srpaulo# define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7 153190207Srpaulo# define DH6OPT_STCODE_MALFORMEDQUERY 8 154190207Srpaulo# define DH6OPT_STCODE_NOTCONFIGURED 9 155190207Srpaulo# define DH6OPT_STCODE_NOTALLOWED 10 156127668Sbms#define DH6OPT_RAPID_COMMIT 14 157127668Sbms#define DH6OPT_USER_CLASS 15 158127668Sbms#define DH6OPT_VENDOR_CLASS 16 159127668Sbms#define DH6OPT_VENDOR_OPTS 17 160127668Sbms#define DH6OPT_INTERFACE_ID 18 161127668Sbms#define DH6OPT_RECONF_MSG 19 162127668Sbms#define DH6OPT_RECONF_ACCEPT 20 163127668Sbms#define DH6OPT_SIP_SERVER_D 21 164127668Sbms#define DH6OPT_SIP_SERVER_A 22 165276788Sdelphij#define DH6OPT_DNS_SERVERS 23 166276788Sdelphij#define DH6OPT_DOMAIN_LIST 24 167146773Ssam#define DH6OPT_IA_PD 25 168146773Ssam#define DH6OPT_IA_PD_PREFIX 26 169172683Smlaier#define DH6OPT_NIS_SERVERS 27 170172683Smlaier#define DH6OPT_NISP_SERVERS 28 171172683Smlaier#define DH6OPT_NIS_NAME 29 172172683Smlaier#define DH6OPT_NISP_NAME 30 173276788Sdelphij#define DH6OPT_SNTP_SERVERS 31 174172683Smlaier#define DH6OPT_LIFETIME 32 175172683Smlaier#define DH6OPT_BCMCS_SERVER_D 33 176172683Smlaier#define DH6OPT_BCMCS_SERVER_A 34 177172683Smlaier#define DH6OPT_GEOCONF_CIVIC 36 178172683Smlaier#define DH6OPT_REMOTE_ID 37 179172683Smlaier#define DH6OPT_SUBSCRIBER_ID 38 180172683Smlaier#define DH6OPT_CLIENT_FQDN 39 181190207Srpaulo#define DH6OPT_PANA_AGENT 40 182190207Srpaulo#define DH6OPT_NEW_POSIX_TIMEZONE 41 183190207Srpaulo#define DH6OPT_NEW_TZDB_TIMEZONE 42 184190207Srpaulo#define DH6OPT_ERO 43 185190207Srpaulo#define DH6OPT_LQ_QUERY 44 186190207Srpaulo#define DH6OPT_CLIENT_DATA 45 187190207Srpaulo#define DH6OPT_CLT_TIME 46 188190207Srpaulo#define DH6OPT_LQ_RELAY_DATA 47 189190207Srpaulo#define DH6OPT_LQ_CLIENT_LINK 48 190276788Sdelphij#define DH6OPT_NTP_SERVER 56 191276788Sdelphij# define DH6OPT_NTP_SUBOPTION_SRV_ADDR 1 192276788Sdelphij# define DH6OPT_NTP_SUBOPTION_MC_ADDR 2 193276788Sdelphij# define DH6OPT_NTP_SUBOPTION_SRV_FQDN 3 194251158Sdelphij#define DH6OPT_AFTR_NAME 64 195127668Sbms 196276788Sdelphijstatic const struct tok dh6opt_str[] = { 197276788Sdelphij { DH6OPT_CLIENTID, "client-ID" }, 198276788Sdelphij { DH6OPT_SERVERID, "server-ID" }, 199276788Sdelphij { DH6OPT_IA_NA, "IA_NA" }, 200276788Sdelphij { DH6OPT_IA_TA, "IA_TA" }, 201276788Sdelphij { DH6OPT_IA_ADDR, "IA_ADDR" }, 202276788Sdelphij { DH6OPT_ORO, "option-request" }, 203276788Sdelphij { DH6OPT_PREFERENCE, "preference" }, 204276788Sdelphij { DH6OPT_ELAPSED_TIME, "elapsed-time" }, 205276788Sdelphij { DH6OPT_RELAY_MSG, "relay-message" }, 206276788Sdelphij { DH6OPT_AUTH, "authentication" }, 207276788Sdelphij { DH6OPT_UNICAST, "server-unicast" }, 208276788Sdelphij { DH6OPT_STATUS_CODE, "status-code" }, 209276788Sdelphij { DH6OPT_RAPID_COMMIT, "rapid-commit" }, 210276788Sdelphij { DH6OPT_USER_CLASS, "user-class" }, 211276788Sdelphij { DH6OPT_VENDOR_CLASS, "vendor-class" }, 212276788Sdelphij { DH6OPT_VENDOR_OPTS, "vendor-specific-info" }, 213276788Sdelphij { DH6OPT_INTERFACE_ID, "interface-ID" }, 214276788Sdelphij { DH6OPT_RECONF_MSG, "reconfigure-message" }, 215276788Sdelphij { DH6OPT_RECONF_ACCEPT, "reconfigure-accept" }, 216276788Sdelphij { DH6OPT_SIP_SERVER_D, "SIP-servers-domain" }, 217276788Sdelphij { DH6OPT_SIP_SERVER_A, "SIP-servers-address" }, 218276788Sdelphij { DH6OPT_DNS_SERVERS, "DNS-server" }, 219276788Sdelphij { DH6OPT_DOMAIN_LIST, "DNS-search-list" }, 220276788Sdelphij { DH6OPT_IA_PD, "IA_PD" }, 221276788Sdelphij { DH6OPT_IA_PD_PREFIX, "IA_PD-prefix" }, 222276788Sdelphij { DH6OPT_SNTP_SERVERS, "SNTP-servers" }, 223276788Sdelphij { DH6OPT_LIFETIME, "lifetime" }, 224276788Sdelphij { DH6OPT_NIS_SERVERS, "NIS-server" }, 225276788Sdelphij { DH6OPT_NISP_SERVERS, "NIS+-server" }, 226276788Sdelphij { DH6OPT_NIS_NAME, "NIS-domain-name" }, 227276788Sdelphij { DH6OPT_NISP_NAME, "NIS+-domain-name" }, 228276788Sdelphij { DH6OPT_BCMCS_SERVER_D, "BCMCS-domain-name" }, 229276788Sdelphij { DH6OPT_BCMCS_SERVER_A, "BCMCS-server" }, 230276788Sdelphij { DH6OPT_GEOCONF_CIVIC, "Geoconf-Civic" }, 231276788Sdelphij { DH6OPT_REMOTE_ID, "Remote-ID" }, 232276788Sdelphij { DH6OPT_SUBSCRIBER_ID, "Subscriber-ID" }, 233276788Sdelphij { DH6OPT_CLIENT_FQDN, "Client-FQDN" }, 234276788Sdelphij { DH6OPT_PANA_AGENT, "PANA-agent" }, 235276788Sdelphij { DH6OPT_NEW_POSIX_TIMEZONE, "POSIX-timezone" }, 236276788Sdelphij { DH6OPT_NEW_TZDB_TIMEZONE, "POSIX-tz-database" }, 237276788Sdelphij { DH6OPT_ERO, "Echo-request-option" }, 238276788Sdelphij { DH6OPT_LQ_QUERY, "Lease-query" }, 239276788Sdelphij { DH6OPT_CLIENT_DATA, "LQ-client-data" }, 240276788Sdelphij { DH6OPT_CLT_TIME, "Clt-time" }, 241276788Sdelphij { DH6OPT_LQ_RELAY_DATA, "LQ-relay-data" }, 242276788Sdelphij { DH6OPT_LQ_CLIENT_LINK, "LQ-client-link" }, 243276788Sdelphij { DH6OPT_NTP_SERVER, "NTP-server" }, 244276788Sdelphij { DH6OPT_AFTR_NAME, "AFTR-Name" }, 245276788Sdelphij { 0, NULL } 246276788Sdelphij}; 247276788Sdelphij 248276788Sdelphijstatic const struct tok dh6opt_stcode_str[] = { 249276788Sdelphij { DH6OPT_STCODE_SUCCESS, "success" }, 250276788Sdelphij { DH6OPT_STCODE_UNSPECFAIL, "unspec failure" }, 251276788Sdelphij { DH6OPT_STCODE_NOADDRAVAIL, "no addresses" }, 252276788Sdelphij { DH6OPT_STCODE_NOBINDING, "no binding" }, 253276788Sdelphij { DH6OPT_STCODE_NOTONLINK, "not on-link" }, 254276788Sdelphij { DH6OPT_STCODE_USEMULTICAST, "use multicast" }, 255276788Sdelphij { DH6OPT_STCODE_NOPREFIXAVAIL, "no prefixes" }, 256276788Sdelphij { DH6OPT_STCODE_UNKNOWNQUERYTYPE, "unknown query type" }, 257276788Sdelphij { DH6OPT_STCODE_MALFORMEDQUERY, "malformed query" }, 258276788Sdelphij { DH6OPT_STCODE_NOTCONFIGURED, "not configured" }, 259276788Sdelphij { DH6OPT_STCODE_NOTALLOWED, "not allowed" }, 260276788Sdelphij { 0, NULL } 261276788Sdelphij}; 262276788Sdelphij 263111726Sfennerstruct dhcp6opt { 264276788Sdelphij uint16_t dh6opt_type; 265276788Sdelphij uint16_t dh6opt_len; 266111726Sfenner /* type-dependent data follows */ 267127668Sbms}; 26856893Sfenner 269127668Sbmsstatic const char * 270276788Sdelphijdhcp6stcode(const uint16_t code) 271127668Sbms{ 272276788Sdelphij return code > 255 ? "INVALID code" : tok2str(dh6opt_stcode_str, "code%u", code); 273127668Sbms} 274127668Sbms 27556893Sfennerstatic void 276276788Sdelphijdhcp6opt_print(netdissect_options *ndo, 277276788Sdelphij const u_char *cp, const u_char *ep) 27856893Sfenner{ 279276788Sdelphij const struct dhcp6opt *dh6o; 280276788Sdelphij const u_char *tp; 281127668Sbms size_t i; 282276788Sdelphij uint16_t opttype; 283111726Sfenner size_t optlen; 284276788Sdelphij uint8_t auth_proto; 285146773Ssam u_int authinfolen, authrealmlen; 286276788Sdelphij int remain_len; /* Length of remaining options */ 287276788Sdelphij int label_len; /* Label length */ 288276788Sdelphij uint16_t subopt_code; 289276788Sdelphij uint16_t subopt_len; 29056893Sfenner 29156893Sfenner if (cp == ep) 29256893Sfenner return; 29356893Sfenner while (cp < ep) { 294127668Sbms if (ep < cp + sizeof(*dh6o)) 295111726Sfenner goto trunc; 296111726Sfenner dh6o = (struct dhcp6opt *)cp; 297276788Sdelphij ND_TCHECK(*dh6o); 298127668Sbms optlen = EXTRACT_16BITS(&dh6o->dh6opt_len); 299127668Sbms if (ep < cp + sizeof(*dh6o) + optlen) 300111726Sfenner goto trunc; 301127668Sbms opttype = EXTRACT_16BITS(&dh6o->dh6opt_type); 302276788Sdelphij ND_PRINT((ndo, " (%s", tok2str(dh6opt_str, "opt_%u", opttype))); 303127668Sbms switch (opttype) { 304127668Sbms case DH6OPT_CLIENTID: 305127668Sbms case DH6OPT_SERVERID: 306111726Sfenner if (optlen < 2) { 307111726Sfenner /*(*/ 308276788Sdelphij ND_PRINT((ndo, " ?)")); 309111726Sfenner break; 310111726Sfenner } 311111726Sfenner tp = (u_char *)(dh6o + 1); 312127668Sbms switch (EXTRACT_16BITS(tp)) { 313111726Sfenner case 1: 314111726Sfenner if (optlen >= 2 + 6) { 315276788Sdelphij ND_PRINT((ndo, " hwaddr/time type %u time %u ", 316127668Sbms EXTRACT_16BITS(&tp[2]), 317276788Sdelphij EXTRACT_32BITS(&tp[4]))); 318111726Sfenner for (i = 8; i < optlen; i++) 319276788Sdelphij ND_PRINT((ndo, "%02x", tp[i])); 320111726Sfenner /*(*/ 321276788Sdelphij ND_PRINT((ndo, ")")); 322111726Sfenner } else { 323111726Sfenner /*(*/ 324276788Sdelphij ND_PRINT((ndo, " ?)")); 325111726Sfenner } 326111726Sfenner break; 327111726Sfenner case 2: 328111726Sfenner if (optlen >= 2 + 8) { 329276788Sdelphij ND_PRINT((ndo, " vid ")); 330111726Sfenner for (i = 2; i < 2 + 8; i++) 331276788Sdelphij ND_PRINT((ndo, "%02x", tp[i])); 332111726Sfenner /*(*/ 333276788Sdelphij ND_PRINT((ndo, ")")); 334111726Sfenner } else { 335111726Sfenner /*(*/ 336276788Sdelphij ND_PRINT((ndo, " ?)")); 337111726Sfenner } 338111726Sfenner break; 339111726Sfenner case 3: 340111726Sfenner if (optlen >= 2 + 2) { 341276788Sdelphij ND_PRINT((ndo, " hwaddr type %u ", 342276788Sdelphij EXTRACT_16BITS(&tp[2]))); 343111726Sfenner for (i = 4; i < optlen; i++) 344276788Sdelphij ND_PRINT((ndo, "%02x", tp[i])); 345111726Sfenner /*(*/ 346276788Sdelphij ND_PRINT((ndo, ")")); 347111726Sfenner } else { 348111726Sfenner /*(*/ 349276788Sdelphij ND_PRINT((ndo, " ?)")); 350111726Sfenner } 351127668Sbms break; 352127668Sbms default: 353276788Sdelphij ND_PRINT((ndo, " type %d)", EXTRACT_16BITS(tp))); 354127668Sbms break; 355111726Sfenner } 35675115Sfenner break; 357172683Smlaier case DH6OPT_IA_ADDR: 358214478Srpaulo if (optlen < 24) { 359214478Srpaulo /*(*/ 360276788Sdelphij ND_PRINT((ndo, " ?)")); 361172683Smlaier break; 362172683Smlaier } 363214478Srpaulo tp = (u_char *)(dh6o + 1); 364276788Sdelphij ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[0]))); 365276788Sdelphij ND_PRINT((ndo, " pltime:%u vltime:%u", 366214478Srpaulo EXTRACT_32BITS(&tp[16]), 367276788Sdelphij EXTRACT_32BITS(&tp[20]))); 368214478Srpaulo if (optlen > 24) { 369172683Smlaier /* there are sub-options */ 370276788Sdelphij dhcp6opt_print(ndo, tp + 24, tp + optlen); 371172683Smlaier } 372276788Sdelphij ND_PRINT((ndo, ")")); 373172683Smlaier break; 374127668Sbms case DH6OPT_ORO: 375190207Srpaulo case DH6OPT_ERO: 376127668Sbms if (optlen % 2) { 377276788Sdelphij ND_PRINT((ndo, " ?)")); 378127668Sbms break; 379127668Sbms } 380127668Sbms tp = (u_char *)(dh6o + 1); 381127668Sbms for (i = 0; i < optlen; i += 2) { 382276788Sdelphij ND_PRINT((ndo, " %s", 383276788Sdelphij tok2str(dh6opt_str, "opt_%u", EXTRACT_16BITS(&tp[i])))); 384127668Sbms } 385276788Sdelphij ND_PRINT((ndo, ")")); 386127668Sbms break; 387127668Sbms case DH6OPT_PREFERENCE: 388127668Sbms if (optlen != 1) { 389276788Sdelphij ND_PRINT((ndo, " ?)")); 390127668Sbms break; 391127668Sbms } 392214478Srpaulo tp = (u_char *)(dh6o + 1); 393276788Sdelphij ND_PRINT((ndo, " %d)", *tp)); 394127668Sbms break; 395127668Sbms case DH6OPT_ELAPSED_TIME: 396127668Sbms if (optlen != 2) { 397276788Sdelphij ND_PRINT((ndo, " ?)")); 398127668Sbms break; 399127668Sbms } 400214478Srpaulo tp = (u_char *)(dh6o + 1); 401276788Sdelphij ND_PRINT((ndo, " %d)", EXTRACT_16BITS(tp))); 402127668Sbms break; 403127668Sbms case DH6OPT_RELAY_MSG: 404276788Sdelphij ND_PRINT((ndo, " (")); 405214478Srpaulo tp = (u_char *)(dh6o + 1); 406276788Sdelphij dhcp6_print(ndo, tp, optlen); 407276788Sdelphij ND_PRINT((ndo, ")")); 408127668Sbms break; 409146773Ssam case DH6OPT_AUTH: 410214478Srpaulo if (optlen < 11) { 411276788Sdelphij ND_PRINT((ndo, " ?)")); 412146773Ssam break; 413146773Ssam } 414214478Srpaulo tp = (u_char *)(dh6o + 1); 415214478Srpaulo auth_proto = *tp; 416214478Srpaulo switch (auth_proto) { 417146773Ssam case DH6OPT_AUTHPROTO_DELAYED: 418276788Sdelphij ND_PRINT((ndo, " proto: delayed")); 419146773Ssam break; 420146773Ssam case DH6OPT_AUTHPROTO_RECONFIG: 421276788Sdelphij ND_PRINT((ndo, " proto: reconfigure")); 422146773Ssam break; 423146773Ssam default: 424276788Sdelphij ND_PRINT((ndo, " proto: %d", auth_proto)); 425146773Ssam break; 426146773Ssam } 427214478Srpaulo tp++; 428214478Srpaulo switch (*tp) { 429146773Ssam case DH6OPT_AUTHALG_HMACMD5: 430146773Ssam /* XXX: may depend on the protocol */ 431276788Sdelphij ND_PRINT((ndo, ", alg: HMAC-MD5")); 432146773Ssam break; 433146773Ssam default: 434276788Sdelphij ND_PRINT((ndo, ", alg: %d", *tp)); 435146773Ssam break; 436146773Ssam } 437214478Srpaulo tp++; 438214478Srpaulo switch (*tp) { 439146773Ssam case DH6OPT_AUTHRDM_MONOCOUNTER: 440276788Sdelphij ND_PRINT((ndo, ", RDM: mono")); 441146773Ssam break; 442146773Ssam default: 443276788Sdelphij ND_PRINT((ndo, ", RDM: %d", *tp)); 444146773Ssam break; 445146773Ssam } 446214478Srpaulo tp++; 447276788Sdelphij ND_PRINT((ndo, ", RD:")); 448214478Srpaulo for (i = 0; i < 4; i++, tp += 2) 449276788Sdelphij ND_PRINT((ndo, " %04x", EXTRACT_16BITS(tp))); 450146773Ssam 451146773Ssam /* protocol dependent part */ 452214478Srpaulo authinfolen = optlen - 11; 453214478Srpaulo switch (auth_proto) { 454146773Ssam case DH6OPT_AUTHPROTO_DELAYED: 455146773Ssam if (authinfolen == 0) 456146773Ssam break; 457146773Ssam if (authinfolen < 20) { 458276788Sdelphij ND_PRINT((ndo, " ??")); 459146773Ssam break; 460146773Ssam } 461146773Ssam authrealmlen = authinfolen - 20; 462146773Ssam if (authrealmlen > 0) { 463276788Sdelphij ND_PRINT((ndo, ", realm: ")); 464146773Ssam } 465146773Ssam for (i = 0; i < authrealmlen; i++, tp++) 466276788Sdelphij ND_PRINT((ndo, "%02x", *tp)); 467276788Sdelphij ND_PRINT((ndo, ", key ID: %08x", EXTRACT_32BITS(tp))); 468146773Ssam tp += 4; 469276788Sdelphij ND_PRINT((ndo, ", HMAC-MD5:")); 470146773Ssam for (i = 0; i < 4; i++, tp+= 4) 471276788Sdelphij ND_PRINT((ndo, " %08x", EXTRACT_32BITS(tp))); 472146773Ssam break; 473146773Ssam case DH6OPT_AUTHPROTO_RECONFIG: 474146773Ssam if (authinfolen != 17) { 475276788Sdelphij ND_PRINT((ndo, " ??")); 476146773Ssam break; 477146773Ssam } 478146773Ssam switch (*tp++) { 479146773Ssam case DH6OPT_AUTHRECONFIG_KEY: 480276788Sdelphij ND_PRINT((ndo, " reconfig-key")); 481146773Ssam break; 482146773Ssam case DH6OPT_AUTHRECONFIG_HMACMD5: 483276788Sdelphij ND_PRINT((ndo, " type: HMAC-MD5")); 484146773Ssam break; 485146773Ssam default: 486276788Sdelphij ND_PRINT((ndo, " type: ??")); 487146773Ssam break; 488146773Ssam } 489276788Sdelphij ND_PRINT((ndo, " value:")); 490146773Ssam for (i = 0; i < 4; i++, tp+= 4) 491276788Sdelphij ND_PRINT((ndo, " %08x", EXTRACT_32BITS(tp))); 492146773Ssam break; 493146773Ssam default: 494276788Sdelphij ND_PRINT((ndo, " ??")); 495146773Ssam break; 496146773Ssam } 497146773Ssam 498276788Sdelphij ND_PRINT((ndo, ")")); 499146773Ssam break; 500127668Sbms case DH6OPT_RAPID_COMMIT: /* nothing todo */ 501276788Sdelphij ND_PRINT((ndo, ")")); 502127668Sbms break; 503127668Sbms case DH6OPT_INTERFACE_ID: 504190207Srpaulo case DH6OPT_SUBSCRIBER_ID: 505127668Sbms /* 506127668Sbms * Since we cannot predict the encoding, print hex dump 507127668Sbms * at most 10 characters. 508127668Sbms */ 509214478Srpaulo tp = (u_char *)(dh6o + 1); 510276788Sdelphij ND_PRINT((ndo, " ")); 511127668Sbms for (i = 0; i < optlen && i < 10; i++) 512276788Sdelphij ND_PRINT((ndo, "%02x", tp[i])); 513276788Sdelphij ND_PRINT((ndo, "...)")); 514127668Sbms break; 515127668Sbms case DH6OPT_RECONF_MSG: 516127668Sbms tp = (u_char *)(dh6o + 1); 517127668Sbms switch (*tp) { 518127668Sbms case DH6_RENEW: 519276788Sdelphij ND_PRINT((ndo, " for renew)")); 520127668Sbms break; 521127668Sbms case DH6_INFORM_REQ: 522276788Sdelphij ND_PRINT((ndo, " for inf-req)")); 523127668Sbms break; 524127668Sbms default: 525276788Sdelphij ND_PRINT((ndo, " for ?\?\?(%02x))", *tp)); 526127668Sbms break; 527127668Sbms } 528127668Sbms break; 529127668Sbms case DH6OPT_RECONF_ACCEPT: /* nothing todo */ 530276788Sdelphij ND_PRINT((ndo, ")")); 531127668Sbms break; 532127668Sbms case DH6OPT_SIP_SERVER_A: 533276788Sdelphij case DH6OPT_DNS_SERVERS: 534276788Sdelphij case DH6OPT_SNTP_SERVERS: 535172683Smlaier case DH6OPT_NIS_SERVERS: 536172683Smlaier case DH6OPT_NISP_SERVERS: 537172683Smlaier case DH6OPT_BCMCS_SERVER_A: 538190207Srpaulo case DH6OPT_PANA_AGENT: 539190207Srpaulo case DH6OPT_LQ_CLIENT_LINK: 540111726Sfenner if (optlen % 16) { 541276788Sdelphij ND_PRINT((ndo, " ?)")); 542111726Sfenner break; 543111726Sfenner } 544111726Sfenner tp = (u_char *)(dh6o + 1); 545111726Sfenner for (i = 0; i < optlen; i += 16) 546276788Sdelphij ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[i]))); 547276788Sdelphij ND_PRINT((ndo, ")")); 548127668Sbms break; 549276788Sdelphij case DH6OPT_SIP_SERVER_D: 550276788Sdelphij case DH6OPT_DOMAIN_LIST: 551276788Sdelphij tp = (u_char *)(dh6o + 1); 552276788Sdelphij while (tp < cp + sizeof(*dh6o) + optlen) { 553276788Sdelphij ND_PRINT((ndo, " ")); 554276788Sdelphij if ((tp = ns_nprint(ndo, tp, cp + sizeof(*dh6o) + optlen)) == NULL) 555276788Sdelphij goto trunc; 556276788Sdelphij } 557276788Sdelphij ND_PRINT((ndo, ")")); 558276788Sdelphij break; 559127668Sbms case DH6OPT_STATUS_CODE: 560127668Sbms if (optlen < 2) { 561276788Sdelphij ND_PRINT((ndo, " ?)")); 562127668Sbms break; 563127668Sbms } 564214478Srpaulo tp = (u_char *)(dh6o + 1); 565276788Sdelphij ND_PRINT((ndo, " %s)", dhcp6stcode(EXTRACT_16BITS(&tp[0])))); 566127668Sbms break; 567127668Sbms case DH6OPT_IA_NA: 568127668Sbms case DH6OPT_IA_PD: 569214478Srpaulo if (optlen < 12) { 570276788Sdelphij ND_PRINT((ndo, " ?)")); 571127668Sbms break; 572127668Sbms } 573214478Srpaulo tp = (u_char *)(dh6o + 1); 574276788Sdelphij ND_PRINT((ndo, " IAID:%u T1:%u T2:%u", 575214478Srpaulo EXTRACT_32BITS(&tp[0]), 576214478Srpaulo EXTRACT_32BITS(&tp[4]), 577276788Sdelphij EXTRACT_32BITS(&tp[8]))); 578214478Srpaulo if (optlen > 12) { 579127668Sbms /* there are sub-options */ 580276788Sdelphij dhcp6opt_print(ndo, tp + 12, tp + optlen); 581127668Sbms } 582276788Sdelphij ND_PRINT((ndo, ")")); 583127668Sbms break; 584190207Srpaulo case DH6OPT_IA_TA: 585190207Srpaulo if (optlen < 4) { 586276788Sdelphij ND_PRINT((ndo, " ?)")); 587190207Srpaulo break; 588190207Srpaulo } 589214478Srpaulo tp = (u_char *)(dh6o + 1); 590276788Sdelphij ND_PRINT((ndo, " IAID:%u", EXTRACT_32BITS(tp))); 591190207Srpaulo if (optlen > 4) { 592190207Srpaulo /* there are sub-options */ 593276788Sdelphij dhcp6opt_print(ndo, tp + 4, tp + optlen); 594190207Srpaulo } 595276788Sdelphij ND_PRINT((ndo, ")")); 596190207Srpaulo break; 597127668Sbms case DH6OPT_IA_PD_PREFIX: 598214478Srpaulo if (optlen < 25) { 599276788Sdelphij ND_PRINT((ndo, " ?)")); 600127668Sbms break; 601127668Sbms } 602214478Srpaulo tp = (u_char *)(dh6o + 1); 603276788Sdelphij ND_PRINT((ndo, " %s/%d", ip6addr_string(ndo, &tp[9]), tp[8])); 604276788Sdelphij ND_PRINT((ndo, " pltime:%u vltime:%u", 605214478Srpaulo EXTRACT_32BITS(&tp[0]), 606276788Sdelphij EXTRACT_32BITS(&tp[4]))); 607214478Srpaulo if (optlen > 25) { 608127668Sbms /* there are sub-options */ 609276788Sdelphij dhcp6opt_print(ndo, tp + 25, tp + optlen); 610127668Sbms } 611276788Sdelphij ND_PRINT((ndo, ")")); 612127668Sbms break; 613146773Ssam case DH6OPT_LIFETIME: 614190207Srpaulo case DH6OPT_CLT_TIME: 615146773Ssam if (optlen != 4) { 616276788Sdelphij ND_PRINT((ndo, " ?)")); 617146773Ssam break; 618146773Ssam } 619214478Srpaulo tp = (u_char *)(dh6o + 1); 620276788Sdelphij ND_PRINT((ndo, " %d)", EXTRACT_32BITS(tp))); 621146773Ssam break; 622190207Srpaulo case DH6OPT_REMOTE_ID: 623190207Srpaulo if (optlen < 4) { 624276788Sdelphij ND_PRINT((ndo, " ?)")); 625190207Srpaulo break; 626190207Srpaulo } 627190207Srpaulo tp = (u_char *)(dh6o + 1); 628276788Sdelphij ND_PRINT((ndo, " %d ", EXTRACT_32BITS(tp))); 629190207Srpaulo /* 630190207Srpaulo * Print hex dump first 10 characters. 631190207Srpaulo */ 632190207Srpaulo for (i = 4; i < optlen && i < 14; i++) 633276788Sdelphij ND_PRINT((ndo, "%02x", tp[i])); 634276788Sdelphij ND_PRINT((ndo, "...)")); 635190207Srpaulo break; 636190207Srpaulo case DH6OPT_LQ_QUERY: 637190207Srpaulo if (optlen < 17) { 638276788Sdelphij ND_PRINT((ndo, " ?)")); 639190207Srpaulo break; 640190207Srpaulo } 641190207Srpaulo tp = (u_char *)(dh6o + 1); 642190207Srpaulo switch (*tp) { 643190207Srpaulo case 1: 644276788Sdelphij ND_PRINT((ndo, " by-address")); 645190207Srpaulo break; 646190207Srpaulo case 2: 647276788Sdelphij ND_PRINT((ndo, " by-clientID")); 648190207Srpaulo break; 649190207Srpaulo default: 650276788Sdelphij ND_PRINT((ndo, " type_%d", (int)*tp)); 651190207Srpaulo break; 652190207Srpaulo } 653276788Sdelphij ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[1]))); 654190207Srpaulo if (optlen > 17) { 655190207Srpaulo /* there are query-options */ 656276788Sdelphij dhcp6opt_print(ndo, tp + 17, tp + optlen); 657190207Srpaulo } 658276788Sdelphij ND_PRINT((ndo, ")")); 659190207Srpaulo break; 660190207Srpaulo case DH6OPT_CLIENT_DATA: 661214478Srpaulo tp = (u_char *)(dh6o + 1); 662190207Srpaulo if (optlen > 0) { 663190207Srpaulo /* there are encapsulated options */ 664276788Sdelphij dhcp6opt_print(ndo, tp, tp + optlen); 665190207Srpaulo } 666276788Sdelphij ND_PRINT((ndo, ")")); 667190207Srpaulo break; 668190207Srpaulo case DH6OPT_LQ_RELAY_DATA: 669190207Srpaulo if (optlen < 16) { 670276788Sdelphij ND_PRINT((ndo, " ?)")); 671190207Srpaulo break; 672190207Srpaulo } 673190207Srpaulo tp = (u_char *)(dh6o + 1); 674276788Sdelphij ND_PRINT((ndo, " %s ", ip6addr_string(ndo, &tp[0]))); 675190207Srpaulo /* 676190207Srpaulo * Print hex dump first 10 characters. 677190207Srpaulo */ 678190207Srpaulo for (i = 16; i < optlen && i < 26; i++) 679276788Sdelphij ND_PRINT((ndo, "%02x", tp[i])); 680276788Sdelphij ND_PRINT((ndo, "...)")); 681190207Srpaulo break; 682276788Sdelphij case DH6OPT_NTP_SERVER: 683276788Sdelphij if (optlen < 4) { 684276788Sdelphij ND_PRINT((ndo, " ?)")); 685276788Sdelphij break; 686276788Sdelphij } 687276788Sdelphij tp = (u_char *)(dh6o + 1); 688276788Sdelphij while (tp < cp + sizeof(*dh6o) + optlen - 4) { 689276788Sdelphij subopt_code = EXTRACT_16BITS(tp); 690276788Sdelphij tp += 2; 691276788Sdelphij subopt_len = EXTRACT_16BITS(tp); 692276788Sdelphij tp += 2; 693276788Sdelphij if (tp + subopt_len > cp + sizeof(*dh6o) + optlen) 694276788Sdelphij goto trunc; 695276788Sdelphij ND_PRINT((ndo, " subopt:%d", subopt_code)); 696276788Sdelphij switch (subopt_code) { 697276788Sdelphij case DH6OPT_NTP_SUBOPTION_SRV_ADDR: 698276788Sdelphij case DH6OPT_NTP_SUBOPTION_MC_ADDR: 699276788Sdelphij if (subopt_len != 16) { 700276788Sdelphij ND_PRINT((ndo, " ?")); 701276788Sdelphij break; 702276788Sdelphij } 703276788Sdelphij ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[0]))); 704276788Sdelphij break; 705276788Sdelphij case DH6OPT_NTP_SUBOPTION_SRV_FQDN: 706276788Sdelphij ND_PRINT((ndo, " ")); 707276788Sdelphij if (ns_nprint(ndo, tp, tp + subopt_len) == NULL) 708276788Sdelphij goto trunc; 709276788Sdelphij break; 710276788Sdelphij default: 711276788Sdelphij ND_PRINT((ndo, " ?")); 712276788Sdelphij break; 713276788Sdelphij } 714276788Sdelphij tp += subopt_len; 715276788Sdelphij } 716276788Sdelphij ND_PRINT((ndo, ")")); 717276788Sdelphij break; 718251158Sdelphij case DH6OPT_AFTR_NAME: 719251158Sdelphij if (optlen < 3) { 720276788Sdelphij ND_PRINT((ndo, " ?)")); 721251158Sdelphij break; 722251158Sdelphij } 723251158Sdelphij tp = (u_char *)(dh6o + 1); 724276788Sdelphij remain_len = optlen; 725276788Sdelphij ND_PRINT((ndo, " ")); 726251158Sdelphij /* Encoding is described in section 3.1 of RFC 1035 */ 727251158Sdelphij while (remain_len && *tp) { 728251158Sdelphij label_len = *tp++; 729251158Sdelphij if (label_len < remain_len - 1) { 730276788Sdelphij ND_PRINT((ndo, "%.*s", label_len, tp)); 731251158Sdelphij tp += label_len; 732251158Sdelphij remain_len -= (label_len + 1); 733276788Sdelphij if(*tp) ND_PRINT((ndo, ".")); 734251158Sdelphij } else { 735276788Sdelphij ND_PRINT((ndo, " ?")); 736251158Sdelphij break; 737251158Sdelphij } 738251158Sdelphij } 739276788Sdelphij ND_PRINT((ndo, ")")); 740251158Sdelphij break; 74156893Sfenner default: 742276788Sdelphij ND_PRINT((ndo, ")")); 74356893Sfenner break; 74456893Sfenner } 74556893Sfenner 746111726Sfenner cp += sizeof(*dh6o) + optlen; 74756893Sfenner } 74856893Sfenner return; 74956893Sfenner 75056893Sfennertrunc: 751276788Sdelphij ND_PRINT((ndo, "[|dhcp6ext]")); 75256893Sfenner} 75356893Sfenner 75456893Sfenner/* 755111726Sfenner * Print dhcp6 packets 75656893Sfenner */ 75756893Sfennervoid 758276788Sdelphijdhcp6_print(netdissect_options *ndo, 759276788Sdelphij const u_char *cp, u_int length) 76056893Sfenner{ 761111726Sfenner struct dhcp6 *dh6; 762127668Sbms struct dhcp6_relay *dh6relay; 763127668Sbms const u_char *ep; 76456893Sfenner u_char *extp; 765111726Sfenner const char *name; 76656893Sfenner 767276788Sdelphij ND_PRINT((ndo, "dhcp6")); 76856893Sfenner 769276788Sdelphij ep = (u_char *)ndo->ndo_snapend; 770127668Sbms if (cp + length < ep) 771127668Sbms ep = cp + length; 77256893Sfenner 773111726Sfenner dh6 = (struct dhcp6 *)cp; 774127668Sbms dh6relay = (struct dhcp6_relay *)cp; 775276788Sdelphij ND_TCHECK(dh6->dh6_xid); 776276788Sdelphij name = tok2str(dh6_msgtype_str, "msgtype-%u", dh6->dh6_msgtype); 777111726Sfenner 778276788Sdelphij if (!ndo->ndo_vflag) { 779276788Sdelphij ND_PRINT((ndo, " %s", name)); 780111726Sfenner return; 781111726Sfenner } 782111726Sfenner 783111726Sfenner /* XXX relay agent messages have to be handled differently */ 784111726Sfenner 785276788Sdelphij ND_PRINT((ndo, " %s (", name)); /*)*/ 786127668Sbms if (dh6->dh6_msgtype != DH6_RELAY_FORW && 787127668Sbms dh6->dh6_msgtype != DH6_RELAY_REPLY) { 788276788Sdelphij ND_PRINT((ndo, "xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK)); 789127668Sbms extp = (u_char *)(dh6 + 1); 790276788Sdelphij dhcp6opt_print(ndo, extp, ep); 791127668Sbms } else { /* relay messages */ 792127668Sbms struct in6_addr addr6; 793127668Sbms 794276788Sdelphij ND_TCHECK(dh6relay->dh6relay_peeraddr); 795127668Sbms 796127668Sbms memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6)); 797276788Sdelphij ND_PRINT((ndo, "linkaddr=%s", ip6addr_string(ndo, &addr6))); 798127668Sbms 799127668Sbms memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6)); 800276788Sdelphij ND_PRINT((ndo, " peeraddr=%s", ip6addr_string(ndo, &addr6))); 801127668Sbms 802276788Sdelphij dhcp6opt_print(ndo, (u_char *)(dh6relay + 1), ep); 803127668Sbms } 804111726Sfenner /*(*/ 805276788Sdelphij ND_PRINT((ndo, ")")); 80656893Sfenner return; 80756893Sfenner 80856893Sfennertrunc: 809276788Sdelphij ND_PRINT((ndo, "[|dhcp6]")); 81056893Sfenner} 811