proto_icmpv6.h:intermediate result
[netsniff-ng.git] / src / proto_icmpv6.h
blobf33ff1eb29759e0a3fa53358afaa3d6df0e2ceb6
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 /* MLDv1 msg */
54 struct icmpv6_type_130_131_132 {
55 uint16_t maxrespdel;
56 uint16_t res;
57 struct in6_addr ipv6_addr;
58 } __packed;
59 /* end MLDv1 msg */
61 struct icmpv6_type_130_mldv2 {
62 uint8_t resv_S_QRV;
63 uint8_t QQIC;
64 uint16_t nr_src;
65 struct in6_addr ipv6_addr[0];
66 } __packed;
68 /* Neighbor Discovery msg */
69 struct icmpv6_type_133 {
70 uint32_t res;
71 uint8_t ops[0];
72 } __packed;
74 struct icmpv6_type_134 {
75 uint8_t cur_hop_limit;
76 uint8_t m_o_res;
77 uint16_t router_lifetime;
78 uint32_t reachable_time;
79 uint32_t retrans_timer;
80 uint8_t ops[0];
81 } __packed;
83 struct icmpv6_type_135 {
84 uint32_t res;
85 struct in6_addr ipv6_addr;
86 uint8_t ops[0];
87 } __packed;
89 struct icmpv6_type_136 {
90 uint32_t r_s_o_res;
91 struct in6_addr ipv6_addr;
92 uint8_t ops[0];
93 } __packed;
95 struct icmpv6_type_137 {
96 uint32_t res;
97 struct in6_addr ipv6_targ_addr;
98 struct in6_addr ipv6_dest_addr;
99 uint8_t ops[0];
100 } __packed;
102 struct icmpv6_neighb_disc_ops_general {
103 uint8_t type;
104 uint8_t length;
105 uint8_t ops[0];
106 } __packed;
108 struct icmpv6_neighb_disc_ops_type_1_2 {
109 uint8_t link_lay_addr[0];
110 } __packed;
112 struct icmpv6_neighb_disc_ops_type_3 {
113 uint8_t prefix_len;
114 uint8_t l_a_res1;
115 uint32_t valid_lifetime;
116 uint32_t preferred_lifetime;
117 uint32_t res2;
118 struct in6_addr prefix;
119 } __packed;
121 struct icmpv6_neighb_disc_ops_type_4 {
122 uint16_t res1;
123 uint32_t res2;
124 uint8_t ip_hdr_data[0];
125 } __packed;
127 struct icmpv6_neighb_disc_ops_type_5 {
128 uint16_t res1;
129 uint32_t MTU;
130 } __packed;
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;
138 while (nr_addr--) {
139 addr = (struct in6_addr *) pkt_pull(pkt, sizeof(*addr));
140 if (addr == NULL)
141 return;
143 tprintf("\n\t Address: %s",
144 inet_ntop(AF_INET6, addr, address,
145 sizeof(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",
154 "Port 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));
165 if (icmp_1 == NULL)
166 return;
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));
177 if (icmp_2 == NULL)
178 return;
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));
194 if (icmp_3 == NULL)
195 return;
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));
212 if (icmp_4 == NULL)
213 return;
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)
226 return;
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)
240 return;
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)
257 return;
258 maxrespdel = ntohs(icmp_130->maxrespdel);
260 if(pkt_len(pkt) >= sizeof(struct icmpv6_type_130_mldv2))
261 switch_mldv2 = 1;
263 if(switch_mldv2)
264 tprintf(", Max Resp Delay (%ums)", maxrespdel >> 15 ?
265 (((maxrespdel & 0xFFF) | 0x1000) <<
266 (((maxrespdel >> 12) & 0x3) + 3)) : maxrespdel);
267 else
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)));
274 if(switch_mldv2) {
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)
280 return;
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)
302 return;
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",
320 "Redirected Header",
321 "MTU",
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");
330 // }
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)
340 return;
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)
354 return;
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)
374 return;
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];
387 uint32_t r_s_o_res;
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)
393 return;
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)
414 return;
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,
430 char **code,
431 void (**optional)(struct pkt_buff *pkt))
433 *type = "Unknown Type";
434 *code = "Unknown Code";
436 switch (icmp->h_type) {
437 case 1:
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;
442 return;
443 case 2:
444 *type = "Packet Too Big";
445 *optional = dissect_icmpv6_type2;
446 return;
447 case 3:
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;
452 return;
453 case 4:
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;
458 return;
459 case 100:
460 *type = "Private experimation";
461 return;
462 case 101:
463 *type = "Private experimation";
464 return;
465 case 127:
466 *type = "Reserved for expansion of ICMPv6 error messages";
467 return;
468 case 128:
469 *type = "Echo Request";
470 *optional = dissect_icmpv6_type128;
471 return;
472 case 129:
473 *type = "Echo Reply";
474 *optional = dissect_icmpv6_type129;
475 return;
476 case 130:
477 *type = "Multicast Listener Query";
478 *optional = dissect_icmpv6_type130;
479 return;
480 case 131:
481 *type = "Multicast Listener Report";
482 *optional = dissect_icmpv6_type131;
483 return;
484 case 132:
485 *type = "Multicast Listener Done";
486 *optional = dissect_icmpv6_type132;
487 return;
488 case 133:
489 *type = "Router Solicitation";
490 *optional = dissect_icmpv6_type133;
491 return;
492 case 134:
493 *type = "Router Advertisement";
494 *optional = dissect_icmpv6_type134;
495 return;
496 case 135:
497 *type = "Neighbor Solicitation";
498 *optional = dissect_icmpv6_type135;
499 return;
500 case 136:
501 *type = "Neighbor Advertisement";
502 *optional = dissect_icmpv6_type136;
503 return;
504 case 137:
505 *type = "Redirect Message";
506 *optional = dissect_icmpv6_type137;
507 return;
508 case 138:
509 *type = "Router Renumbering";
510 return;
511 case 139:
512 *type = "ICMP Node Information Query";
513 return;
514 case 140:
515 *type = "ICMP Node Information Response";
516 return;
517 case 141:
518 *type = "Inverse Neighbor Discovery Solicitation Message";
519 return;
520 case 142:
521 *type = "Inverse Neighbor Discovery Advertisement Message";
522 return;
523 case 143:
524 *type = "Multicast Listener Report v2";
525 return;
526 case 144:
527 *type = "Home Agent Address Discovery Request Message";
528 return;
529 case 145:
530 *type = "Home Agent Address Discovery Reply Message";
531 return;
532 case 146:
533 *type = "Mobile Prefix Solicitation";
534 return;
535 case 147:
536 *type = "Mobile Prefix Advertisement";
537 return;
538 case 148:
539 *type = "Certification Path Solicitation";
540 return;
541 case 149:
542 *type = "Certification Path Advertisement";
543 return;
544 case 150:
545 *type = "ICMP messages utilized by experimental mobility "
546 "protocols such as Seamoby";
547 return;
548 case 151:
549 *type = "Multicast Router Advertisement";
550 return;
551 case 152:
552 *type = "Multicast Router Solicitation";
553 return;
554 case 153:
555 *type = "Multicast Router Termination";
556 return;
557 case 155:
558 *type = "RPL Control Message";
559 return;
560 case 200:
561 *type = "Private experimation";
562 return;
563 case 201:
564 *type = "Private experimation";
565 return;
566 case 255:
567 *type = "Reserved for expansion of ICMPv6 error messages";
568 return;
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));
579 if (icmp == NULL)
580 return;
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));
588 if (optional)
589 (*optional) (pkt);
590 tprintf(" ]\n\n");
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));
598 if (icmp == NULL)
599 return;
601 tprintf(" ICMPv6 Type (%u) Code (%u)", icmp->h_type, icmp->h_code);
604 struct protocol icmpv6_ops = {
605 .key = 0x3A,
606 .print_full = icmpv6,
607 .print_less = icmpv6_less,
610 #endif /* PROTO_ICMPV6_H */