1235427Sdelphij/* 2235427Sdelphij * Copyright (c) 2007-2011 Gr��goire Henry, Juliusz Chroboczek 3235427Sdelphij * 4235427Sdelphij * Redistribution and use in source and binary forms, with or without 5235427Sdelphij * modification, are permitted provided that the following conditions 6235427Sdelphij * are met: 7235427Sdelphij * 1. Redistributions of source code must retain the above copyright 8235427Sdelphij * notice, this list of conditions and the following disclaimer. 9235427Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 10235427Sdelphij * notice, this list of conditions and the following disclaimer in the 11235427Sdelphij * documentation and/or other materials provided with the distribution. 12235427Sdelphij * 3. Neither the name of the project nor the names of its contributors 13235427Sdelphij * may be used to endorse or promote products derived from this software 14235427Sdelphij * without specific prior written permission. 15235427Sdelphij * 16235427Sdelphij * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 17235427Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18235427Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19235427Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 20235427Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21235427Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22235427Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23235427Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24235427Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25235427Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26235427Sdelphij * SUCH DAMAGE. 27235427Sdelphij */ 28235427Sdelphij 29235427Sdelphij#ifdef HAVE_CONFIG_H 30235427Sdelphij#include "config.h" 31235427Sdelphij#endif 32235427Sdelphij 33235427Sdelphij#include <tcpdump-stdinc.h> 34235427Sdelphij 35235427Sdelphij#include <stdio.h> 36235427Sdelphij#include <string.h> 37235427Sdelphij 38235427Sdelphij#include "addrtoname.h" 39235427Sdelphij#include "interface.h" 40235427Sdelphij#include "extract.h" 41235427Sdelphij 42235427Sdelphijstatic void babel_print_v2(const u_char *cp, u_int length); 43235427Sdelphij 44235427Sdelphijvoid 45235427Sdelphijbabel_print(const u_char *cp, u_int length) { 46235427Sdelphij printf("babel"); 47235427Sdelphij 48235427Sdelphij TCHECK2(*cp, 4); 49235427Sdelphij 50235427Sdelphij if(cp[0] != 42) { 51235427Sdelphij printf(" malformed header"); 52235427Sdelphij return; 53235427Sdelphij } else { 54235427Sdelphij printf(" %d", cp[1]); 55235427Sdelphij } 56235427Sdelphij 57235427Sdelphij switch(cp[1]) { 58235427Sdelphij case 2: 59235427Sdelphij babel_print_v2(cp,length); 60235427Sdelphij break; 61235427Sdelphij default: 62235427Sdelphij printf(" unknown version"); 63235427Sdelphij break; 64235427Sdelphij } 65235427Sdelphij 66235427Sdelphij return; 67235427Sdelphij 68235427Sdelphij trunc: 69235427Sdelphij printf(" [|babel]"); 70235427Sdelphij return; 71235427Sdelphij} 72235427Sdelphij 73235427Sdelphij#define MESSAGE_PAD1 0 74235427Sdelphij#define MESSAGE_PADN 1 75235427Sdelphij#define MESSAGE_ACK_REQ 2 76235427Sdelphij#define MESSAGE_ACK 3 77235427Sdelphij#define MESSAGE_HELLO 4 78235427Sdelphij#define MESSAGE_IHU 5 79235427Sdelphij#define MESSAGE_ROUTER_ID 6 80235427Sdelphij#define MESSAGE_NH 7 81235427Sdelphij#define MESSAGE_UPDATE 8 82235427Sdelphij#define MESSAGE_REQUEST 9 83235427Sdelphij#define MESSAGE_MH_REQUEST 10 84252283Sdelphij#define MESSAGE_TSPC 11 85252283Sdelphij#define MESSAGE_HMAC 12 86235427Sdelphij 87235427Sdelphijstatic const char * 88235427Sdelphijformat_id(const u_char *id) 89235427Sdelphij{ 90235427Sdelphij static char buf[25]; 91235427Sdelphij snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 92235427Sdelphij id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]); 93235427Sdelphij buf[24] = '\0'; 94235427Sdelphij return buf; 95235427Sdelphij} 96235427Sdelphij 97235427Sdelphijstatic const unsigned char v4prefix[16] = 98235427Sdelphij {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 99235427Sdelphij 100235427Sdelphijstatic const char * 101235427Sdelphijformat_prefix(const u_char *prefix, unsigned char plen) 102235427Sdelphij{ 103235427Sdelphij static char buf[50]; 104235427Sdelphij if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0) 105235427Sdelphij snprintf(buf, 50, "%s/%u", ipaddr_string(prefix + 12), plen - 96); 106235427Sdelphij else 107252283Sdelphij#ifdef INET6 108235427Sdelphij snprintf(buf, 50, "%s/%u", ip6addr_string(prefix), plen); 109252283Sdelphij#else 110252283Sdelphij snprintf(buf, 50, "IPv6 addresses not supported"); 111252283Sdelphij#endif 112235427Sdelphij buf[49] = '\0'; 113235427Sdelphij return buf; 114235427Sdelphij} 115235427Sdelphij 116235427Sdelphijstatic const char * 117235427Sdelphijformat_address(const u_char *prefix) 118235427Sdelphij{ 119235427Sdelphij if(memcmp(prefix, v4prefix, 12) == 0) 120235427Sdelphij return ipaddr_string(prefix + 12); 121235427Sdelphij else 122252283Sdelphij#ifdef INET6 123235427Sdelphij return ip6addr_string(prefix); 124252283Sdelphij#else 125252283Sdelphij return "IPv6 addresses not supported"; 126252283Sdelphij#endif 127235427Sdelphij} 128235427Sdelphij 129235427Sdelphijstatic int 130235427Sdelphijnetwork_prefix(int ae, int plen, unsigned int omitted, 131235427Sdelphij const unsigned char *p, const unsigned char *dp, 132235427Sdelphij unsigned int len, unsigned char *p_r) 133235427Sdelphij{ 134235427Sdelphij unsigned pb; 135235427Sdelphij unsigned char prefix[16]; 136235427Sdelphij 137235427Sdelphij if(plen >= 0) 138235427Sdelphij pb = (plen + 7) / 8; 139235427Sdelphij else if(ae == 1) 140235427Sdelphij pb = 4; 141235427Sdelphij else 142235427Sdelphij pb = 16; 143235427Sdelphij 144235427Sdelphij if(pb > 16) 145235427Sdelphij return -1; 146235427Sdelphij 147235427Sdelphij memset(prefix, 0, 16); 148235427Sdelphij 149235427Sdelphij switch(ae) { 150235427Sdelphij case 0: break; 151235427Sdelphij case 1: 152235427Sdelphij if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted)) 153235427Sdelphij return -1; 154235427Sdelphij memcpy(prefix, v4prefix, 12); 155235427Sdelphij if(omitted) { 156235427Sdelphij if (dp == NULL) return -1; 157235427Sdelphij memcpy(prefix, dp, 12 + omitted); 158235427Sdelphij } 159235427Sdelphij if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted); 160235427Sdelphij break; 161235427Sdelphij case 2: 162235427Sdelphij if(omitted > 16 || (pb > omitted && len < pb - omitted)) 163235427Sdelphij return -1; 164235427Sdelphij if(omitted) { 165235427Sdelphij if (dp == NULL) return -1; 166235427Sdelphij memcpy(prefix, dp, omitted); 167235427Sdelphij } 168235427Sdelphij if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted); 169235427Sdelphij break; 170235427Sdelphij case 3: 171235427Sdelphij if(pb > 8 && len < pb - 8) return -1; 172235427Sdelphij prefix[0] = 0xfe; 173235427Sdelphij prefix[1] = 0x80; 174235427Sdelphij if(pb > 8) memcpy(prefix + 8, p, pb - 8); 175235427Sdelphij break; 176235427Sdelphij default: 177235427Sdelphij return -1; 178235427Sdelphij } 179235427Sdelphij 180235427Sdelphij memcpy(p_r, prefix, 16); 181235427Sdelphij return 1; 182235427Sdelphij} 183235427Sdelphij 184235427Sdelphijstatic int 185235427Sdelphijnetwork_address(int ae, const unsigned char *a, unsigned int len, 186235427Sdelphij unsigned char *a_r) 187235427Sdelphij{ 188235427Sdelphij return network_prefix(ae, -1, 0, a, NULL, len, a_r); 189235427Sdelphij} 190235427Sdelphij 191235427Sdelphij#define ICHECK(i, l) \ 192235427Sdelphij if ((i) + (l) > bodylen || (i) + (l) > length) goto corrupt; 193235427Sdelphij 194235427Sdelphijstatic void 195235427Sdelphijbabel_print_v2(const u_char *cp, u_int length) { 196235427Sdelphij u_int i; 197235427Sdelphij u_short bodylen; 198235427Sdelphij u_char v4_prefix[16] = 199235427Sdelphij {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 200235427Sdelphij u_char v6_prefix[16] = {0}; 201235427Sdelphij 202235427Sdelphij TCHECK2(*cp, 4); 203235427Sdelphij if (length < 4) 204235427Sdelphij goto corrupt; 205235427Sdelphij bodylen = EXTRACT_16BITS(cp + 2); 206235427Sdelphij printf(" (%u)", bodylen); 207235427Sdelphij 208235427Sdelphij /* Process the TLVs in the body */ 209235427Sdelphij i = 0; 210235427Sdelphij while(i < bodylen) { 211235427Sdelphij const u_char *message; 212252283Sdelphij u_int type, len; 213235427Sdelphij 214235427Sdelphij message = cp + 4 + i; 215235427Sdelphij TCHECK2(*message, 2); 216235427Sdelphij ICHECK(i, 2); 217235427Sdelphij type = message[0]; 218235427Sdelphij len = message[1]; 219235427Sdelphij 220235427Sdelphij TCHECK2(*message, 2 + len); 221235427Sdelphij ICHECK(i, 2 + len); 222235427Sdelphij 223235427Sdelphij switch(type) { 224235427Sdelphij case MESSAGE_PAD1: { 225235427Sdelphij if(!vflag) 226235427Sdelphij printf(" pad1"); 227235427Sdelphij else 228235427Sdelphij printf("\n\tPad 1"); 229235427Sdelphij } 230235427Sdelphij break; 231235427Sdelphij 232235427Sdelphij case MESSAGE_PADN: { 233235427Sdelphij if(!vflag) 234235427Sdelphij printf(" padN"); 235235427Sdelphij else 236235427Sdelphij printf("\n\tPad %d", len + 2); 237235427Sdelphij } 238235427Sdelphij break; 239235427Sdelphij 240235427Sdelphij case MESSAGE_ACK_REQ: { 241235427Sdelphij u_short nonce, interval; 242235427Sdelphij if(!vflag) 243235427Sdelphij printf(" ack-req"); 244235427Sdelphij else { 245235427Sdelphij printf("\n\tAcknowledgment Request "); 246235427Sdelphij if(len < 6) goto corrupt; 247235427Sdelphij nonce = EXTRACT_16BITS(message + 4); 248235427Sdelphij interval = EXTRACT_16BITS(message + 6); 249235427Sdelphij printf("%04x %d", nonce, interval); 250235427Sdelphij } 251235427Sdelphij } 252235427Sdelphij break; 253235427Sdelphij 254235427Sdelphij case MESSAGE_ACK: { 255235427Sdelphij u_short nonce; 256235427Sdelphij if(!vflag) 257235427Sdelphij printf(" ack"); 258235427Sdelphij else { 259235427Sdelphij printf("\n\tAcknowledgment "); 260235427Sdelphij if(len < 2) goto corrupt; 261235427Sdelphij nonce = EXTRACT_16BITS(message + 2); 262235427Sdelphij printf("%04x", nonce); 263235427Sdelphij } 264235427Sdelphij } 265235427Sdelphij break; 266235427Sdelphij 267235427Sdelphij case MESSAGE_HELLO: { 268235427Sdelphij u_short seqno, interval; 269235427Sdelphij if(!vflag) 270235427Sdelphij printf(" hello"); 271235427Sdelphij else { 272235427Sdelphij printf("\n\tHello "); 273235427Sdelphij if(len < 6) goto corrupt; 274235427Sdelphij seqno = EXTRACT_16BITS(message + 4); 275235427Sdelphij interval = EXTRACT_16BITS(message + 6); 276235427Sdelphij printf("seqno %u interval %u", seqno, interval); 277235427Sdelphij } 278235427Sdelphij } 279235427Sdelphij break; 280235427Sdelphij 281235427Sdelphij case MESSAGE_IHU: { 282235427Sdelphij unsigned short txcost, interval; 283235427Sdelphij if(!vflag) 284235427Sdelphij printf(" ihu"); 285235427Sdelphij else { 286235427Sdelphij u_char address[16]; 287235427Sdelphij int rc; 288235427Sdelphij printf("\n\tIHU "); 289235427Sdelphij if(len < 6) goto corrupt; 290235427Sdelphij txcost = EXTRACT_16BITS(message + 4); 291235427Sdelphij interval = EXTRACT_16BITS(message + 6); 292235427Sdelphij rc = network_address(message[2], message + 8, len - 6, address); 293235427Sdelphij if(rc < 0) { printf("[|babel]"); break; } 294235427Sdelphij printf("%s txcost %u interval %d", 295235427Sdelphij format_address(address), txcost, interval); 296235427Sdelphij } 297235427Sdelphij } 298235427Sdelphij break; 299235427Sdelphij 300235427Sdelphij case MESSAGE_ROUTER_ID: { 301235427Sdelphij if(!vflag) 302235427Sdelphij printf(" router-id"); 303235427Sdelphij else { 304235427Sdelphij printf("\n\tRouter Id"); 305235427Sdelphij if(len < 10) goto corrupt; 306235427Sdelphij printf(" %s", format_id(message + 4)); 307235427Sdelphij } 308235427Sdelphij } 309235427Sdelphij break; 310235427Sdelphij 311235427Sdelphij case MESSAGE_NH: { 312235427Sdelphij if(!vflag) 313235427Sdelphij printf(" nh"); 314235427Sdelphij else { 315235427Sdelphij int rc; 316235427Sdelphij u_char nh[16]; 317235427Sdelphij printf("\n\tNext Hop"); 318235427Sdelphij if(len < 2) goto corrupt; 319235427Sdelphij rc = network_address(message[2], message + 4, len - 2, nh); 320235427Sdelphij if(rc < 0) goto corrupt; 321235427Sdelphij printf(" %s", format_address(nh)); 322235427Sdelphij } 323235427Sdelphij } 324235427Sdelphij break; 325235427Sdelphij 326235427Sdelphij case MESSAGE_UPDATE: { 327235427Sdelphij if(!vflag) { 328235427Sdelphij printf(" update"); 329235427Sdelphij if(len < 1) 330235427Sdelphij printf("/truncated"); 331235427Sdelphij else 332235427Sdelphij printf("%s%s%s", 333235427Sdelphij (message[3] & 0x80) ? "/prefix": "", 334235427Sdelphij (message[3] & 0x40) ? "/id" : "", 335235427Sdelphij (message[3] & 0x3f) ? "/unknown" : ""); 336235427Sdelphij } else { 337235427Sdelphij u_short interval, seqno, metric; 338235427Sdelphij u_char plen; 339235427Sdelphij int rc; 340235427Sdelphij u_char prefix[16]; 341235427Sdelphij printf("\n\tUpdate"); 342235427Sdelphij if(len < 10) goto corrupt; 343235427Sdelphij plen = message[4] + (message[2] == 1 ? 96 : 0); 344235427Sdelphij rc = network_prefix(message[2], message[4], message[5], 345235427Sdelphij message + 12, 346235427Sdelphij message[2] == 1 ? v4_prefix : v6_prefix, 347235427Sdelphij len - 10, prefix); 348235427Sdelphij if(rc < 0) goto corrupt; 349235427Sdelphij interval = EXTRACT_16BITS(message + 6); 350235427Sdelphij seqno = EXTRACT_16BITS(message + 8); 351235427Sdelphij metric = EXTRACT_16BITS(message + 10); 352235427Sdelphij printf("%s%s%s %s metric %u seqno %u interval %u", 353235427Sdelphij (message[3] & 0x80) ? "/prefix": "", 354235427Sdelphij (message[3] & 0x40) ? "/id" : "", 355235427Sdelphij (message[3] & 0x3f) ? "/unknown" : "", 356235427Sdelphij format_prefix(prefix, plen), 357235427Sdelphij metric, seqno, interval); 358235427Sdelphij if(message[3] & 0x80) { 359235427Sdelphij if(message[2] == 1) 360235427Sdelphij memcpy(v4_prefix, prefix, 16); 361235427Sdelphij else 362235427Sdelphij memcpy(v6_prefix, prefix, 16); 363235427Sdelphij } 364235427Sdelphij } 365235427Sdelphij } 366235427Sdelphij break; 367235427Sdelphij 368235427Sdelphij case MESSAGE_REQUEST: { 369235427Sdelphij if(!vflag) 370235427Sdelphij printf(" request"); 371235427Sdelphij else { 372235427Sdelphij int rc; 373235427Sdelphij u_char prefix[16], plen; 374235427Sdelphij printf("\n\tRequest "); 375235427Sdelphij if(len < 2) goto corrupt; 376235427Sdelphij plen = message[3] + (message[2] == 1 ? 96 : 0); 377235427Sdelphij rc = network_prefix(message[2], message[3], 0, 378235427Sdelphij message + 4, NULL, len - 2, prefix); 379235427Sdelphij if(rc < 0) goto corrupt; 380235427Sdelphij plen = message[3] + (message[2] == 1 ? 96 : 0); 381235427Sdelphij printf("for %s", 382235427Sdelphij message[2] == 0 ? "any" : format_prefix(prefix, plen)); 383235427Sdelphij } 384235427Sdelphij } 385235427Sdelphij break; 386235427Sdelphij 387235427Sdelphij case MESSAGE_MH_REQUEST : { 388235427Sdelphij if(!vflag) 389235427Sdelphij printf(" mh-request"); 390235427Sdelphij else { 391235427Sdelphij int rc; 392235427Sdelphij u_short seqno; 393235427Sdelphij u_char prefix[16], plen; 394235427Sdelphij printf("\n\tMH-Request "); 395235427Sdelphij if(len < 14) goto corrupt; 396235427Sdelphij seqno = EXTRACT_16BITS(message + 4); 397235427Sdelphij rc = network_prefix(message[2], message[3], 0, 398235427Sdelphij message + 16, NULL, len - 14, prefix); 399235427Sdelphij if(rc < 0) goto corrupt; 400235427Sdelphij plen = message[3] + (message[2] == 1 ? 96 : 0); 401235427Sdelphij printf("(%u hops) for %s seqno %u id %s", 402235427Sdelphij message[6], format_prefix(prefix, plen), 403235427Sdelphij seqno, format_id(message + 8)); 404235427Sdelphij } 405235427Sdelphij } 406235427Sdelphij break; 407252283Sdelphij case MESSAGE_TSPC : 408252283Sdelphij if(!vflag) 409252283Sdelphij printf(" tspc"); 410252283Sdelphij else { 411252283Sdelphij printf("\n\tTS/PC "); 412252283Sdelphij if(len < 6) goto corrupt; 413252283Sdelphij printf("timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4), 414252283Sdelphij EXTRACT_16BITS(message + 2)); 415252283Sdelphij } 416252283Sdelphij break; 417252283Sdelphij case MESSAGE_HMAC : { 418252283Sdelphij if(!vflag) 419252283Sdelphij printf(" hmac"); 420252283Sdelphij else { 421252283Sdelphij unsigned j; 422252283Sdelphij printf("\n\tHMAC "); 423252283Sdelphij if(len < 18) goto corrupt; 424252283Sdelphij printf("key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2); 425252283Sdelphij for (j = 0; j < len - 2; j++) 426252283Sdelphij printf ("%02X", message[4 + j]); 427252283Sdelphij } 428252283Sdelphij } 429252283Sdelphij break; 430235427Sdelphij default: 431235427Sdelphij if(!vflag) 432235427Sdelphij printf(" unknown"); 433235427Sdelphij else 434235427Sdelphij printf("\n\tUnknown message type %d", type); 435235427Sdelphij } 436235427Sdelphij i += len + 2; 437235427Sdelphij } 438235427Sdelphij return; 439235427Sdelphij 440235427Sdelphij trunc: 441235427Sdelphij printf(" [|babel]"); 442235427Sdelphij return; 443235427Sdelphij 444235427Sdelphij corrupt: 445235427Sdelphij printf(" (corrupt)"); 446235427Sdelphij return; 447235427Sdelphij} 448