]> The Tcpdump Group git mirrors - tcpdump/blob - print-icmp6.c
remove extra prototype (now in interface.h)
[tcpdump] / print-icmp6.c
1 /*
2 * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifndef lint
23 static const char rcsid[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.16 2000-06-03 16:40:35 itojun Exp $";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #ifdef INET6
32
33 #include <ctype.h>
34
35 #include <sys/param.h>
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39
40 #include <net/if.h>
41
42 #include <netinet/in.h>
43 #include <netinet/if_ether.h>
44 #include <netinet/in_systm.h>
45 #include <netinet/ip.h>
46 #include <netinet/ip_icmp.h>
47 #include <netinet/ip_var.h>
48 #include <netinet/udp.h>
49 #include <netinet/udp_var.h>
50 #include <netinet/tcp.h>
51
52 #include <arpa/inet.h>
53
54 #include <stdio.h>
55
56 #include <netinet/ip6.h>
57 #include <netinet/icmp6.h>
58
59 #include "interface.h"
60 #include "addrtoname.h"
61
62 void icmp6_opt_print(const u_char *, int);
63 void mld6_print(const u_char *);
64 #ifdef HAVE_STRUCT_ICMP6_NODEINFO
65 static void dnsname_print(const u_char *, const u_char *);
66 void icmp6_nodeinfo_print(int, const u_char *, const u_char *);
67 #endif
68
69 #ifndef abs
70 #define abs(a) ((0 < (a)) ? (a) : -(a))
71 #endif
72
73 #ifndef HAVE_STRUCT_ICMP6_NODEINFO
74 struct icmp6_nodeinfo {
75 struct icmp6_hdr icmp6_ni_hdr;
76 u_int8_t icmp6_ni_nonce[8];
77 /* could be followed by reply data */
78 };
79
80 #define ni_type icmp6_ni_hdr.icmp6_type
81 #define ni_code icmp6_ni_hdr.icmp6_code
82 #define ni_cksum icmp6_ni_hdr.icmp6_cksum
83 #define ni_qtype icmp6_ni_hdr.icmp6_data16[0]
84 #define ni_flags icmp6_ni_hdr.icmp6_data16[1]
85 #endif
86
87 #ifndef ICMP6_NI_SUCCESS
88 #define ICMP6_NI_SUCESS 0 /* node information successful reply */
89 #define ICMP6_NI_REFUSED 1 /* node information request is refused */
90 #define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */
91 #endif
92
93 #ifdef NI_QTYPE_NOOP
94 #define NI_QTYPE_NOOP 0 /* NOOP */
95 #define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes */
96 #define NI_QTYPE_FQDN 2 /* FQDN */
97 #define NI_QTYPE_NODEADDR 3 /* Node Addresses. XXX: spec says 2, but it may be a typo... */
98 #endif
99
100 #ifndef ICMP6_NI_SUBJ_IPV6
101 #define ICMP6_NI_SUBJ_IPV6 0 /* Query Subject is an IPv6 address */
102 #define ICMP6_NI_SUBJ_FQDN 1 /* Query Subject is a Domain name */
103 #define ICMP6_NI_SUBJ_IPV4 2 /* Query Subject is an IPv4 address */
104 #endif
105
106 void
107 icmp6_print(register const u_char *bp, register const u_char *bp2)
108 {
109 const struct icmp6_hdr *dp;
110 register const struct ip6_hdr *ip;
111 register const char *str;
112 register const struct ip6_hdr *oip;
113 register const struct udphdr *ouh;
114 register int hlen, dport;
115 register const u_char *ep;
116 char buf[256];
117 int icmp6len;
118
119 #if 0
120 #define TCHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) goto trunc
121 #endif
122
123 dp = (struct icmp6_hdr *)bp;
124 ip = (struct ip6_hdr *)bp2;
125 oip = (struct ip6_hdr *)(dp + 1);
126 str = buf;
127 /* 'ep' points to the end of avaible data. */
128 ep = snapend;
129 if (ip->ip6_plen)
130 icmp6len = (ntohs(ip->ip6_plen) + sizeof(struct ip6_hdr) -
131 (bp - bp2));
132 else /* XXX: jumbo payload case... */
133 icmp6len = snapend - bp;
134
135 #if 0
136 (void)printf("%s > %s: ",
137 ip6addr_string(&ip->ip6_src),
138 ip6addr_string(&ip->ip6_dst));
139 #endif
140
141 TCHECK(dp->icmp6_code);
142 switch (dp->icmp6_type) {
143 case ICMP6_DST_UNREACH:
144 TCHECK(oip->ip6_dst);
145 switch (dp->icmp6_code) {
146 case ICMP6_DST_UNREACH_NOROUTE:
147 printf("icmp6: %s unreachable route",
148 ip6addr_string(&oip->ip6_dst));
149 break;
150 case ICMP6_DST_UNREACH_ADMIN:
151 printf("icmp6: %s unreachable prohibited",
152 ip6addr_string(&oip->ip6_dst));
153 break;
154 #ifdef ICMP6_DST_UNREACH_BEYONDSCOPE
155 case ICMP6_DST_UNREACH_BEYONDSCOPE:
156 #else
157 case ICMP6_DST_UNREACH_NOTNEIGHBOR:
158 #endif
159 printf("icmp6: %s beyond scope of source address %s",
160 ip6addr_string(&oip->ip6_dst),
161 ip6addr_string(&oip->ip6_src));
162 break;
163 case ICMP6_DST_UNREACH_ADDR:
164 printf("icmp6: %s unreachable address",
165 ip6addr_string(&oip->ip6_dst));
166 break;
167 case ICMP6_DST_UNREACH_NOPORT:
168 TCHECK(oip->ip6_nxt);
169 hlen = sizeof(struct ip6_hdr);
170 ouh = (struct udphdr *)(((u_char *)oip) + hlen);
171 dport = ntohs(ouh->uh_dport);
172 switch (oip->ip6_nxt) {
173 case IPPROTO_TCP:
174 printf("icmp6: %s tcp port %s unreachable",
175 ip6addr_string(&oip->ip6_dst),
176 tcpport_string(dport));
177 break;
178 case IPPROTO_UDP:
179 printf("icmp6: %s udp port %s unreachable",
180 ip6addr_string(&oip->ip6_dst),
181 udpport_string(dport));
182 break;
183 default:
184 printf("icmp6: %s protocol %d port %d unreachable",
185 ip6addr_string(&oip->ip6_dst),
186 oip->ip6_nxt, dport);
187 break;
188 }
189 break;
190 default:
191 printf("icmp6: %s unreachable code-#%d",
192 ip6addr_string(&oip->ip6_dst),
193 dp->icmp6_code);
194 break;
195 }
196 break;
197 case ICMP6_PACKET_TOO_BIG:
198 TCHECK(dp->icmp6_mtu);
199 printf("icmp6: too big %u\n", (u_int32_t)ntohl(dp->icmp6_mtu));
200 break;
201 case ICMP6_TIME_EXCEEDED:
202 TCHECK(oip->ip6_dst);
203 switch (dp->icmp6_code) {
204 case ICMP6_TIME_EXCEED_TRANSIT:
205 printf("icmp6: time exceeded in-transit for %s",
206 ip6addr_string(&oip->ip6_dst));
207 break;
208 case ICMP6_TIME_EXCEED_REASSEMBLY:
209 printf("icmp6: ip6 reassembly time exceeded");
210 break;
211 default:
212 printf("icmp6: time exceeded code-#%d",
213 dp->icmp6_code);
214 break;
215 }
216 break;
217 case ICMP6_PARAM_PROB:
218 TCHECK(oip->ip6_dst);
219 switch (dp->icmp6_code) {
220 case ICMP6_PARAMPROB_HEADER:
221 printf("icmp6: parameter problem errorneous - octet %u\n",
222 (u_int32_t)ntohl(dp->icmp6_pptr));
223 break;
224 case ICMP6_PARAMPROB_NEXTHEADER:
225 printf("icmp6: parameter problem next header - octet %u\n",
226 (u_int32_t)ntohl(dp->icmp6_pptr));
227 break;
228 case ICMP6_PARAMPROB_OPTION:
229 printf("icmp6: parameter problem option - octet %u\n",
230 (u_int32_t)ntohl(dp->icmp6_pptr));
231 break;
232 default:
233 printf("icmp6: parameter problem code-#%d",
234 dp->icmp6_code);
235 break;
236 }
237 break;
238 case ICMP6_ECHO_REQUEST:
239 printf("icmp6: echo request");
240 break;
241 case ICMP6_ECHO_REPLY:
242 printf("icmp6: echo reply");
243 break;
244 case ICMP6_MEMBERSHIP_QUERY:
245 printf("icmp6: multicast listener query ");
246 mld6_print((const u_char *)dp);
247 break;
248 case ICMP6_MEMBERSHIP_REPORT:
249 printf("icmp6: multicast listener report ");
250 mld6_print((const u_char *)dp);
251 break;
252 case ICMP6_MEMBERSHIP_REDUCTION:
253 printf("icmp6: multicast listener done ");
254 mld6_print((const u_char *)dp);
255 break;
256 case ND_ROUTER_SOLICIT:
257 printf("icmp6: router solicitation ");
258 if (vflag) {
259 #define RTSOLLEN 8
260 icmp6_opt_print((const u_char *)dp + RTSOLLEN,
261 icmp6len - RTSOLLEN);
262 }
263 break;
264 case ND_ROUTER_ADVERT:
265 printf("icmp6: router advertisement");
266 if (vflag) {
267 struct nd_router_advert *p;
268
269 p = (struct nd_router_advert *)dp;
270 TCHECK(p->nd_ra_retransmit);
271 printf("(chlim=%d, ", (int)p->nd_ra_curhoplimit);
272 if (p->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
273 printf("M");
274 if (p->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
275 printf("O");
276 #ifndef ND_RA_FLAG_HA
277 #define ND_RA_FLAG_HA 0x20
278 #endif
279 if (p->nd_ra_flags_reserved & ND_RA_FLAG_HA)
280 printf("H");
281 if (p->nd_ra_flags_reserved != 0)
282 printf(" ");
283 printf("router_ltime=%d, ", ntohs(p->nd_ra_router_lifetime));
284 printf("reachable_time=%u, ",
285 (u_int32_t)ntohl(p->nd_ra_reachable));
286 printf("retrans_time=%u)",
287 (u_int32_t)ntohl(p->nd_ra_retransmit));
288 #define RTADVLEN 16
289 icmp6_opt_print((const u_char *)dp + RTADVLEN,
290 icmp6len - RTADVLEN);
291 }
292 break;
293 case ND_NEIGHBOR_SOLICIT:
294 {
295 struct nd_neighbor_solicit *p;
296 p = (struct nd_neighbor_solicit *)dp;
297 TCHECK(p->nd_ns_target);
298 printf("icmp6: neighbor sol: who has %s",
299 ip6addr_string(&p->nd_ns_target));
300 if (vflag) {
301 #define NDSOLLEN 24
302 icmp6_opt_print((const u_char *)dp + NDSOLLEN,
303 icmp6len - NDSOLLEN);
304 }
305 }
306 break;
307 case ND_NEIGHBOR_ADVERT:
308 {
309 struct nd_neighbor_advert *p;
310
311 p = (struct nd_neighbor_advert *)dp;
312 TCHECK(p->nd_na_target);
313 printf("icmp6: neighbor adv: tgt is %s",
314 ip6addr_string(&p->nd_na_target));
315 if (vflag) {
316 #define ND_NA_FLAG_ALL \
317 (ND_NA_FLAG_ROUTER|ND_NA_FLAG_SOLICITED|ND_NA_FLAG_OVERRIDE)
318 /* we don't need ntohl() here. see advanced-api-04. */
319 if (p->nd_na_flags_reserved & ND_NA_FLAG_ALL) {
320 #undef ND_NA_FLAG_ALL
321 u_int32_t flags;
322
323 flags = p->nd_na_flags_reserved;
324 printf("(");
325 if (flags & ND_NA_FLAG_ROUTER)
326 printf("R");
327 if (flags & ND_NA_FLAG_SOLICITED)
328 printf("S");
329 if (flags & ND_NA_FLAG_OVERRIDE)
330 printf("O");
331 printf(")");
332 }
333 #define NDADVLEN 24
334 icmp6_opt_print((const u_char *)dp + NDADVLEN,
335 icmp6len - NDADVLEN);
336 #undef NDADVLEN
337 }
338 }
339 break;
340 case ND_REDIRECT:
341 #define RDR(i) ((struct nd_redirect *)(i))
342 TCHECK(RDR(dp)->nd_rd_dst);
343 printf("icmp6: redirect %s",
344 getname6((const u_char *)&RDR(dp)->nd_rd_dst));
345 printf(" to %s",
346 getname6((const u_char*)&RDR(dp)->nd_rd_target));
347 #define REDIRECTLEN 40
348 if (vflag) {
349 icmp6_opt_print((const u_char *)dp + REDIRECTLEN,
350 icmp6len - REDIRECTLEN);
351 }
352 break;
353 #undef REDIRECTLEN
354 #undef RDR
355 #ifndef ICMP6_ROUTER_RENUMBERING
356 #define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */
357 #endif
358 case ICMP6_ROUTER_RENUMBERING:
359 switch (dp->icmp6_code) {
360 #ifndef ICMP6_ROUTER_RENUMBERING_COMMAND
361 #define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */
362 #endif
363 case ICMP6_ROUTER_RENUMBERING_COMMAND:
364 printf("icmp6: router renum command");
365 break;
366 #ifndef ICMP6_ROUTER_RENUMBERING_RESULT
367 #define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */
368 #endif
369 case ICMP6_ROUTER_RENUMBERING_RESULT:
370 printf("icmp6: router renum result");
371 break;
372 default:
373 printf("icmp6: router renum code-#%d", dp->icmp6_code);
374 break;
375 }
376 break;
377 #ifdef HAVE_STRUCT_ICMP6_NODEINFO
378 #ifndef ICMP6_NI_QUERY
379 #define ICMP6_NI_QUERY 139
380 #endif
381 case ICMP6_NI_QUERY:
382 icmp6_nodeinfo_print(icmp6len, bp, ep);
383 break;
384 #ifndef ICMP6_NI_REPLY
385 #define ICMP6_NI_REPLY 140
386 #endif
387 case ICMP6_NI_REPLY:
388 icmp6_nodeinfo_print(icmp6len, bp, ep);
389 break;
390 #endif
391 default:
392 printf("icmp6: type-#%d", dp->icmp6_type);
393 break;
394 }
395 return;
396 trunc:
397 fputs("[|icmp6]", stdout);
398 #if 0
399 #undef TCHECK
400 #endif
401 }
402
403 void
404 icmp6_opt_print(register const u_char *bp, int resid)
405 {
406 register const struct nd_opt_hdr *op;
407 register const struct nd_opt_hdr *opl; /* why there's no struct? */
408 register const struct nd_opt_prefix_info *opp;
409 register const struct icmp6_opts_redirect *opr;
410 register const struct nd_opt_mtu *opm;
411 register const u_char *ep;
412 int opts_len;
413 #if 0
414 register const struct ip6_hdr *ip;
415 register const char *str;
416 register const struct ip6_hdr *oip;
417 register const struct udphdr *ouh;
418 register int hlen, dport;
419 char buf[256];
420 #endif
421
422 #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return
423
424 op = (struct nd_opt_hdr *)bp;
425 #if 0
426 ip = (struct ip6_hdr *)bp2;
427 oip = &dp->icmp6_ip6;
428 str = buf;
429 #endif
430 /* 'ep' points to the end of avaible data. */
431 ep = snapend;
432
433 ECHECK(op->nd_opt_len);
434 if (resid <= 0)
435 return;
436 switch (op->nd_opt_type) {
437 case ND_OPT_SOURCE_LINKADDR:
438 opl = (struct nd_opt_hdr *)op;
439 #if 1
440 if ((u_char *)opl + (opl->nd_opt_len << 3) > ep)
441 goto trunc;
442 #else
443 TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1);
444 #endif
445 printf("(src lladdr: %s", /*)*/
446 etheraddr_string((u_char *)(opl + 1)));
447 if (opl->nd_opt_len != 1)
448 printf("!");
449 /*(*/
450 printf(")");
451 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3),
452 resid - (op->nd_opt_len << 3));
453 break;
454 case ND_OPT_TARGET_LINKADDR:
455 opl = (struct nd_opt_hdr *)op;
456 #if 1
457 if ((u_char *)opl + (opl->nd_opt_len << 3) > ep)
458 goto trunc;
459 #else
460 TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1);
461 #endif
462 printf("(tgt lladdr: %s", /*)*/
463 etheraddr_string((u_char *)(opl + 1)));
464 if (opl->nd_opt_len != 1)
465 printf("!");
466 /*(*/
467 printf(")");
468 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3),
469 resid - (op->nd_opt_len << 3));
470 break;
471 case ND_OPT_PREFIX_INFORMATION:
472 opp = (struct nd_opt_prefix_info *)op;
473 TCHECK(opp->nd_opt_pi_prefix);
474 printf("(prefix info: "); /*)*/
475 if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK)
476 printf("L");
477 if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO)
478 printf("A");
479 if (opp->nd_opt_pi_flags_reserved)
480 printf(" ");
481 printf("valid_ltime=");
482 if ((u_int32_t)ntohl(opp->nd_opt_pi_valid_time) == ~0U)
483 printf("infinity");
484 else {
485 printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_valid_time));
486 }
487 printf(", ");
488 printf("preffered_ltime=");
489 if ((u_int32_t)ntohl(opp->nd_opt_pi_preferred_time) == ~0U)
490 printf("infinity");
491 else {
492 printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_preferred_time));
493 }
494 printf(", ");
495 printf("prefix=%s/%d", ip6addr_string(&opp->nd_opt_pi_prefix),
496 opp->nd_opt_pi_prefix_len);
497 if (opp->nd_opt_pi_len != 4)
498 printf("!");
499 /*(*/
500 printf(")");
501 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3),
502 resid - (op->nd_opt_len << 3));
503 break;
504 case ND_OPT_REDIRECTED_HEADER:
505 opr = (struct icmp6_opts_redirect *)op;
506 printf("(redirect)");
507 /* xxx */
508 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3),
509 resid - (op->nd_opt_len << 3));
510 break;
511 case ND_OPT_MTU:
512 opm = (struct nd_opt_mtu *)op;
513 TCHECK(opm->nd_opt_mtu_mtu);
514 printf("(mtu: "); /*)*/
515 printf("mtu=%u", (u_int32_t)ntohl(opm->nd_opt_mtu_mtu));
516 if (opm->nd_opt_mtu_len != 1)
517 printf("!");
518 printf(")");
519 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3),
520 resid - (op->nd_opt_len << 3));
521 break;
522 default:
523 opts_len = op->nd_opt_len;
524 printf("(unknwon opt_type=%d, opt_len=%d)",
525 op->nd_opt_type, opts_len);
526 if (opts_len == 0)
527 opts_len = 1; /* XXX */
528 icmp6_opt_print((const u_char *)op + (opts_len << 3),
529 resid - (opts_len << 3));
530 break;
531 }
532 return;
533 trunc:
534 fputs("[ndp opt]", stdout);
535 return;
536 #undef ECHECK
537 }
538
539 #if defined(HAVE_STRUCT_MLD6_HDR)
540 void
541 mld6_print(register const u_char *bp)
542 {
543 register struct mld6_hdr *mp = (struct mld6_hdr *)bp;
544 register const u_char *ep;
545
546 /* 'ep' points to the end of avaible data. */
547 ep = snapend;
548
549 if ((u_char *)mp + sizeof(*mp) > ep)
550 return;
551
552 printf("max resp delay: %d ", ntohs(mp->mld6_maxdelay));
553 printf("addr: %s", ip6addr_string(&mp->mld6_addr));
554 }
555
556 #elif defined(HAVE_STRUCT_ICMP6_MLD)
557
558 void
559 mld6_print(register const u_char *bp)
560 {
561 register struct icmp6_mld *mp = (struct icmp6_mld *)bp;
562 register const u_char *ep;
563
564 /* 'ep' points to the end of avaible data. */
565 ep = snapend;
566
567 if ((u_char *)mp + sizeof(*mp) > ep)
568 return;
569
570 printf("max resp delay: %d ", ntohs(mp->icmp6m_hdr.icmp6_maxdelay));
571 printf("addr: %s", ip6addr_string(&mp->icmp6m_group));
572 }
573
574 #else
575
576 #error unknown mld6 struct
577
578 #endif
579
580 #ifdef HAVE_STRUCT_ICMP6_NODEINFO
581 static void
582 dnsname_print(const u_char *cp, const u_char *ep)
583 {
584 int i;
585
586 /* DNS name decoding - no decompression */
587 printf(", \"");
588 while (cp < ep) {
589 i = *cp++;
590 if (i) {
591 if (i > ep - cp) {
592 printf("???");
593 break;
594 }
595 while (i-- && cp < ep) {
596 safeputchar(*cp);
597 cp++;
598 }
599 if (cp + 1 < ep && *cp)
600 printf(".");
601 } else {
602 if (cp == ep) {
603 /* FQDN */
604 printf(".");
605 } else if (cp + 1 == ep && *cp == '\0') {
606 /* truncated */
607 } else {
608 /* invalid */
609 printf("???");
610 }
611 break;
612 }
613 }
614 printf("\"");
615 }
616
617 void
618 icmp6_nodeinfo_print(int icmp6len, const u_char *bp, const u_char *ep)
619 {
620 struct icmp6_nodeinfo *ni6;
621 struct icmp6_hdr *dp;
622 const u_char *cp;
623 int siz, i;
624
625 dp = (struct icmp6_hdr *)bp;
626 ni6 = (struct icmp6_nodeinfo *)bp;
627 siz = ep - bp;
628
629 switch (ni6->ni_type) {
630 case ICMP6_NI_QUERY:
631 if (siz == sizeof(*dp) + 4) {
632 /* KAME who-are-you */
633 printf("icmp6: who-are-you request");
634 break;
635 }
636 printf("icmp6: node information query");
637
638 TCHECK2(*dp, sizeof(*ni6));
639 ni6 = (struct icmp6_nodeinfo *)dp;
640 printf(" ("); /*)*/
641 switch (ntohs(ni6->ni_qtype)) {
642 case NI_QTYPE_NOOP:
643 printf("noop");
644 break;
645 case NI_QTYPE_SUPTYPES:
646 printf("supported qtypes");
647 i = ntohs(ni6->ni_flags);
648 if (i)
649 printf(" [%s]", (i & 0x01) ? "C" : "");
650 break;
651 break;
652 case NI_QTYPE_FQDN:
653 printf("DNS name");
654 break;
655 case NI_QTYPE_NODEADDR:
656 printf("node addresses");
657 i = ni6->ni_flags;
658 if (!i)
659 break;
660 /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */
661 printf(" [%s%s%s%s%s%s]",
662 (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "",
663 (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "",
664 (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "",
665 (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "",
666 (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "",
667 (i & NI_NODEADDR_FLAG_ALL) ? "A" : "");
668 break;
669 default:
670 printf("unknown");
671 break;
672 }
673
674 if (ni6->ni_qtype == NI_QTYPE_NOOP ||
675 ni6->ni_qtype == NI_QTYPE_SUPTYPES) {
676 if (siz != sizeof(*ni6))
677 if (vflag)
678 printf(", invalid len");
679 /*(*/
680 printf(")");
681 break;
682 }
683
684
685 /* XXX backward compat, icmp-name-lookup-03 */
686 if (siz == sizeof(*ni6)) {
687 printf(", 03 draft");
688 /*(*/
689 printf(")");
690 break;
691 }
692
693 switch (ni6->ni_code) {
694 case ICMP6_NI_SUBJ_IPV6:
695 if (!TTEST2(*dp,
696 sizeof(*ni6) + sizeof(struct in6_addr)))
697 break;
698 if (siz != sizeof(*ni6) + sizeof(struct in6_addr)) {
699 if (vflag)
700 printf(", invalid subject len");
701 break;
702 }
703 printf(", subject=%s",
704 getname6((const u_char *)(ni6 + 1)));
705 break;
706 case ICMP6_NI_SUBJ_FQDN:
707 printf(", subject=DNS name");
708 cp = (const u_char *)(ni6 + 1);
709 if (cp[0] == ep - cp - 1) {
710 /* icmp-name-lookup-03, pascal string */
711 if (vflag)
712 printf(", 03 draft");
713 cp++;
714 printf(", \"");
715 while (cp < ep) {
716 safeputchar(*cp);
717 cp++;
718 }
719 printf("\"");
720 } else
721 dnsname_print(cp, ep);
722 break;
723 case ICMP6_NI_SUBJ_IPV4:
724 if (!TTEST2(*dp, sizeof(*ni6) + sizeof(struct in_addr)))
725 break;
726 if (siz != sizeof(*ni6) + sizeof(struct in_addr)) {
727 if (vflag)
728 printf(", invalid subject len");
729 break;
730 }
731 printf(", subject=%s",
732 getname((const u_char *)(ni6 + 1)));
733 break;
734 default:
735 printf(", unknown subject");
736 break;
737 }
738
739 /*(*/
740 printf(")");
741 break;
742
743 case ICMP6_NI_REPLY:
744 if (icmp6len > siz) {
745 printf("[|icmp6: node information reply]");
746 break;
747 }
748
749 ni6 = (struct icmp6_nodeinfo *)dp;
750 printf("icmp6: node information query");
751 printf(" ("); /*)*/
752 switch (ni6->ni_code) {
753 case ICMP6_NI_SUCESS:
754 break;
755 case ICMP6_NI_REFUSED:
756 printf("refused");
757 if (siz != sizeof(*ni6))
758 if (vflag)
759 printf(", invalid length");
760 break;
761 case ICMP6_NI_UNKNOWN:
762 printf("unknown");
763 if (siz != sizeof(*ni6))
764 if (vflag)
765 printf(", invalid length");
766 break;
767 }
768
769 if (ni6->ni_code != ICMP6_NI_SUCESS) {
770 /*(*/
771 printf(")");
772 break;
773 }
774
775 switch (ntohs(ni6->ni_qtype)) {
776 case NI_QTYPE_NOOP:
777 printf("noop");
778 if (siz != sizeof(*ni6))
779 if (vflag)
780 printf(", invalid length");
781 break;
782 case NI_QTYPE_SUPTYPES:
783 printf("supported qtypes");
784 i = ntohs(ni6->ni_flags);
785 if (i)
786 printf(" [%s]", (i & 0x01) ? "C" : "");
787 break;
788 case NI_QTYPE_FQDN:
789 if (vflag)
790 printf("DNS name");
791 cp = (const u_char *)(ni6 + 1) + 4;
792 if (cp[0] == ep - cp - 1) {
793 /* icmp-name-lookup-03, pascal string */
794 if (vflag)
795 printf(", 03 draft");
796 cp++;
797 printf(", \"");
798 while (cp < ep) {
799 safeputchar(*cp);
800 cp++;
801 }
802 printf("\"");
803 } else
804 dnsname_print(cp, ep);
805 if ((ntohs(ni6->ni_flags) & 0x01) != 0)
806 printf(" [TTL=%u]", *(u_int32_t *)(ni6 + 1));
807 break;
808 case NI_QTYPE_NODEADDR:
809 printf("node addresses");
810 for (i = sizeof(*ni6);
811 i < siz;
812 i += sizeof(struct in6_addr)) {
813 printf(" %s", getname6(bp + i));
814 }
815 i = ni6->ni_flags;
816 if (!i)
817 break;
818 printf(" [%s%s%s%s%s%s%s]",
819 (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "",
820 (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "",
821 (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "",
822 (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "",
823 (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "",
824 (i & NI_NODEADDR_FLAG_ALL) ? "A" : "",
825 (i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : "");
826 break;
827 default:
828 printf("unknown");
829 break;
830 }
831
832 /*(*/
833 printf(")");
834 break;
835 }
836 return;
837
838 trunc:
839 fputs("[|icmp6]", stdout);
840 }
841 #endif
842
843 #endif /* INET6 */