trafgen: Add checksum helpers for TCP/UDP over IPv6
[netsniff-ng.git] / proto_ipv6_mobility_hdr.c
blob90f067808dd89d276777ecaab70d9b60fac261c2
1 /*
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
7 */
9 #include <inttypes.h>
10 #include <stdio.h>
11 #include <stdint.h>
12 #include <netinet/in.h> /* for ntohs() */
13 #include <arpa/inet.h>
15 #include "proto.h"
16 #include "dissector_eth.h"
17 #include "built_in.h"
18 #include "pkt_buff.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
29 struct mobilityhdr {
30 uint8_t payload_proto;
31 uint8_t hdr_len;
32 uint8_t MH_type;
33 uint8_t reserved;
34 uint16_t chksum;
35 uint8_t msgdata[0];
36 } __packed;
38 struct bin_refr_req_msg {
39 uint16_t reserved;
40 uint8_t mobility_opt[0];
41 } __packed;
43 /* for 0x01 and 0x02 */
44 struct tst_init_msg {
45 uint16_t reserved;
46 uint64_t init_cookie;
47 uint8_t mobility_opt[0];
48 } __packed;
50 /* for 0x03 and 0x04 */
51 struct tst_msg {
52 uint16_t nonce_index;
53 uint64_t init_cookie;
54 uint64_t keygen_token;
55 uint8_t mobility_opt[0];
56 } __packed;
58 struct bind_upd_msg {
59 uint16_t sequence;
60 uint16_t ahlk_res;
61 uint16_t lifetime;
62 uint8_t mobility_opt[0];
63 } __packed;
65 struct bind_ack_msg {
66 uint8_t status;
67 uint8_t k_res;
68 uint16_t sequence;
69 uint16_t lifetime;
70 uint8_t mobility_opt[0];
71 } __packed;
73 struct bind_err_msg {
74 uint8_t status;
75 uint8_t res;
76 uint64_t home_addr;
77 uint8_t mobility_opt[0];
78 } __packed;
81 static void dissect_mobility_options(struct pkt_buff *pkt __maybe_unused,
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)
104 return;
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)
118 return;
120 tprintf("Init Cookie (0x%"PRIx64")", 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)
134 return;
136 tprintf("HN Index (%u) ", ntohs(type_3_4->nonce_index));
137 tprintf("Init Cookie (0x%"PRIx64") ", ntohll(type_3_4->init_cookie));
138 tprintf("Keygen Token (0x%"PRIx64")", 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)
152 return;
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 if (type_6 == NULL)
168 return;
170 *message_data_len -= sizeof(*type_6);
171 if (*message_data_len > pkt_len(pkt) || *message_data_len < 0)
172 return;
174 tprintf("Status (0x%x) ", type_6->status);
175 tprintf("K (%u) ", type_6->k_res >> 7);
176 tprintf("Sequence (0x%x)", ntohs(type_6->sequence));
177 tprintf("Lifetime (%us)", ntohs(type_6->lifetime) * 4);
179 dissect_mobility_options(pkt, message_data_len);
182 static void dissect_mobilityhdr_type_7(struct pkt_buff *pkt,
183 ssize_t *message_data_len)
185 char address[INET6_ADDRSTRLEN];
186 uint64_t addr;
187 struct bind_err_msg *type_7;
189 type_7 = (struct bind_err_msg *) pkt_pull(pkt, sizeof(*type_7));
190 if (type_7 == NULL)
191 return;
193 *message_data_len -= sizeof(*type_7);
194 addr = ntohll(type_7->home_addr);
195 if (*message_data_len > pkt_len(pkt) || *message_data_len < 0)
196 return;
198 tprintf("Status (0x%x) ", type_7->status);
199 tprintf("Home Addr (%s)",
200 inet_ntop(AF_INET6, &addr, address,
201 sizeof(address)));
203 dissect_mobility_options(pkt, message_data_len);
206 static void get_mh_type(struct pkt_buff *pkt, ssize_t *message_data_len,
207 uint8_t *mh_type)
209 switch (*mh_type) {
210 case BINDING_REFRESH_REQUEST_MESSAGE:
211 tprintf("Binding Refresh Request Message ");
212 dissect_mobilityhdr_type_0(pkt, message_data_len);
213 break;
214 case HOME_TEST_INIT_MESSAGE:
215 tprintf("Home Test Init Message ");
216 dissect_mobilityhdr_type_1_2(pkt, message_data_len);
217 break;
218 case CARE_OF_TEST_INIT_MESSAGE:
219 tprintf("Care-of Test Init Message ");
220 dissect_mobilityhdr_type_1_2(pkt, message_data_len);
221 break;
222 case HOME_TEST_MESSAGE:
223 tprintf("Binding Refresh Request Message ");
224 dissect_mobilityhdr_type_3_4(pkt, message_data_len);
225 break;
226 case CARE_OF_TEST_MESSAGE:
227 tprintf("Binding Refresh Request Message ");
228 dissect_mobilityhdr_type_3_4(pkt, message_data_len);
229 break;
230 case BINDING_UPDATE_MESSAGE:
231 tprintf("Binding Refresh Request Message ");
232 dissect_mobilityhdr_type_5(pkt, message_data_len);
233 break;
234 case BINDING_ACKNOWLEDGEMENT_MESSAGE:
235 tprintf("Binding Refresh Request Message ");
236 dissect_mobilityhdr_type_6(pkt, message_data_len);
237 break;
238 case BINDING_ERROR_MESSAGE:
239 tprintf("Binding Refresh Request Message ");
240 dissect_mobilityhdr_type_7(pkt, message_data_len);
241 break;
242 default:
243 tprintf("Type %u is unknown. Error", *mh_type);
247 static void mobility(struct pkt_buff *pkt)
249 uint16_t hdr_ext_len;
250 ssize_t message_data_len;
251 struct mobilityhdr *mobility;
253 mobility = (struct mobilityhdr *) pkt_pull(pkt, sizeof(*mobility));
254 if (mobility == NULL)
255 return;
257 /* Total Header Length in Bytes */
258 hdr_ext_len = (mobility->hdr_len + 1) * 8;
259 /* Total Message Data length in Bytes*/
260 message_data_len = (hdr_ext_len - sizeof(*mobility));
262 tprintf("\t [ Mobility ");
263 tprintf("NextHdr (%u), ", mobility->payload_proto);
264 if (message_data_len > pkt_len(pkt) || message_data_len < 0){
265 tprintf("HdrExtLen (%u, %u Bytes %s), ", mobility->hdr_len,
266 hdr_ext_len, colorize_start_full(black, red)
267 "invalid" colorize_end());
268 return;
270 tprintf("HdrExtLen (%u, %u Bytes), ", mobility->hdr_len,
271 hdr_ext_len);
272 tprintf("MH Type (%u), ", mobility->MH_type);
273 tprintf("Res (0x%x), ", mobility->reserved);
274 tprintf("Chks (0x%x), ", ntohs(mobility->chksum));
275 tprintf("MH Data ");
277 get_mh_type(pkt, &message_data_len, &mobility->MH_type);
279 tprintf(" ]\n");
281 if (message_data_len > pkt_len(pkt) || message_data_len < 0)
282 return;
284 pkt_pull(pkt, message_data_len);
285 pkt_set_dissector(pkt, &eth_lay3, mobility->payload_proto);
288 static void mobility_less(struct pkt_buff *pkt)
290 uint16_t hdr_ext_len;
291 ssize_t message_data_len;
292 struct mobilityhdr *mobility;
294 mobility = (struct mobilityhdr *) pkt_pull(pkt, sizeof(*mobility));
295 if (mobility == NULL)
296 return;
298 /* Total Header Length in Bytes */
299 hdr_ext_len = (mobility->hdr_len + 1) * 8;
300 /* Total Message Data length in Bytes*/
301 message_data_len = (hdr_ext_len - sizeof(*mobility));
302 if (message_data_len > pkt_len(pkt) || message_data_len < 0)
303 return;
305 tprintf(" Mobility Type (%u), ", mobility->MH_type);
307 pkt_pull(pkt, message_data_len);
308 pkt_set_dissector(pkt, &eth_lay3, mobility->payload_proto);
311 struct protocol ipv6_mobility_ops = {
312 .key = 0x87,
313 .print_full = mobility,
314 .print_less = mobility_less,