man: astraceroute: Fix closing quotation mark
[netsniff-ng.git] / proto_ipv6_mobility_hdr.c
blob5ae5c7c3fff09d6065c20b446db36c254746d546
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 <stdio.h>
10 #include <stdint.h>
11 #include <netinet/in.h> /* for ntohs() */
12 #include <arpa/inet.h>
14 #include "proto.h"
15 #include "dissector_eth.h"
16 #include "built_in.h"
17 #include "pkt_buff.h"
19 #define BINDING_REFRESH_REQUEST_MESSAGE 0x00
20 #define HOME_TEST_INIT_MESSAGE 0x01
21 #define CARE_OF_TEST_INIT_MESSAGE 0x02
22 #define HOME_TEST_MESSAGE 0x03
23 #define CARE_OF_TEST_MESSAGE 0x04
24 #define BINDING_UPDATE_MESSAGE 0x05
25 #define BINDING_ACKNOWLEDGEMENT_MESSAGE 0x06
26 #define BINDING_ERROR_MESSAGE 0x07
28 struct mobilityhdr {
29 uint8_t payload_proto;
30 uint8_t hdr_len;
31 uint8_t MH_type;
32 uint8_t reserved;
33 uint16_t chksum;
34 uint8_t msgdata[0];
35 } __packed;
37 struct bin_refr_req_msg {
38 uint16_t reserved;
39 uint8_t mobility_opt[0];
40 } __packed;
42 /* for 0x01 and 0x02 */
43 struct tst_init_msg {
44 uint16_t reserved;
45 uint64_t init_cookie;
46 uint8_t mobility_opt[0];
47 } __packed;
49 /* for 0x03 and 0x04 */
50 struct tst_msg {
51 uint16_t nonce_index;
52 uint64_t init_cookie;
53 uint64_t keygen_token;
54 uint8_t mobility_opt[0];
55 } __packed;
57 struct bind_upd_msg {
58 uint16_t sequence;
59 uint16_t ahlk_res;
60 uint16_t lifetime;
61 uint8_t mobility_opt[0];
62 } __packed;
64 struct bind_ack_msg {
65 uint8_t status;
66 uint8_t k_res;
67 uint16_t sequence;
68 uint16_t lifetime;
69 uint8_t mobility_opt[0];
70 } __packed;
72 struct bind_err_msg {
73 uint8_t status;
74 uint8_t res;
75 uint64_t home_addr;
76 uint8_t mobility_opt[0];
77 } __packed;
80 static void dissect_mobility_options(struct pkt_buff *pkt __maybe_unused,
81 ssize_t *message_data_len)
83 /* Have to been upgraded.
84 * http://tools.ietf.org/html/rfc6275#section-6.2.1
86 if (*message_data_len)
87 tprintf("MH Option(s) recognized ");
89 /* If adding dissector reduce message_data_len for each using of
90 * pkt_pull to the same size.
94 static void dissect_mobilityhdr_type_0(struct pkt_buff *pkt,
95 ssize_t *message_data_len)
97 struct bin_refr_req_msg *type_0;
99 type_0 = (struct bin_refr_req_msg *) pkt_pull(pkt, sizeof(*type_0));
100 *message_data_len -= sizeof(*type_0);
101 if (type_0 == NULL || *message_data_len > pkt_len(pkt) ||
102 *message_data_len < 0)
103 return;
105 dissect_mobility_options(pkt, message_data_len);
108 static void dissect_mobilityhdr_type_1_2(struct pkt_buff *pkt,
109 ssize_t *message_data_len)
111 struct tst_init_msg *type_1_2;
113 type_1_2 = (struct tst_init_msg *) pkt_pull(pkt, sizeof(*type_1_2));
114 *message_data_len -= sizeof(*type_1_2);
115 if (type_1_2 == NULL || *message_data_len > pkt_len(pkt) ||
116 *message_data_len < 0)
117 return;
119 tprintf("Init Cookie (0x%lx)", ntohll(type_1_2->init_cookie));
121 dissect_mobility_options(pkt, message_data_len);
124 static void dissect_mobilityhdr_type_3_4(struct pkt_buff *pkt,
125 ssize_t *message_data_len)
127 struct tst_msg *type_3_4;
129 type_3_4 = (struct tst_msg *) pkt_pull(pkt, sizeof(*type_3_4));
130 *message_data_len -= sizeof(*type_3_4);
131 if (type_3_4 == NULL || *message_data_len > pkt_len(pkt) ||
132 *message_data_len < 0)
133 return;
135 tprintf("HN Index (%u) ", ntohs(type_3_4->nonce_index));
136 tprintf("Init Cookie (0x%lx) ", ntohll(type_3_4->init_cookie));
137 tprintf("Keygen Token (0x%lx)", ntohll(type_3_4->keygen_token));
139 dissect_mobility_options(pkt, message_data_len);
142 static void dissect_mobilityhdr_type_5(struct pkt_buff *pkt,
143 ssize_t *message_data_len)
145 struct bind_upd_msg *type_5;
147 type_5 = (struct bind_upd_msg *) pkt_pull(pkt, sizeof(*type_5));
148 *message_data_len -= sizeof(*type_5);
149 if (type_5 == NULL || *message_data_len > pkt_len(pkt) ||
150 *message_data_len < 0)
151 return;
153 tprintf("Sequence (0x%x) ", ntohs(type_5->sequence));
154 tprintf("A|H|L|K (0x%x) ", ntohs(type_5->ahlk_res) >> 12);
155 tprintf("Lifetime (%us)", ntohs(type_5->lifetime) * 4);
157 dissect_mobility_options(pkt, message_data_len);
160 static void dissect_mobilityhdr_type_6(struct pkt_buff *pkt,
161 ssize_t *message_data_len)
163 struct bind_ack_msg *type_6;
165 type_6 = (struct bind_ack_msg *) pkt_pull(pkt, sizeof(*type_6));
166 if (type_6 == NULL)
167 return;
169 *message_data_len -= sizeof(*type_6);
170 if (*message_data_len > pkt_len(pkt) || *message_data_len < 0)
171 return;
173 tprintf("Status (0x%x) ", type_6->status);
174 tprintf("K (%u) ", type_6->k_res >> 7);
175 tprintf("Sequence (0x%x)", ntohs(type_6->sequence));
176 tprintf("Lifetime (%us)", ntohs(type_6->lifetime) * 4);
178 dissect_mobility_options(pkt, message_data_len);
181 static void dissect_mobilityhdr_type_7(struct pkt_buff *pkt,
182 ssize_t *message_data_len)
184 char address[INET6_ADDRSTRLEN];
185 uint64_t addr;
186 struct bind_err_msg *type_7;
188 type_7 = (struct bind_err_msg *) pkt_pull(pkt, sizeof(*type_7));
189 if (type_7 == NULL)
190 return;
192 *message_data_len -= sizeof(*type_7);
193 addr = ntohll(type_7->home_addr);
194 if (*message_data_len > pkt_len(pkt) || *message_data_len < 0)
195 return;
197 tprintf("Status (0x%x) ", type_7->status);
198 tprintf("Home Addr (%s)",
199 inet_ntop(AF_INET6, &addr, address,
200 sizeof(address)));
202 dissect_mobility_options(pkt, message_data_len);
205 static void get_mh_type(struct pkt_buff *pkt, ssize_t *message_data_len,
206 uint8_t *mh_type)
208 switch (*mh_type) {
209 case BINDING_REFRESH_REQUEST_MESSAGE:
210 tprintf("Binding Refresh Request Message ");
211 dissect_mobilityhdr_type_0(pkt, message_data_len);
212 break;
213 case HOME_TEST_INIT_MESSAGE:
214 tprintf("Home Test Init Message ");
215 dissect_mobilityhdr_type_1_2(pkt, message_data_len);
216 break;
217 case CARE_OF_TEST_INIT_MESSAGE:
218 tprintf("Care-of Test Init Message ");
219 dissect_mobilityhdr_type_1_2(pkt, message_data_len);
220 break;
221 case HOME_TEST_MESSAGE:
222 tprintf("Binding Refresh Request Message ");
223 dissect_mobilityhdr_type_3_4(pkt, message_data_len);
224 break;
225 case CARE_OF_TEST_MESSAGE:
226 tprintf("Binding Refresh Request Message ");
227 dissect_mobilityhdr_type_3_4(pkt, message_data_len);
228 break;
229 case BINDING_UPDATE_MESSAGE:
230 tprintf("Binding Refresh Request Message ");
231 dissect_mobilityhdr_type_5(pkt, message_data_len);
232 break;
233 case BINDING_ACKNOWLEDGEMENT_MESSAGE:
234 tprintf("Binding Refresh Request Message ");
235 dissect_mobilityhdr_type_6(pkt, message_data_len);
236 break;
237 case BINDING_ERROR_MESSAGE:
238 tprintf("Binding Refresh Request Message ");
239 dissect_mobilityhdr_type_7(pkt, message_data_len);
240 break;
241 default:
242 tprintf("Type %u is unknown. Error", *mh_type);
246 static void mobility(struct pkt_buff *pkt)
248 uint16_t hdr_ext_len;
249 ssize_t message_data_len;
250 struct mobilityhdr *mobility;
252 mobility = (struct mobilityhdr *) pkt_pull(pkt, sizeof(*mobility));
253 if (mobility == NULL)
254 return;
256 /* Total Header Length in Bytes */
257 hdr_ext_len = (mobility->hdr_len + 1) * 8;
258 /* Total Message Data length in Bytes*/
259 message_data_len = (hdr_ext_len - sizeof(*mobility));
261 tprintf("\t [ Mobility ");
262 tprintf("NextHdr (%u), ", mobility->payload_proto);
263 if (message_data_len > pkt_len(pkt) || message_data_len < 0){
264 tprintf("HdrExtLen (%u, %u Bytes %s), ", mobility->hdr_len,
265 hdr_ext_len, colorize_start_full(black, red)
266 "invalid" colorize_end());
267 return;
269 tprintf("HdrExtLen (%u, %u Bytes), ", mobility->hdr_len,
270 hdr_ext_len);
271 tprintf("MH Type (%u), ", mobility->MH_type);
272 tprintf("Res (0x%x), ", mobility->reserved);
273 tprintf("Chks (0x%x), ", ntohs(mobility->chksum));
274 tprintf("MH Data ");
276 get_mh_type(pkt, &message_data_len, &mobility->MH_type);
278 tprintf(" ]\n");
280 if (message_data_len > pkt_len(pkt) || message_data_len < 0)
281 return;
283 pkt_pull(pkt, message_data_len);
284 pkt_set_proto(pkt, &eth_lay3, mobility->payload_proto);
287 static void mobility_less(struct pkt_buff *pkt)
289 uint16_t hdr_ext_len;
290 ssize_t message_data_len;
291 struct mobilityhdr *mobility;
293 mobility = (struct mobilityhdr *) pkt_pull(pkt, sizeof(*mobility));
294 if (mobility == NULL)
295 return;
297 /* Total Header Length in Bytes */
298 hdr_ext_len = (mobility->hdr_len + 1) * 8;
299 /* Total Message Data length in Bytes*/
300 message_data_len = (hdr_ext_len - sizeof(*mobility));
301 if (message_data_len > pkt_len(pkt) || message_data_len < 0)
302 return;
304 tprintf(" Mobility Type (%u), ", mobility->MH_type);
306 pkt_pull(pkt, message_data_len);
307 pkt_set_proto(pkt, &eth_lay3, mobility->payload_proto);
310 struct protocol ipv6_mobility_ops = {
311 .key = 0x87,
312 .print_full = mobility,
313 .print_less = mobility_less,