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[] = 24 "@(#) $Header: /tcpdump/master/tcpdump/print-rip.c,v 1.49 2001/05/10 05:30:22 fenner Exp $ (LBL)"; 25 #endif 26 27 #ifdef HAVE_CONFIG_H 28 #include "config.h" 29 #endif 30 31 #include <sys/param.h> 32 #include <sys/time.h> 33 #include <sys/socket.h> 34 35 #include <netinet/in.h> 36 37 #include <stdio.h> 38 #include <ctype.h> 39 #include <string.h> 40 41 #include "interface.h" 42 #include "addrtoname.h" 43 #include "extract.h" /* must come after interface.h */ 44 45 struct rip { 46 u_char rip_cmd; /* request/response */ 47 u_char rip_vers; /* protocol version # */ 48 u_short rip_zero2; /* unused */ 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 57 #define RIP_AUTHLEN 16 58 59 struct rip_netinfo { 60 u_short rip_family; 61 u_short rip_tag; 62 u_int32_t rip_dest; 63 u_int32_t rip_dest_mask; 64 u_int32_t rip_router; 65 u_int32_t rip_metric; /* cost of route */ 66 }; 67 68 static void 69 rip_printblk(const u_char *cp, const u_char *ep) 70 { 71 for (; cp < ep; cp += 2) 72 printf(" %04x", EXTRACT_16BITS(cp)); 73 return; 74 } 75 76 static void 77 rip_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 104 static void 105 rip_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 157 void 158 rip_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("\"", 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