117680Spst/* 217680Spst * Copyright (c) 1989, 1990, 1991, 1993, 1994, 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: Routing Information Protocol (RIP) printer */ 23313537Sglebius 2456893Sfenner#ifdef HAVE_CONFIG_H 2556893Sfenner#include "config.h" 2656893Sfenner#endif 2756893Sfenner 28313537Sglebius#include <netdissect-stdinc.h> 2917680Spst 3017680Spst#include <stdio.h> 3117680Spst 32313537Sglebius#include "netdissect.h" 3317680Spst#include "addrtoname.h" 34313537Sglebius#include "extract.h" 3517680Spst 36190207Srpaulo#include "af.h" 37190207Srpaulo 38276788Sdelphijstatic const char tstr[] = "[|rip]"; 39276788Sdelphij 4017680Spststruct rip { 41276788Sdelphij uint8_t rip_cmd; /* request/response */ 42276788Sdelphij uint8_t rip_vers; /* protocol version # */ 43276788Sdelphij uint8_t unused[2]; /* unused */ 4417680Spst}; 45127668Sbms 4617680Spst#define RIPCMD_REQUEST 1 /* want info */ 4717680Spst#define RIPCMD_RESPONSE 2 /* responding to request */ 4817680Spst#define RIPCMD_TRACEON 3 /* turn tracing on */ 4917680Spst#define RIPCMD_TRACEOFF 4 /* turn it off */ 5017680Spst#define RIPCMD_POLL 5 /* want info from everybody */ 5117680Spst#define RIPCMD_POLLENTRY 6 /* poll for entry */ 5217680Spst 53127668Sbmsstatic const struct tok rip_cmd_values[] = { 54127668Sbms { RIPCMD_REQUEST, "Request" }, 55127668Sbms { RIPCMD_RESPONSE, "Response" }, 56127668Sbms { RIPCMD_TRACEON, "Trace on" }, 57127668Sbms { RIPCMD_TRACEOFF, "Trace off" }, 58127668Sbms { RIPCMD_POLL, "Poll" }, 59127668Sbms { RIPCMD_POLLENTRY, "Poll Entry" }, 60127668Sbms { 0, NULL} 61127668Sbms}; 6275115Sfenner 63127668Sbms#define RIP_AUTHLEN 16 64127668Sbms#define RIP_ROUTELEN 20 65127668Sbms 66127668Sbms/* 67127668Sbms * rfc 1723 68276788Sdelphij * 69127668Sbms * 0 1 2 3 3 70127668Sbms * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 71127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 72127668Sbms * | Command (1) | Version (1) | unused | 73127668Sbms * +---------------+---------------+-------------------------------+ 74127668Sbms * | Address Family Identifier (2) | Route Tag (2) | 75127668Sbms * +-------------------------------+-------------------------------+ 76127668Sbms * | IP Address (4) | 77127668Sbms * +---------------------------------------------------------------+ 78127668Sbms * | Subnet Mask (4) | 79127668Sbms * +---------------------------------------------------------------+ 80127668Sbms * | Next Hop (4) | 81127668Sbms * +---------------------------------------------------------------+ 82127668Sbms * | Metric (4) | 83127668Sbms * +---------------------------------------------------------------+ 84127668Sbms * 85127668Sbms */ 86127668Sbms 8717680Spststruct rip_netinfo { 88276788Sdelphij uint16_t rip_family; 89276788Sdelphij uint16_t rip_tag; 90276788Sdelphij uint32_t rip_dest; 91276788Sdelphij uint32_t rip_dest_mask; 92276788Sdelphij uint32_t rip_router; 93276788Sdelphij uint32_t rip_metric; /* cost of route */ 9417680Spst}; 9517680Spst 9617680Spststatic void 97276788Sdelphijrip_entry_print_v1(netdissect_options *ndo, 98276788Sdelphij register const struct rip_netinfo *ni) 9917680Spst{ 10075115Sfenner register u_short family; 10117680Spst 10275115Sfenner /* RFC 1058 */ 10375115Sfenner family = EXTRACT_16BITS(&ni->rip_family); 104251158Sdelphij if (family != BSD_AFNUM_INET && family != 0) { 105276788Sdelphij ND_PRINT((ndo, "\n\t AFI %s, ", tok2str(bsd_af_values, "Unknown (%u)", family))); 106313537Sglebius print_unknown_data(ndo, (const uint8_t *)&ni->rip_family, "\n\t ", RIP_ROUTELEN); 10775115Sfenner return; 10875115Sfenner } 109127668Sbms if (EXTRACT_16BITS(&ni->rip_tag) || 110127668Sbms EXTRACT_32BITS(&ni->rip_dest_mask) || 111127668Sbms EXTRACT_32BITS(&ni->rip_router)) { 11275115Sfenner /* MBZ fields not zero */ 113313537Sglebius print_unknown_data(ndo, (const uint8_t *)&ni->rip_family, "\n\t ", RIP_ROUTELEN); 11475115Sfenner return; 115251158Sdelphij } 116251158Sdelphij if (family == 0) { 117276788Sdelphij ND_PRINT((ndo, "\n\t AFI 0, %s, metric: %u", 118276788Sdelphij ipaddr_string(ndo, &ni->rip_dest), 119276788Sdelphij EXTRACT_32BITS(&ni->rip_metric))); 120251158Sdelphij return; 121190207Srpaulo } /* BSD_AFNUM_INET */ 122276788Sdelphij ND_PRINT((ndo, "\n\t %s, metric: %u", 123276788Sdelphij ipaddr_string(ndo, &ni->rip_dest), 124276788Sdelphij EXTRACT_32BITS(&ni->rip_metric))); 12575115Sfenner} 12675115Sfenner 127251158Sdelphijstatic unsigned 128276788Sdelphijrip_entry_print_v2(netdissect_options *ndo, 129276788Sdelphij register const struct rip_netinfo *ni, const unsigned remaining) 13075115Sfenner{ 13175115Sfenner register u_short family; 13275115Sfenner 13375115Sfenner family = EXTRACT_16BITS(&ni->rip_family); 134251158Sdelphij if (family == 0xFFFF) { /* variable-sized authentication structures */ 135276788Sdelphij uint16_t auth_type = EXTRACT_16BITS(&ni->rip_tag); 136251158Sdelphij if (auth_type == 2) { 137313537Sglebius register const u_char *p = (const u_char *)&ni->rip_dest; 138251158Sdelphij u_int i = 0; 139276788Sdelphij ND_PRINT((ndo, "\n\t Simple Text Authentication data: ")); 140251158Sdelphij for (; i < RIP_AUTHLEN; p++, i++) 141276788Sdelphij ND_PRINT((ndo, "%c", ND_ISPRINT(*p) ? *p : '.')); 142251158Sdelphij } else if (auth_type == 3) { 143276788Sdelphij ND_PRINT((ndo, "\n\t Auth header:")); 144313537Sglebius ND_PRINT((ndo, " Packet Len %u,", EXTRACT_16BITS((const uint8_t *)ni + 4))); 145313537Sglebius ND_PRINT((ndo, " Key-ID %u,", *((const uint8_t *)ni + 6))); 146313537Sglebius ND_PRINT((ndo, " Auth Data Len %u,", *((const uint8_t *)ni + 7))); 147276788Sdelphij ND_PRINT((ndo, " SeqNo %u,", EXTRACT_32BITS(&ni->rip_dest_mask))); 148276788Sdelphij ND_PRINT((ndo, " MBZ %u,", EXTRACT_32BITS(&ni->rip_router))); 149276788Sdelphij ND_PRINT((ndo, " MBZ %u", EXTRACT_32BITS(&ni->rip_metric))); 150251158Sdelphij } else if (auth_type == 1) { 151276788Sdelphij ND_PRINT((ndo, "\n\t Auth trailer:")); 152313537Sglebius print_unknown_data(ndo, (const uint8_t *)&ni->rip_dest, "\n\t ", remaining); 153251158Sdelphij return remaining; /* AT spans till the packet end */ 154276788Sdelphij } else { 155276788Sdelphij ND_PRINT((ndo, "\n\t Unknown (%u) Authentication data:", 156276788Sdelphij EXTRACT_16BITS(&ni->rip_tag))); 157313537Sglebius print_unknown_data(ndo, (const uint8_t *)&ni->rip_dest, "\n\t ", remaining); 15875115Sfenner } 159251158Sdelphij } else if (family != BSD_AFNUM_INET && family != 0) { 160276788Sdelphij ND_PRINT((ndo, "\n\t AFI %s", tok2str(bsd_af_values, "Unknown (%u)", family))); 161313537Sglebius print_unknown_data(ndo, (const uint8_t *)&ni->rip_tag, "\n\t ", RIP_ROUTELEN-2); 162251158Sdelphij } else { /* BSD_AFNUM_INET or AFI 0 */ 163276788Sdelphij ND_PRINT((ndo, "\n\t AFI %s, %15s/%-2d, tag 0x%04x, metric: %u, next-hop: ", 164251158Sdelphij tok2str(bsd_af_values, "%u", family), 165276788Sdelphij ipaddr_string(ndo, &ni->rip_dest), 166127668Sbms mask2plen(EXTRACT_32BITS(&ni->rip_dest_mask)), 167127668Sbms EXTRACT_16BITS(&ni->rip_tag), 168276788Sdelphij EXTRACT_32BITS(&ni->rip_metric))); 169127668Sbms if (EXTRACT_32BITS(&ni->rip_router)) 170276788Sdelphij ND_PRINT((ndo, "%s", ipaddr_string(ndo, &ni->rip_router))); 171276788Sdelphij else 172276788Sdelphij ND_PRINT((ndo, "self")); 17317680Spst } 174251158Sdelphij return sizeof (*ni); 17517680Spst} 17617680Spst 17717680Spstvoid 178276788Sdelphijrip_print(netdissect_options *ndo, 179276788Sdelphij const u_char *dat, u_int length) 18017680Spst{ 18117680Spst register const struct rip *rp; 18217680Spst register const struct rip_netinfo *ni; 183127668Sbms register u_int i, j; 18417680Spst 185276788Sdelphij if (ndo->ndo_snapend < dat) { 186276788Sdelphij ND_PRINT((ndo, " %s", tstr)); 18717680Spst return; 18856893Sfenner } 189276788Sdelphij i = ndo->ndo_snapend - dat; 190127668Sbms if (i > length) 191127668Sbms i = length; 192127668Sbms if (i < sizeof(*rp)) { 193276788Sdelphij ND_PRINT((ndo, " %s", tstr)); 194127668Sbms return; 195127668Sbms } 196127668Sbms i -= sizeof(*rp); 19717680Spst 198313537Sglebius rp = (const struct rip *)dat; 199127668Sbms 200276788Sdelphij ND_PRINT((ndo, "%sRIPv%u", 201276788Sdelphij (ndo->ndo_vflag >= 1) ? "\n\t" : "", 202276788Sdelphij rp->rip_vers)); 203127668Sbms 20475115Sfenner switch (rp->rip_vers) { 20575115Sfenner case 0: 20675115Sfenner /* 20775115Sfenner * RFC 1058. 20875115Sfenner * 20975115Sfenner * XXX - RFC 1058 says 21075115Sfenner * 21175115Sfenner * 0 Datagrams whose version number is zero are to be ignored. 21275115Sfenner * These are from a previous version of the protocol, whose 21375115Sfenner * packet format was machine-specific. 21475115Sfenner * 215127668Sbms * so perhaps we should just dump the packet, in hex. 21698524Sfenner */ 217313537Sglebius print_unknown_data(ndo, (const uint8_t *)&rp->rip_cmd, "\n\t", length); 21817680Spst break; 21917680Spst default: 220127668Sbms /* dump version and lets see if we know the commands name*/ 221276788Sdelphij ND_PRINT((ndo, ", %s, length: %u", 222127668Sbms tok2str(rip_cmd_values, 223127668Sbms "unknown command (%u)", 224127668Sbms rp->rip_cmd), 225276788Sdelphij length)); 226127668Sbms 227276788Sdelphij if (ndo->ndo_vflag < 1) 228127668Sbms return; 229127668Sbms 23075115Sfenner switch (rp->rip_cmd) { 231251158Sdelphij case RIPCMD_REQUEST: 23275115Sfenner case RIPCMD_RESPONSE: 23375115Sfenner j = length / sizeof(*ni); 234276788Sdelphij ND_PRINT((ndo, ", routes: %u%s", j, rp->rip_vers == 2 ? " or less" : "")); 235313537Sglebius ni = (const struct rip_netinfo *)(rp + 1); 236127668Sbms for (; i >= sizeof(*ni); ++ni) { 23775115Sfenner if (rp->rip_vers == 1) 238251158Sdelphij { 239276788Sdelphij rip_entry_print_v1(ndo, ni); 240251158Sdelphij i -= sizeof(*ni); 241251158Sdelphij } 242127668Sbms else if (rp->rip_vers == 2) 243276788Sdelphij i -= rip_entry_print_v2(ndo, ni, i); 244127668Sbms else 245127668Sbms break; 24675115Sfenner } 247251158Sdelphij if (i) 248276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 24975115Sfenner break; 250127668Sbms 25175115Sfenner case RIPCMD_TRACEOFF: 25275115Sfenner case RIPCMD_POLL: 25375115Sfenner case RIPCMD_POLLENTRY: 25475115Sfenner break; 255127668Sbms 256127668Sbms case RIPCMD_TRACEON: 257127668Sbms /* fall through */ 258127668Sbms default: 259276788Sdelphij if (ndo->ndo_vflag <= 1) { 260313537Sglebius if(!print_unknown_data(ndo, (const uint8_t *)rp, "\n\t", length)) 261127668Sbms return; 262127668Sbms } 263127668Sbms break; 264127668Sbms } 265127668Sbms /* do we want to see an additionally hexdump ? */ 266276788Sdelphij if (ndo->ndo_vflag> 1) { 267313537Sglebius if(!print_unknown_data(ndo, (const uint8_t *)rp, "\n\t", length)) 268127668Sbms return; 269127668Sbms } 270127668Sbms } 27117680Spst} 272127668Sbms 273127668Sbms 274