2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright 2019 Conrad Meyer <cem@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include "opt_inet6.h"
33 #include <sys/ctype.h>
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/malloc.h>
38 #include <sys/socket.h>
39 #include <sys/sysctl.h>
40 #include <sys/syslog.h>
41 #include <sys/kernel.h>
43 #include <sys/rmlock.h>
46 #include <ddb/db_lex.h>
49 #include <net/if_var.h>
50 #include <net/if_dl.h>
51 #include <net/route.h>
52 #include <net/route/nhop.h>
53 #include <net/route/route_ctl.h>
54 #include <net/route/route_var.h>
57 * Unfortunately, RTF_ values are expressed as raw masks rather than powers of
58 * 2, so we cannot use them as nice C99 initializer indices below.
60 static const char * const rtf_flag_strings[] = {
88 [31] = "GWFLAG_COMPAT",
91 static const char * __pure
92 rt_flag_name(unsigned idx)
94 if (idx >= nitems(rtf_flag_strings))
95 return ("INVALID_FLAG");
96 if (rtf_flag_strings[idx] == NULL)
98 return (rtf_flag_strings[idx]);
102 rt_dumpaddr_ddb(const char *name, const struct sockaddr *sa)
104 char buf[INET6_ADDRSTRLEN], *res;
109 else if (sa->sa_family == AF_INET) {
110 res = inet_ntop(AF_INET,
111 &((const struct sockaddr_in *)sa)->sin_addr,
113 } else if (sa->sa_family == AF_INET6) {
114 res = inet_ntop(AF_INET6,
115 &((const struct sockaddr_in6 *)sa)->sin6_addr,
117 } else if (sa->sa_family == AF_LINK) {
122 db_printf("%s <%s> ", name, res);
126 db_printf("%s <af:%d> ", name, sa->sa_family);
130 rt_dumpentry_ddb(struct radix_node *rn, void *arg __unused)
132 struct sockaddr_storage ss;
134 struct nhop_object *nh;
137 /* If RNTORT is important, put it in a header. */
139 nh = (struct nhop_object *)rt->rt_nhop;
141 rt_dumpaddr_ddb("dst", rt_key(rt));
142 rt_dumpaddr_ddb("gateway", &rt->rt_nhop->gw_sa);
143 rt_dumpaddr_ddb("netmask", rtsock_fix_netmask(rt_key(rt), rt_mask(rt),
145 if ((nh->nh_ifp->if_flags & IFF_DYING) == 0) {
146 rt_dumpaddr_ddb("ifp", nh->nh_ifp->if_addr->ifa_addr);
147 rt_dumpaddr_ddb("ifa", nh->nh_ifa->ifa_addr);
151 flags = rt->rte_flags | nhop_get_rtflags(nh);
155 while ((idx = ffs(flags)) > 0) {
158 db_printf("%s", rt_flag_name(idx));
159 flags &= ~(1ul << idx);
168 DB_SHOW_COMMAND(routetable, db_show_routetable_cmd)
170 struct rib_head *rnh;
180 for (; i <= lim; i++) {
181 rnh = rt_tables_get_rnh(0, i);
184 db_printf("%s: AF %d not supported?\n",
191 if (!have_addr && i > 1)
194 db_printf("Route table for AF %d%s%s%s:\n", i,
195 (i == AF_INET || i == AF_INET6) ? " (" : "",
196 (i == AF_INET) ? "INET" : (i == AF_INET6) ? "INET6" : "",
197 (i == AF_INET || i == AF_INET6) ? ")" : "");
199 error = rnh->rnh_walktree(&rnh->head, rt_dumpentry_ddb, NULL);
201 db_printf("%s: walktree(%d): %d\n", __func__, i,
206 _DB_FUNC(_show, route, db_show_route_cmd, db_show_table, CS_OWN, NULL)
208 char abuf[INET6_ADDRSTRLEN], *buf, *end;
210 struct radix_node *rn;
214 struct sockaddr_in dest_sin;
215 struct sockaddr_in6 dest_sin6;
221 /* Remove whitespaces from both ends */
222 end = buf + strlen(buf) - 1;
223 for (; (end >= buf) && (*end=='\n' || isspace(*end)); end--)
225 while (isspace(*buf))
229 if (strchr(buf, ':') != NULL) {
231 u.dest_sin6.sin6_family = af;
232 u.dest_sin6.sin6_len = sizeof(struct sockaddr_in6);
233 dst_addrp = &u.dest_sin6.sin6_addr;
236 u.dest_sin.sin_family = af;
237 u.dest_sin.sin_len = sizeof(struct sockaddr_in);
238 dst_addrp = &u.dest_sin.sin_addr;
241 if (inet_pton(af, buf, dst_addrp) != 1)
244 if (inet_ntop(af, dst_addrp, abuf, sizeof(abuf)) != NULL)
245 db_printf("Looking up route to destination '%s'\n", abuf);
250 rh = rt_tables_get_rnh(RT_DEFAULT_FIB, af);
252 rn = rh->rnh_matchaddr(&u, &rh->head);
253 if (rn && ((rn->rn_flags & RNF_ROOT) == 0))
254 rt = (struct rtentry *)rn;
259 db_printf("Could not get route for that server.\n");
263 rt_dumpentry_ddb((void *)rt, NULL);
267 db_printf("Usage: 'show route <address>'\n"
268 " Currently accepts only IPv4 and IPv6 addresses\n");