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