17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*45916cd2Sjpk * Common Development and Distribution License (the "License").
6*45916cd2Sjpk * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*45916cd2Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include <strings.h>
317c478bd9Sstevel@tonic-gate #include <fcntl.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/socket.h>
347c478bd9Sstevel@tonic-gate #include <netinet/in.h>
357c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
367c478bd9Sstevel@tonic-gate #define RIPVERSION RIPv2
377c478bd9Sstevel@tonic-gate #include <protocols/routed.h>
387c478bd9Sstevel@tonic-gate #include "snoop.h"
397c478bd9Sstevel@tonic-gate
40*45916cd2Sjpk static const char *show_cmd(int);
41*45916cd2Sjpk static int get_numtokens(unsigned int);
42*45916cd2Sjpk static const struct rip_sec_entry *rip_next_sec_entry(
43*45916cd2Sjpk const struct rip_sec_entry *, int);
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate int
interpret_rip(int flags,struct rip * rip,int fraglen)467c478bd9Sstevel@tonic-gate interpret_rip(int flags, struct rip *rip, int fraglen)
477c478bd9Sstevel@tonic-gate {
487c478bd9Sstevel@tonic-gate const struct netinfo *nip;
497c478bd9Sstevel@tonic-gate const struct entryinfo *ep;
507c478bd9Sstevel@tonic-gate const struct netauth *nap;
51*45916cd2Sjpk const struct rip_sec_entry *rsep, *rsn;
52*45916cd2Sjpk const struct rip_emetric *rep;
53*45916cd2Sjpk const uint32_t *tokp;
547c478bd9Sstevel@tonic-gate int len, count;
557c478bd9Sstevel@tonic-gate const char *cmdstr, *auth;
567c478bd9Sstevel@tonic-gate struct in_addr dst;
577c478bd9Sstevel@tonic-gate uint32_t mval;
587c478bd9Sstevel@tonic-gate const struct sockaddr_in *sin;
597c478bd9Sstevel@tonic-gate /* Room for IP destination + "/" + IP mask */
607c478bd9Sstevel@tonic-gate char addrstr[15+1+15+1];
617c478bd9Sstevel@tonic-gate /* Room for "RIPv" + uint8_t as %d */
627c478bd9Sstevel@tonic-gate char ripvers[4+3+1];
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate /* RIP header is 4 octets long */
657c478bd9Sstevel@tonic-gate if ((len = fraglen - 4) < 0)
667c478bd9Sstevel@tonic-gate return (0);
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate if (flags & F_SUM) {
697c478bd9Sstevel@tonic-gate switch (rip->rip_cmd) {
707c478bd9Sstevel@tonic-gate case RIPCMD_REQUEST: cmdstr = "C"; break;
717c478bd9Sstevel@tonic-gate case RIPCMD_RESPONSE: cmdstr = "R"; break;
727c478bd9Sstevel@tonic-gate case RIPCMD_TRACEON: cmdstr = "Traceon"; break;
737c478bd9Sstevel@tonic-gate case RIPCMD_TRACEOFF: cmdstr = "Traceoff"; break;
747c478bd9Sstevel@tonic-gate case RIPCMD_POLL: cmdstr = "Poll"; break;
757c478bd9Sstevel@tonic-gate case RIPCMD_POLLENTRY: cmdstr = "Poll entry"; break;
76*45916cd2Sjpk case RIPCMD_SEC_RESPONSE: cmdstr = "R - SEC"; break;
77*45916cd2Sjpk case RIPCMD_SEC_T_RESPONSE: cmdstr = "R - SEC_T"; break;
787c478bd9Sstevel@tonic-gate default: cmdstr = "?"; break;
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate if (rip->rip_vers == RIPv1)
827c478bd9Sstevel@tonic-gate (void) strlcpy(ripvers, "RIP", sizeof (ripvers));
837c478bd9Sstevel@tonic-gate else
847c478bd9Sstevel@tonic-gate (void) snprintf(ripvers, sizeof (ripvers), "RIPv%d",
857c478bd9Sstevel@tonic-gate rip->rip_vers);
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate switch (rip->rip_cmd) {
887c478bd9Sstevel@tonic-gate case RIPCMD_REQUEST:
897c478bd9Sstevel@tonic-gate case RIPCMD_RESPONSE:
907c478bd9Sstevel@tonic-gate case RIPCMD_POLL:
917c478bd9Sstevel@tonic-gate nip = rip->rip_nets;
927c478bd9Sstevel@tonic-gate auth = "";
937c478bd9Sstevel@tonic-gate if (len >= sizeof (*nip) &&
947c478bd9Sstevel@tonic-gate nip->n_family == RIP_AF_AUTH) {
957c478bd9Sstevel@tonic-gate nap = (struct netauth *)nip;
967c478bd9Sstevel@tonic-gate len -= sizeof (*nip);
977c478bd9Sstevel@tonic-gate if (nap->a_type == RIP_AUTH_MD5 &&
987c478bd9Sstevel@tonic-gate len >= ntohs(nap->au.a_md5.md5_auth_len))
997c478bd9Sstevel@tonic-gate len -= ntohs(nap->au.a_md5.
1007c478bd9Sstevel@tonic-gate md5_auth_len);
1017c478bd9Sstevel@tonic-gate auth = " +Auth";
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate count = len / sizeof (*nip);
1047c478bd9Sstevel@tonic-gate len %= sizeof (*nip);
1057c478bd9Sstevel@tonic-gate (void) snprintf(get_sum_line(), MAXLINE,
1067c478bd9Sstevel@tonic-gate "%s %s (%d destinations%s%s)", ripvers, cmdstr,
1077c478bd9Sstevel@tonic-gate count, (len != 0 ? "?" : ""), auth);
1087c478bd9Sstevel@tonic-gate break;
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate case RIPCMD_TRACEON:
1117c478bd9Sstevel@tonic-gate case RIPCMD_TRACEOFF:
1127c478bd9Sstevel@tonic-gate (void) snprintf(get_sum_line(), MAXLINE,
1137c478bd9Sstevel@tonic-gate "%s %s File=\"%.*s\"", ripvers, cmdstr, len,
1147c478bd9Sstevel@tonic-gate rip->rip_tracefile);
1157c478bd9Sstevel@tonic-gate len = 0;
1167c478bd9Sstevel@tonic-gate break;
1177c478bd9Sstevel@tonic-gate
118*45916cd2Sjpk case RIPCMD_SEC_RESPONSE:
119*45916cd2Sjpk case RIPCMD_SEC_T_RESPONSE:
120*45916cd2Sjpk if (len < sizeof (rip->rip_tsol.rip_generation))
121*45916cd2Sjpk break;
122*45916cd2Sjpk len -= sizeof (rip->rip_tsol.rip_generation);
123*45916cd2Sjpk count = 0;
124*45916cd2Sjpk rsep = rip->rip_tsol.rip_sec_entry;
125*45916cd2Sjpk while (len > 0) {
126*45916cd2Sjpk rsn = rip_next_sec_entry(rsep, len);
127*45916cd2Sjpk if (rsn == NULL)
128*45916cd2Sjpk break;
129*45916cd2Sjpk len -= (const char *)rsn - (const char *)rsep;
130*45916cd2Sjpk rsep = rsn;
131*45916cd2Sjpk count++;
132*45916cd2Sjpk }
133*45916cd2Sjpk (void) snprintf(get_sum_line(), MAXLINE,
134*45916cd2Sjpk "%s %s (%d destinations%s)", ripvers, cmdstr,
135*45916cd2Sjpk count, (len != 0 ? "?" : ""));
136*45916cd2Sjpk break;
137*45916cd2Sjpk
1387c478bd9Sstevel@tonic-gate default:
1397c478bd9Sstevel@tonic-gate (void) snprintf(get_sum_line(), MAXLINE,
1407c478bd9Sstevel@tonic-gate "%s %d (%s)", ripvers, rip->rip_cmd, cmdstr);
1417c478bd9Sstevel@tonic-gate len = 0;
1427c478bd9Sstevel@tonic-gate break;
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate if (flags & F_DTAIL) {
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate len = fraglen - 4;
1497c478bd9Sstevel@tonic-gate show_header("RIP: ", "Routing Information Protocol", fraglen);
1507c478bd9Sstevel@tonic-gate show_space();
151*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
152*45916cd2Sjpk "Opcode = %d (%s)", rip->rip_cmd,
153*45916cd2Sjpk show_cmd(rip->rip_cmd));
154*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
155*45916cd2Sjpk "Version = %d", rip->rip_vers);
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate switch (rip->rip_cmd) {
1587c478bd9Sstevel@tonic-gate case RIPCMD_REQUEST:
1597c478bd9Sstevel@tonic-gate case RIPCMD_RESPONSE:
1607c478bd9Sstevel@tonic-gate case RIPCMD_POLL:
1617c478bd9Sstevel@tonic-gate show_space();
1627c478bd9Sstevel@tonic-gate (void) snprintf(get_line(0, 0), get_line_remain(),
1637c478bd9Sstevel@tonic-gate "Destination Next Hop "
1647c478bd9Sstevel@tonic-gate "Tag Metric");
1657c478bd9Sstevel@tonic-gate for (nip = rip->rip_nets; len >= sizeof (*nip); nip++,
1667c478bd9Sstevel@tonic-gate len -= sizeof (*nip)) {
1677c478bd9Sstevel@tonic-gate if (nip->n_family == RIP_AF_AUTH) {
1687c478bd9Sstevel@tonic-gate nap = (const struct netauth *)nip;
1697c478bd9Sstevel@tonic-gate if (nap->a_type == RIP_AUTH_NONE) {
1707c478bd9Sstevel@tonic-gate (void) snprintf(get_line
1717c478bd9Sstevel@tonic-gate ((char *)nip - dlc_header,
1727c478bd9Sstevel@tonic-gate sizeof (*nip)),
1737c478bd9Sstevel@tonic-gate get_line_remain(),
1747c478bd9Sstevel@tonic-gate " *** Auth None");
1757c478bd9Sstevel@tonic-gate } else if (nap->a_type == RIP_AUTH_PW) {
1767c478bd9Sstevel@tonic-gate (void) snprintf(get_line
1777c478bd9Sstevel@tonic-gate ((char *)nip - dlc_header,
1787c478bd9Sstevel@tonic-gate sizeof (*nip)),
1797c478bd9Sstevel@tonic-gate get_line_remain(),
1807c478bd9Sstevel@tonic-gate " *** Auth PW \"%.*s\"",
1817c478bd9Sstevel@tonic-gate RIP_AUTH_PW_LEN,
1827c478bd9Sstevel@tonic-gate nap->au.au_pw);
1837c478bd9Sstevel@tonic-gate } else if (nap->a_type ==
1847c478bd9Sstevel@tonic-gate RIP_AUTH_MD5) {
185*45916cd2Sjpk (void) snprintf(get_line(0, 0),
1867c478bd9Sstevel@tonic-gate get_line_remain(),
1877c478bd9Sstevel@tonic-gate " *** Auth MD5 pkt len %d, "
1887c478bd9Sstevel@tonic-gate "keyid %d, sequence %08lX, "
1897c478bd9Sstevel@tonic-gate "authlen %d",
1907c478bd9Sstevel@tonic-gate ntohs(nap->au.a_md5.
1917c478bd9Sstevel@tonic-gate md5_pkt_len),
1927c478bd9Sstevel@tonic-gate nap->au.a_md5.md5_keyid,
193*45916cd2Sjpk (long)ntohl(nap->au.a_md5.
1947c478bd9Sstevel@tonic-gate md5_seqno),
1957c478bd9Sstevel@tonic-gate ntohs(nap->au.a_md5.
1967c478bd9Sstevel@tonic-gate md5_auth_len));
1977c478bd9Sstevel@tonic-gate if (len - sizeof (*nip) >=
1987c478bd9Sstevel@tonic-gate ntohs(nap->au.a_md5.
1997c478bd9Sstevel@tonic-gate md5_auth_len))
2007c478bd9Sstevel@tonic-gate len -= ntohs(nap->au.
2017c478bd9Sstevel@tonic-gate a_md5.md5_auth_len);
2027c478bd9Sstevel@tonic-gate else
2037c478bd9Sstevel@tonic-gate len = sizeof (*nip);
2047c478bd9Sstevel@tonic-gate } else {
2057c478bd9Sstevel@tonic-gate (void) snprintf(get_line
2067c478bd9Sstevel@tonic-gate ((char *)nip - dlc_header,
2077c478bd9Sstevel@tonic-gate sizeof (*nip)),
2087c478bd9Sstevel@tonic-gate get_line_remain(),
2097c478bd9Sstevel@tonic-gate " *** Auth Type %d?",
2107c478bd9Sstevel@tonic-gate ntohs(nap->a_type));
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate continue;
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate if (nip->n_family == RIP_AF_UNSPEC &&
2157c478bd9Sstevel@tonic-gate rip->rip_cmd == RIPCMD_REQUEST) {
216*45916cd2Sjpk (void) snprintf(get_line(0, 0),
2177c478bd9Sstevel@tonic-gate get_line_remain(),
2187c478bd9Sstevel@tonic-gate " *** All routes");
2197c478bd9Sstevel@tonic-gate continue;
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate if (nip->n_family != RIP_AF_INET) {
222*45916cd2Sjpk (void) snprintf(get_line(0, 0),
2237c478bd9Sstevel@tonic-gate get_line_remain(),
2247c478bd9Sstevel@tonic-gate " *** Address Family %d?",
2257c478bd9Sstevel@tonic-gate ntohs(nip->n_family));
2267c478bd9Sstevel@tonic-gate continue;
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate if (nip->n_dst == htonl(RIP_DEFAULT)) {
2297c478bd9Sstevel@tonic-gate (void) strcpy(addrstr, "default");
2307c478bd9Sstevel@tonic-gate } else {
2317c478bd9Sstevel@tonic-gate dst.s_addr = nip->n_dst;
2327c478bd9Sstevel@tonic-gate (void) strlcpy(addrstr, inet_ntoa(dst),
2337c478bd9Sstevel@tonic-gate sizeof (addrstr));
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate if (nip->n_dst != htonl(RIP_DEFAULT) &&
2367c478bd9Sstevel@tonic-gate rip->rip_vers >= RIPv2) {
2377c478bd9Sstevel@tonic-gate count = strlen(addrstr);
2387c478bd9Sstevel@tonic-gate mval = ntohl(nip->n_mask);
2397c478bd9Sstevel@tonic-gate /* LINTED */
2407c478bd9Sstevel@tonic-gate if (mval == INADDR_ANY) {
2417c478bd9Sstevel@tonic-gate /* No mask */;
2427c478bd9Sstevel@tonic-gate } else if ((mval + (mval & -mval)) ==
2437c478bd9Sstevel@tonic-gate 0) {
2447c478bd9Sstevel@tonic-gate (void) snprintf(addrstr + count,
2457c478bd9Sstevel@tonic-gate sizeof (addrstr) - count,
2467c478bd9Sstevel@tonic-gate "/%d", 33 - ffs(mval));
2477c478bd9Sstevel@tonic-gate } else {
2487c478bd9Sstevel@tonic-gate dst.s_addr = nip->n_mask;
2497c478bd9Sstevel@tonic-gate (void) snprintf(addrstr + count,
2507c478bd9Sstevel@tonic-gate sizeof (addrstr) - count,
2517c478bd9Sstevel@tonic-gate "/%s", inet_ntoa(dst));
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate dst.s_addr = nip->n_nhop;
2557c478bd9Sstevel@tonic-gate mval = ntohl(nip->n_metric);
256*45916cd2Sjpk (void) snprintf(get_line(0, 0),
2577c478bd9Sstevel@tonic-gate get_line_remain(),
2587c478bd9Sstevel@tonic-gate "%-31s %-15s %-6d %d%s",
2597c478bd9Sstevel@tonic-gate addrstr,
2607c478bd9Sstevel@tonic-gate dst.s_addr == htonl(INADDR_ANY) ?
2617c478bd9Sstevel@tonic-gate "--" : addrtoname(AF_INET, &dst),
2627c478bd9Sstevel@tonic-gate ntohs(nip->n_tag),
2637c478bd9Sstevel@tonic-gate mval,
2647c478bd9Sstevel@tonic-gate (mval == HOPCNT_INFINITY ?
2657c478bd9Sstevel@tonic-gate " (not reachable)" : ""));
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate break;
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate case RIPCMD_POLLENTRY:
2707c478bd9Sstevel@tonic-gate if (len < sizeof (*ep))
2717c478bd9Sstevel@tonic-gate break;
2727c478bd9Sstevel@tonic-gate len -= sizeof (*ep);
2737c478bd9Sstevel@tonic-gate ep = (const struct entryinfo *)rip->rip_nets;
2747c478bd9Sstevel@tonic-gate /* LINTED */
2757c478bd9Sstevel@tonic-gate sin = (const struct sockaddr_in *)&ep->rtu_dst;
276*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
2777c478bd9Sstevel@tonic-gate "Destination = %s %s",
2787c478bd9Sstevel@tonic-gate inet_ntoa(sin->sin_addr),
2797c478bd9Sstevel@tonic-gate addrtoname(AF_INET, (void *)&sin->sin_addr));
2807c478bd9Sstevel@tonic-gate /* LINTED */
2817c478bd9Sstevel@tonic-gate sin = (const struct sockaddr_in *)&ep->rtu_router;
282*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
2837c478bd9Sstevel@tonic-gate "Router = %s %s",
2847c478bd9Sstevel@tonic-gate inet_ntoa(sin->sin_addr),
2857c478bd9Sstevel@tonic-gate addrtoname(AF_INET, (void *)&sin->sin_addr));
286*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
2877c478bd9Sstevel@tonic-gate "Flags = %4x", (unsigned)ep->rtu_flags);
288*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
2897c478bd9Sstevel@tonic-gate "State = %d", ep->rtu_state);
290*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
2917c478bd9Sstevel@tonic-gate "Timer = %d", ep->rtu_timer);
292*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
2937c478bd9Sstevel@tonic-gate "Metric = %d", ep->rtu_metric);
294*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
2957c478bd9Sstevel@tonic-gate "Int flags = %8x", ep->int_flags);
296*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
2977c478bd9Sstevel@tonic-gate "Int name = \"%.*s\"", sizeof (ep->int_name),
2987c478bd9Sstevel@tonic-gate ep->int_name);
2997c478bd9Sstevel@tonic-gate break;
3007c478bd9Sstevel@tonic-gate
301*45916cd2Sjpk case RIPCMD_SEC_RESPONSE:
302*45916cd2Sjpk case RIPCMD_SEC_T_RESPONSE:
303*45916cd2Sjpk if (len < sizeof (rip->rip_tsol.rip_generation))
304*45916cd2Sjpk break;
305*45916cd2Sjpk len -= sizeof (rip->rip_tsol.rip_generation);
306*45916cd2Sjpk show_space();
307*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
308*45916cd2Sjpk "Generation = %u",
309*45916cd2Sjpk (unsigned)ntohl(rip->rip_tsol.rip_generation));
310*45916cd2Sjpk rsep = rip->rip_tsol.rip_sec_entry;
311*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
312*45916cd2Sjpk "Address E-METRIC");
313*45916cd2Sjpk rsep = rip->rip_tsol.rip_sec_entry;
314*45916cd2Sjpk while (len > 0) {
315*45916cd2Sjpk char *cp;
316*45916cd2Sjpk int blen, num;
317*45916cd2Sjpk
318*45916cd2Sjpk rsn = rip_next_sec_entry(rsep, len);
319*45916cd2Sjpk if (rsn == NULL)
320*45916cd2Sjpk break;
321*45916cd2Sjpk dst.s_addr = rsep->rip_dst;
322*45916cd2Sjpk cp = get_line(0, 0);
323*45916cd2Sjpk blen = get_line_remain();
324*45916cd2Sjpk (void) snprintf(cp, blen, "%-16s ",
325*45916cd2Sjpk inet_ntoa(dst));
326*45916cd2Sjpk cp += 17;
327*45916cd2Sjpk blen -= 17;
328*45916cd2Sjpk rep = rsep->rip_emetric;
329*45916cd2Sjpk for (count = ntohl(rsep->rip_count); count > 0;
330*45916cd2Sjpk count--) {
331*45916cd2Sjpk (void) snprintf(cp, blen, "metric=%d",
332*45916cd2Sjpk ntohs(rep->rip_metric));
333*45916cd2Sjpk blen -= strlen(cp);
334*45916cd2Sjpk cp += strlen(cp);
335*45916cd2Sjpk tokp = rep->rip_token;
336*45916cd2Sjpk num = get_numtokens(
337*45916cd2Sjpk ntohs(rep->rip_mask));
338*45916cd2Sjpk /* advance to the next emetric */
339*45916cd2Sjpk rep = (const struct rip_emetric *)
340*45916cd2Sjpk &rep->rip_token[num];
341*45916cd2Sjpk if (num > 0) {
342*45916cd2Sjpk (void) snprintf(cp, blen,
343*45916cd2Sjpk ",tokens=%lx",
344*45916cd2Sjpk (long)ntohl(*tokp));
345*45916cd2Sjpk tokp++;
346*45916cd2Sjpk num--;
347*45916cd2Sjpk } else {
348*45916cd2Sjpk (void) strlcpy(cp, ",no tokens",
349*45916cd2Sjpk blen);
350*45916cd2Sjpk }
351*45916cd2Sjpk while (num > 0) {
352*45916cd2Sjpk blen -= strlen(cp);
353*45916cd2Sjpk cp += strlen(cp);
354*45916cd2Sjpk (void) snprintf(cp, blen,
355*45916cd2Sjpk ",%lx",
356*45916cd2Sjpk (long)ntohl(*tokp));
357*45916cd2Sjpk tokp++;
358*45916cd2Sjpk num--;
359*45916cd2Sjpk }
360*45916cd2Sjpk blen -= strlen(cp);
361*45916cd2Sjpk cp += strlen(cp);
362*45916cd2Sjpk }
363*45916cd2Sjpk if (rsep->rip_count == 0) {
364*45916cd2Sjpk (void) strlcpy(cp,
365*45916cd2Sjpk "NULL (not reachable)", blen);
366*45916cd2Sjpk }
367*45916cd2Sjpk len -= (const char *)rsn - (const char *)rsep;
368*45916cd2Sjpk rsep = rsn;
369*45916cd2Sjpk }
370*45916cd2Sjpk break;
371*45916cd2Sjpk
3727c478bd9Sstevel@tonic-gate case RIPCMD_TRACEON:
3737c478bd9Sstevel@tonic-gate case RIPCMD_TRACEOFF:
374*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(),
3757c478bd9Sstevel@tonic-gate "Trace file = %.*s", len, rip->rip_tracefile);
3767c478bd9Sstevel@tonic-gate len = 0;
3777c478bd9Sstevel@tonic-gate break;
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate return (fraglen - len);
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate
384*45916cd2Sjpk static const char *
show_cmd(int c)3857c478bd9Sstevel@tonic-gate show_cmd(int c)
3867c478bd9Sstevel@tonic-gate {
3877c478bd9Sstevel@tonic-gate switch (c) {
3887c478bd9Sstevel@tonic-gate case RIPCMD_REQUEST:
3897c478bd9Sstevel@tonic-gate return ("route request");
3907c478bd9Sstevel@tonic-gate case RIPCMD_RESPONSE:
3917c478bd9Sstevel@tonic-gate return ("route response");
3927c478bd9Sstevel@tonic-gate case RIPCMD_TRACEON:
3937c478bd9Sstevel@tonic-gate return ("route trace on");
3947c478bd9Sstevel@tonic-gate case RIPCMD_TRACEOFF:
3957c478bd9Sstevel@tonic-gate return ("route trace off");
3967c478bd9Sstevel@tonic-gate case RIPCMD_POLL:
3977c478bd9Sstevel@tonic-gate return ("route poll");
3987c478bd9Sstevel@tonic-gate case RIPCMD_POLLENTRY:
3997c478bd9Sstevel@tonic-gate return ("route poll entry");
400*45916cd2Sjpk case RIPCMD_SEC_RESPONSE:
401*45916cd2Sjpk return ("route sec response");
402*45916cd2Sjpk case RIPCMD_SEC_T_RESPONSE:
403*45916cd2Sjpk return ("route sec_t response");
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate return ("?");
4067c478bd9Sstevel@tonic-gate }
407*45916cd2Sjpk
408*45916cd2Sjpk static int
get_numtokens(unsigned int mask)409*45916cd2Sjpk get_numtokens(unsigned int mask)
410*45916cd2Sjpk {
411*45916cd2Sjpk int num = 0;
412*45916cd2Sjpk
413*45916cd2Sjpk while (mask != 0) {
414*45916cd2Sjpk num++;
415*45916cd2Sjpk mask &= mask - 1;
416*45916cd2Sjpk }
417*45916cd2Sjpk return (num);
418*45916cd2Sjpk }
419*45916cd2Sjpk
420*45916cd2Sjpk static const struct rip_sec_entry *
rip_next_sec_entry(const struct rip_sec_entry * rsep,int len)421*45916cd2Sjpk rip_next_sec_entry(const struct rip_sec_entry *rsep, int len)
422*45916cd2Sjpk {
423*45916cd2Sjpk const struct rip_emetric *rep;
424*45916cd2Sjpk const char *limit = (const char *)rsep + len;
425*45916cd2Sjpk long count;
426*45916cd2Sjpk
427*45916cd2Sjpk if ((const char *)(rep = rsep->rip_emetric) > limit)
428*45916cd2Sjpk return (NULL);
429*45916cd2Sjpk count = ntohl(rsep->rip_count);
430*45916cd2Sjpk while (count > 0) {
431*45916cd2Sjpk if ((const char *)rep->rip_token > limit)
432*45916cd2Sjpk return (NULL);
433*45916cd2Sjpk rep = (struct rip_emetric *)
434*45916cd2Sjpk &rep->rip_token[get_numtokens(ntohs(rep->rip_mask))];
435*45916cd2Sjpk if ((const char *)rep > limit)
436*45916cd2Sjpk return (NULL);
437*45916cd2Sjpk count--;
438*45916cd2Sjpk }
439*45916cd2Sjpk return ((const struct rip_sec_entry *)rep);
440*45916cd2Sjpk }
441