10f74e101Schristos /* 20f74e101Schristos * Copyright (c) 1995, 1996 30f74e101Schristos * The Regents of the University of California. All rights reserved. 40f74e101Schristos * 50f74e101Schristos * Redistribution and use in source and binary forms, with or without 60f74e101Schristos * modification, are permitted provided that: (1) source code distributions 70f74e101Schristos * retain the above copyright notice and this paragraph in its entirety, (2) 80f74e101Schristos * distributions including binary code include the above copyright notice and 90f74e101Schristos * this paragraph in its entirety in the documentation or other materials 100f74e101Schristos * provided with the distribution, and (3) all advertising materials mentioning 110f74e101Schristos * features or use of this software display the following acknowledgement: 120f74e101Schristos * ``This product includes software developed by the University of California, 130f74e101Schristos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 140f74e101Schristos * the University nor the names of its contributors may be used to endorse 150f74e101Schristos * or promote products derived from this software without specific prior 160f74e101Schristos * written permission. 170f74e101Schristos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 180f74e101Schristos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 190f74e101Schristos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 200f74e101Schristos */ 210f74e101Schristos 2211b3aaa1Schristos #include <sys/cdefs.h> 230f74e101Schristos #ifndef lint 24*26ba0b50Schristos __RCSID("$NetBSD: print-dvmrp.c,v 1.9 2024/09/02 16:15:31 christos Exp $"); 250f74e101Schristos #endif 260f74e101Schristos 27dc860a36Sspz /* \summary: Distance Vector Multicast Routing Protocol printer */ 28dc860a36Sspz 29c74ad251Schristos #include <config.h> 300f74e101Schristos 31c74ad251Schristos #include "netdissect-stdinc.h" 320f74e101Schristos 33fdccd7e4Schristos #include "netdissect.h" 340f74e101Schristos #include "extract.h" 350f74e101Schristos #include "addrtoname.h" 360f74e101Schristos 370f74e101Schristos /* 38817e9a7eSchristos * See: RFC 1075 and draft-ietf-idmr-dvmrp-v3 39817e9a7eSchristos * 400f74e101Schristos * DVMRP message types and flag values shamelessly stolen from 410f74e101Schristos * mrouted/dvmrp.h. 420f74e101Schristos */ 430f74e101Schristos #define DVMRP_PROBE 1 /* for finding neighbors */ 440f74e101Schristos #define DVMRP_REPORT 2 /* for reporting some or all routes */ 450f74e101Schristos #define DVMRP_ASK_NEIGHBORS 3 /* sent by mapper, asking for a list */ 460f74e101Schristos /* of this router's neighbors */ 470f74e101Schristos #define DVMRP_NEIGHBORS 4 /* response to such a request */ 480f74e101Schristos #define DVMRP_ASK_NEIGHBORS2 5 /* as above, want new format reply */ 490f74e101Schristos #define DVMRP_NEIGHBORS2 6 500f74e101Schristos #define DVMRP_PRUNE 7 /* prune message */ 510f74e101Schristos #define DVMRP_GRAFT 8 /* graft message */ 520f74e101Schristos #define DVMRP_GRAFT_ACK 9 /* graft acknowledgement */ 53c74ad251Schristos static const struct tok dvmrp_msgtype_str[] = { 54c74ad251Schristos { DVMRP_PROBE, "Probe" }, 55c74ad251Schristos { DVMRP_REPORT, "Report" }, 56c74ad251Schristos { DVMRP_ASK_NEIGHBORS, "Ask-neighbors(old)" }, 57c74ad251Schristos { DVMRP_NEIGHBORS, "Neighbors(old)" }, 58c74ad251Schristos { DVMRP_ASK_NEIGHBORS2, "Ask-neighbors2" }, 59c74ad251Schristos { DVMRP_NEIGHBORS2, "Neighbors2" }, 60c74ad251Schristos { DVMRP_PRUNE, "Prune" }, 61c74ad251Schristos { DVMRP_GRAFT, "Graft" }, 62c74ad251Schristos { DVMRP_GRAFT_ACK, "Graft-ACK" }, 63c74ad251Schristos { 0, NULL } 64c74ad251Schristos }; 650f74e101Schristos 660f74e101Schristos /* 670f74e101Schristos * 'flags' byte values in DVMRP_NEIGHBORS2 reply. 680f74e101Schristos */ 690f74e101Schristos #define DVMRP_NF_TUNNEL 0x01 /* neighbors reached via tunnel */ 700f74e101Schristos #define DVMRP_NF_SRCRT 0x02 /* tunnel uses IP source routing */ 710f74e101Schristos #define DVMRP_NF_DOWN 0x10 /* kernel state of interface */ 720f74e101Schristos #define DVMRP_NF_DISABLED 0x20 /* administratively disabled */ 730f74e101Schristos #define DVMRP_NF_QUERIER 0x40 /* I am the subnet's querier */ 740f74e101Schristos 75c74ad251Schristos static void print_probe(netdissect_options *, const u_char *, u_int); 76c74ad251Schristos static void print_report(netdissect_options *, const u_char *, u_int); 77c74ad251Schristos static void print_neighbors(netdissect_options *, const u_char *, u_int); 78c74ad251Schristos static void print_neighbors2(netdissect_options *, const u_char *, u_int, uint8_t, uint8_t); 790f74e101Schristos 800f74e101Schristos void 81b3a00663Schristos dvmrp_print(netdissect_options *ndo, 82c74ad251Schristos const u_char *bp, u_int len) 830f74e101Schristos { 84c74ad251Schristos u_char type; 85817e9a7eSchristos uint8_t major_version, minor_version; 860f74e101Schristos 87c74ad251Schristos ndo->ndo_protocol = "dvmrp"; 88c74ad251Schristos if (len < 8) { 89c74ad251Schristos ND_PRINT(" [length %u < 8]", len); 90c74ad251Schristos goto invalid; 91c74ad251Schristos } 920f74e101Schristos 93c74ad251Schristos type = GET_U_1(bp + 1); 940f74e101Schristos 950f74e101Schristos /* Skip IGMP header */ 960f74e101Schristos bp += 8; 970f74e101Schristos len -= 8; 980f74e101Schristos 99c74ad251Schristos ND_PRINT(" %s", tok2str(dvmrp_msgtype_str, "[type %u]", type)); 1000f74e101Schristos switch (type) { 1010f74e101Schristos 1020f74e101Schristos case DVMRP_PROBE: 103b3a00663Schristos if (ndo->ndo_vflag) { 104c74ad251Schristos print_probe(ndo, bp, len); 1050f74e101Schristos } 1060f74e101Schristos break; 1070f74e101Schristos 1080f74e101Schristos case DVMRP_REPORT: 109b3a00663Schristos if (ndo->ndo_vflag > 1) { 110c74ad251Schristos print_report(ndo, bp, len); 1110f74e101Schristos } 1120f74e101Schristos break; 1130f74e101Schristos 1140f74e101Schristos case DVMRP_NEIGHBORS: 115c74ad251Schristos print_neighbors(ndo, bp, len); 1160f74e101Schristos break; 1170f74e101Schristos 1180f74e101Schristos case DVMRP_NEIGHBORS2: 1190f74e101Schristos /* 120817e9a7eSchristos * extract version from IGMP group address field 1210f74e101Schristos */ 1220f74e101Schristos bp -= 4; 123c74ad251Schristos major_version = GET_U_1(bp + 3); 124c74ad251Schristos minor_version = GET_U_1(bp + 2); 1250f74e101Schristos bp += 4; 126c74ad251Schristos print_neighbors2(ndo, bp, len, major_version, minor_version); 1270f74e101Schristos break; 1280f74e101Schristos 1290f74e101Schristos case DVMRP_PRUNE: 130c74ad251Schristos ND_PRINT(" src %s grp %s", GET_IPADDR_STRING(bp), GET_IPADDR_STRING(bp + 4)); 131c74ad251Schristos ND_PRINT(" timer "); 132c74ad251Schristos unsigned_relts_print(ndo, GET_BE_U_4(bp + 8)); 1330f74e101Schristos break; 1340f74e101Schristos 1350f74e101Schristos case DVMRP_GRAFT: 136c74ad251Schristos ND_PRINT(" src %s grp %s", GET_IPADDR_STRING(bp), GET_IPADDR_STRING(bp + 4)); 1370f74e101Schristos break; 1380f74e101Schristos 1390f74e101Schristos case DVMRP_GRAFT_ACK: 140c74ad251Schristos ND_PRINT(" src %s grp %s", GET_IPADDR_STRING(bp), GET_IPADDR_STRING(bp + 4)); 1410f74e101Schristos break; 1420f74e101Schristos } 1430f74e101Schristos return; 1440f74e101Schristos 145c74ad251Schristos invalid: 146c74ad251Schristos nd_print_invalid(ndo); 1470f74e101Schristos } 1480f74e101Schristos 149c74ad251Schristos static void 150b3a00663Schristos print_report(netdissect_options *ndo, 151c74ad251Schristos const u_char *bp, 152c74ad251Schristos u_int len) 1530f74e101Schristos { 154c74ad251Schristos uint32_t mask, origin; 155c74ad251Schristos u_int metric, done; 156c74ad251Schristos u_int i, width; 1570f74e101Schristos 1580f74e101Schristos while (len > 0) { 1590f74e101Schristos if (len < 3) { 160c74ad251Schristos ND_PRINT(" [length %u < 3]", len); 161c74ad251Schristos goto invalid; 1620f74e101Schristos } 163c74ad251Schristos mask = (uint32_t)0xff << 24 | GET_U_1(bp) << 16 | 164c74ad251Schristos GET_U_1(bp + 1) << 8 | GET_U_1(bp + 2); 1650f74e101Schristos width = 1; 166c74ad251Schristos if (GET_U_1(bp)) 1670f74e101Schristos width = 2; 168c74ad251Schristos if (GET_U_1(bp + 1)) 1690f74e101Schristos width = 3; 170c74ad251Schristos if (GET_U_1(bp + 2)) 1710f74e101Schristos width = 4; 1720f74e101Schristos 173c74ad251Schristos ND_PRINT("\n\tMask %s", intoa(htonl(mask))); 1740f74e101Schristos bp += 3; 1750f74e101Schristos len -= 3; 1760f74e101Schristos do { 1770f74e101Schristos if (len < width + 1) { 178c74ad251Schristos ND_PRINT("\n\t [Truncated Report]"); 179c74ad251Schristos goto invalid; 1800f74e101Schristos } 1810f74e101Schristos origin = 0; 1820f74e101Schristos for (i = 0; i < width; ++i) { 183c74ad251Schristos origin = origin << 8 | GET_U_1(bp); 184c74ad251Schristos bp++; 1850f74e101Schristos } 1860f74e101Schristos for ( ; i < 4; ++i) 1870f74e101Schristos origin <<= 8; 1880f74e101Schristos 189c74ad251Schristos metric = GET_U_1(bp); 190c74ad251Schristos bp++; 1910f74e101Schristos done = metric & 0x80; 1920f74e101Schristos metric &= 0x7f; 193c74ad251Schristos ND_PRINT("\n\t %s metric %u", intoa(htonl(origin)), 194c74ad251Schristos metric); 1950f74e101Schristos len -= width + 1; 1960f74e101Schristos } while (!done); 1970f74e101Schristos } 198c74ad251Schristos return; 199c74ad251Schristos 200c74ad251Schristos invalid: 201c74ad251Schristos nd_print_invalid(ndo); 2020f74e101Schristos } 2030f74e101Schristos 204c74ad251Schristos static void 205b3a00663Schristos print_probe(netdissect_options *ndo, 206c74ad251Schristos const u_char *bp, 207c74ad251Schristos u_int len) 2080f74e101Schristos { 209c74ad251Schristos if (len < 4) { 210c74ad251Schristos ND_PRINT(" [full length %u < 4]", len); 211c74ad251Schristos goto invalid; 2120f74e101Schristos } 213c74ad251Schristos ND_PRINT(ndo->ndo_vflag > 1 ? "\n\t" : " "); 214c74ad251Schristos ND_PRINT("genid %u", GET_BE_U_4(bp)); 215c74ad251Schristos if (ndo->ndo_vflag < 2) 216c74ad251Schristos return; 217c74ad251Schristos 2180f74e101Schristos bp += 4; 2190f74e101Schristos len -= 4; 220c74ad251Schristos while (len > 0) { 221c74ad251Schristos if (len < 4) { 222c74ad251Schristos ND_PRINT("[remaining length %u < 4]", len); 223c74ad251Schristos goto invalid; 224c74ad251Schristos } 225c74ad251Schristos ND_PRINT("\n\tneighbor %s", GET_IPADDR_STRING(bp)); 2260f74e101Schristos bp += 4; len -= 4; 2270f74e101Schristos } 228c74ad251Schristos return; 229c74ad251Schristos 230c74ad251Schristos invalid: 231c74ad251Schristos nd_print_invalid(ndo); 2320f74e101Schristos } 2330f74e101Schristos 234c74ad251Schristos static void 235b3a00663Schristos print_neighbors(netdissect_options *ndo, 236c74ad251Schristos const u_char *bp, 237c74ad251Schristos u_int len) 2380f74e101Schristos { 2390f74e101Schristos const u_char *laddr; 240c74ad251Schristos u_char metric; 241c74ad251Schristos u_char thresh; 242c74ad251Schristos int ncount; 2430f74e101Schristos 244c74ad251Schristos while (len > 0) { 245c74ad251Schristos if (len < 7) { 246c74ad251Schristos ND_PRINT(" [length %u < 7]", len); 247c74ad251Schristos goto invalid; 248c74ad251Schristos } 2490f74e101Schristos laddr = bp; 2500f74e101Schristos bp += 4; 251c74ad251Schristos metric = GET_U_1(bp); 252c74ad251Schristos bp++; 253c74ad251Schristos thresh = GET_U_1(bp); 254c74ad251Schristos bp++; 255c74ad251Schristos ncount = GET_U_1(bp); 256c74ad251Schristos bp++; 2570f74e101Schristos len -= 7; 2580f74e101Schristos while (--ncount >= 0) { 259c74ad251Schristos if (len < 4) { 260c74ad251Schristos ND_PRINT(" [length %u < 4]", len); 261c74ad251Schristos goto invalid; 262c74ad251Schristos } 263c74ad251Schristos ND_PRINT(" [%s ->", GET_IPADDR_STRING(laddr)); 264c74ad251Schristos ND_PRINT(" %s, (%u/%u)]", 265c74ad251Schristos GET_IPADDR_STRING(bp), metric, thresh); 2660f74e101Schristos bp += 4; 2670f74e101Schristos len -= 4; 2680f74e101Schristos } 2690f74e101Schristos } 270c74ad251Schristos return; 271c74ad251Schristos 272c74ad251Schristos invalid: 273c74ad251Schristos nd_print_invalid(ndo); 2740f74e101Schristos } 2750f74e101Schristos 276c74ad251Schristos static void 277b3a00663Schristos print_neighbors2(netdissect_options *ndo, 278c74ad251Schristos const u_char *bp, 279c74ad251Schristos u_int len, uint8_t major_version, 280817e9a7eSchristos uint8_t minor_version) 2810f74e101Schristos { 2820f74e101Schristos const u_char *laddr; 283c74ad251Schristos u_char metric, thresh, flags; 284c74ad251Schristos int ncount; 2850f74e101Schristos 286c74ad251Schristos ND_PRINT(" (v %u.%u):", major_version, minor_version); 2870f74e101Schristos 288c74ad251Schristos while (len > 0) { 289c74ad251Schristos if (len < 8) { 290c74ad251Schristos ND_PRINT(" [length %u < 8]", len); 291c74ad251Schristos goto invalid; 292c74ad251Schristos } 2930f74e101Schristos laddr = bp; 2940f74e101Schristos bp += 4; 295c74ad251Schristos metric = GET_U_1(bp); 296c74ad251Schristos bp++; 297c74ad251Schristos thresh = GET_U_1(bp); 298c74ad251Schristos bp++; 299c74ad251Schristos flags = GET_U_1(bp); 300c74ad251Schristos bp++; 301c74ad251Schristos ncount = GET_U_1(bp); 302c74ad251Schristos bp++; 3030f74e101Schristos len -= 8; 304c74ad251Schristos while (--ncount >= 0 && len > 0) { 305c74ad251Schristos if (len < 4) { 306c74ad251Schristos ND_PRINT(" [length %u < 4]", len); 307c74ad251Schristos goto invalid; 308c74ad251Schristos } 309c74ad251Schristos ND_PRINT(" [%s -> ", GET_IPADDR_STRING(laddr)); 310c74ad251Schristos ND_PRINT("%s (%u/%u", GET_IPADDR_STRING(bp), 311c74ad251Schristos metric, thresh); 3120f74e101Schristos if (flags & DVMRP_NF_TUNNEL) 313c74ad251Schristos ND_PRINT("/tunnel"); 3140f74e101Schristos if (flags & DVMRP_NF_SRCRT) 315c74ad251Schristos ND_PRINT("/srcrt"); 3160f74e101Schristos if (flags & DVMRP_NF_QUERIER) 317c74ad251Schristos ND_PRINT("/querier"); 3180f74e101Schristos if (flags & DVMRP_NF_DISABLED) 319c74ad251Schristos ND_PRINT("/disabled"); 3200f74e101Schristos if (flags & DVMRP_NF_DOWN) 321c74ad251Schristos ND_PRINT("/down"); 322c74ad251Schristos ND_PRINT(")]"); 3230f74e101Schristos bp += 4; 3240f74e101Schristos len -= 4; 3250f74e101Schristos } 3260f74e101Schristos if (ncount != -1) { 327*26ba0b50Schristos ND_PRINT(" [ncount %d]", ncount); 328c74ad251Schristos goto invalid; 3290f74e101Schristos } 3300f74e101Schristos } 331c74ad251Schristos return; 3320f74e101Schristos 333c74ad251Schristos invalid: 334c74ad251Schristos nd_print_invalid(ndo); 3350f74e101Schristos } 336