Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148767630
D24561.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
23 KB
Referenced Files
None
Subscribers
None
D24561.diff
View Options
Index: head/sys/conf/files
===================================================================
--- head/sys/conf/files
+++ head/sys/conf/files
@@ -4095,6 +4095,7 @@
net/route/nhop_ctl.c standard
net/route/nhop_utils.c standard
net/route/route_ctl.c standard
+net/route/route_ddb.c optional ddb
net/route/route_helpers.c standard
net/route/route_temporal.c standard
net/rss_config.c optional inet rss | inet6 rss
Index: head/sys/net/route.h
===================================================================
--- head/sys/net/route.h
+++ head/sys/net/route.h
@@ -388,6 +388,8 @@
int rtsock_routemsg(int, struct rtentry *, struct ifnet *ifp, int, int);
int rtsock_routemsg_info(int, struct rt_addrinfo *, int);
+struct sockaddr *rtsock_fix_netmask(const struct sockaddr *dst,
+ const struct sockaddr *smask, struct sockaddr_storage *dmask);
/*
* Note the following locking behavior:
*
Index: head/sys/net/route/route_ddb.c
===================================================================
--- head/sys/net/route/route_ddb.c
+++ head/sys/net/route/route_ddb.c
@@ -0,0 +1,458 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2019 Conrad Meyer <cem@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/syslog.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/rmlock.h>
+
+#include <ddb/ddb.h>
+#include <ddb/db_lex.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_dl.h>
+#include <net/vnet.h>
+#include <net/route.h>
+#include <net/route/route_var.h>
+#include <net/route/nhop.h>
+#include <netinet/in.h>
+
+/*
+ * Unfortunately, RTF_ values are expressed as raw masks rather than powers of
+ * 2, so we cannot use them as nice C99 initializer indices below.
+ */
+static const char * const rtf_flag_strings[] = {
+ "UP",
+ "GATEWAY",
+ "HOST",
+ "REJECT",
+ "DYNAMIC",
+ "MODIFIED",
+ "DONE",
+ "UNUSED_0x80",
+ "UNUSED_0x100",
+ "XRESOLVE",
+ "LLDATA",
+ "STATIC",
+ "BLACKHOLE",
+ "UNUSED_0x2000",
+ "PROTO2",
+ "PROTO1",
+ "UNUSED_0x10000",
+ "UNUSED_0x20000",
+ "PROTO3",
+ "FIXEDMTU",
+ "PINNED",
+ "LOCAL",
+ "BROADCAST",
+ "MULTICAST",
+ /* Big gap. */
+ [28] = "STICKY",
+ [30] = "RNH_LOCKED",
+ [31] = "GWFLAG_COMPAT",
+};
+
+static const char * __pure
+rt_flag_name(unsigned idx)
+{
+ if (idx >= nitems(rtf_flag_strings))
+ return ("INVALID_FLAG");
+ if (rtf_flag_strings[idx] == NULL)
+ return ("UNKNOWN");
+ return (rtf_flag_strings[idx]);
+}
+
+static void
+rt_dumpaddr_ddb(const char *name, const struct sockaddr *sa)
+{
+ char buf[INET6_ADDRSTRLEN], *res;
+
+ res = NULL;
+ if (sa == NULL)
+ res = "NULL";
+ else if (sa->sa_family == AF_INET) {
+ res = inet_ntop(AF_INET,
+ &((const struct sockaddr_in *)sa)->sin_addr,
+ buf, sizeof(buf));
+ } else if (sa->sa_family == AF_INET6) {
+ res = inet_ntop(AF_INET6,
+ &((const struct sockaddr_in6 *)sa)->sin6_addr,
+ buf, sizeof(buf));
+ } else if (sa->sa_family == AF_LINK) {
+ res = "on link";
+ }
+
+ if (res != NULL) {
+ db_printf("%s <%s> ", name, res);
+ return;
+ }
+
+ db_printf("%s <af:%d> ", name, sa->sa_family);
+}
+
+static int
+rt_dumpentry_ddb(struct radix_node *rn, void *arg __unused)
+{
+ struct sockaddr_storage ss;
+ struct rtentry *rt;
+ int flags, idx;
+
+ /* If RNTORT is important, put it in a header. */
+ rt = (void *)rn;
+
+ rt_dumpaddr_ddb("dst", rt_key(rt));
+ rt_dumpaddr_ddb("gateway", &rt->rt_nhop->gw_sa);
+ rt_dumpaddr_ddb("netmask", rtsock_fix_netmask(rt_key(rt), rt_mask(rt),
+ &ss));
+ if (rt->rt_ifp != NULL && (rt->rt_ifp->if_flags & IFF_DYING) == 0) {
+ rt_dumpaddr_ddb("ifp", rt->rt_ifp->if_addr->ifa_addr);
+ rt_dumpaddr_ddb("ifa", rt->rt_ifa->ifa_addr);
+ }
+
+ db_printf("flags ");
+ flags = rt->rt_flags;
+ if (flags == 0)
+ db_printf("none");
+
+ while ((idx = ffs(flags)) > 0) {
+ idx--;
+
+ if (flags != rt->rt_flags)
+ db_printf(",");
+ db_printf("%s", rt_flag_name(idx));
+
+ flags &= ~(1ul << idx);
+ }
+
+ db_printf("\n");
+ return (0);
+}
+
+DB_SHOW_COMMAND(routetable, db_show_routetable_cmd)
+{
+ struct rib_head *rnh;
+ int error, i, lim;
+
+ if (have_addr)
+ i = lim = addr;
+ else {
+ i = 1;
+ lim = AF_MAX;
+ }
+
+ for (; i <= lim; i++) {
+ rnh = rt_tables_get_rnh(0, i);
+ if (rnh == NULL) {
+ if (have_addr) {
+ db_printf("%s: AF %d not supported?\n",
+ __func__, i);
+ break;
+ }
+ continue;
+ }
+
+ if (!have_addr && i > 1)
+ db_printf("\n");
+
+ db_printf("Route table for AF %d%s%s%s:\n", i,
+ (i == AF_INET || i == AF_INET6) ? " (" : "",
+ (i == AF_INET) ? "INET" : (i == AF_INET6) ? "INET6" : "",
+ (i == AF_INET || i == AF_INET6) ? ")" : "");
+
+ error = rnh->rnh_walktree(&rnh->head, rt_dumpentry_ddb, NULL);
+ if (error != 0)
+ db_printf("%s: walktree(%d): %d\n", __func__, i,
+ error);
+ }
+}
+
+_DB_FUNC(_show, route, db_show_route_cmd, db_show_table, CS_OWN, NULL)
+{
+ char buf[INET6_ADDRSTRLEN], *bp;
+ const void *dst_addrp;
+ struct sockaddr *dstp;
+ struct rtentry *rt;
+ union {
+ struct sockaddr_in dest_sin;
+ struct sockaddr_in6 dest_sin6;
+ } u;
+ uint16_t hextets[8];
+ unsigned i, tets;
+ int t, af, exp, tokflags;
+
+ /*
+ * Undecoded address family. No double-colon expansion seen yet.
+ */
+ af = -1;
+ exp = -1;
+ /* Assume INET6 to start; we can work back if guess was wrong. */
+ tokflags = DRT_WSPACE | DRT_HEX | DRT_HEXADECIMAL;
+
+ /*
+ * db_command has lexed 'show route' for us.
+ */
+ t = db_read_token_flags(tokflags);
+ if (t == tWSPACE)
+ t = db_read_token_flags(tokflags);
+
+ /*
+ * tEOL: Just 'show route' isn't a valid mode.
+ * tMINUS: It's either '-h' or some invalid option. Regardless, usage.
+ */
+ if (t == tEOL || t == tMINUS)
+ goto usage;
+
+ db_unread_token(t);
+
+ tets = nitems(hextets);
+
+ /*
+ * Each loop iteration, we expect to read one octet (v4) or hextet
+ * (v6), followed by an appropriate field separator ('.' or ':' or
+ * '::').
+ *
+ * At the start of each loop, we're looking for a number (octet or
+ * hextet).
+ *
+ * INET6 addresses have a special case where they may begin with '::'.
+ */
+ for (i = 0; i < tets; i++) {
+ t = db_read_token_flags(tokflags);
+
+ if (t == tCOLONCOLON) {
+ /* INET6 with leading '::' or invalid. */
+ if (i != 0) {
+ db_printf("Parse error: unexpected extra "
+ "colons.\n");
+ goto exit;
+ }
+
+ af = AF_INET6;
+ exp = i;
+ hextets[i] = 0;
+ continue;
+ } else if (t == tNUMBER) {
+ /*
+ * Lexer separates out '-' as tMINUS, but make the
+ * assumption explicit here.
+ */
+ MPASS(db_tok_number >= 0);
+
+ if (af == AF_INET && db_tok_number > UINT8_MAX) {
+ db_printf("Not a valid v4 octet: %ld\n",
+ (long)db_tok_number);
+ goto exit;
+ }
+ hextets[i] = db_tok_number;
+ } else if (t == tEOL) {
+ /*
+ * We can only detect the end of an IPv6 address in
+ * compact representation with EOL.
+ */
+ if (af != AF_INET6 || exp < 0) {
+ db_printf("Parse failed. Got unexpected EOF "
+ "when the address is not a compact-"
+ "representation IPv6 address.\n");
+ goto exit;
+ }
+ break;
+ } else {
+ db_printf("Parse failed. Unexpected token %d.\n", t);
+ goto exit;
+ }
+
+ /* Next, look for a separator, if appropriate. */
+ if (i == tets - 1)
+ continue;
+
+ t = db_read_token_flags(tokflags);
+ if (af < 0) {
+ if (t == tCOLON) {
+ af = AF_INET6;
+ continue;
+ }
+ if (t == tCOLONCOLON) {
+ af = AF_INET6;
+ i++;
+ hextets[i] = 0;
+ exp = i;
+ continue;
+ }
+ if (t == tDOT) {
+ unsigned hn, dn;
+
+ af = AF_INET;
+ /* Need to fixup the first parsed number. */
+ if (hextets[0] > 0x255 ||
+ (hextets[0] & 0xf0) > 0x90 ||
+ (hextets[0] & 0xf) > 9) {
+ db_printf("Not a valid v4 octet: %x\n",
+ hextets[0]);
+ goto exit;
+ }
+
+ hn = hextets[0];
+ dn = (hn >> 8) * 100 +
+ ((hn >> 4) & 0xf) * 10 +
+ (hn & 0xf);
+
+ hextets[0] = dn;
+
+ /* Switch to decimal for remaining octets. */
+ tokflags &= ~DRT_RADIX_MASK;
+ tokflags |= DRT_DECIMAL;
+
+ tets = 4;
+ continue;
+ }
+
+ db_printf("Parse error. Unexpected token %d.\n", t);
+ goto exit;
+ } else if (af == AF_INET) {
+ if (t == tDOT)
+ continue;
+ db_printf("Expected '.' (%d) between octets but got "
+ "(%d).\n", tDOT, t);
+ goto exit;
+
+ } else if (af == AF_INET6) {
+ if (t == tCOLON)
+ continue;
+ if (t == tCOLONCOLON) {
+ if (exp < 0) {
+ i++;
+ hextets[i] = 0;
+ exp = i;
+ continue;
+ }
+ db_printf("Got bogus second '::' in v6 "
+ "address.\n");
+ goto exit;
+ }
+ if (t == tEOL) {
+ /*
+ * Handle in the earlier part of the loop
+ * because we need to handle trailing :: too.
+ */
+ db_unread_token(t);
+ continue;
+ }
+
+ db_printf("Expected ':' (%d) or '::' (%d) between "
+ "hextets but got (%d).\n", tCOLON, tCOLONCOLON, t);
+ goto exit;
+ }
+ }
+
+ /* Check for trailing garbage. */
+ if (i == tets) {
+ t = db_read_token_flags(tokflags);
+ if (t != tEOL) {
+ db_printf("Got unexpected garbage after address "
+ "(%d).\n", t);
+ goto exit;
+ }
+ }
+
+ /*
+ * Need to expand compact INET6 addresses.
+ *
+ * Technically '::' for a single ':0:' is MUST NOT but just in case,
+ * don't bother expanding that form (exp >= 0 && i == tets case).
+ */
+ if (af == AF_INET6 && exp >= 0 && i < tets) {
+ if (exp + 1 < i) {
+ memmove(&hextets[exp + 1 + (nitems(hextets) - i)],
+ &hextets[exp + 1],
+ (i - (exp + 1)) * sizeof(hextets[0]));
+ }
+ memset(&hextets[exp + 1], 0, (nitems(hextets) - i) *
+ sizeof(hextets[0]));
+ }
+
+ memset(&u, 0, sizeof(u));
+ if (af == AF_INET) {
+ u.dest_sin.sin_family = AF_INET;
+ u.dest_sin.sin_len = sizeof(u.dest_sin);
+ u.dest_sin.sin_addr.s_addr = htonl(
+ ((uint32_t)hextets[0] << 24) |
+ ((uint32_t)hextets[1] << 16) |
+ ((uint32_t)hextets[2] << 8) |
+ (uint32_t)hextets[3]);
+ dstp = (void *)&u.dest_sin;
+ dst_addrp = &u.dest_sin.sin_addr;
+ } else if (af == AF_INET6) {
+ u.dest_sin6.sin6_family = AF_INET6;
+ u.dest_sin6.sin6_len = sizeof(u.dest_sin6);
+ for (i = 0; i < nitems(hextets); i++)
+ u.dest_sin6.sin6_addr.s6_addr16[i] = htons(hextets[i]);
+ dstp = (void *)&u.dest_sin6;
+ dst_addrp = &u.dest_sin6.sin6_addr;
+ } else {
+ MPASS(false);
+ /* UNREACHABLE */
+ /* Appease Clang false positive: */
+ dstp = NULL;
+ }
+
+ bp = inet_ntop(af, dst_addrp, buf, sizeof(buf));
+ if (bp != NULL)
+ db_printf("Looking up route to destination '%s'\n", bp);
+
+ CURVNET_SET(vnet0);
+ rt = rtalloc1(dstp, 0, RTF_RNH_LOCKED);
+ CURVNET_RESTORE();
+
+ if (rt == NULL) {
+ db_printf("Could not get route for that server.\n");
+ return;
+ }
+
+ rt_dumpentry_ddb((void *)rt, NULL);
+ RTFREE_LOCKED(rt);
+
+ return;
+usage:
+ db_printf("Usage: 'show route <address>'\n"
+ " Currently accepts only dotted-decimal INET or colon-separated\n"
+ " hextet INET6 addresses.\n");
+exit:
+ db_skip_to_eol();
+}
+
Index: head/sys/net/rtsock.c
===================================================================
--- head/sys/net/rtsock.c
+++ head/sys/net/rtsock.c
@@ -54,11 +54,6 @@
#include <sys/sysctl.h>
#include <sys/systm.h>
-#ifdef DDB
-#include <ddb/ddb.h>
-#include <ddb/db_lex.h>
-#endif
-
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_dl.h>
@@ -68,6 +63,9 @@
#include <net/raw_cb.h>
#include <net/route.h>
#include <net/route/route_var.h>
+#ifdef RADIX_MPATH
+#include <net/radix_mpath.h>
+#endif
#include <net/vnet.h>
#include <netinet/in.h>
@@ -182,8 +180,6 @@
static int route_output(struct mbuf *m, struct socket *so, ...);
static void rt_getmetrics(const struct rtentry *rt, struct rt_metrics *out);
static void rt_dispatch(struct mbuf *, sa_family_t);
-static struct sockaddr *rtsock_fix_netmask(struct sockaddr *dst,
- struct sockaddr *smask, struct sockaddr_storage *dmask);
static int handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
struct rt_msghdr *rtm, struct rtentry **ret_nrt);
static int update_rtm_from_rte(struct rt_addrinfo *info,
@@ -1136,8 +1132,8 @@
* Fill in @dmask with valid netmask leaving original @smask
* intact. Mostly used with radix netmasks.
*/
-static struct sockaddr *
-rtsock_fix_netmask(struct sockaddr *dst, struct sockaddr *smask,
+struct sockaddr *
+rtsock_fix_netmask(const struct sockaddr *dst, const struct sockaddr *smask,
struct sockaddr_storage *dmask)
{
if (dst == NULL || smask == NULL)
@@ -2164,407 +2160,3 @@
VNET_DOMAIN_SET(route);
-#ifdef DDB
-/*
- * Unfortunately, RTF_ values are expressed as raw masks rather than powers of
- * 2, so we cannot use them as nice C99 initializer indices below.
- */
-static const char * const rtf_flag_strings[] = {
- "UP",
- "GATEWAY",
- "HOST",
- "REJECT",
- "DYNAMIC",
- "MODIFIED",
- "DONE",
- "UNUSED_0x80",
- "UNUSED_0x100",
- "XRESOLVE",
- "LLDATA",
- "STATIC",
- "BLACKHOLE",
- "UNUSED_0x2000",
- "PROTO2",
- "PROTO1",
- "UNUSED_0x10000",
- "UNUSED_0x20000",
- "PROTO3",
- "FIXEDMTU",
- "PINNED",
- "LOCAL",
- "BROADCAST",
- "MULTICAST",
- /* Big gap. */
- [28] = "STICKY",
- [30] = "RNH_LOCKED",
- [31] = "GWFLAG_COMPAT",
-};
-
-static const char * __pure
-rt_flag_name(unsigned idx)
-{
- if (idx >= nitems(rtf_flag_strings))
- return ("INVALID_FLAG");
- if (rtf_flag_strings[idx] == NULL)
- return ("UNKNOWN");
- return (rtf_flag_strings[idx]);
-}
-
-static void
-rt_dumpaddr_ddb(const char *name, const struct sockaddr *sa)
-{
- char buf[INET6_ADDRSTRLEN], *res;
-
- res = NULL;
- if (sa == NULL)
- res = "NULL";
- else if (sa->sa_family == AF_INET) {
- res = inet_ntop(AF_INET,
- &((const struct sockaddr_in *)sa)->sin_addr,
- buf, sizeof(buf));
- } else if (sa->sa_family == AF_INET6) {
- res = inet_ntop(AF_INET6,
- &((const struct sockaddr_in6 *)sa)->sin6_addr,
- buf, sizeof(buf));
- } else if (sa->sa_family == AF_LINK) {
- res = "on link";
- }
-
- if (res != NULL) {
- db_printf("%s <%s> ", name, res);
- return;
- }
-
- db_printf("%s <af:%d> ", name, sa->sa_family);
-}
-
-static int
-rt_dumpentry_ddb(struct radix_node *rn, void *arg __unused)
-{
- struct sockaddr_storage ss;
- struct rtentry *rt;
- int flags, idx;
-
- /* If RNTORT is important, put it in a header. */
- rt = (void *)rn;
-
- rt_dumpaddr_ddb("dst", rt_key(rt));
- rt_dumpaddr_ddb("gateway", &rt->rt_nhop->gw_sa);
- rt_dumpaddr_ddb("netmask", rtsock_fix_netmask(rt_key(rt), rt_mask(rt),
- &ss));
- if (rt->rt_ifp != NULL && (rt->rt_ifp->if_flags & IFF_DYING) == 0) {
- rt_dumpaddr_ddb("ifp", rt->rt_ifp->if_addr->ifa_addr);
- rt_dumpaddr_ddb("ifa", rt->rt_ifa->ifa_addr);
- }
-
- db_printf("flags ");
- flags = rt->rt_flags;
- if (flags == 0)
- db_printf("none");
-
- while ((idx = ffs(flags)) > 0) {
- idx--;
-
- if (flags != rt->rt_flags)
- db_printf(",");
- db_printf("%s", rt_flag_name(idx));
-
- flags &= ~(1ul << idx);
- }
-
- db_printf("\n");
- return (0);
-}
-
-DB_SHOW_COMMAND(routetable, db_show_routetable_cmd)
-{
- struct rib_head *rnh;
- int error, i, lim;
-
- if (have_addr)
- i = lim = addr;
- else {
- i = 1;
- lim = AF_MAX;
- }
-
- for (; i <= lim; i++) {
- rnh = rt_tables_get_rnh(0, i);
- if (rnh == NULL) {
- if (have_addr) {
- db_printf("%s: AF %d not supported?\n",
- __func__, i);
- break;
- }
- continue;
- }
-
- if (!have_addr && i > 1)
- db_printf("\n");
-
- db_printf("Route table for AF %d%s%s%s:\n", i,
- (i == AF_INET || i == AF_INET6) ? " (" : "",
- (i == AF_INET) ? "INET" : (i == AF_INET6) ? "INET6" : "",
- (i == AF_INET || i == AF_INET6) ? ")" : "");
-
- error = rnh->rnh_walktree(&rnh->head, rt_dumpentry_ddb, NULL);
- if (error != 0)
- db_printf("%s: walktree(%d): %d\n", __func__, i,
- error);
- }
-}
-
-_DB_FUNC(_show, route, db_show_route_cmd, db_show_table, CS_OWN, NULL)
-{
- char buf[INET6_ADDRSTRLEN], *bp;
- const void *dst_addrp;
- struct sockaddr *dstp;
- struct rtentry *rt;
- union {
- struct sockaddr_in dest_sin;
- struct sockaddr_in6 dest_sin6;
- } u;
- uint16_t hextets[8];
- unsigned i, tets;
- int t, af, exp, tokflags;
-
- /*
- * Undecoded address family. No double-colon expansion seen yet.
- */
- af = -1;
- exp = -1;
- /* Assume INET6 to start; we can work back if guess was wrong. */
- tokflags = DRT_WSPACE | DRT_HEX | DRT_HEXADECIMAL;
-
- /*
- * db_command has lexed 'show route' for us.
- */
- t = db_read_token_flags(tokflags);
- if (t == tWSPACE)
- t = db_read_token_flags(tokflags);
-
- /*
- * tEOL: Just 'show route' isn't a valid mode.
- * tMINUS: It's either '-h' or some invalid option. Regardless, usage.
- */
- if (t == tEOL || t == tMINUS)
- goto usage;
-
- db_unread_token(t);
-
- tets = nitems(hextets);
-
- /*
- * Each loop iteration, we expect to read one octet (v4) or hextet
- * (v6), followed by an appropriate field separator ('.' or ':' or
- * '::').
- *
- * At the start of each loop, we're looking for a number (octet or
- * hextet).
- *
- * INET6 addresses have a special case where they may begin with '::'.
- */
- for (i = 0; i < tets; i++) {
- t = db_read_token_flags(tokflags);
-
- if (t == tCOLONCOLON) {
- /* INET6 with leading '::' or invalid. */
- if (i != 0) {
- db_printf("Parse error: unexpected extra "
- "colons.\n");
- goto exit;
- }
-
- af = AF_INET6;
- exp = i;
- hextets[i] = 0;
- continue;
- } else if (t == tNUMBER) {
- /*
- * Lexer separates out '-' as tMINUS, but make the
- * assumption explicit here.
- */
- MPASS(db_tok_number >= 0);
-
- if (af == AF_INET && db_tok_number > UINT8_MAX) {
- db_printf("Not a valid v4 octet: %ld\n",
- (long)db_tok_number);
- goto exit;
- }
- hextets[i] = db_tok_number;
- } else if (t == tEOL) {
- /*
- * We can only detect the end of an IPv6 address in
- * compact representation with EOL.
- */
- if (af != AF_INET6 || exp < 0) {
- db_printf("Parse failed. Got unexpected EOF "
- "when the address is not a compact-"
- "representation IPv6 address.\n");
- goto exit;
- }
- break;
- } else {
- db_printf("Parse failed. Unexpected token %d.\n", t);
- goto exit;
- }
-
- /* Next, look for a separator, if appropriate. */
- if (i == tets - 1)
- continue;
-
- t = db_read_token_flags(tokflags);
- if (af < 0) {
- if (t == tCOLON) {
- af = AF_INET6;
- continue;
- }
- if (t == tCOLONCOLON) {
- af = AF_INET6;
- i++;
- hextets[i] = 0;
- exp = i;
- continue;
- }
- if (t == tDOT) {
- unsigned hn, dn;
-
- af = AF_INET;
- /* Need to fixup the first parsed number. */
- if (hextets[0] > 0x255 ||
- (hextets[0] & 0xf0) > 0x90 ||
- (hextets[0] & 0xf) > 9) {
- db_printf("Not a valid v4 octet: %x\n",
- hextets[0]);
- goto exit;
- }
-
- hn = hextets[0];
- dn = (hn >> 8) * 100 +
- ((hn >> 4) & 0xf) * 10 +
- (hn & 0xf);
-
- hextets[0] = dn;
-
- /* Switch to decimal for remaining octets. */
- tokflags &= ~DRT_RADIX_MASK;
- tokflags |= DRT_DECIMAL;
-
- tets = 4;
- continue;
- }
-
- db_printf("Parse error. Unexpected token %d.\n", t);
- goto exit;
- } else if (af == AF_INET) {
- if (t == tDOT)
- continue;
- db_printf("Expected '.' (%d) between octets but got "
- "(%d).\n", tDOT, t);
- goto exit;
-
- } else if (af == AF_INET6) {
- if (t == tCOLON)
- continue;
- if (t == tCOLONCOLON) {
- if (exp < 0) {
- i++;
- hextets[i] = 0;
- exp = i;
- continue;
- }
- db_printf("Got bogus second '::' in v6 "
- "address.\n");
- goto exit;
- }
- if (t == tEOL) {
- /*
- * Handle in the earlier part of the loop
- * because we need to handle trailing :: too.
- */
- db_unread_token(t);
- continue;
- }
-
- db_printf("Expected ':' (%d) or '::' (%d) between "
- "hextets but got (%d).\n", tCOLON, tCOLONCOLON, t);
- goto exit;
- }
- }
-
- /* Check for trailing garbage. */
- if (i == tets) {
- t = db_read_token_flags(tokflags);
- if (t != tEOL) {
- db_printf("Got unexpected garbage after address "
- "(%d).\n", t);
- goto exit;
- }
- }
-
- /*
- * Need to expand compact INET6 addresses.
- *
- * Technically '::' for a single ':0:' is MUST NOT but just in case,
- * don't bother expanding that form (exp >= 0 && i == tets case).
- */
- if (af == AF_INET6 && exp >= 0 && i < tets) {
- if (exp + 1 < i) {
- memmove(&hextets[exp + 1 + (nitems(hextets) - i)],
- &hextets[exp + 1],
- (i - (exp + 1)) * sizeof(hextets[0]));
- }
- memset(&hextets[exp + 1], 0, (nitems(hextets) - i) *
- sizeof(hextets[0]));
- }
-
- memset(&u, 0, sizeof(u));
- if (af == AF_INET) {
- u.dest_sin.sin_family = AF_INET;
- u.dest_sin.sin_len = sizeof(u.dest_sin);
- u.dest_sin.sin_addr.s_addr = htonl(
- ((uint32_t)hextets[0] << 24) |
- ((uint32_t)hextets[1] << 16) |
- ((uint32_t)hextets[2] << 8) |
- (uint32_t)hextets[3]);
- dstp = (void *)&u.dest_sin;
- dst_addrp = &u.dest_sin.sin_addr;
- } else if (af == AF_INET6) {
- u.dest_sin6.sin6_family = AF_INET6;
- u.dest_sin6.sin6_len = sizeof(u.dest_sin6);
- for (i = 0; i < nitems(hextets); i++)
- u.dest_sin6.sin6_addr.s6_addr16[i] = htons(hextets[i]);
- dstp = (void *)&u.dest_sin6;
- dst_addrp = &u.dest_sin6.sin6_addr;
- } else {
- MPASS(false);
- /* UNREACHABLE */
- /* Appease Clang false positive: */
- dstp = NULL;
- }
-
- bp = inet_ntop(af, dst_addrp, buf, sizeof(buf));
- if (bp != NULL)
- db_printf("Looking up route to destination '%s'\n", bp);
-
- CURVNET_SET(vnet0);
- rt = rtalloc1(dstp, 0, RTF_RNH_LOCKED);
- CURVNET_RESTORE();
-
- if (rt == NULL) {
- db_printf("Could not get route for that server.\n");
- return;
- }
-
- rt_dumpentry_ddb((void *)rt, NULL);
- RTFREE_LOCKED(rt);
-
- return;
-usage:
- db_printf("Usage: 'show route <address>'\n"
- " Currently accepts only dotted-decimal INET or colon-separated\n"
- " hextet INET6 addresses.\n");
-exit:
- db_skip_to_eol();
-}
-#endif
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 21, 3:06 AM (15 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30056605
Default Alt Text
D24561.diff (23 KB)
Attached To
Mode
D24561: Move route-specific ddb commands to route/route_ddb.c
Attached
Detach File
Event Timeline
Log In to Comment