xref: /titanic_53/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rip.c (revision 45916cd2fec6e79bca5dee0421bd39e3c2910d1e)
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