1 /* 2 * Copyright (c) 1995, 1996 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 22 #include <sys/cdefs.h> 23 #ifndef lint 24 #if 0 25 static const char rcsid[] _U_ = 26 "@(#) Header: /tcpdump/master/tcpdump/print-dvmrp.c,v 1.27 2003-11-19 09:42:04 guy Exp (LBL)"; 27 #else 28 __RCSID("$NetBSD: print-dvmrp.c,v 1.3 2013/04/06 19:33:08 christos Exp $"); 29 #endif 30 #endif 31 32 #ifdef HAVE_CONFIG_H 33 #include "config.h" 34 #endif 35 36 #include <tcpdump-stdinc.h> 37 38 #include <stdio.h> 39 #include <string.h> 40 #include <stdlib.h> 41 42 #include "interface.h" 43 #include "extract.h" 44 #include "addrtoname.h" 45 46 /* 47 * DVMRP message types and flag values shamelessly stolen from 48 * mrouted/dvmrp.h. 49 */ 50 #define DVMRP_PROBE 1 /* for finding neighbors */ 51 #define DVMRP_REPORT 2 /* for reporting some or all routes */ 52 #define DVMRP_ASK_NEIGHBORS 3 /* sent by mapper, asking for a list */ 53 /* of this router's neighbors */ 54 #define DVMRP_NEIGHBORS 4 /* response to such a request */ 55 #define DVMRP_ASK_NEIGHBORS2 5 /* as above, want new format reply */ 56 #define DVMRP_NEIGHBORS2 6 57 #define DVMRP_PRUNE 7 /* prune message */ 58 #define DVMRP_GRAFT 8 /* graft message */ 59 #define DVMRP_GRAFT_ACK 9 /* graft acknowledgement */ 60 61 /* 62 * 'flags' byte values in DVMRP_NEIGHBORS2 reply. 63 */ 64 #define DVMRP_NF_TUNNEL 0x01 /* neighbors reached via tunnel */ 65 #define DVMRP_NF_SRCRT 0x02 /* tunnel uses IP source routing */ 66 #define DVMRP_NF_DOWN 0x10 /* kernel state of interface */ 67 #define DVMRP_NF_DISABLED 0x20 /* administratively disabled */ 68 #define DVMRP_NF_QUERIER 0x40 /* I am the subnet's querier */ 69 70 static int print_probe(const u_char *, const u_char *, u_int); 71 static int print_report(const u_char *, const u_char *, u_int); 72 static int print_neighbors(const u_char *, const u_char *, u_int); 73 static int print_neighbors2(const u_char *, const u_char *, u_int); 74 static int print_prune(const u_char *); 75 static int print_graft(const u_char *); 76 static int print_graft_ack(const u_char *); 77 78 static u_int32_t target_level; 79 80 void 81 dvmrp_print(register const u_char *bp, register u_int len) 82 { 83 register const u_char *ep; 84 register u_char type; 85 86 ep = (const u_char *)snapend; 87 if (bp >= ep) 88 return; 89 90 TCHECK(bp[1]); 91 type = bp[1]; 92 93 /* Skip IGMP header */ 94 bp += 8; 95 len -= 8; 96 97 switch (type) { 98 99 case DVMRP_PROBE: 100 printf(" Probe"); 101 if (vflag) { 102 if (print_probe(bp, ep, len) < 0) 103 goto trunc; 104 } 105 break; 106 107 case DVMRP_REPORT: 108 printf(" Report"); 109 if (vflag > 1) { 110 if (print_report(bp, ep, len) < 0) 111 goto trunc; 112 } 113 break; 114 115 case DVMRP_ASK_NEIGHBORS: 116 printf(" Ask-neighbors(old)"); 117 break; 118 119 case DVMRP_NEIGHBORS: 120 printf(" Neighbors(old)"); 121 if (print_neighbors(bp, ep, len) < 0) 122 goto trunc; 123 break; 124 125 case DVMRP_ASK_NEIGHBORS2: 126 printf(" Ask-neighbors2"); 127 break; 128 129 case DVMRP_NEIGHBORS2: 130 printf(" Neighbors2"); 131 /* 132 * extract version and capabilities from IGMP group 133 * address field 134 */ 135 bp -= 4; 136 TCHECK2(bp[0], 4); 137 target_level = (bp[0] << 24) | (bp[1] << 16) | 138 (bp[2] << 8) | bp[3]; 139 bp += 4; 140 if (print_neighbors2(bp, ep, len) < 0) 141 goto trunc; 142 break; 143 144 case DVMRP_PRUNE: 145 printf(" Prune"); 146 if (print_prune(bp) < 0) 147 goto trunc; 148 break; 149 150 case DVMRP_GRAFT: 151 printf(" Graft"); 152 if (print_graft(bp) < 0) 153 goto trunc; 154 break; 155 156 case DVMRP_GRAFT_ACK: 157 printf(" Graft-ACK"); 158 if (print_graft_ack(bp) < 0) 159 goto trunc; 160 break; 161 162 default: 163 printf(" [type %d]", type); 164 break; 165 } 166 return; 167 168 trunc: 169 printf("[|dvmrp]"); 170 return; 171 } 172 173 static int 174 print_report(register const u_char *bp, register const u_char *ep, 175 register u_int len) 176 { 177 register u_int32_t mask, origin; 178 register int metric, done; 179 register u_int i, width; 180 181 while (len > 0) { 182 if (len < 3) { 183 printf(" [|]"); 184 return (0); 185 } 186 TCHECK2(bp[0], 3); 187 mask = (u_int32_t)0xff << 24 | bp[0] << 16 | bp[1] << 8 | bp[2]; 188 width = 1; 189 if (bp[0]) 190 width = 2; 191 if (bp[1]) 192 width = 3; 193 if (bp[2]) 194 width = 4; 195 196 printf("\n\tMask %s", intoa(htonl(mask))); 197 bp += 3; 198 len -= 3; 199 do { 200 if (bp + width + 1 > ep) { 201 printf(" [|]"); 202 return (0); 203 } 204 if (len < width + 1) { 205 printf("\n\t [Truncated Report]"); 206 return (0); 207 } 208 origin = 0; 209 for (i = 0; i < width; ++i) { 210 TCHECK(*bp); 211 origin = origin << 8 | *bp++; 212 } 213 for ( ; i < 4; ++i) 214 origin <<= 8; 215 216 TCHECK(*bp); 217 metric = *bp++; 218 done = metric & 0x80; 219 metric &= 0x7f; 220 printf("\n\t %s metric %d", intoa(htonl(origin)), 221 metric); 222 len -= width + 1; 223 } while (!done); 224 } 225 return (0); 226 trunc: 227 return (-1); 228 } 229 230 static int 231 print_probe(register const u_char *bp, register const u_char *ep, 232 register u_int len) 233 { 234 register u_int32_t genid; 235 236 TCHECK2(bp[0], 4); 237 if ((len < 4) || ((bp + 4) > ep)) { 238 /* { (ctags) */ 239 printf(" [|}"); 240 return (0); 241 } 242 genid = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3]; 243 bp += 4; 244 len -= 4; 245 if (vflag > 1) 246 printf("\n\t"); 247 else 248 printf(" "); 249 printf("genid %u", genid); 250 if (vflag < 2) 251 return (0); 252 253 while ((len > 0) && (bp < ep)) { 254 TCHECK2(bp[0], 4); 255 printf("\n\tneighbor %s", ipaddr_string(bp)); 256 bp += 4; len -= 4; 257 } 258 return (0); 259 trunc: 260 return (-1); 261 } 262 263 static int 264 print_neighbors(register const u_char *bp, register const u_char *ep, 265 register u_int len) 266 { 267 const u_char *laddr; 268 register u_char metric; 269 register u_char thresh; 270 register int ncount; 271 272 while (len > 0 && bp < ep) { 273 TCHECK2(bp[0], 7); 274 laddr = bp; 275 bp += 4; 276 metric = *bp++; 277 thresh = *bp++; 278 ncount = *bp++; 279 len -= 7; 280 while (--ncount >= 0) { 281 TCHECK2(bp[0], 4); 282 printf(" [%s ->", ipaddr_string(laddr)); 283 printf(" %s, (%d/%d)]", 284 ipaddr_string(bp), metric, thresh); 285 bp += 4; 286 len -= 4; 287 } 288 } 289 return (0); 290 trunc: 291 return (-1); 292 } 293 294 static int 295 print_neighbors2(register const u_char *bp, register const u_char *ep, 296 register u_int len) 297 { 298 const u_char *laddr; 299 register u_char metric, thresh, flags; 300 register int ncount; 301 302 printf(" (v %d.%d):", 303 (int)target_level & 0xff, 304 (int)(target_level >> 8) & 0xff); 305 306 while (len > 0 && bp < ep) { 307 TCHECK2(bp[0], 8); 308 laddr = bp; 309 bp += 4; 310 metric = *bp++; 311 thresh = *bp++; 312 flags = *bp++; 313 ncount = *bp++; 314 len -= 8; 315 while (--ncount >= 0 && (len >= 4) && (bp + 4) <= ep) { 316 printf(" [%s -> ", ipaddr_string(laddr)); 317 printf("%s (%d/%d", ipaddr_string(bp), 318 metric, thresh); 319 if (flags & DVMRP_NF_TUNNEL) 320 printf("/tunnel"); 321 if (flags & DVMRP_NF_SRCRT) 322 printf("/srcrt"); 323 if (flags & DVMRP_NF_QUERIER) 324 printf("/querier"); 325 if (flags & DVMRP_NF_DISABLED) 326 printf("/disabled"); 327 if (flags & DVMRP_NF_DOWN) 328 printf("/down"); 329 printf(")]"); 330 bp += 4; 331 len -= 4; 332 } 333 if (ncount != -1) { 334 printf(" [|]"); 335 return (0); 336 } 337 } 338 return (0); 339 trunc: 340 return (-1); 341 } 342 343 static int 344 print_prune(register const u_char *bp) 345 { 346 TCHECK2(bp[0], 12); 347 printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); 348 bp += 8; 349 (void)printf(" timer "); 350 relts_print(EXTRACT_32BITS(bp)); 351 return (0); 352 trunc: 353 return (-1); 354 } 355 356 static int 357 print_graft(register const u_char *bp) 358 { 359 TCHECK2(bp[0], 8); 360 printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); 361 return (0); 362 trunc: 363 return (-1); 364 } 365 366 static int 367 print_graft_ack(register const u_char *bp) 368 { 369 TCHECK2(bp[0], 8); 370 printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); 371 return (0); 372 trunc: 373 return (-1); 374 } 375