xref: /titanic_51/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rip.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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