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 2017 Gary Mills
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
29 * Dynamic Host Configuration Protocol version 6, for IPv6. Supports
30 * RFCs 3315, 3319, 3646, 3898, 4075, 4242, 4280, 4580, 4649, and 4704.
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <netinet/dhcp6.h>
42 #include <arpa/inet.h>
43 #include <dhcp_impl.h>
44 #include <dhcp_inittab.h>
48 static const char *mtype_to_str(uint8_t);
49 static const char *option_to_str(uint8_t);
50 static const char *duidtype_to_str(uint16_t);
51 static const char *status_to_str(uint16_t);
52 static const char *entr_to_str(uint32_t);
53 static const char *reconf_to_str(uint8_t);
54 static const char *authproto_to_str(uint8_t);
55 static const char *authalg_to_str(uint8_t, uint8_t);
56 static const char *authrdm_to_str(uint8_t);
57 static const char *cwhat_to_str(uint8_t);
58 static const char *catype_to_str(uint8_t);
59 static void show_hex(const uint8_t *, int, const char *);
60 static void show_ascii(const uint8_t *, int, const char *);
61 static void show_address(const char *, const void *);
62 static void show_options(const uint8_t *, int);
65 interpret_dhcpv6(int flags
, const uint8_t *data
, int len
)
75 (void) strlcpy(get_sum_line(), "DHCPv6?", MAXLINE
);
81 in6_addr_t link
, peer
;
82 char linkstr
[INET6_ADDRSTRLEN
];
83 char peerstr
[INET6_ADDRSTRLEN
];
85 line
= lstart
= get_sum_line();
86 line
+= snprintf(line
, MAXLINE
, "DHCPv6 %s",
87 mtype_to_str(data
[0]));
88 if (data
[0] == DHCPV6_MSG_RELAY_FORW
||
89 data
[0] == DHCPV6_MSG_RELAY_REPL
) {
90 if (len
< sizeof (d6r
)) {
91 (void) strlcpy(line
, "?",
92 MAXLINE
- (line
- lstart
));
95 /* Not much in DHCPv6 is aligned. */
96 (void) memcpy(&d6r
, data
, sizeof (d6r
));
97 (void) memcpy(&link
, d6r
.d6r_linkaddr
, sizeof (link
));
98 (void) memcpy(&peer
, d6r
.d6r_peeraddr
, sizeof (peer
));
99 line
+= snprintf(line
, MAXLINE
- (line
- lstart
),
100 " HC=%d link=%s peer=%s", d6r
.d6r_hop_count
,
101 inet_ntop(AF_INET6
, &link
, linkstr
,
103 inet_ntop(AF_INET6
, &peer
, peerstr
,
105 data
+= sizeof (d6r
);
108 if (len
< sizeof (d6m
)) {
109 (void) strlcpy(line
, "?",
110 MAXLINE
- (line
- lstart
));
113 (void) memcpy(&d6m
, data
, sizeof (d6m
));
114 line
+= snprintf(line
, MAXLINE
- (line
- lstart
),
115 " xid=%x", DHCPV6_GET_TRANSID(&d6m
));
116 data
+= sizeof (d6m
);
121 while ((d6o
= dhcpv6_find_option(data
, len
, d6o
,
122 DHCPV6_OPT_IA_NA
, NULL
)) != NULL
)
125 line
+= snprintf(line
, MAXLINE
- (line
- lstart
),
127 d6o
= dhcpv6_find_option(data
, len
, NULL
,
128 DHCPV6_OPT_STATUS_CODE
, &optlen
);
129 optlen
-= sizeof (*d6o
);
130 if (d6o
!= NULL
&& optlen
>= sizeof (statuscode
)) {
131 (void) memcpy(&statuscode
, d6o
+ 1,
132 sizeof (statuscode
));
133 line
+= snprintf(line
, MAXLINE
- (line
- lstart
),
134 " status=%u", ntohs(statuscode
));
135 optlen
-= sizeof (statuscode
);
137 line
+= snprintf(line
,
138 MAXLINE
- (line
- lstart
), " \"%.*s\"",
139 optlen
, (char *)(d6o
+ 1) + 2);
142 d6o
= dhcpv6_find_option(data
, len
, NULL
,
143 DHCPV6_OPT_RELAY_MSG
, &optlen
);
144 optlen
-= sizeof (*d6o
);
145 if (d6o
!= NULL
&& optlen
>= 1) {
146 line
+= snprintf(line
, MAXLINE
- (line
- lstart
),
147 " relay=%s", mtype_to_str(*(uint8_t *)(d6o
+ 1)));
149 } else if (flags
& F_DTAIL
) {
150 show_header("DHCPv6: ",
151 "Dynamic Host Configuration Protocol Version 6", len
);
153 (void) snprintf(get_line(0, 0), get_line_remain(),
154 "Message type (msg-type) = %u (%s)", data
[0],
155 mtype_to_str(data
[0]));
156 if (data
[0] == DHCPV6_MSG_RELAY_FORW
||
157 data
[0] == DHCPV6_MSG_RELAY_REPL
) {
158 if (len
< sizeof (d6r
)) {
159 (void) strlcpy(get_line(0, 0), "Truncated",
163 (void) memcpy(&d6r
, data
, sizeof (d6r
));
164 (void) snprintf(get_line(0, 0), get_line_remain(),
165 "Hop count = %u", d6r
.d6r_hop_count
);
166 show_address("Link address", d6r
.d6r_linkaddr
);
167 show_address("Peer address", d6r
.d6r_peeraddr
);
168 data
+= sizeof (d6r
);
171 if (len
< sizeof (d6m
)) {
172 (void) strlcpy(get_line(0, 0), "Truncated",
176 (void) memcpy(&d6m
, data
, sizeof (d6m
));
177 (void) snprintf(get_line(0, 0), get_line_remain(),
178 "Transaction ID = %x", DHCPV6_GET_TRANSID(&d6m
));
179 data
+= sizeof (d6m
);
183 show_options(data
, len
);
190 mtype_to_str(uint8_t mtype
)
193 case DHCPV6_MSG_SOLICIT
:
195 case DHCPV6_MSG_ADVERTISE
:
196 return ("Advertise");
197 case DHCPV6_MSG_REQUEST
:
199 case DHCPV6_MSG_CONFIRM
:
201 case DHCPV6_MSG_RENEW
:
203 case DHCPV6_MSG_REBIND
:
205 case DHCPV6_MSG_REPLY
:
207 case DHCPV6_MSG_RELEASE
:
209 case DHCPV6_MSG_DECLINE
:
211 case DHCPV6_MSG_RECONFIGURE
:
212 return ("Reconfigure");
213 case DHCPV6_MSG_INFO_REQ
:
214 return ("Information-Request");
215 case DHCPV6_MSG_RELAY_FORW
:
216 return ("Relay-Forward");
217 case DHCPV6_MSG_RELAY_REPL
:
218 return ("Relay-Reply");
225 option_to_str(uint8_t mtype
)
228 case DHCPV6_OPT_CLIENTID
:
229 return ("Client Identifier");
230 case DHCPV6_OPT_SERVERID
:
231 return ("Server Identifier");
232 case DHCPV6_OPT_IA_NA
:
233 return ("Identity Association for Non-temporary Addresses");
234 case DHCPV6_OPT_IA_TA
:
235 return ("Identity Association for Temporary Addresses");
236 case DHCPV6_OPT_IAADDR
:
237 return ("IA Address");
239 return ("Option Request");
240 case DHCPV6_OPT_PREFERENCE
:
241 return ("Preference");
242 case DHCPV6_OPT_ELAPSED_TIME
:
243 return ("Elapsed Time");
244 case DHCPV6_OPT_RELAY_MSG
:
245 return ("Relay Message");
246 case DHCPV6_OPT_AUTH
:
247 return ("Authentication");
248 case DHCPV6_OPT_UNICAST
:
249 return ("Server Unicast");
250 case DHCPV6_OPT_STATUS_CODE
:
251 return ("Status Code");
252 case DHCPV6_OPT_RAPID_COMMIT
:
253 return ("Rapid Commit");
254 case DHCPV6_OPT_USER_CLASS
:
255 return ("User Class");
256 case DHCPV6_OPT_VENDOR_CLASS
:
257 return ("Vendor Class");
258 case DHCPV6_OPT_VENDOR_OPT
:
259 return ("Vendor-specific Information");
260 case DHCPV6_OPT_INTERFACE_ID
:
261 return ("Interface-Id");
262 case DHCPV6_OPT_RECONF_MSG
:
263 return ("Reconfigure Message");
264 case DHCPV6_OPT_RECONF_ACC
:
265 return ("Reconfigure Accept");
266 case DHCPV6_OPT_SIP_NAMES
:
267 return ("SIP Servers Domain Name List");
268 case DHCPV6_OPT_SIP_ADDR
:
269 return ("SIP Servers IPv6 Address List");
270 case DHCPV6_OPT_DNS_ADDR
:
271 return ("DNS Recursive Name Server");
272 case DHCPV6_OPT_DNS_SEARCH
:
273 return ("Domain Search List");
274 case DHCPV6_OPT_IA_PD
:
275 return ("Identity Association for Prefix Delegation");
276 case DHCPV6_OPT_IAPREFIX
:
277 return ("IA_PD Prefix");
278 case DHCPV6_OPT_NIS_SERVERS
:
279 return ("Network Information Service Servers");
280 case DHCPV6_OPT_NIS_DOMAIN
:
281 return ("Network Information Service Domain Name");
282 case DHCPV6_OPT_SNTP_SERVERS
:
283 return ("Simple Network Time Protocol Servers");
284 case DHCPV6_OPT_INFO_REFTIME
:
285 return ("Information Refresh Time");
286 case DHCPV6_OPT_BCMCS_SRV_D
:
287 return ("BCMCS Controller Domain Name List");
288 case DHCPV6_OPT_BCMCS_SRV_A
:
289 return ("BCMCS Controller IPv6 Address");
290 case DHCPV6_OPT_GEOCONF_CVC
:
291 return ("Civic Location");
292 case DHCPV6_OPT_REMOTE_ID
:
293 return ("Relay Agent Remote-ID");
294 case DHCPV6_OPT_SUBSCRIBER
:
295 return ("Relay Agent Subscriber-ID");
296 case DHCPV6_OPT_CLIENT_FQDN
:
297 return ("Client FQDN");
304 duidtype_to_str(uint16_t dtype
)
307 case DHCPV6_DUID_LLT
:
308 return ("Link-layer Address Plus Time");
310 return ("Enterprise Number");
312 return ("Link-layer Address");
319 status_to_str(uint16_t status
)
322 case DHCPV6_STAT_SUCCESS
:
324 case DHCPV6_STAT_UNSPECFAIL
:
325 return ("Failure, reason unspecified");
326 case DHCPV6_STAT_NOADDRS
:
327 return ("No addresses for IAs");
328 case DHCPV6_STAT_NOBINDING
:
329 return ("Client binding unavailable");
330 case DHCPV6_STAT_NOTONLINK
:
331 return ("Prefix not on link");
332 case DHCPV6_STAT_USEMCAST
:
333 return ("Use multicast");
334 case DHCPV6_STAT_NOPREFIX
:
335 return ("No prefix available");
342 entr_to_str(uint32_t entr
)
346 return ("Sun Microsystems");
353 reconf_to_str(uint8_t msgtype
)
356 case DHCPV6_RECONF_RENEW
:
358 case DHCPV6_RECONF_INFO
:
359 return ("Information-request");
366 authproto_to_str(uint8_t aproto
)
369 case DHCPV6_PROTO_DELAYED
:
371 case DHCPV6_PROTO_RECONFIG
:
372 return ("Reconfigure Key");
379 authalg_to_str(uint8_t aproto
, uint8_t aalg
)
382 case DHCPV6_PROTO_DELAYED
:
383 case DHCPV6_PROTO_RECONFIG
:
385 case DHCPV6_ALG_HMAC_MD5
:
386 return ("HMAC-MD5 Signature");
397 authrdm_to_str(uint8_t ardm
)
400 case DHCPV6_RDM_MONOCNT
:
401 return ("Monotonic Counter");
408 cwhat_to_str(uint8_t what
)
411 case DHCPV6_CWHAT_SERVER
:
413 case DHCPV6_CWHAT_NETWORK
:
415 case DHCPV6_CWHAT_CLIENT
:
423 catype_to_str(uint8_t catype
)
427 return ("Language; RFC 2277");
429 return ("National division (state)");
435 return ("City division");
437 return ("Neighborhood");
439 return ("Street group");
441 return ("Leading street direction");
443 return ("Trailing street suffix");
445 return ("Street suffix or type");
447 return ("House number");
449 return ("House number suffix");
453 return ("Additional location information");
455 return ("Name/occupant");
457 return ("Postal Code/ZIP");
461 return ("Unit/apt/suite");
465 return ("Room number");
467 return ("Place type");
469 return ("Postal community name");
470 case CIVICADDR_POBOX
:
471 return ("Post office box");
473 return ("Additional code");
475 return ("Seat/desk");
477 return ("Primary road or street");
479 return ("Road section");
481 return ("Road branch");
483 return ("Road sub-branch");
485 return ("Street name pre-modifier");
486 case CIVICADDR_SPOST
:
487 return ("Street name post-modifier");
488 case CIVICADDR_SCRIPT
:
496 show_hex(const uint8_t *data
, int len
, const char *name
)
498 char buffer
[16 * 3 + 1];
506 for (i
= 0; i
< 16 && i
< len
; i
++)
507 (void) snprintf(buffer
+ 3 * i
, 4, " %02x", *data
++);
508 (void) snprintf(get_line(0, 0), get_line_remain(), "%*s %c%s",
509 nlen
, name
, sep
, buffer
);
517 show_ascii(const uint8_t *data
, int len
, const char *name
)
519 char buffer
[64], *bp
;
528 for (i
= 0; i
< sizeof (buffer
) - 4 && len
> 0; len
--) {
529 if (!isascii(*data
) || !isprint(*data
))
530 bp
+= snprintf(bp
, 5, "\\%03o", *data
++);
535 (void) snprintf(get_line(0, 0), get_line_remain(),
536 "%*s %c \"%s\"", nlen
, name
, sep
, buffer
);
543 show_address(const char *addrname
, const void *aptr
)
546 char addrstr
[INET6_ADDRSTRLEN
];
549 (void) memcpy(&addr
, aptr
, sizeof (in6_addr_t
));
550 (void) inet_ntop(AF_INET6
, &addr
, addrstr
, sizeof (addrstr
));
551 hname
= addrtoname(AF_INET6
, &addr
);
552 if (strcmp(hname
, addrstr
) == 0) {
553 (void) snprintf(get_line(0, 0), get_line_remain(), "%s = %s",
556 (void) snprintf(get_line(0, 0), get_line_remain(),
557 "%s = %s (%s)", addrname
, addrstr
, hname
);
562 nest_options(const uint8_t *data
, uint_t olen
, char *prefix
, char *title
)
564 char *str
, *oldnest
, *oldprefix
;
568 oldprefix
= prot_prefix
;
569 oldnest
= prot_nest_prefix
;
570 str
= malloc(strlen(prot_nest_prefix
) + strlen(prot_prefix
) + 1);
572 prot_nest_prefix
= prot_prefix
;
574 (void) sprintf(str
, "%s%s", prot_nest_prefix
, prot_prefix
);
575 prot_nest_prefix
= str
;
577 show_header(prefix
, title
, 0);
578 show_options(data
, olen
);
580 prot_prefix
= oldprefix
;
581 prot_nest_prefix
= oldnest
;
585 show_options(const uint8_t *data
, int len
)
592 const uint8_t *ostart
;
597 * Be very careful with negative numbers; ANSI signed/unsigned
598 * comparison doesn't work as expected.
600 while (len
>= (signed)sizeof (d6o
)) {
601 (void) memcpy(&d6o
, data
, sizeof (d6o
));
602 d6o
.d6o_code
= ntohs(d6o
.d6o_code
);
603 d6o
.d6o_len
= olen
= ntohs(d6o
.d6o_len
);
604 (void) snprintf(get_line(0, 0), get_line_remain(),
605 "Option Code = %u (%s)", d6o
.d6o_code
,
606 option_to_str(d6o
.d6o_code
));
607 ostart
= data
+= sizeof (d6o
);
610 (void) strlcpy(get_line(0, 0), "Option truncated",
614 switch (d6o
.d6o_code
) {
615 case DHCPV6_OPT_CLIENTID
:
616 case DHCPV6_OPT_SERVERID
:
617 if (olen
< sizeof (val16
))
619 (void) memcpy(&val16
, data
, sizeof (val16
));
620 data
+= sizeof (val16
);
621 olen
-= sizeof (val16
);
623 (void) snprintf(get_line(0, 0), get_line_remain(),
624 " DUID Type = %u (%s)", type
,
625 duidtype_to_str(type
));
626 if (type
== DHCPV6_DUID_LLT
|| type
== DHCPV6_DUID_LL
) {
627 if (olen
< sizeof (val16
))
629 (void) memcpy(&val16
, data
, sizeof (val16
));
630 data
+= sizeof (val16
);
631 olen
-= sizeof (val16
);
632 val16
= ntohs(val16
);
633 (void) snprintf(get_line(0, 0),
635 " Hardware Type = %u (%s)", val16
,
638 if (type
== DHCPV6_DUID_LLT
) {
641 if (olen
< sizeof (val32
))
643 (void) memcpy(&val32
, data
, sizeof (val32
));
644 data
+= sizeof (val32
);
645 olen
-= sizeof (val32
);
646 timevalue
= ntohl(val32
) + DUID_TIME_BASE
;
647 (void) snprintf(get_line(0, 0),
649 " Time = %lu (%.24s)", ntohl(val32
),
652 if (type
== DHCPV6_DUID_EN
) {
653 if (olen
< sizeof (val32
))
655 (void) memcpy(&val32
, data
, sizeof (val32
));
656 data
+= sizeof (val32
);
657 olen
-= sizeof (val32
);
658 val32
= ntohl(val32
);
659 (void) snprintf(get_line(0, 0),
661 " Enterprise Number = %lu (%s)", val32
,
666 if ((str
= malloc(olen
* 3)) == NULL
)
667 pr_err("interpret_dhcpv6: no mem");
668 sp
= str
+ snprintf(str
, 3, "%02x", *data
++);
670 *sp
++ = (type
== DHCPV6_DUID_LLT
||
671 type
== DHCPV6_DUID_LL
) ? ':' : ' ';
672 sp
= sp
+ snprintf(sp
, 3, "%02x", *data
++);
674 (void) snprintf(get_line(0, 0), get_line_remain(),
675 (type
== DHCPV6_DUID_LLT
||
676 type
== DHCPV6_DUID_LL
) ?
677 " Link Layer Address = %s" :
678 " Identifier = %s", str
);
681 case DHCPV6_OPT_IA_NA
:
682 case DHCPV6_OPT_IA_PD
: {
685 if (olen
< sizeof (d6in
) - sizeof (d6o
))
687 (void) memcpy(&d6in
, data
- sizeof (d6o
),
689 data
+= sizeof (d6in
) - sizeof (d6o
);
690 olen
-= sizeof (d6in
) - sizeof (d6o
);
691 (void) snprintf(get_line(0, 0), get_line_remain(),
692 " IAID = %u", ntohl(d6in
.d6in_iaid
));
693 (void) snprintf(get_line(0, 0), get_line_remain(),
694 " T1 (renew) = %u seconds", ntohl(d6in
.d6in_t1
));
695 (void) snprintf(get_line(0, 0), get_line_remain(),
696 " T2 (rebind) = %u seconds", ntohl(d6in
.d6in_t2
));
697 nest_options(data
, olen
, "IA: ",
698 "Identity Association");
701 case DHCPV6_OPT_IA_TA
: {
704 if (olen
< sizeof (d6it
) - sizeof (d6o
))
706 (void) memcpy(&d6it
, data
- sizeof (d6o
),
708 data
+= sizeof (d6it
) - sizeof (d6o
);
709 olen
-= sizeof (d6it
) - sizeof (d6o
);
710 (void) snprintf(get_line(0, 0), get_line_remain(),
711 " IAID = %u", ntohl(d6it
.d6it_iaid
));
712 nest_options(data
, olen
, "IA: ",
713 "Identity Association");
716 case DHCPV6_OPT_IAADDR
: {
717 dhcpv6_iaaddr_t d6ia
;
719 if (olen
< sizeof (d6ia
) - sizeof (d6o
))
721 (void) memcpy(&d6ia
, data
- sizeof (d6o
),
723 data
+= sizeof (d6ia
) - sizeof (d6o
);
724 olen
-= sizeof (d6ia
) - sizeof (d6o
);
725 show_address(" Address", &d6ia
.d6ia_addr
);
726 (void) snprintf(get_line(0, 0), get_line_remain(),
727 " Preferred lifetime = %u seconds",
728 ntohl(d6ia
.d6ia_preflife
));
729 (void) snprintf(get_line(0, 0), get_line_remain(),
730 " Valid lifetime = %u seconds",
731 ntohl(d6ia
.d6ia_vallife
));
732 nest_options(data
, olen
, "ADDR: ", "Address");
736 while (olen
>= sizeof (val16
)) {
737 (void) memcpy(&val16
, data
, sizeof (val16
));
738 val16
= ntohs(val16
);
739 (void) snprintf(get_line(0, 0),
741 " Requested Option Code = %u (%s)", val16
,
742 option_to_str(val16
));
743 data
+= sizeof (val16
);
744 olen
-= sizeof (val16
);
747 case DHCPV6_OPT_PREFERENCE
:
749 (void) snprintf(get_line(0, 0),
752 " Preference = %u (immediate)" :
753 " Preference = %u", *data
);
756 case DHCPV6_OPT_ELAPSED_TIME
:
757 if (olen
== sizeof (val16
)) {
758 (void) memcpy(&val16
, data
, sizeof (val16
));
759 val16
= ntohs(val16
);
760 (void) snprintf(get_line(0, 0),
762 " Elapsed Time = %u.%02u seconds",
763 val16
/ 100, val16
% 100);
766 case DHCPV6_OPT_RELAY_MSG
:
768 oldnest
= prot_nest_prefix
;
769 prot_nest_prefix
= prot_prefix
;
770 (void) interpret_dhcpv6(F_DTAIL
, data
, olen
);
771 prot_prefix
= prot_nest_prefix
;
772 prot_nest_prefix
= oldnest
;
775 case DHCPV6_OPT_AUTH
: {
778 if (olen
< DHCPV6_AUTH_SIZE
- sizeof (d6o
))
780 (void) memcpy(&d6a
, data
- sizeof (d6o
),
782 data
+= DHCPV6_AUTH_SIZE
- sizeof (d6o
);
783 olen
+= DHCPV6_AUTH_SIZE
- sizeof (d6o
);
784 (void) snprintf(get_line(0, 0), get_line_remain(),
785 " Protocol = %u (%s)", d6a
.d6a_proto
,
786 authproto_to_str(d6a
.d6a_proto
));
787 (void) snprintf(get_line(0, 0), get_line_remain(),
788 " Algorithm = %u (%s)", d6a
.d6a_alg
,
789 authalg_to_str(d6a
.d6a_proto
, d6a
.d6a_alg
));
790 (void) snprintf(get_line(0, 0), get_line_remain(),
791 " Replay Detection Method = %u (%s)", d6a
.d6a_rdm
,
792 authrdm_to_str(d6a
.d6a_rdm
));
793 show_hex(d6a
.d6a_replay
, sizeof (d6a
.d6a_replay
),
796 show_hex(data
, olen
, " Auth Info");
799 case DHCPV6_OPT_UNICAST
:
800 if (olen
>= sizeof (in6_addr_t
))
801 show_address(" Server Address", data
);
803 case DHCPV6_OPT_STATUS_CODE
:
804 if (olen
< sizeof (val16
))
806 (void) memcpy(&val16
, data
, sizeof (val16
));
807 val16
= ntohs(val16
);
808 (void) snprintf(get_line(0, 0), get_line_remain(),
809 " Status Code = %u (%s)", val16
,
810 status_to_str(val16
));
811 data
+= sizeof (val16
);
812 olen
-= sizeof (val16
);
814 (void) snprintf(get_line(0, 0),
815 get_line_remain(), " Text = \"%.*s\"",
818 case DHCPV6_OPT_VENDOR_CLASS
:
819 if (olen
< sizeof (val32
))
821 (void) memcpy(&val32
, data
, sizeof (val32
));
822 data
+= sizeof (val32
);
823 olen
-= sizeof (val32
);
824 val32
= ntohl(val32
);
825 (void) snprintf(get_line(0, 0), get_line_remain(),
826 " Enterprise Number = %lu (%s)", val32
,
829 case DHCPV6_OPT_USER_CLASS
:
830 while (olen
>= sizeof (val16
)) {
831 (void) memcpy(&val16
, data
, sizeof (val16
));
832 data
+= sizeof (val16
);
833 olen
-= sizeof (val16
);
834 val16
= ntohs(val16
);
836 (void) strlcpy(get_line(0, 0),
841 show_hex(data
, olen
, " Class");
846 case DHCPV6_OPT_VENDOR_OPT
: {
847 dhcpv6_option_t sd6o
;
849 if (olen
< sizeof (val32
))
851 (void) memcpy(&val32
, data
, sizeof (val32
));
852 data
+= sizeof (val32
);
853 olen
-= sizeof (val32
);
854 val32
= ntohl(val32
);
855 (void) snprintf(get_line(0, 0), get_line_remain(),
856 " Enterprise Number = %lu (%s)", val32
,
858 while (olen
>= sizeof (sd6o
)) {
859 (void) memcpy(&sd6o
, data
, sizeof (sd6o
));
860 sd6o
.d6o_code
= ntohs(sd6o
.d6o_code
);
861 sd6o
.d6o_len
= ntohs(sd6o
.d6o_len
);
862 (void) snprintf(get_line(0, 0),
864 " Vendor Option Code = %u", d6o
.d6o_code
);
865 data
+= sizeof (d6o
);
866 olen
-= sizeof (d6o
);
867 if (sd6o
.d6o_len
> olen
) {
868 (void) strlcpy(get_line(0, 0),
869 " Vendor Option truncated",
873 if (sd6o
.d6o_len
> 0) {
874 show_hex(data
, sd6o
.d6o_len
,
876 data
+= sd6o
.d6o_len
;
877 olen
-= sd6o
.d6o_len
;
882 case DHCPV6_OPT_REMOTE_ID
:
883 if (olen
< sizeof (val32
))
885 (void) memcpy(&val32
, data
, sizeof (val32
));
886 data
+= sizeof (val32
);
887 olen
-= sizeof (val32
);
888 val32
= ntohl(val32
);
889 (void) snprintf(get_line(0, 0), get_line_remain(),
890 " Enterprise Number = %lu (%s)", val32
,
893 case DHCPV6_OPT_INTERFACE_ID
:
894 case DHCPV6_OPT_SUBSCRIBER
:
896 show_hex(data
, olen
, " ID");
898 case DHCPV6_OPT_RECONF_MSG
:
900 (void) snprintf(get_line(0, 0),
902 " Message Type = %u (%s)", *data
,
903 reconf_to_str(*data
));
906 case DHCPV6_OPT_SIP_NAMES
:
907 case DHCPV6_OPT_DNS_SEARCH
:
908 case DHCPV6_OPT_NIS_DOMAIN
:
909 case DHCPV6_OPT_BCMCS_SRV_D
: {
913 symp
= inittab_getbycode(
914 ITAB_CAT_STANDARD
| ITAB_CAT_V6
, ITAB_CONS_SNOOP
,
917 str
= inittab_decode(symp
, data
, olen
, B_TRUE
);
921 sp2
= strchr(sp
, ' ');
924 (void) snprintf(get_line(0, 0),
927 } while ((sp
= sp2
) != NULL
);
934 case DHCPV6_OPT_SIP_ADDR
:
935 case DHCPV6_OPT_DNS_ADDR
:
936 case DHCPV6_OPT_NIS_SERVERS
:
937 case DHCPV6_OPT_SNTP_SERVERS
:
938 case DHCPV6_OPT_BCMCS_SRV_A
:
939 while (olen
>= sizeof (in6_addr_t
)) {
940 show_address(" Address", data
);
941 data
+= sizeof (in6_addr_t
);
942 olen
-= sizeof (in6_addr_t
);
945 case DHCPV6_OPT_IAPREFIX
: {
946 dhcpv6_iaprefix_t d6ip
;
948 if (olen
< DHCPV6_IAPREFIX_SIZE
- sizeof (d6o
))
950 (void) memcpy(&d6ip
, data
- sizeof (d6o
),
951 DHCPV6_IAPREFIX_SIZE
);
952 data
+= DHCPV6_IAPREFIX_SIZE
- sizeof (d6o
);
953 olen
-= DHCPV6_IAPREFIX_SIZE
- sizeof (d6o
);
954 show_address(" Prefix", d6ip
.d6ip_addr
);
955 (void) snprintf(get_line(0, 0), get_line_remain(),
956 " Preferred lifetime = %u seconds",
957 ntohl(d6ip
.d6ip_preflife
));
958 (void) snprintf(get_line(0, 0), get_line_remain(),
959 " Valid lifetime = %u seconds",
960 ntohl(d6ip
.d6ip_vallife
));
961 (void) snprintf(get_line(0, 0), get_line_remain(),
962 " Prefix length = %u", d6ip
.d6ip_preflen
);
963 nest_options(data
, olen
, "ADDR: ", "Address");
966 case DHCPV6_OPT_INFO_REFTIME
:
967 if (olen
< sizeof (val32
))
969 (void) memcpy(&val32
, data
, sizeof (val32
));
970 (void) snprintf(get_line(0, 0), get_line_remain(),
971 " Refresh Time = %lu seconds", ntohl(val32
));
973 case DHCPV6_OPT_GEOCONF_CVC
: {
977 if (olen
< DHCPV6_CIVIC_SIZE
- sizeof (d6o
))
979 (void) memcpy(&d6c
, data
- sizeof (d6o
),
981 data
+= DHCPV6_CIVIC_SIZE
- sizeof (d6o
);
982 olen
-= DHCPV6_CIVIC_SIZE
- sizeof (d6o
);
983 (void) snprintf(get_line(0, 0), get_line_remain(),
984 " What Location = %u (%s)", d6c
.d6c_what
,
985 cwhat_to_str(d6c
.d6c_what
));
986 (void) snprintf(get_line(0, 0), get_line_remain(),
987 " Country Code = %.*s", sizeof (d6c
.d6c_cc
),
990 (void) snprintf(get_line(0, 0),
992 " CA Element = %u (%s)", *data
,
993 catype_to_str(*data
));
998 (void) strlcpy(get_line(0, 0),
999 " CA Element truncated",
1004 show_ascii(data
, solen
, " CA Data");
1011 case DHCPV6_OPT_CLIENT_FQDN
: {
1012 dhcp_symbol_t
*symp
;
1016 (void) snprintf(get_line(0, 0), get_line_remain(),
1017 " Flags = %02x", *data
);
1018 (void) snprintf(get_line(0, 0), get_line_remain(),
1019 " %s", getflag(*data
, DHCPV6_FQDNF_S
,
1020 "Perform AAAA RR updates", "No AAAA RR updates"));
1021 (void) snprintf(get_line(0, 0), get_line_remain(),
1022 " %s", getflag(*data
, DHCPV6_FQDNF_O
,
1023 "Server override updates",
1024 "No server override updates"));
1025 (void) snprintf(get_line(0, 0), get_line_remain(),
1026 " %s", getflag(*data
, DHCPV6_FQDNF_N
,
1027 "Server performs no updates",
1028 "Server performs updates"));
1029 symp
= inittab_getbycode(
1030 ITAB_CAT_STANDARD
| ITAB_CAT_V6
, ITAB_CONS_SNOOP
,
1033 str
= inittab_decode(symp
, data
, olen
, B_TRUE
);
1035 (void) snprintf(get_line(0, 0),
1045 data
= ostart
+ d6o
.d6o_len
;
1049 (void) strlcpy(get_line(0, 0), "Option entry truncated",