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