trafgen: Add checksum helpers for TCP/UDP over IPv6
[netsniff-ng.git] / proto_icmpv6.c
blobb5eee920cbbcf0248bbc7d8c2a1d2b1d0903b228
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2012 Markus Amend <markus@netsniff-ng.org>, Deutsche Flugsicherung GmbH
4 * Subject to the GPL, version 2.
6 * ICMPv6 described in RFC4443, RFC2710, RFC4861, RFC2894,
7 * RFC4620, RFC3122, RFC3810, RFC3775, RFC3971, RFC4065
8 * RFC4286
9 * Look also for an good overview:
10 * http://www.iana.org/assignments/icmpv6-parameters
13 #include <inttypes.h>
14 #include <stdio.h>
15 #include <stdint.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <asm/byteorder.h>
20 #include "proto.h"
21 #include "protos.h"
22 #include "pkt_buff.h"
23 #include "built_in.h"
25 #define icmpv6_code_range_valid(code, sarr) ((size_t) (code) < array_size((sarr)))
27 struct icmpv6_general_hdr {
28 uint8_t h_type;
29 uint8_t h_code;
30 uint16_t h_chksum;
31 } __packed;
33 /* for type 0x01 and 0x03 */
34 struct icmpv6_type_1_3 {
35 uint32_t unused;
36 uint8_t invoking_pkt[0];
37 } __packed;
39 struct icmpv6_type_2 {
40 uint32_t MTU;
41 uint8_t invoking_pkt[0];
42 } __packed;
44 struct icmpv6_type_4 {
45 uint32_t pointer;
46 uint8_t invoking_pkt[0];
47 } __packed;
49 struct icmpv6_type_128_129 {
50 uint16_t id;
51 uint16_t sn;
52 uint8_t data[0];
53 } __packed;
55 /* MLDv1 msg */
56 struct icmpv6_type_130_131_132 {
57 uint16_t maxrespdel;
58 uint16_t res;
59 struct in6_addr ipv6_addr;
60 } __packed;
61 /* end MLDv1 msg */
63 struct icmpv6_type_130_mldv2 {
64 uint8_t resv_S_QRV;
65 uint8_t QQIC;
66 uint16_t nr_src;
67 struct in6_addr ipv6_addr[0];
68 } __packed;
70 /* Neighbor Discovery msg */
71 struct icmpv6_type_133_141_142 {
72 uint32_t res;
73 uint8_t ops[0];
74 } __packed;
76 struct icmpv6_type_134 {
77 uint8_t cur_hop_limit;
78 uint8_t m_o_res;
79 uint16_t router_lifetime;
80 uint32_t reachable_time;
81 uint32_t retrans_timer;
82 uint8_t ops[0];
83 } __packed;
85 struct icmpv6_type_135 {
86 uint32_t res;
87 struct in6_addr ipv6_addr;
88 uint8_t ops[0];
89 } __packed;
91 struct icmpv6_type_136 {
92 uint32_t r_s_o_res;
93 struct in6_addr ipv6_addr;
94 uint8_t ops[0];
95 } __packed;
97 struct icmpv6_type_137 {
98 uint32_t res;
99 struct in6_addr ipv6_targ_addr;
100 struct in6_addr ipv6_dest_addr;
101 uint8_t ops[0];
102 } __packed;
104 struct icmpv6_neighb_disc_ops_general {
105 uint8_t type;
106 uint8_t len;
107 uint8_t ops[0];
108 } __packed;
110 struct icmpv6_neighb_disc_ops_type_1_2 {
111 uint8_t link_lay_addr[0];
112 } __packed;
114 struct icmpv6_neighb_disc_ops_type_3 {
115 uint8_t prefix_len;
116 uint8_t l_a_res1;
117 uint32_t valid_lifetime;
118 uint32_t preferred_lifetime;
119 uint32_t res2;
120 struct in6_addr prefix;
121 } __packed;
123 struct icmpv6_neighb_disc_ops_type_4 {
124 uint16_t res1;
125 uint32_t res2;
126 uint8_t ip_hdr_data[0];
127 } __packed;
129 struct icmpv6_neighb_disc_ops_type_5 {
130 uint16_t res1;
131 uint32_t MTU;
132 } __packed;
134 struct icmpv6_neighb_disc_ops_type_9_10 {
135 uint16_t res1;
136 uint32_t res2;
137 uint8_t ip_hdr_data[0];
138 } __packed;
140 struct icmpv6_neighb_disc_ops_type_15 {
141 uint8_t name_type;
142 size_t pad_len;
143 char name[0];
144 uint8_t pad[0];
145 } __packed;
147 struct icmpv6_neighb_disc_ops_type_16 {
148 uint8_t cert_type;
149 uint8_t res;
150 uint8_t cert[0];
151 uint8_t pad[0];
152 } __packed;
154 struct icmpv6_neighb_disc_ops_type_17 {
155 uint8_t opt_code;
156 uint8_t prefix_len;
157 uint8_t data[0];
158 } __packed;
160 struct icmpv6_neighb_disc_ops_type_17_1 {
161 uint32_t res;
162 struct in6_addr ipv6_addr;
163 } __packed;
165 struct icmpv6_neighb_disc_ops_type_17_2 {
166 struct in6_addr ipv6_addr;
167 } __packed;
169 struct icmpv6_neighb_disc_ops_type_19 {
170 uint8_t opt_code;
171 uint8_t lla[0];
172 } __packed;
173 /* end Neighbor Discovery msg */
175 struct icmpv6_type_138 {
176 uint32_t seq_nr;
177 uint8_t seg_nr;
178 uint8_t flags;
179 uint16_t maxdelay;
180 uint32_t res;
181 } __packed;
183 /* Node Information Queries */
184 struct icmpv6_type_139_140 {
185 uint16_t qtype;
186 uint16_t flags;
187 uint64_t nonce;
188 uint8_t data[0];
189 } __packed;
190 /* end Node Information Queries */
192 /* MLDv2 report */
193 struct icmpv6_type_143 {
194 uint16_t res;
195 uint16_t nr_rec;
196 uint8_t addr_rec[0];
197 } __packed;
199 struct icmpv6_mldv2_addr_rec {
200 uint8_t rec_type;
201 uint8_t aux_data_len;
202 uint16_t nr_src;
203 struct in6_addr multic_addr;
204 struct in6_addr src_addr[0];
205 } __packed;
206 /* end MLDv2 report */
208 /* ICMP Mobility Support */
209 struct icmpv6_type_144_146 {
210 uint16_t id;
211 uint16_t res;
212 } __packed;
214 struct icmpv6_type_145 {
215 uint16_t id;
216 uint16_t res;
217 struct in6_addr home_agent_addr[0];
218 } __packed;
220 struct icmpv6_type_147 {
221 uint16_t id;
222 uint16_t m_o_res;
223 uint8_t ops[0];
224 } __packed;
225 /* end ICMP Mobility Support */
227 /* SEcure Neighbor Discovery */
228 struct icmpv6_type_148 {
229 uint16_t id;
230 uint16_t comp;
231 uint8_t ops[0];
232 } __packed;
234 struct icmpv6_type_149 {
235 uint16_t id;
236 uint16_t all_comp;
237 uint16_t comp;
238 uint16_t res;
239 uint8_t ops[0];
240 } __packed;
241 /* end SEcure Neighbor Discovery */
243 struct icmpv6_type_150 {
244 union {
245 uint32_t subtype_res;
246 struct {
247 #if defined(__LITTLE_ENDIAN_BITFIELD)
248 uint32_t res :24,
249 subtype :8;
250 #elif defined(__BIG_ENDIAN_BITFIELD)
251 uint32_t subtype :8,
252 res :24;
253 #else
254 # error "Please fix <asm/byteorder.h>"
255 #endif
258 uint8_t ops[0];
259 } __packed;
261 /* Multicast Router Discovery */
262 struct icmpv6_type_151 {
263 uint16_t query_intv;
264 uint16_t rob_var;
265 } __packed;
267 struct icmpv6_type_152 {
268 uint8_t null[0];
269 } __packed;
271 struct icmpv6_type_153 {
272 uint8_t null[0];
273 } __packed;
274 /* end Multicast Router Discovery */
276 struct icmpv6_type_154 {
277 uint8_t subtype;
278 uint8_t res;
279 uint16_t id;
280 uint8_t ops[0];
281 } __packed;
283 static int8_t print_ipv6_addr_list(struct pkt_buff *pkt, uint8_t nr_addr)
285 char address[INET6_ADDRSTRLEN];
286 struct in6_addr *addr;
288 while (nr_addr--) {
289 addr = (struct in6_addr *) pkt_pull(pkt, sizeof(*addr));
290 if (addr == NULL)
291 return 0;
293 tprintf("\n\t Address: %s",
294 inet_ntop(AF_INET6, addr, address,
295 sizeof(address)));
298 return 1;
301 static const char *icmpv6_mcast_rec_types[] = {
302 "MODE_IS_INCLUDE",
303 "MODE_IS_EXCLUDE",
304 "CHANGE_TO_INCLUDE_MODE",
305 "CHANGE_TO_EXCLUDE_MODE",
306 "ALLOW_NEW_SOURCES",
307 "BLOCK_OLD_SOURCES",
310 static int8_t dissect_icmpv6_mcast_rec(struct pkt_buff *pkt,
311 uint16_t nr_rec)
313 uint16_t nr_src, aux_data_len_bytes;
314 char address[INET6_ADDRSTRLEN];
315 struct icmpv6_mldv2_addr_rec *addr_rec;
317 while (nr_rec--) {
318 addr_rec = (struct icmpv6_mldv2_addr_rec *)
319 pkt_pull(pkt,sizeof(*addr_rec));
320 if (addr_rec == NULL)
321 return 0;
322 aux_data_len_bytes = addr_rec->aux_data_len * 4;
323 nr_src = ntohs(addr_rec->nr_src);
325 tprintf(", Rec Type %s (%u)",
326 icmpv6_code_range_valid(addr_rec->rec_type - 1,
327 icmpv6_mcast_rec_types) ?
328 icmpv6_mcast_rec_types[addr_rec->rec_type - 1]
329 : "Unknown", addr_rec->rec_type);
330 if (aux_data_len_bytes > pkt_len(pkt)) {
331 tprintf(", Aux Data Len (%u, %u bytes) %s",
332 addr_rec->aux_data_len,
333 aux_data_len_bytes,
334 colorize_start_full(black, red) "invalid"
335 colorize_end());
336 return 0;
338 tprintf(", Aux Data Len (%u, %u bytes)",addr_rec->aux_data_len,
339 aux_data_len_bytes);
340 tprintf(", Nr. of Sources (%u)",nr_src);
341 tprintf(", Address: %s",
342 inet_ntop(AF_INET6, &addr_rec->multic_addr,
343 address, sizeof(address)));
345 if(!print_ipv6_addr_list(pkt, nr_src))
346 return 0;
348 if (aux_data_len_bytes > pkt_len(pkt)) {
349 tprintf("\nAux Data Len %s",
350 colorize_start_full(black, red) "invalid"
351 colorize_end());
352 return 0;
355 tprintf(", Aux Data: ");
356 while (aux_data_len_bytes--) {
357 uint8_t *data = pkt_pull(pkt, 1);
359 if (data == NULL) {
360 tprintf("%sINVALID%s", colorize_start_full(black, red),
361 colorize_end());
362 return 0;
365 tprintf("%x", *data);
369 return 1;
372 static int8_t dissect_neighb_disc_ops_1(struct pkt_buff *pkt,
373 ssize_t len)
375 struct icmpv6_neighb_disc_ops_type_1_2 *icmp_neighb_disc_1;
377 icmp_neighb_disc_1 = (struct icmpv6_neighb_disc_ops_type_1_2 *)
378 pkt_pull(pkt,sizeof(*icmp_neighb_disc_1));
379 if (icmp_neighb_disc_1 == NULL)
380 return 0;
381 len -= sizeof(*icmp_neighb_disc_1);
382 if (len < 0)
383 return 0;
385 tprintf("Address 0x");
387 while (len--) {
388 uint8_t *data = pkt_pull(pkt, 1);
390 if (data == NULL) {
391 tprintf("%sINVALID%s", colorize_start_full(black, red),
392 colorize_end());
393 return 0;
396 tprintf("%x", *data);
399 return 1;
402 static int8_t dissect_neighb_disc_ops_2(struct pkt_buff *pkt,
403 ssize_t len)
405 return dissect_neighb_disc_ops_1(pkt, len);
408 static int8_t dissect_neighb_disc_ops_3(struct pkt_buff *pkt,
409 ssize_t len)
411 char address[INET6_ADDRSTRLEN];
412 struct icmpv6_neighb_disc_ops_type_3 *icmp_neighb_disc_3;
414 icmp_neighb_disc_3 = (struct icmpv6_neighb_disc_ops_type_3 *)
415 pkt_pull(pkt,sizeof(*icmp_neighb_disc_3));
416 if (icmp_neighb_disc_3 == NULL)
417 return 0;
418 len -= sizeof(*icmp_neighb_disc_3);
419 if (len < 0)
420 return 0;
422 tprintf("Prefix Len (%u) ",icmp_neighb_disc_3->prefix_len);
423 tprintf("L (%u) A (%u) Res1 (0x%x) ",icmp_neighb_disc_3->l_a_res1 >> 7,
424 (icmp_neighb_disc_3->l_a_res1 >> 7) & 0x1,
425 icmp_neighb_disc_3->l_a_res1 & 0x3F);
426 tprintf("Valid Lifetime (%us) ",
427 ntohl(icmp_neighb_disc_3->valid_lifetime));
428 tprintf("Preferred Lifetime (%us) ",
429 ntohl(icmp_neighb_disc_3->preferred_lifetime));
430 tprintf("Reserved2 (0x%x) ",
431 ntohl(icmp_neighb_disc_3->res2));
432 tprintf("Prefix: %s ",
433 inet_ntop(AF_INET6,&icmp_neighb_disc_3->prefix,
434 address, sizeof(address)));
436 return 1;
439 static int8_t dissect_neighb_disc_ops_4(struct pkt_buff *pkt,
440 ssize_t len)
442 struct icmpv6_neighb_disc_ops_type_4 *icmp_neighb_disc_4;
444 icmp_neighb_disc_4 = (struct icmpv6_neighb_disc_ops_type_4 *)
445 pkt_pull(pkt,sizeof(*icmp_neighb_disc_4));
446 if (icmp_neighb_disc_4 == NULL)
447 return 0;
448 len -= sizeof(*icmp_neighb_disc_4);
449 if (len < 0)
450 return 0;
452 tprintf("Reserved 1 (0x%x) ", ntohs(icmp_neighb_disc_4->res1));
453 tprintf("Reserved 2 (0x%x) ", ntohl(icmp_neighb_disc_4->res2));
454 tprintf("IP header + data ");
456 while (len--) {
457 uint8_t *data = pkt_pull(pkt, 1);
459 if (data == NULL) {
460 tprintf("%sINVALID%s", colorize_start_full(black, red),
461 colorize_end());
462 return 0;
465 tprintf("%x", *data);
468 return 1;
471 static int8_t dissect_neighb_disc_ops_5(struct pkt_buff *pkt,
472 ssize_t len)
474 struct icmpv6_neighb_disc_ops_type_5 *icmp_neighb_disc_5;
476 icmp_neighb_disc_5 = (struct icmpv6_neighb_disc_ops_type_5 *)
477 pkt_pull(pkt,sizeof(*icmp_neighb_disc_5));
478 if (icmp_neighb_disc_5 == NULL)
479 return 0;
480 len -= sizeof(*icmp_neighb_disc_5);
481 if (len < 0)
482 return 0;
484 tprintf("Reserved (0x%x) ", ntohs(icmp_neighb_disc_5->res1));
485 tprintf("MTU (%u)", ntohl(icmp_neighb_disc_5->MTU));
487 return 1;
490 static int8_t dissect_neighb_disc_ops_9(struct pkt_buff *pkt,
491 ssize_t len)
493 struct icmpv6_neighb_disc_ops_type_9_10 *icmp_neighb_disc_9;
495 icmp_neighb_disc_9 = (struct icmpv6_neighb_disc_ops_type_9_10 *)
496 pkt_pull(pkt,sizeof(*icmp_neighb_disc_9));
497 if (icmp_neighb_disc_9 == NULL)
498 return 0;
499 len -= sizeof(*icmp_neighb_disc_9);
500 if (len < 0)
501 return 0;
503 tprintf("Reserved 1 (0x%x) ", ntohs(icmp_neighb_disc_9->res1));
504 tprintf("Reserved 2 (0x%x) ", ntohl(icmp_neighb_disc_9->res2));
506 return print_ipv6_addr_list(pkt, len / sizeof(struct in6_addr));
509 static int8_t dissect_neighb_disc_ops_10(struct pkt_buff *pkt,
510 ssize_t len)
512 return dissect_neighb_disc_ops_9(pkt, len);
515 static const char *icmpv6_neighb_disc_ops_15_name[] = {
516 "DER Encoded X.501 Name",
517 "FQDN",
520 static int8_t dissect_neighb_disc_ops_15(struct pkt_buff *pkt,
521 ssize_t len)
523 size_t pad_len;
524 ssize_t name_len;
525 struct icmpv6_neighb_disc_ops_type_15 *icmp_neighb_disc_15;
527 icmp_neighb_disc_15 = (struct icmpv6_neighb_disc_ops_type_15 *)
528 pkt_pull(pkt,sizeof(*icmp_neighb_disc_15));
529 if (icmp_neighb_disc_15 == NULL)
530 return 0;
531 len -= sizeof(*icmp_neighb_disc_15);
532 if (len < 0)
533 return 0;
534 pad_len = icmp_neighb_disc_15->pad_len;
536 tprintf("Name Type %s (%u) ",
537 icmpv6_code_range_valid(icmp_neighb_disc_15->name_type - 1,
538 icmpv6_neighb_disc_ops_15_name) ?
539 icmpv6_neighb_disc_ops_15_name[
540 icmp_neighb_disc_15->name_type - 1] : "Unknown",
541 icmp_neighb_disc_15->name_type);
542 if (pad_len > (size_t) len) {
543 tprintf("Pad Len (%zu, invalid)\n%s", pad_len,
544 colorize_start_full(black, red)
545 "Skip Option" colorize_end());
546 pkt_pull(pkt, len);
547 return 1;
549 else
550 tprintf("Pad Len (%zu) ", pad_len);
552 name_len = len - pad_len;
554 tprintf("Name (");
555 while (name_len--) {
556 uint8_t *data = pkt_pull(pkt, 1);
558 if (data == NULL) {
559 tprintf("%sINVALID%s", colorize_start_full(black, red),
560 colorize_end());
561 return 0;
564 tprintf("%c", *data);
566 tprintf(") ");
568 tprintf("Padding (");
570 while (pad_len--) {
571 uint8_t *data = pkt_pull(pkt, 1);
573 if (data == NULL) {
574 tprintf("%sINVALID%s", colorize_start_full(black, red),
575 colorize_end());
576 break;
579 tprintf("%x", *data);
581 tprintf(")");
583 return 1;
586 static const char *icmpv6_neighb_disc_ops_16_cert[] = {
587 "X.509v3 Certificate",
590 static int8_t dissect_neighb_disc_ops_16(struct pkt_buff *pkt,
591 ssize_t len)
593 struct icmpv6_neighb_disc_ops_type_16 *icmp_neighb_disc_16;
595 icmp_neighb_disc_16 = (struct icmpv6_neighb_disc_ops_type_16 *)
596 pkt_pull(pkt,sizeof(*icmp_neighb_disc_16));
597 if (icmp_neighb_disc_16 == NULL)
598 return 0;
599 len -= sizeof(*icmp_neighb_disc_16);
600 if (len < 0)
601 return 0;
603 tprintf("Cert Type %s (%u) ",
604 icmpv6_code_range_valid(icmp_neighb_disc_16->cert_type - 1,
605 icmpv6_neighb_disc_ops_16_cert) ?
606 icmpv6_neighb_disc_ops_16_cert[
607 icmp_neighb_disc_16->cert_type - 1] : "Unknown",
608 icmp_neighb_disc_16->cert_type);
609 tprintf("Res (0x%x) ", icmp_neighb_disc_16->res);
611 tprintf("Certificate + Padding (");
612 while (len--) {
613 uint8_t *data = pkt_pull(pkt, 1);
615 if (data == NULL) {
616 tprintf("%sINVALID%s", colorize_start_full(black, red),
617 colorize_end());
618 break;
621 tprintf("%x", *data);
623 tprintf(") ");
625 return 1;
628 static const char *icmpv6_neighb_disc_ops_17_codes[] = {
629 "Old Care-of Address",
630 "New Care-of Address",
631 "NAR's IP address",
632 "NAR's Prefix",
635 static int8_t dissect_neighb_disc_ops_17(struct pkt_buff *pkt,
636 ssize_t len)
638 char address[INET6_ADDRSTRLEN];
639 struct icmpv6_neighb_disc_ops_type_17 *icmp_neighb_disc_17;
641 icmp_neighb_disc_17 = (struct icmpv6_neighb_disc_ops_type_17 *)
642 pkt_pull(pkt,sizeof(*icmp_neighb_disc_17));
643 if (icmp_neighb_disc_17 == NULL)
644 return 0;
645 len -= sizeof(*icmp_neighb_disc_17);
646 if (len < 0)
647 return 0;
649 tprintf("Opt Code %s (%u) ",
650 icmpv6_code_range_valid(icmp_neighb_disc_17->opt_code - 1,
651 icmpv6_neighb_disc_ops_17_codes) ?
652 icmpv6_neighb_disc_ops_17_codes[
653 icmp_neighb_disc_17->opt_code - 1] : "Unknown",
654 icmp_neighb_disc_17->opt_code);
655 tprintf("Prefix Len (%u) ", icmp_neighb_disc_17->prefix_len);
657 if (len == sizeof(struct icmpv6_neighb_disc_ops_type_17_1)) {
658 struct icmpv6_neighb_disc_ops_type_17_1
659 *icmp_neighb_disc_17_1;
661 icmp_neighb_disc_17_1 =
662 (struct icmpv6_neighb_disc_ops_type_17_1 *)
663 pkt_pull(pkt,sizeof(*icmp_neighb_disc_17_1));
664 if (icmp_neighb_disc_17_1 == NULL)
665 return 0;
666 len -= sizeof(*icmp_neighb_disc_17_1);
667 if (len < 0)
668 return 0;
670 tprintf("Res (0x%x) ",icmp_neighb_disc_17_1->res);
671 tprintf("Addr: %s ",
672 inet_ntop(AF_INET6,&icmp_neighb_disc_17_1->ipv6_addr,
673 address, sizeof(address)));
675 else if (len == sizeof(struct icmpv6_neighb_disc_ops_type_17_2)) {
676 struct icmpv6_neighb_disc_ops_type_17_2
677 *icmp_neighb_disc_17_2;
679 icmp_neighb_disc_17_2 =
680 (struct icmpv6_neighb_disc_ops_type_17_2 *)
681 pkt_pull(pkt,sizeof(*icmp_neighb_disc_17_2));
682 if (icmp_neighb_disc_17_2 == NULL)
683 return 0;
684 len -= sizeof(*icmp_neighb_disc_17_2);
685 if (len < 0)
686 return 0;
688 tprintf("Addr: %s ",
689 inet_ntop(AF_INET6,&icmp_neighb_disc_17_2->ipv6_addr,
690 address, sizeof(address)));
692 else {
693 tprintf("%s (", colorize_start_full(black, red)
694 "Error Wrong Length. Skip Option" colorize_end());
695 while (len--) {
696 uint8_t *data = pkt_pull(pkt, 1);
698 if (data == NULL) {
699 tprintf("%sINVALID%s", colorize_start_full(black, red),
700 colorize_end());
701 break;
704 tprintf("%x", *data);
706 tprintf(") ");
709 return 1;
712 static const char *icmpv6_neighb_disc_ops_19_codes[] = {
713 "Wildcard requesting resolution for all nearby access points",
714 "Link-Layer Address of the New Access Point",
715 "Link-Layer Address of the MN",
716 "Link-Layer Address of the NAR",
717 "Link-Layer Address of the source of RtSolPr or PrRtAdv \
718 message",
719 "The access point identified by the LLA belongs to the \
720 current interface of the router",
721 "No prefix information available for the access point \
722 identified by the LLA",
723 "No fast handover support available for the access point \
724 identified by the LLA",
727 static int8_t dissect_neighb_disc_ops_19(struct pkt_buff *pkt,
728 ssize_t len)
730 struct icmpv6_neighb_disc_ops_type_19 *icmp_neighb_disc_19;
732 icmp_neighb_disc_19 = (struct icmpv6_neighb_disc_ops_type_19 *)
733 pkt_pull(pkt,sizeof(*icmp_neighb_disc_19));
734 if (icmp_neighb_disc_19 == NULL)
735 return 0;
736 len -= sizeof(*icmp_neighb_disc_19);
737 if (len < 0)
738 return 0;
740 tprintf("Opt Code %s (%u) ",
741 icmpv6_code_range_valid(icmp_neighb_disc_19->opt_code,
742 icmpv6_neighb_disc_ops_19_codes) ?
743 icmpv6_neighb_disc_ops_19_codes[
744 icmp_neighb_disc_19->opt_code] : "Unknown",
745 icmp_neighb_disc_19->opt_code);
747 tprintf("LLA (");
748 while(len--) {
749 uint8_t *data = pkt_pull(pkt, 1);
751 if (data == NULL) {
752 tprintf("%sINVALID%s", colorize_start_full(black, red),
753 colorize_end());
754 return 0;
757 tprintf("%x", *data);
759 tprintf(") ");
761 return 1;
764 static inline char *icmpv6_neighb_disc_ops(uint8_t code) {
765 switch (code) {
766 case 1: return "Source Link-Layer Address";
767 case 2: return "Target Link-Layer Address";
768 case 3: return "Prefix Information";
769 case 4: return "Redirected Header";
770 case 5: return "MTU";
771 case 6: return "NBMA Shortcut Limit Option";
772 case 7: return "Advertisement Interval Option";
773 case 8: return "Home Agent Information Option";
774 case 9: return "Source Address List";
775 case 10: return "Target Address List";
776 case 11: return "CGA option";
777 case 12: return "RSA Signature option";
778 case 13: return "Timestamp option";
779 case 14: return "Nonce option";
780 case 15: return "Trust Anchor option";
781 case 16: return "Certificate option";
782 case 17: return "IP Address/Prefix Option";
783 case 18: return "New Router Prefix Information Option";
784 case 19: return "Link-layer Address Option";
785 case 20: return "Neighbor Advertisement Acknowledgment Option";
787 case 23: return "Prefix Information";
788 case 24: return "Redirected Header";
789 case 25: return "MTU";
790 case 26: return "NBMA Shortcut Limit Option";
791 case 27: return "Advertisement Interval Option";
792 case 28: return "Home Agent Information Option";
793 case 29: return "Source Address List";
794 case 30: return "Target Address List";
795 case 31: return "DNS Search List Option";
796 case 32: return "Proxy Signature (PS)";
798 case 138: return "CARD Request option";
799 case 139: return "CARD Reply option";
801 case 253: return "RFC3692-style Experiment 1";
802 case 254: return "RFC3692-style Experiment 2";
805 return NULL;
808 static int8_t dissect_neighb_disc_ops(struct pkt_buff *pkt)
810 size_t pad_bytes;
811 uint16_t ops_total_len;
812 ssize_t ops_payl_len;
813 struct icmpv6_neighb_disc_ops_general *icmp_neighb_disc;
815 while(pkt_len(pkt)) {
816 icmp_neighb_disc = (struct icmpv6_neighb_disc_ops_general *)
817 pkt_pull(pkt,sizeof(*icmp_neighb_disc));
818 if (icmp_neighb_disc == NULL)
819 return 0;
821 ops_total_len = icmp_neighb_disc->len * 8;
822 pad_bytes = (size_t) (ops_total_len % 8);
823 ops_payl_len = ops_total_len - sizeof(*icmp_neighb_disc) -
824 pad_bytes;
826 tprintf("\n\tOption %s (%u) ",
827 icmpv6_neighb_disc_ops(icmp_neighb_disc->type) ?
828 icmpv6_neighb_disc_ops(icmp_neighb_disc->type)
829 : "Type Unknown", icmp_neighb_disc->type);
830 if (ops_payl_len > pkt_len(pkt) || ops_payl_len < 0) {
831 tprintf("Length (%u, %u bytes, %s%s%s) ",
832 icmp_neighb_disc->len,
833 ops_total_len,
834 colorize_start_full(black, red),
835 "invalid", colorize_end());
836 return 0;
839 tprintf("Length (%u, %u bytes) ",icmp_neighb_disc->len,
840 ops_total_len);
842 switch (icmp_neighb_disc->type) {
843 case 1:
844 if (!dissect_neighb_disc_ops_1(pkt, ops_payl_len))
845 return 0;
846 break;
847 case 2:
848 if (!dissect_neighb_disc_ops_2(pkt, ops_payl_len))
849 return 0;
850 break;
851 case 3:
852 if (!dissect_neighb_disc_ops_3(pkt, ops_payl_len))
853 return 0;
854 break;
855 case 4:
856 if (!dissect_neighb_disc_ops_4(pkt, ops_payl_len))
857 return 0;
858 break;
859 case 5:
860 if (!dissect_neighb_disc_ops_5(pkt, ops_payl_len))
861 return 0;
862 break;
863 /* Type 9 and 10 defined in
864 * http://tools.ietf.org/html/rfc3122#section-3.1
866 case 9:
867 if (!dissect_neighb_disc_ops_9(pkt, ops_payl_len))
868 return 0;
869 break;
870 case 10:
871 if (!dissect_neighb_disc_ops_10(pkt, ops_payl_len))
872 return 0;
873 break;
874 /* Type 15 and 16 defined in
875 * http://tools.ietf.org/html/rfc3971#section-6.4.3
876 * http://tools.ietf.org/html/rfc3971#section-6.4.4
878 case 15:
879 if (!dissect_neighb_disc_ops_15(pkt, ops_payl_len))
880 return 0;
881 break;
882 case 16:
883 if (!dissect_neighb_disc_ops_16(pkt, ops_payl_len))
884 return 0;
885 break;
886 /* Type 17 and 19 defined in
887 * http://tools.ietf.org/html/rfc5568#section-6.4
889 case 17:
890 if (!dissect_neighb_disc_ops_17(pkt, ops_payl_len))
891 return 0;
892 break;
893 case 19:
894 if (!dissect_neighb_disc_ops_19(pkt, ops_payl_len))
895 return 0;
896 break;
897 default:
898 pkt_pull(pkt, ops_payl_len);
901 /* Skip Padding Bytes */
902 if (pad_bytes > pkt_len(pkt)) {
903 tprintf(" %s",colorize_start_full(black, red)
904 "Invalid Padding" colorize_end());
905 return 0;
907 pkt_pull(pkt, pad_bytes);
910 return 1;
913 static const char *icmpv6_type_1_codes[] = {
914 "No route to destination",
915 "Communication with destination administratively prohibited",
916 "Beyond scope of source address",
917 "Address unreachable",
918 "Port unreachable",
919 "Source address failed ingress/egress policy",
920 "Reject route to destination",
921 "Error in Source Routing Header",
924 static int8_t dissect_icmpv6_type1(struct pkt_buff *pkt)
926 struct icmpv6_type_1_3 *icmp_1;
928 icmp_1 = (struct icmpv6_type_1_3 *) pkt_pull(pkt,sizeof(*icmp_1));
929 if (icmp_1 == NULL)
930 return 0;
932 tprintf(", Unused (0x%x)",ntohl(icmp_1->unused));
933 tprintf(" Payload include as much of invoking packet");
935 return 1;
938 static int8_t dissect_icmpv6_type2(struct pkt_buff *pkt)
940 struct icmpv6_type_2 *icmp_2;
942 icmp_2 = (struct icmpv6_type_2 *) pkt_pull(pkt,sizeof(*icmp_2));
943 if (icmp_2 == NULL)
944 return 0;
946 tprintf(", MTU (0x%x)",ntohl(icmp_2->MTU));
947 tprintf(" Payload include as much of invoking packet");
949 return 1;
952 static const char *icmpv6_type_3_codes[] = {
953 "Hop limit exceeded in transit",
954 "Fragment reassembly time exceeded",
957 static int8_t dissect_icmpv6_type3(struct pkt_buff *pkt)
959 struct icmpv6_type_1_3 *icmp_3;
961 icmp_3 = (struct icmpv6_type_1_3 *) pkt_pull(pkt,sizeof(*icmp_3));
962 if (icmp_3 == NULL)
963 return 0;
965 tprintf(", Unused (0x%x)",ntohl(icmp_3->unused));
966 tprintf(" Payload include as much of invoking packet");
968 return 1;
971 static const char *icmpv6_type_4_codes[] = {
972 "Erroneous header field encountered",
973 "Unrecognized Next Header type encountered",
974 "Unrecognized IPv6 option encountered",
977 static int8_t dissect_icmpv6_type4(struct pkt_buff *pkt)
979 struct icmpv6_type_4 *icmp_4;
981 icmp_4 = (struct icmpv6_type_4 *) pkt_pull(pkt,sizeof(*icmp_4));
982 if (icmp_4 == NULL)
983 return 0;
985 tprintf(", Pointer (0x%x)",ntohl(icmp_4->pointer));
986 tprintf(" Payload include as much of invoking packet");
988 return 1;
991 static int8_t dissect_icmpv6_type128(struct pkt_buff *pkt)
993 struct icmpv6_type_128_129 *icmp_128;
995 icmp_128 = (struct icmpv6_type_128_129 *)
996 pkt_pull(pkt,sizeof(*icmp_128));
997 if (icmp_128 == NULL)
998 return 0;
1000 tprintf(", ID (0x%x)",ntohs(icmp_128->id));
1001 tprintf(", Seq. Nr. (%u)",ntohs(icmp_128->sn));
1002 tprintf(" Payload include Data");
1004 return 1;
1007 static int8_t dissect_icmpv6_type129(struct pkt_buff *pkt)
1009 struct icmpv6_type_128_129 *icmp_129;
1011 icmp_129 = (struct icmpv6_type_128_129 *)
1012 pkt_pull(pkt,sizeof(*icmp_129));
1013 if (icmp_129 == NULL)
1014 return 0;
1016 tprintf(", ID (0x%x)",ntohs(icmp_129->id));
1017 tprintf(", Seq. Nr. (%u)",ntohs(icmp_129->sn));
1018 tprintf(" Payload include Data");
1020 return 1;
1023 static int8_t dissect_icmpv6_type130(struct pkt_buff *pkt)
1025 char address[INET6_ADDRSTRLEN];
1026 uint16_t nr_src, maxrespdel;
1027 uint8_t switch_mldv2 = 0;
1028 struct icmpv6_type_130_131_132 *icmp_130;
1030 icmp_130 = (struct icmpv6_type_130_131_132 *)
1031 pkt_pull(pkt,sizeof(*icmp_130));
1032 if (icmp_130 == NULL)
1033 return 0;
1034 maxrespdel = ntohs(icmp_130->maxrespdel);
1036 if(pkt_len(pkt) >= sizeof(struct icmpv6_type_130_mldv2))
1037 switch_mldv2 = 1;
1039 if(switch_mldv2)
1040 tprintf(", MLDv2, Max Resp Delay (%ums)", maxrespdel >> 15 ?
1041 (((maxrespdel & 0xFFF) | 0x1000) <<
1042 (((maxrespdel >> 12) & 0x3) + 3)) : maxrespdel);
1043 else
1044 tprintf(", Max Resp Delay (%ums)",maxrespdel);
1045 tprintf(", Res (0x%x)",ntohs(icmp_130->res));
1046 tprintf(", Address: %s",
1047 inet_ntop(AF_INET6, &icmp_130->ipv6_addr,
1048 address, sizeof(address)));
1050 if(switch_mldv2) {
1051 struct icmpv6_type_130_mldv2 *icmp_130_mldv2;
1053 icmp_130_mldv2 = (struct icmpv6_type_130_mldv2 *)
1054 pkt_pull(pkt,sizeof(*icmp_130_mldv2));
1055 if (icmp_130_mldv2 == NULL)
1056 return 0;
1058 nr_src = ntohs(icmp_130_mldv2->nr_src);
1060 tprintf(", Resv (0x%x)",icmp_130_mldv2->resv_S_QRV >> 4);
1061 tprintf(", S (%u)",(icmp_130_mldv2->resv_S_QRV >> 3) & 0x1);
1062 tprintf(", QRV (0x%x)",icmp_130_mldv2->resv_S_QRV & 0x3);
1063 tprintf(", QQIC (%u)",icmp_130_mldv2->QQIC);
1064 tprintf(", Nr Src (%u)",nr_src);
1066 return print_ipv6_addr_list(pkt, nr_src);
1069 return 1;
1072 static int8_t dissect_icmpv6_type131(struct pkt_buff *pkt)
1074 char address[INET6_ADDRSTRLEN];
1075 struct icmpv6_type_130_131_132 *icmp_131;
1077 icmp_131 = (struct icmpv6_type_130_131_132 *)
1078 pkt_pull(pkt,sizeof(*icmp_131));
1079 if (icmp_131 == NULL)
1080 return 0;
1082 tprintf(", Max Resp Delay (%ums)",ntohs(icmp_131->maxrespdel));
1083 tprintf(", Res (0x%x)",ntohs(icmp_131->res));
1084 tprintf(", Address: %s",
1085 inet_ntop(AF_INET6, &icmp_131->ipv6_addr,
1086 address, sizeof(address)));
1088 return 1;
1091 static inline int8_t dissect_icmpv6_type132(struct pkt_buff *pkt)
1093 return dissect_icmpv6_type131(pkt);
1096 static int8_t dissect_icmpv6_type133(struct pkt_buff *pkt)
1098 struct icmpv6_type_133_141_142 *icmp_133;
1100 icmp_133 = (struct icmpv6_type_133_141_142 *)
1101 pkt_pull(pkt,sizeof(*icmp_133));
1102 if (icmp_133 == NULL)
1103 return 0;
1105 tprintf(", Reserved (0x%x)",ntohl(icmp_133->res));
1107 return dissect_neighb_disc_ops(pkt);
1110 static int8_t dissect_icmpv6_type134(struct pkt_buff *pkt)
1112 struct icmpv6_type_134 *icmp_134;
1114 icmp_134 = (struct icmpv6_type_134 *)
1115 pkt_pull(pkt,sizeof(*icmp_134));
1116 if (icmp_134 == NULL)
1117 return 0;
1119 tprintf(", Cur Hop Limit (%u)",icmp_134->cur_hop_limit);
1120 tprintf(", M (%u) O (%u)",icmp_134->m_o_res >> 7,
1121 (icmp_134->m_o_res >> 6) & 0x1);
1122 tprintf(", Router Lifetime (%us)",ntohs(icmp_134->router_lifetime));
1123 tprintf(", Reachable Time (%ums)",ntohl(icmp_134->reachable_time));
1124 tprintf(", Retrans Timer (%ums)",ntohl(icmp_134->retrans_timer));
1126 return dissect_neighb_disc_ops(pkt);
1129 static int8_t dissect_icmpv6_type135(struct pkt_buff *pkt)
1131 char address[INET6_ADDRSTRLEN];
1132 struct icmpv6_type_135 *icmp_135;
1134 icmp_135 = (struct icmpv6_type_135 *)
1135 pkt_pull(pkt,sizeof(*icmp_135));
1136 if (icmp_135 == NULL)
1137 return 0;
1139 tprintf(", Reserved (0x%x)",ntohl(icmp_135->res));
1140 tprintf(", Target Address: %s",
1141 inet_ntop(AF_INET6, &icmp_135->ipv6_addr,
1142 address, sizeof(address)));
1144 return dissect_neighb_disc_ops(pkt);
1147 static int8_t dissect_icmpv6_type136(struct pkt_buff *pkt)
1149 char address[INET6_ADDRSTRLEN];
1150 uint32_t r_s_o_res;
1151 struct icmpv6_type_136 *icmp_136;
1153 icmp_136 = (struct icmpv6_type_136 *)
1154 pkt_pull(pkt,sizeof(*icmp_136));
1155 if (icmp_136 == NULL)
1156 return 0;
1157 r_s_o_res = ntohl(icmp_136->r_s_o_res);
1159 tprintf(", R (%u) S (%u) O (%u) Reserved (0x%x)", r_s_o_res >> 31,
1160 (r_s_o_res >> 30) & 0x1, (r_s_o_res >> 29) & 0x1,
1161 r_s_o_res & 0x1FFFFFFF);
1162 tprintf(", Target Address: %s",
1163 inet_ntop(AF_INET6, &icmp_136->ipv6_addr,
1164 address, sizeof(address)));
1166 return dissect_neighb_disc_ops(pkt);
1169 static int8_t dissect_icmpv6_type137(struct pkt_buff *pkt)
1171 char address[INET6_ADDRSTRLEN];
1172 struct icmpv6_type_137 *icmp_137;
1174 icmp_137 = (struct icmpv6_type_137 *)
1175 pkt_pull(pkt,sizeof(*icmp_137));
1176 if (icmp_137 == NULL)
1177 return 0;
1179 tprintf(", Reserved (0x%x)",icmp_137->res);
1180 tprintf(", Target Address: %s",
1181 inet_ntop(AF_INET6, &icmp_137->ipv6_targ_addr,
1182 address, sizeof(address)));
1183 tprintf(", Dest Address: %s",
1184 inet_ntop(AF_INET6, &icmp_137->ipv6_dest_addr,
1185 address, sizeof(address)));
1187 return dissect_neighb_disc_ops(pkt);
1190 static void dissect_icmpv6_rr_body(struct pkt_buff *pkt)
1193 * Upgrade Dissector for Message Body
1194 * from http://tools.ietf.org/html/rfc2894#section-3.2
1196 if(pkt_len(pkt))
1197 tprintf(" Message Body recognized");
1200 static inline char *icmpv6_type_138_codes(uint8_t code) {
1201 switch (code) {
1202 case 1: return "Router Renumbering Command";
1203 case 2: return "Router Renumbering Result";
1204 case 255: return "Sequence Number Reset";
1207 return NULL;
1210 static int8_t dissect_icmpv6_type138(struct pkt_buff *pkt)
1212 struct icmpv6_type_138 *icmp_138;
1214 icmp_138 = (struct icmpv6_type_138 *)
1215 pkt_pull(pkt,sizeof(*icmp_138));
1216 if (icmp_138 == NULL)
1217 return 0;
1219 tprintf(", Sequence Nr. (%u)",ntohl(icmp_138->seq_nr));
1220 tprintf(", Segment Nr. (%u)",icmp_138->seg_nr);
1221 tprintf(", T (%u) R (%u) A (%u) S (%u) P (%u) Res \
1222 (0x%x) ",icmp_138->flags >> 7, (icmp_138->flags >> 6) & 1,
1223 (icmp_138->flags >> 5) & 1, (icmp_138->flags >> 4) & 1,
1224 (icmp_138->flags >> 3) & 1, icmp_138->flags & 7);
1225 tprintf(", Max Delay (%ums)", ntohs(icmp_138->maxdelay));
1226 tprintf(", Res (0x%x)", ntohl(icmp_138->res));
1228 dissect_icmpv6_rr_body(pkt);
1230 return 1;
1233 static void dissect_icmpv6_node_inf_data(struct pkt_buff *pkt)
1236 * Upgrade Dissector for Data field
1237 * http://tools.ietf.org/html/rfc4620#section-4
1239 if(pkt_len(pkt))
1240 tprintf(" Data recognized");
1243 static const char *icmpv6_node_inf_qtypes[] = {
1244 "NOOP",
1245 "unused",
1246 "Node Name",
1247 "Node Addresses",
1248 "IPv4 Addresses ",
1251 static const char *icmpv6_type_139_codes[] = {
1252 "Data contains IPv6 Address",
1253 "Data contains Name or nothing",
1254 "Data contains IPv4 Address",
1257 static int8_t dissect_icmpv6_type139(struct pkt_buff *pkt)
1259 const char *qtype_name = "Unknown";
1260 uint16_t qtype_nr;
1261 struct icmpv6_type_139_140 *icmp_139;
1263 icmp_139 = (struct icmpv6_type_139_140 *)
1264 pkt_pull(pkt,sizeof(*icmp_139));
1265 if (icmp_139 == NULL)
1266 return 0;
1268 qtype_nr = ntohs(icmp_139->qtype);
1269 if (icmpv6_code_range_valid(qtype_nr, icmpv6_node_inf_qtypes))
1270 qtype_name = icmpv6_node_inf_qtypes[qtype_nr];
1272 tprintf(", Qtype %s (%u)", qtype_name, qtype_nr);
1273 tprintf(", Flags (0x%x)", ntohs(icmp_139->flags));
1274 tprintf(", Nonce (0x%"PRIx64")", ntohll(icmp_139->nonce));
1276 dissect_icmpv6_node_inf_data(pkt);
1278 return 1;
1281 static char *icmpv6_type_140_codes[] = {
1282 "Successful reply",
1283 "Responder refuses answer",
1284 "Qtype is unknown to the Responder",
1287 static inline int8_t dissect_icmpv6_type140(struct pkt_buff *pkt)
1289 return dissect_icmpv6_type139(pkt);
1292 static inline int8_t dissect_icmpv6_type141(struct pkt_buff *pkt)
1294 return dissect_icmpv6_type133(pkt);
1297 static inline int8_t dissect_icmpv6_type142(struct pkt_buff *pkt)
1299 return dissect_icmpv6_type133(pkt);
1302 static int8_t dissect_icmpv6_type143(struct pkt_buff *pkt)
1304 uint16_t nr_rec;
1305 struct icmpv6_type_143 *icmp_143;
1307 icmp_143 = (struct icmpv6_type_143 *)
1308 pkt_pull(pkt,sizeof(*icmp_143));
1309 if (icmp_143 == NULL)
1310 return 0;
1311 nr_rec = ntohs(icmp_143->nr_rec);
1313 tprintf(", Res (0x%x)",ntohs(icmp_143->res));
1314 tprintf(", Nr. Mcast Addr Records (%u)",nr_rec);
1316 return dissect_icmpv6_mcast_rec(pkt, nr_rec);
1319 static int8_t dissect_icmpv6_type144(struct pkt_buff *pkt)
1321 struct icmpv6_type_144_146 *icmp_144;
1323 icmp_144 = (struct icmpv6_type_144_146 *)
1324 pkt_pull(pkt,sizeof(*icmp_144));
1325 if (icmp_144 == NULL)
1326 return 0;
1328 tprintf(", ID (%u)",ntohs(icmp_144->id));
1329 tprintf(", Res (0x%x)",ntohs(icmp_144->res));
1331 return 1;
1334 static int8_t dissect_icmpv6_type145(struct pkt_buff *pkt)
1336 struct icmpv6_type_145 *icmp_145;
1338 icmp_145 = (struct icmpv6_type_145 *)
1339 pkt_pull(pkt,sizeof(*icmp_145));
1340 if (icmp_145 == NULL)
1341 return 0;
1343 tprintf(", ID (%u)",ntohs(icmp_145->id));
1344 tprintf(", Res (0x%x)",ntohs(icmp_145->res));
1346 return print_ipv6_addr_list(pkt, pkt_len(pkt) /
1347 sizeof(struct in6_addr));
1350 static inline int8_t dissect_icmpv6_type146(struct pkt_buff *pkt)
1352 return dissect_icmpv6_type144(pkt);
1355 static int8_t dissect_icmpv6_type147(struct pkt_buff *pkt)
1357 uint16_t m_o_res;
1358 struct icmpv6_type_147 *icmp_147;
1360 icmp_147 = (struct icmpv6_type_147 *)
1361 pkt_pull(pkt,sizeof(*icmp_147));
1362 if (icmp_147 == NULL)
1363 return 0;
1364 m_o_res = ntohs(icmp_147->m_o_res);
1366 tprintf(", ID (%u)",ntohs(icmp_147->id));
1367 tprintf(", M (%u) O (%u) Res (0x%x)",m_o_res >> 15,
1368 (m_o_res >> 14) & 1, m_o_res & 0x3FFF);
1370 return dissect_neighb_disc_ops(pkt);
1373 static int8_t dissect_icmpv6_type148(struct pkt_buff *pkt)
1375 struct icmpv6_type_148 *icmp_148;
1377 icmp_148 = (struct icmpv6_type_148 *)
1378 pkt_pull(pkt,sizeof(*icmp_148));
1379 if (icmp_148 == NULL)
1380 return 0;
1382 tprintf(", ID (%u)",ntohs(icmp_148->id));
1383 tprintf(", Component (%u)",ntohs(icmp_148->comp));
1385 return dissect_neighb_disc_ops(pkt);
1388 static int8_t dissect_icmpv6_type149(struct pkt_buff *pkt)
1390 struct icmpv6_type_149 *icmp_149;
1392 icmp_149 = (struct icmpv6_type_149 *)
1393 pkt_pull(pkt,sizeof(*icmp_149));
1394 if (icmp_149 == NULL)
1395 return 0;
1397 tprintf(", ID (%u)",ntohs(icmp_149->id));
1398 tprintf(", All Components (%u)",ntohs(icmp_149->all_comp));
1399 tprintf(", Component (%u)",ntohs(icmp_149->comp));
1400 tprintf(", Res (0x%x)",ntohs(icmp_149->res));
1402 return dissect_neighb_disc_ops(pkt);
1405 static int8_t dissect_icmpv6_type150(struct pkt_buff *pkt)
1407 struct icmpv6_type_150 *icmp_150;
1409 icmp_150 = (struct icmpv6_type_150 *)
1410 pkt_pull(pkt,sizeof(*icmp_150));
1411 if (icmp_150 == NULL)
1412 return 0;
1414 tprintf(", Subtype (%u)",icmp_150->subtype);
1415 tprintf(", Res (0x%x)",icmp_150->res);
1416 tprintf(", Options in Payload");
1418 return 1;
1421 static int8_t dissect_icmpv6_type151(struct pkt_buff *pkt)
1423 struct icmpv6_type_151 *icmp_151;
1425 icmp_151 = (struct icmpv6_type_151 *)
1426 pkt_pull(pkt,sizeof(*icmp_151));
1427 if (icmp_151 == NULL)
1428 return 0;
1430 tprintf(", Query Interval (%us)",ntohs(icmp_151->query_intv));
1431 tprintf(", Robustness Variable (%u)",ntohs(icmp_151->rob_var));
1433 return 1;
1436 static int8_t dissect_icmpv6_type152(struct pkt_buff *pkt)
1438 struct icmpv6_type_152 *icmp_152;
1440 icmp_152 = (struct icmpv6_type_152 *)
1441 pkt_pull(pkt,sizeof(*icmp_152));
1442 if (icmp_152 == NULL)
1443 return 0;
1445 return 1;
1448 static int8_t dissect_icmpv6_type153(struct pkt_buff *pkt)
1450 struct icmpv6_type_153 *icmp_153;
1452 icmp_153 = (struct icmpv6_type_153 *)
1453 pkt_pull(pkt,sizeof(*icmp_153));
1454 if (icmp_153 == NULL)
1455 return 0;
1457 return 1;
1460 static int8_t dissect_icmpv6_type154(struct pkt_buff *pkt)
1462 struct icmpv6_type_154 *icmp_154;
1464 icmp_154 = (struct icmpv6_type_154 *)
1465 pkt_pull(pkt,sizeof(*icmp_154));
1466 if (icmp_154 == NULL)
1467 return 0;
1469 tprintf(", Subtype (%u)",icmp_154->subtype);
1470 tprintf(", Res (0x%x)",icmp_154->res);
1471 tprintf(", ID (%u)",ntohs(icmp_154->id));
1473 return dissect_neighb_disc_ops(pkt);
1476 static inline char *icmpv6_type_155_codes(uint8_t code) {
1477 switch (code) {
1478 case 0x00: return "DODAG Information Solicitation";
1479 case 0x01: return "DODAG Information Object";
1480 case 0x02: return "Destination Advertisement Object";
1481 case 0x03: return "Destination Advertisement Object Acknowledgment";
1482 case 0x80: return "Secure DODAG Information Solicitation";
1483 case 0x81: return "Secure DODAG Information Object";
1484 case 0x82: return "Secure Destination Advertisement Object";
1485 case 0x83: return "Secure Destination Advertisement Object Acknowledgment";
1486 case 0x8A: return "Consistency Check";
1489 return NULL;
1492 static void icmpv6_process(struct icmpv6_general_hdr *icmp, const char **type,
1493 const char **code, int8_t (**optional)(struct pkt_buff *pkt))
1495 *type = "Unknown Type";
1496 *code = "Unknown Code";
1498 switch (icmp->h_type) {
1499 case 1:
1500 *type = "Destination Unreachable";
1501 if (icmpv6_code_range_valid(icmp->h_code, icmpv6_type_1_codes))
1502 *code = icmpv6_type_1_codes[icmp->h_code];
1503 *optional = dissect_icmpv6_type1;
1504 return;
1505 case 2:
1506 *type = "Packet Too Big";
1507 *optional = dissect_icmpv6_type2;
1508 return;
1509 case 3:
1510 *type = "Time Exceeded";
1511 if (icmpv6_code_range_valid(icmp->h_code, icmpv6_type_3_codes))
1512 *code = icmpv6_type_3_codes[icmp->h_code];
1513 *optional = dissect_icmpv6_type3;
1514 return;
1515 case 4:
1516 *type = "Parameter Problem";
1517 if (icmpv6_code_range_valid(icmp->h_code, icmpv6_type_4_codes))
1518 *code = icmpv6_type_4_codes[icmp->h_code];
1519 *optional = dissect_icmpv6_type4;
1520 return;
1521 case 100:
1522 *type = "Private experimation";
1523 return;
1524 case 101:
1525 *type = "Private experimation";
1526 return;
1527 case 127:
1528 *type = "Reserved for expansion of ICMPv6 error messages";
1529 return;
1530 case 128:
1531 *type = "Echo Request";
1532 *optional = dissect_icmpv6_type128;
1533 return;
1534 case 129:
1535 *type = "Echo Reply";
1536 *optional = dissect_icmpv6_type129;
1537 return;
1538 case 130:
1539 *type = "Multicast Listener Query";
1540 *optional = dissect_icmpv6_type130;
1541 return;
1542 case 131:
1543 *type = "Multicast Listener Report";
1544 *optional = dissect_icmpv6_type131;
1545 return;
1546 case 132:
1547 *type = "Multicast Listener Done";
1548 *optional = dissect_icmpv6_type132;
1549 return;
1550 case 133:
1551 *type = "Router Solicitation";
1552 *optional = dissect_icmpv6_type133;
1553 return;
1554 case 134:
1555 *type = "Router Advertisement";
1556 *optional = dissect_icmpv6_type134;
1557 return;
1558 case 135:
1559 *type = "Neighbor Solicitation";
1560 *optional = dissect_icmpv6_type135;
1561 return;
1562 case 136:
1563 *type = "Neighbor Advertisement";
1564 *optional = dissect_icmpv6_type136;
1565 return;
1566 case 137:
1567 *type = "Redirect Message";
1568 *optional = dissect_icmpv6_type137;
1569 return;
1570 case 138:
1571 *type = "Router Renumbering";
1572 if(icmpv6_type_138_codes(icmp->h_code))
1573 *code = icmpv6_type_138_codes(icmp->h_code);
1574 *optional = dissect_icmpv6_type138;
1575 return;
1576 case 139:
1577 *type = "ICMP Node Information Query";
1578 if (icmpv6_code_range_valid(icmp->h_code,
1579 icmpv6_type_139_codes))
1580 *code = icmpv6_type_139_codes[icmp->h_code];
1581 *optional = dissect_icmpv6_type139;
1582 return;
1583 case 140:
1584 *type = "ICMP Node Information Response";
1585 if (icmpv6_code_range_valid(icmp->h_code,
1586 icmpv6_type_140_codes))
1587 *code = icmpv6_type_140_codes[icmp->h_code];
1588 *optional = dissect_icmpv6_type140;
1589 return;
1590 case 141:
1591 *type = "Inverse Neighbor Discovery Solicitation Message";
1592 *optional = dissect_icmpv6_type141;
1593 return;
1594 case 142:
1595 *type = "Inverse Neighbor Discovery Advertisement Message";
1596 *optional = dissect_icmpv6_type142;
1597 return;
1598 case 143:
1599 *type = "Multicast Listener Report v2";
1600 *optional = dissect_icmpv6_type143;
1601 return;
1602 case 144:
1603 *type = "Home Agent Address Discovery Request Message";
1604 *optional = dissect_icmpv6_type144;
1605 return;
1606 case 145:
1607 *type = "Home Agent Address Discovery Reply Message";
1608 *optional = dissect_icmpv6_type145;
1609 return;
1610 case 146:
1611 *type = "Mobile Prefix Solicitation";
1612 *optional = dissect_icmpv6_type146;
1613 return;
1614 case 147:
1615 *type = "Mobile Prefix Advertisement";
1616 *optional = dissect_icmpv6_type147;
1617 return;
1618 case 148:
1619 *type = "Certification Path Solicitation";
1620 *optional = dissect_icmpv6_type148;
1621 return;
1622 case 149:
1623 *type = "Certification Path Advertisement";
1624 *optional = dissect_icmpv6_type149;
1625 return;
1626 case 150:
1627 *type = "ICMP messages utilized by experimental mobility "
1628 "protocols such as Seamoby";
1629 *optional = dissect_icmpv6_type150;
1630 return;
1631 case 151:
1632 *type = "Multicast Router Advertisement";
1633 *code = "Ad. Interval";
1634 *optional = dissect_icmpv6_type151;
1635 return;
1636 case 152:
1637 *type = "Multicast Router Solicitation";
1638 *code = "Reserved";
1639 *optional = dissect_icmpv6_type152;
1640 return;
1641 case 153:
1642 *type = "Multicast Router Termination";
1643 *code = "Reserved";
1644 *optional = dissect_icmpv6_type153;
1645 return;
1646 case 154:
1647 *type = "FMIPv6 Messages";
1648 *optional = dissect_icmpv6_type154;
1649 return;
1650 case 155:
1651 *type = "RPL Control Message";
1652 if(icmpv6_type_155_codes(icmp->h_code))
1653 *code = icmpv6_type_155_codes(icmp->h_code);
1654 return;
1655 case 200:
1656 *type = "Private experimation";
1657 return;
1658 case 201:
1659 *type = "Private experimation";
1660 return;
1661 case 255:
1662 *type = "Reserved for expansion of ICMPv6 error messages";
1663 return;
1667 static void icmpv6(struct pkt_buff *pkt)
1669 const char *type = NULL, *code = NULL;
1670 int8_t (*optional)(struct pkt_buff *pkt) = NULL;
1671 struct icmpv6_general_hdr *icmp =
1672 (struct icmpv6_general_hdr *) pkt_pull(pkt, sizeof(*icmp));
1674 if (icmp == NULL)
1675 return;
1677 icmpv6_process(icmp, &type, &code, &optional);
1679 tprintf(" [ ICMPv6 ");
1680 tprintf("%s (%u), ", type, icmp->h_type);
1681 tprintf("%s (%u), ", code, icmp->h_code);
1682 tprintf("Chks (0x%x)", ntohs(icmp->h_chksum));
1683 if (optional)
1684 if (!((*optional) (pkt)))
1685 tprintf("\n%s%s%s", colorize_start_full(black, red),
1686 "Failed to dissect Message", colorize_end());
1687 tprintf(" ]\n");
1690 static void icmpv6_less(struct pkt_buff *pkt)
1692 struct icmpv6_general_hdr *icmp =
1693 (struct icmpv6_general_hdr *) pkt_pull(pkt, sizeof(*icmp));
1695 if (icmp == NULL)
1696 return;
1698 tprintf(" ICMPv6 Type (%u) Code (%u)", icmp->h_type, icmp->h_code);
1701 struct protocol icmpv6_ops = {
1702 .key = 0x3A,
1703 .print_full = icmpv6,
1704 .print_less = icmpv6_less,