1 /* $NetBSD: show.c,v 1.38 2008/09/10 01:06:58 dyoung Exp $ */
4 * Copyright (c) 1983, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "from: @(#)route.c 8.3 (Berkeley) 3/9/94";
37 __RCSID("$NetBSD: show.c,v 1.38 2008/09/10 01:06:58 dyoung Exp $");
41 #include <sys/param.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
47 #include <net/if_dl.h>
48 #include <net/if_types.h>
49 #include <net/route.h>
50 #include <netinet/in.h>
52 #include <sys/sysctl.h>
66 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
67 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
70 * Definitions for showing gateway flags.
76 static const struct bits bits
[] = {
82 { RTF_MODIFIED
, 'M' },
83 { RTF_DONE
, 'd' }, /* Completed -- for routing messages only */
84 { RTF_MASK
, 'm' }, /* Mask Present -- for routing messages only */
86 { RTF_XRESOLVE
, 'X' },
89 { RTF_BLACKHOLE
, 'B' },
96 static void pr_rthdr(int);
97 static void p_rtentry(struct rt_msghdr
*);
98 static void pr_family(int);
99 static void p_sockaddr(struct sockaddr
*, struct sockaddr
*, int, int );
100 static void p_flags(int);
103 parse_show_opts(int argc
, char * const *argv
, int *afp
, int *flagsp
,
104 const char **afnamep
, bool nolink
)
106 const char *afname
= "unspec";
111 for (; argc
>= 2; argc
--) {
112 if (*argv
[argc
- 1] != '-')
114 switch (keyword(argv
[argc
- 1] + 1)) {
123 afname
= argv
[argc
- 1] + 1;
128 afname
= argv
[argc
- 1] + 1;
134 afname
= argv
[argc
- 1] + 1;
139 afname
= argv
[argc
- 1] + 1;
146 afname
= argv
[argc
- 1] + 1;
158 usage(argv
[argc
- 1]);
167 * Print routing tables.
170 show(int argc
, char *const *argv
)
173 int af
, flags
, mib
[6];
174 char *buf
, *next
, *lim
;
175 struct rt_msghdr
*rtm
;
178 parse_show_opts(argc
, argv
, &af
, &flags
, NULL
, true);
183 mib
[4] = NET_RT_DUMP
;
185 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
186 err(EXIT_FAILURE
, "route-sysctl-estimate");
189 if ((buf
= malloc(needed
)) == 0)
190 err(EXIT_FAILURE
, "malloc");
191 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0)
192 err(EXIT_FAILURE
, "sysctl of routing table");
196 printf("Routing table%s\n", (af
== AF_UNSPEC
)? "s" : "");
199 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
) {
200 rtm
= (struct rt_msghdr
*)next
;
201 sa
= (struct sockaddr
*)(rtm
+ 1);
202 if ((rtm
->rtm_flags
& flags
) != flags
)
204 if (af
== AF_UNSPEC
|| af
== sa
->sa_family
)
212 /* column widths; each followed by one space */
214 #define WID_DST(af) 18 /* width of destination column */
215 #define WID_GW(af) 18 /* width of gateway column */
217 /* width of destination/gateway column */
219 /* strlen("fe80::aaaa:bbbb:cccc:dddd@gif0") == 30, strlen("/128") == 4 */
220 #define WID_DST(af) ((af) == AF_INET6 ? (nflag ? 34 : 18) : 18)
221 #define WID_GW(af) ((af) == AF_INET6 ? (nflag ? 30 : 18) : 18)
223 /* strlen("fe80::aaaa:bbbb:cccc:dddd") == 25, strlen("/128") == 4 */
224 #define WID_DST(af) ((af) == AF_INET6 ? (nflag ? 29 : 18) : 18)
225 #define WID_GW(af) ((af) == AF_INET6 ? (nflag ? 25 : 18) : 18)
230 * Print header for routing table columns.
236 printf("%-*.*s %-*.*s %-6.6s\n",
237 WID_DST(af
), WID_DST(af
), "Destination",
238 WID_GW(af
), WID_GW(af
), "Gateway",
244 * Print a routing table entry.
247 p_rtentry(struct rt_msghdr
*rtm
)
249 struct sockaddr
*sa
= (struct sockaddr
*)(rtm
+ 1);
251 static int masks_done
, banner_printed
;
254 int af
= 0, interesting
= RTF_UP
| RTF_GATEWAY
| RTF_HOST
|
255 RTF_REJECT
| RTF_LLINFO
;
258 /* for the moment, netmasks are skipped over */
259 if (!banner_printed
) {
260 printf("Netmasks:\n");
263 if (masks_done
== 0) {
264 if (rtm
->rtm_addrs
!= RTA_DST
) {
276 if (rtm
->rtm_addrs
== RTA_DST
)
277 p_sockaddr(sa
, NULL
, 0, WID_DST(af
) + 1 + WID_GW(af
) + 1);
281 if ((rtm
->rtm_addrs
& RTA_NETMASK
) == 0)
284 /* skip to gateway */
285 nm
= (struct sockaddr
*)
286 (ROUNDUP(sa
->sa_len
) + (char *)sa
);
287 /* skip over gateway to netmask */
288 nm
= (struct sockaddr
*)
289 (ROUNDUP(nm
->sa_len
) + (char *)nm
);
292 p_sockaddr(sa
, nm
, rtm
->rtm_flags
, WID_DST(af
));
293 sa
= (struct sockaddr
*)(ROUNDUP(sa
->sa_len
) + (char *)sa
);
294 p_sockaddr(sa
, NULL
, 0, WID_GW(af
));
296 p_flags(rtm
->rtm_flags
& interesting
);
302 * Print address family header before a section of the routing table.
315 afname
= "Internet6";
324 afname
= "AppleTalk";
331 printf("\n%s:\n", afname
);
333 printf("\nProtocol Family %d:\n", af
);
338 p_sockaddr(struct sockaddr
*sa
, struct sockaddr
*nm
, int flags
, int width
)
343 switch(sa
->sa_family
) {
346 if (getnameinfo(sa
, sa
->sa_len
, workbuf
, sizeof(workbuf
),
347 NULL
, 0, NI_NUMERICHOST
) != 0)
348 strlcpy(workbuf
, "invalid", sizeof(workbuf
));
353 cp
= routename(sa
, nm
, flags
);
358 cp
= routename(sa
, nm
, flags
);
359 /* make sure numeric address is not truncated */
360 if (strchr(cp
, ':') != NULL
&& (int)strlen(cp
) > width
)
370 u_char
*s
= (u_char
*)sa
->sa_data
, *slim
;
371 char *wp
= workbuf
, *wplim
;
373 slim
= sa
->sa_len
+ (u_char
*)sa
;
374 wplim
= wp
+ sizeof(workbuf
) - 6;
375 wp
+= snprintf(wp
, wplim
- wp
, "(%d)", sa
->sa_family
);
376 while (s
< slim
&& wp
< wplim
) {
377 wp
+= snprintf(wp
, wplim
- wp
, " %02x", *s
++);
379 wp
+= snprintf(wp
, wplim
- wp
, "%02x", *s
++);
388 printf("%-*s ", width
, cp
);
390 printf("%-*.*s ", width
, width
, cp
);
397 char name
[33], *flags
;
398 const struct bits
*p
= bits
;
400 for (flags
= name
; p
->b_mask
; p
++)
406 printf("%-6.6s ", name
);