1 /* 2 * Copyright (c) 2007-2011 Grgoire 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 /* TLVs */ 74 #define MESSAGE_PAD1 0 75 #define MESSAGE_PADN 1 76 #define MESSAGE_ACK_REQ 2 77 #define MESSAGE_ACK 3 78 #define MESSAGE_HELLO 4 79 #define MESSAGE_IHU 5 80 #define MESSAGE_ROUTER_ID 6 81 #define MESSAGE_NH 7 82 #define MESSAGE_UPDATE 8 83 #define MESSAGE_REQUEST 9 84 #define MESSAGE_MH_REQUEST 10 85 #define MESSAGE_TSPC 11 86 #define MESSAGE_HMAC 12 87 88 /* sub-TLVs */ 89 #define MESSAGE_SUB_PAD1 0 90 #define MESSAGE_SUB_PADN 1 91 #define MESSAGE_SUB_DIVERSITY 2 92 93 /* Diversity sub-TLV channel codes */ 94 static const struct tok diversity_str[] = { 95 { 0, "reserved" }, 96 { 255, "all" }, 97 { 0, NULL } 98 }; 99 100 static const char * 101 format_id(const u_char *id) 102 { 103 static char buf[25]; 104 snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 105 id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]); 106 buf[24] = '\0'; 107 return buf; 108 } 109 110 static const unsigned char v4prefix[16] = 111 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 112 113 static const char * 114 format_prefix(const u_char *prefix, unsigned char plen) 115 { 116 static char buf[50]; 117 if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0) 118 snprintf(buf, 50, "%s/%u", ipaddr_string(prefix + 12), plen - 96); 119 else 120 #ifdef INET6 121 snprintf(buf, 50, "%s/%u", ip6addr_string(prefix), plen); 122 #else 123 snprintf(buf, 50, "IPv6 addresses not supported"); 124 #endif 125 buf[49] = '\0'; 126 return buf; 127 } 128 129 static const char * 130 format_address(const u_char *prefix) 131 { 132 if(memcmp(prefix, v4prefix, 12) == 0) 133 return ipaddr_string(prefix + 12); 134 else 135 #ifdef INET6 136 return ip6addr_string(prefix); 137 #else 138 return "IPv6 addresses not supported"; 139 #endif 140 } 141 142 static const char * 143 format_interval(const u_int16_t i) 144 { 145 static char buf[sizeof("0000.0s")]; 146 147 if (i == 0) 148 return "0.0s (bogus)"; 149 snprintf(buf, sizeof(buf), "%u.%us", i / 10, i % 10); 150 return buf; 151 } 152 153 static const char * 154 format_interval_update(const u_int16_t i) 155 { 156 return i == 0xFFFF ? "infinity" : format_interval(i); 157 } 158 159 /* Return number of octets consumed from the input buffer (not the prefix length 160 * in bytes), or -1 for encoding error. */ 161 static int 162 network_prefix(int ae, int plen, unsigned int omitted, 163 const unsigned char *p, const unsigned char *dp, 164 unsigned int len, unsigned char *p_r) 165 { 166 unsigned pb; 167 unsigned char prefix[16]; 168 int consumed = 0; 169 170 if(plen >= 0) 171 pb = (plen + 7) / 8; 172 else if(ae == 1) 173 pb = 4; 174 else 175 pb = 16; 176 177 if(pb > 16) 178 return -1; 179 180 memset(prefix, 0, 16); 181 182 switch(ae) { 183 case 0: break; 184 case 1: 185 if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted)) 186 return -1; 187 memcpy(prefix, v4prefix, 12); 188 if(omitted) { 189 if (dp == NULL) return -1; 190 memcpy(prefix, dp, 12 + omitted); 191 } 192 if(pb > omitted) { 193 memcpy(prefix + 12 + omitted, p, pb - omitted); 194 consumed = pb - omitted; 195 } 196 break; 197 case 2: 198 if(omitted > 16 || (pb > omitted && len < pb - omitted)) 199 return -1; 200 if(omitted) { 201 if (dp == NULL) return -1; 202 memcpy(prefix, dp, omitted); 203 } 204 if(pb > omitted) { 205 memcpy(prefix + omitted, p, pb - omitted); 206 consumed = pb - omitted; 207 } 208 break; 209 case 3: 210 if(pb > 8 && len < pb - 8) return -1; 211 prefix[0] = 0xfe; 212 prefix[1] = 0x80; 213 if(pb > 8) { 214 memcpy(prefix + 8, p, pb - 8); 215 consumed = pb - 8; 216 } 217 break; 218 default: 219 return -1; 220 } 221 222 memcpy(p_r, prefix, 16); 223 return consumed; 224 } 225 226 static int 227 network_address(int ae, const unsigned char *a, unsigned int len, 228 unsigned char *a_r) 229 { 230 return network_prefix(ae, -1, 0, a, NULL, len, a_r); 231 } 232 233 /* 234 * Sub-TLVs consume the "extra data" of Babel TLVs (see Section 4.3 of RFC6126), 235 * their encoding is similar to the encoding of TLVs, but the type namespace is 236 * different: 237 * 238 * o Type 0 stands for Pad1 sub-TLV with the same encoding as the Pad1 TLV. 239 * o Type 1 stands for PadN sub-TLV with the same encoding as the PadN TLV. 240 * o Type 2 stands for Diversity sub-TLV, which propagates diversity routing 241 * data. Its body is a variable-length sequence of 8-bit unsigned integers, 242 * each representing per-hop number of interferring radio channel for the 243 * prefix. Channel 0 is invalid and must not be used in the sub-TLV, channel 244 * 255 interferes with any other channel. 245 * 246 * Sub-TLV types 0 and 1 are valid for any TLV type, whether sub-TLV type 2 is 247 * only valid for TLV type 8 (Update). Note that within an Update TLV a missing 248 * Diversity sub-TLV is not the same as a Diversity sub-TLV with an empty body. 249 * The former would mean a lack of any claims about the interference, and the 250 * latter would state that interference is definitely absent. */ 251 static void 252 subtlvs_print(const u_char *cp, const u_char *ep, const uint8_t tlv_type) { 253 uint8_t subtype, sublen; 254 const char *sep; 255 256 while (cp < ep) { 257 subtype = *cp++; 258 if(subtype == MESSAGE_SUB_PAD1) { 259 printf(" sub-pad1"); 260 continue; 261 } 262 if(cp == ep) 263 goto corrupt; 264 sublen = *cp++; 265 if(cp + sublen > ep) 266 goto corrupt; 267 268 switch(subtype) { 269 case MESSAGE_SUB_PADN: 270 printf(" sub-padn"); 271 cp += sublen; 272 break; 273 case MESSAGE_SUB_DIVERSITY: 274 printf(" sub-diversity"); 275 if (sublen == 0) { 276 printf(" empty"); 277 break; 278 } 279 sep = " "; 280 while(sublen--) { 281 printf("%s%s", sep, tok2str(diversity_str, "%u", *cp++)); 282 sep = "-"; 283 } 284 if(tlv_type != MESSAGE_UPDATE) 285 printf(" (bogus)"); 286 break; 287 default: 288 printf(" sub-unknown-0x%02x", subtype); 289 cp += sublen; 290 } /* switch */ 291 } /* while */ 292 return; 293 294 corrupt: 295 printf(" (corrupt)"); 296 } 297 298 #define ICHECK(i, l) \ 299 if ((i) + (l) > bodylen || (i) + (l) > length) goto corrupt; 300 301 static void 302 babel_print_v2(const u_char *cp, u_int length) { 303 u_int i; 304 u_short bodylen; 305 u_char v4_prefix[16] = 306 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 307 u_char v6_prefix[16] = {0}; 308 309 TCHECK2(*cp, 4); 310 if (length < 4) 311 goto corrupt; 312 bodylen = EXTRACT_16BITS(cp + 2); 313 printf(" (%u)", bodylen); 314 315 /* Process the TLVs in the body */ 316 i = 0; 317 while(i < bodylen) { 318 const u_char *message; 319 u_int type, len; 320 321 message = cp + 4 + i; 322 323 TCHECK2(*message, 1); 324 if((type = message[0]) == MESSAGE_PAD1) { 325 printf(vflag ? "\n\tPad 1" : " pad1"); 326 i += 1; 327 continue; 328 } 329 330 TCHECK2(*message, 2); 331 ICHECK(i, 2); 332 len = message[1]; 333 334 TCHECK2(*message, 2 + len); 335 ICHECK(i, 2 + len); 336 337 switch(type) { 338 case MESSAGE_PADN: { 339 if(!vflag) 340 printf(" padN"); 341 else 342 printf("\n\tPad %d", len + 2); 343 } 344 break; 345 346 case MESSAGE_ACK_REQ: { 347 u_short nonce, interval; 348 if(!vflag) 349 printf(" ack-req"); 350 else { 351 printf("\n\tAcknowledgment Request "); 352 if(len < 6) goto corrupt; 353 nonce = EXTRACT_16BITS(message + 4); 354 interval = EXTRACT_16BITS(message + 6); 355 printf("%04x %s", nonce, format_interval(interval)); 356 } 357 } 358 break; 359 360 case MESSAGE_ACK: { 361 u_short nonce; 362 if(!vflag) 363 printf(" ack"); 364 else { 365 printf("\n\tAcknowledgment "); 366 if(len < 2) goto corrupt; 367 nonce = EXTRACT_16BITS(message + 2); 368 printf("%04x", nonce); 369 } 370 } 371 break; 372 373 case MESSAGE_HELLO: { 374 u_short seqno, interval; 375 if(!vflag) 376 printf(" hello"); 377 else { 378 printf("\n\tHello "); 379 if(len < 6) goto corrupt; 380 seqno = EXTRACT_16BITS(message + 4); 381 interval = EXTRACT_16BITS(message + 6); 382 printf("seqno %u interval %s", seqno, format_interval(interval)); 383 } 384 } 385 break; 386 387 case MESSAGE_IHU: { 388 unsigned short txcost, interval; 389 if(!vflag) 390 printf(" ihu"); 391 else { 392 u_char address[16]; 393 int rc; 394 printf("\n\tIHU "); 395 if(len < 6) goto corrupt; 396 txcost = EXTRACT_16BITS(message + 4); 397 interval = EXTRACT_16BITS(message + 6); 398 rc = network_address(message[2], message + 8, len - 6, address); 399 if(rc < 0) { printf("[|babel]"); break; } 400 printf("%s txcost %u interval %s", 401 format_address(address), txcost, format_interval(interval)); 402 } 403 } 404 break; 405 406 case MESSAGE_ROUTER_ID: { 407 if(!vflag) 408 printf(" router-id"); 409 else { 410 printf("\n\tRouter Id"); 411 if(len < 10) goto corrupt; 412 printf(" %s", format_id(message + 4)); 413 } 414 } 415 break; 416 417 case MESSAGE_NH: { 418 if(!vflag) 419 printf(" nh"); 420 else { 421 int rc; 422 u_char nh[16]; 423 printf("\n\tNext Hop"); 424 if(len < 2) goto corrupt; 425 rc = network_address(message[2], message + 4, len - 2, nh); 426 if(rc < 0) goto corrupt; 427 printf(" %s", format_address(nh)); 428 } 429 } 430 break; 431 432 case MESSAGE_UPDATE: { 433 if(!vflag) { 434 printf(" update"); 435 if(len < 1) 436 printf("/truncated"); 437 else 438 printf("%s%s%s", 439 (message[3] & 0x80) ? "/prefix": "", 440 (message[3] & 0x40) ? "/id" : "", 441 (message[3] & 0x3f) ? "/unknown" : ""); 442 } else { 443 u_short interval, seqno, metric; 444 u_char plen; 445 int rc; 446 u_char prefix[16]; 447 printf("\n\tUpdate"); 448 if(len < 10) goto corrupt; 449 plen = message[4] + (message[2] == 1 ? 96 : 0); 450 rc = network_prefix(message[2], message[4], message[5], 451 message + 12, 452 message[2] == 1 ? v4_prefix : v6_prefix, 453 len - 10, prefix); 454 if(rc < 0) goto corrupt; 455 interval = EXTRACT_16BITS(message + 6); 456 seqno = EXTRACT_16BITS(message + 8); 457 metric = EXTRACT_16BITS(message + 10); 458 printf("%s%s%s %s metric %u seqno %u interval %s", 459 (message[3] & 0x80) ? "/prefix": "", 460 (message[3] & 0x40) ? "/id" : "", 461 (message[3] & 0x3f) ? "/unknown" : "", 462 format_prefix(prefix, plen), 463 metric, seqno, format_interval_update(interval)); 464 if(message[3] & 0x80) { 465 if(message[2] == 1) 466 memcpy(v4_prefix, prefix, 16); 467 else 468 memcpy(v6_prefix, prefix, 16); 469 } 470 /* extra data? */ 471 if((u_int)rc < len - 10) 472 subtlvs_print(message + 12 + rc, message + 2 + len, type); 473 } 474 } 475 break; 476 477 case MESSAGE_REQUEST: { 478 if(!vflag) 479 printf(" request"); 480 else { 481 int rc; 482 u_char prefix[16], plen; 483 printf("\n\tRequest "); 484 if(len < 2) goto corrupt; 485 plen = message[3] + (message[2] == 1 ? 96 : 0); 486 rc = network_prefix(message[2], message[3], 0, 487 message + 4, NULL, len - 2, prefix); 488 if(rc < 0) goto corrupt; 489 plen = message[3] + (message[2] == 1 ? 96 : 0); 490 printf("for %s", 491 message[2] == 0 ? "any" : format_prefix(prefix, plen)); 492 } 493 } 494 break; 495 496 case MESSAGE_MH_REQUEST : { 497 if(!vflag) 498 printf(" mh-request"); 499 else { 500 int rc; 501 u_short seqno; 502 u_char prefix[16], plen; 503 printf("\n\tMH-Request "); 504 if(len < 14) goto corrupt; 505 seqno = EXTRACT_16BITS(message + 4); 506 rc = network_prefix(message[2], message[3], 0, 507 message + 16, NULL, len - 14, prefix); 508 if(rc < 0) goto corrupt; 509 plen = message[3] + (message[2] == 1 ? 96 : 0); 510 printf("(%u hops) for %s seqno %u id %s", 511 message[6], format_prefix(prefix, plen), 512 seqno, format_id(message + 8)); 513 } 514 } 515 break; 516 case MESSAGE_TSPC : 517 if(!vflag) 518 printf(" tspc"); 519 else { 520 printf("\n\tTS/PC "); 521 if(len < 6) goto corrupt; 522 printf("timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4), 523 EXTRACT_16BITS(message + 2)); 524 } 525 break; 526 case MESSAGE_HMAC : { 527 if(!vflag) 528 printf(" hmac"); 529 else { 530 unsigned j; 531 printf("\n\tHMAC "); 532 if(len < 18) goto corrupt; 533 printf("key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2); 534 for (j = 0; j < len - 2; j++) 535 printf ("%02X", message[4 + j]); 536 } 537 } 538 break; 539 default: 540 if(!vflag) 541 printf(" unknown"); 542 else 543 printf("\n\tUnknown message type %d", type); 544 } 545 i += len + 2; 546 } 547 return; 548 549 trunc: 550 printf(" [|babel]"); 551 return; 552 553 corrupt: 554 printf(" (corrupt)"); 555 return; 556 } 557