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[] = 24 "@(#) $Header: /tcpdump/master/tcpdump/print-dvmrp.c,v 1.21 2001/05/10 05:30:20 fenner Exp $ (LBL)"; 25 #endif 26 27 #ifdef HAVE_CONFIG_H 28 #include "config.h" 29 #endif 30 31 #include <sys/param.h> 32 #include <sys/time.h> 33 #include <sys/socket.h> 34 35 #include <netinet/in.h> 36 37 #include <stdio.h> 38 #include <string.h> 39 #include <stdlib.h> 40 #include <unistd.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 void print_probe(const u_char *, const u_char *, u_int); 71 static void print_report(const u_char *, const u_char *, u_int); 72 static void print_neighbors(const u_char *, const u_char *, u_int); 73 static void print_neighbors2(const u_char *, const u_char *, u_int); 74 static void print_prune(const u_char *, const u_char *, u_int); 75 static void print_graft(const u_char *, const u_char *, u_int); 76 static void print_graft_ack(const u_char *, const u_char *, u_int); 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 type = bp[1]; 91 92 /* Skip IGMP header */ 93 bp += 8; 94 len -= 8; 95 96 switch (type) { 97 98 case DVMRP_PROBE: 99 printf(" Probe"); 100 if (vflag) 101 print_probe(bp, ep, len); 102 break; 103 104 case DVMRP_REPORT: 105 printf(" Report"); 106 if (vflag > 1) 107 print_report(bp, ep, len); 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 print_neighbors(bp, ep, len); 117 break; 118 119 case DVMRP_ASK_NEIGHBORS2: 120 printf(" Ask-neighbors2"); 121 break; 122 123 case DVMRP_NEIGHBORS2: 124 printf(" Neighbors2"); 125 /* 126 * extract version and capabilities from IGMP group 127 * address field 128 */ 129 bp -= 4; 130 target_level = (bp[0] << 24) | (bp[1] << 16) | 131 (bp[2] << 8) | bp[3]; 132 bp += 4; 133 print_neighbors2(bp, ep, len); 134 break; 135 136 case DVMRP_PRUNE: 137 printf(" Prune"); 138 print_prune(bp, ep, len); 139 break; 140 141 case DVMRP_GRAFT: 142 printf(" Graft"); 143 print_graft(bp, ep, len); 144 break; 145 146 case DVMRP_GRAFT_ACK: 147 printf(" Graft-ACK"); 148 print_graft_ack(bp, ep, len); 149 break; 150 151 default: 152 printf(" [type %d]", type); 153 break; 154 } 155 } 156 157 static void 158 print_report(register const u_char *bp, register const u_char *ep, 159 register u_int len) 160 { 161 register u_int32_t mask, origin; 162 register int metric, i, width, done; 163 164 while (len > 0) { 165 if (len < 3) { 166 printf(" [|]"); 167 return; 168 } 169 mask = (u_int32_t)0xff << 24 | bp[0] << 16 | bp[1] << 8 | bp[2]; 170 width = 1; 171 if (bp[0]) 172 width = 2; 173 if (bp[1]) 174 width = 3; 175 if (bp[2]) 176 width = 4; 177 178 printf("\n\tMask %s", intoa(htonl(mask))); 179 bp += 3; 180 len -= 3; 181 do { 182 if (bp + width + 1 > ep) { 183 printf(" [|]"); 184 return; 185 } 186 if (len < width + 1) { 187 printf("\n\t [Truncated Report]"); 188 return; 189 } 190 origin = 0; 191 for (i = 0; i < width; ++i) 192 origin = origin << 8 | *bp++; 193 for ( ; i < 4; ++i) 194 origin <<= 8; 195 196 metric = *bp++; 197 done = metric & 0x80; 198 metric &= 0x7f; 199 printf("\n\t %s metric %d", intoa(htonl(origin)), 200 metric); 201 len -= width + 1; 202 } while (!done); 203 } 204 } 205 206 static void 207 print_probe(register const u_char *bp, register const u_char *ep, 208 register u_int len) 209 { 210 register u_int32_t genid; 211 212 TCHECK2(bp[0], 4); 213 if ((len < 4) || ((bp + 4) > ep)) { 214 /* { (ctags) */ 215 printf(" [|}"); 216 return; 217 } 218 genid = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3]; 219 bp += 4; 220 len -= 4; 221 if (vflag > 1) 222 printf("\n\t"); 223 else 224 printf(" "); 225 printf("genid %u", genid); 226 if (vflag < 2) 227 return; 228 229 while ((len > 0) && (bp < ep)) { 230 TCHECK2(bp[0], 4); 231 printf("\n\tneighbor %s", ipaddr_string(bp)); 232 bp += 4; len -= 4; 233 } 234 return; 235 trunc: 236 (void)printf("[|dvmrp]"); 237 } 238 239 static void 240 print_neighbors(register const u_char *bp, register const u_char *ep, 241 register u_int len) 242 { 243 const u_char *laddr; 244 register u_char metric; 245 register u_char thresh; 246 register int ncount; 247 248 while (len > 0 && bp < ep) { 249 TCHECK2(bp[0], 7); 250 laddr = bp; 251 bp += 4; 252 metric = *bp++; 253 thresh = *bp++; 254 ncount = *bp++; 255 len -= 7; 256 while (--ncount >= 0) { 257 TCHECK2(bp[0], 4); 258 printf(" [%s ->", ipaddr_string(laddr)); 259 printf(" %s, (%d/%d)]", 260 ipaddr_string(bp), metric, thresh); 261 bp += 4; 262 len -= 4; 263 } 264 } 265 return; 266 trunc: 267 (void)printf("[|dvmrp]"); 268 } 269 270 static void 271 print_neighbors2(register const u_char *bp, register const u_char *ep, 272 register u_int len) 273 { 274 const u_char *laddr; 275 register u_char metric, thresh, flags; 276 register int ncount; 277 278 printf(" (v %d.%d):", 279 (int)target_level & 0xff, 280 (int)(target_level >> 8) & 0xff); 281 282 while (len > 0 && bp < ep) { 283 TCHECK2(bp[0], 8); 284 laddr = bp; 285 bp += 4; 286 metric = *bp++; 287 thresh = *bp++; 288 flags = *bp++; 289 ncount = *bp++; 290 len -= 8; 291 while (--ncount >= 0 && (len >= 4) && (bp + 4) <= ep) { 292 printf(" [%s -> ", ipaddr_string(laddr)); 293 printf("%s (%d/%d", ipaddr_string(bp), 294 metric, thresh); 295 if (flags & DVMRP_NF_TUNNEL) 296 printf("/tunnel"); 297 if (flags & DVMRP_NF_SRCRT) 298 printf("/srcrt"); 299 if (flags & DVMRP_NF_QUERIER) 300 printf("/querier"); 301 if (flags & DVMRP_NF_DISABLED) 302 printf("/disabled"); 303 if (flags & DVMRP_NF_DOWN) 304 printf("/down"); 305 printf(")]"); 306 bp += 4; 307 len -= 4; 308 } 309 if (ncount != -1) { 310 printf(" [|]"); 311 return; 312 } 313 } 314 return; 315 trunc: 316 (void)printf("[|dvmrp]"); 317 } 318 319 static void 320 print_prune(register const u_char *bp, register const u_char *ep, 321 register u_int len) 322 { 323 TCHECK2(bp[0], 12); 324 printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); 325 bp += 8; 326 (void)printf(" timer "); 327 relts_print(EXTRACT_32BITS(bp)); 328 return; 329 trunc: 330 (void)printf("[|dvmrp]"); 331 } 332 333 static void 334 print_graft(register const u_char *bp, register const u_char *ep, 335 register u_int len) 336 { 337 TCHECK2(bp[0], 8); 338 printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); 339 return; 340 trunc: 341 (void)printf("[|dvmrp]"); 342 } 343 344 static void 345 print_graft_ack(register const u_char *bp, register const u_char *ep, 346 register u_int len) 347 { 348 TCHECK2(bp[0], 8); 349 printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); 350 return; 351 trunc: 352 (void)printf("[|dvmrp]"); 353 } 354