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