1 /* $NetBSD: show.c,v 1.7 2009/04/12 16:08:37 lukem Exp $ */
2 /* $OpenBSD: show.c,v 1.1 2006/05/27 19:16:37 claudio Exp $ */
5 * Copyright (c) 1983, 1988, 1993
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/param.h>
34 #include <sys/protosw.h>
35 #include <sys/socket.h>
37 #include <sys/sysctl.h>
40 #include <net/if_dl.h>
41 #include <net/if_types.h>
42 #include <net/pfvar.h>
43 #include <net/pfkeyv2.h>
44 #include <net/route.h>
45 #include <netinet/in.h>
46 #include <netinet/if_ether.h>
47 #include <arpa/inet.h>
60 char *any_ntoa(const struct sockaddr
*);
61 char *link_print(struct sockaddr
*);
64 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
65 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
67 #define PFKEYV2_CHUNK sizeof(u_int64_t)
70 * Definitions for showing gateway flags.
76 static const struct bits bits
[] = {
81 { RTF_BLACKHOLE
, 'B' },
83 { RTF_MODIFIED
, 'M' },
84 { RTF_DONE
, 'd' }, /* Completed -- for routing messages only */
85 { RTF_MASK
, 'm' }, /* Mask Present -- for routing messages only */
87 { RTF_XRESOLVE
, 'X' },
92 /* { RTF_PROTO3, '3' }, */
94 /* { RTF_JUMBO, 'J' }, */
98 void pr_rthdr(int, int);
99 void p_rtentry(struct rt_msghdr
*);
101 void p_sockaddr(struct sockaddr
*, struct sockaddr
*, int, int);
102 char *routename4(in_addr_t
);
103 char *routename6(struct sockaddr_in6
*);
106 * Print routing tables.
111 struct rt_msghdr
*rtm
;
112 char *buf
= NULL
, *next
, *lim
= NULL
;
121 mib
[4] = NET_RT_DUMP
;
123 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
124 err(1, "route-sysctl-estimate");
126 if ((buf
= malloc(needed
)) == 0)
128 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0)
129 err(1, "sysctl of routing table");
133 printf("Routing tables\n");
136 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
) {
137 rtm
= (struct rt_msghdr
*)next
;
138 sa
= (struct sockaddr
*)(rtm
+ 1);
139 if (paf
!= AF_UNSPEC
&& sa
->sa_family
!= paf
)
147 if (paf
!= 0 && paf
!= PF_KEY
)
154 mib
[3] = NET_KEY_SPD_DUMP
;
157 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) == -1) {
158 if (errno
== ENOPROTOOPT
)
160 err(1, "spd-sysctl-estimate");
163 if ((buf
= malloc(needed
)) == 0)
165 if (sysctl(mib
, 4, buf
, &needed
, NULL
, 0) == -1)
166 err(1,"sysctl of spd");
171 printf("\nEncap:\n");
173 for (next
= buf
; next
< lim
; next
+= msg
->sadb_msg_len
*
175 msg
= (struct sadb_msg
*)next
;
176 if (msg
->sadb_msg_len
== 0)
187 * column widths; each followed by one space
188 * width of destination/gateway column
189 * strlen("fe80::aaaa:bbbb:cccc:dddd@gif0") == 30, strlen("/128") == 4
191 #define WID_DST(af) ((af) == AF_INET6 ? (nflag ? 34 : 18) : 18)
192 #define WID_GW(af) ((af) == AF_INET6 ? (nflag ? 30 : 18) : 18)
195 * Print header for routing table columns.
198 pr_rthdr(int paf
, int pAflag
)
201 printf("%-*.*s ", PLEN
, PLEN
, "Address");
203 printf("%-*.*s %-*.*s %-6.6s %6.6s %8.8s %6.6s %s\n",
204 WID_DST(paf
), WID_DST(paf
), "Destination",
205 WID_GW(paf
), WID_GW(paf
), "Gateway",
206 "Flags", "Refs", "Use", "Mtu", "Interface");
208 printf("%-18s %-5s %-18s %-5s %-5s %-22s\n",
209 "Source", "Port", "Destination",
210 "Port", "Proto", "SA(Address/Proto/Type/Direction)");
214 get_rtaddrs(int addrs
, struct sockaddr
*sa
, struct sockaddr
**rti_info
)
218 for (i
= 0; i
< RTAX_MAX
; i
++) {
219 if (addrs
& (1 << i
)) {
221 sa
= (struct sockaddr
*)((char *)(sa
) +
222 ROUNDUP(sa
->sa_len
));
229 * Print a routing table entry.
232 p_rtentry(struct rt_msghdr
*rtm
)
234 static int old_af
= -1;
235 struct sockaddr
*sa
= (struct sockaddr
*)(rtm
+ 1);
236 struct sockaddr
*mask
, *rti_info
[RTAX_MAX
];
237 char ifbuf
[IF_NAMESIZE
];
240 if (old_af
!= sa
->sa_family
) {
241 old_af
= sa
->sa_family
;
242 pr_family(sa
->sa_family
);
243 pr_rthdr(sa
->sa_family
, 0);
245 get_rtaddrs(rtm
->rtm_addrs
, sa
, rti_info
);
247 mask
= rti_info
[RTAX_NETMASK
];
248 if ((sa
= rti_info
[RTAX_DST
]) == NULL
)
251 p_sockaddr(sa
, mask
, rtm
->rtm_flags
, WID_DST(sa
->sa_family
));
252 p_sockaddr(rti_info
[RTAX_GATEWAY
], NULL
, RTF_HOST
,
253 WID_GW(sa
->sa_family
));
254 p_flags(rtm
->rtm_flags
, "%-6.6s ");
256 printf("%6d %8ld ", (int)rtm
->rtm_rmx
.rmx_refcnt
,
257 rtm
->rtm_rmx
.rmx_pksent
);
259 printf("%6s %8s ", "-", "-");
261 if (rtm
->rtm_rmx
.rmx_mtu
)
262 printf("%6ld", rtm
->rtm_rmx
.rmx_mtu
);
265 putchar((rtm
->rtm_rmx
.rmx_locks
& RTV_MTU
) ? 'L' : ' ');
266 printf(" %.16s", if_indextoname(rtm
->rtm_index
, ifbuf
));
271 * Print address family header before a section of the routing table.
283 afname
= "Internet6";
289 afname
= "AppleTalk";
296 printf("\n%s:\n", afname
);
298 printf("\nProtocol Family %d:\n", paf
);
302 p_addr(struct sockaddr
*sa
, struct sockaddr
*mask
, int flags
)
304 p_sockaddr(sa
, mask
, flags
, WID_DST(sa
->sa_family
));
308 p_gwaddr(struct sockaddr
*sa
, int gwaf
)
310 p_sockaddr(sa
, 0, RTF_HOST
, WID_GW(gwaf
));
314 p_sockaddr(struct sockaddr
*sa
, struct sockaddr
*mask
, int flags
, int width
)
318 switch (sa
->sa_family
) {
321 struct sockaddr_in6
*sa6
= (struct sockaddr_in6
*)sa
;
322 struct in6_addr
*in6
= &sa6
->sin6_addr
;
325 * XXX: This is a special workaround for KAME kernels.
326 * sin6_scope_id field of SA should be set in the future.
328 if (IN6_IS_ADDR_LINKLOCAL(in6
) ||
329 IN6_IS_ADDR_MC_LINKLOCAL(in6
)) {
330 /* XXX: override is ok? */
331 sa6
->sin6_scope_id
= (u_int32_t
)ntohs(*(u_short
*)
333 *(u_short
*)&in6
->s6_addr
[2] = 0;
335 if (flags
& RTF_HOST
)
336 cp
= routename((struct sockaddr
*)sa6
);
338 cp
= netname((struct sockaddr
*)sa6
, mask
);
342 if ((flags
& RTF_HOST
) || mask
== NULL
)
345 cp
= netname(sa
, mask
);
352 printf("%-*s ", width
, cp
);
354 printf("%-*.*s ", width
, width
, cp
);
359 p_flags(int f
, const char *format
)
361 char name
[33], *flags
;
362 const struct bits
*p
= bits
;
364 for (flags
= name
; p
->b_mask
&& flags
< &name
[sizeof(name
) - 2]; p
++)
368 printf(format
, name
);
371 static char line
[MAXHOSTNAMELEN
];
372 static char domain
[MAXHOSTNAMELEN
];
375 routename(struct sockaddr
*sa
)
378 static int first
= 1;
382 if (gethostname(domain
, sizeof(domain
)) == 0 &&
383 (cp
= strchr(domain
, '.')))
384 (void)strlcpy(domain
, cp
+ 1, sizeof(domain
));
390 if (sa
->sa_len
== 0) {
391 (void)strlcpy(line
, "default", sizeof(line
));
395 switch (sa
->sa_family
) {
398 (routename4(((struct sockaddr_in
*)sa
)->sin_addr
.s_addr
));
402 struct sockaddr_in6 sin6
;
404 memset(&sin6
, 0, sizeof(sin6
));
405 memcpy(&sin6
, sa
, sa
->sa_len
);
406 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
407 sin6
.sin6_family
= AF_INET6
;
408 if (sa
->sa_len
== sizeof(struct sockaddr_in6
) &&
409 (IN6_IS_ADDR_LINKLOCAL(&sin6
.sin6_addr
) ||
410 IN6_IS_ADDR_MC_LINKLOCAL(&sin6
.sin6_addr
)) &&
411 sin6
.sin6_scope_id
== 0) {
413 ntohs(*(u_int16_t
*)&sin6
.sin6_addr
.s6_addr
[2]);
414 sin6
.sin6_addr
.s6_addr
[2] = 0;
415 sin6
.sin6_addr
.s6_addr
[3] = 0;
417 return (routename6(&sin6
));
421 return (link_print(sa
));
425 if (sa
->sa_len
== sizeof(struct sockaddr_rtlabel
)) {
426 static char name
[RTLABEL_LEN
];
427 struct sockaddr_rtlabel
*sr
;
429 sr
= (struct sockaddr_rtlabel
*)sa
;
430 strlcpy(name
, sr
->sr_label
, sizeof(name
));
436 (void)snprintf(line
, sizeof(line
), "(%d) %s",
437 sa
->sa_family
, any_ntoa(sa
));
444 routename4(in_addr_t in
)
446 const char *cp
= NULL
;
450 if (in
== INADDR_ANY
)
453 if ((hp
= gethostbyaddr((char *)&in
,
454 sizeof(in
), AF_INET
)) != NULL
) {
456 if ((p
= strchr(hp
->h_name
, '.')) &&
457 !strcmp(p
+ 1, domain
))
463 strlcpy(line
, cp
? cp
: inet_ntoa(ina
), sizeof(line
));
469 routename6(struct sockaddr_in6
*sin6
)
474 niflags
|= NI_NUMERICHOST
;
476 niflags
|= NI_NOFQDN
;
478 if (getnameinfo((struct sockaddr
*)sin6
, sin6
->sin6_len
,
479 line
, sizeof(line
), NULL
, 0, niflags
) != 0)
480 strncpy(line
, "invalid", sizeof(line
));
486 * Return the name of the network whose address is given.
487 * The address is assumed to be that of a net or subnet, not a host.
490 netname4(in_addr_t in
, in_addr_t mask
)
492 const char *cp
= NULL
;
493 struct netent
*np
= NULL
;
498 if (!nflag
&& in
!= INADDR_ANY
) {
499 if ((np
= getnetbyaddr(in
, AF_INET
)) != NULL
)
502 mbits
= mask
? 33 - ffs(mask
) : 0;
503 if (in
== INADDR_ANY
&& !mbits
)
506 strlcpy(line
, cp
, sizeof(line
));
507 #define C(x) ((x) & 0xff)
509 snprintf(line
, sizeof(line
), "%u/%d", C(in
>> 24), mbits
);
511 snprintf(line
, sizeof(line
), "%u.%u/%d",
512 C(in
>> 24) , C(in
>> 16), mbits
);
514 snprintf(line
, sizeof(line
), "%u.%u.%u/%d",
515 C(in
>> 24), C(in
>> 16), C(in
>> 8), mbits
);
517 snprintf(line
, sizeof(line
), "%u.%u.%u.%u/%d", C(in
>> 24),
518 C(in
>> 16), C(in
>> 8), C(in
), mbits
);
525 netname6(struct sockaddr_in6
*sa6
, struct sockaddr_in6
*mask
)
527 struct sockaddr_in6 sin6
;
529 int masklen
, final
= 0, illegal
= 0;
530 int i
, lim
, flag
, error
;
531 char hbuf
[NI_MAXHOST
];
538 lim
= mask
->sin6_len
- offsetof(struct sockaddr_in6
, sin6_addr
);
541 else if (lim
> (int)sizeof(struct in6_addr
))
542 lim
= sizeof(struct in6_addr
);
543 for (p
= (u_char
*)&mask
->sin6_addr
, i
= 0; i
< lim
; p
++) {
546 sin6
.sin6_addr
.s6_addr
[i
++] = 0x00;
592 sin6
.sin6_addr
.s6_addr
[i
++] &= *p
;
594 sin6
.sin6_addr
.s6_addr
[i
++] = 0x00;
596 while (i
< (int)sizeof(struct in6_addr
))
597 sin6
.sin6_addr
.s6_addr
[i
++] = 0x00;
601 if (masklen
== 0 && IN6_IS_ADDR_UNSPECIFIED(&sin6
.sin6_addr
)) {
602 snprintf(line
, sizeof(line
), "default");
607 warnx("illegal prefixlen");
610 flag
|= NI_NUMERICHOST
;
611 error
= getnameinfo((struct sockaddr
*)&sin6
, sin6
.sin6_len
,
612 hbuf
, sizeof(hbuf
), NULL
, 0, flag
);
614 snprintf(hbuf
, sizeof(hbuf
), "invalid");
616 snprintf(line
, sizeof(line
), "%s/%d", hbuf
, masklen
);
622 * Return the name of the network whose address is given.
623 * The address is assumed to be that of a net or subnet, not a host.
626 netname(struct sockaddr
*sa
, struct sockaddr
*mask
)
628 switch (sa
->sa_family
) {
631 return netname4(((struct sockaddr_in
*)sa
)->sin_addr
.s_addr
,
632 ((struct sockaddr_in
*)mask
)->sin_addr
.s_addr
);
635 return netname6((struct sockaddr_in6
*)sa
,
636 (struct sockaddr_in6
*)mask
);
639 return (link_print(sa
));
641 snprintf(line
, sizeof(line
), "af %d: %s",
642 sa
->sa_family
, any_ntoa(sa
));
648 static const char hexlist
[] = "0123456789abcdef";
651 any_ntoa(const struct sockaddr
*sa
)
653 static char obuf
[240];
654 const char *in
= sa
->sa_data
;
656 int len
= sa
->sa_len
- offsetof(struct sockaddr
, sa_data
);
660 *out
++ = hexlist
[(*in
>> 4) & 15];
661 *out
++ = hexlist
[(*in
++) & 15];
663 } while (--len
> 0 && (out
+ 3) < &obuf
[sizeof(obuf
) - 1]);
669 link_print(struct sockaddr
*sa
)
671 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)sa
;
672 u_char
*lla
= (u_char
*)sdl
->sdl_data
+ sdl
->sdl_nlen
;
674 if (sdl
->sdl_nlen
== 0 && sdl
->sdl_alen
== 0 &&
675 sdl
->sdl_slen
== 0) {
676 (void)snprintf(line
, sizeof(line
), "link#%d", sdl
->sdl_index
);
679 switch (sdl
->sdl_type
) {
682 return (ether_ntoa((struct ether_addr
*)lla
));
684 return (link_ntoa(sdl
));