proto_icmpv6.h: intermediate state
[netsniff-ng.git] / src / proto_icmpv6.h
blob24a05c2c2125d2a0d2b2122b62fe147ab0f6ce82
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 #define icmpv6_code_range_valid(code, sarr) ((code) < array_size((sarr)))
27 struct icmpv6_general_hdr {
28 uint8_t h_type;
29 uint8_t h_code;
30 uint16_t h_chksum;
31 } __packed;
33 /* for type 0x01 and 0x03 */
34 struct icmpv6_type_1_3 {
35 uint32_t unused;
36 uint8_t invoking_pkt[0];
37 } __packed;
39 struct icmpv6_type_2 {
40 uint32_t MTU;
41 uint8_t invoking_pkt[0];
42 } __packed;
44 struct icmpv6_type_4 {
45 uint32_t pointer;
46 uint8_t invoking_pkt[0];
47 } __packed;
49 struct icmpv6_type_128_129 {
50 uint16_t id;
51 uint16_t sn;
52 uint8_t data[0];
53 } __packed;
55 /* MLDv1 msg */
56 struct icmpv6_type_130_131_132 {
57 uint16_t maxrespdel;
58 uint16_t res;
59 struct in6_addr ipv6_addr;
60 } __packed;
61 /* end MLDv1 msg */
63 struct icmpv6_type_130_mldv2 {
64 uint8_t resv_S_QRV;
65 uint8_t QQIC;
66 uint16_t nr_src;
67 struct in6_addr ipv6_addr[0];
68 } __packed;
70 /* Neighbor Discovery msg */
71 struct icmpv6_type_133 {
72 uint32_t res;
73 uint8_t ops[0];
74 } __packed;
76 struct icmpv6_type_134 {
77 uint8_t cur_hop_limit;
78 uint8_t m_o_res;
79 uint16_t router_lifetime;
80 uint32_t reachable_time;
81 uint32_t retrans_timer;
82 uint8_t ops[0];
83 } __packed;
85 struct icmpv6_type_135 {
86 uint32_t res;
87 struct in6_addr ipv6_addr;
88 uint8_t ops[0];
89 } __packed;
91 struct icmpv6_type_136 {
92 uint32_t r_s_o_res;
93 struct in6_addr ipv6_addr;
94 uint8_t ops[0];
95 } __packed;
97 struct icmpv6_type_137 {
98 uint32_t res;
99 struct in6_addr ipv6_targ_addr;
100 struct in6_addr ipv6_dest_addr;
101 uint8_t ops[0];
102 } __packed;
104 struct icmpv6_neighb_disc_ops_general {
105 uint8_t type;
106 uint8_t len;
107 uint8_t ops[0];
108 } __packed;
110 struct icmpv6_neighb_disc_ops_type_1_2 {
111 uint8_t link_lay_addr[0];
112 } __packed;
114 struct icmpv6_neighb_disc_ops_type_3 {
115 uint8_t prefix_len;
116 uint8_t l_a_res1;
117 uint32_t valid_lifetime;
118 uint32_t preferred_lifetime;
119 uint32_t res2;
120 struct in6_addr prefix;
121 } __packed;
123 struct icmpv6_neighb_disc_ops_type_4 {
124 uint16_t res1;
125 uint32_t res2;
126 uint8_t ip_hdr_data[0];
127 } __packed;
129 struct icmpv6_neighb_disc_ops_type_5 {
130 uint16_t res1;
131 uint32_t MTU;
132 } __packed;
133 /* end Neighbor Discovery msg */
135 struct icmpv6_type_138 {
136 uint16_t chks;
137 uint32_t seq_nr;
138 uint8_t seg_nr;
139 uint8_t flags;
140 uint16_t maxdelay;
141 uint32_t res;
142 } __packed;
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;
149 while (nr_addr--) {
150 addr = (struct in6_addr *) pkt_pull(pkt, sizeof(*addr));
151 if (addr == NULL)
152 return;
154 tprintf("\n\t Address: %s",
155 inet_ntop(AF_INET6, addr, address,
156 sizeof(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",
165 "Port 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));
176 if (icmp_1 == NULL)
177 return;
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));
188 if (icmp_2 == NULL)
189 return;
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));
205 if (icmp_3 == NULL)
206 return;
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));
223 if (icmp_4 == NULL)
224 return;
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)
237 return;
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)
251 return;
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)
268 return;
269 maxrespdel = ntohs(icmp_130->maxrespdel);
271 if(pkt_len(pkt) >= sizeof(struct icmpv6_type_130_mldv2))
272 switch_mldv2 = 1;
274 if(switch_mldv2)
275 tprintf(", Max Resp Delay (%ums)", maxrespdel >> 15 ?
276 (((maxrespdel & 0xFFF) | 0x1000) <<
277 (((maxrespdel >> 12) & 0x3) + 3)) : maxrespdel);
278 else
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)));
285 if(switch_mldv2) {
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)
291 return;
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)
313 return;
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)
334 return;
336 tprintf("Address 0x");
338 while(len--){
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)
356 return;
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)
380 return;
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 ");
386 while(len--){
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)
398 return;
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",
408 "Redirected Header",
409 "MTU",
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)
421 return;
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,
432 ops_total_len);
434 switch (icmp_neighb_disc->type) {
435 case 1:
436 dissect_neighb_disc_ops_1(pkt, ops_payl_len);
437 break;
438 case 2:
439 dissect_neighb_disc_ops_2(pkt, ops_payl_len);
440 break;
441 case 3:
442 dissect_neighb_disc_ops_3(pkt, ops_payl_len);
443 break;
444 case 4:
445 dissect_neighb_disc_ops_4(pkt, ops_payl_len);
446 break;
447 case 5:
448 dissect_neighb_disc_ops_5(pkt, ops_payl_len);
449 break;
450 default:
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)
463 return;
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)
477 return;
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)
497 return;
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];
510 uint32_t r_s_o_res;
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)
516 return;
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)
537 return;
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)
571 return;
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,
579 char **code,
580 void (**optional)(struct pkt_buff *pkt))
582 *type = "Unknown Type";
583 *code = "Unknown Code";
585 switch (icmp->h_type) {
586 case 1:
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;
591 return;
592 case 2:
593 *type = "Packet Too Big";
594 *optional = dissect_icmpv6_type2;
595 return;
596 case 3:
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;
601 return;
602 case 4:
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;
607 return;
608 case 100:
609 *type = "Private experimation";
610 return;
611 case 101:
612 *type = "Private experimation";
613 return;
614 case 127:
615 *type = "Reserved for expansion of ICMPv6 error messages";
616 return;
617 case 128:
618 *type = "Echo Request";
619 *optional = dissect_icmpv6_type128;
620 return;
621 case 129:
622 *type = "Echo Reply";
623 *optional = dissect_icmpv6_type129;
624 return;
625 case 130:
626 *type = "Multicast Listener Query";
627 *optional = dissect_icmpv6_type130;
628 return;
629 case 131:
630 *type = "Multicast Listener Report";
631 *optional = dissect_icmpv6_type131;
632 return;
633 case 132:
634 *type = "Multicast Listener Done";
635 *optional = dissect_icmpv6_type132;
636 return;
637 case 133:
638 *type = "Router Solicitation";
639 *optional = dissect_icmpv6_type133;
640 return;
641 case 134:
642 *type = "Router Advertisement";
643 *optional = dissect_icmpv6_type134;
644 return;
645 case 135:
646 *type = "Neighbor Solicitation";
647 *optional = dissect_icmpv6_type135;
648 return;
649 case 136:
650 *type = "Neighbor Advertisement";
651 *optional = dissect_icmpv6_type136;
652 return;
653 case 137:
654 *type = "Redirect Message";
655 *optional = dissect_icmpv6_type137;
656 return;
657 case 138:
658 *type = "Router Renumbering";
659 return;
660 case 139:
661 *type = "ICMP Node Information Query";
662 return;
663 case 140:
664 *type = "ICMP Node Information Response";
665 return;
666 case 141:
667 *type = "Inverse Neighbor Discovery Solicitation Message";
668 return;
669 case 142:
670 *type = "Inverse Neighbor Discovery Advertisement Message";
671 return;
672 case 143:
673 *type = "Multicast Listener Report v2";
674 return;
675 case 144:
676 *type = "Home Agent Address Discovery Request Message";
677 return;
678 case 145:
679 *type = "Home Agent Address Discovery Reply Message";
680 return;
681 case 146:
682 *type = "Mobile Prefix Solicitation";
683 return;
684 case 147:
685 *type = "Mobile Prefix Advertisement";
686 return;
687 case 148:
688 *type = "Certification Path Solicitation";
689 return;
690 case 149:
691 *type = "Certification Path Advertisement";
692 return;
693 case 150:
694 *type = "ICMP messages utilized by experimental mobility "
695 "protocols such as Seamoby";
696 return;
697 case 151:
698 *type = "Multicast Router Advertisement";
699 return;
700 case 152:
701 *type = "Multicast Router Solicitation";
702 return;
703 case 153:
704 *type = "Multicast Router Termination";
705 return;
706 case 155:
707 *type = "RPL Control Message";
708 return;
709 case 200:
710 *type = "Private experimation";
711 return;
712 case 201:
713 *type = "Private experimation";
714 return;
715 case 255:
716 *type = "Reserved for expansion of ICMPv6 error messages";
717 return;
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));
728 if (icmp == NULL)
729 return;
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));
737 if (optional)
738 (*optional) (pkt);
739 tprintf(" ]\n\n");
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));
747 if (icmp == NULL)
748 return;
750 tprintf(" ICMPv6 Type (%u) Code (%u)", icmp->h_type, icmp->h_code);
753 struct protocol icmpv6_ops = {
754 .key = 0x3A,
755 .print_full = icmpv6,
756 .print_less = icmpv6_less,
759 #endif /* PROTO_ICMPV6_H */