1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1676 jpk * Common Development and Distribution License (the "License"). 6 1676 jpk * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 1676 jpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 27 0 stevel 28 0 stevel #include <stdio.h> 29 0 stevel #include <string.h> 30 0 stevel #include <strings.h> 31 0 stevel #include <fcntl.h> 32 0 stevel #include <sys/types.h> 33 0 stevel #include <sys/socket.h> 34 0 stevel #include <netinet/in.h> 35 0 stevel #include <arpa/inet.h> 36 0 stevel #define RIPVERSION RIPv2 37 0 stevel #include <protocols/routed.h> 38 0 stevel #include "snoop.h" 39 0 stevel 40 1676 jpk static const char *show_cmd(int); 41 1676 jpk static int get_numtokens(unsigned int); 42 1676 jpk static const struct rip_sec_entry *rip_next_sec_entry( 43 1676 jpk const struct rip_sec_entry *, int); 44 0 stevel 45 0 stevel int 46 0 stevel interpret_rip(int flags, struct rip *rip, int fraglen) 47 0 stevel { 48 0 stevel const struct netinfo *nip; 49 0 stevel const struct entryinfo *ep; 50 0 stevel const struct netauth *nap; 51 1676 jpk const struct rip_sec_entry *rsep, *rsn; 52 1676 jpk const struct rip_emetric *rep; 53 1676 jpk const uint32_t *tokp; 54 0 stevel int len, count; 55 0 stevel const char *cmdstr, *auth; 56 0 stevel struct in_addr dst; 57 0 stevel uint32_t mval; 58 0 stevel const struct sockaddr_in *sin; 59 0 stevel /* Room for IP destination + "/" + IP mask */ 60 0 stevel char addrstr[15+1+15+1]; 61 0 stevel /* Room for "RIPv" + uint8_t as %d */ 62 0 stevel char ripvers[4+3+1]; 63 0 stevel 64 0 stevel /* RIP header is 4 octets long */ 65 0 stevel if ((len = fraglen - 4) < 0) 66 0 stevel return (0); 67 0 stevel 68 0 stevel if (flags & F_SUM) { 69 0 stevel switch (rip->rip_cmd) { 70 0 stevel case RIPCMD_REQUEST: cmdstr = "C"; break; 71 0 stevel case RIPCMD_RESPONSE: cmdstr = "R"; break; 72 0 stevel case RIPCMD_TRACEON: cmdstr = "Traceon"; break; 73 0 stevel case RIPCMD_TRACEOFF: cmdstr = "Traceoff"; break; 74 0 stevel case RIPCMD_POLL: cmdstr = "Poll"; break; 75 0 stevel case RIPCMD_POLLENTRY: cmdstr = "Poll entry"; break; 76 1676 jpk case RIPCMD_SEC_RESPONSE: cmdstr = "R - SEC"; break; 77 1676 jpk case RIPCMD_SEC_T_RESPONSE: cmdstr = "R - SEC_T"; break; 78 0 stevel default: cmdstr = "?"; break; 79 0 stevel } 80 0 stevel 81 0 stevel if (rip->rip_vers == RIPv1) 82 0 stevel (void) strlcpy(ripvers, "RIP", sizeof (ripvers)); 83 0 stevel else 84 0 stevel (void) snprintf(ripvers, sizeof (ripvers), "RIPv%d", 85 0 stevel rip->rip_vers); 86 0 stevel 87 0 stevel switch (rip->rip_cmd) { 88 0 stevel case RIPCMD_REQUEST: 89 0 stevel case RIPCMD_RESPONSE: 90 0 stevel case RIPCMD_POLL: 91 0 stevel nip = rip->rip_nets; 92 0 stevel auth = ""; 93 0 stevel if (len >= sizeof (*nip) && 94 0 stevel nip->n_family == RIP_AF_AUTH) { 95 0 stevel nap = (struct netauth *)nip; 96 0 stevel len -= sizeof (*nip); 97 0 stevel if (nap->a_type == RIP_AUTH_MD5 && 98 0 stevel len >= ntohs(nap->au.a_md5.md5_auth_len)) 99 0 stevel len -= ntohs(nap->au.a_md5. 100 0 stevel md5_auth_len); 101 0 stevel auth = " +Auth"; 102 0 stevel } 103 0 stevel count = len / sizeof (*nip); 104 0 stevel len %= sizeof (*nip); 105 0 stevel (void) snprintf(get_sum_line(), MAXLINE, 106 0 stevel "%s %s (%d destinations%s%s)", ripvers, cmdstr, 107 0 stevel count, (len != 0 ? "?" : ""), auth); 108 0 stevel break; 109 0 stevel 110 0 stevel case RIPCMD_TRACEON: 111 0 stevel case RIPCMD_TRACEOFF: 112 0 stevel (void) snprintf(get_sum_line(), MAXLINE, 113 0 stevel "%s %s File=\"%.*s\"", ripvers, cmdstr, len, 114 0 stevel rip->rip_tracefile); 115 0 stevel len = 0; 116 0 stevel break; 117 0 stevel 118 1676 jpk case RIPCMD_SEC_RESPONSE: 119 1676 jpk case RIPCMD_SEC_T_RESPONSE: 120 1676 jpk if (len < sizeof (rip->rip_tsol.rip_generation)) 121 1676 jpk break; 122 1676 jpk len -= sizeof (rip->rip_tsol.rip_generation); 123 1676 jpk count = 0; 124 1676 jpk rsep = rip->rip_tsol.rip_sec_entry; 125 1676 jpk while (len > 0) { 126 1676 jpk rsn = rip_next_sec_entry(rsep, len); 127 1676 jpk if (rsn == NULL) 128 1676 jpk break; 129 1676 jpk len -= (const char *)rsn - (const char *)rsep; 130 1676 jpk rsep = rsn; 131 1676 jpk count++; 132 1676 jpk } 133 1676 jpk (void) snprintf(get_sum_line(), MAXLINE, 134 1676 jpk "%s %s (%d destinations%s)", ripvers, cmdstr, 135 1676 jpk count, (len != 0 ? "?" : "")); 136 1676 jpk break; 137 1676 jpk 138 0 stevel default: 139 0 stevel (void) snprintf(get_sum_line(), MAXLINE, 140 0 stevel "%s %d (%s)", ripvers, rip->rip_cmd, cmdstr); 141 0 stevel len = 0; 142 0 stevel break; 143 0 stevel } 144 0 stevel } 145 0 stevel 146 0 stevel if (flags & F_DTAIL) { 147 0 stevel 148 0 stevel len = fraglen - 4; 149 0 stevel show_header("RIP: ", "Routing Information Protocol", fraglen); 150 0 stevel show_space(); 151 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 152 1676 jpk "Opcode = %d (%s)", rip->rip_cmd, 153 1676 jpk show_cmd(rip->rip_cmd)); 154 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 155 1676 jpk "Version = %d", rip->rip_vers); 156 0 stevel 157 0 stevel switch (rip->rip_cmd) { 158 0 stevel case RIPCMD_REQUEST: 159 0 stevel case RIPCMD_RESPONSE: 160 0 stevel case RIPCMD_POLL: 161 0 stevel show_space(); 162 0 stevel (void) snprintf(get_line(0, 0), get_line_remain(), 163 0 stevel "Destination Next Hop " 164 0 stevel "Tag Metric"); 165 0 stevel for (nip = rip->rip_nets; len >= sizeof (*nip); nip++, 166 0 stevel len -= sizeof (*nip)) { 167 0 stevel if (nip->n_family == RIP_AF_AUTH) { 168 0 stevel nap = (const struct netauth *)nip; 169 0 stevel if (nap->a_type == RIP_AUTH_NONE) { 170 0 stevel (void) snprintf(get_line 171 0 stevel ((char *)nip - dlc_header, 172 0 stevel sizeof (*nip)), 173 0 stevel get_line_remain(), 174 0 stevel " *** Auth None"); 175 0 stevel } else if (nap->a_type == RIP_AUTH_PW) { 176 0 stevel (void) snprintf(get_line 177 0 stevel ((char *)nip - dlc_header, 178 0 stevel sizeof (*nip)), 179 0 stevel get_line_remain(), 180 0 stevel " *** Auth PW \"%.*s\"", 181 0 stevel RIP_AUTH_PW_LEN, 182 0 stevel nap->au.au_pw); 183 0 stevel } else if (nap->a_type == 184 0 stevel RIP_AUTH_MD5) { 185 1676 jpk (void) snprintf(get_line(0, 0), 186 0 stevel get_line_remain(), 187 0 stevel " *** Auth MD5 pkt len %d, " 188 0 stevel "keyid %d, sequence %08lX, " 189 0 stevel "authlen %d", 190 0 stevel ntohs(nap->au.a_md5. 191 0 stevel md5_pkt_len), 192 0 stevel nap->au.a_md5.md5_keyid, 193 1676 jpk (long)ntohl(nap->au.a_md5. 194 0 stevel md5_seqno), 195 0 stevel ntohs(nap->au.a_md5. 196 0 stevel md5_auth_len)); 197 0 stevel if (len - sizeof (*nip) >= 198 0 stevel ntohs(nap->au.a_md5. 199 0 stevel md5_auth_len)) 200 0 stevel len -= ntohs(nap->au. 201 0 stevel a_md5.md5_auth_len); 202 0 stevel else 203 0 stevel len = sizeof (*nip); 204 0 stevel } else { 205 0 stevel (void) snprintf(get_line 206 0 stevel ((char *)nip - dlc_header, 207 0 stevel sizeof (*nip)), 208 0 stevel get_line_remain(), 209 0 stevel " *** Auth Type %d?", 210 0 stevel ntohs(nap->a_type)); 211 0 stevel } 212 0 stevel continue; 213 0 stevel } 214 0 stevel if (nip->n_family == RIP_AF_UNSPEC && 215 0 stevel rip->rip_cmd == RIPCMD_REQUEST) { 216 1676 jpk (void) snprintf(get_line(0, 0), 217 0 stevel get_line_remain(), 218 0 stevel " *** All routes"); 219 0 stevel continue; 220 0 stevel } 221 0 stevel if (nip->n_family != RIP_AF_INET) { 222 1676 jpk (void) snprintf(get_line(0, 0), 223 0 stevel get_line_remain(), 224 0 stevel " *** Address Family %d?", 225 0 stevel ntohs(nip->n_family)); 226 0 stevel continue; 227 0 stevel } 228 0 stevel if (nip->n_dst == htonl(RIP_DEFAULT)) { 229 0 stevel (void) strcpy(addrstr, "default"); 230 0 stevel } else { 231 0 stevel dst.s_addr = nip->n_dst; 232 0 stevel (void) strlcpy(addrstr, inet_ntoa(dst), 233 0 stevel sizeof (addrstr)); 234 0 stevel } 235 0 stevel if (nip->n_dst != htonl(RIP_DEFAULT) && 236 0 stevel rip->rip_vers >= RIPv2) { 237 0 stevel count = strlen(addrstr); 238 0 stevel mval = ntohl(nip->n_mask); 239 0 stevel /* LINTED */ 240 0 stevel if (mval == INADDR_ANY) { 241 0 stevel /* No mask */; 242 0 stevel } else if ((mval + (mval & -mval)) == 243 0 stevel 0) { 244 0 stevel (void) snprintf(addrstr + count, 245 0 stevel sizeof (addrstr) - count, 246 0 stevel "/%d", 33 - ffs(mval)); 247 0 stevel } else { 248 0 stevel dst.s_addr = nip->n_mask; 249 0 stevel (void) snprintf(addrstr + count, 250 0 stevel sizeof (addrstr) - count, 251 0 stevel "/%s", inet_ntoa(dst)); 252 0 stevel } 253 0 stevel } 254 0 stevel dst.s_addr = nip->n_nhop; 255 0 stevel mval = ntohl(nip->n_metric); 256 1676 jpk (void) snprintf(get_line(0, 0), 257 0 stevel get_line_remain(), 258 0 stevel "%-31s %-15s %-6d %d%s", 259 0 stevel addrstr, 260 0 stevel dst.s_addr == htonl(INADDR_ANY) ? 261 0 stevel "--" : addrtoname(AF_INET, &dst), 262 0 stevel ntohs(nip->n_tag), 263 0 stevel mval, 264 0 stevel (mval == HOPCNT_INFINITY ? 265 0 stevel " (not reachable)" : "")); 266 0 stevel } 267 0 stevel break; 268 0 stevel 269 0 stevel case RIPCMD_POLLENTRY: 270 0 stevel if (len < sizeof (*ep)) 271 0 stevel break; 272 0 stevel len -= sizeof (*ep); 273 0 stevel ep = (const struct entryinfo *)rip->rip_nets; 274 0 stevel /* LINTED */ 275 0 stevel sin = (const struct sockaddr_in *)&ep->rtu_dst; 276 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 277 0 stevel "Destination = %s %s", 278 0 stevel inet_ntoa(sin->sin_addr), 279 0 stevel addrtoname(AF_INET, (void *)&sin->sin_addr)); 280 0 stevel /* LINTED */ 281 0 stevel sin = (const struct sockaddr_in *)&ep->rtu_router; 282 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 283 0 stevel "Router = %s %s", 284 0 stevel inet_ntoa(sin->sin_addr), 285 0 stevel addrtoname(AF_INET, (void *)&sin->sin_addr)); 286 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 287 0 stevel "Flags = %4x", (unsigned)ep->rtu_flags); 288 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 289 0 stevel "State = %d", ep->rtu_state); 290 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 291 0 stevel "Timer = %d", ep->rtu_timer); 292 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 293 0 stevel "Metric = %d", ep->rtu_metric); 294 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 295 0 stevel "Int flags = %8x", ep->int_flags); 296 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 297 0 stevel "Int name = \"%.*s\"", sizeof (ep->int_name), 298 0 stevel ep->int_name); 299 0 stevel break; 300 0 stevel 301 1676 jpk case RIPCMD_SEC_RESPONSE: 302 1676 jpk case RIPCMD_SEC_T_RESPONSE: 303 1676 jpk if (len < sizeof (rip->rip_tsol.rip_generation)) 304 1676 jpk break; 305 1676 jpk len -= sizeof (rip->rip_tsol.rip_generation); 306 1676 jpk show_space(); 307 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 308 1676 jpk "Generation = %u", 309 1676 jpk (unsigned)ntohl(rip->rip_tsol.rip_generation)); 310 1676 jpk rsep = rip->rip_tsol.rip_sec_entry; 311 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 312 1676 jpk "Address E-METRIC"); 313 1676 jpk rsep = rip->rip_tsol.rip_sec_entry; 314 1676 jpk while (len > 0) { 315 1676 jpk char *cp; 316 1676 jpk int blen, num; 317 1676 jpk 318 1676 jpk rsn = rip_next_sec_entry(rsep, len); 319 1676 jpk if (rsn == NULL) 320 1676 jpk break; 321 1676 jpk dst.s_addr = rsep->rip_dst; 322 1676 jpk cp = get_line(0, 0); 323 1676 jpk blen = get_line_remain(); 324 1676 jpk (void) snprintf(cp, blen, "%-16s ", 325 1676 jpk inet_ntoa(dst)); 326 1676 jpk cp += 17; 327 1676 jpk blen -= 17; 328 1676 jpk rep = rsep->rip_emetric; 329 1676 jpk for (count = ntohl(rsep->rip_count); count > 0; 330 1676 jpk count--) { 331 1676 jpk (void) snprintf(cp, blen, "metric=%d", 332 1676 jpk ntohs(rep->rip_metric)); 333 1676 jpk blen -= strlen(cp); 334 1676 jpk cp += strlen(cp); 335 1676 jpk tokp = rep->rip_token; 336 1676 jpk num = get_numtokens( 337 1676 jpk ntohs(rep->rip_mask)); 338 1676 jpk /* advance to the next emetric */ 339 1676 jpk rep = (const struct rip_emetric *) 340 1676 jpk &rep->rip_token[num]; 341 1676 jpk if (num > 0) { 342 1676 jpk (void) snprintf(cp, blen, 343 1676 jpk ",tokens=%lx", 344 1676 jpk (long)ntohl(*tokp)); 345 1676 jpk tokp++; 346 1676 jpk num--; 347 1676 jpk } else { 348 1676 jpk (void) strlcpy(cp, ",no tokens", 349 1676 jpk blen); 350 1676 jpk } 351 1676 jpk while (num > 0) { 352 1676 jpk blen -= strlen(cp); 353 1676 jpk cp += strlen(cp); 354 1676 jpk (void) snprintf(cp, blen, 355 1676 jpk ",%lx", 356 1676 jpk (long)ntohl(*tokp)); 357 1676 jpk tokp++; 358 1676 jpk num--; 359 1676 jpk } 360 1676 jpk blen -= strlen(cp); 361 1676 jpk cp += strlen(cp); 362 1676 jpk } 363 1676 jpk if (rsep->rip_count == 0) { 364 1676 jpk (void) strlcpy(cp, 365 1676 jpk "NULL (not reachable)", blen); 366 1676 jpk } 367 1676 jpk len -= (const char *)rsn - (const char *)rsep; 368 1676 jpk rsep = rsn; 369 1676 jpk } 370 1676 jpk break; 371 1676 jpk 372 0 stevel case RIPCMD_TRACEON: 373 0 stevel case RIPCMD_TRACEOFF: 374 1676 jpk (void) snprintf(get_line(0, 0), get_line_remain(), 375 0 stevel "Trace file = %.*s", len, rip->rip_tracefile); 376 0 stevel len = 0; 377 0 stevel break; 378 0 stevel } 379 0 stevel } 380 0 stevel 381 0 stevel return (fraglen - len); 382 0 stevel } 383 0 stevel 384 1676 jpk static const char * 385 0 stevel show_cmd(int c) 386 0 stevel { 387 0 stevel switch (c) { 388 0 stevel case RIPCMD_REQUEST: 389 0 stevel return ("route request"); 390 0 stevel case RIPCMD_RESPONSE: 391 0 stevel return ("route response"); 392 0 stevel case RIPCMD_TRACEON: 393 0 stevel return ("route trace on"); 394 0 stevel case RIPCMD_TRACEOFF: 395 0 stevel return ("route trace off"); 396 0 stevel case RIPCMD_POLL: 397 0 stevel return ("route poll"); 398 0 stevel case RIPCMD_POLLENTRY: 399 0 stevel return ("route poll entry"); 400 1676 jpk case RIPCMD_SEC_RESPONSE: 401 1676 jpk return ("route sec response"); 402 1676 jpk case RIPCMD_SEC_T_RESPONSE: 403 1676 jpk return ("route sec_t response"); 404 0 stevel } 405 0 stevel return ("?"); 406 0 stevel } 407 1676 jpk 408 1676 jpk static int 409 1676 jpk get_numtokens(unsigned int mask) 410 1676 jpk { 411 1676 jpk int num = 0; 412 1676 jpk 413 1676 jpk while (mask != 0) { 414 1676 jpk num++; 415 1676 jpk mask &= mask - 1; 416 1676 jpk } 417 1676 jpk return (num); 418 1676 jpk } 419 1676 jpk 420 1676 jpk static const struct rip_sec_entry * 421 1676 jpk rip_next_sec_entry(const struct rip_sec_entry *rsep, int len) 422 1676 jpk { 423 1676 jpk const struct rip_emetric *rep; 424 1676 jpk const char *limit = (const char *)rsep + len; 425 1676 jpk long count; 426 1676 jpk 427 1676 jpk if ((const char *)(rep = rsep->rip_emetric) > limit) 428 1676 jpk return (NULL); 429 1676 jpk count = ntohl(rsep->rip_count); 430 1676 jpk while (count > 0) { 431 1676 jpk if ((const char *)rep->rip_token > limit) 432 1676 jpk return (NULL); 433 1676 jpk rep = (struct rip_emetric *) 434 1676 jpk &rep->rip_token[get_numtokens(ntohs(rep->rip_mask))]; 435 1676 jpk if ((const char *)rep > limit) 436 1676 jpk return (NULL); 437 1676 jpk count--; 438 1676 jpk } 439 1676 jpk return ((const struct rip_sec_entry *)rep); 440 1676 jpk } 441