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