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