print-rip.c revision 1.8
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.8 2020/02/24 18:39:47 kamil 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 101UNALIGNED_OK 102static void 103rip_entry_print_v1(netdissect_options *ndo, 104 register const struct rip_netinfo *ni) 105{ 106 register u_short family; 107 108 /* RFC 1058 */ 109 family = EXTRACT_16BITS(&ni->rip_family); 110 if (family != BSD_AFNUM_INET && family != 0) { 111 ND_PRINT((ndo, "\n\t AFI %s, ", tok2str(bsd_af_values, "Unknown (%u)", family))); 112 print_unknown_data(ndo, (const uint8_t *)&ni->rip_family, "\n\t ", RIP_ROUTELEN); 113 return; 114 } 115 if (EXTRACT_16BITS(&ni->rip_tag) || 116 EXTRACT_32BITS(&ni->rip_dest_mask) || 117 EXTRACT_32BITS(&ni->rip_router)) { 118 /* MBZ fields not zero */ 119 print_unknown_data(ndo, (const uint8_t *)&ni->rip_family, "\n\t ", RIP_ROUTELEN); 120 return; 121 } 122 if (family == 0) { 123 ND_PRINT((ndo, "\n\t AFI 0, %s, metric: %u", 124 ipaddr_string(ndo, &ni->rip_dest), 125 EXTRACT_32BITS(&ni->rip_metric))); 126 return; 127 } /* BSD_AFNUM_INET */ 128 ND_PRINT((ndo, "\n\t %s, metric: %u", 129 ipaddr_string(ndo, &ni->rip_dest), 130 EXTRACT_32BITS(&ni->rip_metric))); 131} 132 133UNALIGNED_OK 134static unsigned 135rip_entry_print_v2(netdissect_options *ndo, 136 register const struct rip_netinfo *ni, const unsigned remaining) 137{ 138 register u_short family; 139 140 family = EXTRACT_16BITS(&ni->rip_family); 141 if (family == 0xFFFF) { /* variable-sized authentication structures */ 142 uint16_t auth_type = EXTRACT_16BITS(&ni->rip_tag); 143 if (auth_type == 2) { 144 register const u_char *p = (const u_char *)&ni->rip_dest; 145 u_int i = 0; 146 ND_PRINT((ndo, "\n\t Simple Text Authentication data: ")); 147 for (; i < RIP_AUTHLEN; p++, i++) 148 ND_PRINT((ndo, "%c", ND_ISPRINT(*p) ? *p : '.')); 149 } else if (auth_type == 3) { 150 ND_PRINT((ndo, "\n\t Auth header:")); 151 ND_PRINT((ndo, " Packet Len %u,", EXTRACT_16BITS((const uint8_t *)ni + 4))); 152 ND_PRINT((ndo, " Key-ID %u,", *((const uint8_t *)ni + 6))); 153 ND_PRINT((ndo, " Auth Data Len %u,", *((const uint8_t *)ni + 7))); 154 ND_PRINT((ndo, " SeqNo %u,", EXTRACT_32BITS(&ni->rip_dest_mask))); 155 ND_PRINT((ndo, " MBZ %u,", EXTRACT_32BITS(&ni->rip_router))); 156 ND_PRINT((ndo, " MBZ %u", EXTRACT_32BITS(&ni->rip_metric))); 157 } else if (auth_type == 1) { 158 ND_PRINT((ndo, "\n\t Auth trailer:")); 159 print_unknown_data(ndo, (const uint8_t *)&ni->rip_dest, "\n\t ", remaining); 160 return remaining; /* AT spans till the packet end */ 161 } else { 162 ND_PRINT((ndo, "\n\t Unknown (%u) Authentication data:", 163 EXTRACT_16BITS(&ni->rip_tag))); 164 print_unknown_data(ndo, (const uint8_t *)&ni->rip_dest, "\n\t ", remaining); 165 } 166 } else if (family != BSD_AFNUM_INET && family != 0) { 167 ND_PRINT((ndo, "\n\t AFI %s", tok2str(bsd_af_values, "Unknown (%u)", family))); 168 print_unknown_data(ndo, (const uint8_t *)&ni->rip_tag, "\n\t ", RIP_ROUTELEN-2); 169 } else { /* BSD_AFNUM_INET or AFI 0 */ 170 ND_PRINT((ndo, "\n\t AFI %s, %15s/%-2d, tag 0x%04x, metric: %u, next-hop: ", 171 tok2str(bsd_af_values, "%u", family), 172 ipaddr_string(ndo, &ni->rip_dest), 173 mask2plen(EXTRACT_32BITS(&ni->rip_dest_mask)), 174 EXTRACT_16BITS(&ni->rip_tag), 175 EXTRACT_32BITS(&ni->rip_metric))); 176 if (EXTRACT_32BITS(&ni->rip_router)) 177 ND_PRINT((ndo, "%s", ipaddr_string(ndo, &ni->rip_router))); 178 else 179 ND_PRINT((ndo, "self")); 180 } 181 return sizeof (*ni); 182} 183 184void 185rip_print(netdissect_options *ndo, 186 const u_char *dat, u_int length) 187{ 188 register const struct rip *rp; 189 register const struct rip_netinfo *ni; 190 register u_int i, j; 191 192 if (ndo->ndo_snapend < dat) { 193 ND_PRINT((ndo, " %s", tstr)); 194 return; 195 } 196 i = ndo->ndo_snapend - dat; 197 if (i > length) 198 i = length; 199 if (i < sizeof(*rp)) { 200 ND_PRINT((ndo, " %s", tstr)); 201 return; 202 } 203 i -= sizeof(*rp); 204 205 rp = (const struct rip *)dat; 206 207 ND_PRINT((ndo, "%sRIPv%u", 208 (ndo->ndo_vflag >= 1) ? "\n\t" : "", 209 rp->rip_vers)); 210 211 switch (rp->rip_vers) { 212 case 0: 213 /* 214 * RFC 1058. 215 * 216 * XXX - RFC 1058 says 217 * 218 * 0 Datagrams whose version number is zero are to be ignored. 219 * These are from a previous version of the protocol, whose 220 * packet format was machine-specific. 221 * 222 * so perhaps we should just dump the packet, in hex. 223 */ 224 print_unknown_data(ndo, (const uint8_t *)&rp->rip_cmd, "\n\t", length); 225 break; 226 default: 227 /* dump version and lets see if we know the commands name*/ 228 ND_PRINT((ndo, ", %s, length: %u", 229 tok2str(rip_cmd_values, 230 "unknown command (%u)", 231 rp->rip_cmd), 232 length)); 233 234 if (ndo->ndo_vflag < 1) 235 return; 236 237 switch (rp->rip_cmd) { 238 case RIPCMD_REQUEST: 239 case RIPCMD_RESPONSE: 240 j = length / sizeof(*ni); 241 ND_PRINT((ndo, ", routes: %u%s", j, rp->rip_vers == 2 ? " or less" : "")); 242 ni = (const struct rip_netinfo *)(rp + 1); 243 for (; i >= sizeof(*ni); ++ni) { 244 if (rp->rip_vers == 1) 245 { 246 rip_entry_print_v1(ndo, ni); 247 i -= sizeof(*ni); 248 } 249 else if (rp->rip_vers == 2) 250 i -= rip_entry_print_v2(ndo, ni, i); 251 else 252 break; 253 } 254 if (i) 255 ND_PRINT((ndo, "%s", tstr)); 256 break; 257 258 case RIPCMD_TRACEOFF: 259 case RIPCMD_POLL: 260 case RIPCMD_POLLENTRY: 261 break; 262 263 case RIPCMD_TRACEON: 264 /* fall through */ 265 default: 266 if (ndo->ndo_vflag <= 1) { 267 if(!print_unknown_data(ndo, (const uint8_t *)rp, "\n\t", length)) 268 return; 269 } 270 break; 271 } 272 /* do we want to see an additionally hexdump ? */ 273 if (ndo->ndo_vflag> 1) { 274 if(!print_unknown_data(ndo, (const uint8_t *)rp, "\n\t", length)) 275 return; 276 } 277 } 278} 279