4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Dynamic Host Configuration Protocol version 6, for IPv6. Supports
29 * RFCs 3315, 3319, 3646, 3898, 4075, 4242, 4280, 4580, 4649, and 4704.
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <netinet/dhcp6.h>
41 #include <arpa/inet.h>
42 #include <dhcp_impl.h>
43 #include <dhcp_inittab.h>
47 static const char *mtype_to_str(uint8_t);
48 static const char *option_to_str(uint8_t);
49 static const char *duidtype_to_str(uint16_t);
50 static const char *status_to_str(uint16_t);
51 static const char *entr_to_str(uint32_t);
52 static const char *reconf_to_str(uint8_t);
53 static const char *authproto_to_str(uint8_t);
54 static const char *authalg_to_str(uint8_t, uint8_t);
55 static const char *authrdm_to_str(uint8_t);
56 static const char *cwhat_to_str(uint8_t);
57 static const char *catype_to_str(uint8_t);
58 static void show_hex(const uint8_t *, int, const char *);
59 static void show_ascii(const uint8_t *, int, const char *);
60 static void show_address(const char *, const void *);
61 static void show_options(const uint8_t *, int);
64 interpret_dhcpv6(int flags
, const uint8_t *data
, int len
)
74 (void) strlcpy(get_sum_line(), "DHCPv6?", MAXLINE
);
80 in6_addr_t link
, peer
;
81 char linkstr
[INET6_ADDRSTRLEN
];
82 char peerstr
[INET6_ADDRSTRLEN
];
84 line
= lstart
= get_sum_line();
85 line
+= snprintf(line
, MAXLINE
, "DHCPv6 %s",
86 mtype_to_str(data
[0]));
87 if (data
[0] == DHCPV6_MSG_RELAY_FORW
||
88 data
[0] == DHCPV6_MSG_RELAY_REPL
) {
89 if (len
< sizeof (d6r
)) {
90 (void) strlcpy(line
, "?",
91 MAXLINE
- (line
- lstart
));
94 /* Not much in DHCPv6 is aligned. */
95 (void) memcpy(&d6r
, data
, sizeof (d6r
));
96 (void) memcpy(&link
, d6r
.d6r_linkaddr
, sizeof (link
));
97 (void) memcpy(&peer
, d6r
.d6r_peeraddr
, sizeof (peer
));
98 line
+= snprintf(line
, MAXLINE
- (line
- lstart
),
99 " HC=%d link=%s peer=%s", d6r
.d6r_hop_count
,
100 inet_ntop(AF_INET6
, &link
, linkstr
,
102 inet_ntop(AF_INET6
, &peer
, peerstr
,
104 data
+= sizeof (d6r
);
107 if (len
< sizeof (d6m
)) {
108 (void) strlcpy(line
, "?",
109 MAXLINE
- (line
- lstart
));
112 (void) memcpy(&d6m
, data
, sizeof (d6m
));
113 line
+= snprintf(line
, MAXLINE
- (line
- lstart
),
114 " xid=%x", DHCPV6_GET_TRANSID(&d6m
));
115 data
+= sizeof (d6m
);
120 while ((d6o
= dhcpv6_find_option(data
, len
, d6o
,
121 DHCPV6_OPT_IA_NA
, NULL
)) != NULL
)
124 line
+= snprintf(line
, MAXLINE
- (line
- lstart
),
126 d6o
= dhcpv6_find_option(data
, len
, NULL
,
127 DHCPV6_OPT_STATUS_CODE
, &optlen
);
128 optlen
-= sizeof (*d6o
);
129 if (d6o
!= NULL
&& optlen
>= sizeof (statuscode
)) {
130 (void) memcpy(&statuscode
, d6o
+ 1,
131 sizeof (statuscode
));
132 line
+= snprintf(line
, MAXLINE
- (line
- lstart
),
133 " status=%u", ntohs(statuscode
));
134 optlen
-= sizeof (statuscode
);
136 line
+= snprintf(line
,
137 MAXLINE
- (line
- lstart
), " \"%.*s\"",
138 optlen
, (char *)(d6o
+ 1) + 2);
141 d6o
= dhcpv6_find_option(data
, len
, NULL
,
142 DHCPV6_OPT_RELAY_MSG
, &optlen
);
143 optlen
-= sizeof (*d6o
);
144 if (d6o
!= NULL
&& optlen
>= 1) {
145 line
+= snprintf(line
, MAXLINE
- (line
- lstart
),
146 " relay=%s", mtype_to_str(*(uint8_t *)(d6o
+ 1)));
148 } else if (flags
& F_DTAIL
) {
149 show_header("DHCPv6: ",
150 "Dynamic Host Configuration Protocol Version 6", len
);
152 (void) snprintf(get_line(0, 0), get_line_remain(),
153 "Message type (msg-type) = %u (%s)", data
[0],
154 mtype_to_str(data
[0]));
155 if (data
[0] == DHCPV6_MSG_RELAY_FORW
||
156 data
[0] == DHCPV6_MSG_RELAY_REPL
) {
157 if (len
< sizeof (d6r
)) {
158 (void) strlcpy(get_line(0, 0), "Truncated",
162 (void) memcpy(&d6r
, data
, sizeof (d6r
));
163 (void) snprintf(get_line(0, 0), get_line_remain(),
164 "Hop count = %u", d6r
.d6r_hop_count
);
165 show_address("Link address", d6r
.d6r_linkaddr
);
166 show_address("Peer address", d6r
.d6r_peeraddr
);
167 data
+= sizeof (d6r
);
170 if (len
< sizeof (d6m
)) {
171 (void) strlcpy(get_line(0, 0), "Truncated",
175 (void) memcpy(&d6m
, data
, sizeof (d6m
));
176 (void) snprintf(get_line(0, 0), get_line_remain(),
177 "Transaction ID = %x", DHCPV6_GET_TRANSID(&d6m
));
178 data
+= sizeof (d6m
);
182 show_options(data
, len
);
189 mtype_to_str(uint8_t mtype
)
192 case DHCPV6_MSG_SOLICIT
:
194 case DHCPV6_MSG_ADVERTISE
:
195 return ("Advertise");
196 case DHCPV6_MSG_REQUEST
:
198 case DHCPV6_MSG_CONFIRM
:
200 case DHCPV6_MSG_RENEW
:
202 case DHCPV6_MSG_REBIND
:
204 case DHCPV6_MSG_REPLY
:
206 case DHCPV6_MSG_RELEASE
:
208 case DHCPV6_MSG_DECLINE
:
210 case DHCPV6_MSG_RECONFIGURE
:
211 return ("Reconfigure");
212 case DHCPV6_MSG_INFO_REQ
:
213 return ("Information-Request");
214 case DHCPV6_MSG_RELAY_FORW
:
215 return ("Relay-Forward");
216 case DHCPV6_MSG_RELAY_REPL
:
217 return ("Relay-Reply");
224 option_to_str(uint8_t mtype
)
227 case DHCPV6_OPT_CLIENTID
:
228 return ("Client Identifier");
229 case DHCPV6_OPT_SERVERID
:
230 return ("Server Identifier");
231 case DHCPV6_OPT_IA_NA
:
232 return ("Identity Association for Non-temporary Addresses");
233 case DHCPV6_OPT_IA_TA
:
234 return ("Identity Association for Temporary Addresses");
235 case DHCPV6_OPT_IAADDR
:
236 return ("IA Address");
238 return ("Option Request");
239 case DHCPV6_OPT_PREFERENCE
:
240 return ("Preference");
241 case DHCPV6_OPT_ELAPSED_TIME
:
242 return ("Elapsed Time");
243 case DHCPV6_OPT_RELAY_MSG
:
244 return ("Relay Message");
245 case DHCPV6_OPT_AUTH
:
246 return ("Authentication");
247 case DHCPV6_OPT_UNICAST
:
248 return ("Server Unicast");
249 case DHCPV6_OPT_STATUS_CODE
:
250 return ("Status Code");
251 case DHCPV6_OPT_RAPID_COMMIT
:
252 return ("Rapid Commit");
253 case DHCPV6_OPT_USER_CLASS
:
254 return ("User Class");
255 case DHCPV6_OPT_VENDOR_CLASS
:
256 return ("Vendor Class");
257 case DHCPV6_OPT_VENDOR_OPT
:
258 return ("Vendor-specific Information");
259 case DHCPV6_OPT_INTERFACE_ID
:
260 return ("Interface-Id");
261 case DHCPV6_OPT_RECONF_MSG
:
262 return ("Reconfigure Message");
263 case DHCPV6_OPT_RECONF_ACC
:
264 return ("Reconfigure Accept");
265 case DHCPV6_OPT_SIP_NAMES
:
266 return ("SIP Servers Domain Name List");
267 case DHCPV6_OPT_SIP_ADDR
:
268 return ("SIP Servers IPv6 Address List");
269 case DHCPV6_OPT_DNS_ADDR
:
270 return ("DNS Recursive Name Server");
271 case DHCPV6_OPT_DNS_SEARCH
:
272 return ("Domain Search List");
273 case DHCPV6_OPT_IA_PD
:
274 return ("Identity Association for Prefix Delegation");
275 case DHCPV6_OPT_IAPREFIX
:
276 return ("IA_PD Prefix");
277 case DHCPV6_OPT_NIS_SERVERS
:
278 return ("Network Information Service Servers");
279 case DHCPV6_OPT_NIS_DOMAIN
:
280 return ("Network Information Service Domain Name");
281 case DHCPV6_OPT_SNTP_SERVERS
:
282 return ("Simple Network Time Protocol Servers");
283 case DHCPV6_OPT_INFO_REFTIME
:
284 return ("Information Refresh Time");
285 case DHCPV6_OPT_BCMCS_SRV_D
:
286 return ("BCMCS Controller Domain Name List");
287 case DHCPV6_OPT_BCMCS_SRV_A
:
288 return ("BCMCS Controller IPv6 Address");
289 case DHCPV6_OPT_GEOCONF_CVC
:
290 return ("Civic Location");
291 case DHCPV6_OPT_REMOTE_ID
:
292 return ("Relay Agent Remote-ID");
293 case DHCPV6_OPT_SUBSCRIBER
:
294 return ("Relay Agent Subscriber-ID");
295 case DHCPV6_OPT_CLIENT_FQDN
:
296 return ("Client FQDN");
303 duidtype_to_str(uint16_t dtype
)
306 case DHCPV6_DUID_LLT
:
307 return ("Link-layer Address Plus Time");
309 return ("Enterprise Number");
311 return ("Link-layer Address");
318 status_to_str(uint16_t status
)
321 case DHCPV6_STAT_SUCCESS
:
323 case DHCPV6_STAT_UNSPECFAIL
:
324 return ("Failure, reason unspecified");
325 case DHCPV6_STAT_NOADDRS
:
326 return ("No addresses for IAs");
327 case DHCPV6_STAT_NOBINDING
:
328 return ("Client binding unavailable");
329 case DHCPV6_STAT_NOTONLINK
:
330 return ("Prefix not on link");
331 case DHCPV6_STAT_USEMCAST
:
332 return ("Use multicast");
333 case DHCPV6_STAT_NOPREFIX
:
334 return ("No prefix available");
341 entr_to_str(uint32_t entr
)
345 return ("Sun Microsystems");
352 reconf_to_str(uint8_t msgtype
)
355 case DHCPV6_RECONF_RENEW
:
357 case DHCPV6_RECONF_INFO
:
358 return ("Information-request");
365 authproto_to_str(uint8_t aproto
)
368 case DHCPV6_PROTO_DELAYED
:
370 case DHCPV6_PROTO_RECONFIG
:
371 return ("Reconfigure Key");
378 authalg_to_str(uint8_t aproto
, uint8_t aalg
)
381 case DHCPV6_PROTO_DELAYED
:
382 case DHCPV6_PROTO_RECONFIG
:
384 case DHCPV6_ALG_HMAC_MD5
:
385 return ("HMAC-MD5 Signature");
396 authrdm_to_str(uint8_t ardm
)
399 case DHCPV6_RDM_MONOCNT
:
400 return ("Monotonic Counter");
407 cwhat_to_str(uint8_t what
)
410 case DHCPV6_CWHAT_SERVER
:
412 case DHCPV6_CWHAT_NETWORK
:
414 case DHCPV6_CWHAT_CLIENT
:
422 catype_to_str(uint8_t catype
)
426 return ("Language; RFC 2277");
428 return ("National division (state)");
434 return ("City division");
436 return ("Neighborhood");
438 return ("Street group");
440 return ("Leading street direction");
442 return ("Trailing street suffix");
444 return ("Street suffix or type");
446 return ("House number");
448 return ("House number suffix");
452 return ("Additional location information");
454 return ("Name/occupant");
456 return ("Postal Code/ZIP");
460 return ("Unit/apt/suite");
464 return ("Room number");
466 return ("Place type");
468 return ("Postal community name");
469 case CIVICADDR_POBOX
:
470 return ("Post office box");
472 return ("Additional code");
474 return ("Seat/desk");
476 return ("Primary road or street");
478 return ("Road section");
480 return ("Road branch");
482 return ("Road sub-branch");
484 return ("Street name pre-modifier");
485 case CIVICADDR_SPOST
:
486 return ("Street name post-modifier");
487 case CIVICADDR_SCRIPT
:
495 show_hex(const uint8_t *data
, int len
, const char *name
)
497 char buffer
[16 * 3 + 1];
505 for (i
= 0; i
< 16 && i
< len
; i
++)
506 (void) snprintf(buffer
+ 3 * i
, 4, " %02x", *data
++);
507 (void) snprintf(get_line(0, 0), get_line_remain(), "%*s %c%s",
508 nlen
, name
, sep
, buffer
);
516 show_ascii(const uint8_t *data
, int len
, const char *name
)
518 char buffer
[64], *bp
;
527 for (i
= 0; i
< sizeof (buffer
) - 4 && len
> 0; len
--) {
528 if (!isascii(*data
) || !isprint(*data
))
529 bp
+= snprintf(bp
, 5, "\\%03o", *data
++);
534 (void) snprintf(get_line(0, 0), get_line_remain(),
535 "%*s %c \"%s\"", nlen
, name
, sep
, buffer
);
542 show_address(const char *addrname
, const void *aptr
)
545 char addrstr
[INET6_ADDRSTRLEN
];
548 (void) memcpy(&addr
, aptr
, sizeof (in6_addr_t
));
549 (void) inet_ntop(AF_INET6
, &addr
, addrstr
, sizeof (addrstr
));
550 hname
= addrtoname(AF_INET6
, &addr
);
551 if (strcmp(hname
, addrstr
) == 0) {
552 (void) snprintf(get_line(0, 0), get_line_remain(), "%s = %s",
555 (void) snprintf(get_line(0, 0), get_line_remain(),
556 "%s = %s (%s)", addrname
, addrstr
, hname
);
561 nest_options(const uint8_t *data
, uint_t olen
, char *prefix
, char *title
)
563 char *str
, *oldnest
, *oldprefix
;
567 oldprefix
= prot_prefix
;
568 oldnest
= prot_nest_prefix
;
569 str
= malloc(strlen(prot_nest_prefix
) + strlen(prot_prefix
) + 1);
571 prot_nest_prefix
= prot_prefix
;
573 (void) sprintf(str
, "%s%s", prot_nest_prefix
, prot_prefix
);
574 prot_nest_prefix
= str
;
576 show_header(prefix
, title
, 0);
577 show_options(data
, olen
);
579 prot_prefix
= oldprefix
;
580 prot_nest_prefix
= oldnest
;
584 show_options(const uint8_t *data
, int len
)
591 const uint8_t *ostart
;
596 * Be very careful with negative numbers; ANSI signed/unsigned
597 * comparison doesn't work as expected.
599 while (len
>= (signed)sizeof (d6o
)) {
600 (void) memcpy(&d6o
, data
, sizeof (d6o
));
601 d6o
.d6o_code
= ntohs(d6o
.d6o_code
);
602 d6o
.d6o_len
= olen
= ntohs(d6o
.d6o_len
);
603 (void) snprintf(get_line(0, 0), get_line_remain(),
604 "Option Code = %u (%s)", d6o
.d6o_code
,
605 option_to_str(d6o
.d6o_code
));
606 ostart
= data
+= sizeof (d6o
);
609 (void) strlcpy(get_line(0, 0), "Option truncated",
613 switch (d6o
.d6o_code
) {
614 case DHCPV6_OPT_CLIENTID
:
615 case DHCPV6_OPT_SERVERID
:
616 if (olen
< sizeof (val16
))
618 (void) memcpy(&val16
, data
, sizeof (val16
));
619 data
+= sizeof (val16
);
620 olen
-= sizeof (val16
);
622 (void) snprintf(get_line(0, 0), get_line_remain(),
623 " DUID Type = %u (%s)", type
,
624 duidtype_to_str(type
));
625 if (type
== DHCPV6_DUID_LLT
|| type
== DHCPV6_DUID_LL
) {
626 if (olen
< sizeof (val16
))
628 (void) memcpy(&val16
, data
, sizeof (val16
));
629 data
+= sizeof (val16
);
630 olen
-= sizeof (val16
);
631 val16
= ntohs(val16
);
632 (void) snprintf(get_line(0, 0),
634 " Hardware Type = %u (%s)", val16
,
637 if (type
== DHCPV6_DUID_LLT
) {
640 if (olen
< sizeof (val32
))
642 (void) memcpy(&val32
, data
, sizeof (val32
));
643 data
+= sizeof (val32
);
644 olen
-= sizeof (val32
);
645 timevalue
= ntohl(val32
) + DUID_TIME_BASE
;
646 (void) snprintf(get_line(0, 0),
648 " Time = %lu (%.24s)", ntohl(val32
),
651 if (type
== DHCPV6_DUID_EN
) {
652 if (olen
< sizeof (val32
))
654 (void) memcpy(&val32
, data
, sizeof (val32
));
655 data
+= sizeof (val32
);
656 olen
-= sizeof (val32
);
657 val32
= ntohl(val32
);
658 (void) snprintf(get_line(0, 0),
660 " Enterprise Number = %lu (%s)", val32
,
665 if ((str
= malloc(olen
* 3)) == NULL
)
666 pr_err("interpret_dhcpv6: no mem");
667 sp
= str
+ snprintf(str
, 3, "%02x", *data
++);
669 *sp
++ = (type
== DHCPV6_DUID_LLT
||
670 type
== DHCPV6_DUID_LL
) ? ':' : ' ';
671 sp
= sp
+ snprintf(sp
, 3, "%02x", *data
++);
673 (void) snprintf(get_line(0, 0), get_line_remain(),
674 (type
== DHCPV6_DUID_LLT
||
675 type
== DHCPV6_DUID_LL
) ?
676 " Link Layer Address = %s" :
677 " Identifier = %s", str
);
680 case DHCPV6_OPT_IA_NA
:
681 case DHCPV6_OPT_IA_PD
: {
684 if (olen
< sizeof (d6in
) - sizeof (d6o
))
686 (void) memcpy(&d6in
, data
- sizeof (d6o
),
688 data
+= sizeof (d6in
) - sizeof (d6o
);
689 olen
-= sizeof (d6in
) - sizeof (d6o
);
690 (void) snprintf(get_line(0, 0), get_line_remain(),
691 " IAID = %u", ntohl(d6in
.d6in_iaid
));
692 (void) snprintf(get_line(0, 0), get_line_remain(),
693 " T1 (renew) = %u seconds", ntohl(d6in
.d6in_t1
));
694 (void) snprintf(get_line(0, 0), get_line_remain(),
695 " T2 (rebind) = %u seconds", ntohl(d6in
.d6in_t2
));
696 nest_options(data
, olen
, "IA: ",
697 "Identity Association");
700 case DHCPV6_OPT_IA_TA
: {
703 if (olen
< sizeof (d6it
) - sizeof (d6o
))
705 (void) memcpy(&d6it
, data
- sizeof (d6o
),
707 data
+= sizeof (d6it
) - sizeof (d6o
);
708 olen
-= sizeof (d6it
) - sizeof (d6o
);
709 (void) snprintf(get_line(0, 0), get_line_remain(),
710 " IAID = %u", ntohl(d6it
.d6it_iaid
));
711 nest_options(data
, olen
, "IA: ",
712 "Identity Association");
715 case DHCPV6_OPT_IAADDR
: {
716 dhcpv6_iaaddr_t d6ia
;
718 if (olen
< sizeof (d6ia
) - sizeof (d6o
))
720 (void) memcpy(&d6ia
, data
- sizeof (d6o
),
722 data
+= sizeof (d6ia
) - sizeof (d6o
);
723 olen
-= sizeof (d6ia
) - sizeof (d6o
);
724 show_address(" Address", &d6ia
.d6ia_addr
);
725 (void) snprintf(get_line(0, 0), get_line_remain(),
726 " Preferred lifetime = %u seconds",
727 ntohl(d6ia
.d6ia_preflife
));
728 (void) snprintf(get_line(0, 0), get_line_remain(),
729 " Valid lifetime = %u seconds",
730 ntohl(d6ia
.d6ia_vallife
));
731 nest_options(data
, olen
, "ADDR: ", "Address");
735 while (olen
>= sizeof (val16
)) {
736 (void) memcpy(&val16
, data
, sizeof (val16
));
737 val16
= ntohs(val16
);
738 (void) snprintf(get_line(0, 0),
740 " Requested Option Code = %u (%s)", val16
,
741 option_to_str(val16
));
742 data
+= sizeof (val16
);
743 olen
-= sizeof (val16
);
746 case DHCPV6_OPT_PREFERENCE
:
748 (void) snprintf(get_line(0, 0),
751 " Preference = %u (immediate)" :
752 " Preference = %u", *data
);
755 case DHCPV6_OPT_ELAPSED_TIME
:
756 if (olen
== sizeof (val16
)) {
757 (void) memcpy(&val16
, data
, sizeof (val16
));
758 val16
= ntohs(val16
);
759 (void) snprintf(get_line(0, 0),
761 " Elapsed Time = %u.%02u seconds",
762 val16
/ 100, val16
% 100);
765 case DHCPV6_OPT_RELAY_MSG
:
767 oldnest
= prot_nest_prefix
;
768 prot_nest_prefix
= prot_prefix
;
769 retlen
= interpret_dhcpv6(F_DTAIL
, data
, olen
);
770 prot_prefix
= prot_nest_prefix
;
771 prot_nest_prefix
= oldnest
;
774 case DHCPV6_OPT_AUTH
: {
777 if (olen
< DHCPV6_AUTH_SIZE
- sizeof (d6o
))
779 (void) memcpy(&d6a
, data
- sizeof (d6o
),
781 data
+= DHCPV6_AUTH_SIZE
- sizeof (d6o
);
782 olen
+= DHCPV6_AUTH_SIZE
- sizeof (d6o
);
783 (void) snprintf(get_line(0, 0), get_line_remain(),
784 " Protocol = %u (%s)", d6a
.d6a_proto
,
785 authproto_to_str(d6a
.d6a_proto
));
786 (void) snprintf(get_line(0, 0), get_line_remain(),
787 " Algorithm = %u (%s)", d6a
.d6a_alg
,
788 authalg_to_str(d6a
.d6a_proto
, d6a
.d6a_alg
));
789 (void) snprintf(get_line(0, 0), get_line_remain(),
790 " Replay Detection Method = %u (%s)", d6a
.d6a_rdm
,
791 authrdm_to_str(d6a
.d6a_rdm
));
792 show_hex(d6a
.d6a_replay
, sizeof (d6a
.d6a_replay
),
795 show_hex(data
, olen
, " Auth Info");
798 case DHCPV6_OPT_UNICAST
:
799 if (olen
>= sizeof (in6_addr_t
))
800 show_address(" Server Address", data
);
802 case DHCPV6_OPT_STATUS_CODE
:
803 if (olen
< sizeof (val16
))
805 (void) memcpy(&val16
, data
, sizeof (val16
));
806 val16
= ntohs(val16
);
807 (void) snprintf(get_line(0, 0), get_line_remain(),
808 " Status Code = %u (%s)", val16
,
809 status_to_str(val16
));
810 data
+= sizeof (val16
);
811 olen
-= sizeof (val16
);
813 (void) snprintf(get_line(0, 0),
814 get_line_remain(), " Text = \"%.*s\"",
817 case DHCPV6_OPT_VENDOR_CLASS
:
818 if (olen
< sizeof (val32
))
820 (void) memcpy(&val32
, data
, sizeof (val32
));
821 data
+= sizeof (val32
);
822 olen
-= sizeof (val32
);
823 val32
= ntohl(val32
);
824 (void) snprintf(get_line(0, 0), get_line_remain(),
825 " Enterprise Number = %lu (%s)", val32
,
828 case DHCPV6_OPT_USER_CLASS
:
829 while (olen
>= sizeof (val16
)) {
830 (void) memcpy(&val16
, data
, sizeof (val16
));
831 data
+= sizeof (val16
);
832 olen
-= sizeof (val16
);
833 val16
= ntohs(val16
);
835 (void) strlcpy(get_line(0, 0),
840 show_hex(data
, olen
, " Class");
845 case DHCPV6_OPT_VENDOR_OPT
: {
846 dhcpv6_option_t sd6o
;
848 if (olen
< sizeof (val32
))
850 (void) memcpy(&val32
, data
, sizeof (val32
));
851 data
+= sizeof (val32
);
852 olen
-= sizeof (val32
);
853 val32
= ntohl(val32
);
854 (void) snprintf(get_line(0, 0), get_line_remain(),
855 " Enterprise Number = %lu (%s)", val32
,
857 while (olen
>= sizeof (sd6o
)) {
858 (void) memcpy(&sd6o
, data
, sizeof (sd6o
));
859 sd6o
.d6o_code
= ntohs(sd6o
.d6o_code
);
860 sd6o
.d6o_len
= ntohs(sd6o
.d6o_len
);
861 (void) snprintf(get_line(0, 0),
863 " Vendor Option Code = %u", d6o
.d6o_code
);
864 data
+= sizeof (d6o
);
865 olen
-= sizeof (d6o
);
866 if (sd6o
.d6o_len
> olen
) {
867 (void) strlcpy(get_line(0, 0),
868 " Vendor Option truncated",
872 if (sd6o
.d6o_len
> 0) {
873 show_hex(data
, sd6o
.d6o_len
,
875 data
+= sd6o
.d6o_len
;
876 olen
-= sd6o
.d6o_len
;
881 case DHCPV6_OPT_REMOTE_ID
:
882 if (olen
< sizeof (val32
))
884 (void) memcpy(&val32
, data
, sizeof (val32
));
885 data
+= sizeof (val32
);
886 olen
-= sizeof (val32
);
887 val32
= ntohl(val32
);
888 (void) snprintf(get_line(0, 0), get_line_remain(),
889 " Enterprise Number = %lu (%s)", val32
,
892 case DHCPV6_OPT_INTERFACE_ID
:
893 case DHCPV6_OPT_SUBSCRIBER
:
895 show_hex(data
, olen
, " ID");
897 case DHCPV6_OPT_RECONF_MSG
:
899 (void) snprintf(get_line(0, 0),
901 " Message Type = %u (%s)", *data
,
902 reconf_to_str(*data
));
905 case DHCPV6_OPT_SIP_NAMES
:
906 case DHCPV6_OPT_DNS_SEARCH
:
907 case DHCPV6_OPT_NIS_DOMAIN
:
908 case DHCPV6_OPT_BCMCS_SRV_D
: {
912 symp
= inittab_getbycode(
913 ITAB_CAT_STANDARD
| ITAB_CAT_V6
, ITAB_CONS_SNOOP
,
916 str
= inittab_decode(symp
, data
, olen
, B_TRUE
);
920 sp2
= strchr(sp
, ' ');
923 (void) snprintf(get_line(0, 0),
926 } while ((sp
= sp2
) != NULL
);
933 case DHCPV6_OPT_SIP_ADDR
:
934 case DHCPV6_OPT_DNS_ADDR
:
935 case DHCPV6_OPT_NIS_SERVERS
:
936 case DHCPV6_OPT_SNTP_SERVERS
:
937 case DHCPV6_OPT_BCMCS_SRV_A
:
938 while (olen
>= sizeof (in6_addr_t
)) {
939 show_address(" Address", data
);
940 data
+= sizeof (in6_addr_t
);
941 olen
-= sizeof (in6_addr_t
);
944 case DHCPV6_OPT_IAPREFIX
: {
945 dhcpv6_iaprefix_t d6ip
;
947 if (olen
< DHCPV6_IAPREFIX_SIZE
- sizeof (d6o
))
949 (void) memcpy(&d6ip
, data
- sizeof (d6o
),
950 DHCPV6_IAPREFIX_SIZE
);
951 data
+= DHCPV6_IAPREFIX_SIZE
- sizeof (d6o
);
952 olen
-= DHCPV6_IAPREFIX_SIZE
- sizeof (d6o
);
953 show_address(" Prefix", d6ip
.d6ip_addr
);
954 (void) snprintf(get_line(0, 0), get_line_remain(),
955 " Preferred lifetime = %u seconds",
956 ntohl(d6ip
.d6ip_preflife
));
957 (void) snprintf(get_line(0, 0), get_line_remain(),
958 " Valid lifetime = %u seconds",
959 ntohl(d6ip
.d6ip_vallife
));
960 (void) snprintf(get_line(0, 0), get_line_remain(),
961 " Prefix length = %u", d6ip
.d6ip_preflen
);
962 nest_options(data
, olen
, "ADDR: ", "Address");
965 case DHCPV6_OPT_INFO_REFTIME
:
966 if (olen
< sizeof (val32
))
968 (void) memcpy(&val32
, data
, sizeof (val32
));
969 (void) snprintf(get_line(0, 0), get_line_remain(),
970 " Refresh Time = %lu seconds", ntohl(val32
));
972 case DHCPV6_OPT_GEOCONF_CVC
: {
976 if (olen
< DHCPV6_CIVIC_SIZE
- sizeof (d6o
))
978 (void) memcpy(&d6c
, data
- sizeof (d6o
),
980 data
+= DHCPV6_CIVIC_SIZE
- sizeof (d6o
);
981 olen
-= DHCPV6_CIVIC_SIZE
- sizeof (d6o
);
982 (void) snprintf(get_line(0, 0), get_line_remain(),
983 " What Location = %u (%s)", d6c
.d6c_what
,
984 cwhat_to_str(d6c
.d6c_what
));
985 (void) snprintf(get_line(0, 0), get_line_remain(),
986 " Country Code = %.*s", sizeof (d6c
.d6c_cc
),
989 (void) snprintf(get_line(0, 0),
991 " CA Element = %u (%s)", *data
,
992 catype_to_str(*data
));
997 (void) strlcpy(get_line(0, 0),
998 " CA Element truncated",
1003 show_ascii(data
, solen
, " CA Data");
1010 case DHCPV6_OPT_CLIENT_FQDN
: {
1011 dhcp_symbol_t
*symp
;
1015 (void) snprintf(get_line(0, 0), get_line_remain(),
1016 " Flags = %02x", *data
);
1017 (void) snprintf(get_line(0, 0), get_line_remain(),
1018 " %s", getflag(*data
, DHCPV6_FQDNF_S
,
1019 "Perform AAAA RR updates", "No AAAA RR updates"));
1020 (void) snprintf(get_line(0, 0), get_line_remain(),
1021 " %s", getflag(*data
, DHCPV6_FQDNF_O
,
1022 "Server override updates",
1023 "No server override updates"));
1024 (void) snprintf(get_line(0, 0), get_line_remain(),
1025 " %s", getflag(*data
, DHCPV6_FQDNF_N
,
1026 "Server performs no updates",
1027 "Server performs updates"));
1028 symp
= inittab_getbycode(
1029 ITAB_CAT_STANDARD
| ITAB_CAT_V6
, ITAB_CONS_SNOOP
,
1032 str
= inittab_decode(symp
, data
, olen
, B_TRUE
);
1034 (void) snprintf(get_line(0, 0),
1044 data
= ostart
+ d6o
.d6o_len
;
1048 (void) strlcpy(get_line(0, 0), "Option entry truncated",