1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1991-2002 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <string.h> 31 #include <strings.h> 32 #include <fcntl.h> 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 #include <netinet/in.h> 36 #include <arpa/inet.h> 37 #define RIPVERSION RIPv2 38 #include <protocols/routed.h> 39 #include "snoop.h" 40 41 static char *show_cmd(int); 42 43 int 44 interpret_rip(int flags, struct rip *rip, int fraglen) 45 { 46 const struct netinfo *nip; 47 const struct entryinfo *ep; 48 const struct netauth *nap; 49 int len, count; 50 const char *cmdstr, *auth; 51 struct in_addr dst; 52 uint32_t mval; 53 const struct sockaddr_in *sin; 54 /* Room for IP destination + "/" + IP mask */ 55 char addrstr[15+1+15+1]; 56 /* Room for "RIPv" + uint8_t as %d */ 57 char ripvers[4+3+1]; 58 59 /* RIP header is 4 octets long */ 60 if ((len = fraglen - 4) < 0) 61 return (0); 62 63 if (flags & F_SUM) { 64 switch (rip->rip_cmd) { 65 case RIPCMD_REQUEST: cmdstr = "C"; break; 66 case RIPCMD_RESPONSE: cmdstr = "R"; break; 67 case RIPCMD_TRACEON: cmdstr = "Traceon"; break; 68 case RIPCMD_TRACEOFF: cmdstr = "Traceoff"; break; 69 case RIPCMD_POLL: cmdstr = "Poll"; break; 70 case RIPCMD_POLLENTRY: cmdstr = "Poll entry"; break; 71 default: cmdstr = "?"; break; 72 } 73 74 if (rip->rip_vers == RIPv1) 75 (void) strlcpy(ripvers, "RIP", sizeof (ripvers)); 76 else 77 (void) snprintf(ripvers, sizeof (ripvers), "RIPv%d", 78 rip->rip_vers); 79 80 switch (rip->rip_cmd) { 81 case RIPCMD_REQUEST: 82 case RIPCMD_RESPONSE: 83 case RIPCMD_POLL: 84 nip = rip->rip_nets; 85 auth = ""; 86 if (len >= sizeof (*nip) && 87 nip->n_family == RIP_AF_AUTH) { 88 nap = (struct netauth *)nip; 89 len -= sizeof (*nip); 90 if (nap->a_type == RIP_AUTH_MD5 && 91 len >= ntohs(nap->au.a_md5.md5_auth_len)) 92 len -= ntohs(nap->au.a_md5. 93 md5_auth_len); 94 auth = " +Auth"; 95 } 96 count = len / sizeof (*nip); 97 len %= sizeof (*nip); 98 (void) snprintf(get_sum_line(), MAXLINE, 99 "%s %s (%d destinations%s%s)", ripvers, cmdstr, 100 count, (len != 0 ? "?" : ""), auth); 101 break; 102 103 case RIPCMD_TRACEON: 104 case RIPCMD_TRACEOFF: 105 (void) snprintf(get_sum_line(), MAXLINE, 106 "%s %s File=\"%.*s\"", ripvers, cmdstr, len, 107 rip->rip_tracefile); 108 len = 0; 109 break; 110 111 default: 112 (void) snprintf(get_sum_line(), MAXLINE, 113 "%s %d (%s)", ripvers, rip->rip_cmd, cmdstr); 114 len = 0; 115 break; 116 } 117 } 118 119 if (flags & F_DTAIL) { 120 121 len = fraglen - 4; 122 show_header("RIP: ", "Routing Information Protocol", fraglen); 123 show_space(); 124 (void) snprintf(get_line((char *)rip->rip_cmd - dlc_header, 1), 125 get_line_remain(), "Opcode = %d (%s)", rip->rip_cmd, 126 show_cmd(rip->rip_cmd)); 127 (void) snprintf(get_line((char *)rip->rip_vers - dlc_header, 1), 128 get_line_remain(), "Version = %d", rip->rip_vers); 129 130 switch (rip->rip_cmd) { 131 case RIPCMD_REQUEST: 132 case RIPCMD_RESPONSE: 133 case RIPCMD_POLL: 134 show_space(); 135 (void) snprintf(get_line(0, 0), get_line_remain(), 136 "Destination Next Hop " 137 "Tag Metric"); 138 for (nip = rip->rip_nets; len >= sizeof (*nip); nip++, 139 len -= sizeof (*nip)) { 140 if (nip->n_family == RIP_AF_AUTH) { 141 nap = (const struct netauth *)nip; 142 if (nap->a_type == RIP_AUTH_NONE) { 143 (void) snprintf(get_line 144 ((char *)nip - dlc_header, 145 sizeof (*nip)), 146 get_line_remain(), 147 " *** Auth None"); 148 } else if (nap->a_type == RIP_AUTH_PW) { 149 (void) snprintf(get_line 150 ((char *)nip - dlc_header, 151 sizeof (*nip)), 152 get_line_remain(), 153 " *** Auth PW \"%.*s\"", 154 RIP_AUTH_PW_LEN, 155 nap->au.au_pw); 156 } else if (nap->a_type == 157 RIP_AUTH_MD5) { 158 (void) snprintf(get_line 159 ((char *)nip - dlc_header, 160 sizeof (*nip)), 161 get_line_remain(), 162 " *** Auth MD5 pkt len %d, " 163 "keyid %d, sequence %08lX, " 164 "authlen %d", 165 ntohs(nap->au.a_md5. 166 md5_pkt_len), 167 nap->au.a_md5.md5_keyid, 168 ntohl(nap->au.a_md5. 169 md5_seqno), 170 ntohs(nap->au.a_md5. 171 md5_auth_len)); 172 if (len - sizeof (*nip) >= 173 ntohs(nap->au.a_md5. 174 md5_auth_len)) 175 len -= ntohs(nap->au. 176 a_md5.md5_auth_len); 177 else 178 len = sizeof (*nip); 179 } else { 180 (void) snprintf(get_line 181 ((char *)nip - dlc_header, 182 sizeof (*nip)), 183 get_line_remain(), 184 " *** Auth Type %d?", 185 ntohs(nap->a_type)); 186 } 187 continue; 188 } 189 if (nip->n_family == RIP_AF_UNSPEC && 190 rip->rip_cmd == RIPCMD_REQUEST) { 191 (void) snprintf(get_line((char *)nip - 192 dlc_header, sizeof (*nip)), 193 get_line_remain(), 194 " *** All routes"); 195 continue; 196 } 197 if (nip->n_family != RIP_AF_INET) { 198 (void) snprintf(get_line((char *)nip - 199 dlc_header, sizeof (*nip)), 200 get_line_remain(), 201 " *** Address Family %d?", 202 ntohs(nip->n_family)); 203 continue; 204 } 205 if (nip->n_dst == htonl(RIP_DEFAULT)) { 206 (void) strcpy(addrstr, "default"); 207 } else { 208 dst.s_addr = nip->n_dst; 209 (void) strlcpy(addrstr, inet_ntoa(dst), 210 sizeof (addrstr)); 211 } 212 if (nip->n_dst != htonl(RIP_DEFAULT) && 213 rip->rip_vers >= RIPv2) { 214 count = strlen(addrstr); 215 mval = ntohl(nip->n_mask); 216 /* LINTED */ 217 if (mval == INADDR_ANY) { 218 /* No mask */; 219 } else if ((mval + (mval & -mval)) == 220 0) { 221 (void) snprintf(addrstr + count, 222 sizeof (addrstr) - count, 223 "/%d", 33 - ffs(mval)); 224 } else { 225 dst.s_addr = nip->n_mask; 226 (void) snprintf(addrstr + count, 227 sizeof (addrstr) - count, 228 "/%s", inet_ntoa(dst)); 229 } 230 } 231 dst.s_addr = nip->n_nhop; 232 mval = ntohl(nip->n_metric); 233 (void) snprintf(get_line((char *)nip - 234 dlc_header, sizeof (*nip)), 235 get_line_remain(), 236 "%-31s %-15s %-6d %d%s", 237 addrstr, 238 dst.s_addr == htonl(INADDR_ANY) ? 239 "--" : addrtoname(AF_INET, &dst), 240 ntohs(nip->n_tag), 241 mval, 242 (mval == HOPCNT_INFINITY ? 243 " (not reachable)" : "")); 244 } 245 break; 246 247 case RIPCMD_POLLENTRY: 248 if (len < sizeof (*ep)) 249 break; 250 len -= sizeof (*ep); 251 ep = (const struct entryinfo *)rip->rip_nets; 252 /* LINTED */ 253 sin = (const struct sockaddr_in *)&ep->rtu_dst; 254 (void) snprintf(get_line((char *)sin - dlc_header, 255 sizeof (struct sockaddr)), get_line_remain(), 256 "Destination = %s %s", 257 inet_ntoa(sin->sin_addr), 258 addrtoname(AF_INET, (void *)&sin->sin_addr)); 259 /* LINTED */ 260 sin = (const struct sockaddr_in *)&ep->rtu_router; 261 (void) snprintf(get_line((char *)sin - dlc_header, 262 sizeof (struct sockaddr)), get_line_remain(), 263 "Router = %s %s", 264 inet_ntoa(sin->sin_addr), 265 addrtoname(AF_INET, (void *)&sin->sin_addr)); 266 (void) snprintf(get_line((char *)&ep->rtu_flags - 267 dlc_header, 2), get_line_remain(), 268 "Flags = %4x", (unsigned)ep->rtu_flags); 269 (void) snprintf(get_line((char *)&ep->rtu_state - 270 dlc_header, 2), get_line_remain(), 271 "State = %d", ep->rtu_state); 272 (void) snprintf(get_line((char *)&ep->rtu_timer - 273 dlc_header, 4), get_line_remain(), 274 "Timer = %d", ep->rtu_timer); 275 (void) snprintf(get_line((char *)&ep->rtu_metric - 276 dlc_header, 4), get_line_remain(), 277 "Metric = %d", ep->rtu_metric); 278 (void) snprintf(get_line((char *)&ep->int_flags - 279 dlc_header, 4), get_line_remain(), 280 "Int flags = %8x", ep->int_flags); 281 (void) snprintf(get_line((char *)ep->int_name - 282 dlc_header, sizeof (ep->int_name)), 283 get_line_remain(), 284 "Int name = \"%.*s\"", sizeof (ep->int_name), 285 ep->int_name); 286 break; 287 288 case RIPCMD_TRACEON: 289 case RIPCMD_TRACEOFF: 290 (void) snprintf(get_line((char *)rip->rip_tracefile - 291 dlc_header, 2), get_line_remain(), 292 "Trace file = %.*s", len, rip->rip_tracefile); 293 len = 0; 294 break; 295 } 296 } 297 298 return (fraglen - len); 299 } 300 301 static char * 302 show_cmd(int c) 303 { 304 switch (c) { 305 case RIPCMD_REQUEST: 306 return ("route request"); 307 case RIPCMD_RESPONSE: 308 return ("route response"); 309 case RIPCMD_TRACEON: 310 return ("route trace on"); 311 case RIPCMD_TRACEOFF: 312 return ("route trace off"); 313 case RIPCMD_POLL: 314 return ("route poll"); 315 case RIPCMD_POLLENTRY: 316 return ("route poll entry"); 317 } 318 return ("?"); 319 } 320