tcpdump segfaulted on me when i was running it on sparc64, and i think i
narrowed it down to the dhcp6 code. while trying to fix it i discovered
that it implements parsing of some extremely pre-rfc dhcpv6 protocol,
and is completely wrong. this rewrites it so it follows the most recent
rfc, specifically rfc8415.

the main difference difference between the pre-rfc code and the post-rfc
code is that pre-rfc seemed to implement some large basic messages, and
decorated some of them with a small number of options or extension
headers. rfc compliant dhcpv6 is all options. the base header is 4 bytes
and includes a 1 byte message type, and a 3 byte transaction id.
literally everything else is handled by options.

if you need convincing about the rfc compliant message structure,
look at https://tools.ietf.org/html/rfc8415#section-8.

the exception is relay messages, which have a slightly larger header,
but i am ignoring them for now.

as well as throwing out the base pre-rfc message parsing, this diff
basically throws out the option handling too and just prints all options
as bytes. this means some future work will be needed to make it
prettier, but until then i know this wont segfault.

to demo what it looks like before and after, i'm using the DHCPv6.cap
file from https://packetlife.net/captures/protocol/dhcpv6/.

a diff of vanilla tcpdump output:

@@ -1,12 +1,12 @@
 07:52:36.799722 fe80::a00:27ff:fed4:10bb > ff02::16: HBH multicast listener 
report v2, 2 group record(s) [hlim 1]
-07:52:44.775688 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: dhcp6 solicit [hlim 1]
+07:52:44.775688 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: DHCPv6 Solicit xid 100874 [hlim 1]
 07:52:44.776922 fe80::a00:27ff:fed4:10bb > ff02::1:fffe:8f95: icmp6: neighbor 
sol: who has fe80::a00:27ff:fefe:8f95
 07:52:44.777020 fe80::a00:27ff:fefe:8f95 > fe80::a00:27ff:fed4:10bb: icmp6: 
neighbor adv: tgt is fe80::a00:27ff:fefe:8f95
-07:52:44.777375 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: dhcp6 advert
+07:52:44.777375 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: DHCPv6 Advertise xid 100874
 07:52:44.987623 fe80::a00:27ff:fed4:10bb > ff02::16: HBH multicast listener 
report v2, 2 group record(s) [hlim 1]
-07:52:45.837792 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: dhcp6 request [hlim 1]
-07:52:45.839157 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: dhcp6
+07:52:45.837792 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: DHCPv6 Request xid 49174e [hlim 1]
+07:52:45.839157 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: DHCPv6 Reply xid 49174e
 07:52:49.784131 fe80::a00:27ff:fefe:8f95 > fe80::a00:27ff:fed4:10bb: icmp6: 
neighbor sol: who has fe80::a00:27ff:fed4:10bb
 07:52:49.784807 fe80::a00:27ff:fed4:10bb > fe80::a00:27ff:fefe:8f95: icmp6: 
neighbor adv: tgt is fe80::a00:27ff:fed4:10bb
-07:52:49.892611 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: dhcp6 [hlim 1]
-07:52:49.893300 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: dhcp6
+07:52:49.892611 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: DHCPv6 Release xid c789b0 [hlim 1]
+07:52:49.893300 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: DHCPv6 Reply xid c789b0

tcpdump -v:

@@ -1,12 +1,35 @@
 07:52:36.799722 fe80::a00:27ff:fed4:10bb > ff02::16: HBH (rtalert: 0x0000) 
multicast listener report v2, 2 group record(s) [gaddr ff05::1:3 to_ex, 0 
source(s)] [gaddr ff02::1:2 to_ex, 0 source(s)] [icmp6 cksum ok] [hlim 1] (len 
56)
-07:52:44.775688 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: [udp sum ok] dhcp6 solicit( 
cliaddr=1:e:1:1:1c39:cf88:800:27fe relayaddr=8f95:6:4:17:18:8:2:0) [hlim 1] 
(len 60)
+07:52:44.775688 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: [udp sum ok] DHCPv6 Solicit xid 100874
+       option 1 len 14 1c39cf88080027fe8f9500060004
+       option 6 len 4 00080002
+       option 8 len 2 000c
+       option 25 len 12 00000e100000151800000000 [hlim 1] (len 60)
 07:52:44.776922 fe80::a00:27ff:fed4:10bb > ff02::1:fffe:8f95: icmp6: neighbor 
sol: who has fe80::a00:27ff:fefe:8f95(src lladdr: 08:00:27:d4:10:bb) [icmp6 
cksum ok] (len 32, hlim 255)
 07:52:44.777020 fe80::a00:27ff:fefe:8f95 > fe80::a00:27ff:fed4:10bb: icmp6: 
neighbor adv: tgt is fe80::a00:27ff:fefe:8f95(SO)(tgt lladdr: 
08:00:27:fe:8f:95) [icmp6 cksum ok] (len 32, hlim 255)
-07:52:44.777375 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: [udp sum ok] dhcp6 advert( pref=116 
cliaddr=19:29:27fe:8f95:: relayaddr=1a:19:0:1194:0:1c20:4020:100 
servaddr=0:fe::100 (unknown, len=256)) (len 93, hlim 64)
+07:52:44.777375 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: [udp sum ok] DHCPv6 Advertise xid 100874
+       option 25 len 41 
0000000000000000001a00190000119400001c2040200100000000fe0000000000000000000001000e
+       option 1 len 14 1c39cf88080027fe8f950002000e
+       option 2 len 14 1c3825e8080027d410bb00000000 (len 93, hlim 64)
 07:52:44.987623 fe80::a00:27ff:fed4:10bb > ff02::16: HBH (rtalert: 0x0000) 
multicast listener report v2, 2 group record(s) [gaddr ff05::1:3 to_ex, 0 
source(s)] [gaddr ff02::1:2 to_ex, 0 source(s)] [icmp6 cksum ok] [hlim 1] (len 
56)
-07:52:45.837792 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: [udp sum ok] dhcp6 request(S xid=0x4e17 
cliaddr=1:e:1:1:1c39:cf88:800:27fe relayaddr=8f95:2:e:1:1:1c38:25e8:800 
servaddr=27d4:10bb:6:4:17:18:8:2 (unknown, len=25)(unknown, len=8193)) [hlim 1] 
(len 107)
-07:52:45.839157 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: [udp sum ok] dhcp6 (len 93, hlim 64)
+07:52:45.837792 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: [udp sum ok] DHCPv6 Request xid 49174e
+       option 1 len 14 1c39cf88080027fe8f950002000e
+       option 2 len 14 1c3825e8080027d410bb00060004
+       option 6 len 4 00080002
+       option 8 len 2 0029
+       option 25 len 41 
00000e1000001518001a001900001c2000001d4c40200100000000fe00000000000000000000000000
 [hlim 1] (len 107)
+07:52:45.839157 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: [udp sum ok] DHCPv6 Reply xid 49174e
+       option 25 len 41 
0000000000000000001a00190000119400001c2040200100000000fe0000000000000000000001000e
+       option 1 len 14 1c39cf88080027fe8f950002000e
+       option 2 len 14 1c3825e8080027d410bb00000000 (len 93, hlim 64)
 07:52:49.784131 fe80::a00:27ff:fefe:8f95 > fe80::a00:27ff:fed4:10bb: icmp6: 
neighbor sol: who has fe80::a00:27ff:fed4:10bb(src lladdr: 08:00:27:fe:8f:95) 
[icmp6 cksum ok] (len 32, hlim 255)
 07:52:49.784807 fe80::a00:27ff:fed4:10bb > fe80::a00:27ff:fefe:8f95: icmp6: 
neighbor adv: tgt is fe80::a00:27ff:fed4:10bb(S) [icmp6 cksum ok] (len 24, hlim 
255)
-07:52:49.892611 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: [udp sum ok] dhcp6 [hlim 1] (len 107)
-07:52:49.893300 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: [udp sum ok] dhcp6 (len 71, hlim 255)
+07:52:49.892611 fe80::a00:27ff:fefe:8f95.dhcpv6-client > 
ff02::1:2.dhcpv6-server: [udp sum ok] DHCPv6 Release xid c789b0
+       option 1 len 14 1c39cf88080027fe8f950002000e
+       option 2 len 14 1c3825e8080027d410bb00060004
+       option 6 len 4 00080002
+       option 8 len 2 0029
+       option 25 len 41 
0000000000000000001a0019000000000000000040200100000000fe00000000000000000000000000
 [hlim 1] (len 107)
+07:52:49.893300 fe80::a00:27ff:fed4:10bb.dhcpv6-server > 
fe80::a00:27ff:fefe:8f95.dhcpv6-client: [udp sum ok] DHCPv6 Reply xid c789b0
+       option 1 len 14 1c39cf88080027fe8f950002000e
+       option 2 len 14 1c3825e8080027d410bb000d0013
+       option 13 len 19 6c656173652072656365697665642e00000000 (len 71, hlim 
255)

ok?

Index: dhcp6.h
===================================================================
RCS file: dhcp6.h
diff -N dhcp6.h
--- dhcp6.h     26 Apr 2000 21:35:38 -0000      1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,193 +0,0 @@
-/*     $OpenBSD: dhcp6.h,v 1.1 2000/04/26 21:35:38 jakob Exp $ */
-
-/*
- * Copyright (C) 1998 and 1999 WIDE Project.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-/*
- * draft-ietf-dhc-dhcpv6-14
- */
-
-#ifndef __DHCP6_H_DEFINED
-#define __DHCP6_H_DEFINED
-
-/* Error Values */
-#define DH6ERR_FAILURE         16
-#define DH6ERR_AUTHFAIL                17
-#define DH6ERR_POORLYFORMED    18
-#define DH6ERR_UNAVAIL         19
-#define DH6ERR_NOBINDING       20
-#define DH6ERR_INVALIDSOURCE   21
-#define DH6ERR_NOSERVER                23
-#define DH6ERR_ICMPERROR       64
-
-/* Message type */
-#define DH6_SOLICIT    1
-#define DH6_ADVERT     2
-#define DH6_REQUEST    3
-#define DH6_REPLY      4
-#define DH6_RELEASE    5
-#define DH6_RECONFIG   6
-
-/* Predefined addresses */
-#define DH6ADDR_ALLAGENT       "ff02::1:2"
-#define DH6ADDR_ALLSERVER      "ff05::1:3"
-#define DH6ADDR_ALLRELAY       "ff05::1:4"
-#define DH6PORT_DOWNSTREAM     "546"
-#define DH6PORT_UPSTREAM       "547"
-
-/* Protocol constants */
-#define ADV_CLIENT_WAIT                2       /* sec */
-#define DEFAULT_SOLICIT_HOPCOUNT       4
-#define SERVER_MIN_ADV_DELAY   100     /* msec */
-#define SERVER_MAX_ADV_DELAY   1000    /* msec */
-#define REPLY_MSG_TIMEOUT      2       /* sec */
-#define REQUEST_MSG_MIN_RETRANS        10      /* retransmissions */
-#define RECONF_MSG_MIN_RETRANS 10      /* retransmissions */
-#define RECONF_MSG_RETRANS_INTERVAL    12      /* sec */
-#define RECONF_MMSG_MIN_RESP   2       /* sec */
-#define RECONF_MMSG_MAX_RESP   10      /* sec */
-#define RECONF_MULTICAST_REQUEST_WAIT  120     /* sec */
-#define MIN_SOLICIT_DELAY      1       /* sec */
-#define MAX_SOLICIT_DELAY      5       /* sec */
-#define XID_TIMEOUT            600     /* sec */
-
-/* DHCP6 base packet format */
-struct dhcp6_solicit {
-       u_int8_t dh6sol_msgtype;                /* DH6_SOLICIT */
-       u_int8_t dh6sol_flags;
-#define DH6SOL_CLOSE   0x80
-       u_int8_t dh6sol_pad;
-       u_int8_t dh6sol_prefixsiz;      /* prefix-size */
-       struct in6_addr dh6sol_cliaddr; /* client's lladdr */
-       struct in6_addr dh6sol_relayaddr; /* relay agent's lladdr */
-};
-
-/* NOTE: dhcpv6-12 and dhcpv6-13+n are not compatible at all */
-struct dhcp6_advert {
-       u_int8_t dh6adv_msgtype;                /* DH6_ADVERT */
-       u_int8_t dh6adv_flags;
-#define DH6ADV_SERVPRESENT     0x80
-       u_int8_t dh6adv_pad;
-       u_int8_t dh6adv_pref;
-       struct in6_addr dh6adv_cliaddr; /* client's lladdr */
-       struct in6_addr dh6adv_relayaddr; /* relay agent's (non-ll) addr */
-       struct in6_addr dh6adv_serveraddr; /* server's addr */
-       /* extensions */
-};
-
-struct dhcp6_request {
-       u_int8_t dh6req_msgtype;                /* DH6_REQUEST */
-       u_int8_t dh6req_flags;
-#define DH6REQ_CLOSE           0x80
-#define DH6REQ_SERVPRESENT     0x40
-#define DH6REQ_REBOOT          0x20
-       u_int16_t dh6req_xid;           /* transaction-ID */
-       struct in6_addr dh6req_cliaddr; /* client's lladdr */
-       struct in6_addr dh6req_relayaddr; /* relay agent's (non-ll) addr */
-       /* struct in6_addr dh6req_serveraddr; optional: server's addr */
-       /* extensions */
-};
-
-struct dhcp6_reply {
-       u_int8_t dh6rep_msgtype;                /* DH6_REPLY */
-       u_int8_t dh6rep_flagandstat;
-#define DH6REP_CLIPRESENT      0x80
-#define DH6REP_STATMASK                0x7f
-       u_int16_t dh6rep_xid;           /* transaction-ID */
-       /* struct in6_addr dh6rep_cliaddr;      optional: client's lladdr */
-       /* extensions */
-};
-
-struct dhcp6_release {
-       u_int8_t dh6rel_msgtype;                /* DH6_RELEASE */
-       u_int8_t dh6rel_flags;
-#define DH6REL_DIRECT  0x80
-       u_int16_t dh6rel_xid;           /* transaction-ID */
-       struct in6_addr dh6rel_cliaddr; /* client's lladdr */
-       struct in6_addr dh6rel_relayaddr; /* relay agent's (non-ll) addr */
-       struct in6_addr dh6rel_reladdr; /* server's addr to be released */
-       /* extensions */
-};
-
-struct dhcp6_reconfig {
-       u_int8_t dh6cfg_msgtype;                /* DH6_RECONFIG */
-       u_int8_t dh6cfg_flags;
-#define DH6REP_NOREPLY 0x80
-       u_int16_t dh6cfg_xid;           /* transaction-ID */
-       struct in6_addr dh6cfg_servaddr; /* server's addr */
-       /* extensions */
-};
-
-union dhcp6 {
-       u_int8_t dh6_msgtype;
-       struct dhcp6_solicit dh6_sol;
-       struct dhcp6_advert dh6_adv;
-       struct dhcp6_request dh6_req;
-       struct dhcp6_reply dh6_rep;
-       struct dhcp6_release dh6_rel;
-       struct dhcp6_reconfig dh6_cfg;
-};
-
-/* DHCP6 extension */
-struct dhcp6e_ipaddr {
-       u_int16_t dh6eip_type;
-       u_int16_t dh6eip_len;
-       u_int8_t dh6eip_status;
-#define DH6EX_IP_SUCCESS       0       /* request granted, no errors */
-#define DH6EX_IP_SECFAIL       18      /* Security parameters failed */
-#define DH6EX_IP_AAAAFAIL      20      /* AAAA Record Parameter Problem */
-#define DH6EX_IP_PTRFAIL       21      /* PTR Record Parameter Problem */
-#define DH6EX_IP_PARAMFAIL     22      /* Unable to honor required params */
-#define DH6EX_IP_DNSNAMEFAIL   23      /* DNS name string error */
-#define DH6EX_IP_NODYNDNS      24      /* dynDNS Not Implemented */
-#define DH6EX_IP_NOAUTHDNS     25      /* Authoritative DNS Server not found */
-#define DH6EX_IP_DNSFORMFAIL   33      /* DNS format error */
-#define DH6EX_IP_SERVFAIL      34      /* dynDNS unavailable at this time */
-#define DH6EX_IP_NXDOMAIN      35      /* name does not exist */
-#define DH6EX_IP_NOTIMP                36      /* DNS does not support the 
Opcode */
-#define DH6EX_IP_REFUSED       37      /* DNS refuses specified operation */
-#define DH6EX_IP_YXDOMAIN      38      /* name does not exist */
-#define DH6EX_IP_YXRRSET       39      /* RRset does not exist */
-#define DH6EX_IP_NXRRSET       40      /* RRset does not exist */
-#define DH6EX_IP_NOTAUTH       41      /* non authoritative name server */
-#define DH6EX_IP_NOTZONE       42      /* prerequisite out of zone */
-       u_int8_t dh6eip_flags;
-#define DH6EX_IP_CLIANTADDR    0x80    /* C: cliant's addr */
-#define DH6EX_IP_LIFETIME      0x40    /* L: preferred/valid lifetime */
-#define DH6EX_IP_FORCEOPTS     0x20    /* Q: options are mandatory */
-#define DH6EX_IP_AAAA          0x10    /* A: DNS dynamic update for AAAA */
-#define DH6EX_IP_PTR           0x08    /* P: DNS dynamic update for PTR*/
-       u_int8_t dh6eip_pad;
-       u_int8_t dh6eip_prefixlen;
-       /* struct in6_addr: client's address (if C bit = 1) */
-       /* u_int: preferred lifetime (if L bit = 1) */
-       /* u_int: valid lifetime (if L bit = 1) */
-       /* string: DNS name */
-};
-
-#endif /*__DHCP6_H_DEFINED*/
Index: dhcp6opt.h
===================================================================
RCS file: dhcp6opt.h
diff -N dhcp6opt.h
--- dhcp6opt.h  16 Feb 2002 21:28:09 -0000      1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,82 +0,0 @@
-/*     $OpenBSD: dhcp6opt.h,v 1.2 2002/02/16 21:28:09 millert Exp $    */
-
-/*
- * Copyright (C) 1998 and 1999 WIDE Project.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * draft-ietf-dhc-v6exts-11
- */
-
-#ifndef __DHCP6OPT_H_DEFINED
-#define __DHCP6OPT_H_DEFINED
-
-#define OL6_N  -1
-#define OL6_16N        -2
-#define OL6_Z  -3
-
-#define OT6_NONE       0
-#define OT6_V6         1
-#define OT6_STR                2
-#define OT6_NUM                3
-
-struct dhcp6_opt {
-       u_int code;
-       int len;
-       char *name;
-       int type;
-};
-
-/* index to parameters */
-#define DH6T_CLIENT_ADV_WAIT           1       /* milliseconds */
-#define DH6T_DEFAULT_SOLICIT_HOPCOUNT  2       /* times */
-#define DH6T_SERVER_MIN_ADV_DELAY      3       /* milliseconds */
-#define DH6T_SERVER_MAX_ADV_DELAY      4       /* milliseconds */
-#define DH6T_REQUEST_MSG_MIN_RETRANS   5       /* retransmissions */
-#define DH6T_REPLY_MSG_TIMEOUT         6       /* milliseconds */
-#define DH6T_REPLY_MSG_RETRANS_INTERVAL        7       /* milliseconds */
-#define DH6T_RECONF_MSG_TIMEOUT                8       /* milliseconds */
-#define DH6T_RECONF_MSG_MIN_RETRANS    9       /* retransmissions */
-#define DH6T_RECONF_MSG_RETRANS_INTERVAL 10    /* milliseconds */
-#define DH6T_RECONF_MMSG_MIN_RESP      11      /* milliseconds */
-#define DH6T_RECONF_MMSG_MAX_RESP      12      /* milliseconds */
-#define DH6T_MIN_SOLICIT_DELAY         13      /* milliseconds */
-#define DH6T_MAX_SOLICIT_DELAY         14      /* milliseconds */
-#define DH6T_XID_TIMEOUT               15      /* milliseconds */
-#define DH6T_RECONF_MULTICAST_REQUEST_WAIT 16  /* milliseconds */
-
-#if 0
-extern struct dhcp6_opt *dh6o_pad;
-extern struct dhcp6_opt *dh6o_end;
-extern int dhcp6_param[];
-extern void dhcp6opttab_init(void);
-extern struct dhcp6_opt *dhcp6opttab_byname(char *);
-extern struct dhcp6_opt *dhcp6opttab_bycode(u_int);
-#endif
-
-#endif /*__DHCP6OPT_H_DEFINED*/
Index: interface.h
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/interface.h,v
retrieving revision 1.81
diff -u -p -r1.81 interface.h
--- interface.h 26 May 2019 22:42:42 -0000      1.81
+++ interface.h 2 Dec 2019 11:51:36 -0000
@@ -296,7 +296,7 @@ extern void icmp6_print(const u_char *, 
 extern void ripng_print(const u_char *, int);
 extern int rt6_print(const u_char *, const u_char *);
 extern void ospf6_print(const u_char *, u_int);
-extern void dhcp6_print(const u_char *, u_int, u_short, u_short);
+extern void dhcp6_print(const u_char *, u_int);
 
 extern uint32_t in_cksum_add(const void *, size_t, uint32_t);
 extern uint16_t in_cksum_fini(uint32_t);
Index: print-dhcp6.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-dhcp6.c,v
retrieving revision 1.11
diff -u -p -r1.11 print-dhcp6.c
--- print-dhcp6.c       22 Oct 2018 16:12:45 -0000      1.11
+++ print-dhcp6.c       2 Dec 2019 11:51:36 -0000
@@ -1,32 +1,19 @@
 /*     $OpenBSD: print-dhcp6.c,v 1.11 2018/10/22 16:12:45 kn Exp $     */
 
 /*
- * Copyright (C) 1998 and 1999 WIDE Project.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * Copyright (c) 2019 David Gwynne <d...@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
 #include <sys/time.h>
@@ -44,286 +31,179 @@ struct rtentry;
 #include <arpa/inet.h>
 
 #include "interface.h"
+#include "extract.h"
 #include "addrtoname.h"
-#include "dhcp6.h"
-#include "dhcp6opt.h"
 
-#if 0
-static void dhcp6opttab_init(void);
-static struct dhcp6_opt *dhcp6opttab_byname(char *);
-#endif
-static struct dhcp6_opt *dhcp6opttab_bycode(u_int);
-
-static char tstr[] = " [|dhcp6]";
-
-static struct dhcp6_opt dh6opttab[] = {
-       /* IP Address Extension */
-       { 1, OL6_N,     "IP Address",                   OT6_NONE, },
-
-       /* General Extension */
-       { 2, 4,         "Time Offset",                  OT6_NUM, },
-       { 3, OL6_N,     "IEEE 1003.1 POSIX Timezone",   OT6_STR, },
-       { 6, OL6_16N,   "Domain Name Server",           OT6_V6, },
-       { 10, OL6_N,    "Domain Name",                  OT6_STR, },
-
-       /* Application and Service Parameters */
-       { 16, OL6_N,    "Directory Agent",              OT6_NONE, },
-       { 17, OL6_N,    "Service Scope" ,               OT6_NONE, },
-       { 18, OL6_16N,  "Network Time Protocol Servers", OT6_V6, },
-       { 19, OL6_N,    "NIS Domain",                   OT6_STR, },
-       { 20, OL6_16N,  "NIS Servers",                  OT6_V6, },
-       { 21, OL6_N,    "NIS+ Domain",                  OT6_STR, },
-       { 22, OL6_16N,  "NIS+ Servers",                 OT6_V6, },
-
-       /* TCP Parameters */
-       { 32, 4,        "TCP Keepalive Interval",       OT6_NUM, },
-
-       /* DHCPv6 Extensions */
-       { 40, 4,        "Maximum DHCPv6 Message Size",  OT6_NUM, },
-       { 41, OL6_N,    "DHCP Retransmission and Configuration Parameter",
-                                                       OT6_NONE, },
-       { 48, OL6_N,    "Platform Specific Information", OT6_NONE, },
-       { 49, OL6_N,    "Platform Class Identifier",    OT6_STR, },
-       { 64, OL6_N,    "Class Identifier",             OT6_STR, },
-       { 66, 16,       "Reconfigure Multicast Address", OT6_V6, },
-       { 67, 16,       "Renumber DHCPv6 Server Address",
-                                                       OT6_V6, },
-       { 68, OL6_N,    "DHCP Relay ICMP Error Message", OT6_NONE, },
-       { 84, OL6_N,    "Client-Server Authentication", OT6_NONE, },
-       { 85, 4,        "Client Key Selection",         OT6_NUM, },
-
-       /* End Extension */
-       { 65536, OL6_Z, "End",                          OT6_NONE, },
-
-       { 0 },
-};
-
-#if 0
-static struct dhcp6_opt *dh6o_pad;
-static struct dhcp6_opt *dh6o_end;
+/* Message type */
+#define DH6_SOLICIT            1
+#define DH6_ADVERTISE          2
+#define DH6_REQUEST            3
+#define DH6_CONFIRM            4
+#define DH6_RENEW              5
+#define DH6_REBIND             6
+#define DH6_REPLY              7
+#define DH6_RELEASE            8
+#define DH6_DECLINE            9
+#define DH6_RECONFIGURE                10
+#define DH6_INFORMATION_REQUEST        11
+#define DH6_RELAY_FORW         12
+#define DH6_RELAY_REPL         13
 
 static void
-dhcp6opttab_init()
+dhcp6opt_print(const u_char *cp, u_int length)
 {
-       dh6o_pad = dhcp6opttab_bycode(0);
-       dh6o_end = dhcp6opttab_bycode(65536);
-}
-#endif
+       uint16_t code, len;
+       u_int i;
+       int l = snapend - cp;
+
+       while (length > 0) {
+               if (l < sizeof(code))
+                       goto trunc;
+               if (length < sizeof(code))
+                       goto iptrunc;
+
+               code = EXTRACT_16BITS(cp);
+               cp += sizeof(code);
+               length -= sizeof(code);
+               l -= sizeof(code);
+
+               if (l < sizeof(len))
+                       goto trunc;
+               if (length < sizeof(len))
+                       goto iptrunc;
+
+               len = EXTRACT_16BITS(cp);
+               cp += sizeof(len);
+               length -= sizeof(len);
+               l -= sizeof(len);
 
-#if 0
-static struct dhcp6_opt *
-dhcp6opttab_byname(name)
-       char *name;
-{
-       struct dhcp6_opt *p;
+               printf("\n\toption %u len %u", code, len);
 
-       for (p = dh6opttab; p->code; p++)
-               if (strcmp(name, p->name) == 0)
-                       return p;
-       return NULL;
-}
-#endif
+               if (len > 0) {
+                       if (l < len)
+                               goto trunc;
+                       if (length < len)
+                               goto iptrunc;
 
-static struct dhcp6_opt *
-dhcp6opttab_bycode(code)
-       u_int code;
-{
-       struct dhcp6_opt *p;
+                       printf(" ");
+                       for (i = 0; i < len; i++)
+                               printf("%02x", cp[4 + i] & 0xff);
 
-       for (p = dh6opttab; p->code; p++)
-               if (p->code == code)
-                       return p;
-       return NULL;
+                       cp += len;
+                       length -= len;
+                       l -= len;
+               }
+       }
+       return;
+
+trunc:
+       printf(" [|dhcp6opt]");
+       return;
+iptrunc:
+       printf(" ip truncated");
 }
 
 static void
-dhcp6ext_print(u_char *cp, u_char *ep)
+dhcp6_relay_print(const u_char *cp, u_int length)
 {
-       u_int16_t code, len;
-       struct dhcp6_opt *p;
-       char buf[BUFSIZ];
-       int i;
+       uint8_t msgtype;
+       const char *msgname = NULL;
 
-       if (cp == ep)
-               return;
-       printf(" ");
-       while (cp < ep) {
-               code = ntohs(*(u_int16_t *)&cp[0]);
-               if (code != 65535)
-                       len = ntohs(*(u_int16_t *)&cp[2]);
-               else
-                       len = 0;
-               p = dhcp6opttab_bycode(code);
-               if (p == NULL) {
-                       printf("(unknown, len=%d)", len);
-                       cp += len + 4;
-                       continue;
-               }
+       msgtype = *cp;
 
-               /* sanity check on length */
-               switch (p->len) {
-               case OL6_N:
-                       break;
-               case OL6_16N:
-                       if (len % 16 != 0)
-                               goto trunc;
-                       break;
-               case OL6_Z:
-                       if (len != 0)
-                               goto trunc;
-                       break;
-               default:
-                       if (len != p->len)
-                               goto trunc;
-                       break;
-               }
-               if (cp + 4 + len > ep) {
-                       printf("[|%s]", p->name);
-                       return;
-               }
-
-               printf("(%s, ", p->name);
-               switch (p->type) {
-               case OT6_V6:
-                       for (i = 0; i < len; i += 16) {
-                               inet_ntop(AF_INET6, &cp[4 + i], buf,
-                                       sizeof(buf));
-                               if (i != 0)
-                                       printf(",");
-                               printf("%s", buf);
-                       }
-                       break;
-               case OT6_STR:
-                       memset(&buf, 0, sizeof(buf));
-                       strlcpy(buf, &cp[4], len);
-                       printf("%s", buf);
-                       break;
-               case OT6_NUM:
-                       printf("%d", (u_int32_t)ntohl(*(u_int32_t *)&cp[4]));
-                       break;
-               default:
-                       for (i = 0; i < len; i++)
-                               printf("%02x", cp[4 + i] & 0xff);
-               }
-               printf(")");
-               cp += len + 4;
+       switch (msgtype) {
+       case DH6_RELAY_FORW:
+               msgname = "Relay-forward";
+               break;
+       case DH6_RELAY_REPL:
+               msgname = "Relay-reply";
+               break;
        }
-       return;
 
-trunc:
-       printf("[|dhcp6ext]");
+       printf(" %s", msgname);
 }
 
-/*
- * Print dhcp6 requests
- */
 void
-dhcp6_print(const u_char *cp, u_int length,
-           u_short sport, u_short dport)
+dhcp6_print(const u_char *cp, u_int length)
 {
-       union dhcp6 *dh6;
-       u_char *ep;
-       u_char *extp;
+       uint8_t msgtype;
+       uint32_t hdr;
+       int l = snapend - cp;
+       const char *msgname;
+
+       printf("DHCPv6");
 
-       printf("dhcp6");
+       if (l < sizeof(msgtype))
+               goto trunc;
+       if (length < sizeof(msgtype))
+               goto iptrunc;
 
-       ep = (u_char *)snapend;
+       msgtype = *cp;
 
-       dh6 = (union dhcp6 *)cp;
-       TCHECK(dh6->dh6_msgtype);
-       switch (dh6->dh6_msgtype) {
+       switch (msgtype) {
        case DH6_SOLICIT:
-               if (vflag && TTEST(dh6->dh6_sol.dh6sol_relayaddr)) {
-                       printf(" solicit(");
-                       if ((dh6->dh6_sol.dh6sol_flags & DH6SOL_CLOSE) != 0)
-                               printf("C");
-                       if (dh6->dh6_sol.dh6sol_flags != 0)
-                               printf(" ");
-                       printf("cliaddr=%s",
-                               ip6addr_string(&dh6->dh6_sol.dh6sol_cliaddr));
-                       printf(" relayaddr=%s", 
-                               ip6addr_string(&dh6->dh6_sol.dh6sol_relayaddr));
-                       printf(")");
-               } else
-                       printf(" solicit");
-               break;
-       case DH6_ADVERT:
-               if (!(vflag && TTEST(dh6->dh6_adv.dh6adv_serveraddr))) {
-                       printf(" advert");
-                       break;
-               }
-               printf(" advert(");
-               if ((dh6->dh6_adv.dh6adv_flags & DH6ADV_SERVPRESENT) != 0)
-                       printf("S");
-               if (dh6->dh6_adv.dh6adv_flags != 0)
-                       printf(" ");
-               printf("pref=%u", dh6->dh6_adv.dh6adv_pref);
-               printf(" cliaddr=%s",
-                       ip6addr_string(&dh6->dh6_adv.dh6adv_cliaddr));
-               printf(" relayaddr=%s", 
-                       ip6addr_string(&dh6->dh6_adv.dh6adv_relayaddr));
-               printf(" servaddr=%s", 
-                       ip6addr_string(&dh6->dh6_adv.dh6adv_serveraddr));
-               extp = (u_char *)((&dh6->dh6_adv) + 1);
-               dhcp6ext_print(extp, ep);
-               printf(")");
+               msgname = "Solicit";
+               break;
+       case DH6_ADVERTISE:
+               msgname = "Advertise";
                break;
        case DH6_REQUEST:
-               if (!(vflag && TTEST(dh6->dh6_req.dh6req_relayaddr))) {
-                       printf(" request");
-                       break;
-               }
-               printf(" request(");
-               if ((dh6->dh6_req.dh6req_flags & DH6REQ_CLOSE) != 0)
-                       printf("C");
-               if ((dh6->dh6_req.dh6req_flags & DH6REQ_SERVPRESENT) != 0)
-                       printf("S");
-               if ((dh6->dh6_req.dh6req_flags & DH6REQ_REBOOT) != 0)
-                       printf("R");
-               if (dh6->dh6_req.dh6req_flags != 0)
-                       printf(" ");
-               printf("xid=0x%04x", dh6->dh6_req.dh6req_xid);
-               printf(" cliaddr=%s",
-                       ip6addr_string(&dh6->dh6_req.dh6req_cliaddr));
-               printf(" relayaddr=%s", 
-                       ip6addr_string(&dh6->dh6_req.dh6req_relayaddr));
-               extp = (char *)((&dh6->dh6_req) + 1);
-               if ((dh6->dh6_req.dh6req_flags & DH6REQ_SERVPRESENT) != 0) {
-                       printf(" servaddr=%s", ip6addr_string(extp));
-                       extp += 16;
-               }
-               dhcp6ext_print(extp, ep);
-               printf(")");
+               msgname = "Request";
+               break;
+       case DH6_CONFIRM:
+               msgname = "Confirm";
+               break;
+       case DH6_RENEW:
+               msgname = "Renew";
+               break;
+       case DH6_REBIND:
+               msgname = "Rebind";
                break;
        case DH6_REPLY:
-               if (!(vflag && TTEST(dh6->dh6_rep.dh6rep_xid))) {
-                       printf(" reply");
-                       break;
-               }
-               printf(" reply(");
-               if ((dh6->dh6_rep.dh6rep_flagandstat & DH6REP_CLIPRESENT) != 0)
-                       printf("C");
-               if (dh6->dh6_rep.dh6rep_flagandstat != 0)
-                       printf(" ");
-               printf("stat=0x%02x",
-                       dh6->dh6_rep.dh6rep_flagandstat & DH6REP_STATMASK);
-               extp = (u_char *)((&dh6->dh6_rep) + 1);
-               if ((dh6->dh6_rep.dh6rep_flagandstat & DH6REP_CLIPRESENT) != 0) 
{
-                       printf(" cliaddr=%s", ip6addr_string(extp));
-                       extp += 16;
-               }
-               dhcp6ext_print(extp, ep);
-               printf(")");
+               msgname = "Reply";
                break;
        case DH6_RELEASE:
-               printf(" release");
+               msgname = "Release";
+               break;
+       case DH6_DECLINE:
+               msgname = "Decline";
+               break;
+       case DH6_RECONFIGURE:
+               msgname = "Reconfigure";
                break;
-       case DH6_RECONFIG:
-               printf(" reconfig");
+       case DH6_INFORMATION_REQUEST:
+               msgname = "Information-request";
                break;
+       case DH6_RELAY_FORW:
+       case DH6_RELAY_REPL:
+               dhcp6_relay_print(cp, length);
+               return;
+       default:
+               printf(" unknown message type %u", msgtype);
+               return;
+       }
+
+       printf(" %s", msgname);
+
+       if (l < sizeof(hdr))
+               goto trunc;
+       if (length < sizeof(hdr))
+               goto iptrunc;
+
+       hdr = EXTRACT_32BITS(cp);
+       printf(" xid %x", hdr & 0xffffff);
+
+       if (vflag) {
+               cp += sizeof(hdr);
+               length -= sizeof(hdr);
+
+               dhcp6opt_print(cp, length);
        }
        return;
 
 trunc:
-       printf("%s", tstr);
+       printf(" [|dhcp6]");
+       return;
+iptrunc:
+       printf(" ip truncated");
 }
Index: print-udp.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-udp.c,v
retrieving revision 1.51
diff -u -p -r1.51 print-udp.c
--- print-udp.c 22 Oct 2018 16:12:45 -0000      1.51
+++ print-udp.c 2 Dec 2019 11:51:36 -0000
@@ -565,9 +565,8 @@ udp_print(const u_char *bp, u_int length
                        mpls_print(cp, length);
                else if (ISPORT(RIPNG_PORT))
                        ripng_print(cp, length);
-               else if (ISPORT(DHCP6_PORT1) || ISPORT(DHCP6_PORT2)) {
-                       dhcp6_print(cp, length, sport, dport);
-               }
+               else if (ISPORT(DHCP6_PORT1) || ISPORT(DHCP6_PORT2))
+                       dhcp6_print(cp, length);
                else if (ISPORT(GTP_C_PORT) || ISPORT(GTP_U_PORT) ||
                    ISPORT(GTP_PRIME_PORT))
                        gtp_print(cp, length, sport, dport);

Reply via email to