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