]> The Tcpdump Group git mirrors - tcpdump/blob - print-babel.c
update for current Babel auth spec
[tcpdump] / print-babel.c
1 /*
2 * Copyright (c) 2007-2011 Grégoire Henry, Juliusz Chroboczek
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the project nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <tcpdump-stdinc.h>
34
35 #include <stdio.h>
36 #include <string.h>
37
38 #include "addrtoname.h"
39 #include "interface.h"
40 #include "extract.h"
41
42 static void babel_print_v2(const u_char *cp, u_int length);
43
44 void
45 babel_print(const u_char *cp, u_int length) {
46 printf("babel");
47
48 TCHECK2(*cp, 4);
49
50 if(cp[0] != 42) {
51 printf(" malformed header");
52 return;
53 } else {
54 printf(" %d", cp[1]);
55 }
56
57 switch(cp[1]) {
58 case 2:
59 babel_print_v2(cp,length);
60 break;
61 default:
62 printf(" unknown version");
63 break;
64 }
65
66 return;
67
68 trunc:
69 printf(" [|babel]");
70 return;
71 }
72
73 #define MESSAGE_PAD1 0
74 #define MESSAGE_PADN 1
75 #define MESSAGE_ACK_REQ 2
76 #define MESSAGE_ACK 3
77 #define MESSAGE_HELLO 4
78 #define MESSAGE_IHU 5
79 #define MESSAGE_ROUTER_ID 6
80 #define MESSAGE_NH 7
81 #define MESSAGE_UPDATE 8
82 #define MESSAGE_REQUEST 9
83 #define MESSAGE_MH_REQUEST 10
84 #define MESSAGE_TSPC 11
85 #define MESSAGE_HMAC 12
86
87 static const char *
88 format_id(const u_char *id)
89 {
90 static char buf[25];
91 snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
92 id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]);
93 buf[24] = '\0';
94 return buf;
95 }
96
97 static const unsigned char v4prefix[16] =
98 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
99
100 static const char *
101 format_prefix(const u_char *prefix, unsigned char plen)
102 {
103 static char buf[50];
104 if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0)
105 snprintf(buf, 50, "%s/%u", ipaddr_string(prefix + 12), plen - 96);
106 else
107 snprintf(buf, 50, "%s/%u", ip6addr_string(prefix), plen);
108 buf[49] = '\0';
109 return buf;
110 }
111
112 static const char *
113 format_address(const u_char *prefix)
114 {
115 if(memcmp(prefix, v4prefix, 12) == 0)
116 return ipaddr_string(prefix + 12);
117 else
118 return ip6addr_string(prefix);
119 }
120
121 static int
122 network_prefix(int ae, int plen, unsigned int omitted,
123 const unsigned char *p, const unsigned char *dp,
124 unsigned int len, unsigned char *p_r)
125 {
126 unsigned pb;
127 unsigned char prefix[16];
128
129 if(plen >= 0)
130 pb = (plen + 7) / 8;
131 else if(ae == 1)
132 pb = 4;
133 else
134 pb = 16;
135
136 if(pb > 16)
137 return -1;
138
139 memset(prefix, 0, 16);
140
141 switch(ae) {
142 case 0: break;
143 case 1:
144 if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
145 return -1;
146 memcpy(prefix, v4prefix, 12);
147 if(omitted) {
148 if (dp == NULL) return -1;
149 memcpy(prefix, dp, 12 + omitted);
150 }
151 if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted);
152 break;
153 case 2:
154 if(omitted > 16 || (pb > omitted && len < pb - omitted))
155 return -1;
156 if(omitted) {
157 if (dp == NULL) return -1;
158 memcpy(prefix, dp, omitted);
159 }
160 if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted);
161 break;
162 case 3:
163 if(pb > 8 && len < pb - 8) return -1;
164 prefix[0] = 0xfe;
165 prefix[1] = 0x80;
166 if(pb > 8) memcpy(prefix + 8, p, pb - 8);
167 break;
168 default:
169 return -1;
170 }
171
172 memcpy(p_r, prefix, 16);
173 return 1;
174 }
175
176 static int
177 network_address(int ae, const unsigned char *a, unsigned int len,
178 unsigned char *a_r)
179 {
180 return network_prefix(ae, -1, 0, a, NULL, len, a_r);
181 }
182
183 #define ICHECK(i, l) \
184 if ((i) + (l) > bodylen || (i) + (l) > length) goto corrupt;
185
186 static void
187 babel_print_v2(const u_char *cp, u_int length) {
188 u_int i;
189 u_short bodylen;
190 u_char v4_prefix[16] =
191 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
192 u_char v6_prefix[16] = {0};
193
194 TCHECK2(*cp, 4);
195 if (length < 4)
196 goto corrupt;
197 bodylen = EXTRACT_16BITS(cp + 2);
198 printf(" (%u)", bodylen);
199
200 /* Process the TLVs in the body */
201 i = 0;
202 while(i < bodylen) {
203 const u_char *message;
204 u_int type, len;
205
206 message = cp + 4 + i;
207 TCHECK2(*message, 2);
208 ICHECK(i, 2);
209 type = message[0];
210 len = message[1];
211
212 TCHECK2(*message, 2 + len);
213 ICHECK(i, 2 + len);
214
215 switch(type) {
216 case MESSAGE_PAD1: {
217 if(!vflag)
218 printf(" pad1");
219 else
220 printf("\n\tPad 1");
221 }
222 break;
223
224 case MESSAGE_PADN: {
225 if(!vflag)
226 printf(" padN");
227 else
228 printf("\n\tPad %d", len + 2);
229 }
230 break;
231
232 case MESSAGE_ACK_REQ: {
233 u_short nonce, interval;
234 if(!vflag)
235 printf(" ack-req");
236 else {
237 printf("\n\tAcknowledgment Request ");
238 if(len < 6) goto corrupt;
239 nonce = EXTRACT_16BITS(message + 4);
240 interval = EXTRACT_16BITS(message + 6);
241 printf("%04x %d", nonce, interval);
242 }
243 }
244 break;
245
246 case MESSAGE_ACK: {
247 u_short nonce;
248 if(!vflag)
249 printf(" ack");
250 else {
251 printf("\n\tAcknowledgment ");
252 if(len < 2) goto corrupt;
253 nonce = EXTRACT_16BITS(message + 2);
254 printf("%04x", nonce);
255 }
256 }
257 break;
258
259 case MESSAGE_HELLO: {
260 u_short seqno, interval;
261 if(!vflag)
262 printf(" hello");
263 else {
264 printf("\n\tHello ");
265 if(len < 6) goto corrupt;
266 seqno = EXTRACT_16BITS(message + 4);
267 interval = EXTRACT_16BITS(message + 6);
268 printf("seqno %u interval %u", seqno, interval);
269 }
270 }
271 break;
272
273 case MESSAGE_IHU: {
274 unsigned short txcost, interval;
275 if(!vflag)
276 printf(" ihu");
277 else {
278 u_char address[16];
279 int rc;
280 printf("\n\tIHU ");
281 if(len < 6) goto corrupt;
282 txcost = EXTRACT_16BITS(message + 4);
283 interval = EXTRACT_16BITS(message + 6);
284 rc = network_address(message[2], message + 8, len - 6, address);
285 if(rc < 0) { printf("[|babel]"); break; }
286 printf("%s txcost %u interval %d",
287 format_address(address), txcost, interval);
288 }
289 }
290 break;
291
292 case MESSAGE_ROUTER_ID: {
293 if(!vflag)
294 printf(" router-id");
295 else {
296 printf("\n\tRouter Id");
297 if(len < 10) goto corrupt;
298 printf(" %s", format_id(message + 4));
299 }
300 }
301 break;
302
303 case MESSAGE_NH: {
304 if(!vflag)
305 printf(" nh");
306 else {
307 int rc;
308 u_char nh[16];
309 printf("\n\tNext Hop");
310 if(len < 2) goto corrupt;
311 rc = network_address(message[2], message + 4, len - 2, nh);
312 if(rc < 0) goto corrupt;
313 printf(" %s", format_address(nh));
314 }
315 }
316 break;
317
318 case MESSAGE_UPDATE: {
319 if(!vflag) {
320 printf(" update");
321 if(len < 1)
322 printf("/truncated");
323 else
324 printf("%s%s%s",
325 (message[3] & 0x80) ? "/prefix": "",
326 (message[3] & 0x40) ? "/id" : "",
327 (message[3] & 0x3f) ? "/unknown" : "");
328 } else {
329 u_short interval, seqno, metric;
330 u_char plen;
331 int rc;
332 u_char prefix[16];
333 printf("\n\tUpdate");
334 if(len < 10) goto corrupt;
335 plen = message[4] + (message[2] == 1 ? 96 : 0);
336 rc = network_prefix(message[2], message[4], message[5],
337 message + 12,
338 message[2] == 1 ? v4_prefix : v6_prefix,
339 len - 10, prefix);
340 if(rc < 0) goto corrupt;
341 interval = EXTRACT_16BITS(message + 6);
342 seqno = EXTRACT_16BITS(message + 8);
343 metric = EXTRACT_16BITS(message + 10);
344 printf("%s%s%s %s metric %u seqno %u interval %u",
345 (message[3] & 0x80) ? "/prefix": "",
346 (message[3] & 0x40) ? "/id" : "",
347 (message[3] & 0x3f) ? "/unknown" : "",
348 format_prefix(prefix, plen),
349 metric, seqno, interval);
350 if(message[3] & 0x80) {
351 if(message[2] == 1)
352 memcpy(v4_prefix, prefix, 16);
353 else
354 memcpy(v6_prefix, prefix, 16);
355 }
356 }
357 }
358 break;
359
360 case MESSAGE_REQUEST: {
361 if(!vflag)
362 printf(" request");
363 else {
364 int rc;
365 u_char prefix[16], plen;
366 printf("\n\tRequest ");
367 if(len < 2) goto corrupt;
368 plen = message[3] + (message[2] == 1 ? 96 : 0);
369 rc = network_prefix(message[2], message[3], 0,
370 message + 4, NULL, len - 2, prefix);
371 if(rc < 0) goto corrupt;
372 plen = message[3] + (message[2] == 1 ? 96 : 0);
373 printf("for %s",
374 message[2] == 0 ? "any" : format_prefix(prefix, plen));
375 }
376 }
377 break;
378
379 case MESSAGE_MH_REQUEST : {
380 if(!vflag)
381 printf(" mh-request");
382 else {
383 int rc;
384 u_short seqno;
385 u_char prefix[16], plen;
386 printf("\n\tMH-Request ");
387 if(len < 14) goto corrupt;
388 seqno = EXTRACT_16BITS(message + 4);
389 rc = network_prefix(message[2], message[3], 0,
390 message + 16, NULL, len - 14, prefix);
391 if(rc < 0) goto corrupt;
392 plen = message[3] + (message[2] == 1 ? 96 : 0);
393 printf("(%u hops) for %s seqno %u id %s",
394 message[6], format_prefix(prefix, plen),
395 seqno, format_id(message + 8));
396 }
397 }
398 break;
399 case MESSAGE_TSPC :
400 if(!vflag)
401 printf(" tspc");
402 else {
403 printf("\n\tTS/PC ");
404 if(len < 6) goto corrupt;
405 printf("timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4),
406 EXTRACT_16BITS(message + 2));
407 }
408 break;
409 case MESSAGE_HMAC : {
410 if(!vflag)
411 printf(" hmac");
412 else {
413 unsigned j;
414 printf("\n\tHMAC ");
415 if(len < 18) goto corrupt;
416 printf("key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2);
417 for (j = 0; j < len - 2; j++)
418 printf ("%02X", message[4 + j]);
419 }
420 }
421 break;
422 default:
423 if(!vflag)
424 printf(" unknown");
425 else
426 printf("\n\tUnknown message type %d", type);
427 }
428 i += len + 2;
429 }
430 return;
431
432 trunc:
433 printf(" [|babel]");
434 return;
435
436 corrupt:
437 printf(" (corrupt)");
438 return;
439 }