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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 #include <sys/types.h>
29 #include <sys/socket.h>
31 #include <sys/stropts.h>
32 #include <sys/sysmacros.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/in.h>
35 #include <netinet/ip.h>
36 #include <netinet/ip_icmp.h>
37 #include <netinet/udp.h>
38 #include <netinet/tcp.h>
39 #include <netinet/icmp6.h>
40 #include <netinet/ip6.h>
43 #include <arpa/inet.h>
46 #include "snoop_mip.h"
48 static void interpret_options(char *, int);
49 static void interpret_mldv2qry(icmp6_t
*, int);
50 static void interpret_mldv2rpt(icmp6_t
*, int);
53 /* Mobile-IP routines from snoop_mip.c */
54 extern void interpret_icmp_mip_ext(uchar_t
*, int);
55 extern const char *get_mip_adv_desc(uint8_t);
57 /* Router advertisement message structure. */
65 interpret_icmp(int flags
, struct icmp
*icmp
, int iplen
, int ilen
)
69 char buff
[67627]; /* Router adv. can have 256 routers .... */
70 /* Each router has a name 256 char long .. */
71 char extbuff
[MAXHOSTNAMELEN
+ 1];
72 struct udphdr
*orig_uhdr
;
73 int num_rtr_addrs
= 0;
74 extern char *prot_nest_prefix
;
76 if (ilen
< ICMP_MINLEN
)
77 return; /* incomplete header */
83 switch (icmp
->icmp_type
) {
86 (void) sprintf(buff
, "ID: %d Sequence number: %d",
87 ntohs(icmp
->icmp_id
), ntohs(icmp
->icmp_seq
));
91 pt
= "Destination unreachable";
92 switch (icmp
->icmp_code
) {
93 case ICMP_UNREACH_NET
:
94 if (ilen
>= ICMP_ADVLENMIN
) {
95 (void) sprintf(buff
, "Net %s unreachable",
97 &icmp
->icmp_ip
.ip_dst
));
103 case ICMP_UNREACH_HOST
:
104 if (ilen
>= ICMP_ADVLENMIN
) {
105 (void) sprintf(buff
, "Host %s unreachable",
107 &icmp
->icmp_ip
.ip_dst
));
113 case ICMP_UNREACH_PROTOCOL
:
114 if (ilen
>= ICMP_ADVLENMIN
) {
115 (void) sprintf(buff
, "Bad protocol %d",
122 case ICMP_UNREACH_PORT
:
123 if (ilen
>= ICMP_ADVLENMIN
) {
124 orig_uhdr
= (struct udphdr
*)((uchar_t
*)icmp
+
125 ICMP_MINLEN
+ icmp
->icmp_ip
.ip_hl
* 4);
126 switch (icmp
->icmp_ip
.ip_p
) {
128 (void) sprintf(buff
, "TCP port %d"
130 ntohs(orig_uhdr
->uh_dport
));
134 (void) sprintf(buff
, "UDP port %d"
136 ntohs(orig_uhdr
->uh_dport
));
140 pc
= "Port unreachable";
147 case ICMP_UNREACH_NEEDFRAG
:
148 if (ntohs(icmp
->icmp_nextmtu
) != 0) {
149 (void) sprintf(buff
, "Needed to fragment:"
150 " next hop MTU = %d",
151 ntohs(icmp
->icmp_nextmtu
));
154 pc
= "Needed to fragment";
157 case ICMP_UNREACH_SRCFAIL
:
158 pc
= "Source route failed";
160 case ICMP_UNREACH_NET_UNKNOWN
:
161 pc
= "Unknown network";
163 case ICMP_UNREACH_HOST_UNKNOWN
:
166 case ICMP_UNREACH_ISOLATED
:
167 pc
= "Source host isolated";
169 case ICMP_UNREACH_NET_PROHIB
:
170 pc
= "Net administratively prohibited";
172 case ICMP_UNREACH_HOST_PROHIB
:
173 pc
= "Host administratively prohibited";
175 case ICMP_UNREACH_TOSNET
:
176 pc
= "Net unreachable for this TOS";
178 case ICMP_UNREACH_TOSHOST
:
179 pc
= "Host unreachable for this TOS";
181 case ICMP_UNREACH_FILTER_PROHIB
:
182 pc
= "Communication administratively prohibited";
184 case ICMP_UNREACH_HOST_PRECEDENCE
:
185 pc
= "Host precedence violation";
187 case ICMP_UNREACH_PRECEDENCE_CUTOFF
:
188 pc
= "Precedence cutoff in effect";
194 case ICMP_SOURCEQUENCH
:
195 pt
= "Packet lost, slow down";
199 switch (icmp
->icmp_code
) {
200 case ICMP_REDIRECT_NET
:
203 case ICMP_REDIRECT_HOST
:
206 case ICMP_REDIRECT_TOSNET
:
207 pc
= "for tos and net";
209 case ICMP_REDIRECT_TOSHOST
:
210 pc
= "for tos and host";
215 (void) sprintf(buff
, "%s %s to %s",
216 pc
, addrtoname(AF_INET
, &icmp
->icmp_ip
.ip_dst
),
217 addrtoname(AF_INET
, &icmp
->icmp_gwaddr
));
222 (void) sprintf(buff
, "ID: %d Sequence number: %d",
223 ntohs(icmp
->icmp_id
), ntohs(icmp
->icmp_seq
));
226 case ICMP_ROUTERADVERT
:
228 #define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
229 #define icmp_wpa icmp_hun.ih_rtradv.irt_wpa
230 #define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime
232 pt
= "Router advertisement";
233 (void) sprintf(buff
, "Lifetime %ds [%d]:",
234 ntohs(icmp
->icmp_lifetime
), icmp
->icmp_num_addrs
);
235 if (icmp
->icmp_wpa
== 2) {
236 struct icmp_ra_addr
*ra
;
237 char ra_buf
[MAXHOSTNAMELEN
+ 32];
243 /* Cannot trust anything from the network... */
244 num_rtr_addrs
= MIN((ilen
- ICMP_MINLEN
) / 8,
245 icmp
->icmp_num_addrs
);
247 ra
= (struct icmp_ra_addr
*)icmp
->icmp_data
;
248 for (i
= 0; i
< num_rtr_addrs
; i
++) {
249 sin
.s_addr
= ra
->addr
;
250 (void) snprintf(ra_buf
, sizeof (ra_buf
),
252 addrtoname(AF_INET
, &sin
),
253 ntohl(ra
->preference
));
254 if (strlcat(buff
, ra_buf
, sizeof (buff
)) >=
257 strlen("<Too Long>)")] = '\0';
258 (void) strlcat(buff
, "<Too Long>",
265 icmp_ra_len
= ICMP_MINLEN
+ num_rtr_addrs
*
266 sizeof (struct icmp_ra_addr
);
267 if (ilen
> icmp_ra_len
) {
268 int curr_len
= ilen
- icmp_ra_len
;
270 exthdr_t
*exthdr
= (exthdr_t
*)ra
;
274 while (curr_len
> 0) {
275 /* Append Mobile-IP description */
276 (void) snprintf(ra_ext_buf
,
277 sizeof (ra_ext_buf
), ", %s",
278 get_mip_adv_desc(exthdr
->type
));
279 (void) strlcat(extbuff
, ra_ext_buf
,
282 /* Special case for padding */
284 ICMP_ADV_MSG_PADDING_EXT
) {
287 exthdr
= (exthdr_t
*)
288 ((char *)exthdr
+ 1);
292 /* else normal extension */
293 ocurr_len
= curr_len
;
294 curr_len
-= sizeof (*exthdr
) +
296 /* detect bad length */
297 if (ocurr_len
< curr_len
)
299 exthdr
= (exthdr_t
*)
309 case ICMP_ROUTERSOLICIT
:
310 pt
= "Router solicitation";
313 pt
= "Time exceeded";
314 switch (icmp
->icmp_code
) {
315 case ICMP_TIMXCEED_INTRANS
:
318 case ICMP_TIMXCEED_REASS
:
319 pc
= "in reassembly";
326 pt
= "IP parameter problem";
327 switch (icmp
->icmp_code
) {
328 case ICMP_PARAMPROB_OPTABSENT
:
329 pc
= "Required option missing";
331 case ICMP_PARAMPROB_BADLENGTH
:
334 case 0: /* Should this be the default? */
335 (void) sprintf(buff
, "Problem at octet %d\n",
343 pt
= "Timestamp request";
345 case ICMP_TSTAMPREPLY
:
346 pt
= "Timestamp reply";
349 pt
= "Information request";
352 pt
= "Information reply";
355 pt
= "Address mask request";
358 pt
= "Address mask reply";
359 (void) sprintf(buff
, "Mask = 0x%x", ntohl(icmp
->icmp_mask
));
367 line
= get_sum_line();
370 (void) sprintf(line
, "ICMP %s (%s)%s",
373 (void) sprintf(line
, "ICMP %s (%s)", pt
, pc
);
376 (void) sprintf(line
, "ICMP %s", pt
);
380 if (flags
& F_DTAIL
) {
381 show_header("ICMP: ", "ICMP Header", ilen
);
383 (void) sprintf(get_line(0, 0), "Type = %d (%s)",
384 icmp
->icmp_type
, pt
);
386 (void) sprintf(get_line(0, 0), "Code = %d (%s)",
387 icmp
->icmp_code
, pc
);
389 (void) sprintf(get_line(0, 0), "Code = %d",
392 (void) sprintf(get_line(0, 0), "Checksum = %x",
393 ntohs(icmp
->icmp_cksum
));
395 if (icmp
->icmp_type
== ICMP_UNREACH
||
396 icmp
->icmp_type
== ICMP_REDIRECT
) {
399 (void) sprintf(get_line(0, 0),
400 "[ subject header follows ]");
402 prot_nest_prefix
= "ICMP:";
403 (void) interpret_ip(flags
,
404 (struct ip
*)icmp
->icmp_data
, 28);
405 prot_nest_prefix
= "";
407 } else if (icmp
->icmp_type
== ICMP_PARAMPROB
) {
410 (void) sprintf(get_line(0, 0),
411 "[ subject header follows ]");
413 prot_nest_prefix
= "ICMP:";
414 (void) interpret_ip(flags
,
415 (struct ip
*)icmp
->icmp_data
, 28);
416 prot_nest_prefix
= "";
418 } else if (icmp
->icmp_type
== ICMP_ROUTERADVERT
) {
419 if (icmp
->icmp_wpa
== 2) {
423 icmp_ra_len
= ICMP_MINLEN
+
425 sizeof (struct icmp_ra_addr
);
426 prot_nest_prefix
= "";
427 if (ilen
> icmp_ra_len
) {
428 interpret_icmp_mip_ext(
429 (uchar_t
*)icmp
+ icmp_ra_len
,
440 interpret_icmpv6(flags
, icmp6
, iplen
, ilen
)
447 extern char *prot_nest_prefix
;
448 char addrstr
[INET6_ADDRSTRLEN
];
451 if (ilen
< ICMP6_MINLEN
)
452 return; /* incomplete header */
457 switch (icmp6
->icmp6_type
) {
458 case ICMP6_DST_UNREACH
:
459 pt
= "Destination unreachable";
460 switch (icmp6
->icmp6_code
) {
461 case ICMP6_DST_UNREACH_NOROUTE
:
462 pc
= "No route to destination";
464 case ICMP6_DST_UNREACH_ADMIN
:
465 pc
= "Communication administratively prohibited";
467 case ICMP6_DST_UNREACH_ADDR
:
468 pc
= "Address unreachable";
470 case ICMP6_DST_UNREACH_NOPORT
:
471 if (ilen
>= ICMP6_MINLEN
+ IPV6_HDR_LEN
+
472 sizeof (struct udphdr
)) {
474 ip6_t
*orig_ip6hdr
= (ip6_t
*)&icmp6
[1];
476 switch (orig_ip6hdr
->ip6_nxt
) {
478 struct tcphdr
*orig_thdr
=
479 (struct tcphdr
*)&orig_ip6hdr
[1];
481 (void) sprintf(buff
, "TCP port %hu"
483 ntohs(orig_thdr
->th_dport
));
488 struct udphdr
*orig_uhdr
=
489 (struct udphdr
*)&orig_ip6hdr
[1];
491 (void) sprintf(buff
, "UDP port %hu"
493 ntohs(orig_uhdr
->uh_dport
));
498 pc
= "Port unreachable";
509 case ICMP6_PACKET_TOO_BIG
:
510 pt
= "Packet too big";
515 case ICMP6_TIME_EXCEEDED
:
516 pt
= "Time exceeded";
517 switch (icmp6
->icmp6_code
) {
518 case ICMP6_TIME_EXCEED_TRANSIT
:
519 pc
= "Hop limit exceeded in transit";
521 case ICMP6_TIME_EXCEED_REASSEMBLY
:
522 pc
= "Fragment reassembly time exceeded";
528 case ICMP6_PARAM_PROB
:
529 pt
= "Parameter problem";
530 switch (icmp6
->icmp6_code
) {
531 case ICMP6_PARAMPROB_HEADER
:
532 pc
= "Erroneous header field";
534 case ICMP6_PARAMPROB_NEXTHEADER
:
535 pc
= "Unrecognized next header type";
537 case ICMP6_PARAMPROB_OPTION
:
538 pc
= "Unrecognized IPv6 option";
542 case ICMP6_ECHO_REQUEST
:
544 (void) sprintf(buff
, "ID: %d Sequence number: %d",
545 ntohs(icmp6
->icmp6_id
), ntohs(icmp6
->icmp6_seq
));
548 case ICMP6_ECHO_REPLY
:
550 (void) sprintf(buff
, "ID: %d Sequence number: %d",
551 ntohs(icmp6
->icmp6_id
), ntohs(icmp6
->icmp6_seq
));
554 case MLD_LISTENER_QUERY
:
555 if (ilen
== MLD_MINLEN
)
556 pt
= "Group membership query - MLDv1";
557 else if (ilen
>= MLD_V2_QUERY_MINLEN
)
558 pt
= "Group membership query - MLDv2";
560 pt
= "Unknown membership query";
562 case MLD_LISTENER_REPORT
:
563 pt
= "Group membership report - MLDv1";
565 case MLD_LISTENER_REDUCTION
:
566 pt
= "Group membership termination - MLDv1";
568 case MLD_V2_LISTENER_REPORT
:
569 pt
= "Group membership report - MLDv2";
571 case ND_ROUTER_SOLICIT
:
572 pt
= "Router solicitation";
574 case ND_ROUTER_ADVERT
:
575 pt
= "Router advertisement";
577 case ND_NEIGHBOR_SOLICIT
:
578 pt
= "Neighbor solicitation";
580 case ND_NEIGHBOR_ADVERT
:
581 pt
= "Neighbor advertisement";
588 line
= get_sum_line();
590 (void) sprintf(line
, "ICMPv6 %s (%s)", pt
, pc
);
592 (void) sprintf(line
, "ICMPv6 %s", pt
);
595 if (flags
& F_DTAIL
) {
596 show_header("ICMPv6: ", "ICMPv6 Header", ilen
);
598 (void) sprintf(get_line(0, 0), "Type = %d (%s)",
599 icmp6
->icmp6_type
, pt
);
601 (void) sprintf(get_line(0, 0), "Code = %d (%s)",
602 icmp6
->icmp6_code
, pc
);
604 (void) sprintf(get_line(0, 0), "Code = %d",
606 (void) sprintf(get_line(0, 0), "Checksum = %x",
607 ntohs(icmp6
->icmp6_cksum
));
609 switch (icmp6
->icmp6_type
) {
610 case ICMP6_DST_UNREACH
:
611 if (ilen
> ICMP6_MINLEN
+ IPV6_HDR_LEN
) {
613 (void) sprintf(get_line(0, 0),
614 "[ subject header follows ]");
616 prot_nest_prefix
= "ICMPv6:";
617 (void) interpret_ipv6(flags
, (ip6_t
*)&icmp6
[1],
618 ICMP6_MINLEN
+ IPV6_HDR_LEN
);
619 prot_nest_prefix
= "";
622 case ICMP6_PACKET_TOO_BIG
:
624 (void) sprintf(get_line(0, 0),
625 " Packet too big MTU = %d",
626 ntohl(icmp6
->icmp6_mtu
));
630 nd_redirect_t
*rd
= (nd_redirect_t
*)icmp6
;
632 (void) sprintf(get_line(0, 0), "Target address= %s",
633 inet_ntop(AF_INET6
, (char *)&rd
->nd_rd_target
,
634 addrstr
, INET6_ADDRSTRLEN
));
636 (void) sprintf(get_line(0, 0),
637 "Destination address= %s",
638 inet_ntop(AF_INET6
, (char *)&rd
->nd_rd_dst
,
639 addrstr
, INET6_ADDRSTRLEN
));
641 interpret_options((char *)icmp6
+ sizeof (*rd
),
642 ilen
- sizeof (*rd
));
645 case ND_NEIGHBOR_SOLICIT
: {
646 struct nd_neighbor_solicit
*ns
;
647 if (ilen
< sizeof (*ns
))
649 ns
= (struct nd_neighbor_solicit
*)icmp6
;
650 (void) sprintf(get_line(0, 0), "Target node = %s, %s",
651 inet_ntop(AF_INET6
, (char *)&ns
->nd_ns_target
,
652 addrstr
, INET6_ADDRSTRLEN
),
653 addrtoname(AF_INET6
, &ns
->nd_ns_target
));
655 interpret_options((char *)icmp6
+ sizeof (*ns
),
656 ilen
- sizeof (*ns
));
660 case ND_NEIGHBOR_ADVERT
: {
661 struct nd_neighbor_advert
*na
;
663 if (ilen
< sizeof (*na
))
665 na
= (struct nd_neighbor_advert
*)icmp6
;
666 (void) sprintf(get_line(0, 0), "Target node = %s, %s",
667 inet_ntop(AF_INET6
, (char *)&na
->nd_na_target
,
668 addrstr
, INET6_ADDRSTRLEN
),
669 addrtoname(AF_INET6
, &na
->nd_na_target
));
670 (void) sprintf(get_line(0, 0),
671 "Router flag: %s, Solicited flag: %s, "
673 na
->nd_na_flags_reserved
& ND_NA_FLAG_ROUTER
?
675 na
->nd_na_flags_reserved
& ND_NA_FLAG_SOLICITED
?
677 na
->nd_na_flags_reserved
& ND_NA_FLAG_OVERRIDE
?
681 interpret_options((char *)icmp6
+ sizeof (*na
),
682 ilen
- sizeof (*na
));
686 case ND_ROUTER_SOLICIT
: {
687 if (ilen
< sizeof (struct nd_router_solicit
))
690 (char *)icmp6
+ sizeof (struct nd_router_solicit
),
691 ilen
- sizeof (struct nd_router_solicit
));
695 case ND_ROUTER_ADVERT
: {
696 struct nd_router_advert
*ra
;
698 if (ilen
< sizeof (*ra
))
700 ra
= (struct nd_router_advert
*)icmp6
;
701 (void) sprintf(get_line(0, 0),
702 "Max hops= %d, Router lifetime= %d",
703 ra
->nd_ra_curhoplimit
,
704 ntohs(ra
->nd_ra_router_lifetime
));
706 (void) sprintf(get_line(0, 0),
707 "Managed addr conf flag: %s, Other conf flag: %s",
708 ra
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
?
710 ra
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
?
713 (void) sprintf(get_line(0, 0),
714 "Reachable time: %u, Reachable retrans time %u",
715 ntohl(ra
->nd_ra_reachable
),
716 ntohl(ra
->nd_ra_retransmit
));
719 interpret_options((char *)icmp6
+ sizeof (*ra
),
720 ilen
- sizeof (*ra
));
723 case ICMP6_PARAM_PROB
:
724 if (ilen
< sizeof (*icmp6
))
726 (void) sprintf(get_line(0, 0), "Ptr = %u",
727 ntohl(icmp6
->icmp6_pptr
));
731 case MLD_LISTENER_QUERY
: {
732 struct mld_hdr
*mldg
= (struct mld_hdr
*)icmp6
;
734 if (ilen
< MLD_MINLEN
)
737 if (ilen
>= MLD_V2_QUERY_MINLEN
) {
738 interpret_mldv2qry(icmp6
, ilen
);
740 (void) snprintf(get_line(0, 0),
742 "Multicast address= %s",
743 inet_ntop(AF_INET6
, mldg
->mld_addr
.s6_addr
,
744 addrstr
, INET6_ADDRSTRLEN
));
750 case MLD_LISTENER_REPORT
:
751 case MLD_LISTENER_REDUCTION
: {
752 struct mld_hdr
*mldg
;
754 if (ilen
< sizeof (*mldg
))
756 mldg
= (struct mld_hdr
*)icmp6
;
757 (void) snprintf(get_line(0, 0), get_line_remain(),
758 "Multicast address= %s", inet_ntop(AF_INET6
,
759 mldg
->mld_addr
.s6_addr
, addrstr
, INET6_ADDRSTRLEN
));
764 case MLD_V2_LISTENER_REPORT
: {
765 interpret_mldv2rpt(icmp6
, ilen
);
777 interpret_options(optc
, ilen
)
781 #define PREFIX_OPTION_LENGTH 4
782 #define MTU_OPTION_LENGTH 1
784 #define PREFIX_INFINITY 0xffffffffUL
786 struct nd_opt_hdr
*opt
;
788 for (; ilen
>= sizeof (*opt
); ) {
789 opt
= (struct nd_opt_hdr
*)optc
;
790 if (opt
->nd_opt_len
== 0)
792 switch (opt
->nd_opt_type
) {
793 case ND_OPT_SOURCE_LINKADDR
:
794 case ND_OPT_TARGET_LINKADDR
:
796 struct nd_opt_lla
*lopt
;
797 char *buf
, chbuf
[128];
801 if (ilen
< (int)opt
->nd_opt_len
* 8)
806 lopt
= (struct nd_opt_lla
*)opt
;
807 if (lopt
->nd_opt_lla_type
== ND_OPT_SOURCE_LINKADDR
) {
808 (void) sprintf(get_line(0, 0),
809 "+++ ICMPv6 Source LL Addr option +++");
811 (void) sprintf(get_line(0, 0),
812 "+++ ICMPv6 Target LL Addr option +++");
816 * The option length is in 8 octet units, and
817 * includes the first two bytes (the type and
818 * lenght fields) of the option.
820 addr_len
= lopt
->nd_opt_lla_len
* 8 - 2;
821 for (i
= 0; i
< addr_len
; i
++) {
822 snprintf(buf
, sizeof (chbuf
) - (buf
- chbuf
),
823 "%x:", lopt
->nd_opt_lla_hdw_addr
[i
]);
825 if (buf
>= &chbuf
[sizeof (chbuf
)]) {
827 chbuf
[sizeof (chbuf
) -
828 strlen("<Too Long>)")] = '\0';
829 (void) strlcat(chbuf
, "<Too Long>",
835 *(buf
- 1) = '\0'; /* Erase last colon */
836 (void) sprintf(get_line(0, 0),
837 "Link Layer address: %s", chbuf
);
842 struct nd_opt_mtu
*mopt
;
843 if (opt
->nd_opt_len
!= MTU_OPTION_LENGTH
||
844 ilen
< sizeof (struct nd_opt_mtu
))
846 (void) sprintf(get_line(0, 0),
847 "+++ ICMPv6 MTU option +++");
848 mopt
= (struct nd_opt_mtu
*)opt
;
849 (void) sprintf(get_line(0, 0),
850 "MTU = %u ", ntohl(mopt
->nd_opt_mtu_mtu
));
854 case ND_OPT_PREFIX_INFORMATION
: {
855 struct nd_opt_prefix_info
*popt
;
857 char preferredstr
[30];
858 char prefixstr
[INET6_ADDRSTRLEN
];
860 if (opt
->nd_opt_len
!= PREFIX_OPTION_LENGTH
||
861 ilen
< sizeof (struct nd_opt_prefix_info
))
863 popt
= (struct nd_opt_prefix_info
*)opt
;
864 (void) sprintf(get_line(0, 0),
865 "+++ ICMPv6 Prefix option +++");
866 (void) sprintf(get_line(0, 0),
867 "Prefix length = %d ", popt
->nd_opt_pi_prefix_len
);
868 (void) sprintf(get_line(0, 0),
869 "Onlink flag: %s, Autonomous addr conf flag: %s",
870 popt
->nd_opt_pi_flags_reserved
&
871 ND_OPT_PI_FLAG_ONLINK
? "SET" : "NOT SET",
872 popt
->nd_opt_pi_flags_reserved
&
873 ND_OPT_PI_FLAG_AUTO
? "SET" : "NOT SET");
875 if (ntohl(popt
->nd_opt_pi_valid_time
) ==
877 sprintf(validstr
, "INFINITY");
879 sprintf(validstr
, "%lu",
880 ntohl(popt
->nd_opt_pi_valid_time
));
882 if (ntohl(popt
->nd_opt_pi_preferred_time
) ==
884 sprintf(preferredstr
, "INFINITY");
886 sprintf(preferredstr
, "%lu",
887 ntohl(popt
->nd_opt_pi_preferred_time
));
889 (void) sprintf(get_line(0, 0),
890 "Valid Lifetime %s, Preferred Lifetime %s",
891 validstr
, preferredstr
);
892 (void) sprintf(get_line(0, 0), "Prefix %s",
894 (char *)&popt
->nd_opt_pi_prefix
, prefixstr
,
901 optc
+= opt
->nd_opt_len
* 8;
902 ilen
-= opt
->nd_opt_len
* 8;
907 interpret_mldv2qry(icmp6_t
*icmp6
, int ilen
)
913 char addrstr
[INET6_ADDRSTRLEN
];
915 if (ilen
< sizeof (*qry
)) {
916 (void) snprintf(get_line(0, 0), get_line_remain(),
917 "Malformed MLD Query");
920 qry
= (mld2q_t
*)icmp6
;
921 rem
-= sizeof (*qry
);
922 srccnt
= ntohs(qry
->mld2q_numsrc
);
923 (void) snprintf(get_line(0, 0), get_line_remain(),
924 "Multicast address= %s", inet_ntop(AF_INET6
,
925 &qry
->mld2q_addr
.s6_addr
, addrstr
, INET6_ADDRSTRLEN
));
926 (void) snprintf(get_line(0, 0), get_line_remain(),
927 "%d Source Address%s:", srccnt
, (srccnt
== 1) ? "" : "es");
929 src
= (in6_addr_t
*)&qry
[1];
930 while (srccnt
> 0 && rem
>= sizeof (*src
)) {
931 rem
-= sizeof (*src
);
933 (void) snprintf(get_line(0, 0), get_line_remain(), " %s",
934 inet_ntop(AF_INET6
, src
, addrstr
, INET6_ADDRSTRLEN
));
941 #define MAX_MLDV2_REPORT_TYPE 6
943 const char *mldv2rpt_types
[] = {
954 interpret_mldv2rpt(icmp6_t
*icmp6
, int ilen
)
959 int rem
= ilen
, auxlen
;
960 uint16_t marcnt
, srccnt
;
961 char addrstr
[INET6_ADDRSTRLEN
];
963 if (ilen
< sizeof (*rpt
)) {
964 (void) snprintf(get_line(0, 0), get_line_remain(),
965 "Malformed MLDv2 Report");
968 rpt
= (mld2r_t
*)icmp6
;
969 mar
= (mld2mar_t
*)&rpt
[1];
970 marcnt
= ntohs(rpt
->mld2r_nummar
);
971 (void) snprintf(get_line(0, 0), get_line_remain(),
972 "%d Multicast Address Record%s:", marcnt
, (marcnt
== 1) ? "" : "s");
973 rem
-= sizeof (*rpt
);
974 while (marcnt
> 0 && rem
>= sizeof (*mar
)) {
975 rem
-= sizeof (*mar
);
977 (void) snprintf(get_line(0, 0), get_line_remain(),
978 "Multicast address= %s type = %s", inet_ntop(AF_INET6
,
979 &mar
->mld2mar_group
.s6_addr
, addrstr
, INET6_ADDRSTRLEN
),
980 (mar
->mld2mar_type
> MAX_MLDV2_REPORT_TYPE
) ?
981 "<unknown>" : mldv2rpt_types
[mar
->mld2mar_type
]);
982 srccnt
= ntohs(mar
->mld2mar_numsrc
);
983 (void) snprintf(get_line(0, 0), get_line_remain(),
984 "%d Source Address%s:", srccnt
, (srccnt
== 1) ? "" : "es");
986 src
= (in6_addr_t
*)&mar
[1];
987 while (srccnt
> 0 && rem
>= sizeof (*src
)) {
988 rem
-= sizeof (*src
);
990 (void) snprintf(get_line(0, 0), get_line_remain(),
991 " %s", inet_ntop(AF_INET6
, src
, addrstr
,
999 auxlen
= mar
->mld2mar_auxlen
* 4;
1001 mar
= (mld2mar_t
*)((uint8_t *)src
+ auxlen
);