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 42static void babel_print_v2(const u_char *cp, u_int length); 43 44void 45babel_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 87static const char * 88format_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 97static const unsigned char v4prefix[16] = 98 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 99 100static const char * 101format_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#ifdef INET6 108 snprintf(buf, 50, "%s/%u", ip6addr_string(prefix), plen); 109#else 110 snprintf(buf, 50, "IPv6 addresses not supported"); 111#endif 112 buf[49] = '\0'; 113 return buf; 114} 115 116static const char * 117format_address(const u_char *prefix) 118{ 119 if(memcmp(prefix, v4prefix, 12) == 0) 120 return ipaddr_string(prefix + 12); 121 else 122#ifdef INET6 123 return ip6addr_string(prefix); 124#else 125 return "IPv6 addresses not supported"; 126#endif 127} 128 129static int 130network_prefix(int ae, int plen, unsigned int omitted, 131 const unsigned char *p, const unsigned char *dp, 132 unsigned int len, unsigned char *p_r) 133{ 134 unsigned pb; 135 unsigned char prefix[16]; 136 137 if(plen >= 0) 138 pb = (plen + 7) / 8; 139 else if(ae == 1) 140 pb = 4; 141 else 142 pb = 16; 143 144 if(pb > 16) 145 return -1; 146 147 memset(prefix, 0, 16); 148 149 switch(ae) { 150 case 0: break; 151 case 1: 152 if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted)) 153 return -1; 154 memcpy(prefix, v4prefix, 12); 155 if(omitted) { 156 if (dp == NULL) return -1; 157 memcpy(prefix, dp, 12 + omitted); 158 } 159 if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted); 160 break; 161 case 2: 162 if(omitted > 16 || (pb > omitted && len < pb - omitted)) 163 return -1; 164 if(omitted) { 165 if (dp == NULL) return -1; 166 memcpy(prefix, dp, omitted); 167 } 168 if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted); 169 break; 170 case 3: 171 if(pb > 8 && len < pb - 8) return -1; 172 prefix[0] = 0xfe; 173 prefix[1] = 0x80; 174 if(pb > 8) memcpy(prefix + 8, p, pb - 8); 175 break; 176 default: 177 return -1; 178 } 179 180 memcpy(p_r, prefix, 16); 181 return 1; 182} 183 184static int 185network_address(int ae, const unsigned char *a, unsigned int len, 186 unsigned char *a_r) 187{ 188 return network_prefix(ae, -1, 0, a, NULL, len, a_r); 189} 190 191#define ICHECK(i, l) \ 192 if ((i) + (l) > bodylen || (i) + (l) > length) goto corrupt; 193 194static void 195babel_print_v2(const u_char *cp, u_int length) { 196 u_int i; 197 u_short bodylen; 198 u_char v4_prefix[16] = 199 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 200 u_char v6_prefix[16] = {0}; 201 202 TCHECK2(*cp, 4); 203 if (length < 4) 204 goto corrupt; 205 bodylen = EXTRACT_16BITS(cp + 2); 206 printf(" (%u)", bodylen); 207 208 /* Process the TLVs in the body */ 209 i = 0; 210 while(i < bodylen) { 211 const u_char *message; 212 u_int type, len; 213 214 message = cp + 4 + i; 215 TCHECK2(*message, 2); 216 ICHECK(i, 2); 217 type = message[0]; 218 len = message[1]; 219 220 TCHECK2(*message, 2 + len); 221 ICHECK(i, 2 + len); 222 223 switch(type) { 224 case MESSAGE_PAD1: { 225 if(!vflag) 226 printf(" pad1"); 227 else 228 printf("\n\tPad 1"); 229 } 230 break; 231 232 case MESSAGE_PADN: { 233 if(!vflag) 234 printf(" padN"); 235 else 236 printf("\n\tPad %d", len + 2); 237 } 238 break; 239 240 case MESSAGE_ACK_REQ: { 241 u_short nonce, interval; 242 if(!vflag) 243 printf(" ack-req"); 244 else { 245 printf("\n\tAcknowledgment Request "); 246 if(len < 6) goto corrupt; 247 nonce = EXTRACT_16BITS(message + 4); 248 interval = EXTRACT_16BITS(message + 6); 249 printf("%04x %d", nonce, interval); 250 } 251 } 252 break; 253 254 case MESSAGE_ACK: { 255 u_short nonce; 256 if(!vflag) 257 printf(" ack"); 258 else { 259 printf("\n\tAcknowledgment "); 260 if(len < 2) goto corrupt; 261 nonce = EXTRACT_16BITS(message + 2); 262 printf("%04x", nonce); 263 } 264 } 265 break; 266 267 case MESSAGE_HELLO: { 268 u_short seqno, interval; 269 if(!vflag) 270 printf(" hello"); 271 else { 272 printf("\n\tHello "); 273 if(len < 6) goto corrupt; 274 seqno = EXTRACT_16BITS(message + 4); 275 interval = EXTRACT_16BITS(message + 6); 276 printf("seqno %u interval %u", seqno, interval); 277 } 278 } 279 break; 280 281 case MESSAGE_IHU: { 282 unsigned short txcost, interval; 283 if(!vflag) 284 printf(" ihu"); 285 else { 286 u_char address[16]; 287 int rc; 288 printf("\n\tIHU "); 289 if(len < 6) goto corrupt; 290 txcost = EXTRACT_16BITS(message + 4); 291 interval = EXTRACT_16BITS(message + 6); 292 rc = network_address(message[2], message + 8, len - 6, address); 293 if(rc < 0) { printf("[|babel]"); break; } 294 printf("%s txcost %u interval %d", 295 format_address(address), txcost, interval); 296 } 297 } 298 break; 299 300 case MESSAGE_ROUTER_ID: { 301 if(!vflag) 302 printf(" router-id"); 303 else { 304 printf("\n\tRouter Id"); 305 if(len < 10) goto corrupt; 306 printf(" %s", format_id(message + 4)); 307 } 308 } 309 break; 310 311 case MESSAGE_NH: { 312 if(!vflag) 313 printf(" nh"); 314 else { 315 int rc; 316 u_char nh[16]; 317 printf("\n\tNext Hop"); 318 if(len < 2) goto corrupt; 319 rc = network_address(message[2], message + 4, len - 2, nh); 320 if(rc < 0) goto corrupt; 321 printf(" %s", format_address(nh)); 322 } 323 } 324 break; 325 326 case MESSAGE_UPDATE: { 327 if(!vflag) { 328 printf(" update"); 329 if(len < 1) 330 printf("/truncated"); 331 else 332 printf("%s%s%s", 333 (message[3] & 0x80) ? "/prefix": "", 334 (message[3] & 0x40) ? "/id" : "", 335 (message[3] & 0x3f) ? "/unknown" : ""); 336 } else { 337 u_short interval, seqno, metric; 338 u_char plen; 339 int rc; 340 u_char prefix[16]; 341 printf("\n\tUpdate"); 342 if(len < 10) goto corrupt; 343 plen = message[4] + (message[2] == 1 ? 96 : 0); 344 rc = network_prefix(message[2], message[4], message[5], 345 message + 12, 346 message[2] == 1 ? v4_prefix : v6_prefix, 347 len - 10, prefix); 348 if(rc < 0) goto corrupt; 349 interval = EXTRACT_16BITS(message + 6); 350 seqno = EXTRACT_16BITS(message + 8); 351 metric = EXTRACT_16BITS(message + 10); 352 printf("%s%s%s %s metric %u seqno %u interval %u", 353 (message[3] & 0x80) ? "/prefix": "", 354 (message[3] & 0x40) ? "/id" : "", 355 (message[3] & 0x3f) ? "/unknown" : "", 356 format_prefix(prefix, plen), 357 metric, seqno, interval); 358 if(message[3] & 0x80) { 359 if(message[2] == 1) 360 memcpy(v4_prefix, prefix, 16); 361 else 362 memcpy(v6_prefix, prefix, 16); 363 } 364 } 365 } 366 break; 367 368 case MESSAGE_REQUEST: { 369 if(!vflag) 370 printf(" request"); 371 else { 372 int rc; 373 u_char prefix[16], plen; 374 printf("\n\tRequest "); 375 if(len < 2) goto corrupt; 376 plen = message[3] + (message[2] == 1 ? 96 : 0); 377 rc = network_prefix(message[2], message[3], 0, 378 message + 4, NULL, len - 2, prefix); 379 if(rc < 0) goto corrupt; 380 plen = message[3] + (message[2] == 1 ? 96 : 0); 381 printf("for %s", 382 message[2] == 0 ? "any" : format_prefix(prefix, plen)); 383 } 384 } 385 break; 386 387 case MESSAGE_MH_REQUEST : { 388 if(!vflag) 389 printf(" mh-request"); 390 else { 391 int rc; 392 u_short seqno; 393 u_char prefix[16], plen; 394 printf("\n\tMH-Request "); 395 if(len < 14) goto corrupt; 396 seqno = EXTRACT_16BITS(message + 4); 397 rc = network_prefix(message[2], message[3], 0, 398 message + 16, NULL, len - 14, prefix); 399 if(rc < 0) goto corrupt; 400 plen = message[3] + (message[2] == 1 ? 96 : 0); 401 printf("(%u hops) for %s seqno %u id %s", 402 message[6], format_prefix(prefix, plen), 403 seqno, format_id(message + 8)); 404 } 405 } 406 break; 407 case MESSAGE_TSPC : 408 if(!vflag) 409 printf(" tspc"); 410 else { 411 printf("\n\tTS/PC "); 412 if(len < 6) goto corrupt; 413 printf("timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4), 414 EXTRACT_16BITS(message + 2)); 415 } 416 break; 417 case MESSAGE_HMAC : { 418 if(!vflag) 419 printf(" hmac"); 420 else { 421 unsigned j; 422 printf("\n\tHMAC "); 423 if(len < 18) goto corrupt; 424 printf("key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2); 425 for (j = 0; j < len - 2; j++) 426 printf ("%02X", message[4 + j]); 427 } 428 } 429 break; 430 default: 431 if(!vflag) 432 printf(" unknown"); 433 else 434 printf("\n\tUnknown message type %d", type); 435 } 436 i += len + 2; 437 } 438 return; 439 440 trunc: 441 printf(" [|babel]"); 442 return; 443 444 corrupt: 445 printf(" (corrupt)"); 446 return; 447} 448