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
{
53 static char *icmpv6_type_1_codes
[] = {
54 "No route to destination",
55 "Communication with destination administratively prohibited",
56 "Beyond scope of source address",
57 "Address unreachable",
59 "Source address failed ingress/egress policy",
60 "Reject route to destination",
61 "Error in Source Routing Header",
64 static inline void dissect_icmpv6_type1(struct pkt_buff
*pkt
)
66 struct icmpv6_type_1_3
*icmp_1
;
68 icmp_1
= (struct icmpv6_type_1_3
*) pkt_pull(pkt
,sizeof(*icmp_1
));
72 tprintf(", Unused (0x%x)",ntohl(icmp_1
->unused
));
73 tprintf(" Payload include as much of invoking packet");
76 static inline void dissect_icmpv6_type2(struct pkt_buff
*pkt
)
78 struct icmpv6_type_2
*icmp_2
;
80 icmp_2
= (struct icmpv6_type_2
*) pkt_pull(pkt
,sizeof(*icmp_2
));
84 tprintf(", MTU (0x%x)",ntohl(icmp_2
->MTU
));
85 tprintf(" Payload include as much of invoking packet");
88 static char *icmpv6_type_3_codes
[] = {
89 "Hop limit exceeded in transit",
90 "Fragment reassembly time exceeded",
93 static inline void dissect_icmpv6_type3(struct pkt_buff
*pkt
)
95 struct icmpv6_type_1_3
*icmp_3
;
97 icmp_3
= (struct icmpv6_type_1_3
*) pkt_pull(pkt
,sizeof(*icmp_3
));
101 tprintf(", Unused (0x%x)",ntohl(icmp_3
->unused
));
102 tprintf(" Payload include as much of invoking packet");
105 static char *icmpv6_type_4_codes
[] = {
106 "Erroneous header field encountered",
107 "Unrecognized Next Header type encountered",
108 "Unrecognized IPv6 option encountered",
111 static inline void dissect_icmpv6_type4(struct pkt_buff
*pkt
)
113 struct icmpv6_type_4
*icmp_4
;
115 icmp_4
= (struct icmpv6_type_4
*) pkt_pull(pkt
,sizeof(*icmp_4
));
119 tprintf(", Pointer (0x%x)",ntohl(icmp_4
->pointer
));
120 tprintf(" Payload include as much of invoking packet");
123 static inline void dissect_icmpv6_type128(struct pkt_buff
*pkt
)
125 struct icmpv6_type_128_129
*icmp_128
;
127 icmp_128
= (struct icmpv6_type_128_129
*)
128 pkt_pull(pkt
,sizeof(*icmp_128
));
129 if (icmp_128
== NULL
)
132 tprintf(", ID (0x%x)",ntohs(icmp_128
->id
));
133 tprintf(", Seq. Nr. (%u)",ntohs(icmp_128
->sn
));
134 tprintf(" Payload include Data");
137 static inline void dissect_icmpv6_type129(struct pkt_buff
*pkt
)
139 struct icmpv6_type_128_129
*icmp_129
;
141 icmp_129
= (struct icmpv6_type_128_129
*)
142 pkt_pull(pkt
,sizeof(*icmp_129
));
143 if (icmp_129
== NULL
)
146 tprintf(", ID (0x%x)",ntohs(icmp_129
->id
));
147 tprintf(", Seq. Nr. (%u)",ntohs(icmp_129
->sn
));
148 tprintf(" Payload include Data");
151 #define icmpv6_code_range_valid(code, sarr) ((code) < array_size((sarr)))
153 static inline void icmpv6_process(struct icmpv6_general_hdr
*icmp
, char **type
,
155 void (**optional
)(struct pkt_buff
*pkt
))
157 *type
= "Unknown Type";
158 *code
= "Unknown Code";
160 switch (icmp
->h_type
) {
162 *type
= "Destination Unreachable";
163 if (icmpv6_code_range_valid(icmp
->h_code
, icmpv6_type_1_codes
))
164 *code
= icmpv6_type_1_codes
[icmp
->h_code
];
165 *optional
= dissect_icmpv6_type1
;
168 *type
= "Packet Too Big";
169 *optional
= dissect_icmpv6_type2
;
172 *type
= "Time Exceeded";
173 if (icmpv6_code_range_valid(icmp
->h_code
, icmpv6_type_3_codes
))
174 *code
= icmpv6_type_3_codes
[icmp
->h_code
];
175 *optional
= dissect_icmpv6_type3
;
178 *type
= "Parameter Problem";
179 if (icmpv6_code_range_valid(icmp
->h_code
, icmpv6_type_4_codes
))
180 *code
= icmpv6_type_4_codes
[icmp
->h_code
];
181 *optional
= dissect_icmpv6_type4
;
184 *type
= "Private experimation";
187 *type
= "Private experimation";
190 *type
= "Reserved for expansion of ICMPv6 error messages";
193 *type
= "Echo Request";
194 *optional
= dissect_icmpv6_type128
;
197 *type
= "Echo Reply";
198 *optional
= dissect_icmpv6_type129
;
201 *type
= "Multicast Listener Query";
204 *type
= "Multicast Listener Report";
207 *type
= "Multicast Listener Done";
210 *type
= "Router Solicitation";
213 *type
= "Router Advertisement";
216 *type
= "Neighbor Solicitation";
219 *type
= "Neighbor Advertisement";
222 *type
= "Redirect Message";
225 *type
= "Router Renumbering";
228 *type
= "ICMP Node Information Query";
231 *type
= "ICMP Node Information Response";
234 *type
= "Inverse Neighbor Discovery Solicitation Message";
237 *type
= "Inverse Neighbor Discovery Advertisement Message";
240 *type
= "Multicast Listener Report v2";
243 *type
= "Home Agent Address Discovery Request Message";
246 *type
= "Home Agent Address Discovery Reply Message";
249 *type
= "Mobile Prefix Solicitation";
252 *type
= "Mobile Prefix Advertisement";
255 *type
= "Certification Path Solicitation";
258 *type
= "Certification Path Advertisement";
261 *type
= "ICMP messages utilized by experimental mobility "
262 "protocols such as Seamoby";
265 *type
= "Multicast Router Advertisement";
268 *type
= "Multicast Router Solicitation";
271 *type
= "Multicast Router Termination";
274 *type
= "RPL Control Message";
277 *type
= "Private experimation";
280 *type
= "Private experimation";
283 *type
= "Reserved for expansion of ICMPv6 error messages";
288 static inline void icmpv6(struct pkt_buff
*pkt
)
290 char *type
= NULL
, *code
= NULL
;
291 void (*optional
)(struct pkt_buff
*pkt
) = NULL
;
292 struct icmpv6_general_hdr
*icmp
=
293 (struct icmpv6_general_hdr
*) pkt_pull(pkt
, sizeof(*icmp
));
298 icmpv6_process(icmp
, &type
, &code
, &optional
);
300 tprintf(" [ ICMPv6 ");
301 tprintf("%s (%u), ", type
, icmp
->h_type
);
302 tprintf("%s (%u), ", code
, icmp
->h_code
);
303 tprintf("Chks (0x%x)", ntohs(icmp
->h_chksum
));
309 static inline void icmpv6_less(struct pkt_buff
*pkt
)
311 struct icmpv6_general_hdr
*icmp
=
312 (struct icmpv6_general_hdr
*) pkt_pull(pkt
, sizeof(*icmp
));
317 tprintf(" ICMPv6 Type (%u) Code (%u)", icmp
->h_type
, icmp
->h_code
);
320 struct protocol icmpv6_ops
= {
322 .print_full
= icmpv6
,
323 .print_less
= icmpv6_less
,
326 #endif /* PROTO_ICMPV6_H */