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