print-rip.c revision 75115
1178476Sjb/* 2178476Sjb * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1996 3178476Sjb * The Regents of the University of California. All rights reserved. 4178476Sjb * 5178476Sjb * Redistribution and use in source and binary forms, with or without 6178476Sjb * modification, are permitted provided that: (1) source code distributions 7178476Sjb * retain the above copyright notice and this paragraph in its entirety, (2) 8178476Sjb * distributions including binary code include the above copyright notice and 9178476Sjb * this paragraph in its entirety in the documentation or other materials 10178476Sjb * provided with the distribution, and (3) all advertising materials mentioning 11178476Sjb * features or use of this software display the following acknowledgement: 12178476Sjb * ``This product includes software developed by the University of California, 13178476Sjb * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14178476Sjb * the University nor the names of its contributors may be used to endorse 15178476Sjb * or promote products derived from this software without specific prior 16178476Sjb * written permission. 17178476Sjb * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18178476Sjb * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19178476Sjb * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20178476Sjb */ 21178476Sjb 22178476Sjb#ifndef lint 23178476Sjbstatic const char rcsid[] = 24178476Sjb "@(#) $Header: /tcpdump/master/tcpdump/print-rip.c,v 1.47 2000/10/03 04:19:07 itojun Exp $ (LBL)"; 25178476Sjb#endif 26178476Sjb 27178476Sjb#ifdef HAVE_CONFIG_H 28178476Sjb#include "config.h" 29178476Sjb#endif 30178476Sjb 31178476Sjb#include <sys/param.h> 32178476Sjb#include <sys/time.h> 33178476Sjb#include <sys/socket.h> 34178476Sjb 35178476Sjb#include <netinet/in.h> 36178476Sjb 37178476Sjb#include <stdio.h> 38178476Sjb#include <ctype.h> 39178476Sjb#include <string.h> 40178476Sjb 41178476Sjb#include "interface.h" 42178476Sjb#include "addrtoname.h" 43178476Sjb#include "extract.h" /* must come after interface.h */ 44178476Sjb 45178476Sjbstruct rip { 46178476Sjb u_char rip_cmd; /* request/response */ 47178476Sjb u_char rip_vers; /* protocol version # */ 48178476Sjb u_short rip_zero2; /* unused */ 49178476Sjb}; 50178476Sjb#define RIPCMD_REQUEST 1 /* want info */ 51178476Sjb#define RIPCMD_RESPONSE 2 /* responding to request */ 52178476Sjb#define RIPCMD_TRACEON 3 /* turn tracing on */ 53178476Sjb#define RIPCMD_TRACEOFF 4 /* turn it off */ 54178476Sjb#define RIPCMD_POLL 5 /* want info from everybody */ 55178476Sjb#define RIPCMD_POLLENTRY 6 /* poll for entry */ 56178476Sjb 57178476Sjb#define RIP_AUTHLEN 16 58178476Sjb 59178476Sjbstruct rip_netinfo { 60178476Sjb u_short rip_family; 61178476Sjb u_short rip_tag; 62178476Sjb u_int32_t rip_dest; 63178476Sjb u_int32_t rip_dest_mask; 64178476Sjb u_int32_t rip_router; 65178476Sjb u_int32_t rip_metric; /* cost of route */ 66178476Sjb}; 67178476Sjb 68178476Sjbstatic void 69178476Sjbrip_printblk(const u_char *cp, const u_char *ep) 70178476Sjb{ 71178476Sjb for (; cp < ep; cp += 2) 72211545Srpaulo printf(" %04x", EXTRACT_16BITS(cp)); 73178476Sjb return; 74} 75 76static void 77rip_entry_print_v1(register int vers, register const struct rip_netinfo *ni) 78{ 79 register u_short family; 80 81 /* RFC 1058 */ 82 family = EXTRACT_16BITS(&ni->rip_family); 83 if (family != AF_INET) { 84 printf(" [family %d:", family); 85 rip_printblk((u_char *)&ni->rip_tag, 86 (u_char *)&ni->rip_metric + 87 sizeof(ni->rip_metric)); 88 printf("]"); 89 return; 90 } 91 if (ni->rip_tag || ni->rip_dest_mask || ni->rip_router) { 92 /* MBZ fields not zero */ 93 printf(" ["); 94 rip_printblk((u_char *)&ni->rip_family, 95 (u_char *)&ni->rip_metric + 96 sizeof(ni->rip_metric)); 97 printf("]"); 98 return; 99 } 100 printf(" {%s}(%d)", ipaddr_string(&ni->rip_dest), 101 EXTRACT_32BITS(&ni->rip_metric)); 102} 103 104static void 105rip_entry_print_v2(register int vers, register const struct rip_netinfo *ni) 106{ 107 register u_char *p; 108 register u_short family; 109 u_char buf[RIP_AUTHLEN]; 110 111 /* RFC 1723 */ 112 family = EXTRACT_16BITS(&ni->rip_family); 113 if (family == 0xFFFF) { 114 if (EXTRACT_16BITS(&ni->rip_tag) == 2) { 115 memcpy(buf, &ni->rip_dest, sizeof(buf)); 116 buf[sizeof(buf)-1] = '\0'; 117 for (p = buf; *p; p++) { 118 if (!isprint(*p)) 119 break; 120 } 121 if (!*p) { 122 printf(" [password %s]", buf); 123 } else { 124 printf(" [password: "); 125 rip_printblk((u_char *)&ni->rip_dest, 126 (u_char *)&ni->rip_metric + 127 sizeof(ni->rip_metric)); 128 printf("]"); 129 } 130 } else { 131 printf(" [auth %d:", 132 EXTRACT_16BITS(&ni->rip_tag)); 133 rip_printblk((u_char *)&ni->rip_dest, 134 (u_char *)&ni->rip_metric + 135 sizeof(ni->rip_metric)); 136 printf("]"); 137 } 138 } else if (family != AF_INET) { 139 printf(" [family %d:", family); 140 rip_printblk((u_char *)&ni->rip_tag, 141 (u_char *)&ni->rip_metric + 142 sizeof(ni->rip_metric)); 143 printf("]"); 144 return; 145 } else { /* AF_INET */ 146 printf(" {%s", ipaddr_string(&ni->rip_dest)); 147 if (ni->rip_dest_mask) 148 printf("/%s", ipaddr_string(&ni->rip_dest_mask)); 149 if (ni->rip_router) 150 printf("->%s", ipaddr_string(&ni->rip_router)); 151 if (ni->rip_tag) 152 printf(" tag %04x", EXTRACT_16BITS(&ni->rip_tag)); 153 printf("}(%d)", EXTRACT_32BITS(&ni->rip_metric)); 154 } 155} 156 157void 158rip_print(const u_char *dat, u_int length) 159{ 160 register const struct rip *rp; 161 register const struct rip_netinfo *ni; 162 register int i, j, trunc; 163 164 i = min(length, snapend - dat) - sizeof(*rp); 165 if (i < 0) { 166 printf(" [|rip]"); 167 return; 168 } 169 170 rp = (struct rip *)dat; 171 switch (rp->rip_vers) { 172 case 0: 173 /* 174 * RFC 1058. 175 * 176 * XXX - RFC 1058 says 177 * 178 * 0 Datagrams whose version number is zero are to be ignored. 179 * These are from a previous version of the protocol, whose 180 * packet format was machine-specific. 181 * 182 * so perhaps we should just dump the first few words of 183 * the packet, in hex. 184 */ 185 printf(" RIPv0: "); 186 ni = (struct rip_netinfo *)(rp + 1); 187 rip_printblk((u_char *)&ni->rip_family, 188 (u_char *)&ni->rip_metric + 189 sizeof(ni->rip_metric)); 190 break; 191 default: 192 switch (rp->rip_cmd) { 193 case RIPCMD_REQUEST: 194 printf(" RIPv%d-req %d", rp->rip_vers, length); 195 break; 196 case RIPCMD_RESPONSE: 197 j = length / sizeof(*ni); 198 if (j * sizeof(*ni) != length - 4) 199 printf(" RIPv%d-resp [items %d] [%d]:", 200 rp->rip_vers, j, length); 201 else 202 printf(" RIPv%d-resp [items %d]:", 203 rp->rip_vers, j); 204 trunc = (i / sizeof(*ni)) != j; 205 ni = (struct rip_netinfo *)(rp + 1); 206 for (; (i -= sizeof(*ni)) >= 0; ++ni) { 207 if (rp->rip_vers == 1) 208 rip_entry_print_v1(rp->rip_vers, ni); 209 else 210 rip_entry_print_v2(rp->rip_vers, ni); 211 } 212 if (trunc) 213 printf("[|rip]"); 214 break; 215 case RIPCMD_TRACEON: 216 printf(" RIPv%d-traceon %d: \"", rp->rip_vers, length); 217 (void)fn_print((const u_char *)(rp + 1), snapend); 218 fputs("\"\n", stdout); 219 break; 220 case RIPCMD_TRACEOFF: 221 printf(" RIPv%d-traceoff %d", rp->rip_vers, length); 222 break; 223 case RIPCMD_POLL: 224 printf(" RIPv%d-poll %d", rp->rip_vers, length); 225 break; 226 case RIPCMD_POLLENTRY: 227 printf(" RIPv%d-pollentry %d", rp->rip_vers, length); 228 break; 229 default: 230 printf(" RIPv%d-#%d %d", rp->rip_vers, rp->rip_cmd, 231 length); 232 break; 233 } 234 } 235} 236