4 * Copyright (C) 1998 and 1999 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * supported DHCPv6 options:
43 #include <sys/cdefs.h>
46 static const char rcsid
[] _U_
=
47 "@(#) Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.35.2.1 2006/10/25 22:04:36 guy Exp";
49 __RCSID("$NetBSD: tcpdump2rcsid.ex,v 1.1 2001/06/25 20:09:58 itojun Exp $");
57 #include <tcpdump-stdinc.h>
62 #include "interface.h"
63 #include "addrtoname.h"
67 #define DHCP6_DURATITION_INFINITE 0xffffffff
70 #define DH6ERR_FAILURE 16
71 #define DH6ERR_AUTHFAIL 17
72 #define DH6ERR_POORLYFORMED 18
73 #define DH6ERR_UNAVAIL 19
74 #define DH6ERR_OPTUNAVAIL 20
78 #define DH6_ADVERTISE 2
86 #define DH6_RECONFIGURE 10
87 #define DH6_INFORM_REQ 11
88 #define DH6_RELAY_FORW 12
89 #define DH6_RELAY_REPLY 13
91 /* DHCP6 base packet format */
99 #define dh6_msgtype dh6_msgtypexid.m
100 #define dh6_xid dh6_msgtypexid.x
101 #define DH6_XIDMASK 0x00ffffff
103 /* DHCPv6 relay messages */
105 u_int8_t dh6relay_msgtype
;
106 u_int8_t dh6relay_hcnt
;
107 u_int8_t dh6relay_linkaddr
[16]; /* XXX: badly aligned */
108 u_int8_t dh6relay_peeraddr
[16];
113 #define DH6OPT_CLIENTID 1
114 #define DH6OPT_SERVERID 2
115 #define DH6OPT_IA_NA 3
116 #define DH6OPT_IA_TA 4
117 #define DH6OPT_IA_ADDR 5
119 #define DH6OPT_PREFERENCE 7
120 # define DH6OPT_PREF_MAX 255
121 #define DH6OPT_ELAPSED_TIME 8
122 #define DH6OPT_RELAY_MSG 9
123 /*#define DH6OPT_SERVER_MSG 10 deprecated */
124 #define DH6OPT_AUTH 11
125 # define DH6OPT_AUTHPROTO_DELAYED 2
126 # define DH6OPT_AUTHPROTO_RECONFIG 3
127 # define DH6OPT_AUTHALG_HMACMD5 1
128 # define DH6OPT_AUTHRDM_MONOCOUNTER 0
129 # define DH6OPT_AUTHRECONFIG_KEY 1
130 # define DH6OPT_AUTHRECONFIG_HMACMD5 2
131 #define DH6OPT_UNICAST 12
132 #define DH6OPT_STATUS_CODE 13
133 # define DH6OPT_STCODE_SUCCESS 0
134 # define DH6OPT_STCODE_UNSPECFAIL 1
135 # define DH6OPT_STCODE_NOADDRAVAIL 2
136 # define DH6OPT_STCODE_NOBINDING 3
137 # define DH6OPT_STCODE_NOTONLINK 4
138 # define DH6OPT_STCODE_USEMULTICAST 5
139 # define DH6OPT_STCODE_NOPREFIXAVAIL 6
140 #define DH6OPT_RAPID_COMMIT 14
141 #define DH6OPT_USER_CLASS 15
142 #define DH6OPT_VENDOR_CLASS 16
143 #define DH6OPT_VENDOR_OPTS 17
144 #define DH6OPT_INTERFACE_ID 18
145 #define DH6OPT_RECONF_MSG 19
146 #define DH6OPT_RECONF_ACCEPT 20
147 #define DH6OPT_SIP_SERVER_D 21
148 #define DH6OPT_SIP_SERVER_A 22
149 #define DH6OPT_DNS 23
150 #define DH6OPT_DNSNAME 24
151 #define DH6OPT_IA_PD 25
152 #define DH6OPT_IA_PD_PREFIX 26
153 #define DH6OPT_NIS_SERVERS 27
154 #define DH6OPT_NISP_SERVERS 28
155 #define DH6OPT_NIS_NAME 29
156 #define DH6OPT_NISP_NAME 30
157 #define DH6OPT_NTP_SERVERS 31
158 #define DH6OPT_LIFETIME 32
159 #define DH6OPT_BCMCS_SERVER_D 33
160 #define DH6OPT_BCMCS_SERVER_A 34
161 #define DH6OPT_GEOCONF_CIVIC 36
162 #define DH6OPT_REMOTE_ID 37
163 #define DH6OPT_SUBSCRIBER_ID 38
164 #define DH6OPT_CLIENT_FQDN 39
167 u_int16_t dh6opt_type
;
168 u_int16_t dh6opt_len
;
169 /* type-dependent data follows */
173 u_int16_t dh6opt_ia_type
;
174 u_int16_t dh6opt_ia_len
;
175 u_int32_t dh6opt_ia_iaid
;
176 u_int32_t dh6opt_ia_t1
;
177 u_int32_t dh6opt_ia_t2
;
180 struct dhcp6_ia_addr
{
181 u_int16_t dh6opt_ia_addr_type
;
182 u_int16_t dh6opt_ia_addr_len
;
183 struct in6_addr dh6opt_ia_addr_addr
;
184 u_int32_t dh6opt_ia_addr_pltime
;
185 u_int32_t dh6opt_ia_addr_vltime
;
186 } __attribute__ ((__packed__
));
188 struct dhcp6_ia_prefix
{
189 u_int16_t dh6opt_ia_prefix_type
;
190 u_int16_t dh6opt_ia_prefix_len
;
191 u_int32_t dh6opt_ia_prefix_pltime
;
192 u_int32_t dh6opt_ia_prefix_vltime
;
193 u_int8_t dh6opt_ia_prefix_plen
;
194 struct in6_addr dh6opt_ia_prefix_addr
;
195 } __attribute__ ((__packed__
));
198 u_int16_t dh6opt_auth_type
;
199 u_int16_t dh6opt_auth_len
;
200 u_int8_t dh6opt_auth_proto
;
201 u_int8_t dh6opt_auth_alg
;
202 u_int8_t dh6opt_auth_rdm
;
203 u_int8_t dh6opt_auth_rdinfo
[8];
204 /* authentication information follows */
205 } __attribute__ ((__packed__
));
208 dhcp6opt_name(int type
)
210 static char genstr
[sizeof("opt_65535") + 1]; /* XXX thread unsafe */
213 return "INVALID option";
216 case DH6OPT_CLIENTID
:
218 case DH6OPT_SERVERID
:
227 return "option request";
228 case DH6OPT_PREFERENCE
:
230 case DH6OPT_ELAPSED_TIME
:
231 return "elapsed time";
232 case DH6OPT_RELAY_MSG
:
233 return "relay message";
235 return "authentication";
237 return "server unicast";
238 case DH6OPT_STATUS_CODE
:
239 return "status code";
240 case DH6OPT_RAPID_COMMIT
:
241 return "rapid commit";
242 case DH6OPT_USER_CLASS
:
244 case DH6OPT_VENDOR_CLASS
:
245 return "vendor class";
246 case DH6OPT_VENDOR_OPTS
:
247 return "vendor-specific info";
248 case DH6OPT_INTERFACE_ID
:
249 return "interface ID";
250 case DH6OPT_RECONF_MSG
:
251 return "reconfigure message";
252 case DH6OPT_RECONF_ACCEPT
:
253 return "reconfigure accept";
254 case DH6OPT_SIP_SERVER_D
:
255 return "SIP servers domain";
256 case DH6OPT_SIP_SERVER_A
:
257 return "SIP servers address";
264 case DH6OPT_IA_PD_PREFIX
:
265 return "IA_PD prefix";
266 case DH6OPT_NTP_SERVERS
:
268 case DH6OPT_LIFETIME
:
270 case DH6OPT_NIS_SERVERS
:
272 case DH6OPT_NISP_SERVERS
:
273 return "NIS+ server";
274 case DH6OPT_NIS_NAME
:
275 return "NIS domain name";
276 case DH6OPT_NISP_NAME
:
277 return "NIS+ domain name";
278 case DH6OPT_BCMCS_SERVER_D
:
279 return "BCMCS domain name";
280 case DH6OPT_BCMCS_SERVER_A
:
281 return "BCMCS server";
282 case DH6OPT_GEOCONF_CIVIC
:
283 return "Geoconf Civic";
284 case DH6OPT_REMOTE_ID
:
286 case DH6OPT_SUBSCRIBER_ID
:
287 return "Subscriber ID";
288 case DH6OPT_CLIENT_FQDN
:
289 return "Client FQDN";
291 snprintf(genstr
, sizeof(genstr
), "opt_%d", type
);
297 dhcp6stcode(int code
)
299 static char genstr
[sizeof("code255") + 1]; /* XXX thread unsafe */
302 return "INVALID code";
305 case DH6OPT_STCODE_SUCCESS
:
307 case DH6OPT_STCODE_UNSPECFAIL
:
308 return "unspec failure";
309 case DH6OPT_STCODE_NOADDRAVAIL
:
310 return "no addresses";
311 case DH6OPT_STCODE_NOBINDING
:
313 case DH6OPT_STCODE_NOTONLINK
:
314 return "not on-link";
315 case DH6OPT_STCODE_USEMULTICAST
:
316 return "use multicast";
317 case DH6OPT_STCODE_NOPREFIXAVAIL
:
318 return "no prefixes";
320 snprintf(genstr
, sizeof(genstr
), "code%d", code
);
326 dhcp6opt_print(const u_char
*cp
, const u_char
*ep
)
328 struct dhcp6opt
*dh6o
;
336 struct dhcp6_ia_prefix ia_prefix
;
337 struct dhcp6_ia_addr ia_addr
;
338 struct dhcp6_auth authopt
;
339 u_int authinfolen
, authrealmlen
;
344 if (ep
< cp
+ sizeof(*dh6o
))
346 dh6o
= (struct dhcp6opt
*)cp
;
347 optlen
= EXTRACT_16BITS(&dh6o
->dh6opt_len
);
348 if (ep
< cp
+ sizeof(*dh6o
) + optlen
)
350 opttype
= EXTRACT_16BITS(&dh6o
->dh6opt_type
);
351 printf(" (%s", dhcp6opt_name(opttype
));
353 case DH6OPT_CLIENTID
:
354 case DH6OPT_SERVERID
:
360 tp
= (u_char
*)(dh6o
+ 1);
361 switch (EXTRACT_16BITS(tp
)) {
363 if (optlen
>= 2 + 6) {
364 printf(" hwaddr/time type %u time %u ",
365 EXTRACT_16BITS(&tp
[2]),
366 EXTRACT_32BITS(&tp
[4]));
367 for (i
= 8; i
< optlen
; i
++)
368 printf("%02x", tp
[i
]);
377 if (optlen
>= 2 + 8) {
379 for (i
= 2; i
< 2 + 8; i
++)
380 printf("%02x", tp
[i
]);
389 if (optlen
>= 2 + 2) {
390 printf(" hwaddr type %u ",
391 EXTRACT_16BITS(&tp
[2]));
392 for (i
= 4; i
< optlen
; i
++)
393 printf("%02x", tp
[i
]);
402 printf(" type %d)", EXTRACT_16BITS(tp
));
407 if (optlen
< sizeof(ia_addr
) - 4) {
411 memcpy(&ia_addr
, (u_char
*)dh6o
, sizeof(ia_addr
));
413 ip6addr_string(&ia_addr
.dh6opt_ia_addr_addr
));
414 ia_addr
.dh6opt_ia_addr_pltime
=
415 ntohl(ia_addr
.dh6opt_ia_addr_pltime
);
416 ia_addr
.dh6opt_ia_addr_vltime
=
417 ntohl(ia_addr
.dh6opt_ia_addr_vltime
);
418 printf(" pltime:%lu vltime:%lu",
419 (unsigned long)ia_addr
.dh6opt_ia_addr_pltime
,
420 (unsigned long)ia_addr
.dh6opt_ia_addr_vltime
);
421 if (optlen
> sizeof(ia_addr
) - 4) {
422 /* there are sub-options */
423 dhcp6opt_print((u_char
*)dh6o
+
425 (u_char
*)(dh6o
+ 1) + optlen
);
434 tp
= (u_char
*)(dh6o
+ 1);
435 for (i
= 0; i
< optlen
; i
+= 2) {
438 memcpy(&opt
, &tp
[i
], sizeof(opt
));
439 printf(" %s", dhcp6opt_name(ntohs(opt
)));
443 case DH6OPT_PREFERENCE
:
448 printf(" %d)", *((u_char
*)(dh6o
+ 1) + 1));
450 case DH6OPT_ELAPSED_TIME
:
455 memcpy(&val16
, dh6o
+ 1, sizeof(val16
));
456 val16
= ntohs(val16
);
457 printf(" %d)", (int)val16
);
459 case DH6OPT_RELAY_MSG
:
461 dhcp6_print((const u_char
*)(dh6o
+ 1), optlen
);
465 if (optlen
< sizeof(authopt
) - sizeof(*dh6o
)) {
469 memcpy(&authopt
, dh6o
, sizeof(authopt
));
470 switch (authopt
.dh6opt_auth_proto
) {
471 case DH6OPT_AUTHPROTO_DELAYED
:
472 printf(" proto: delayed");
474 case DH6OPT_AUTHPROTO_RECONFIG
:
475 printf(" proto: reconfigure");
479 authopt
.dh6opt_auth_proto
);
482 switch (authopt
.dh6opt_auth_alg
) {
483 case DH6OPT_AUTHALG_HMACMD5
:
484 /* XXX: may depend on the protocol */
485 printf(", alg: HMAC-MD5");
488 printf(", alg: %d", authopt
.dh6opt_auth_alg
);
491 switch (authopt
.dh6opt_auth_rdm
) {
492 case DH6OPT_AUTHRDM_MONOCOUNTER
:
493 printf(", RDM: mono");
496 printf(", RDM: %d", authopt
.dh6opt_auth_rdm
);
499 tp
= (u_char
*)&authopt
.dh6opt_auth_rdinfo
;
501 for (i
= 0; i
< 4; i
++, tp
+= sizeof(val16
))
502 printf(" %04x", EXTRACT_16BITS(tp
));
504 /* protocol dependent part */
505 tp
= (u_char
*)dh6o
+ sizeof(authopt
);
507 optlen
+ sizeof(*dh6o
) - sizeof(authopt
);
508 switch (authopt
.dh6opt_auth_proto
) {
509 case DH6OPT_AUTHPROTO_DELAYED
:
510 if (authinfolen
== 0)
512 if (authinfolen
< 20) {
516 authrealmlen
= authinfolen
- 20;
517 if (authrealmlen
> 0) {
520 for (i
= 0; i
< authrealmlen
; i
++, tp
++)
522 printf(", key ID: %08x", EXTRACT_32BITS(tp
));
524 printf(", HMAC-MD5:");
525 for (i
= 0; i
< 4; i
++, tp
+= 4)
526 printf(" %08x", EXTRACT_32BITS(tp
));
528 case DH6OPT_AUTHPROTO_RECONFIG
:
529 if (authinfolen
!= 17) {
534 case DH6OPT_AUTHRECONFIG_KEY
:
535 printf(" reconfig-key");
537 case DH6OPT_AUTHRECONFIG_HMACMD5
:
538 printf(" type: HMAC-MD5");
545 for (i
= 0; i
< 4; i
++, tp
+= 4)
546 printf(" %08x", EXTRACT_32BITS(tp
));
555 case DH6OPT_RAPID_COMMIT
: /* nothing todo */
558 case DH6OPT_INTERFACE_ID
:
560 * Since we cannot predict the encoding, print hex dump
561 * at most 10 characters.
563 for (i
= 0; i
< optlen
&& i
< 10; i
++)
564 printf("%02x", ((u_char
*)(dh6o
+ 1))[i
]);
566 case DH6OPT_RECONF_MSG
:
567 tp
= (u_char
*)(dh6o
+ 1);
570 printf(" for renew)");
573 printf(" for inf-req)");
576 printf(" for ?\?\?(%02x))", *tp
);
580 case DH6OPT_RECONF_ACCEPT
: /* nothing todo */
583 case DH6OPT_SIP_SERVER_A
:
585 case DH6OPT_NTP_SERVERS
:
586 case DH6OPT_NIS_SERVERS
:
587 case DH6OPT_NISP_SERVERS
:
588 case DH6OPT_BCMCS_SERVER_A
:
593 tp
= (u_char
*)(dh6o
+ 1);
594 for (i
= 0; i
< optlen
; i
+= 16)
595 printf(" %s", ip6addr_string(&tp
[i
]));
598 case DH6OPT_STATUS_CODE
:
603 memcpy(&val16
, (u_char
*)(dh6o
+ 1), sizeof(val16
));
604 val16
= ntohs(val16
);
605 printf(" %s)", dhcp6stcode(val16
));
609 if (optlen
< sizeof(ia
) - 4) {
613 memcpy(&ia
, (u_char
*)dh6o
, sizeof(ia
));
614 ia
.dh6opt_ia_iaid
= ntohl(ia
.dh6opt_ia_iaid
);
615 ia
.dh6opt_ia_t1
= ntohl(ia
.dh6opt_ia_t1
);
616 ia
.dh6opt_ia_t2
= ntohl(ia
.dh6opt_ia_t2
);
617 printf(" IAID:%lu T1:%lu T2:%lu",
618 (unsigned long)ia
.dh6opt_ia_iaid
,
619 (unsigned long)ia
.dh6opt_ia_t1
,
620 (unsigned long)ia
.dh6opt_ia_t2
);
621 if (optlen
> sizeof(ia
) - 4) {
622 /* there are sub-options */
623 dhcp6opt_print((u_char
*)dh6o
+ sizeof(ia
),
624 (u_char
*)(dh6o
+ 1) + optlen
);
628 case DH6OPT_IA_PD_PREFIX
:
629 if (optlen
< sizeof(ia_prefix
) - 4) {
633 memcpy(&ia_prefix
, (u_char
*)dh6o
, sizeof(ia_prefix
));
635 ip6addr_string(&ia_prefix
.dh6opt_ia_prefix_addr
),
636 ia_prefix
.dh6opt_ia_prefix_plen
);
637 ia_prefix
.dh6opt_ia_prefix_pltime
=
638 ntohl(ia_prefix
.dh6opt_ia_prefix_pltime
);
639 ia_prefix
.dh6opt_ia_prefix_vltime
=
640 ntohl(ia_prefix
.dh6opt_ia_prefix_vltime
);
641 printf(" pltime:%lu vltime:%lu",
642 (unsigned long)ia_prefix
.dh6opt_ia_prefix_pltime
,
643 (unsigned long)ia_prefix
.dh6opt_ia_prefix_vltime
);
644 if (optlen
> sizeof(ia_prefix
) - 4) {
645 /* there are sub-options */
646 dhcp6opt_print((u_char
*)dh6o
+
648 (u_char
*)(dh6o
+ 1) + optlen
);
652 case DH6OPT_LIFETIME
:
657 memcpy(&val32
, dh6o
+ 1, sizeof(val32
));
658 val32
= ntohl(val32
);
659 printf(" %d)", (int)val32
);
666 cp
+= sizeof(*dh6o
) + optlen
;
671 printf("[|dhcp6ext]");
675 * Print dhcp6 packets
678 dhcp6_print(const u_char
*cp
, u_int length
)
681 struct dhcp6_relay
*dh6relay
;
688 ep
= (u_char
*)snapend
;
689 if (cp
+ length
< ep
)
692 dh6
= (struct dhcp6
*)cp
;
693 dh6relay
= (struct dhcp6_relay
*)cp
;
694 TCHECK(dh6
->dh6_xid
);
695 switch (dh6
->dh6_msgtype
) {
723 case DH6_RECONFIGURE
:
724 name
= "reconfigure";
732 case DH6_RELAY_REPLY
:
743 else if (dh6
->dh6_msgtype
!= DH6_RELAY_FORW
&&
744 dh6
->dh6_msgtype
!= DH6_RELAY_REPLY
) {
745 printf(" msgtype-%u", dh6
->dh6_msgtype
);
750 /* XXX relay agent messages have to be handled differently */
753 printf(" %s (", name
); /*)*/
755 printf(" msgtype-%u (", dh6
->dh6_msgtype
); /*)*/
756 if (dh6
->dh6_msgtype
!= DH6_RELAY_FORW
&&
757 dh6
->dh6_msgtype
!= DH6_RELAY_REPLY
) {
758 printf("xid=%x", EXTRACT_32BITS(&dh6
->dh6_xid
) & DH6_XIDMASK
);
759 extp
= (u_char
*)(dh6
+ 1);
760 dhcp6opt_print(extp
, ep
);
761 } else { /* relay messages */
762 struct in6_addr addr6
;
764 TCHECK(dh6relay
->dh6relay_peeraddr
);
766 memcpy(&addr6
, dh6relay
->dh6relay_linkaddr
, sizeof (addr6
));
767 printf("linkaddr=%s", ip6addr_string(&addr6
));
769 memcpy(&addr6
, dh6relay
->dh6relay_peeraddr
, sizeof (addr6
));
770 printf(" peeraddr=%s", ip6addr_string(&addr6
));
772 dhcp6opt_print((u_char
*)(dh6relay
+ 1), ep
);