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 char rcsid[] = 24 "@(#) $Header: print-dvmrp.c,v 1.9 96/07/23 14:17:23 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_report(const u_char *, const u_char *, u_int); 75 static void print_neighbors(const u_char *, const u_char *, u_int); 76 static void print_neighbors2(const u_char *, const u_char *, u_int); 77 static void print_prune(const u_char *, const u_char *, u_int); 78 static void print_graft(const u_char *, const u_char *, u_int); 79 static void print_graft_ack(const u_char *, const u_char *, u_int); 80 81 static u_int32_t target_level; 82 83 void 84 dvmrp_print(register const u_char *bp, register u_int len) 85 { 86 register const u_char *ep; 87 register u_char type; 88 89 ep = (const u_char *)snapend; 90 if (bp >= ep) 91 return; 92 93 type = bp[1]; 94 bp += 8; 95 /* 96 * Skip IGMP header 97 */ 98 99 len -= 8; 100 101 switch (type) { 102 case DVMRP_PROBE: 103 printf(" Probe"); 104 break; 105 106 case DVMRP_REPORT: 107 printf(" Report"); 108 if (vflag) 109 print_report(bp, ep, len); 110 break; 111 112 case DVMRP_ASK_NEIGHBORS: 113 printf(" Ask-neighbors(old)"); 114 break; 115 116 case DVMRP_NEIGHBORS: 117 printf(" Neighbors(old)"); 118 print_neighbors(bp, ep, len); 119 break; 120 121 case DVMRP_ASK_NEIGHBORS2: 122 printf(" Ask-neighbors"); 123 break; 124 125 case DVMRP_NEIGHBORS2: 126 printf(" Neighbors"); 127 bp -= 4; 128 target_level = ((u_int32_t) * bp++ << 24); 129 /* 130 * Group address in IGMP 131 */ 132 133 target_level += ((u_int32_t) * bp++ << 16); 134 /* 135 * header is version number 136 */ 137 138 target_level += ((u_int32_t) * bp++ << 8); 139 target_level += ((u_int32_t) * bp++); 140 target_level = htonl(target_level); 141 print_neighbors2(bp, ep, len); 142 break; 143 144 case DVMRP_PRUNE: 145 printf(" Prune"); 146 print_prune(bp, ep, len); 147 break; 148 149 case DVMRP_GRAFT: 150 printf(" Graft"); 151 print_graft(bp, ep, len); 152 break; 153 154 case DVMRP_GRAFT_ACK: 155 printf(" Graft-ACK"); 156 print_graft_ack(bp, ep, len); 157 break; 158 159 default: 160 printf(" [type %d]", type); 161 break; 162 } 163 } 164 165 static void 166 print_report(const u_char *bp, const u_char *ep, u_int len) 167 { 168 u_int32_t mask, origin; 169 int metric; 170 int i; 171 int width; 172 int done; 173 174 while (len > 0) { 175 if (len < 3) { 176 printf(" [|]"); 177 return; 178 } 179 mask = 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 #define GET_ADDR(to) (memcpy((char*)to, (char*)bp, 4), bp += 4) 217 218 static void 219 print_neighbors(const u_char *bp, const u_char *ep, u_int len) 220 { 221 u_char laddr[4], neighbor[4]; 222 u_char metric; 223 u_char thresh; 224 u_char save_nflag; 225 int ncount; 226 227 save_nflag = nflag; 228 while (len > 0 && bp < ep) { 229 if (len < 7 || (bp + 7) >= ep) { 230 printf(" [|]"); 231 return; 232 } 233 GET_ADDR(laddr); 234 metric = *bp++; 235 thresh = *bp++; 236 ncount = *bp++; 237 len -= 7; 238 while (--ncount >= 0 && (len >= 4) && (bp + 4) < ep) { 239 GET_ADDR(neighbor); 240 nflag = 0; 241 printf(" [%s ->", ipaddr_string(laddr)); 242 nflag = save_nflag; 243 printf(" %s, (%d/%d)]", 244 ipaddr_string(neighbor), metric, thresh); 245 len -= 4; 246 } 247 } 248 } 249 250 static void 251 print_neighbors2(const u_char *bp, const u_char *ep, u_int len) 252 { 253 u_char laddr[4], neighbor[4]; 254 u_char metric; 255 u_char thresh; 256 u_char flags; 257 u_char save_nflag; 258 int ncount; 259 260 printf(" (v %d.%d):", 261 (int)target_level & 0xff, 262 (int)(target_level >> 8) & 0xff); 263 264 save_nflag = nflag; 265 while (len > 0 && bp < ep) { 266 if (len < 8 || (bp + 8) >= ep) { 267 printf(" [|]"); 268 return; 269 } 270 GET_ADDR(laddr); 271 metric = *bp++; 272 thresh = *bp++; 273 flags = *bp++; 274 ncount = *bp++; 275 len -= 8; 276 while (--ncount >= 0 && (len >= 4) && (bp + 4) < ep) { 277 GET_ADDR(neighbor); 278 nflag = 0; 279 printf(" [%s -> ", ipaddr_string(laddr)); 280 nflag = save_nflag; 281 printf("%s (%d/%d", ipaddr_string(neighbor), 282 metric, thresh); 283 if (flags & DVMRP_NF_TUNNEL) 284 printf("/tunnel"); 285 if (flags & DVMRP_NF_SRCRT) 286 printf("/srcrt"); 287 if (flags & DVMRP_NF_QUERIER) 288 printf("/querier"); 289 if (flags & DVMRP_NF_DISABLED) 290 printf("/disabled"); 291 if (flags & DVMRP_NF_DOWN) 292 printf("/down"); 293 printf(")]"); 294 len -= 4; 295 } 296 if (ncount != -1) { 297 printf(" [|]"); 298 return; 299 } 300 } 301 } 302 303 static void 304 print_prune(const u_char *bp, const u_char *ep, u_int len) 305 { 306 union a { 307 u_char b[4]; 308 u_int32_t i; 309 } prune_timer; 310 311 if (len < 12 || (bp + 12) >= ep) { 312 printf(" [|]"); 313 return; 314 } 315 printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); 316 bp += 8; 317 GET_ADDR(prune_timer.b); 318 printf(" timer %d", (int)ntohl(prune_timer.i)); 319 } 320 321 static void 322 print_graft(const u_char *bp, const u_char *ep, u_int len) 323 { 324 325 if (len < 8 || (bp + 8) >= ep) { 326 printf(" [|]"); 327 return; 328 } 329 printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); 330 } 331 332 static void 333 print_graft_ack(const u_char *bp, const u_char *ep, u_int len) 334 { 335 336 if (len < 8 || (bp + 8) >= ep) { 337 printf(" [|]"); 338 return; 339 } 340 printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); 341 } 342