aboutsummaryrefslogtreecommitdiff
path: root/sbin/route
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/route')
-rw-r--r--sbin/route/Makefile2
-rw-r--r--sbin/route/Makefile.depend1
-rw-r--r--sbin/route/keywords1
-rw-r--r--sbin/route/route.818
-rw-r--r--sbin/route/route.c53
-rw-r--r--sbin/route/route_netlink.c40
-rw-r--r--sbin/route/tests/Makefile9
-rw-r--r--sbin/route/tests/Makefile.depend10
-rw-r--r--sbin/route/tests/basic.sh58
9 files changed, 127 insertions, 65 deletions
diff --git a/sbin/route/Makefile b/sbin/route/Makefile
index 7685a2fecd64..43b9c0d8d821 100644
--- a/sbin/route/Makefile
+++ b/sbin/route/Makefile
@@ -1,5 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-
.include <src.opts.mk>
PACKAGE=runtime
diff --git a/sbin/route/Makefile.depend b/sbin/route/Makefile.depend
index 344a5d0e9310..672ec75190c6 100644
--- a/sbin/route/Makefile.depend
+++ b/sbin/route/Makefile.depend
@@ -7,6 +7,7 @@ DIRDEPS = \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
+ lib/libjail \
.include <dirdeps.mk>
diff --git a/sbin/route/keywords b/sbin/route/keywords
index 496fb8b95e2e..cbd8799ffb6b 100644
--- a/sbin/route/keywords
+++ b/sbin/route/keywords
@@ -1,4 +1,3 @@
-# @(#)keywords 8.2 (Berkeley) 3/19/94
4
6
diff --git a/sbin/route/route.8 b/sbin/route/route.8
index 4eccd511f0cc..572781ef59c8 100644
--- a/sbin/route/route.8
+++ b/sbin/route/route.8
@@ -25,9 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)route.8 8.3 (Berkeley) 3/19/94
-.\"
-.Dd June 16, 2023
+.Dd November 12, 2024
.Dt ROUTE 8
.Os
.Sh NAME
@@ -554,17 +552,3 @@ The
.Nm
utility appeared in
.Bx 4.2 .
-.Sh BUGS
-The first paragraph may have slightly exaggerated
-.Xr routed 8 Ns 's
-abilities.
-.Pp
-Currently, routes with the
-.Dv RTF_BLACKHOLE
-flag set need to have the gateway set to an instance of the
-.Xr lo 4
-driver, using the
-.Fl iface
-option, for the flag to have any effect; unless IP fast forwarding
-is enabled, in which case the meaning of the flag will always
-be honored.
diff --git a/sbin/route/route.c b/sbin/route/route.c
index 3913bdc9e6af..f37d23d25c2c 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -29,19 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1983, 1989, 1991, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95";
-#endif
-#endif /* not lint */
-
-#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
@@ -107,8 +94,8 @@ static u_long rtm_inits;
static uid_t uid;
static int defaultfib;
static int numfibs;
-static char domain[MAXHOSTNAMELEN + 1];
-static bool domain_initialized;
+static char domain_storage[MAXHOSTNAMELEN + 1];
+static const char *domain;
static char rt_line[NI_MAXHOST];
static char net_line[MAXHOSTNAMELEN + 1];
@@ -594,14 +581,16 @@ routename(struct sockaddr *sa)
const char *cp;
int n;
- if (!domain_initialized) {
- domain_initialized = true;
- if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
- (cp = strchr(domain, '.'))) {
- domain[MAXHOSTNAMELEN] = '\0';
- (void)strcpy(domain, cp + 1);
- } else
- domain[0] = '\0';
+ if (domain == NULL) {
+ if (gethostname(domain_storage,
+ sizeof(domain_storage) - 1) == 0 &&
+ (cp = strchr(domain_storage, '.')) != NULL) {
+ domain_storage[sizeof(domain_storage) - 1] = '\0';
+ domain = cp + 1;
+ } else {
+ domain_storage[0] = '\0';
+ domain = domain_storage;
+ }
}
/* If the address is zero-filled, use "default". */
@@ -1342,6 +1331,9 @@ getaddr(int idx, char *str, int nrflags)
q = strchr(str,'/');
if (q != NULL && idx == RTAX_DST) {
/* A.B.C.D/NUM */
+ struct sockaddr_in *mask;
+ uint32_t mask_bits;
+
*q = '\0';
if (inet_aton(str, &sin->sin_addr) == 0)
errx(EX_NOHOST, "bad address: %s", str);
@@ -1351,6 +1343,20 @@ getaddr(int idx, char *str, int nrflags)
errx(EX_NOHOST, "bad mask length: %s", q + 1);
inet_makemask((struct sockaddr_in *)&so[RTAX_NETMASK],masklen);
+
+ /*
+ * Check for bogus destination such as "10/8"; heuristic is
+ * that there are bits set in the host part, and no dot
+ * is present.
+ */
+ mask = ((struct sockaddr_in *) &so[RTAX_NETMASK]);
+ mask_bits = ntohl(mask->sin_addr.s_addr);
+ if ((ntohl(sin->sin_addr.s_addr) & ~mask_bits) != 0 &&
+ strchr(str, '.') == NULL)
+ errx(EX_NOHOST,
+ "malformed address, bits set after mask;"
+ " %s means %s",
+ str, inet_ntoa(sin->sin_addr));
return (0);
}
if (inet_aton(str, &sin->sin_addr) != 0)
@@ -1657,6 +1663,7 @@ static const char *const msgtypes[] = {
"RTM_DELMADDR: multicast group membership removed from iface",
"RTM_IFANNOUNCE: interface arrival/departure",
"RTM_IEEE80211: IEEE 802.11 wireless event",
+ "RTM_IPFWLOG: IPFW log",
};
static const char metricnames[] =
diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c
index 0dbd90151e10..ba22a2ec1e22 100644
--- a/sbin/route/route_netlink.c
+++ b/sbin/route/route_netlink.c
@@ -266,27 +266,32 @@ rtmsg_nl_int(struct nl_helper *h, int cmd, int rtm_flags, int fib, int rtm_addrs
if (rt_metrics->rmx_weight > 0)
snl_add_msg_attr_u32(&nw, NL_RTA_WEIGHT, rt_metrics->rmx_weight);
- if (snl_finalize_msg(&nw) && snl_send_message(ss, hdr)) {
+ if ((hdr = snl_finalize_msg(&nw)) && snl_send_message(ss, hdr)) {
struct snl_errmsg_data e = {};
hdr = snl_read_reply(ss, hdr->nlmsg_seq);
if (nl_type == NL_RTM_GETROUTE) {
- if (hdr->nlmsg_type == NL_RTM_NEWROUTE)
+ if (hdr->nlmsg_type == NL_RTM_NEWROUTE) {
print_getmsg(h, hdr, dst);
- else {
- snl_parse_errmsg(ss, hdr, &e);
- if (e.error == ESRCH)
- warn("route has not been found");
- else
- warn("message indicates error %d", e.error);
+ return (0);
}
-
- return (0);
}
- if (snl_parse_errmsg(ss, hdr, &e))
+ if (snl_parse_errmsg(ss, hdr, &e)) {
+ switch (e.error) {
+ case (ESRCH):
+ warnx("route has not been found");
+ break;
+ default:
+ if (e.error == 0)
+ break;
+ warnc(e.error, "message indicates error");
+ }
+
return (e.error);
+ }
}
+
return (EINVAL);
}
@@ -314,7 +319,7 @@ get_ifdata(struct nl_helper *h, uint32_t ifindex, struct snl_parsed_link_simple
struct ifinfomsg *ifmsg = snl_reserve_msg_object(&nw, struct ifinfomsg);
if (ifmsg != NULL)
ifmsg->ifi_index = ifindex;
- if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
return;
hdr = snl_read_reply(ss, hdr->nlmsg_seq);
@@ -584,7 +589,7 @@ print_nlmsg_link(struct nl_helper *h, struct nlmsghdr *hdr,
printf("iface#%u %s ", l.ifi_index, l.ifla_ifname);
printf("admin %s ", (l.ifi_flags & IFF_UP) ? "UP" : "DOWN");
- if (l.ifla_operstate < NL_ARRAY_LEN(operstate))
+ if (l.ifla_operstate < nitems(operstate))
printf("oper %s ", operstate[l.ifla_operstate]);
if (l.ifla_mtu > 0)
printf("mtu %u ", l.ifla_mtu);
@@ -663,7 +668,7 @@ print_nlmsg_neigh(struct nl_helper *h, struct nlmsghdr *hdr,
struct snl_parsed_link_simple link = {};
get_ifdata(h, attrs.nda_ifindex, &link);
- for (unsigned int i = 0; i < NL_ARRAY_LEN(nudstate); i++) {
+ for (unsigned int i = 0; i < nitems(nudstate); i++) {
if ((1 << i) & attrs.ndm_state) {
printf("state %s ", nudstate[i]);
break;
@@ -733,6 +738,7 @@ print_nlmsg(struct nl_helper *h, struct nlmsghdr *hdr, struct snl_msg_info *cinf
print_nlmsg_generic(h, hdr, cinfo);
}
+ fflush(stdout);
snl_clear_lb(&h->ss_cmd);
}
@@ -763,7 +769,7 @@ monitor_nl(int fib)
socklen_t optlen = sizeof(optval);
setsockopt(ss_event.fd, SOL_NETLINK, NETLINK_MSG_INFO, &optval, optlen);
- for (unsigned int i = 0; i < NL_ARRAY_LEN(groups); i++) {
+ for (unsigned int i = 0; i < nitems(groups); i++) {
int error;
int optval = groups[i];
socklen_t optlen = sizeof(optval);
@@ -817,7 +823,7 @@ flushroute_one(struct nl_helper *h, struct snl_parsed_route *r)
snl_add_msg_attr_u32(&nw, RTA_TABLE, r->rta_table);
snl_add_msg_attr_ip(&nw, RTA_DST, r->rta_dst);
- if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
return (ENOMEM);
if (!snl_read_reply_code(ss, hdr->nlmsg_seq, &e)) {
@@ -864,7 +870,7 @@ flushroutes_fib_nl(int fib, int af)
rtm->rtm_family = af;
snl_add_msg_attr_u32(&nw, RTA_TABLE, fib);
- if (!snl_finalize_msg(&nw) || !snl_send_message(&ss, hdr)) {
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(&ss, hdr)) {
snl_free(&ss);
return (EINVAL);
}
diff --git a/sbin/route/tests/Makefile b/sbin/route/tests/Makefile
index 1ae964693ff4..9d634d7c48b8 100644
--- a/sbin/route/tests/Makefile
+++ b/sbin/route/tests/Makefile
@@ -1,10 +1,9 @@
-
PACKAGE= tests
-ATF_TESTS_SH+= \
- basic
+ATF_TESTS_SH+= basic
+# Tests reuse jail names and so cannot run in parallel.
+TEST_METADATA.basic+= is_exclusive=true
-${PACKAGE}FILES+= \
- utils.subr
+${PACKAGE}FILES+= utils.subr
.include <bsd.test.mk>
diff --git a/sbin/route/tests/Makefile.depend b/sbin/route/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/sbin/route/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sbin/route/tests/basic.sh b/sbin/route/tests/basic.sh
index bb432daa0793..2e2ab9dba97f 100644
--- a/sbin/route/tests/basic.sh
+++ b/sbin/route/tests/basic.sh
@@ -117,8 +117,66 @@ basic_v6_cleanup()
vnet_cleanup
}
+atf_test_case "interface_route_v4" "cleanup"
+interface_route_v4_head()
+{
+ atf_set descr 'add interface route for v4'
+ atf_set require.user root
+ atf_set require.progs jail jq
+}
+
+interface_route_v4_body()
+{
+ epair=$(vnet_mkepair)
+ ifconfig ${epair}a up
+ vnet_mkjail alcatraz ${epair}b
+
+ # add interface route
+ jexec alcatraz route add "192.0.2.1" -iface ${epair}b
+ gateway=$(check_route "alcatraz" "192.0.2.1")
+
+ if [ -z "${gateway}" ]; then
+ atf_fail "Failed to add interface route."
+ fi
+}
+
+interface_route_v4_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_test_case "interface_route_v6" "cleanup"
+interface_route_v6_head()
+{
+ atf_set descr 'add interface route for v6'
+ atf_set require.user root
+ atf_set require.progs jail jq
+}
+
+interface_route_v6_body()
+{
+ epair=$(vnet_mkepair)
+ ifconfig ${epair}a up
+ vnet_mkjail alcatraz ${epair}b
+
+ # add interface route
+ jexec alcatraz route add -6 "2001:db8:cc4b::1" -iface ${epair}b
+ gateway=$(check_route "alcatraz" "2001:db8:cc4b::1")
+
+ if [ -z "${gateway}" ]; then
+ atf_fail "Failed to add interface route."
+ fi
+}
+
+interface_route_v6_cleanup()
+{
+ vnet_cleanup
+}
+
atf_init_test_cases()
{
atf_add_test_case "basic_v4"
atf_add_test_case "basic_v6"
+ atf_add_test_case "interface_route_v4"
+ atf_add_test_case "interface_route_v6"
}