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 struct icmpv6_general_hdr
{
31 /* for type 0x01 and 0x03 */
32 struct icmpv6_type_1_3
{
34 uint8_t invoking_pkt
[0];
37 struct icmpv6_type_2
{
39 uint8_t invoking_pkt
[0];
42 struct icmpv6_type_4
{
44 uint8_t invoking_pkt
[0];
47 struct icmpv6_type_128_129
{
54 struct icmpv6_type_130_131_132
{
57 struct in6_addr ipv6_addr
;
61 struct icmpv6_type_130_mldv2
{
65 struct in6_addr ipv6_addr
[0];
68 /* Neighbor Discovery msg */
69 struct icmpv6_type_133
{
74 struct icmpv6_type_134
{
75 uint8_t cur_hop_limit
;
77 uint16_t router_lifetime
;
78 uint32_t reachable_time
;
79 uint32_t retrans_timer
;
83 struct icmpv6_type_135
{
85 struct in6_addr ipv6_addr
;
89 struct icmpv6_type_136
{
91 struct in6_addr ipv6_addr
;
95 struct icmpv6_type_137
{
97 struct in6_addr ipv6_targ_addr
;
98 struct in6_addr ipv6_dest_addr
;
102 struct icmpv6_neighb_disc_ops_general
{
108 struct icmpv6_neighb_disc_ops_type_1_2
{
109 uint8_t link_lay_addr
[0];
112 struct icmpv6_neighb_disc_ops_type_3
{
115 uint32_t valid_lifetime
;
116 uint32_t preferred_lifetime
;
118 struct in6_addr prefix
;
121 struct icmpv6_neighb_disc_ops_type_4
{
124 uint8_t ip_hdr_data
[0];
127 struct icmpv6_neighb_disc_ops_type_5
{
131 /* end Neighbor Discovery msg */
133 static inline void print_ipv6_addr_list(struct pkt_buff
*pkt
, uint8_t nr_addr
)
135 char address
[INET6_ADDRSTRLEN
];
136 struct in6_addr
*addr
;
139 addr
= (struct in6_addr
*) pkt_pull(pkt
, sizeof(*addr
));
143 tprintf("\n\t Address: %s",
144 inet_ntop(AF_INET6
, addr
, address
,
149 static char *icmpv6_type_1_codes
[] = {
150 "No route to destination",
151 "Communication with destination administratively prohibited",
152 "Beyond scope of source address",
153 "Address unreachable",
155 "Source address failed ingress/egress policy",
156 "Reject route to destination",
157 "Error in Source Routing Header",
160 static inline void dissect_icmpv6_type1(struct pkt_buff
*pkt
)
162 struct icmpv6_type_1_3
*icmp_1
;
164 icmp_1
= (struct icmpv6_type_1_3
*) pkt_pull(pkt
,sizeof(*icmp_1
));
168 tprintf(", Unused (0x%x)",ntohl(icmp_1
->unused
));
169 tprintf(" Payload include as much of invoking packet");
172 static inline void dissect_icmpv6_type2(struct pkt_buff
*pkt
)
174 struct icmpv6_type_2
*icmp_2
;
176 icmp_2
= (struct icmpv6_type_2
*) pkt_pull(pkt
,sizeof(*icmp_2
));
180 tprintf(", MTU (0x%x)",ntohl(icmp_2
->MTU
));
181 tprintf(" Payload include as much of invoking packet");
184 static char *icmpv6_type_3_codes
[] = {
185 "Hop limit exceeded in transit",
186 "Fragment reassembly time exceeded",
189 static inline void dissect_icmpv6_type3(struct pkt_buff
*pkt
)
191 struct icmpv6_type_1_3
*icmp_3
;
193 icmp_3
= (struct icmpv6_type_1_3
*) pkt_pull(pkt
,sizeof(*icmp_3
));
197 tprintf(", Unused (0x%x)",ntohl(icmp_3
->unused
));
198 tprintf(" Payload include as much of invoking packet");
201 static char *icmpv6_type_4_codes
[] = {
202 "Erroneous header field encountered",
203 "Unrecognized Next Header type encountered",
204 "Unrecognized IPv6 option encountered",
207 static inline void dissect_icmpv6_type4(struct pkt_buff
*pkt
)
209 struct icmpv6_type_4
*icmp_4
;
211 icmp_4
= (struct icmpv6_type_4
*) pkt_pull(pkt
,sizeof(*icmp_4
));
215 tprintf(", Pointer (0x%x)",ntohl(icmp_4
->pointer
));
216 tprintf(" Payload include as much of invoking packet");
219 static inline void dissect_icmpv6_type128(struct pkt_buff
*pkt
)
221 struct icmpv6_type_128_129
*icmp_128
;
223 icmp_128
= (struct icmpv6_type_128_129
*)
224 pkt_pull(pkt
,sizeof(*icmp_128
));
225 if (icmp_128
== NULL
)
228 tprintf(", ID (0x%x)",ntohs(icmp_128
->id
));
229 tprintf(", Seq. Nr. (%u)",ntohs(icmp_128
->sn
));
230 tprintf(" Payload include Data");
233 static inline void dissect_icmpv6_type129(struct pkt_buff
*pkt
)
235 struct icmpv6_type_128_129
*icmp_129
;
237 icmp_129
= (struct icmpv6_type_128_129
*)
238 pkt_pull(pkt
,sizeof(*icmp_129
));
239 if (icmp_129
== NULL
)
242 tprintf(", ID (0x%x)",ntohs(icmp_129
->id
));
243 tprintf(", Seq. Nr. (%u)",ntohs(icmp_129
->sn
));
244 tprintf(" Payload include Data");
247 static inline void dissect_icmpv6_type130(struct pkt_buff
*pkt
)
249 char address
[INET6_ADDRSTRLEN
];
250 uint16_t nr_src
, maxrespdel
;
251 uint8_t switch_mldv2
= 0;
252 struct icmpv6_type_130_131_132
*icmp_130
;
254 icmp_130
= (struct icmpv6_type_130_131_132
*)
255 pkt_pull(pkt
,sizeof(*icmp_130
));
256 if (icmp_130
== NULL
)
258 maxrespdel
= ntohs(icmp_130
->maxrespdel
);
260 if(pkt_len(pkt
) >= sizeof(struct icmpv6_type_130_mldv2
))
264 tprintf(", Max Resp Delay (%ums)", maxrespdel
>> 15 ?
265 (((maxrespdel
& 0xFFF) | 0x1000) <<
266 (((maxrespdel
>> 12) & 0x3) + 3)) : maxrespdel
);
268 tprintf(", Max Resp Delay (%ums)",maxrespdel
);
269 tprintf(", Res (0x%x)",ntohs(icmp_130
->res
));
270 tprintf(", Address: %s",
271 inet_ntop(AF_INET6
, &icmp_130
->ipv6_addr
,
272 address
, sizeof(address
)));
275 struct icmpv6_type_130_mldv2
*icmp_130_mldv2
;
277 icmp_130_mldv2
= (struct icmpv6_type_130_mldv2
*)
278 pkt_pull(pkt
,sizeof(*icmp_130_mldv2
));
279 if (icmp_130_mldv2
== NULL
)
282 nr_src
= ntohs(icmp_130_mldv2
->nr_src
);
284 tprintf(", Resv (0x%x)",icmp_130_mldv2
->resv_S_QRV
>> 4);
285 tprintf(", S (%u)",(icmp_130_mldv2
->resv_S_QRV
>> 3) & 0x1);
286 tprintf(", QRV (0x%x)",icmp_130_mldv2
->resv_S_QRV
& 0x3);
287 tprintf(", QQIC (%u)",icmp_130_mldv2
->QQIC
);
288 tprintf(", Nr Src (0x%x)",nr_src
);
290 print_ipv6_addr_list(pkt
, nr_src
);
294 static inline void dissect_icmpv6_type131(struct pkt_buff
*pkt
)
296 char address
[INET6_ADDRSTRLEN
];
297 struct icmpv6_type_130_131_132
*icmp_131
;
299 icmp_131
= (struct icmpv6_type_130_131_132
*)
300 pkt_pull(pkt
,sizeof(*icmp_131
));
301 if (icmp_131
== NULL
)
304 tprintf(", Max Resp Delay (%ums)",ntohs(icmp_131
->maxrespdel
));
305 tprintf(", Res (0x%x)",ntohs(icmp_131
->res
));
306 tprintf(", Address: %s",
307 inet_ntop(AF_INET6
, &icmp_131
->ipv6_addr
,
308 address
, sizeof(address
)));
311 static inline void dissect_icmpv6_type132(struct pkt_buff
*pkt
)
313 dissect_icmpv6_type131(pkt
);
316 static char *icmpv6_neighb_disc_ops
[] = {
317 "Source Link-Layer Address",
318 "Target Link-Layer Address",
319 "Prefix Information",
324 static inline void dissect_neighb_disc_ops(struct pkt_buff
*pkt
)
326 // while(pkt_len(pkt)) {
327 // if (icmpv6_code_range_valid(icmp->h_code, icmpv6_type_1_codes))
328 // *ops = icmpv6_type_1_codes[icmp->h_code];
329 // tprintf(", Option(s) recognized");
333 static inline void dissect_icmpv6_type133(struct pkt_buff
*pkt
)
335 struct icmpv6_type_133
*icmp_133
;
337 icmp_133
= (struct icmpv6_type_133
*)
338 pkt_pull(pkt
,sizeof(*icmp_133
));
339 if (icmp_133
== NULL
)
342 tprintf(", Reserved (0x%x)",ntohl(icmp_133
->res
));
344 dissect_neighb_disc_ops(pkt
);
347 static inline void dissect_icmpv6_type134(struct pkt_buff
*pkt
)
349 struct icmpv6_type_134
*icmp_134
;
351 icmp_134
= (struct icmpv6_type_134
*)
352 pkt_pull(pkt
,sizeof(*icmp_134
));
353 if (icmp_134
== NULL
)
356 tprintf(", Cur Hop Limit (%u)",icmp_134
->cur_hop_limit
);
357 tprintf(", M (%u) O (%u)",icmp_134
->m_o_res
>> 7,
358 (icmp_134
->m_o_res
>> 6) & 0x1);
359 tprintf(", Router Lifetime (%us)",ntohs(icmp_134
->router_lifetime
));
360 tprintf(", Reachable Time (%ums)",ntohl(icmp_134
->reachable_time
));
361 tprintf(", Retrans Timer (%ums)",ntohl(icmp_134
->retrans_timer
));
363 dissect_neighb_disc_ops(pkt
);
366 static inline void dissect_icmpv6_type135(struct pkt_buff
*pkt
)
368 char address
[INET6_ADDRSTRLEN
];
369 struct icmpv6_type_135
*icmp_135
;
371 icmp_135
= (struct icmpv6_type_135
*)
372 pkt_pull(pkt
,sizeof(*icmp_135
));
373 if (icmp_135
== NULL
)
376 tprintf(", Reserved (0x%x)",ntohl(icmp_135
->res
));
377 tprintf(", Target Address: %s",
378 inet_ntop(AF_INET6
, &icmp_135
->ipv6_addr
,
379 address
, sizeof(address
)));
381 dissect_neighb_disc_ops(pkt
);
384 static inline void dissect_icmpv6_type136(struct pkt_buff
*pkt
)
386 char address
[INET6_ADDRSTRLEN
];
388 struct icmpv6_type_136
*icmp_136
;
390 icmp_136
= (struct icmpv6_type_136
*)
391 pkt_pull(pkt
,sizeof(*icmp_136
));
392 if (icmp_136
== NULL
)
394 r_s_o_res
= ntohl(icmp_136
->r_s_o_res
);
396 tprintf(", R (%u) S (%u) O (%u) Reserved (0x%x)", r_s_o_res
>> 31,
397 (r_s_o_res
>> 30) & 0x1, (r_s_o_res
>> 29) & 0x1,
398 r_s_o_res
& 0x1FFFFFFF);
399 tprintf(", Target Address: %s",
400 inet_ntop(AF_INET6
, &icmp_136
->ipv6_addr
,
401 address
, sizeof(address
)));
403 dissect_neighb_disc_ops(pkt
);
406 static inline void dissect_icmpv6_type137(struct pkt_buff
*pkt
)
408 char address
[INET6_ADDRSTRLEN
];
409 struct icmpv6_type_137
*icmp_137
;
411 icmp_137
= (struct icmpv6_type_137
*)
412 pkt_pull(pkt
,sizeof(*icmp_137
));
413 if (icmp_137
== NULL
)
416 tprintf(", Reserved (0x%x)",icmp_137
->res
);
417 tprintf(", Target Address: %s",
418 inet_ntop(AF_INET6
, &icmp_137
->ipv6_targ_addr
,
419 address
, sizeof(address
)));
420 tprintf(", Dest Address: %s",
421 inet_ntop(AF_INET6
, &icmp_137
->ipv6_dest_addr
,
422 address
, sizeof(address
)));
424 dissect_neighb_disc_ops(pkt
);
427 #define icmpv6_code_range_valid(code, sarr) ((code) < array_size((sarr)))
429 static inline void icmpv6_process(struct icmpv6_general_hdr
*icmp
, char **type
,
431 void (**optional
)(struct pkt_buff
*pkt
))
433 *type
= "Unknown Type";
434 *code
= "Unknown Code";
436 switch (icmp
->h_type
) {
438 *type
= "Destination Unreachable";
439 if (icmpv6_code_range_valid(icmp
->h_code
, icmpv6_type_1_codes
))
440 *code
= icmpv6_type_1_codes
[icmp
->h_code
];
441 *optional
= dissect_icmpv6_type1
;
444 *type
= "Packet Too Big";
445 *optional
= dissect_icmpv6_type2
;
448 *type
= "Time Exceeded";
449 if (icmpv6_code_range_valid(icmp
->h_code
, icmpv6_type_3_codes
))
450 *code
= icmpv6_type_3_codes
[icmp
->h_code
];
451 *optional
= dissect_icmpv6_type3
;
454 *type
= "Parameter Problem";
455 if (icmpv6_code_range_valid(icmp
->h_code
, icmpv6_type_4_codes
))
456 *code
= icmpv6_type_4_codes
[icmp
->h_code
];
457 *optional
= dissect_icmpv6_type4
;
460 *type
= "Private experimation";
463 *type
= "Private experimation";
466 *type
= "Reserved for expansion of ICMPv6 error messages";
469 *type
= "Echo Request";
470 *optional
= dissect_icmpv6_type128
;
473 *type
= "Echo Reply";
474 *optional
= dissect_icmpv6_type129
;
477 *type
= "Multicast Listener Query";
478 *optional
= dissect_icmpv6_type130
;
481 *type
= "Multicast Listener Report";
482 *optional
= dissect_icmpv6_type131
;
485 *type
= "Multicast Listener Done";
486 *optional
= dissect_icmpv6_type132
;
489 *type
= "Router Solicitation";
490 *optional
= dissect_icmpv6_type133
;
493 *type
= "Router Advertisement";
494 *optional
= dissect_icmpv6_type134
;
497 *type
= "Neighbor Solicitation";
498 *optional
= dissect_icmpv6_type135
;
501 *type
= "Neighbor Advertisement";
502 *optional
= dissect_icmpv6_type136
;
505 *type
= "Redirect Message";
506 *optional
= dissect_icmpv6_type137
;
509 *type
= "Router Renumbering";
512 *type
= "ICMP Node Information Query";
515 *type
= "ICMP Node Information Response";
518 *type
= "Inverse Neighbor Discovery Solicitation Message";
521 *type
= "Inverse Neighbor Discovery Advertisement Message";
524 *type
= "Multicast Listener Report v2";
527 *type
= "Home Agent Address Discovery Request Message";
530 *type
= "Home Agent Address Discovery Reply Message";
533 *type
= "Mobile Prefix Solicitation";
536 *type
= "Mobile Prefix Advertisement";
539 *type
= "Certification Path Solicitation";
542 *type
= "Certification Path Advertisement";
545 *type
= "ICMP messages utilized by experimental mobility "
546 "protocols such as Seamoby";
549 *type
= "Multicast Router Advertisement";
552 *type
= "Multicast Router Solicitation";
555 *type
= "Multicast Router Termination";
558 *type
= "RPL Control Message";
561 *type
= "Private experimation";
564 *type
= "Private experimation";
567 *type
= "Reserved for expansion of ICMPv6 error messages";
572 static inline void icmpv6(struct pkt_buff
*pkt
)
574 char *type
= NULL
, *code
= NULL
;
575 void (*optional
)(struct pkt_buff
*pkt
) = NULL
;
576 struct icmpv6_general_hdr
*icmp
=
577 (struct icmpv6_general_hdr
*) pkt_pull(pkt
, sizeof(*icmp
));
582 icmpv6_process(icmp
, &type
, &code
, &optional
);
584 tprintf(" [ ICMPv6 ");
585 tprintf("%s (%u), ", type
, icmp
->h_type
);
586 tprintf("%s (%u), ", code
, icmp
->h_code
);
587 tprintf("Chks (0x%x)", ntohs(icmp
->h_chksum
));
593 static inline void icmpv6_less(struct pkt_buff
*pkt
)
595 struct icmpv6_general_hdr
*icmp
=
596 (struct icmpv6_general_hdr
*) pkt_pull(pkt
, sizeof(*icmp
));
601 tprintf(" ICMPv6 Type (%u) Code (%u)", icmp
->h_type
, icmp
->h_code
);
604 struct protocol icmpv6_ops
= {
606 .print_full
= icmpv6
,
607 .print_less
= icmpv6_less
,
610 #endif /* PROTO_ICMPV6_H */