117680Spst/* 217680Spst * Copyright (c) 1995, 1996 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2017680Spst */ 2117680Spst 22313537Sglebius/* \summary: Distance Vector Multicast Routing Protocol printer */ 23313537Sglebius 2456893Sfenner#ifdef HAVE_CONFIG_H 2556893Sfenner#include "config.h" 2656893Sfenner#endif 2756893Sfenner 28313537Sglebius#include <netdissect-stdinc.h> 2917680Spst 30313537Sglebius#include "netdissect.h" 3156893Sfenner#include "extract.h" 3217680Spst#include "addrtoname.h" 3317680Spst 3417680Spst/* 35356341Scy * See: RFC 1075 and draft-ietf-idmr-dvmrp-v3 36356341Scy * 3717680Spst * DVMRP message types and flag values shamelessly stolen from 3817680Spst * mrouted/dvmrp.h. 3917680Spst */ 4017680Spst#define DVMRP_PROBE 1 /* for finding neighbors */ 4117680Spst#define DVMRP_REPORT 2 /* for reporting some or all routes */ 4217680Spst#define DVMRP_ASK_NEIGHBORS 3 /* sent by mapper, asking for a list */ 4398524Sfenner /* of this router's neighbors */ 4417680Spst#define DVMRP_NEIGHBORS 4 /* response to such a request */ 4517680Spst#define DVMRP_ASK_NEIGHBORS2 5 /* as above, want new format reply */ 4617680Spst#define DVMRP_NEIGHBORS2 6 4717680Spst#define DVMRP_PRUNE 7 /* prune message */ 4817680Spst#define DVMRP_GRAFT 8 /* graft message */ 4917680Spst#define DVMRP_GRAFT_ACK 9 /* graft acknowledgement */ 5017680Spst 5117680Spst/* 5217680Spst * 'flags' byte values in DVMRP_NEIGHBORS2 reply. 5317680Spst */ 5417680Spst#define DVMRP_NF_TUNNEL 0x01 /* neighbors reached via tunnel */ 5517680Spst#define DVMRP_NF_SRCRT 0x02 /* tunnel uses IP source routing */ 5617680Spst#define DVMRP_NF_DOWN 0x10 /* kernel state of interface */ 5717680Spst#define DVMRP_NF_DISABLED 0x20 /* administratively disabled */ 5817680Spst#define DVMRP_NF_QUERIER 0x40 /* I am the subnet's querier */ 5917680Spst 60276788Sdelphijstatic int print_probe(netdissect_options *, const u_char *, const u_char *, u_int); 61276788Sdelphijstatic int print_report(netdissect_options *, const u_char *, const u_char *, u_int); 62276788Sdelphijstatic int print_neighbors(netdissect_options *, const u_char *, const u_char *, u_int); 63356341Scystatic int print_neighbors2(netdissect_options *, const u_char *, const u_char *, u_int, uint8_t, uint8_t); 64276788Sdelphijstatic int print_prune(netdissect_options *, const u_char *); 65276788Sdelphijstatic int print_graft(netdissect_options *, const u_char *); 66276788Sdelphijstatic int print_graft_ack(netdissect_options *, const u_char *); 6717680Spst 6817680Spstvoid 69276788Sdelphijdvmrp_print(netdissect_options *ndo, 70276788Sdelphij register const u_char *bp, register u_int len) 7117680Spst{ 7217680Spst register const u_char *ep; 7317680Spst register u_char type; 74356341Scy uint8_t major_version, minor_version; 7517680Spst 76276788Sdelphij ep = (const u_char *)ndo->ndo_snapend; 7717680Spst if (bp >= ep) 7817680Spst return; 7917680Spst 80276788Sdelphij ND_TCHECK(bp[1]); 8117680Spst type = bp[1]; 8298524Sfenner 8398524Sfenner /* Skip IGMP header */ 8417680Spst bp += 8; 8517680Spst len -= 8; 8617680Spst 8717680Spst switch (type) { 8826180Sfenner 8917680Spst case DVMRP_PROBE: 90276788Sdelphij ND_PRINT((ndo, " Probe")); 91276788Sdelphij if (ndo->ndo_vflag) { 92276788Sdelphij if (print_probe(ndo, bp, ep, len) < 0) 93127668Sbms goto trunc; 94127668Sbms } 9517680Spst break; 9617680Spst 9717680Spst case DVMRP_REPORT: 98276788Sdelphij ND_PRINT((ndo, " Report")); 99276788Sdelphij if (ndo->ndo_vflag > 1) { 100276788Sdelphij if (print_report(ndo, bp, ep, len) < 0) 101127668Sbms goto trunc; 102127668Sbms } 10317680Spst break; 10417680Spst 10517680Spst case DVMRP_ASK_NEIGHBORS: 106276788Sdelphij ND_PRINT((ndo, " Ask-neighbors(old)")); 10717680Spst break; 10817680Spst 10917680Spst case DVMRP_NEIGHBORS: 110276788Sdelphij ND_PRINT((ndo, " Neighbors(old)")); 111276788Sdelphij if (print_neighbors(ndo, bp, ep, len) < 0) 112127668Sbms goto trunc; 11317680Spst break; 11417680Spst 11517680Spst case DVMRP_ASK_NEIGHBORS2: 116276788Sdelphij ND_PRINT((ndo, " Ask-neighbors2")); 11717680Spst break; 11817680Spst 11917680Spst case DVMRP_NEIGHBORS2: 120276788Sdelphij ND_PRINT((ndo, " Neighbors2")); 12117680Spst /* 122356341Scy * extract version from IGMP group address field 12317680Spst */ 12426180Sfenner bp -= 4; 125276788Sdelphij ND_TCHECK2(bp[0], 4); 126356341Scy major_version = *(bp + 3); 127356341Scy minor_version = *(bp + 2); 12826180Sfenner bp += 4; 129356341Scy if (print_neighbors2(ndo, bp, ep, len, major_version, 130356341Scy minor_version) < 0) 131127668Sbms goto trunc; 13217680Spst break; 13317680Spst 13417680Spst case DVMRP_PRUNE: 135276788Sdelphij ND_PRINT((ndo, " Prune")); 136276788Sdelphij if (print_prune(ndo, bp) < 0) 137127668Sbms goto trunc; 13817680Spst break; 13917680Spst 14017680Spst case DVMRP_GRAFT: 141276788Sdelphij ND_PRINT((ndo, " Graft")); 142276788Sdelphij if (print_graft(ndo, bp) < 0) 143127668Sbms goto trunc; 14417680Spst break; 14517680Spst 14617680Spst case DVMRP_GRAFT_ACK: 147276788Sdelphij ND_PRINT((ndo, " Graft-ACK")); 148276788Sdelphij if (print_graft_ack(ndo, bp) < 0) 149127668Sbms goto trunc; 15017680Spst break; 15117680Spst 15217680Spst default: 153276788Sdelphij ND_PRINT((ndo, " [type %d]", type)); 15417680Spst break; 15517680Spst } 156127668Sbms return; 157127668Sbms 158127668Sbmstrunc: 159276788Sdelphij ND_PRINT((ndo, "[|dvmrp]")); 160127668Sbms return; 16117680Spst} 16217680Spst 163276788Sdelphijstatic int 164276788Sdelphijprint_report(netdissect_options *ndo, 165276788Sdelphij register const u_char *bp, register const u_char *ep, 166276788Sdelphij register u_int len) 16717680Spst{ 168276788Sdelphij register uint32_t mask, origin; 169127668Sbms register int metric, done; 170127668Sbms register u_int i, width; 17117680Spst 17217680Spst while (len > 0) { 17317680Spst if (len < 3) { 174276788Sdelphij ND_PRINT((ndo, " [|]")); 175127668Sbms return (0); 17617680Spst } 177276788Sdelphij ND_TCHECK2(bp[0], 3); 178276788Sdelphij mask = (uint32_t)0xff << 24 | bp[0] << 16 | bp[1] << 8 | bp[2]; 17917680Spst width = 1; 18017680Spst if (bp[0]) 18117680Spst width = 2; 18217680Spst if (bp[1]) 18317680Spst width = 3; 18417680Spst if (bp[2]) 18517680Spst width = 4; 18617680Spst 187276788Sdelphij ND_PRINT((ndo, "\n\tMask %s", intoa(htonl(mask)))); 18817680Spst bp += 3; 18917680Spst len -= 3; 19017680Spst do { 19117680Spst if (bp + width + 1 > ep) { 192276788Sdelphij ND_PRINT((ndo, " [|]")); 193127668Sbms return (0); 19417680Spst } 19517680Spst if (len < width + 1) { 196276788Sdelphij ND_PRINT((ndo, "\n\t [Truncated Report]")); 197127668Sbms return (0); 19817680Spst } 19917680Spst origin = 0; 200127668Sbms for (i = 0; i < width; ++i) { 201276788Sdelphij ND_TCHECK(*bp); 20217680Spst origin = origin << 8 | *bp++; 203127668Sbms } 20417680Spst for ( ; i < 4; ++i) 20517680Spst origin <<= 8; 20617680Spst 207276788Sdelphij ND_TCHECK(*bp); 20817680Spst metric = *bp++; 20917680Spst done = metric & 0x80; 21017680Spst metric &= 0x7f; 211276788Sdelphij ND_PRINT((ndo, "\n\t %s metric %d", intoa(htonl(origin)), 212276788Sdelphij metric)); 21317680Spst len -= width + 1; 21417680Spst } while (!done); 21517680Spst } 216127668Sbms return (0); 217127668Sbmstrunc: 218127668Sbms return (-1); 21917680Spst} 22017680Spst 221127668Sbmsstatic int 222276788Sdelphijprint_probe(netdissect_options *ndo, 223276788Sdelphij register const u_char *bp, register const u_char *ep, 224276788Sdelphij register u_int len) 22517680Spst{ 226276788Sdelphij register uint32_t genid; 22726180Sfenner 228276788Sdelphij ND_TCHECK2(bp[0], 4); 22926180Sfenner if ((len < 4) || ((bp + 4) > ep)) { 23026180Sfenner /* { (ctags) */ 231276788Sdelphij ND_PRINT((ndo, " [|}")); 232127668Sbms return (0); 23326180Sfenner } 234356341Scy genid = EXTRACT_32BITS(bp); 23526180Sfenner bp += 4; 23626180Sfenner len -= 4; 237276788Sdelphij ND_PRINT((ndo, ndo->ndo_vflag > 1 ? "\n\t" : " ")); 238276788Sdelphij ND_PRINT((ndo, "genid %u", genid)); 239276788Sdelphij if (ndo->ndo_vflag < 2) 240127668Sbms return (0); 24126180Sfenner 24226180Sfenner while ((len > 0) && (bp < ep)) { 243276788Sdelphij ND_TCHECK2(bp[0], 4); 244276788Sdelphij ND_PRINT((ndo, "\n\tneighbor %s", ipaddr_string(ndo, bp))); 24556893Sfenner bp += 4; len -= 4; 24626180Sfenner } 247127668Sbms return (0); 24856893Sfennertrunc: 249127668Sbms return (-1); 25026180Sfenner} 25126180Sfenner 252127668Sbmsstatic int 253276788Sdelphijprint_neighbors(netdissect_options *ndo, 254276788Sdelphij register const u_char *bp, register const u_char *ep, 255276788Sdelphij register u_int len) 25626180Sfenner{ 25756893Sfenner const u_char *laddr; 25826180Sfenner register u_char metric; 25926180Sfenner register u_char thresh; 26026180Sfenner register int ncount; 26117680Spst 26217680Spst while (len > 0 && bp < ep) { 263276788Sdelphij ND_TCHECK2(bp[0], 7); 26456893Sfenner laddr = bp; 26556893Sfenner bp += 4; 26617680Spst metric = *bp++; 26717680Spst thresh = *bp++; 26817680Spst ncount = *bp++; 26917680Spst len -= 7; 27056893Sfenner while (--ncount >= 0) { 271276788Sdelphij ND_TCHECK2(bp[0], 4); 272276788Sdelphij ND_PRINT((ndo, " [%s ->", ipaddr_string(ndo, laddr))); 273276788Sdelphij ND_PRINT((ndo, " %s, (%d/%d)]", 274276788Sdelphij ipaddr_string(ndo, bp), metric, thresh)); 27556893Sfenner bp += 4; 27617680Spst len -= 4; 27717680Spst } 27817680Spst } 279127668Sbms return (0); 28056893Sfennertrunc: 281127668Sbms return (-1); 28217680Spst} 28317680Spst 284127668Sbmsstatic int 285276788Sdelphijprint_neighbors2(netdissect_options *ndo, 286276788Sdelphij register const u_char *bp, register const u_char *ep, 287356341Scy register u_int len, uint8_t major_version, 288356341Scy uint8_t minor_version) 28917680Spst{ 29056893Sfenner const u_char *laddr; 29126180Sfenner register u_char metric, thresh, flags; 29226180Sfenner register int ncount; 29317680Spst 294356341Scy ND_PRINT((ndo, " (v %d.%d):", major_version, minor_version)); 29517680Spst 29617680Spst while (len > 0 && bp < ep) { 297276788Sdelphij ND_TCHECK2(bp[0], 8); 29856893Sfenner laddr = bp; 29956893Sfenner bp += 4; 30017680Spst metric = *bp++; 30117680Spst thresh = *bp++; 30217680Spst flags = *bp++; 30317680Spst ncount = *bp++; 30417680Spst len -= 8; 30526180Sfenner while (--ncount >= 0 && (len >= 4) && (bp + 4) <= ep) { 306276788Sdelphij ND_PRINT((ndo, " [%s -> ", ipaddr_string(ndo, laddr))); 307276788Sdelphij ND_PRINT((ndo, "%s (%d/%d", ipaddr_string(ndo, bp), 308276788Sdelphij metric, thresh)); 30917680Spst if (flags & DVMRP_NF_TUNNEL) 310276788Sdelphij ND_PRINT((ndo, "/tunnel")); 31117680Spst if (flags & DVMRP_NF_SRCRT) 312276788Sdelphij ND_PRINT((ndo, "/srcrt")); 31317680Spst if (flags & DVMRP_NF_QUERIER) 314276788Sdelphij ND_PRINT((ndo, "/querier")); 31517680Spst if (flags & DVMRP_NF_DISABLED) 316276788Sdelphij ND_PRINT((ndo, "/disabled")); 31717680Spst if (flags & DVMRP_NF_DOWN) 318276788Sdelphij ND_PRINT((ndo, "/down")); 319276788Sdelphij ND_PRINT((ndo, ")]")); 32056893Sfenner bp += 4; 32117680Spst len -= 4; 32217680Spst } 32317680Spst if (ncount != -1) { 324276788Sdelphij ND_PRINT((ndo, " [|]")); 325127668Sbms return (0); 32617680Spst } 32717680Spst } 328127668Sbms return (0); 32956893Sfennertrunc: 330127668Sbms return (-1); 33117680Spst} 33217680Spst 333127668Sbmsstatic int 334276788Sdelphijprint_prune(netdissect_options *ndo, 335276788Sdelphij register const u_char *bp) 33617680Spst{ 337276788Sdelphij ND_TCHECK2(bp[0], 12); 338276788Sdelphij ND_PRINT((ndo, " src %s grp %s", ipaddr_string(ndo, bp), ipaddr_string(ndo, bp + 4))); 33917680Spst bp += 8; 340276788Sdelphij ND_PRINT((ndo, " timer ")); 341313537Sglebius unsigned_relts_print(ndo, EXTRACT_32BITS(bp)); 342127668Sbms return (0); 34356893Sfennertrunc: 344127668Sbms return (-1); 34517680Spst} 34617680Spst 347127668Sbmsstatic int 348276788Sdelphijprint_graft(netdissect_options *ndo, 349276788Sdelphij register const u_char *bp) 35017680Spst{ 351276788Sdelphij ND_TCHECK2(bp[0], 8); 352276788Sdelphij ND_PRINT((ndo, " src %s grp %s", ipaddr_string(ndo, bp), ipaddr_string(ndo, bp + 4))); 353127668Sbms return (0); 35456893Sfennertrunc: 355127668Sbms return (-1); 35617680Spst} 35717680Spst 358127668Sbmsstatic int 359276788Sdelphijprint_graft_ack(netdissect_options *ndo, 360276788Sdelphij register const u_char *bp) 36117680Spst{ 362276788Sdelphij ND_TCHECK2(bp[0], 8); 363276788Sdelphij ND_PRINT((ndo, " src %s grp %s", ipaddr_string(ndo, bp), ipaddr_string(ndo, bp + 4))); 364127668Sbms return (0); 36556893Sfennertrunc: 366127668Sbms return (-1); 36717680Spst} 368