1b0453382SBill Fenner /* 2b0453382SBill Fenner * Copyright (C) 1998 and 1999 WIDE Project. 3b0453382SBill Fenner * All rights reserved. 4b0453382SBill Fenner * 5b0453382SBill Fenner * Redistribution and use in source and binary forms, with or without 6b0453382SBill Fenner * modification, are permitted provided that the following conditions 7b0453382SBill Fenner * are met: 8b0453382SBill Fenner * 1. Redistributions of source code must retain the above copyright 9b0453382SBill Fenner * notice, this list of conditions and the following disclaimer. 10b0453382SBill Fenner * 2. Redistributions in binary form must reproduce the above copyright 11b0453382SBill Fenner * notice, this list of conditions and the following disclaimer in the 12b0453382SBill Fenner * documentation and/or other materials provided with the distribution. 13b0453382SBill Fenner * 3. Neither the name of the project nor the names of its contributors 14b0453382SBill Fenner * may be used to endorse or promote products derived from this software 15b0453382SBill Fenner * without specific prior written permission. 16b0453382SBill Fenner * 17b0453382SBill Fenner * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18b0453382SBill Fenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19b0453382SBill Fenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20b0453382SBill Fenner * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21b0453382SBill Fenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22b0453382SBill Fenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23b0453382SBill Fenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24b0453382SBill Fenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25b0453382SBill Fenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26b0453382SBill Fenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27b0453382SBill Fenner * SUCH DAMAGE. 28b0453382SBill Fenner */ 299afd0c29SBill Fenner /* 305b0fe478SBruce M Simpson * RFC3315: DHCPv6 315b0fe478SBruce M Simpson * supported DHCPv6 options: 325b0fe478SBruce M Simpson * RFC3319, 335b0fe478SBruce M Simpson * draft-ietf-dhc-dhcpv6-opt-dnsconfig-04.txt, 345b0fe478SBruce M Simpson * draft-ietf-dhc-dhcpv6-opt-prefix-delegation-05.txt 355b0fe478SBruce M Simpson * draft-ietf-dhc-dhcpv6-opt-timeconfig-02.txt, 369afd0c29SBill Fenner */ 37b0453382SBill Fenner 38b0453382SBill Fenner #ifndef lint 395b0fe478SBruce M Simpson static const char rcsid[] _U_ = 405b0fe478SBruce M Simpson "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.27.2.4 2003/11/18 23:26:14 guy Exp $"; 41b0453382SBill Fenner #endif 42b0453382SBill Fenner 43b0453382SBill Fenner #ifdef HAVE_CONFIG_H 44b0453382SBill Fenner #include "config.h" 45b0453382SBill Fenner #endif 46b0453382SBill Fenner 475b0fe478SBruce M Simpson #include <tcpdump-stdinc.h> 48b0453382SBill Fenner 49b0453382SBill Fenner #include <stdio.h> 50b0453382SBill Fenner #include <string.h> 51b0453382SBill Fenner 52b0453382SBill Fenner #include "interface.h" 53b0453382SBill Fenner #include "addrtoname.h" 545b0fe478SBruce M Simpson #include "extract.h" 555b0fe478SBruce M Simpson 565b0fe478SBruce M Simpson /* lease duration */ 575b0fe478SBruce M Simpson #define DHCP6_DURATITION_INFINITE 0xffffffff 58b0453382SBill Fenner 599afd0c29SBill Fenner /* Error Values */ 609afd0c29SBill Fenner #define DH6ERR_FAILURE 16 619afd0c29SBill Fenner #define DH6ERR_AUTHFAIL 17 629afd0c29SBill Fenner #define DH6ERR_POORLYFORMED 18 639afd0c29SBill Fenner #define DH6ERR_UNAVAIL 19 649afd0c29SBill Fenner #define DH6ERR_OPTUNAVAIL 20 65b0453382SBill Fenner 669afd0c29SBill Fenner /* Message type */ 675b0fe478SBruce M Simpson #define DH6_SOLICIT 1 685b0fe478SBruce M Simpson #define DH6_ADVERTISE 2 695b0fe478SBruce M Simpson #define DH6_REQUEST 3 705b0fe478SBruce M Simpson #define DH6_CONFIRM 4 715b0fe478SBruce M Simpson #define DH6_RENEW 5 725b0fe478SBruce M Simpson #define DH6_REBIND 6 739afd0c29SBill Fenner #define DH6_REPLY 7 745b0fe478SBruce M Simpson #define DH6_RELEASE 8 755b0fe478SBruce M Simpson #define DH6_DECLINE 9 765b0fe478SBruce M Simpson #define DH6_RECONFIGURE 10 779afd0c29SBill Fenner #define DH6_INFORM_REQ 11 785b0fe478SBruce M Simpson #define DH6_RELAY_FORW 12 795b0fe478SBruce M Simpson #define DH6_RELAY_REPLY 13 80b0453382SBill Fenner 819afd0c29SBill Fenner /* DHCP6 base packet format */ 829afd0c29SBill Fenner struct dhcp6 { 839afd0c29SBill Fenner union { 849afd0c29SBill Fenner u_int8_t m; 859afd0c29SBill Fenner u_int32_t x; 869afd0c29SBill Fenner } dh6_msgtypexid; 879afd0c29SBill Fenner /* options follow */ 885b0fe478SBruce M Simpson }; 899afd0c29SBill Fenner #define dh6_msgtype dh6_msgtypexid.m 909afd0c29SBill Fenner #define dh6_xid dh6_msgtypexid.x 919afd0c29SBill Fenner #define DH6_XIDMASK 0x00ffffff 92b0453382SBill Fenner 935b0fe478SBruce M Simpson /* DHCPv6 relay messages */ 945b0fe478SBruce M Simpson struct dhcp6_relay { 955b0fe478SBruce M Simpson u_int8_t dh6relay_msgtype; 965b0fe478SBruce M Simpson u_int8_t dh6relay_hcnt; 975b0fe478SBruce M Simpson u_int8_t dh6relay_linkaddr[16]; /* XXX: badly aligned */ 985b0fe478SBruce M Simpson u_int8_t dh6relay_peeraddr[16]; 995b0fe478SBruce M Simpson /* options follow */ 1005b0fe478SBruce M Simpson }; 1015b0fe478SBruce M Simpson 1025b0fe478SBruce M Simpson /* options */ 1035b0fe478SBruce M Simpson #define DH6OPT_CLIENTID 1 1045b0fe478SBruce M Simpson #define DH6OPT_SERVERID 2 1055b0fe478SBruce M Simpson #define DH6OPT_IA_NA 3 1065b0fe478SBruce M Simpson #define DH6OPT_IA_TMP 4 1075b0fe478SBruce M Simpson #define DH6OPT_IADDR 5 1085b0fe478SBruce M Simpson #define DH6OPT_ORO 6 1095b0fe478SBruce M Simpson #define DH6OPT_PREFERENCE 7 1105b0fe478SBruce M Simpson # define DH6OPT_PREF_UNDEF -1 1115b0fe478SBruce M Simpson # define DH6OPT_PREF_MAX 255 1125b0fe478SBruce M Simpson #define DH6OPT_ELAPSED_TIME 8 1135b0fe478SBruce M Simpson #define DH6OPT_RELAY_MSG 9 1145b0fe478SBruce M Simpson /*#define DH6OPT_SERVER_MSG 10 deprecated */ 1155b0fe478SBruce M Simpson #define DH6OPT_AUTH 11 1165b0fe478SBruce M Simpson #define DH6OPT_UNICAST 12 1175b0fe478SBruce M Simpson #define DH6OPT_STATUS_CODE 13 1185b0fe478SBruce M Simpson # define DH6OPT_STCODE_SUCCESS 0 1195b0fe478SBruce M Simpson # define DH6OPT_STCODE_UNSPECFAIL 1 1205b0fe478SBruce M Simpson # define DH6OPT_STCODE_NOADDRAVAIL 2 1215b0fe478SBruce M Simpson # define DH6OPT_STCODE_NOBINDING 3 1225b0fe478SBruce M Simpson # define DH6OPT_STCODE_NOTONLINK 4 1235b0fe478SBruce M Simpson # define DH6OPT_STCODE_USEMULTICAST 5 1245b0fe478SBruce M Simpson # define DH6OPT_STCODE_NOPREFIXAVAIL 6 1255b0fe478SBruce M Simpson #define DH6OPT_RAPID_COMMIT 14 1265b0fe478SBruce M Simpson #define DH6OPT_USER_CLASS 15 1275b0fe478SBruce M Simpson #define DH6OPT_VENDOR_CLASS 16 1285b0fe478SBruce M Simpson #define DH6OPT_VENDOR_OPTS 17 1295b0fe478SBruce M Simpson #define DH6OPT_INTERFACE_ID 18 1305b0fe478SBruce M Simpson #define DH6OPT_RECONF_MSG 19 1315b0fe478SBruce M Simpson #define DH6OPT_RECONF_ACCEPT 20 1325b0fe478SBruce M Simpson #define DH6OPT_SIP_SERVER_D 21 1335b0fe478SBruce M Simpson #define DH6OPT_SIP_SERVER_A 22 1345b0fe478SBruce M Simpson #define DH6OPT_DNS 23 1355b0fe478SBruce M Simpson #define DH6OPT_DNSNAME 24 1365b0fe478SBruce M Simpson 1375b0fe478SBruce M Simpson /* 1385b0fe478SBruce M Simpson * The option type has not been assigned for the following options. 1395b0fe478SBruce M Simpson * We temporarily adopt values used in the service specification document 1405b0fe478SBruce M Simpson * (200206xx version) by NTT Communications. 1415b0fe478SBruce M Simpson * Note that we'll change the following definitions if different type values 1425b0fe478SBruce M Simpson * are officially assigned. 1435b0fe478SBruce M Simpson */ 1445b0fe478SBruce M Simpson #define DH6OPT_PREFIX_DELEGATION 30 1455b0fe478SBruce M Simpson #define DH6OPT_PREFIX_INFORMATION 31 1465b0fe478SBruce M Simpson #define DH6OPT_PREFIX_REQUEST 32 1475b0fe478SBruce M Simpson 1485b0fe478SBruce M Simpson /* 1495b0fe478SBruce M Simpson * The followings are also unassigned numbers. 1505b0fe478SBruce M Simpson * We temporarily use values as of KAME snap 20031013. 1515b0fe478SBruce M Simpson */ 1525b0fe478SBruce M Simpson #define DH6OPT_IA_PD 33 1535b0fe478SBruce M Simpson #define DH6OPT_IA_PD_PREFIX 34 1545b0fe478SBruce M Simpson #define DH6OPT_NTP_SERVERS 35 1555b0fe478SBruce M Simpson 1569afd0c29SBill Fenner struct dhcp6opt { 1579afd0c29SBill Fenner u_int16_t dh6opt_type; 1589afd0c29SBill Fenner u_int16_t dh6opt_len; 1599afd0c29SBill Fenner /* type-dependent data follows */ 1605b0fe478SBruce M Simpson }; 1615b0fe478SBruce M Simpson 1625b0fe478SBruce M Simpson struct dhcp6_ia { 1635b0fe478SBruce M Simpson u_int16_t dh6opt_ia_type; 1645b0fe478SBruce M Simpson u_int16_t dh6opt_ia_len; 1655b0fe478SBruce M Simpson u_int32_t dh6opt_ia_iaid; 1665b0fe478SBruce M Simpson u_int32_t dh6opt_ia_t1; 1675b0fe478SBruce M Simpson u_int32_t dh6opt_ia_t2; 1685b0fe478SBruce M Simpson }; 1695b0fe478SBruce M Simpson 1705b0fe478SBruce M Simpson struct dhcp6_ia_prefix { 1715b0fe478SBruce M Simpson u_int16_t dh6opt_ia_prefix_type; 1725b0fe478SBruce M Simpson u_int16_t dh6opt_ia_prefix_len; 1735b0fe478SBruce M Simpson u_int32_t dh6opt_ia_prefix_pltime; 1745b0fe478SBruce M Simpson u_int32_t dh6opt_ia_prefix_vltime; 1755b0fe478SBruce M Simpson u_int8_t dh6opt_ia_prefix_plen; 1765b0fe478SBruce M Simpson struct in6_addr dh6opt_ia_prefix_addr; 1779afd0c29SBill Fenner } __attribute__ ((__packed__)); 178b0453382SBill Fenner 1795b0fe478SBruce M Simpson static const char * 1805b0fe478SBruce M Simpson dhcp6opt_name(int type) 1815b0fe478SBruce M Simpson { 1825b0fe478SBruce M Simpson static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */ 1835b0fe478SBruce M Simpson 1845b0fe478SBruce M Simpson if (type > 65535) 1855b0fe478SBruce M Simpson return "INVALID option"; 1865b0fe478SBruce M Simpson 1875b0fe478SBruce M Simpson switch(type) { 1885b0fe478SBruce M Simpson case DH6OPT_CLIENTID: 1895b0fe478SBruce M Simpson return "client ID"; 1905b0fe478SBruce M Simpson case DH6OPT_SERVERID: 1915b0fe478SBruce M Simpson return "server ID"; 1925b0fe478SBruce M Simpson case DH6OPT_IA_NA: 1935b0fe478SBruce M Simpson return "IA_NA"; 1945b0fe478SBruce M Simpson case DH6OPT_ORO: 1955b0fe478SBruce M Simpson return "option request"; 1965b0fe478SBruce M Simpson case DH6OPT_PREFERENCE: 1975b0fe478SBruce M Simpson return "preference"; 1985b0fe478SBruce M Simpson case DH6OPT_ELAPSED_TIME: 1995b0fe478SBruce M Simpson return "elapsed time"; 2005b0fe478SBruce M Simpson case DH6OPT_RELAY_MSG: 2015b0fe478SBruce M Simpson return "relay message"; 2025b0fe478SBruce M Simpson case DH6OPT_STATUS_CODE: 2035b0fe478SBruce M Simpson return "status code"; 2045b0fe478SBruce M Simpson case DH6OPT_RAPID_COMMIT: 2055b0fe478SBruce M Simpson return "rapid commit"; 2065b0fe478SBruce M Simpson case DH6OPT_INTERFACE_ID: 2075b0fe478SBruce M Simpson return "interface ID"; 2085b0fe478SBruce M Simpson case DH6OPT_RECONF_MSG: 2095b0fe478SBruce M Simpson return "reconfigure message"; 2105b0fe478SBruce M Simpson case DH6OPT_RECONF_ACCEPT: 2115b0fe478SBruce M Simpson return "reconfigure accept"; 2125b0fe478SBruce M Simpson case DH6OPT_SIP_SERVER_D: 2135b0fe478SBruce M Simpson return "SIP Servers Domain"; 2145b0fe478SBruce M Simpson case DH6OPT_SIP_SERVER_A: 2155b0fe478SBruce M Simpson return "SIP Servers Address"; 2165b0fe478SBruce M Simpson case DH6OPT_DNS: 2175b0fe478SBruce M Simpson return "DNS"; 2185b0fe478SBruce M Simpson case DH6OPT_PREFIX_DELEGATION: 2195b0fe478SBruce M Simpson return "prefix delegation"; 2205b0fe478SBruce M Simpson case DH6OPT_PREFIX_INFORMATION: 2215b0fe478SBruce M Simpson return "prefix information"; 2225b0fe478SBruce M Simpson case DH6OPT_IA_PD: 2235b0fe478SBruce M Simpson return "IA_PD"; 2245b0fe478SBruce M Simpson case DH6OPT_IA_PD_PREFIX: 2255b0fe478SBruce M Simpson return "IA_PD prefix"; 2265b0fe478SBruce M Simpson case DH6OPT_NTP_SERVERS: 2275b0fe478SBruce M Simpson return "NTP Server"; 2285b0fe478SBruce M Simpson default: 2295b0fe478SBruce M Simpson snprintf(genstr, sizeof(genstr), "opt_%d", type); 2305b0fe478SBruce M Simpson return(genstr); 2315b0fe478SBruce M Simpson } 2325b0fe478SBruce M Simpson } 2335b0fe478SBruce M Simpson 2345b0fe478SBruce M Simpson static const char * 2355b0fe478SBruce M Simpson dhcp6stcode(int code) 2365b0fe478SBruce M Simpson { 2375b0fe478SBruce M Simpson static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */ 2385b0fe478SBruce M Simpson 2395b0fe478SBruce M Simpson if (code > 255) 2405b0fe478SBruce M Simpson return "INVALID code"; 2415b0fe478SBruce M Simpson 2425b0fe478SBruce M Simpson switch(code) { 2435b0fe478SBruce M Simpson case DH6OPT_STCODE_SUCCESS: 2445b0fe478SBruce M Simpson return "success"; 2455b0fe478SBruce M Simpson case DH6OPT_STCODE_UNSPECFAIL: 2465b0fe478SBruce M Simpson return "unspec failure"; 2475b0fe478SBruce M Simpson case DH6OPT_STCODE_NOADDRAVAIL: 2485b0fe478SBruce M Simpson return "no addresses"; 2495b0fe478SBruce M Simpson case DH6OPT_STCODE_NOBINDING: 2505b0fe478SBruce M Simpson return "no binding"; 2515b0fe478SBruce M Simpson case DH6OPT_STCODE_NOTONLINK: 2525b0fe478SBruce M Simpson return "not on-link"; 2535b0fe478SBruce M Simpson case DH6OPT_STCODE_USEMULTICAST: 2545b0fe478SBruce M Simpson return "use multicast"; 2555b0fe478SBruce M Simpson case DH6OPT_STCODE_NOPREFIXAVAIL: 2565b0fe478SBruce M Simpson return "no prefixes"; 2575b0fe478SBruce M Simpson default: 2585b0fe478SBruce M Simpson snprintf(genstr, sizeof(genstr), "code%d", code); 2595b0fe478SBruce M Simpson return(genstr); 2605b0fe478SBruce M Simpson } 2615b0fe478SBruce M Simpson } 2625b0fe478SBruce M Simpson 263b0453382SBill Fenner static void 2645b0fe478SBruce M Simpson dhcp6opt_print(const u_char *cp, const u_char *ep) 265b0453382SBill Fenner { 2669afd0c29SBill Fenner struct dhcp6opt *dh6o; 2679afd0c29SBill Fenner u_char *tp; 2685b0fe478SBruce M Simpson size_t i; 2695b0fe478SBruce M Simpson u_int16_t opttype; 2709afd0c29SBill Fenner size_t optlen; 2715b0fe478SBruce M Simpson u_int16_t val16; 2725b0fe478SBruce M Simpson u_int32_t val32; 2735b0fe478SBruce M Simpson struct in6_addr addr6; 2745b0fe478SBruce M Simpson struct dhcp6_ia ia; 2755b0fe478SBruce M Simpson struct dhcp6_ia_prefix ia_prefix; 276b0453382SBill Fenner 277b0453382SBill Fenner if (cp == ep) 278b0453382SBill Fenner return; 279b0453382SBill Fenner while (cp < ep) { 2805b0fe478SBruce M Simpson if (ep < cp + sizeof(*dh6o)) 281b0453382SBill Fenner goto trunc; 2829afd0c29SBill Fenner dh6o = (struct dhcp6opt *)cp; 2835b0fe478SBruce M Simpson optlen = EXTRACT_16BITS(&dh6o->dh6opt_len); 2845b0fe478SBruce M Simpson if (ep < cp + sizeof(*dh6o) + optlen) 285b0453382SBill Fenner goto trunc; 2865b0fe478SBruce M Simpson opttype = EXTRACT_16BITS(&dh6o->dh6opt_type); 2875b0fe478SBruce M Simpson printf(" (%s", dhcp6opt_name(opttype)); 2885b0fe478SBruce M Simpson switch (opttype) { 2895b0fe478SBruce M Simpson case DH6OPT_CLIENTID: 2905b0fe478SBruce M Simpson case DH6OPT_SERVERID: 2919afd0c29SBill Fenner if (optlen < 2) { 2929afd0c29SBill Fenner /*(*/ 2935b0fe478SBruce M Simpson printf(" ?)"); 294b0453382SBill Fenner break; 295b0453382SBill Fenner } 2969afd0c29SBill Fenner tp = (u_char *)(dh6o + 1); 2975b0fe478SBruce M Simpson switch (EXTRACT_16BITS(tp)) { 2989afd0c29SBill Fenner case 1: 2999afd0c29SBill Fenner if (optlen >= 2 + 6) { 3005b0fe478SBruce M Simpson printf(" hwaddr/time type %u time %u ", 3015b0fe478SBruce M Simpson EXTRACT_16BITS(&tp[2]), 3025b0fe478SBruce M Simpson EXTRACT_32BITS(&tp[4])); 3039afd0c29SBill Fenner for (i = 8; i < optlen; i++) 3049afd0c29SBill Fenner printf("%02x", tp[i]); 3059afd0c29SBill Fenner /*(*/ 306b0453382SBill Fenner printf(")"); 3079afd0c29SBill Fenner } else { 3089afd0c29SBill Fenner /*(*/ 3095b0fe478SBruce M Simpson printf(" ?)"); 3109afd0c29SBill Fenner } 3119afd0c29SBill Fenner break; 3129afd0c29SBill Fenner case 2: 3139afd0c29SBill Fenner if (optlen >= 2 + 8) { 3149afd0c29SBill Fenner printf(" vid "); 3159afd0c29SBill Fenner for (i = 2; i < 2 + 8; i++) 3169afd0c29SBill Fenner printf("%02x", tp[i]); 3179afd0c29SBill Fenner /*(*/ 3189afd0c29SBill Fenner printf(")"); 3199afd0c29SBill Fenner } else { 3209afd0c29SBill Fenner /*(*/ 3215b0fe478SBruce M Simpson printf(" ?)"); 3229afd0c29SBill Fenner } 3239afd0c29SBill Fenner break; 3249afd0c29SBill Fenner case 3: 3259afd0c29SBill Fenner if (optlen >= 2 + 2) { 3269afd0c29SBill Fenner printf(" hwaddr type %u ", 3275b0fe478SBruce M Simpson EXTRACT_16BITS(&tp[2])); 3289afd0c29SBill Fenner for (i = 4; i < optlen; i++) 3299afd0c29SBill Fenner printf("%02x", tp[i]); 3309afd0c29SBill Fenner /*(*/ 3319afd0c29SBill Fenner printf(")"); 3329afd0c29SBill Fenner } else { 3339afd0c29SBill Fenner /*(*/ 3345b0fe478SBruce M Simpson printf(" ?)"); 3359afd0c29SBill Fenner } 3369afd0c29SBill Fenner break; 3375b0fe478SBruce M Simpson default: 3385b0fe478SBruce M Simpson printf(" type %d)", EXTRACT_16BITS(tp)); 3395b0fe478SBruce M Simpson break; 3405b0fe478SBruce M Simpson } 3415b0fe478SBruce M Simpson break; 3425b0fe478SBruce M Simpson case DH6OPT_ORO: 3435b0fe478SBruce M Simpson if (optlen % 2) { 3445b0fe478SBruce M Simpson printf(" ?)"); 3455b0fe478SBruce M Simpson break; 3465b0fe478SBruce M Simpson } 3475b0fe478SBruce M Simpson tp = (u_char *)(dh6o + 1); 3485b0fe478SBruce M Simpson for (i = 0; i < optlen; i += 2) { 3495b0fe478SBruce M Simpson u_int16_t opt; 3505b0fe478SBruce M Simpson 3515b0fe478SBruce M Simpson memcpy(&opt, &tp[i], sizeof(opt)); 3525b0fe478SBruce M Simpson printf(" %s", dhcp6opt_name(ntohs(opt))); 3535b0fe478SBruce M Simpson } 3545b0fe478SBruce M Simpson printf(")"); 3555b0fe478SBruce M Simpson break; 3565b0fe478SBruce M Simpson case DH6OPT_PREFERENCE: 3575b0fe478SBruce M Simpson if (optlen != 1) { 3585b0fe478SBruce M Simpson printf(" ?)"); 3595b0fe478SBruce M Simpson break; 3605b0fe478SBruce M Simpson } 3615b0fe478SBruce M Simpson printf(" %d)", *((u_char *)(dh6o + 1) + 1)); 3625b0fe478SBruce M Simpson break; 3635b0fe478SBruce M Simpson case DH6OPT_ELAPSED_TIME: 3645b0fe478SBruce M Simpson if (optlen != 2) { 3655b0fe478SBruce M Simpson printf(" ?)"); 3665b0fe478SBruce M Simpson break; 3675b0fe478SBruce M Simpson } 3685b0fe478SBruce M Simpson memcpy(&val16, dh6o + 1, sizeof(val16)); 3695b0fe478SBruce M Simpson val16 = ntohs(val16); 3705b0fe478SBruce M Simpson printf(" %d)", (int)val16); 3715b0fe478SBruce M Simpson break; 3725b0fe478SBruce M Simpson case DH6OPT_RELAY_MSG: 3735b0fe478SBruce M Simpson printf(" ("); 3745b0fe478SBruce M Simpson dhcp6_print((const u_char *)(dh6o + 1), optlen); 3755b0fe478SBruce M Simpson printf(")"); 3765b0fe478SBruce M Simpson break; 3775b0fe478SBruce M Simpson case DH6OPT_RAPID_COMMIT: /* nothing todo */ 3785b0fe478SBruce M Simpson printf(")"); 3795b0fe478SBruce M Simpson break; 3805b0fe478SBruce M Simpson case DH6OPT_INTERFACE_ID: 3815b0fe478SBruce M Simpson /* 3825b0fe478SBruce M Simpson * Since we cannot predict the encoding, print hex dump 3835b0fe478SBruce M Simpson * at most 10 characters. 3845b0fe478SBruce M Simpson */ 3855b0fe478SBruce M Simpson for (i = 0; i < optlen && i < 10; i++) 3865b0fe478SBruce M Simpson printf("%02x", ((u_char *)(dh6o + 1))[i]); 3875b0fe478SBruce M Simpson break; 3885b0fe478SBruce M Simpson case DH6OPT_RECONF_MSG: 3895b0fe478SBruce M Simpson tp = (u_char *)(dh6o + 1); 3905b0fe478SBruce M Simpson switch (*tp) { 3915b0fe478SBruce M Simpson case DH6_RENEW: 3925b0fe478SBruce M Simpson printf(" for renew)"); 3935b0fe478SBruce M Simpson break; 3945b0fe478SBruce M Simpson case DH6_INFORM_REQ: 3955b0fe478SBruce M Simpson printf(" for inf-req)"); 3965b0fe478SBruce M Simpson break; 3975b0fe478SBruce M Simpson default: 3985b0fe478SBruce M Simpson printf(" for ?\?\?(%02x))", *tp); 3995b0fe478SBruce M Simpson break; 4005b0fe478SBruce M Simpson } 4015b0fe478SBruce M Simpson break; 4025b0fe478SBruce M Simpson case DH6OPT_RECONF_ACCEPT: /* nothing todo */ 4035b0fe478SBruce M Simpson printf(")"); 4045b0fe478SBruce M Simpson break; 4055b0fe478SBruce M Simpson case DH6OPT_SIP_SERVER_A: 4069afd0c29SBill Fenner case DH6OPT_DNS: 4075b0fe478SBruce M Simpson case DH6OPT_NTP_SERVERS: 4089afd0c29SBill Fenner if (optlen % 16) { 4095b0fe478SBruce M Simpson printf(" ?)"); 4109afd0c29SBill Fenner break; 4119afd0c29SBill Fenner } 4129afd0c29SBill Fenner tp = (u_char *)(dh6o + 1); 4139afd0c29SBill Fenner for (i = 0; i < optlen; i += 16) 4149afd0c29SBill Fenner printf(" %s", ip6addr_string(&tp[i])); 4159afd0c29SBill Fenner printf(")"); 4165b0fe478SBruce M Simpson break; 4175b0fe478SBruce M Simpson case DH6OPT_PREFIX_DELEGATION: 4185b0fe478SBruce M Simpson dhcp6opt_print((u_char *)(dh6o + 1), 4195b0fe478SBruce M Simpson (u_char *)(dh6o + 1) + optlen); 4205b0fe478SBruce M Simpson printf(")"); 4215b0fe478SBruce M Simpson break; 4225b0fe478SBruce M Simpson case DH6OPT_PREFIX_INFORMATION: 4235b0fe478SBruce M Simpson if (optlen % 21) 4245b0fe478SBruce M Simpson printf(" ?)"); 4255b0fe478SBruce M Simpson memcpy(&addr6, (u_char *)(dh6o + 1) + 5, 4265b0fe478SBruce M Simpson sizeof(addr6)); 4275b0fe478SBruce M Simpson printf(" %s/%d", ip6addr_string(&addr6), 4285b0fe478SBruce M Simpson (int)*((u_char *)(dh6o + 1) + 4)); 4295b0fe478SBruce M Simpson memcpy(&val32, dh6o + 1, sizeof(val32)); 4305b0fe478SBruce M Simpson val32 = ntohl(val32); 4315b0fe478SBruce M Simpson if (val32 == DHCP6_DURATITION_INFINITE) 4325b0fe478SBruce M Simpson printf(" lease-duration: infinite)"); 4335b0fe478SBruce M Simpson else 4345b0fe478SBruce M Simpson printf(" lease-duration: %u)", val32); 4355b0fe478SBruce M Simpson break; 4365b0fe478SBruce M Simpson case DH6OPT_STATUS_CODE: 4375b0fe478SBruce M Simpson if (optlen < 2) { 4385b0fe478SBruce M Simpson printf(" ?)"); 4395b0fe478SBruce M Simpson break; 4405b0fe478SBruce M Simpson } 4415b0fe478SBruce M Simpson memcpy(&val16, (u_char *)(dh6o + 1), sizeof(val16)); 4425b0fe478SBruce M Simpson val16 = ntohs(val16); 4435b0fe478SBruce M Simpson printf(" %s)", dhcp6stcode(val16)); 4445b0fe478SBruce M Simpson break; 4455b0fe478SBruce M Simpson case DH6OPT_IA_NA: 4465b0fe478SBruce M Simpson case DH6OPT_IA_PD: 4475b0fe478SBruce M Simpson if (optlen < sizeof(ia) - 4) { 4485b0fe478SBruce M Simpson printf(" ?)"); 4495b0fe478SBruce M Simpson break; 4505b0fe478SBruce M Simpson } 4515b0fe478SBruce M Simpson memcpy(&ia, (u_char *)dh6o, sizeof(ia)); 4525b0fe478SBruce M Simpson ia.dh6opt_ia_iaid = ntohl(ia.dh6opt_ia_iaid); 4535b0fe478SBruce M Simpson ia.dh6opt_ia_t1 = ntohl(ia.dh6opt_ia_t1); 4545b0fe478SBruce M Simpson ia.dh6opt_ia_t2 = ntohl(ia.dh6opt_ia_t2); 4555b0fe478SBruce M Simpson printf(" IAID:%lu T1:%lu T2:%lu", 4565b0fe478SBruce M Simpson (unsigned long)ia.dh6opt_ia_iaid, 4575b0fe478SBruce M Simpson (unsigned long)ia.dh6opt_ia_t1, 4585b0fe478SBruce M Simpson (unsigned long)ia.dh6opt_ia_t2); 4595b0fe478SBruce M Simpson if (optlen > sizeof(ia) - 4) { 4605b0fe478SBruce M Simpson /* there are sub-options */ 4615b0fe478SBruce M Simpson dhcp6opt_print((u_char *)dh6o + sizeof(ia), 4625b0fe478SBruce M Simpson (u_char *)(dh6o + 1) + optlen); 4635b0fe478SBruce M Simpson } 4645b0fe478SBruce M Simpson printf(")"); 4655b0fe478SBruce M Simpson break; 4665b0fe478SBruce M Simpson case DH6OPT_IA_PD_PREFIX: 4675b0fe478SBruce M Simpson if (optlen < sizeof(ia_prefix) - 4) { 4685b0fe478SBruce M Simpson printf(" ?)"); 4695b0fe478SBruce M Simpson break; 4705b0fe478SBruce M Simpson } 4715b0fe478SBruce M Simpson memcpy(&ia_prefix, (u_char *)dh6o, sizeof(ia_prefix)); 4725b0fe478SBruce M Simpson printf(" %s/%d", 4735b0fe478SBruce M Simpson ip6addr_string(&ia_prefix.dh6opt_ia_prefix_addr), 4745b0fe478SBruce M Simpson ia_prefix.dh6opt_ia_prefix_plen); 4755b0fe478SBruce M Simpson ia_prefix.dh6opt_ia_prefix_pltime = 4765b0fe478SBruce M Simpson ntohl(ia_prefix.dh6opt_ia_prefix_pltime); 4775b0fe478SBruce M Simpson ia_prefix.dh6opt_ia_prefix_vltime = 4785b0fe478SBruce M Simpson ntohl(ia_prefix.dh6opt_ia_prefix_vltime); 4795b0fe478SBruce M Simpson printf(" pltime:%lu vltime:%lu", 4805b0fe478SBruce M Simpson (unsigned long)ia_prefix.dh6opt_ia_prefix_pltime, 4815b0fe478SBruce M Simpson (unsigned long)ia_prefix.dh6opt_ia_prefix_vltime); 4825b0fe478SBruce M Simpson if (optlen > sizeof(ia_prefix) - 4) { 4835b0fe478SBruce M Simpson /* there are sub-options */ 4845b0fe478SBruce M Simpson dhcp6opt_print((u_char *)dh6o + 4855b0fe478SBruce M Simpson sizeof(ia_prefix), 4865b0fe478SBruce M Simpson (u_char *)(dh6o + 1) + optlen); 4875b0fe478SBruce M Simpson } 4885b0fe478SBruce M Simpson printf(")"); 4895b0fe478SBruce M Simpson break; 4909afd0c29SBill Fenner default: 4915b0fe478SBruce M Simpson printf(")"); 4929afd0c29SBill Fenner break; 4939afd0c29SBill Fenner } 4949afd0c29SBill Fenner 4959afd0c29SBill Fenner cp += sizeof(*dh6o) + optlen; 496b0453382SBill Fenner } 497b0453382SBill Fenner return; 498b0453382SBill Fenner 499b0453382SBill Fenner trunc: 500b0453382SBill Fenner printf("[|dhcp6ext]"); 501b0453382SBill Fenner } 502b0453382SBill Fenner 503b0453382SBill Fenner /* 5049afd0c29SBill Fenner * Print dhcp6 packets 505b0453382SBill Fenner */ 506b0453382SBill Fenner void 5075b0fe478SBruce M Simpson dhcp6_print(const u_char *cp, u_int length) 508b0453382SBill Fenner { 5099afd0c29SBill Fenner struct dhcp6 *dh6; 5105b0fe478SBruce M Simpson struct dhcp6_relay *dh6relay; 5115b0fe478SBruce M Simpson const u_char *ep; 512b0453382SBill Fenner u_char *extp; 5139afd0c29SBill Fenner const char *name; 514b0453382SBill Fenner 515b0453382SBill Fenner printf("dhcp6"); 516b0453382SBill Fenner 517b0453382SBill Fenner ep = (u_char *)snapend; 5185b0fe478SBruce M Simpson if (cp + length < ep) 5195b0fe478SBruce M Simpson ep = cp + length; 520b0453382SBill Fenner 5219afd0c29SBill Fenner dh6 = (struct dhcp6 *)cp; 5225b0fe478SBruce M Simpson dh6relay = (struct dhcp6_relay *)cp; 5235b0fe478SBruce M Simpson TCHECK(dh6->dh6_xid); 524b0453382SBill Fenner switch (dh6->dh6_msgtype) { 5255b0fe478SBruce M Simpson case DH6_SOLICIT: 5265b0fe478SBruce M Simpson name = "solicit"; 5275b0fe478SBruce M Simpson break; 5285b0fe478SBruce M Simpson case DH6_ADVERTISE: 5295b0fe478SBruce M Simpson name = "advertise"; 5305b0fe478SBruce M Simpson break; 5315b0fe478SBruce M Simpson case DH6_REQUEST: 5325b0fe478SBruce M Simpson name = "request"; 5335b0fe478SBruce M Simpson break; 5345b0fe478SBruce M Simpson case DH6_CONFIRM: 5355b0fe478SBruce M Simpson name = "confirm"; 5365b0fe478SBruce M Simpson break; 5375b0fe478SBruce M Simpson case DH6_RENEW: 5385b0fe478SBruce M Simpson name = "renew"; 5395b0fe478SBruce M Simpson break; 5405b0fe478SBruce M Simpson case DH6_REBIND: 5415b0fe478SBruce M Simpson name = "rebind"; 5425b0fe478SBruce M Simpson break; 543b0453382SBill Fenner case DH6_REPLY: 5449afd0c29SBill Fenner name = "reply"; 5459afd0c29SBill Fenner break; 5465b0fe478SBruce M Simpson case DH6_RELEASE: 5475b0fe478SBruce M Simpson name = "release"; 5485b0fe478SBruce M Simpson break; 5495b0fe478SBruce M Simpson case DH6_DECLINE: 5505b0fe478SBruce M Simpson name = "decline"; 5515b0fe478SBruce M Simpson break; 5525b0fe478SBruce M Simpson case DH6_RECONFIGURE: 5535b0fe478SBruce M Simpson name = "reconfigure"; 5545b0fe478SBruce M Simpson break; 5559afd0c29SBill Fenner case DH6_INFORM_REQ: 5569afd0c29SBill Fenner name= "inf-req"; 5579afd0c29SBill Fenner break; 5585b0fe478SBruce M Simpson case DH6_RELAY_FORW: 5595b0fe478SBruce M Simpson name= "relay-fwd"; 5605b0fe478SBruce M Simpson break; 5615b0fe478SBruce M Simpson case DH6_RELAY_REPLY: 5625b0fe478SBruce M Simpson name= "relay-reply"; 5635b0fe478SBruce M Simpson break; 5649afd0c29SBill Fenner default: 5659afd0c29SBill Fenner name = NULL; 566b0453382SBill Fenner break; 567b0453382SBill Fenner } 5689afd0c29SBill Fenner 5699afd0c29SBill Fenner if (!vflag) { 5709afd0c29SBill Fenner if (name) 5719afd0c29SBill Fenner printf(" %s", name); 5725b0fe478SBruce M Simpson else if (dh6->dh6_msgtype != DH6_RELAY_FORW && 5735b0fe478SBruce M Simpson dh6->dh6_msgtype != DH6_RELAY_REPLY) { 5749afd0c29SBill Fenner printf(" msgtype-%u", dh6->dh6_msgtype); 5755b0fe478SBruce M Simpson } 5769afd0c29SBill Fenner return; 577b0453382SBill Fenner } 5789afd0c29SBill Fenner 5799afd0c29SBill Fenner /* XXX relay agent messages have to be handled differently */ 5809afd0c29SBill Fenner 5819afd0c29SBill Fenner if (name) 5829afd0c29SBill Fenner printf(" %s (", name); /*)*/ 5839afd0c29SBill Fenner else 5849afd0c29SBill Fenner printf(" msgtype-%u (", dh6->dh6_msgtype); /*)*/ 5855b0fe478SBruce M Simpson if (dh6->dh6_msgtype != DH6_RELAY_FORW && 5865b0fe478SBruce M Simpson dh6->dh6_msgtype != DH6_RELAY_REPLY) { 5875b0fe478SBruce M Simpson printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK); 5889afd0c29SBill Fenner extp = (u_char *)(dh6 + 1); 5899afd0c29SBill Fenner dhcp6opt_print(extp, ep); 5905b0fe478SBruce M Simpson } else { /* relay messages */ 5915b0fe478SBruce M Simpson struct in6_addr addr6; 5925b0fe478SBruce M Simpson 5935b0fe478SBruce M Simpson TCHECK(dh6relay->dh6relay_peeraddr); 5945b0fe478SBruce M Simpson 5955b0fe478SBruce M Simpson memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6)); 5965b0fe478SBruce M Simpson printf("linkaddr=%s", ip6addr_string(&addr6)); 5975b0fe478SBruce M Simpson 5985b0fe478SBruce M Simpson memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6)); 5995b0fe478SBruce M Simpson printf(" peeraddr=%s", ip6addr_string(&addr6)); 6005b0fe478SBruce M Simpson 6015b0fe478SBruce M Simpson dhcp6opt_print((u_char *)(dh6relay + 1), ep); 6025b0fe478SBruce M Simpson } 603685295f4SBill Fenner /*(*/ 604b0453382SBill Fenner printf(")"); 605b0453382SBill Fenner return; 606b0453382SBill Fenner 607b0453382SBill Fenner trunc: 6089afd0c29SBill Fenner printf("[|dhcp6]"); 609b0453382SBill Fenner } 610