4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #define RIPVERSION RIPv2
37 #include <protocols/routed.h>
40 static const char *show_cmd(int);
41 static int get_numtokens(unsigned int);
44 interpret_rip(int flags
, struct rip
*rip
, int fraglen
)
46 const struct netinfo
*nip
;
47 const struct entryinfo
*ep
;
48 const struct netauth
*nap
;
49 const struct rip_emetric
*rep
;
52 const char *cmdstr
, *auth
;
55 const struct sockaddr_in
*sin
;
56 /* Room for IP destination + "/" + IP mask */
57 char addrstr
[15+1+15+1];
58 /* Room for "RIPv" + uint8_t as %d */
61 /* RIP header is 4 octets long */
62 if ((len
= fraglen
- 4) < 0)
66 switch (rip
->rip_cmd
) {
67 case RIPCMD_REQUEST
: cmdstr
= "C"; break;
68 case RIPCMD_RESPONSE
: cmdstr
= "R"; break;
69 case RIPCMD_TRACEON
: cmdstr
= "Traceon"; break;
70 case RIPCMD_TRACEOFF
: cmdstr
= "Traceoff"; break;
71 case RIPCMD_POLL
: cmdstr
= "Poll"; break;
72 case RIPCMD_POLLENTRY
: cmdstr
= "Poll entry"; break;
73 default: cmdstr
= "?"; break;
76 if (rip
->rip_vers
== RIPv1
)
77 (void) strlcpy(ripvers
, "RIP", sizeof (ripvers
));
79 (void) snprintf(ripvers
, sizeof (ripvers
), "RIPv%d",
82 switch (rip
->rip_cmd
) {
88 if (len
>= sizeof (*nip
) &&
89 nip
->n_family
== RIP_AF_AUTH
) {
90 nap
= (struct netauth
*)nip
;
92 if (nap
->a_type
== RIP_AUTH_MD5
&&
93 len
>= ntohs(nap
->au
.a_md5
.md5_auth_len
))
94 len
-= ntohs(nap
->au
.a_md5
.
98 count
= len
/ sizeof (*nip
);
100 (void) snprintf(get_sum_line(), MAXLINE
,
101 "%s %s (%d destinations%s%s)", ripvers
, cmdstr
,
102 count
, (len
!= 0 ? "?" : ""), auth
);
106 case RIPCMD_TRACEOFF
:
107 (void) snprintf(get_sum_line(), MAXLINE
,
108 "%s %s File=\"%.*s\"", ripvers
, cmdstr
, len
,
114 (void) snprintf(get_sum_line(), MAXLINE
,
115 "%s %d (%s)", ripvers
, rip
->rip_cmd
, cmdstr
);
121 if (flags
& F_DTAIL
) {
124 show_header("RIP: ", "Routing Information Protocol", fraglen
);
126 (void) snprintf(get_line(0, 0), get_line_remain(),
127 "Opcode = %d (%s)", rip
->rip_cmd
,
128 show_cmd(rip
->rip_cmd
));
129 (void) snprintf(get_line(0, 0), get_line_remain(),
130 "Version = %d", rip
->rip_vers
);
132 switch (rip
->rip_cmd
) {
134 case RIPCMD_RESPONSE
:
137 (void) snprintf(get_line(0, 0), get_line_remain(),
138 "Destination Next Hop "
140 for (nip
= rip
->rip_nets
; len
>= sizeof (*nip
); nip
++,
141 len
-= sizeof (*nip
)) {
142 if (nip
->n_family
== RIP_AF_AUTH
) {
143 nap
= (const struct netauth
*)nip
;
144 if (nap
->a_type
== RIP_AUTH_NONE
) {
145 (void) snprintf(get_line
146 ((char *)nip
- dlc_header
,
150 } else if (nap
->a_type
== RIP_AUTH_PW
) {
151 (void) snprintf(get_line
152 ((char *)nip
- dlc_header
,
155 " *** Auth PW \"%.*s\"",
158 } else if (nap
->a_type
==
160 (void) snprintf(get_line(0, 0),
162 " *** Auth MD5 pkt len %d, "
163 "keyid %d, sequence %08lX, "
167 nap
->au
.a_md5
.md5_keyid
,
168 (long)ntohl(nap
->au
.a_md5
.
172 if (len
- sizeof (*nip
) >=
175 len
-= ntohs(nap
->au
.
180 (void) snprintf(get_line
181 ((char *)nip
- dlc_header
,
184 " *** Auth Type %d?",
189 if (nip
->n_family
== RIP_AF_UNSPEC
&&
190 rip
->rip_cmd
== RIPCMD_REQUEST
) {
191 (void) snprintf(get_line(0, 0),
196 if (nip
->n_family
!= RIP_AF_INET
) {
197 (void) snprintf(get_line(0, 0),
199 " *** Address Family %d?",
200 ntohs(nip
->n_family
));
203 if (nip
->n_dst
== htonl(RIP_DEFAULT
)) {
204 (void) strcpy(addrstr
, "default");
206 dst
.s_addr
= nip
->n_dst
;
207 (void) strlcpy(addrstr
, inet_ntoa(dst
),
210 if (nip
->n_dst
!= htonl(RIP_DEFAULT
) &&
211 rip
->rip_vers
>= RIPv2
) {
212 count
= strlen(addrstr
);
213 mval
= ntohl(nip
->n_mask
);
215 if (mval
== INADDR_ANY
) {
217 } else if ((mval
+ (mval
& -mval
)) ==
219 (void) snprintf(addrstr
+ count
,
220 sizeof (addrstr
) - count
,
221 "/%d", 33 - ffs(mval
));
223 dst
.s_addr
= nip
->n_mask
;
224 (void) snprintf(addrstr
+ count
,
225 sizeof (addrstr
) - count
,
226 "/%s", inet_ntoa(dst
));
229 dst
.s_addr
= nip
->n_nhop
;
230 mval
= ntohl(nip
->n_metric
);
231 (void) snprintf(get_line(0, 0),
233 "%-31s %-15s %-6d %d%s",
235 dst
.s_addr
== htonl(INADDR_ANY
) ?
236 "--" : addrtoname(AF_INET
, &dst
),
239 (mval
== HOPCNT_INFINITY
?
240 " (not reachable)" : ""));
244 case RIPCMD_POLLENTRY
:
245 if (len
< sizeof (*ep
))
248 ep
= (const struct entryinfo
*)rip
->rip_nets
;
250 sin
= (const struct sockaddr_in
*)&ep
->rtu_dst
;
251 (void) snprintf(get_line(0, 0), get_line_remain(),
252 "Destination = %s %s",
253 inet_ntoa(sin
->sin_addr
),
254 addrtoname(AF_INET
, (void *)&sin
->sin_addr
));
256 sin
= (const struct sockaddr_in
*)&ep
->rtu_router
;
257 (void) snprintf(get_line(0, 0), get_line_remain(),
259 inet_ntoa(sin
->sin_addr
),
260 addrtoname(AF_INET
, (void *)&sin
->sin_addr
));
261 (void) snprintf(get_line(0, 0), get_line_remain(),
262 "Flags = %4x", (unsigned)ep
->rtu_flags
);
263 (void) snprintf(get_line(0, 0), get_line_remain(),
264 "State = %d", ep
->rtu_state
);
265 (void) snprintf(get_line(0, 0), get_line_remain(),
266 "Timer = %d", ep
->rtu_timer
);
267 (void) snprintf(get_line(0, 0), get_line_remain(),
268 "Metric = %d", ep
->rtu_metric
);
269 (void) snprintf(get_line(0, 0), get_line_remain(),
270 "Int flags = %8x", ep
->int_flags
);
271 (void) snprintf(get_line(0, 0), get_line_remain(),
272 "Int name = \"%.*s\"", sizeof (ep
->int_name
),
277 case RIPCMD_TRACEOFF
:
278 (void) snprintf(get_line(0, 0), get_line_remain(),
279 "Trace file = %.*s", len
, rip
->rip_tracefile
);
285 return (fraglen
- len
);
293 return ("route request");
294 case RIPCMD_RESPONSE
:
295 return ("route response");
297 return ("route trace on");
298 case RIPCMD_TRACEOFF
:
299 return ("route trace off");
301 return ("route poll");
302 case RIPCMD_POLLENTRY
:
303 return ("route poll entry");
309 get_numtokens(unsigned int mask
)