2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2012 Markus Amend <markus@netsniff-ng.org>
4 * Subject to the GPL, version 2.
6 * ICMPv6 described in RFC4443, RFC2710, RFC4861, RFC2894,
7 * RFC4620, RFC3122, RFC3810, RFC3775, RFC3971, RFC4065
11 #ifndef PROTO_ICMPV6_H
12 #define PROTO_ICMPV6_H
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
20 #include "proto_struct.h"
21 #include "dissector_eth.h"
25 #define icmpv6_code_range_valid(code, sarr) ((code) < array_size((sarr)))
27 struct icmpv6_general_hdr
{
33 /* for type 0x01 and 0x03 */
34 struct icmpv6_type_1_3
{
36 uint8_t invoking_pkt
[0];
39 struct icmpv6_type_2
{
41 uint8_t invoking_pkt
[0];
44 struct icmpv6_type_4
{
46 uint8_t invoking_pkt
[0];
49 struct icmpv6_type_128_129
{
56 struct icmpv6_type_130_131_132
{
59 struct in6_addr ipv6_addr
;
63 struct icmpv6_type_130_mldv2
{
67 struct in6_addr ipv6_addr
[0];
70 /* Neighbor Discovery msg */
71 struct icmpv6_type_133
{
76 struct icmpv6_type_134
{
77 uint8_t cur_hop_limit
;
79 uint16_t router_lifetime
;
80 uint32_t reachable_time
;
81 uint32_t retrans_timer
;
85 struct icmpv6_type_135
{
87 struct in6_addr ipv6_addr
;
91 struct icmpv6_type_136
{
93 struct in6_addr ipv6_addr
;
97 struct icmpv6_type_137
{
99 struct in6_addr ipv6_targ_addr
;
100 struct in6_addr ipv6_dest_addr
;
104 struct icmpv6_neighb_disc_ops_general
{
110 struct icmpv6_neighb_disc_ops_type_1_2
{
111 uint8_t link_lay_addr
[0];
114 struct icmpv6_neighb_disc_ops_type_3
{
117 uint32_t valid_lifetime
;
118 uint32_t preferred_lifetime
;
120 struct in6_addr prefix
;
123 struct icmpv6_neighb_disc_ops_type_4
{
126 uint8_t ip_hdr_data
[0];
129 struct icmpv6_neighb_disc_ops_type_5
{
133 /* end Neighbor Discovery msg */
135 struct icmpv6_type_138
{
144 static inline void print_ipv6_addr_list(struct pkt_buff
*pkt
, uint8_t nr_addr
)
146 char address
[INET6_ADDRSTRLEN
];
147 struct in6_addr
*addr
;
150 addr
= (struct in6_addr
*) pkt_pull(pkt
, sizeof(*addr
));
154 tprintf("\n\t Address: %s",
155 inet_ntop(AF_INET6
, addr
, address
,
160 static char *icmpv6_type_1_codes
[] = {
161 "No route to destination",
162 "Communication with destination administratively prohibited",
163 "Beyond scope of source address",
164 "Address unreachable",
166 "Source address failed ingress/egress policy",
167 "Reject route to destination",
168 "Error in Source Routing Header",
171 static inline void dissect_icmpv6_type1(struct pkt_buff
*pkt
)
173 struct icmpv6_type_1_3
*icmp_1
;
175 icmp_1
= (struct icmpv6_type_1_3
*) pkt_pull(pkt
,sizeof(*icmp_1
));
179 tprintf(", Unused (0x%x)",ntohl(icmp_1
->unused
));
180 tprintf(" Payload include as much of invoking packet");
183 static inline void dissect_icmpv6_type2(struct pkt_buff
*pkt
)
185 struct icmpv6_type_2
*icmp_2
;
187 icmp_2
= (struct icmpv6_type_2
*) pkt_pull(pkt
,sizeof(*icmp_2
));
191 tprintf(", MTU (0x%x)",ntohl(icmp_2
->MTU
));
192 tprintf(" Payload include as much of invoking packet");
195 static char *icmpv6_type_3_codes
[] = {
196 "Hop limit exceeded in transit",
197 "Fragment reassembly time exceeded",
200 static inline void dissect_icmpv6_type3(struct pkt_buff
*pkt
)
202 struct icmpv6_type_1_3
*icmp_3
;
204 icmp_3
= (struct icmpv6_type_1_3
*) pkt_pull(pkt
,sizeof(*icmp_3
));
208 tprintf(", Unused (0x%x)",ntohl(icmp_3
->unused
));
209 tprintf(" Payload include as much of invoking packet");
212 static char *icmpv6_type_4_codes
[] = {
213 "Erroneous header field encountered",
214 "Unrecognized Next Header type encountered",
215 "Unrecognized IPv6 option encountered",
218 static inline void dissect_icmpv6_type4(struct pkt_buff
*pkt
)
220 struct icmpv6_type_4
*icmp_4
;
222 icmp_4
= (struct icmpv6_type_4
*) pkt_pull(pkt
,sizeof(*icmp_4
));
226 tprintf(", Pointer (0x%x)",ntohl(icmp_4
->pointer
));
227 tprintf(" Payload include as much of invoking packet");
230 static inline void dissect_icmpv6_type128(struct pkt_buff
*pkt
)
232 struct icmpv6_type_128_129
*icmp_128
;
234 icmp_128
= (struct icmpv6_type_128_129
*)
235 pkt_pull(pkt
,sizeof(*icmp_128
));
236 if (icmp_128
== NULL
)
239 tprintf(", ID (0x%x)",ntohs(icmp_128
->id
));
240 tprintf(", Seq. Nr. (%u)",ntohs(icmp_128
->sn
));
241 tprintf(" Payload include Data");
244 static inline void dissect_icmpv6_type129(struct pkt_buff
*pkt
)
246 struct icmpv6_type_128_129
*icmp_129
;
248 icmp_129
= (struct icmpv6_type_128_129
*)
249 pkt_pull(pkt
,sizeof(*icmp_129
));
250 if (icmp_129
== NULL
)
253 tprintf(", ID (0x%x)",ntohs(icmp_129
->id
));
254 tprintf(", Seq. Nr. (%u)",ntohs(icmp_129
->sn
));
255 tprintf(" Payload include Data");
258 static inline void dissect_icmpv6_type130(struct pkt_buff
*pkt
)
260 char address
[INET6_ADDRSTRLEN
];
261 uint16_t nr_src
, maxrespdel
;
262 uint8_t switch_mldv2
= 0;
263 struct icmpv6_type_130_131_132
*icmp_130
;
265 icmp_130
= (struct icmpv6_type_130_131_132
*)
266 pkt_pull(pkt
,sizeof(*icmp_130
));
267 if (icmp_130
== NULL
)
269 maxrespdel
= ntohs(icmp_130
->maxrespdel
);
271 if(pkt_len(pkt
) >= sizeof(struct icmpv6_type_130_mldv2
))
275 tprintf(", Max Resp Delay (%ums)", maxrespdel
>> 15 ?
276 (((maxrespdel
& 0xFFF) | 0x1000) <<
277 (((maxrespdel
>> 12) & 0x3) + 3)) : maxrespdel
);
279 tprintf(", Max Resp Delay (%ums)",maxrespdel
);
280 tprintf(", Res (0x%x)",ntohs(icmp_130
->res
));
281 tprintf(", Address: %s",
282 inet_ntop(AF_INET6
, &icmp_130
->ipv6_addr
,
283 address
, sizeof(address
)));
286 struct icmpv6_type_130_mldv2
*icmp_130_mldv2
;
288 icmp_130_mldv2
= (struct icmpv6_type_130_mldv2
*)
289 pkt_pull(pkt
,sizeof(*icmp_130_mldv2
));
290 if (icmp_130_mldv2
== NULL
)
293 nr_src
= ntohs(icmp_130_mldv2
->nr_src
);
295 tprintf(", Resv (0x%x)",icmp_130_mldv2
->resv_S_QRV
>> 4);
296 tprintf(", S (%u)",(icmp_130_mldv2
->resv_S_QRV
>> 3) & 0x1);
297 tprintf(", QRV (0x%x)",icmp_130_mldv2
->resv_S_QRV
& 0x3);
298 tprintf(", QQIC (%u)",icmp_130_mldv2
->QQIC
);
299 tprintf(", Nr Src (0x%x)",nr_src
);
301 print_ipv6_addr_list(pkt
, nr_src
);
305 static inline void dissect_icmpv6_type131(struct pkt_buff
*pkt
)
307 char address
[INET6_ADDRSTRLEN
];
308 struct icmpv6_type_130_131_132
*icmp_131
;
310 icmp_131
= (struct icmpv6_type_130_131_132
*)
311 pkt_pull(pkt
,sizeof(*icmp_131
));
312 if (icmp_131
== NULL
)
315 tprintf(", Max Resp Delay (%ums)",ntohs(icmp_131
->maxrespdel
));
316 tprintf(", Res (0x%x)",ntohs(icmp_131
->res
));
317 tprintf(", Address: %s",
318 inet_ntop(AF_INET6
, &icmp_131
->ipv6_addr
,
319 address
, sizeof(address
)));
322 static inline void dissect_icmpv6_type132(struct pkt_buff
*pkt
)
324 dissect_icmpv6_type131(pkt
);
327 static inline void dissect_neighb_disc_ops_1(struct pkt_buff
*pkt
, size_t len
)
329 struct icmpv6_neighb_disc_ops_type_1_2
*icmp_neighb_disc_1
;
331 icmp_neighb_disc_1
= (struct icmpv6_neighb_disc_ops_type_1_2
*)
332 pkt_pull(pkt
,sizeof(*icmp_neighb_disc_1
));
333 if (icmp_neighb_disc_1
== NULL
)
336 tprintf("Address 0x");
339 tprintf("%x", *pkt_pull(pkt
,1));
343 static inline void dissect_neighb_disc_ops_2(struct pkt_buff
*pkt
, size_t len
)
345 dissect_neighb_disc_ops_1(pkt
, len
);
348 static inline void dissect_neighb_disc_ops_3(struct pkt_buff
*pkt
, size_t len
)
350 char address
[INET6_ADDRSTRLEN
];
351 struct icmpv6_neighb_disc_ops_type_3
*icmp_neighb_disc_3
;
353 icmp_neighb_disc_3
= (struct icmpv6_neighb_disc_ops_type_3
*)
354 pkt_pull(pkt
,sizeof(*icmp_neighb_disc_3
));
355 if (icmp_neighb_disc_3
== NULL
)
358 tprintf("Prefix Len (%u) ",icmp_neighb_disc_3
->prefix_len
);
359 tprintf("L (%u) A (%u) Res1 (0x%x) ",icmp_neighb_disc_3
->l_a_res1
>> 7,
360 (icmp_neighb_disc_3
->l_a_res1
>> 7) & 0x1,
361 icmp_neighb_disc_3
->l_a_res1
& 0x3F);
362 tprintf("Valid Lifetime (%us) ",
363 ntohl(icmp_neighb_disc_3
->valid_lifetime
));
364 tprintf("Preferred Lifetime (%us) ",
365 ntohl(icmp_neighb_disc_3
->preferred_lifetime
));
366 tprintf("Reserved2 (0x%x) ",
367 ntohl(icmp_neighb_disc_3
->res2
));
368 tprintf(", Prefix: %s ",
369 inet_ntop(AF_INET6
,&icmp_neighb_disc_3
->prefix
,
370 address
, sizeof(address
)));
373 static inline void dissect_neighb_disc_ops_4(struct pkt_buff
*pkt
, size_t len
)
375 struct icmpv6_neighb_disc_ops_type_4
*icmp_neighb_disc_4
;
377 icmp_neighb_disc_4
= (struct icmpv6_neighb_disc_ops_type_4
*)
378 pkt_pull(pkt
,sizeof(*icmp_neighb_disc_4
));
379 if (icmp_neighb_disc_4
== NULL
)
382 tprintf("Reserved 1 (0x%x) ", ntohs(icmp_neighb_disc_4
->res1
));
383 tprintf("Reserved 2 (0x%x) ", ntohl(icmp_neighb_disc_4
->res2
));
384 tprintf("IP header + data ");
387 tprintf("%x", *pkt_pull(pkt
,1));
391 static inline void dissect_neighb_disc_ops_5(struct pkt_buff
*pkt
, size_t len
)
393 struct icmpv6_neighb_disc_ops_type_5
*icmp_neighb_disc_5
;
395 icmp_neighb_disc_5
= (struct icmpv6_neighb_disc_ops_type_5
*)
396 pkt_pull(pkt
,sizeof(*icmp_neighb_disc_5
));
397 if (icmp_neighb_disc_5
== NULL
)
400 tprintf("Reserved (0x%x) ", ntohs(icmp_neighb_disc_5
->res1
));
401 tprintf("MTU (%u)", ntohl(icmp_neighb_disc_5
->MTU
));
404 static char *icmpv6_neighb_disc_ops
[] = {
405 "Source Link-Layer Address",
406 "Target Link-Layer Address",
407 "Prefix Information",
412 static inline void dissect_neighb_disc_ops(struct pkt_buff
*pkt
)
414 size_t ops_total_len
, ops_payl_len
;
415 struct icmpv6_neighb_disc_ops_general
*icmp_neighb_disc
;
417 while(pkt_len(pkt
)) {
418 icmp_neighb_disc
= (struct icmpv6_neighb_disc_ops_general
*)
419 pkt_pull(pkt
,sizeof(*icmp_neighb_disc
));
420 if (icmp_neighb_disc
== NULL
)
423 ops_total_len
= icmp_neighb_disc
->len
* 8;
424 ops_payl_len
= ops_total_len
- sizeof(*icmp_neighb_disc
);
426 tprintf("\n\tOption %s (%u) ",
427 icmpv6_code_range_valid(icmp_neighb_disc
->type
- 1,
428 icmpv6_neighb_disc_ops
) ?
429 icmpv6_neighb_disc_ops
[icmp_neighb_disc
->type
- 1]
430 : "Type Unknown", icmp_neighb_disc
->type
);
431 tprintf("Length (%u, %u bytes) ", icmp_neighb_disc
->len
,
434 switch (icmp_neighb_disc
->type
) {
436 dissect_neighb_disc_ops_1(pkt
, ops_payl_len
);
439 dissect_neighb_disc_ops_2(pkt
, ops_payl_len
);
442 dissect_neighb_disc_ops_3(pkt
, ops_payl_len
);
445 dissect_neighb_disc_ops_4(pkt
, ops_payl_len
);
448 dissect_neighb_disc_ops_5(pkt
, ops_payl_len
);
451 pkt_pull(pkt
, ops_payl_len
);
456 static inline void dissect_icmpv6_type133(struct pkt_buff
*pkt
)
458 struct icmpv6_type_133
*icmp_133
;
460 icmp_133
= (struct icmpv6_type_133
*)
461 pkt_pull(pkt
,sizeof(*icmp_133
));
462 if (icmp_133
== NULL
)
465 tprintf(", Reserved (0x%x)",ntohl(icmp_133
->res
));
467 dissect_neighb_disc_ops(pkt
);
470 static inline void dissect_icmpv6_type134(struct pkt_buff
*pkt
)
472 struct icmpv6_type_134
*icmp_134
;
474 icmp_134
= (struct icmpv6_type_134
*)
475 pkt_pull(pkt
,sizeof(*icmp_134
));
476 if (icmp_134
== NULL
)
479 tprintf(", Cur Hop Limit (%u)",icmp_134
->cur_hop_limit
);
480 tprintf(", M (%u) O (%u)",icmp_134
->m_o_res
>> 7,
481 (icmp_134
->m_o_res
>> 6) & 0x1);
482 tprintf(", Router Lifetime (%us)",ntohs(icmp_134
->router_lifetime
));
483 tprintf(", Reachable Time (%ums)",ntohl(icmp_134
->reachable_time
));
484 tprintf(", Retrans Timer (%ums)",ntohl(icmp_134
->retrans_timer
));
486 dissect_neighb_disc_ops(pkt
);
489 static inline void dissect_icmpv6_type135(struct pkt_buff
*pkt
)
491 char address
[INET6_ADDRSTRLEN
];
492 struct icmpv6_type_135
*icmp_135
;
494 icmp_135
= (struct icmpv6_type_135
*)
495 pkt_pull(pkt
,sizeof(*icmp_135
));
496 if (icmp_135
== NULL
)
499 tprintf(", Reserved (0x%x)",ntohl(icmp_135
->res
));
500 tprintf(", Target Address: %s",
501 inet_ntop(AF_INET6
, &icmp_135
->ipv6_addr
,
502 address
, sizeof(address
)));
504 dissect_neighb_disc_ops(pkt
);
507 static inline void dissect_icmpv6_type136(struct pkt_buff
*pkt
)
509 char address
[INET6_ADDRSTRLEN
];
511 struct icmpv6_type_136
*icmp_136
;
513 icmp_136
= (struct icmpv6_type_136
*)
514 pkt_pull(pkt
,sizeof(*icmp_136
));
515 if (icmp_136
== NULL
)
517 r_s_o_res
= ntohl(icmp_136
->r_s_o_res
);
519 tprintf(", R (%u) S (%u) O (%u) Reserved (0x%x)", r_s_o_res
>> 31,
520 (r_s_o_res
>> 30) & 0x1, (r_s_o_res
>> 29) & 0x1,
521 r_s_o_res
& 0x1FFFFFFF);
522 tprintf(", Target Address: %s",
523 inet_ntop(AF_INET6
, &icmp_136
->ipv6_addr
,
524 address
, sizeof(address
)));
526 dissect_neighb_disc_ops(pkt
);
529 static inline void dissect_icmpv6_type137(struct pkt_buff
*pkt
)
531 char address
[INET6_ADDRSTRLEN
];
532 struct icmpv6_type_137
*icmp_137
;
534 icmp_137
= (struct icmpv6_type_137
*)
535 pkt_pull(pkt
,sizeof(*icmp_137
));
536 if (icmp_137
== NULL
)
539 tprintf(", Reserved (0x%x)",icmp_137
->res
);
540 tprintf(", Target Address: %s",
541 inet_ntop(AF_INET6
, &icmp_137
->ipv6_targ_addr
,
542 address
, sizeof(address
)));
543 tprintf(", Dest Address: %s",
544 inet_ntop(AF_INET6
, &icmp_137
->ipv6_dest_addr
,
545 address
, sizeof(address
)));
547 dissect_neighb_disc_ops(pkt
);
550 static inline void dissect_icmpv6_rr_body(struct pkt_buff
*pkt
)
553 * Upgrade Dissector for Message Body
554 * from http://tools.ietf.org/html/rfc2894#section-3.2
558 static char *icmpv6_type_138_codes
[] = {
559 "Router Renumbering Command",
560 "Router Renumbering Result",
561 "Sequence Number Reset",
564 static inline void dissect_icmpv6_type138(struct pkt_buff
*pkt
)
566 struct icmpv6_type_138
*icmp_138
;
568 icmp_138
= (struct icmpv6_type_138
*)
569 pkt_pull(pkt
,sizeof(*icmp_138
));
570 if (icmp_138
== NULL
)
573 tprintf(", Chks (0x%x)",icmp_138
->chks
);
575 dissect_icmpv6_rr_body(pkt
);
578 static inline void icmpv6_process(struct icmpv6_general_hdr
*icmp
, char **type
,
580 void (**optional
)(struct pkt_buff
*pkt
))
582 *type
= "Unknown Type";
583 *code
= "Unknown Code";
585 switch (icmp
->h_type
) {
587 *type
= "Destination Unreachable";
588 if (icmpv6_code_range_valid(icmp
->h_code
, icmpv6_type_1_codes
))
589 *code
= icmpv6_type_1_codes
[icmp
->h_code
];
590 *optional
= dissect_icmpv6_type1
;
593 *type
= "Packet Too Big";
594 *optional
= dissect_icmpv6_type2
;
597 *type
= "Time Exceeded";
598 if (icmpv6_code_range_valid(icmp
->h_code
, icmpv6_type_3_codes
))
599 *code
= icmpv6_type_3_codes
[icmp
->h_code
];
600 *optional
= dissect_icmpv6_type3
;
603 *type
= "Parameter Problem";
604 if (icmpv6_code_range_valid(icmp
->h_code
, icmpv6_type_4_codes
))
605 *code
= icmpv6_type_4_codes
[icmp
->h_code
];
606 *optional
= dissect_icmpv6_type4
;
609 *type
= "Private experimation";
612 *type
= "Private experimation";
615 *type
= "Reserved for expansion of ICMPv6 error messages";
618 *type
= "Echo Request";
619 *optional
= dissect_icmpv6_type128
;
622 *type
= "Echo Reply";
623 *optional
= dissect_icmpv6_type129
;
626 *type
= "Multicast Listener Query";
627 *optional
= dissect_icmpv6_type130
;
630 *type
= "Multicast Listener Report";
631 *optional
= dissect_icmpv6_type131
;
634 *type
= "Multicast Listener Done";
635 *optional
= dissect_icmpv6_type132
;
638 *type
= "Router Solicitation";
639 *optional
= dissect_icmpv6_type133
;
642 *type
= "Router Advertisement";
643 *optional
= dissect_icmpv6_type134
;
646 *type
= "Neighbor Solicitation";
647 *optional
= dissect_icmpv6_type135
;
650 *type
= "Neighbor Advertisement";
651 *optional
= dissect_icmpv6_type136
;
654 *type
= "Redirect Message";
655 *optional
= dissect_icmpv6_type137
;
658 *type
= "Router Renumbering";
661 *type
= "ICMP Node Information Query";
664 *type
= "ICMP Node Information Response";
667 *type
= "Inverse Neighbor Discovery Solicitation Message";
670 *type
= "Inverse Neighbor Discovery Advertisement Message";
673 *type
= "Multicast Listener Report v2";
676 *type
= "Home Agent Address Discovery Request Message";
679 *type
= "Home Agent Address Discovery Reply Message";
682 *type
= "Mobile Prefix Solicitation";
685 *type
= "Mobile Prefix Advertisement";
688 *type
= "Certification Path Solicitation";
691 *type
= "Certification Path Advertisement";
694 *type
= "ICMP messages utilized by experimental mobility "
695 "protocols such as Seamoby";
698 *type
= "Multicast Router Advertisement";
701 *type
= "Multicast Router Solicitation";
704 *type
= "Multicast Router Termination";
707 *type
= "RPL Control Message";
710 *type
= "Private experimation";
713 *type
= "Private experimation";
716 *type
= "Reserved for expansion of ICMPv6 error messages";
721 static inline void icmpv6(struct pkt_buff
*pkt
)
723 char *type
= NULL
, *code
= NULL
;
724 void (*optional
)(struct pkt_buff
*pkt
) = NULL
;
725 struct icmpv6_general_hdr
*icmp
=
726 (struct icmpv6_general_hdr
*) pkt_pull(pkt
, sizeof(*icmp
));
731 icmpv6_process(icmp
, &type
, &code
, &optional
);
733 tprintf(" [ ICMPv6 ");
734 tprintf("%s (%u), ", type
, icmp
->h_type
);
735 tprintf("%s (%u), ", code
, icmp
->h_code
);
736 tprintf("Chks (0x%x)", ntohs(icmp
->h_chksum
));
742 static inline void icmpv6_less(struct pkt_buff
*pkt
)
744 struct icmpv6_general_hdr
*icmp
=
745 (struct icmpv6_general_hdr
*) pkt_pull(pkt
, sizeof(*icmp
));
750 tprintf(" ICMPv6 Type (%u) Code (%u)", icmp
->h_type
, icmp
->h_code
);
753 struct protocol icmpv6_ops
= {
755 .print_full
= icmpv6
,
756 .print_less
= icmpv6_less
,
759 #endif /* PROTO_ICMPV6_H */