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 2005 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 *)(uintptr_t)rip->rip_cmd - 125 dlc_header, 1), get_line_remain(), "Opcode = %d (%s)", 126 rip->rip_cmd, show_cmd(rip->rip_cmd)); 127 (void) snprintf(get_line((char *)(uintptr_t)rip->rip_vers - 128 dlc_header, 1), get_line_remain(), "Version = %d", 129 rip->rip_vers); 130 131 switch (rip->rip_cmd) { 132 case RIPCMD_REQUEST: 133 case RIPCMD_RESPONSE: 134 case RIPCMD_POLL: 135 show_space(); 136 (void) snprintf(get_line(0, 0), get_line_remain(), 137 "Destination Next Hop " 138 "Tag Metric"); 139 for (nip = rip->rip_nets; len >= sizeof (*nip); nip++, 140 len -= sizeof (*nip)) { 141 if (nip->n_family == RIP_AF_AUTH) { 142 nap = (const struct netauth *)nip; 143 if (nap->a_type == RIP_AUTH_NONE) { 144 (void) snprintf(get_line 145 ((char *)nip - dlc_header, 146 sizeof (*nip)), 147 get_line_remain(), 148 " *** Auth None"); 149 } else if (nap->a_type == RIP_AUTH_PW) { 150 (void) snprintf(get_line 151 ((char *)nip - dlc_header, 152 sizeof (*nip)), 153 get_line_remain(), 154 " *** Auth PW \"%.*s\"", 155 RIP_AUTH_PW_LEN, 156 nap->au.au_pw); 157 } else if (nap->a_type == 158 RIP_AUTH_MD5) { 159 (void) snprintf(get_line 160 ((char *)nip - dlc_header, 161 sizeof (*nip)), 162 get_line_remain(), 163 " *** Auth MD5 pkt len %d, " 164 "keyid %d, sequence %08lX, " 165 "authlen %d", 166 ntohs(nap->au.a_md5. 167 md5_pkt_len), 168 nap->au.a_md5.md5_keyid, 169 ntohl(nap->au.a_md5. 170 md5_seqno), 171 ntohs(nap->au.a_md5. 172 md5_auth_len)); 173 if (len - sizeof (*nip) >= 174 ntohs(nap->au.a_md5. 175 md5_auth_len)) 176 len -= ntohs(nap->au. 177 a_md5.md5_auth_len); 178 else 179 len = sizeof (*nip); 180 } else { 181 (void) snprintf(get_line 182 ((char *)nip - dlc_header, 183 sizeof (*nip)), 184 get_line_remain(), 185 " *** Auth Type %d?", 186 ntohs(nap->a_type)); 187 } 188 continue; 189 } 190 if (nip->n_family == RIP_AF_UNSPEC && 191 rip->rip_cmd == RIPCMD_REQUEST) { 192 (void) snprintf(get_line((char *)nip - 193 dlc_header, sizeof (*nip)), 194 get_line_remain(), 195 " *** All routes"); 196 continue; 197 } 198 if (nip->n_family != RIP_AF_INET) { 199 (void) snprintf(get_line((char *)nip - 200 dlc_header, sizeof (*nip)), 201 get_line_remain(), 202 " *** Address Family %d?", 203 ntohs(nip->n_family)); 204 continue; 205 } 206 if (nip->n_dst == htonl(RIP_DEFAULT)) { 207 (void) strcpy(addrstr, "default"); 208 } else { 209 dst.s_addr = nip->n_dst; 210 (void) strlcpy(addrstr, inet_ntoa(dst), 211 sizeof (addrstr)); 212 } 213 if (nip->n_dst != htonl(RIP_DEFAULT) && 214 rip->rip_vers >= RIPv2) { 215 count = strlen(addrstr); 216 mval = ntohl(nip->n_mask); 217 /* LINTED */ 218 if (mval == INADDR_ANY) { 219 /* No mask */; 220 } else if ((mval + (mval & -mval)) == 221 0) { 222 (void) snprintf(addrstr + count, 223 sizeof (addrstr) - count, 224 "/%d", 33 - ffs(mval)); 225 } else { 226 dst.s_addr = nip->n_mask; 227 (void) snprintf(addrstr + count, 228 sizeof (addrstr) - count, 229 "/%s", inet_ntoa(dst)); 230 } 231 } 232 dst.s_addr = nip->n_nhop; 233 mval = ntohl(nip->n_metric); 234 (void) snprintf(get_line((char *)nip - 235 dlc_header, sizeof (*nip)), 236 get_line_remain(), 237 "%-31s %-15s %-6d %d%s", 238 addrstr, 239 dst.s_addr == htonl(INADDR_ANY) ? 240 "--" : addrtoname(AF_INET, &dst), 241 ntohs(nip->n_tag), 242 mval, 243 (mval == HOPCNT_INFINITY ? 244 " (not reachable)" : "")); 245 } 246 break; 247 248 case RIPCMD_POLLENTRY: 249 if (len < sizeof (*ep)) 250 break; 251 len -= sizeof (*ep); 252 ep = (const struct entryinfo *)rip->rip_nets; 253 /* LINTED */ 254 sin = (const struct sockaddr_in *)&ep->rtu_dst; 255 (void) snprintf(get_line((char *)sin - dlc_header, 256 sizeof (struct sockaddr)), get_line_remain(), 257 "Destination = %s %s", 258 inet_ntoa(sin->sin_addr), 259 addrtoname(AF_INET, (void *)&sin->sin_addr)); 260 /* LINTED */ 261 sin = (const struct sockaddr_in *)&ep->rtu_router; 262 (void) snprintf(get_line((char *)sin - dlc_header, 263 sizeof (struct sockaddr)), get_line_remain(), 264 "Router = %s %s", 265 inet_ntoa(sin->sin_addr), 266 addrtoname(AF_INET, (void *)&sin->sin_addr)); 267 (void) snprintf(get_line((char *)&ep->rtu_flags - 268 dlc_header, 2), get_line_remain(), 269 "Flags = %4x", (unsigned)ep->rtu_flags); 270 (void) snprintf(get_line((char *)&ep->rtu_state - 271 dlc_header, 2), get_line_remain(), 272 "State = %d", ep->rtu_state); 273 (void) snprintf(get_line((char *)&ep->rtu_timer - 274 dlc_header, 4), get_line_remain(), 275 "Timer = %d", ep->rtu_timer); 276 (void) snprintf(get_line((char *)&ep->rtu_metric - 277 dlc_header, 4), get_line_remain(), 278 "Metric = %d", ep->rtu_metric); 279 (void) snprintf(get_line((char *)&ep->int_flags - 280 dlc_header, 4), get_line_remain(), 281 "Int flags = %8x", ep->int_flags); 282 (void) snprintf(get_line((char *)ep->int_name - 283 dlc_header, sizeof (ep->int_name)), 284 get_line_remain(), 285 "Int name = \"%.*s\"", sizeof (ep->int_name), 286 ep->int_name); 287 break; 288 289 case RIPCMD_TRACEON: 290 case RIPCMD_TRACEOFF: 291 (void) snprintf(get_line((char *)rip->rip_tracefile - 292 dlc_header, 2), get_line_remain(), 293 "Trace file = %.*s", len, rip->rip_tracefile); 294 len = 0; 295 break; 296 } 297 } 298 299 return (fraglen - len); 300 } 301 302 static char * 303 show_cmd(int c) 304 { 305 switch (c) { 306 case RIPCMD_REQUEST: 307 return ("route request"); 308 case RIPCMD_RESPONSE: 309 return ("route response"); 310 case RIPCMD_TRACEON: 311 return ("route trace on"); 312 case RIPCMD_TRACEOFF: 313 return ("route trace off"); 314 case RIPCMD_POLL: 315 return ("route poll"); 316 case RIPCMD_POLLENTRY: 317 return ("route poll entry"); 318 } 319 return ("?"); 320 } 321