Page MenuHomeFreeBSD

D58294.diff
No OneTemporary

D58294.diff

diff --git a/sbin/route/keywords b/sbin/route/keywords
--- a/sbin/route/keywords
+++ b/sbin/route/keywords
@@ -36,6 +36,7 @@
nostick
osi
prefixlen
+prefsrc
proto1
proto2
proxy
diff --git a/sbin/route/route.c b/sbin/route/route.c
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -946,6 +946,7 @@
errx(EX_USAGE,
"invalid fib number: %s", *argv);
break;
+ case K_PREFSRC:
case K_IFA:
if (!--argc)
usage(NULL);
diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c
--- a/sbin/route/route_netlink.c
+++ b/sbin/route/route_netlink.c
@@ -174,6 +174,7 @@
struct sockaddr *dst = get_addr(so, rtm_addrs, RTAX_DST);
struct sockaddr *mask = get_addr(so, rtm_addrs, RTAX_NETMASK);
struct sockaddr *gw = get_addr(so, rtm_addrs, RTAX_GATEWAY);
+ struct sockaddr *prefsrc = get_addr(so, rtm_addrs, RTAX_IFA);
if (dst == NULL)
return (EINVAL);
@@ -225,6 +226,7 @@
rtm->rtm_flags = RTM_F_PREFIX;
snl_add_msg_attr_ip(&nw, RTA_DST, dst);
+ snl_add_msg_attr_ip(&nw, RTA_PREFSRC, prefsrc);
snl_add_msg_attr_u32(&nw, RTA_TABLE, fib);
uint32_t rta_oif = 0;
diff --git a/sys/net/route/nhop_ctl.c b/sys/net/route/nhop_ctl.c
--- a/sys/net/route/nhop_ctl.c
+++ b/sys/net/route/nhop_ctl.c
@@ -120,8 +120,8 @@
/*
* Fetches the interface of source address used by the route.
- * In all cases except interface-address-route it would be the
- * same as the transmit interfaces.
+ * In all cases except interface-address-route and prefsrc it
+ * would be the same as the transmit interfaces.
* However, for the interface address this function will return
* this interface ifp instead of loopback. This is needed to support
* link-local IPv6 loopback communications.
@@ -147,7 +147,8 @@
FIB_NH_LOG(LOG_WARNING, nh, "unable to get aifp for %s index %d",
if_name(nh->nh_ifp), nh->gwl_sa.sdl_index);
}
- }
+ } else if (nh->nh_ifa->ifa_ifp != nh->nh_ifp)
+ aifp = nh->nh_ifa->ifa_ifp;
if (aifp == NULL)
aifp = nh->nh_ifp;
diff --git a/sys/netlink/netlink_snl_route_parsers.h b/sys/netlink/netlink_snl_route_parsers.h
--- a/sys/netlink/netlink_snl_route_parsers.h
+++ b/sys/netlink/netlink_snl_route_parsers.h
@@ -113,6 +113,7 @@
struct snl_parsed_route {
struct sockaddr *rta_dst;
struct sockaddr *rta_gw;
+ struct sockaddr *rta_pref_src;
struct nlattr *rta_metrics;
struct rta_mpath rta_multipath;
uint32_t rta_oif;
@@ -142,6 +143,7 @@
{ .type = NL_RTA_OIF, .off = _OUT(rta_oif), .cb = snl_attr_get_uint32 },
{ .type = NL_RTA_GATEWAY, .off = _OUT(rta_gw), .cb = snl_attr_get_ip },
{ .type = NL_RTA_PRIORITY, .off = _OUT(rta_metric), .cb = snl_attr_get_uint32 },
+ { .type = NL_RTA_PREFSRC, .off = _OUT(rta_pref_src), .cb = snl_attr_get_ip },
{ .type = NL_RTA_METRICS, .arg = &_metrics_parser, .cb = snl_attr_get_nested },
{ .type = NL_RTA_MULTIPATH, .off = _OUT(rta_multipath), .cb = nlattr_get_multipath },
{ .type = NL_RTA_KNH_ID, .off = _OUT(rta_knh_id), .cb = snl_attr_get_uint32 },
diff --git a/sys/netlink/route/nexthop.c b/sys/netlink/route/nexthop.c
--- a/sys/netlink/route/nexthop.c
+++ b/sys/netlink/route/nexthop.c
@@ -811,6 +811,26 @@
return (0);
}
+/*
+ * Sets nexthop @nh prefsrc specified by @src.
+ * Returns 0 on success or errno.
+ */
+int
+nl_set_nexthop_prefsrc(struct nhop_object *nh, struct sockaddr *src)
+{
+ struct ifaddr *ifa = NULL;
+ int fibnum = nhop_get_fibnum(nh);
+
+ MPASS(src != NULL);
+
+ ifa = ifa_ifwithaddr_fib(src, fibnum);
+ if (ifa == NULL)
+ return (EINVAL);
+
+ nhop_set_src(nh, ifa);
+ return (0);
+}
+
static int
newnhop(struct nl_parsed_nhop *attrs, struct user_nhop *unhop, struct nl_pstate *npt)
{
diff --git a/sys/netlink/route/route.h b/sys/netlink/route/route.h
--- a/sys/netlink/route/route.h
+++ b/sys/netlink/route/route.h
@@ -145,12 +145,12 @@
enum rtattr_type_t {
NL_RTA_UNSPEC,
NL_RTA_DST = 1, /* binary, IPv4/IPv6 destination */
- NL_RTA_SRC = 2, /* binary, preferred source address */
+ NL_RTA_SRC = 2, /* not supported */
NL_RTA_IIF = 3, /* not supported */
NL_RTA_OIF = 4, /* u32, transmit ifindex */
NL_RTA_GATEWAY = 5, /* binary: IPv4/IPv6 gateway */
NL_RTA_PRIORITY = 6, /* u32, path metric */
- NL_RTA_PREFSRC = 7, /* not supported */
+ NL_RTA_PREFSRC = 7, /* binary, preferred source address */
NL_RTA_METRICS = 8, /* nested, list of NL_RTAX* attrs */
NL_RTA_MULTIPATH = 9, /* binary, array of struct rtnexthop */
NL_RTA_PROTOINFO = 10, /* not supported / deprecated */
@@ -200,6 +200,7 @@
#define RTA_GATEWAY NL_RTA_GATEWAY
#define RTA_PRIORITY NL_RTA_PRIORITY
#define RTA_PREFSRC NL_RTA_PREFSRC
+#define RTA_IFA NL_RTA_PREFSRC
#define RTA_METRICS NL_RTA_METRICS
#define RTA_MULTIPATH NL_RTA_MULTIPATH
#define RTA_PROTOINFO NL_RTA_PROTOINFO
diff --git a/sys/netlink/route/route_var.h b/sys/netlink/route/route_var.h
--- a/sys/netlink/route/route_var.h
+++ b/sys/netlink/route/route_var.h
@@ -136,6 +136,7 @@
uint32_t uidx, int nh_flags, int *perror);
int nl_set_nexthop_gw(struct nhop_object *nh, struct sockaddr *gw,
struct ifnet *ifp, struct nl_pstate *npt);
+int nl_set_nexthop_prefsrc(struct nhop_object *nh, struct sockaddr *src);
#endif
diff --git a/sys/netlink/route/rt.c b/sys/netlink/route/rt.c
--- a/sys/netlink/route/rt.c
+++ b/sys/netlink/route/rt.c
@@ -158,6 +158,31 @@
}
}
+static void
+dump_rc_nhop_prefsrc(struct nl_writer *nw, const struct nhop_object *nh)
+{
+ const struct ifaddr *ifa = nh->nh_ifa;
+#ifdef INET6
+ struct in6_addr in6;
+#endif
+
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ nlattr_add(nw, NL_RTA_PREFSRC, 4,
+ &((struct sockaddr_in *)((ifa)->ifa_addr))->sin_addr);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ in6 = ((struct sockaddr_in6 *)((ifa)->ifa_addr))->sin6_addr;
+ in6_clearscope(&in6);
+ nlattr_add(nw, NL_RTA_PREFSRC, 16, &in6);
+ break;
+#endif
+ }
+}
+
static void
dump_rc_nhop_mtu(struct nl_writer *nw, const struct nhop_object *nh)
{
@@ -193,6 +218,7 @@
if (nh->nh_flags & NHF_GATEWAY)
dump_rc_nhop_gw(nw, nh);
+ dump_rc_nhop_prefsrc(nw, nh);
wn = nhgrp_get_nhops(nhg, &num_nhops);
base_rtflags = nhop_get_rtflags(wn[0].nh);
uidx = nhgrp_get_uidx(nhg);
@@ -269,6 +295,7 @@
if (nh->nh_flags & NHF_GATEWAY)
dump_rc_nhop_gw(nw, nh);
+ dump_rc_nhop_prefsrc(nw, nh);
uidx = nhop_get_uidx(nh);
if (uidx != 0)
nlattr_add_u32(nw, NL_RTA_NH_ID, uidx);
@@ -518,6 +545,7 @@
struct nl_parsed_route {
struct sockaddr *rta_dst;
struct sockaddr *rta_gw;
+ struct sockaddr *rta_pref_src;
struct ifnet *rta_oif;
struct rta_mpath *rta_multipath;
uint32_t rta_table;
@@ -547,6 +575,7 @@
{ .type = NL_RTA_OIF, .off = _OUT(rta_oif), .cb = nlattr_get_ifp },
{ .type = NL_RTA_GATEWAY, .off = _OUT(rta_gw), .cb = nlattr_get_ip },
{ .type = NL_RTA_PRIORITY, .off = _OUT(rta_metric), .cb = nlattr_get_uint32 },
+ { .type = NL_RTA_PREFSRC, .off = _OUT(rta_pref_src), .cb = nlattr_get_ip },
{ .type = NL_RTA_METRICS, .arg = &metrics_parser, .cb = nlattr_get_nested },
{ .type = NL_RTA_MULTIPATH, .off = _OUT(rta_multipath), .cb = nlattr_get_multipath },
{ .type = NL_RTA_WEIGHT, .off = _OUT(rta_weight), .cb = nlattr_get_uint32 },
@@ -575,6 +604,7 @@
set_scope6(attrs->rta_dst, attrs->rta_oif);
set_scope6(attrs->rta_gw, attrs->rta_oif);
+ set_scope6(attrs->rta_pref_src, attrs->rta_oif);
return (true);
}
NL_DECLARE_PARSER_EXT(rtm_parser, struct rtmsg, NULL, nlf_p_rtmsg, nla_p_rtmsg, post_p_rtmsg);
@@ -873,6 +903,13 @@
}
if (mpnh->ifp != NULL)
nhop_set_transmit_ifp(nh, mpnh->ifp);
+ if (attrs->rta_pref_src != NULL) {
+ error = nl_set_nexthop_prefsrc(nh, attrs->rta_pref_src);
+ if (error != 0) {
+ nhop_free(nh);
+ return (error);
+ }
+ }
nhop_set_pxtype_flag(nh, get_pxflag(attrs));
nhop_set_rtflags(nh, attrs->rta_rtflags);
nhop_set_metric(nh, attrs->rta_metric);
@@ -945,6 +982,13 @@
}
if (attrs->rta_oif != NULL)
nhop_set_transmit_ifp(nh, attrs->rta_oif);
+ if (attrs->rta_pref_src != NULL) {
+ *perror = nl_set_nexthop_prefsrc(nh, attrs->rta_pref_src);
+ if (*perror != 0) {
+ nhop_free(nh);
+ return (NULL);
+ }
+ }
if (attrs->rtax_mtu != 0)
nhop_set_mtu(nh, attrs->rtax_mtu, true);
if (attrs->rta_expire > 0) {

File Metadata

Mime Type
text/plain
Expires
Sat, Jul 25, 12:28 AM (8 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35457185
Default Alt Text
D58294.diff (8 KB)

Event Timeline