print-rip.c revision 1.7
1/* 2 * Copyright (c) 1989, 1990, 1991, 1993, 1994, 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#include <sys/cdefs.h> 23#ifndef lint 24__RCSID("$NetBSD: print-rip.c,v 1.7 2017/02/05 04:05:05 spz Exp $"); 25#endif 26 27/* \summary: Routing Information Protocol (RIP) printer */ 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33#include <netdissect-stdinc.h> 34 35#include <stdio.h> 36 37#include "netdissect.h" 38#include "addrtoname.h" 39#include "extract.h" 40 41#include "af.h" 42 43static const char tstr[] = "[|rip]"; 44 45struct rip { 46 uint8_t rip_cmd; /* request/response */ 47 uint8_t rip_vers; /* protocol version # */ 48 uint8_t unused[2]; /* unused */ 49}; 50 51#define RIPCMD_REQUEST 1 /* want info */ 52#define RIPCMD_RESPONSE 2 /* responding to request */ 53#define RIPCMD_TRACEON 3 /* turn tracing on */ 54#define RIPCMD_TRACEOFF 4 /* turn it off */ 55#define RIPCMD_POLL 5 /* want info from everybody */ 56#define RIPCMD_POLLENTRY 6 /* poll for entry */ 57 58static const struct tok rip_cmd_values[] = { 59 { RIPCMD_REQUEST, "Request" }, 60 { RIPCMD_RESPONSE, "Response" }, 61 { RIPCMD_TRACEON, "Trace on" }, 62 { RIPCMD_TRACEOFF, "Trace off" }, 63 { RIPCMD_POLL, "Poll" }, 64 { RIPCMD_POLLENTRY, "Poll Entry" }, 65 { 0, NULL} 66}; 67 68#define RIP_AUTHLEN 16 69#define RIP_ROUTELEN 20 70 71/* 72 * rfc 1723 73 * 74 * 0 1 2 3 3 75 * 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 76 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 77 * | Command (1) | Version (1) | unused | 78 * +---------------+---------------+-------------------------------+ 79 * | Address Family Identifier (2) | Route Tag (2) | 80 * +-------------------------------+-------------------------------+ 81 * | IP Address (4) | 82 * +---------------------------------------------------------------+ 83 * | Subnet Mask (4) | 84 * +---------------------------------------------------------------+ 85 * | Next Hop (4) | 86 * +---------------------------------------------------------------+ 87 * | Metric (4) | 88 * +---------------------------------------------------------------+ 89 * 90 */ 91 92struct rip_netinfo { 93 uint16_t rip_family; 94 uint16_t rip_tag; 95 uint32_t rip_dest; 96 uint32_t rip_dest_mask; 97 uint32_t rip_router; 98 uint32_t rip_metric; /* cost of route */ 99}; 100 101static void 102rip_entry_print_v1(netdissect_options *ndo, 103 register const struct rip_netinfo *ni) 104{ 105 register u_short family; 106 107 /* RFC 1058 */ 108 family = EXTRACT_16BITS(&ni->rip_family); 109 if (family != BSD_AFNUM_INET && family != 0) { 110 ND_PRINT((ndo, "\n\t AFI %s, ", tok2str(bsd_af_values, "Unknown (%u)", family))); 111 print_unknown_data(ndo, (const uint8_t *)&ni->rip_family, "\n\t ", RIP_ROUTELEN); 112 return; 113 } 114 if (EXTRACT_16BITS(&ni->rip_tag) || 115 EXTRACT_32BITS(&ni->rip_dest_mask) || 116 EXTRACT_32BITS(&ni->rip_router)) { 117 /* MBZ fields not zero */ 118 print_unknown_data(ndo, (const uint8_t *)&ni->rip_family, "\n\t ", RIP_ROUTELEN); 119 return; 120 } 121 if (family == 0) { 122 ND_PRINT((ndo, "\n\t AFI 0, %s, metric: %u", 123 ipaddr_string(ndo, &ni->rip_dest), 124 EXTRACT_32BITS(&ni->rip_metric))); 125 return; 126 } /* BSD_AFNUM_INET */ 127 ND_PRINT((ndo, "\n\t %s, metric: %u", 128 ipaddr_string(ndo, &ni->rip_dest), 129 EXTRACT_32BITS(&ni->rip_metric))); 130} 131 132static unsigned 133rip_entry_print_v2(netdissect_options *ndo, 134 register const struct rip_netinfo *ni, const unsigned remaining) 135{ 136 register u_short family; 137 138 family = EXTRACT_16BITS(&ni->rip_family); 139 if (family == 0xFFFF) { /* variable-sized authentication structures */ 140 uint16_t auth_type = EXTRACT_16BITS(&ni->rip_tag); 141 if (auth_type == 2) { 142 register const u_char *p = (const u_char *)&ni->rip_dest; 143 u_int i = 0; 144 ND_PRINT((ndo, "\n\t Simple Text Authentication data: ")); 145 for (; i < RIP_AUTHLEN; p++, i++) 146 ND_PRINT((ndo, "%c", ND_ISPRINT(*p) ? *p : '.')); 147 } else if (auth_type == 3) { 148 ND_PRINT((ndo, "\n\t Auth header:")); 149 ND_PRINT((ndo, " Packet Len %u,", EXTRACT_16BITS((const uint8_t *)ni + 4))); 150 ND_PRINT((ndo, " Key-ID %u,", *((const uint8_t *)ni + 6))); 151 ND_PRINT((ndo, " Auth Data Len %u,", *((const uint8_t *)ni + 7))); 152 ND_PRINT((ndo, " SeqNo %u,", EXTRACT_32BITS(&ni->rip_dest_mask))); 153 ND_PRINT((ndo, " MBZ %u,", EXTRACT_32BITS(&ni->rip_router))); 154 ND_PRINT((ndo, " MBZ %u", EXTRACT_32BITS(&ni->rip_metric))); 155 } else if (auth_type == 1) { 156 ND_PRINT((ndo, "\n\t Auth trailer:")); 157 print_unknown_data(ndo, (const uint8_t *)&ni->rip_dest, "\n\t ", remaining); 158 return remaining; /* AT spans till the packet end */ 159 } else { 160 ND_PRINT((ndo, "\n\t Unknown (%u) Authentication data:", 161 EXTRACT_16BITS(&ni->rip_tag))); 162 print_unknown_data(ndo, (const uint8_t *)&ni->rip_dest, "\n\t ", remaining); 163 } 164 } else if (family != BSD_AFNUM_INET && family != 0) { 165 ND_PRINT((ndo, "\n\t AFI %s", tok2str(bsd_af_values, "Unknown (%u)", family))); 166 print_unknown_data(ndo, (const uint8_t *)&ni->rip_tag, "\n\t ", RIP_ROUTELEN-2); 167 } else { /* BSD_AFNUM_INET or AFI 0 */ 168 ND_PRINT((ndo, "\n\t AFI %s, %15s/%-2d, tag 0x%04x, metric: %u, next-hop: ", 169 tok2str(bsd_af_values, "%u", family), 170 ipaddr_string(ndo, &ni->rip_dest), 171 mask2plen(EXTRACT_32BITS(&ni->rip_dest_mask)), 172 EXTRACT_16BITS(&ni->rip_tag), 173 EXTRACT_32BITS(&ni->rip_metric))); 174 if (EXTRACT_32BITS(&ni->rip_router)) 175 ND_PRINT((ndo, "%s", ipaddr_string(ndo, &ni->rip_router))); 176 else 177 ND_PRINT((ndo, "self")); 178 } 179 return sizeof (*ni); 180} 181 182void 183rip_print(netdissect_options *ndo, 184 const u_char *dat, u_int length) 185{ 186 register const struct rip *rp; 187 register const struct rip_netinfo *ni; 188 register u_int i, j; 189 190 if (ndo->ndo_snapend < dat) { 191 ND_PRINT((ndo, " %s", tstr)); 192 return; 193 } 194 i = ndo->ndo_snapend - dat; 195 if (i > length) 196 i = length; 197 if (i < sizeof(*rp)) { 198 ND_PRINT((ndo, " %s", tstr)); 199 return; 200 } 201 i -= sizeof(*rp); 202 203 rp = (const struct rip *)dat; 204 205 ND_PRINT((ndo, "%sRIPv%u", 206 (ndo->ndo_vflag >= 1) ? "\n\t" : "", 207 rp->rip_vers)); 208 209 switch (rp->rip_vers) { 210 case 0: 211 /* 212 * RFC 1058. 213 * 214 * XXX - RFC 1058 says 215 * 216 * 0 Datagrams whose version number is zero are to be ignored. 217 * These are from a previous version of the protocol, whose 218 * packet format was machine-specific. 219 * 220 * so perhaps we should just dump the packet, in hex. 221 */ 222 print_unknown_data(ndo, (const uint8_t *)&rp->rip_cmd, "\n\t", length); 223 break; 224 default: 225 /* dump version and lets see if we know the commands name*/ 226 ND_PRINT((ndo, ", %s, length: %u", 227 tok2str(rip_cmd_values, 228 "unknown command (%u)", 229 rp->rip_cmd), 230 length)); 231 232 if (ndo->ndo_vflag < 1) 233 return; 234 235 switch (rp->rip_cmd) { 236 case RIPCMD_REQUEST: 237 case RIPCMD_RESPONSE: 238 j = length / sizeof(*ni); 239 ND_PRINT((ndo, ", routes: %u%s", j, rp->rip_vers == 2 ? " or less" : "")); 240 ni = (const struct rip_netinfo *)(rp + 1); 241 for (; i >= sizeof(*ni); ++ni) { 242 if (rp->rip_vers == 1) 243 { 244 rip_entry_print_v1(ndo, ni); 245 i -= sizeof(*ni); 246 } 247 else if (rp->rip_vers == 2) 248 i -= rip_entry_print_v2(ndo, ni, i); 249 else 250 break; 251 } 252 if (i) 253 ND_PRINT((ndo, "%s", tstr)); 254 break; 255 256 case RIPCMD_TRACEOFF: 257 case RIPCMD_POLL: 258 case RIPCMD_POLLENTRY: 259 break; 260 261 case RIPCMD_TRACEON: 262 /* fall through */ 263 default: 264 if (ndo->ndo_vflag <= 1) { 265 if(!print_unknown_data(ndo, (const uint8_t *)rp, "\n\t", length)) 266 return; 267 } 268 break; 269 } 270 /* do we want to see an additionally hexdump ? */ 271 if (ndo->ndo_vflag> 1) { 272 if(!print_unknown_data(ndo, (const uint8_t *)rp, "\n\t", length)) 273 return; 274 } 275 } 276} 277 278 279