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