2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2012 Markus Amend <markus@netsniff-ng.org>, Deutsche Flugsicherung GmbH
4 * Subject to the GPL, version 2.
6 * IPv6 Mobility Header described in RFC6275
11 #include <netinet/in.h> /* for ntohs() */
12 #include <arpa/inet.h>
16 #include "dissector_eth.h"
20 #define BINDING_REFRESH_REQUEST_MESSAGE 0x00
21 #define HOME_TEST_INIT_MESSAGE 0x01
22 #define CARE_OF_TEST_INIT_MESSAGE 0x02
23 #define HOME_TEST_MESSAGE 0x03
24 #define CARE_OF_TEST_MESSAGE 0x04
25 #define BINDING_UPDATE_MESSAGE 0x05
26 #define BINDING_ACKNOWLEDGEMENT_MESSAGE 0x06
27 #define BINDING_ERROR_MESSAGE 0x07
30 uint8_t payload_proto
;
38 struct bin_refr_req_msg
{
40 uint8_t mobility_opt
[0];
43 /* for 0x01 and 0x02 */
47 uint8_t mobility_opt
[0];
50 /* for 0x03 and 0x04 */
54 uint64_t keygen_token
;
55 uint8_t mobility_opt
[0];
62 uint8_t mobility_opt
[0];
70 uint8_t mobility_opt
[0];
77 uint8_t mobility_opt
[0];
81 static void dissect_mobility_options(struct pkt_buff
*pkt
,
82 ssize_t
*message_data_len
)
84 /* Have to been upgraded.
85 * http://tools.ietf.org/html/rfc6275#section-6.2.1
87 if (*message_data_len
)
88 tprintf("MH Option(s) recognized ");
90 /* If adding dissector reduce message_data_len for each using of
91 * pkt_pull to the same size.
95 static void dissect_mobilityhdr_type_0(struct pkt_buff
*pkt
,
96 ssize_t
*message_data_len
)
98 struct bin_refr_req_msg
*type_0
;
100 type_0
= (struct bin_refr_req_msg
*) pkt_pull(pkt
, sizeof(*type_0
));
101 *message_data_len
-= sizeof(*type_0
);
102 if (type_0
== NULL
|| *message_data_len
> pkt_len(pkt
) ||
103 *message_data_len
< 0)
106 dissect_mobility_options(pkt
, message_data_len
);
109 static void dissect_mobilityhdr_type_1_2(struct pkt_buff
*pkt
,
110 ssize_t
*message_data_len
)
112 struct tst_init_msg
*type_1_2
;
114 type_1_2
= (struct tst_init_msg
*) pkt_pull(pkt
, sizeof(*type_1_2
));
115 *message_data_len
-= sizeof(*type_1_2
);
116 if (type_1_2
== NULL
|| *message_data_len
> pkt_len(pkt
) ||
117 *message_data_len
< 0)
120 tprintf("Init Cookie (0x%lx)", ntohll(type_1_2
->init_cookie
));
122 dissect_mobility_options(pkt
, message_data_len
);
125 static void dissect_mobilityhdr_type_3_4(struct pkt_buff
*pkt
,
126 ssize_t
*message_data_len
)
128 struct tst_msg
*type_3_4
;
130 type_3_4
= (struct tst_msg
*) pkt_pull(pkt
, sizeof(*type_3_4
));
131 *message_data_len
-= sizeof(*type_3_4
);
132 if (type_3_4
== NULL
|| *message_data_len
> pkt_len(pkt
) ||
133 *message_data_len
< 0)
136 tprintf("HN Index (%u) ", ntohs(type_3_4
->nonce_index
));
137 tprintf("Init Cookie (0x%lx) ", ntohll(type_3_4
->init_cookie
));
138 tprintf("Keygen Token (0x%lx)", ntohll(type_3_4
->keygen_token
));
140 dissect_mobility_options(pkt
, message_data_len
);
143 static void dissect_mobilityhdr_type_5(struct pkt_buff
*pkt
,
144 ssize_t
*message_data_len
)
146 struct bind_upd_msg
*type_5
;
148 type_5
= (struct bind_upd_msg
*) pkt_pull(pkt
, sizeof(*type_5
));
149 *message_data_len
-= sizeof(*type_5
);
150 if (type_5
== NULL
|| *message_data_len
> pkt_len(pkt
) ||
151 *message_data_len
< 0)
154 tprintf("Sequence (0x%x) ", ntohs(type_5
->sequence
));
155 tprintf("A|H|L|K (0x%x) ", ntohs(type_5
->ahlk_res
) >> 12);
156 tprintf("Lifetime (%us)", ntohs(type_5
->lifetime
) * 4);
158 dissect_mobility_options(pkt
, message_data_len
);
161 static void dissect_mobilityhdr_type_6(struct pkt_buff
*pkt
,
162 ssize_t
*message_data_len
)
164 struct bind_ack_msg
*type_6
;
166 type_6
= (struct bind_ack_msg
*) pkt_pull(pkt
, sizeof(*type_6
));
167 *message_data_len
-= sizeof(*type_6
);
168 if (type_6
== NULL
|| *message_data_len
> pkt_len(pkt
) ||
169 *message_data_len
< 0)
172 tprintf("Status (0x%x) ", type_6
->status
);
173 tprintf("K (%u) ", type_6
->k_res
>> 7);
174 tprintf("Sequence (0x%x)", ntohs(type_6
->sequence
));
175 tprintf("Lifetime (%us)", ntohs(type_6
->lifetime
) * 4);
177 dissect_mobility_options(pkt
, message_data_len
);
180 static void dissect_mobilityhdr_type_7(struct pkt_buff
*pkt
,
181 ssize_t
*message_data_len
)
183 char address
[INET6_ADDRSTRLEN
];
185 struct bind_err_msg
*type_7
;
187 type_7
= (struct bind_err_msg
*) pkt_pull(pkt
, sizeof(*type_7
));
188 *message_data_len
-= sizeof(*type_7
);
189 addr
= ntohll(type_7
->home_addr
);
190 if (type_7
== NULL
|| *message_data_len
> pkt_len(pkt
) ||
191 *message_data_len
< 0)
194 tprintf("Status (0x%x) ", type_7
->status
);
195 tprintf("Home Addr (%s)",
196 inet_ntop(AF_INET6
, &addr
, address
,
199 dissect_mobility_options(pkt
, message_data_len
);
202 static void get_mh_type(struct pkt_buff
*pkt
, ssize_t
*message_data_len
,
206 case BINDING_REFRESH_REQUEST_MESSAGE
:
207 tprintf("Binding Refresh Request Message ");
208 dissect_mobilityhdr_type_0(pkt
, message_data_len
);
210 case HOME_TEST_INIT_MESSAGE
:
211 tprintf("Home Test Init Message ");
212 dissect_mobilityhdr_type_1_2(pkt
, message_data_len
);
214 case CARE_OF_TEST_INIT_MESSAGE
:
215 tprintf("Care-of Test Init Message ");
216 dissect_mobilityhdr_type_1_2(pkt
, message_data_len
);
218 case HOME_TEST_MESSAGE
:
219 tprintf("Binding Refresh Request Message ");
220 dissect_mobilityhdr_type_3_4(pkt
, message_data_len
);
222 case CARE_OF_TEST_MESSAGE
:
223 tprintf("Binding Refresh Request Message ");
224 dissect_mobilityhdr_type_3_4(pkt
, message_data_len
);
226 case BINDING_UPDATE_MESSAGE
:
227 tprintf("Binding Refresh Request Message ");
228 dissect_mobilityhdr_type_5(pkt
, message_data_len
);
230 case BINDING_ACKNOWLEDGEMENT_MESSAGE
:
231 tprintf("Binding Refresh Request Message ");
232 dissect_mobilityhdr_type_6(pkt
, message_data_len
);
234 case BINDING_ERROR_MESSAGE
:
235 tprintf("Binding Refresh Request Message ");
236 dissect_mobilityhdr_type_7(pkt
, message_data_len
);
239 tprintf("Type %u is unknown. Error", *mh_type
);
243 static void mobility(struct pkt_buff
*pkt
)
245 uint16_t hdr_ext_len
;
246 ssize_t message_data_len
;
247 struct mobilityhdr
*mobility
;
249 mobility
= (struct mobilityhdr
*) pkt_pull(pkt
, sizeof(*mobility
));
250 if (mobility
== NULL
)
253 /* Total Header Length in Bytes */
254 hdr_ext_len
= (mobility
->hdr_len
+ 1) * 8;
255 /* Total Message Data length in Bytes*/
256 message_data_len
= (hdr_ext_len
- sizeof(*mobility
));
258 tprintf("\t [ Mobility ");
259 tprintf("NextHdr (%u), ", mobility
->payload_proto
);
260 if (message_data_len
> pkt_len(pkt
) || message_data_len
< 0){
261 tprintf("HdrExtLen (%u, %u Bytes %s), ", mobility
->hdr_len
,
262 hdr_ext_len
, colorize_start_full(black
, red
)
263 "invalid" colorize_end());
266 tprintf("HdrExtLen (%u, %u Bytes), ", mobility
->hdr_len
,
268 tprintf("MH Type (%u), ", mobility
->MH_type
);
269 tprintf("Res (0x%x), ", mobility
->reserved
);
270 tprintf("Chks (0x%x), ", ntohs(mobility
->chksum
));
273 get_mh_type(pkt
, &message_data_len
, &mobility
->MH_type
);
277 if (message_data_len
> pkt_len(pkt
) || message_data_len
< 0)
280 pkt_pull(pkt
, message_data_len
);
281 pkt_set_proto(pkt
, ð_lay3
, mobility
->payload_proto
);
284 static void mobility_less(struct pkt_buff
*pkt
)
286 uint16_t hdr_ext_len
;
287 ssize_t message_data_len
;
288 struct mobilityhdr
*mobility
;
290 mobility
= (struct mobilityhdr
*) pkt_pull(pkt
, sizeof(*mobility
));
291 if (mobility
== NULL
)
294 /* Total Header Length in Bytes */
295 hdr_ext_len
= (mobility
->hdr_len
+ 1) * 8;
296 /* Total Message Data length in Bytes*/
297 message_data_len
= (hdr_ext_len
- sizeof(*mobility
));
298 if (message_data_len
> pkt_len(pkt
) || message_data_len
< 0)
301 tprintf(" Mobility Type (%u), ", mobility
->MH_type
);
303 pkt_pull(pkt
, message_data_len
);
304 pkt_set_proto(pkt
, ð_lay3
, mobility
->payload_proto
);
307 struct protocol ipv6_mobility_ops
= {
309 .print_full
= mobility
,
310 .print_less
= mobility_less
,
313 EXPORT_SYMBOL(ipv6_mobility_ops
);