proto_icmpv6.h: upgrading message detection
[netsniff-ng.git] / src / proto_icmpv6.h
blobc4a3441e0681c06e87cf6d7f3ffbd39fef510dc3
1 /*
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
8 * RFC4286
9 */
11 #ifndef PROTO_ICMPV6_H
12 #define PROTO_ICMPV6_H
14 #include <stdio.h>
15 #include <stdint.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
19 #include "built_in.h"
20 #include "proto_struct.h"
21 #include "dissector_eth.h"
22 #include "pkt_buff.h"
23 #include "built_in.h"
25 struct icmpv6_general_hdr {
26 uint8_t h_type;
27 uint8_t h_code;
28 uint16_t h_chksum;
29 } __packed;
31 /* for type 0x01 and 0x03 */
32 struct icmpv6_type_1_3 {
33 uint32_t unused;
34 uint8_t invoking_pkt[0];
35 } __packed;
37 struct icmpv6_type_2 {
38 uint32_t MTU;
39 uint8_t invoking_pkt[0];
40 } __packed;
42 struct icmpv6_type_4 {
43 uint32_t pointer;
44 uint8_t invoking_pkt[0];
45 } __packed;
47 struct icmpv6_type_128_129 {
48 uint16_t id;
49 uint16_t sn;
50 uint8_t data[0];
51 } __packed;
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",
58 "Port 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));
69 if (icmp_1 == NULL)
70 return;
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));
81 if (icmp_2 == NULL)
82 return;
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));
98 if (icmp_3 == NULL)
99 return;
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));
116 if (icmp_4 == NULL)
117 return;
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)
130 return;
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)
144 return;
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,
154 char **code,
155 void (**optional)(struct pkt_buff *pkt))
157 *type = "Unknown Type";
158 *code = "Unknown Code";
160 switch (icmp->h_type) {
161 case 1:
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;
166 return;
167 case 2:
168 *type = "Packet Too Big";
169 *optional = dissect_icmpv6_type2;
170 return;
171 case 3:
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;
176 return;
177 case 4:
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;
182 return;
183 case 100:
184 *type = "Private experimation";
185 return;
186 case 101:
187 *type = "Private experimation";
188 return;
189 case 127:
190 *type = "Reserved for expansion of ICMPv6 error messages";
191 return;
192 case 128:
193 *type = "Echo Request";
194 *optional = dissect_icmpv6_type128;
195 return;
196 case 129:
197 *type = "Echo Reply";
198 *optional = dissect_icmpv6_type129;
199 return;
200 case 130:
201 *type = "Multicast Listener Query";
202 return;
203 case 131:
204 *type = "Multicast Listener Report";
205 return;
206 case 132:
207 *type = "Multicast Listener Done";
208 return;
209 case 133:
210 *type = "Router Solicitation";
211 return;
212 case 134:
213 *type = "Router Advertisement";
214 return;
215 case 135:
216 *type = "Neighbor Solicitation";
217 return;
218 case 136:
219 *type = "Neighbor Advertisement";
220 return;
221 case 137:
222 *type = "Redirect Message";
223 return;
224 case 138:
225 *type = "Router Renumbering";
226 return;
227 case 139:
228 *type = "ICMP Node Information Query";
229 return;
230 case 140:
231 *type = "ICMP Node Information Response";
232 return;
233 case 141:
234 *type = "Inverse Neighbor Discovery Solicitation Message";
235 return;
236 case 142:
237 *type = "Inverse Neighbor Discovery Advertisement Message";
238 return;
239 case 143:
240 *type = "Multicast Listener Report v2";
241 return;
242 case 144:
243 *type = "Home Agent Address Discovery Request Message";
244 return;
245 case 145:
246 *type = "Home Agent Address Discovery Reply Message";
247 return;
248 case 146:
249 *type = "Mobile Prefix Solicitation";
250 return;
251 case 147:
252 *type = "Mobile Prefix Advertisement";
253 return;
254 case 148:
255 *type = "Certification Path Solicitation";
256 return;
257 case 149:
258 *type = "Certification Path Advertisement";
259 return;
260 case 150:
261 *type = "ICMP messages utilized by experimental mobility "
262 "protocols such as Seamoby";
263 return;
264 case 151:
265 *type = "Multicast Router Advertisement";
266 return;
267 case 152:
268 *type = "Multicast Router Solicitation";
269 return;
270 case 153:
271 *type = "Multicast Router Termination";
272 return;
273 case 155:
274 *type = "RPL Control Message";
275 return;
276 case 200:
277 *type = "Private experimation";
278 return;
279 case 201:
280 *type = "Private experimation";
281 return;
282 case 255:
283 *type = "Reserved for expansion of ICMPv6 error messages";
284 return;
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));
295 if (icmp == NULL)
296 return;
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));
304 if (optional)
305 (*optional) (pkt);
306 tprintf(" ]\n\n");
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));
314 if (icmp == NULL)
315 return;
317 tprintf(" ICMPv6 Type (%u) Code (%u)", icmp->h_type, icmp->h_code);
320 struct protocol icmpv6_ops = {
321 .key = 0x3A,
322 .print_full = icmpv6,
323 .print_less = icmpv6_less,
326 #endif /* PROTO_ICMPV6_H */