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