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 31127668Sbms * 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, 39251158Sdelphij * RFC6334: Dual-Stack Lite option, 40111726Sfenner */ 4156893Sfenner 4256893Sfenner#ifndef lint 43127668Sbmsstatic const char rcsid[] _U_ = 44214478Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.37 2008-02-06 10:26:09 guy Exp $"; 4556893Sfenner#endif 4656893Sfenner 4756893Sfenner#ifdef HAVE_CONFIG_H 4856893Sfenner#include "config.h" 4956893Sfenner#endif 5056893Sfenner 51127668Sbms#include <tcpdump-stdinc.h> 5256893Sfenner 5356893Sfenner#include <stdio.h> 5456893Sfenner#include <string.h> 5556893Sfenner 5656893Sfenner#include "interface.h" 5756893Sfenner#include "addrtoname.h" 58127668Sbms#include "extract.h" 5956893Sfenner 60127668Sbms/* lease duration */ 61127668Sbms#define DHCP6_DURATITION_INFINITE 0xffffffff 62127668Sbms 63111726Sfenner/* Error Values */ 64111726Sfenner#define DH6ERR_FAILURE 16 65111726Sfenner#define DH6ERR_AUTHFAIL 17 66111726Sfenner#define DH6ERR_POORLYFORMED 18 67111726Sfenner#define DH6ERR_UNAVAIL 19 68111726Sfenner#define DH6ERR_OPTUNAVAIL 20 6956893Sfenner 70111726Sfenner/* Message type */ 71127668Sbms#define DH6_SOLICIT 1 72127668Sbms#define DH6_ADVERTISE 2 73127668Sbms#define DH6_REQUEST 3 74127668Sbms#define DH6_CONFIRM 4 75127668Sbms#define DH6_RENEW 5 76127668Sbms#define DH6_REBIND 6 77111726Sfenner#define DH6_REPLY 7 78127668Sbms#define DH6_RELEASE 8 79127668Sbms#define DH6_DECLINE 9 80127668Sbms#define DH6_RECONFIGURE 10 81111726Sfenner#define DH6_INFORM_REQ 11 82127668Sbms#define DH6_RELAY_FORW 12 83127668Sbms#define DH6_RELAY_REPLY 13 84190207Srpaulo#define DH6_LEASEQUERY 14 85190207Srpaulo#define DH6_LQ_REPLY 15 8656893Sfenner 87111726Sfenner/* DHCP6 base packet format */ 88111726Sfennerstruct dhcp6 { 89111726Sfenner union { 90111726Sfenner u_int8_t m; 91111726Sfenner u_int32_t x; 92111726Sfenner } dh6_msgtypexid; 93111726Sfenner /* options follow */ 94127668Sbms}; 95111726Sfenner#define dh6_msgtype dh6_msgtypexid.m 96111726Sfenner#define dh6_xid dh6_msgtypexid.x 97111726Sfenner#define DH6_XIDMASK 0x00ffffff 9856893Sfenner 99127668Sbms/* DHCPv6 relay messages */ 100127668Sbmsstruct dhcp6_relay { 101127668Sbms u_int8_t dh6relay_msgtype; 102127668Sbms u_int8_t dh6relay_hcnt; 103127668Sbms u_int8_t dh6relay_linkaddr[16]; /* XXX: badly aligned */ 104127668Sbms u_int8_t dh6relay_peeraddr[16]; 105127668Sbms /* options follow */ 106127668Sbms}; 107127668Sbms 108127668Sbms/* options */ 109127668Sbms#define DH6OPT_CLIENTID 1 110127668Sbms#define DH6OPT_SERVERID 2 111127668Sbms#define DH6OPT_IA_NA 3 112172683Smlaier#define DH6OPT_IA_TA 4 113172683Smlaier#define DH6OPT_IA_ADDR 5 114127668Sbms#define DH6OPT_ORO 6 115127668Sbms#define DH6OPT_PREFERENCE 7 116127668Sbms# define DH6OPT_PREF_MAX 255 117127668Sbms#define DH6OPT_ELAPSED_TIME 8 118127668Sbms#define DH6OPT_RELAY_MSG 9 119127668Sbms/*#define DH6OPT_SERVER_MSG 10 deprecated */ 120127668Sbms#define DH6OPT_AUTH 11 121146773Ssam# define DH6OPT_AUTHPROTO_DELAYED 2 122146773Ssam# define DH6OPT_AUTHPROTO_RECONFIG 3 123146773Ssam# define DH6OPT_AUTHALG_HMACMD5 1 124146773Ssam# define DH6OPT_AUTHRDM_MONOCOUNTER 0 125146773Ssam# define DH6OPT_AUTHRECONFIG_KEY 1 126146773Ssam# define DH6OPT_AUTHRECONFIG_HMACMD5 2 127127668Sbms#define DH6OPT_UNICAST 12 128127668Sbms#define DH6OPT_STATUS_CODE 13 129127668Sbms# define DH6OPT_STCODE_SUCCESS 0 130127668Sbms# define DH6OPT_STCODE_UNSPECFAIL 1 131127668Sbms# define DH6OPT_STCODE_NOADDRAVAIL 2 132127668Sbms# define DH6OPT_STCODE_NOBINDING 3 133127668Sbms# define DH6OPT_STCODE_NOTONLINK 4 134127668Sbms# define DH6OPT_STCODE_USEMULTICAST 5 135127668Sbms# define DH6OPT_STCODE_NOPREFIXAVAIL 6 136190207Srpaulo# define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7 137190207Srpaulo# define DH6OPT_STCODE_MALFORMEDQUERY 8 138190207Srpaulo# define DH6OPT_STCODE_NOTCONFIGURED 9 139190207Srpaulo# define DH6OPT_STCODE_NOTALLOWED 10 140127668Sbms#define DH6OPT_RAPID_COMMIT 14 141127668Sbms#define DH6OPT_USER_CLASS 15 142127668Sbms#define DH6OPT_VENDOR_CLASS 16 143127668Sbms#define DH6OPT_VENDOR_OPTS 17 144127668Sbms#define DH6OPT_INTERFACE_ID 18 145127668Sbms#define DH6OPT_RECONF_MSG 19 146127668Sbms#define DH6OPT_RECONF_ACCEPT 20 147127668Sbms#define DH6OPT_SIP_SERVER_D 21 148127668Sbms#define DH6OPT_SIP_SERVER_A 22 149127668Sbms#define DH6OPT_DNS 23 150127668Sbms#define DH6OPT_DNSNAME 24 151146773Ssam#define DH6OPT_IA_PD 25 152146773Ssam#define DH6OPT_IA_PD_PREFIX 26 153172683Smlaier#define DH6OPT_NIS_SERVERS 27 154172683Smlaier#define DH6OPT_NISP_SERVERS 28 155172683Smlaier#define DH6OPT_NIS_NAME 29 156172683Smlaier#define DH6OPT_NISP_NAME 30 157172683Smlaier#define DH6OPT_NTP_SERVERS 31 158172683Smlaier#define DH6OPT_LIFETIME 32 159172683Smlaier#define DH6OPT_BCMCS_SERVER_D 33 160172683Smlaier#define DH6OPT_BCMCS_SERVER_A 34 161172683Smlaier#define DH6OPT_GEOCONF_CIVIC 36 162172683Smlaier#define DH6OPT_REMOTE_ID 37 163172683Smlaier#define DH6OPT_SUBSCRIBER_ID 38 164172683Smlaier#define DH6OPT_CLIENT_FQDN 39 165190207Srpaulo#define DH6OPT_PANA_AGENT 40 166190207Srpaulo#define DH6OPT_NEW_POSIX_TIMEZONE 41 167190207Srpaulo#define DH6OPT_NEW_TZDB_TIMEZONE 42 168190207Srpaulo#define DH6OPT_ERO 43 169190207Srpaulo#define DH6OPT_LQ_QUERY 44 170190207Srpaulo#define DH6OPT_CLIENT_DATA 45 171190207Srpaulo#define DH6OPT_CLT_TIME 46 172190207Srpaulo#define DH6OPT_LQ_RELAY_DATA 47 173190207Srpaulo#define DH6OPT_LQ_CLIENT_LINK 48 174251158Sdelphij#define DH6OPT_AFTR_NAME 64 175127668Sbms 176111726Sfennerstruct dhcp6opt { 177111726Sfenner u_int16_t dh6opt_type; 178111726Sfenner u_int16_t dh6opt_len; 179111726Sfenner /* type-dependent data follows */ 180127668Sbms}; 18156893Sfenner 182127668Sbmsstatic const char * 183127668Sbmsdhcp6opt_name(int type) 184127668Sbms{ 185127668Sbms static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */ 186127668Sbms 187127668Sbms if (type > 65535) 188214478Srpaulo return "INVALID-option"; 189127668Sbms 190127668Sbms switch(type) { 191127668Sbms case DH6OPT_CLIENTID: 192214478Srpaulo return "client-ID"; 193127668Sbms case DH6OPT_SERVERID: 194214478Srpaulo return "server-ID"; 195127668Sbms case DH6OPT_IA_NA: 196127668Sbms return "IA_NA"; 197172683Smlaier case DH6OPT_IA_TA: 198172683Smlaier return "IA_TA"; 199172683Smlaier case DH6OPT_IA_ADDR: 200172683Smlaier return "IA_ADDR"; 201127668Sbms case DH6OPT_ORO: 202214478Srpaulo return "option-request"; 203127668Sbms case DH6OPT_PREFERENCE: 204127668Sbms return "preference"; 205127668Sbms case DH6OPT_ELAPSED_TIME: 206214478Srpaulo return "elapsed-time"; 207127668Sbms case DH6OPT_RELAY_MSG: 208214478Srpaulo return "relay-message"; 209146773Ssam case DH6OPT_AUTH: 210146773Ssam return "authentication"; 211146773Ssam case DH6OPT_UNICAST: 212214478Srpaulo return "server-unicast"; 213127668Sbms case DH6OPT_STATUS_CODE: 214214478Srpaulo return "status-code"; 215127668Sbms case DH6OPT_RAPID_COMMIT: 216214478Srpaulo return "rapid-commit"; 217146773Ssam case DH6OPT_USER_CLASS: 218214478Srpaulo return "user-class"; 219146773Ssam case DH6OPT_VENDOR_CLASS: 220214478Srpaulo return "vendor-class"; 221146773Ssam case DH6OPT_VENDOR_OPTS: 222214478Srpaulo return "vendor-specific-info"; 223127668Sbms case DH6OPT_INTERFACE_ID: 224214478Srpaulo return "interface-ID"; 225127668Sbms case DH6OPT_RECONF_MSG: 226214478Srpaulo return "reconfigure-message"; 227127668Sbms case DH6OPT_RECONF_ACCEPT: 228214478Srpaulo return "reconfigure-accept"; 229127668Sbms case DH6OPT_SIP_SERVER_D: 230214478Srpaulo return "SIP-servers-domain"; 231127668Sbms case DH6OPT_SIP_SERVER_A: 232214478Srpaulo return "SIP-servers-address"; 233127668Sbms case DH6OPT_DNS: 234235530Sdelphij return "DNS-server"; 235146773Ssam case DH6OPT_DNSNAME: 236235530Sdelphij return "DNS-search-list"; 237127668Sbms case DH6OPT_IA_PD: 238127668Sbms return "IA_PD"; 239127668Sbms case DH6OPT_IA_PD_PREFIX: 240214478Srpaulo return "IA_PD-prefix"; 241127668Sbms case DH6OPT_NTP_SERVERS: 242235530Sdelphij return "NTP-server"; 243146773Ssam case DH6OPT_LIFETIME: 244146773Ssam return "lifetime"; 245172683Smlaier case DH6OPT_NIS_SERVERS: 246214478Srpaulo return "NIS-server"; 247172683Smlaier case DH6OPT_NISP_SERVERS: 248214478Srpaulo return "NIS+-server"; 249172683Smlaier case DH6OPT_NIS_NAME: 250214478Srpaulo return "NIS-domain-name"; 251172683Smlaier case DH6OPT_NISP_NAME: 252214478Srpaulo return "NIS+-domain-name"; 253172683Smlaier case DH6OPT_BCMCS_SERVER_D: 254214478Srpaulo return "BCMCS-domain-name"; 255172683Smlaier case DH6OPT_BCMCS_SERVER_A: 256214478Srpaulo return "BCMCS-server"; 257172683Smlaier case DH6OPT_GEOCONF_CIVIC: 258214478Srpaulo return "Geoconf-Civic"; 259172683Smlaier case DH6OPT_REMOTE_ID: 260214478Srpaulo return "Remote-ID"; 261172683Smlaier case DH6OPT_SUBSCRIBER_ID: 262214478Srpaulo return "Subscriber-ID"; 263172683Smlaier case DH6OPT_CLIENT_FQDN: 264214478Srpaulo return "Client-FQDN"; 265190207Srpaulo case DH6OPT_PANA_AGENT: 266214478Srpaulo return "PANA-agent"; 267190207Srpaulo case DH6OPT_NEW_POSIX_TIMEZONE: 268214478Srpaulo return "POSIX-timezone"; 269190207Srpaulo case DH6OPT_NEW_TZDB_TIMEZONE: 270214478Srpaulo return "POSIX-tz-database"; 271190207Srpaulo case DH6OPT_ERO: 272214478Srpaulo return "Echo-request-option"; 273190207Srpaulo case DH6OPT_LQ_QUERY: 274214478Srpaulo return "Lease-query"; 275190207Srpaulo case DH6OPT_CLIENT_DATA: 276214478Srpaulo return "LQ-client-data"; 277190207Srpaulo case DH6OPT_CLT_TIME: 278214478Srpaulo return "Clt-time"; 279190207Srpaulo case DH6OPT_LQ_RELAY_DATA: 280214478Srpaulo return "LQ-relay-data"; 281190207Srpaulo case DH6OPT_LQ_CLIENT_LINK: 282214478Srpaulo return "LQ-client-link"; 283251158Sdelphij case DH6OPT_AFTR_NAME: 284251158Sdelphij return "AFTR-Name"; 285127668Sbms default: 286127668Sbms snprintf(genstr, sizeof(genstr), "opt_%d", type); 287127668Sbms return(genstr); 288127668Sbms } 289127668Sbms} 290127668Sbms 291127668Sbmsstatic const char * 292127668Sbmsdhcp6stcode(int code) 293127668Sbms{ 294127668Sbms static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */ 295127668Sbms 296127668Sbms if (code > 255) 297127668Sbms return "INVALID code"; 298127668Sbms 299127668Sbms switch(code) { 300127668Sbms case DH6OPT_STCODE_SUCCESS: 301127668Sbms return "success"; 302127668Sbms case DH6OPT_STCODE_UNSPECFAIL: 303127668Sbms return "unspec failure"; 304127668Sbms case DH6OPT_STCODE_NOADDRAVAIL: 305127668Sbms return "no addresses"; 306127668Sbms case DH6OPT_STCODE_NOBINDING: 307127668Sbms return "no binding"; 308127668Sbms case DH6OPT_STCODE_NOTONLINK: 309127668Sbms return "not on-link"; 310127668Sbms case DH6OPT_STCODE_USEMULTICAST: 311127668Sbms return "use multicast"; 312127668Sbms case DH6OPT_STCODE_NOPREFIXAVAIL: 313127668Sbms return "no prefixes"; 314190207Srpaulo case DH6OPT_STCODE_UNKNOWNQUERYTYPE: 315190207Srpaulo return "unknown query type"; 316190207Srpaulo case DH6OPT_STCODE_MALFORMEDQUERY: 317190207Srpaulo return "malformed query"; 318190207Srpaulo case DH6OPT_STCODE_NOTCONFIGURED: 319190207Srpaulo return "not configured"; 320190207Srpaulo case DH6OPT_STCODE_NOTALLOWED: 321190207Srpaulo return "not allowed"; 322127668Sbms default: 323127668Sbms snprintf(genstr, sizeof(genstr), "code%d", code); 324127668Sbms return(genstr); 325127668Sbms } 326127668Sbms} 327127668Sbms 32856893Sfennerstatic void 329127668Sbmsdhcp6opt_print(const u_char *cp, const u_char *ep) 33056893Sfenner{ 331111726Sfenner struct dhcp6opt *dh6o; 332111726Sfenner u_char *tp; 333127668Sbms size_t i; 334127668Sbms u_int16_t opttype; 335111726Sfenner size_t optlen; 336214478Srpaulo u_int8_t auth_proto; 337146773Ssam u_int authinfolen, authrealmlen; 33856893Sfenner 33956893Sfenner if (cp == ep) 34056893Sfenner return; 34156893Sfenner while (cp < ep) { 342127668Sbms if (ep < cp + sizeof(*dh6o)) 343111726Sfenner goto trunc; 344111726Sfenner dh6o = (struct dhcp6opt *)cp; 345251158Sdelphij TCHECK(*dh6o); 346127668Sbms optlen = EXTRACT_16BITS(&dh6o->dh6opt_len); 347127668Sbms if (ep < cp + sizeof(*dh6o) + optlen) 348111726Sfenner goto trunc; 349127668Sbms opttype = EXTRACT_16BITS(&dh6o->dh6opt_type); 350127668Sbms printf(" (%s", dhcp6opt_name(opttype)); 351127668Sbms switch (opttype) { 352127668Sbms case DH6OPT_CLIENTID: 353127668Sbms case DH6OPT_SERVERID: 354111726Sfenner if (optlen < 2) { 355111726Sfenner /*(*/ 356127668Sbms printf(" ?)"); 357111726Sfenner break; 358111726Sfenner } 359111726Sfenner tp = (u_char *)(dh6o + 1); 360127668Sbms switch (EXTRACT_16BITS(tp)) { 361111726Sfenner case 1: 362111726Sfenner if (optlen >= 2 + 6) { 363127668Sbms printf(" hwaddr/time type %u time %u ", 364127668Sbms EXTRACT_16BITS(&tp[2]), 365127668Sbms EXTRACT_32BITS(&tp[4])); 366111726Sfenner for (i = 8; i < optlen; i++) 367111726Sfenner printf("%02x", tp[i]); 368111726Sfenner /*(*/ 369111726Sfenner printf(")"); 370111726Sfenner } else { 371111726Sfenner /*(*/ 372127668Sbms printf(" ?)"); 373111726Sfenner } 374111726Sfenner break; 375111726Sfenner case 2: 376111726Sfenner if (optlen >= 2 + 8) { 377111726Sfenner printf(" vid "); 378111726Sfenner for (i = 2; i < 2 + 8; i++) 379111726Sfenner printf("%02x", tp[i]); 380111726Sfenner /*(*/ 381111726Sfenner printf(")"); 382111726Sfenner } else { 383111726Sfenner /*(*/ 384127668Sbms printf(" ?)"); 385111726Sfenner } 386111726Sfenner break; 387111726Sfenner case 3: 388111726Sfenner if (optlen >= 2 + 2) { 389111726Sfenner printf(" hwaddr type %u ", 390127668Sbms EXTRACT_16BITS(&tp[2])); 391111726Sfenner for (i = 4; i < optlen; i++) 392111726Sfenner printf("%02x", tp[i]); 393111726Sfenner /*(*/ 394111726Sfenner printf(")"); 395111726Sfenner } else { 396111726Sfenner /*(*/ 397127668Sbms printf(" ?)"); 398111726Sfenner } 399127668Sbms break; 400127668Sbms default: 401127668Sbms printf(" type %d)", EXTRACT_16BITS(tp)); 402127668Sbms break; 403111726Sfenner } 40475115Sfenner break; 405172683Smlaier case DH6OPT_IA_ADDR: 406214478Srpaulo if (optlen < 24) { 407214478Srpaulo /*(*/ 408172683Smlaier printf(" ?)"); 409172683Smlaier break; 410172683Smlaier } 411214478Srpaulo tp = (u_char *)(dh6o + 1); 412214478Srpaulo printf(" %s", ip6addr_string(&tp[0])); 413214478Srpaulo printf(" pltime:%u vltime:%u", 414214478Srpaulo EXTRACT_32BITS(&tp[16]), 415214478Srpaulo EXTRACT_32BITS(&tp[20])); 416214478Srpaulo if (optlen > 24) { 417172683Smlaier /* there are sub-options */ 418251158Sdelphij dhcp6opt_print(tp + 24, tp + optlen); 419172683Smlaier } 420172683Smlaier printf(")"); 421172683Smlaier break; 422127668Sbms case DH6OPT_ORO: 423190207Srpaulo case DH6OPT_ERO: 424127668Sbms if (optlen % 2) { 425127668Sbms printf(" ?)"); 426127668Sbms break; 427127668Sbms } 428127668Sbms tp = (u_char *)(dh6o + 1); 429127668Sbms for (i = 0; i < optlen; i += 2) { 430214478Srpaulo printf(" %s", 431214478Srpaulo dhcp6opt_name(EXTRACT_16BITS(&tp[i]))); 432127668Sbms } 433127668Sbms printf(")"); 434127668Sbms break; 435127668Sbms case DH6OPT_PREFERENCE: 436127668Sbms if (optlen != 1) { 437127668Sbms printf(" ?)"); 438127668Sbms break; 439127668Sbms } 440214478Srpaulo tp = (u_char *)(dh6o + 1); 441214478Srpaulo printf(" %d)", *tp); 442127668Sbms break; 443127668Sbms case DH6OPT_ELAPSED_TIME: 444127668Sbms if (optlen != 2) { 445127668Sbms printf(" ?)"); 446127668Sbms break; 447127668Sbms } 448214478Srpaulo tp = (u_char *)(dh6o + 1); 449214478Srpaulo printf(" %d)", EXTRACT_16BITS(tp)); 450127668Sbms break; 451127668Sbms case DH6OPT_RELAY_MSG: 452127668Sbms printf(" ("); 453214478Srpaulo tp = (u_char *)(dh6o + 1); 454214478Srpaulo dhcp6_print(tp, optlen); 455127668Sbms printf(")"); 456127668Sbms break; 457146773Ssam case DH6OPT_AUTH: 458214478Srpaulo if (optlen < 11) { 459146773Ssam printf(" ?)"); 460146773Ssam break; 461146773Ssam } 462214478Srpaulo tp = (u_char *)(dh6o + 1); 463214478Srpaulo auth_proto = *tp; 464214478Srpaulo switch (auth_proto) { 465146773Ssam case DH6OPT_AUTHPROTO_DELAYED: 466146773Ssam printf(" proto: delayed"); 467146773Ssam break; 468146773Ssam case DH6OPT_AUTHPROTO_RECONFIG: 469146773Ssam printf(" proto: reconfigure"); 470146773Ssam break; 471146773Ssam default: 472214478Srpaulo printf(" proto: %d", auth_proto); 473146773Ssam break; 474146773Ssam } 475214478Srpaulo tp++; 476214478Srpaulo switch (*tp) { 477146773Ssam case DH6OPT_AUTHALG_HMACMD5: 478146773Ssam /* XXX: may depend on the protocol */ 479146773Ssam printf(", alg: HMAC-MD5"); 480146773Ssam break; 481146773Ssam default: 482214478Srpaulo printf(", alg: %d", *tp); 483146773Ssam break; 484146773Ssam } 485214478Srpaulo tp++; 486214478Srpaulo switch (*tp) { 487146773Ssam case DH6OPT_AUTHRDM_MONOCOUNTER: 488146773Ssam printf(", RDM: mono"); 489146773Ssam break; 490146773Ssam default: 491214478Srpaulo printf(", RDM: %d", *tp); 492146773Ssam break; 493146773Ssam } 494214478Srpaulo tp++; 495146773Ssam printf(", RD:"); 496214478Srpaulo for (i = 0; i < 4; i++, tp += 2) 497146773Ssam printf(" %04x", EXTRACT_16BITS(tp)); 498146773Ssam 499146773Ssam /* protocol dependent part */ 500214478Srpaulo authinfolen = optlen - 11; 501214478Srpaulo switch (auth_proto) { 502146773Ssam case DH6OPT_AUTHPROTO_DELAYED: 503146773Ssam if (authinfolen == 0) 504146773Ssam break; 505146773Ssam if (authinfolen < 20) { 506146773Ssam printf(" ??"); 507146773Ssam break; 508146773Ssam } 509146773Ssam authrealmlen = authinfolen - 20; 510146773Ssam if (authrealmlen > 0) { 511146773Ssam printf(", realm: "); 512146773Ssam } 513146773Ssam for (i = 0; i < authrealmlen; i++, tp++) 514146773Ssam printf("%02x", *tp); 515146773Ssam printf(", key ID: %08x", EXTRACT_32BITS(tp)); 516146773Ssam tp += 4; 517146773Ssam printf(", HMAC-MD5:"); 518146773Ssam for (i = 0; i < 4; i++, tp+= 4) 519146773Ssam printf(" %08x", EXTRACT_32BITS(tp)); 520146773Ssam break; 521146773Ssam case DH6OPT_AUTHPROTO_RECONFIG: 522146773Ssam if (authinfolen != 17) { 523146773Ssam printf(" ??"); 524146773Ssam break; 525146773Ssam } 526146773Ssam switch (*tp++) { 527146773Ssam case DH6OPT_AUTHRECONFIG_KEY: 528146773Ssam printf(" reconfig-key"); 529146773Ssam break; 530146773Ssam case DH6OPT_AUTHRECONFIG_HMACMD5: 531146773Ssam printf(" type: HMAC-MD5"); 532146773Ssam break; 533146773Ssam default: 534146773Ssam printf(" type: ??"); 535146773Ssam break; 536146773Ssam } 537146773Ssam printf(" value:"); 538146773Ssam for (i = 0; i < 4; i++, tp+= 4) 539146773Ssam printf(" %08x", EXTRACT_32BITS(tp)); 540146773Ssam break; 541146773Ssam default: 542146773Ssam printf(" ??"); 543146773Ssam break; 544146773Ssam } 545146773Ssam 546146773Ssam printf(")"); 547146773Ssam break; 548127668Sbms case DH6OPT_RAPID_COMMIT: /* nothing todo */ 549127668Sbms printf(")"); 550127668Sbms break; 551127668Sbms case DH6OPT_INTERFACE_ID: 552190207Srpaulo case DH6OPT_SUBSCRIBER_ID: 553127668Sbms /* 554127668Sbms * Since we cannot predict the encoding, print hex dump 555127668Sbms * at most 10 characters. 556127668Sbms */ 557214478Srpaulo tp = (u_char *)(dh6o + 1); 558190207Srpaulo printf(" "); 559127668Sbms for (i = 0; i < optlen && i < 10; i++) 560214478Srpaulo printf("%02x", tp[i]); 561190207Srpaulo printf("...)"); 562127668Sbms break; 563127668Sbms case DH6OPT_RECONF_MSG: 564127668Sbms tp = (u_char *)(dh6o + 1); 565127668Sbms switch (*tp) { 566127668Sbms case DH6_RENEW: 567127668Sbms printf(" for renew)"); 568127668Sbms break; 569127668Sbms case DH6_INFORM_REQ: 570127668Sbms printf(" for inf-req)"); 571127668Sbms break; 572127668Sbms default: 573127668Sbms printf(" for ?\?\?(%02x))", *tp); 574127668Sbms break; 575127668Sbms } 576127668Sbms break; 577127668Sbms case DH6OPT_RECONF_ACCEPT: /* nothing todo */ 578127668Sbms printf(")"); 579127668Sbms break; 580127668Sbms case DH6OPT_SIP_SERVER_A: 581111726Sfenner case DH6OPT_DNS: 582127668Sbms case DH6OPT_NTP_SERVERS: 583172683Smlaier case DH6OPT_NIS_SERVERS: 584172683Smlaier case DH6OPT_NISP_SERVERS: 585172683Smlaier case DH6OPT_BCMCS_SERVER_A: 586190207Srpaulo case DH6OPT_PANA_AGENT: 587190207Srpaulo case DH6OPT_LQ_CLIENT_LINK: 588111726Sfenner if (optlen % 16) { 589127668Sbms printf(" ?)"); 590111726Sfenner break; 591111726Sfenner } 592111726Sfenner tp = (u_char *)(dh6o + 1); 593111726Sfenner for (i = 0; i < optlen; i += 16) 594111726Sfenner printf(" %s", ip6addr_string(&tp[i])); 595111726Sfenner printf(")"); 596127668Sbms break; 597127668Sbms case DH6OPT_STATUS_CODE: 598127668Sbms if (optlen < 2) { 599127668Sbms printf(" ?)"); 600127668Sbms break; 601127668Sbms } 602214478Srpaulo tp = (u_char *)(dh6o + 1); 603214478Srpaulo printf(" %s)", dhcp6stcode(EXTRACT_16BITS(&tp[0]))); 604127668Sbms break; 605127668Sbms case DH6OPT_IA_NA: 606127668Sbms case DH6OPT_IA_PD: 607214478Srpaulo if (optlen < 12) { 608127668Sbms printf(" ?)"); 609127668Sbms break; 610127668Sbms } 611214478Srpaulo tp = (u_char *)(dh6o + 1); 612214478Srpaulo printf(" IAID:%u T1:%u T2:%u", 613214478Srpaulo EXTRACT_32BITS(&tp[0]), 614214478Srpaulo EXTRACT_32BITS(&tp[4]), 615214478Srpaulo EXTRACT_32BITS(&tp[8])); 616214478Srpaulo if (optlen > 12) { 617127668Sbms /* there are sub-options */ 618251158Sdelphij dhcp6opt_print(tp + 12, tp + optlen); 619127668Sbms } 620127668Sbms printf(")"); 621127668Sbms break; 622190207Srpaulo case DH6OPT_IA_TA: 623190207Srpaulo if (optlen < 4) { 624190207Srpaulo printf(" ?)"); 625190207Srpaulo break; 626190207Srpaulo } 627214478Srpaulo tp = (u_char *)(dh6o + 1); 628214478Srpaulo printf(" IAID:%u", EXTRACT_32BITS(tp)); 629190207Srpaulo if (optlen > 4) { 630190207Srpaulo /* there are sub-options */ 631251158Sdelphij dhcp6opt_print(tp + 4, tp + optlen); 632190207Srpaulo } 633190207Srpaulo printf(")"); 634190207Srpaulo break; 635127668Sbms case DH6OPT_IA_PD_PREFIX: 636214478Srpaulo if (optlen < 25) { 637127668Sbms printf(" ?)"); 638127668Sbms break; 639127668Sbms } 640214478Srpaulo tp = (u_char *)(dh6o + 1); 641214478Srpaulo printf(" %s/%d", ip6addr_string(&tp[9]), tp[8]); 642214478Srpaulo printf(" pltime:%u vltime:%u", 643214478Srpaulo EXTRACT_32BITS(&tp[0]), 644214478Srpaulo EXTRACT_32BITS(&tp[4])); 645214478Srpaulo if (optlen > 25) { 646127668Sbms /* there are sub-options */ 647251158Sdelphij dhcp6opt_print(tp + 25, tp + optlen); 648127668Sbms } 649127668Sbms printf(")"); 650127668Sbms break; 651146773Ssam case DH6OPT_LIFETIME: 652190207Srpaulo case DH6OPT_CLT_TIME: 653146773Ssam if (optlen != 4) { 654146773Ssam printf(" ?)"); 655146773Ssam break; 656146773Ssam } 657214478Srpaulo tp = (u_char *)(dh6o + 1); 658214478Srpaulo printf(" %d)", EXTRACT_32BITS(tp)); 659146773Ssam break; 660190207Srpaulo case DH6OPT_REMOTE_ID: 661190207Srpaulo if (optlen < 4) { 662190207Srpaulo printf(" ?)"); 663190207Srpaulo break; 664190207Srpaulo } 665190207Srpaulo tp = (u_char *)(dh6o + 1); 666214478Srpaulo printf(" %d ", EXTRACT_32BITS(tp)); 667190207Srpaulo /* 668190207Srpaulo * Print hex dump first 10 characters. 669190207Srpaulo */ 670190207Srpaulo for (i = 4; i < optlen && i < 14; i++) 671190207Srpaulo printf("%02x", tp[i]); 672190207Srpaulo printf("...)"); 673190207Srpaulo break; 674190207Srpaulo case DH6OPT_LQ_QUERY: 675190207Srpaulo if (optlen < 17) { 676190207Srpaulo printf(" ?)"); 677190207Srpaulo break; 678190207Srpaulo } 679190207Srpaulo tp = (u_char *)(dh6o + 1); 680190207Srpaulo switch (*tp) { 681190207Srpaulo case 1: 682190207Srpaulo printf(" by-address"); 683190207Srpaulo break; 684190207Srpaulo case 2: 685190207Srpaulo printf(" by-clientID"); 686190207Srpaulo break; 687190207Srpaulo default: 688190207Srpaulo printf(" type_%d", (int)*tp); 689190207Srpaulo break; 690190207Srpaulo } 691190207Srpaulo printf(" %s", ip6addr_string(&tp[1])); 692190207Srpaulo if (optlen > 17) { 693190207Srpaulo /* there are query-options */ 694190207Srpaulo dhcp6opt_print(tp + 17, tp + optlen); 695190207Srpaulo } 696190207Srpaulo printf(")"); 697190207Srpaulo break; 698190207Srpaulo case DH6OPT_CLIENT_DATA: 699214478Srpaulo tp = (u_char *)(dh6o + 1); 700190207Srpaulo if (optlen > 0) { 701190207Srpaulo /* there are encapsulated options */ 702214478Srpaulo dhcp6opt_print(tp, tp + optlen); 703190207Srpaulo } 704190207Srpaulo printf(")"); 705190207Srpaulo break; 706190207Srpaulo case DH6OPT_LQ_RELAY_DATA: 707190207Srpaulo if (optlen < 16) { 708190207Srpaulo printf(" ?)"); 709190207Srpaulo break; 710190207Srpaulo } 711190207Srpaulo tp = (u_char *)(dh6o + 1); 712190207Srpaulo printf(" %s ", ip6addr_string(&tp[0])); 713190207Srpaulo /* 714190207Srpaulo * Print hex dump first 10 characters. 715190207Srpaulo */ 716190207Srpaulo for (i = 16; i < optlen && i < 26; i++) 717190207Srpaulo printf("%02x", tp[i]); 718190207Srpaulo printf("...)"); 719190207Srpaulo break; 720251158Sdelphij case DH6OPT_AFTR_NAME: 721251158Sdelphij if (optlen < 3) { 722251158Sdelphij printf(" ?)"); 723251158Sdelphij break; 724251158Sdelphij } 725251158Sdelphij tp = (u_char *)(dh6o + 1); 726251158Sdelphij int remain_len = optlen; 727251158Sdelphij printf(" "); 728251158Sdelphij /* Encoding is described in section 3.1 of RFC 1035 */ 729251158Sdelphij int label_len; /* Label length */ 730251158Sdelphij while (remain_len && *tp) { 731251158Sdelphij label_len = *tp++; 732251158Sdelphij if (label_len < remain_len - 1) { 733251158Sdelphij printf("%.*s", label_len, tp); 734251158Sdelphij tp += label_len; 735251158Sdelphij remain_len -= (label_len + 1); 736251158Sdelphij if(*tp) printf("."); 737251158Sdelphij } else { 738251158Sdelphij printf(" ?"); 739251158Sdelphij break; 740251158Sdelphij } 741251158Sdelphij } 742251158Sdelphij printf(")"); 743251158Sdelphij break; 74456893Sfenner default: 745127668Sbms printf(")"); 74656893Sfenner break; 74756893Sfenner } 74856893Sfenner 749111726Sfenner cp += sizeof(*dh6o) + optlen; 75056893Sfenner } 75156893Sfenner return; 75256893Sfenner 75356893Sfennertrunc: 75456893Sfenner printf("[|dhcp6ext]"); 75556893Sfenner} 75656893Sfenner 75756893Sfenner/* 758111726Sfenner * Print dhcp6 packets 75956893Sfenner */ 76056893Sfennervoid 761127668Sbmsdhcp6_print(const u_char *cp, u_int length) 76256893Sfenner{ 763111726Sfenner struct dhcp6 *dh6; 764127668Sbms struct dhcp6_relay *dh6relay; 765127668Sbms const u_char *ep; 76656893Sfenner u_char *extp; 767111726Sfenner const char *name; 76856893Sfenner 76956893Sfenner printf("dhcp6"); 77056893Sfenner 77156893Sfenner ep = (u_char *)snapend; 772127668Sbms if (cp + length < ep) 773127668Sbms ep = cp + length; 77456893Sfenner 775111726Sfenner dh6 = (struct dhcp6 *)cp; 776127668Sbms dh6relay = (struct dhcp6_relay *)cp; 777127668Sbms TCHECK(dh6->dh6_xid); 77856893Sfenner switch (dh6->dh6_msgtype) { 779127668Sbms case DH6_SOLICIT: 780127668Sbms name = "solicit"; 781127668Sbms break; 782127668Sbms case DH6_ADVERTISE: 783127668Sbms name = "advertise"; 784127668Sbms break; 785127668Sbms case DH6_REQUEST: 786127668Sbms name = "request"; 787127668Sbms break; 788127668Sbms case DH6_CONFIRM: 789127668Sbms name = "confirm"; 790127668Sbms break; 791127668Sbms case DH6_RENEW: 792127668Sbms name = "renew"; 793127668Sbms break; 794127668Sbms case DH6_REBIND: 795127668Sbms name = "rebind"; 796127668Sbms break; 79756893Sfenner case DH6_REPLY: 798111726Sfenner name = "reply"; 79956893Sfenner break; 800127668Sbms case DH6_RELEASE: 801127668Sbms name = "release"; 802127668Sbms break; 803127668Sbms case DH6_DECLINE: 804127668Sbms name = "decline"; 805127668Sbms break; 806127668Sbms case DH6_RECONFIGURE: 807127668Sbms name = "reconfigure"; 808127668Sbms break; 809111726Sfenner case DH6_INFORM_REQ: 810111726Sfenner name= "inf-req"; 81156893Sfenner break; 812127668Sbms case DH6_RELAY_FORW: 813127668Sbms name= "relay-fwd"; 814127668Sbms break; 815127668Sbms case DH6_RELAY_REPLY: 816127668Sbms name= "relay-reply"; 817127668Sbms break; 818190207Srpaulo case DH6_LEASEQUERY: 819190207Srpaulo name= "leasequery"; 820190207Srpaulo break; 821190207Srpaulo case DH6_LQ_REPLY: 822190207Srpaulo name= "leasequery-reply"; 823190207Srpaulo break; 824111726Sfenner default: 825111726Sfenner name = NULL; 82656893Sfenner break; 82756893Sfenner } 828111726Sfenner 829111726Sfenner if (!vflag) { 830111726Sfenner if (name) 831111726Sfenner printf(" %s", name); 832127668Sbms else if (dh6->dh6_msgtype != DH6_RELAY_FORW && 833127668Sbms dh6->dh6_msgtype != DH6_RELAY_REPLY) { 834111726Sfenner printf(" msgtype-%u", dh6->dh6_msgtype); 835127668Sbms } 836111726Sfenner return; 837111726Sfenner } 838111726Sfenner 839111726Sfenner /* XXX relay agent messages have to be handled differently */ 840111726Sfenner 841111726Sfenner if (name) 842111726Sfenner printf(" %s (", name); /*)*/ 843111726Sfenner else 844111726Sfenner printf(" msgtype-%u (", dh6->dh6_msgtype); /*)*/ 845127668Sbms if (dh6->dh6_msgtype != DH6_RELAY_FORW && 846127668Sbms dh6->dh6_msgtype != DH6_RELAY_REPLY) { 847127668Sbms printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK); 848127668Sbms extp = (u_char *)(dh6 + 1); 849127668Sbms dhcp6opt_print(extp, ep); 850127668Sbms } else { /* relay messages */ 851127668Sbms struct in6_addr addr6; 852127668Sbms 853127668Sbms TCHECK(dh6relay->dh6relay_peeraddr); 854127668Sbms 855127668Sbms memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6)); 856127668Sbms printf("linkaddr=%s", ip6addr_string(&addr6)); 857127668Sbms 858127668Sbms memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6)); 859127668Sbms printf(" peeraddr=%s", ip6addr_string(&addr6)); 860127668Sbms 861127668Sbms dhcp6opt_print((u_char *)(dh6relay + 1), ep); 862127668Sbms } 863111726Sfenner /*(*/ 864111726Sfenner printf(")"); 86556893Sfenner return; 86656893Sfenner 86756893Sfennertrunc: 868111726Sfenner printf("[|dhcp6]"); 86956893Sfenner} 870