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