Page MenuHomeFreeBSD

D28246.id82595.diff
No OneTemporary

D28246.id82595.diff

Index: sys/netinet/in.c
===================================================================
--- sys/netinet/in.c
+++ sys/netinet/in.c
@@ -79,6 +79,8 @@
static void in_socktrim(struct sockaddr_in *);
static void in_purgemaddrs(struct ifnet *);
+static bool ia_need_loopback_route(const struct in_ifaddr *);
+
VNET_DEFINE_STATIC(int, nosameprefix);
#define V_nosameprefix VNET(nosameprefix)
SYSCTL_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_VNET | CTLFLAG_RW,
@@ -494,10 +496,7 @@
/*
* Add a loopback route to self.
*/
- if (vhid == 0 && (ifp->if_flags & IFF_LOOPBACK) == 0 &&
- ia->ia_addr.sin_addr.s_addr != INADDR_ANY &&
- !((ifp->if_flags & IFF_POINTOPOINT) &&
- ia->ia_dstaddr.sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr)) {
+ if (vhid == 0 && ia_need_loopback_route(ia)) {
struct in_ifaddr *eia;
eia = in_localip_more(ia);
@@ -723,7 +722,8 @@
static int
in_handle_prefix_route(uint32_t fibnum, int cmd,
- struct sockaddr_in *dst, struct sockaddr_in *netmask, struct ifaddr *ifa)
+ struct sockaddr_in *dst, struct sockaddr_in *netmask, struct ifaddr *ifa,
+ struct ifnet *ifp)
{
NET_EPOCH_ASSERT();
@@ -738,6 +738,7 @@
struct rt_addrinfo info = {
.rti_ifa = ifa,
+ .rti_ifp = ifp,
.rti_flags = RTF_PINNED | ((netmask != NULL) ? 0 : RTF_HOST),
.rti_info = {
[RTAX_DST] = (struct sockaddr *)dst,
@@ -752,6 +753,55 @@
return (rib_handle_ifaddr_info(fibnum, cmd, &info));
}
+static void
+ia_getrtprefix(const struct in_ifaddr *ia, struct in_addr *prefix, struct in_addr *mask)
+{
+
+ if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) {
+ *prefix = ia->ia_dstaddr.sin_addr;
+ mask->s_addr = INADDR_BROADCAST;
+ } else if (ia->ia_ifp->if_flags & IFF_LOOPBACK) {
+ *prefix = ia->ia_addr.sin_addr;
+ mask->s_addr = INADDR_BROADCAST;
+ } else {
+ *prefix = ia->ia_addr.sin_addr;
+ *mask = ia->ia_sockmask.sin_addr;
+ prefix->s_addr &= mask->s_addr;
+ }
+}
+
+/*
+ * Checks if @ia needs to have loopback route installed.
+ *
+ * Skip loopback interfaces - prefix route will be installed by
+ * in_handle_ifaddr_route().
+ * Skip p2p interfaces with both addresses are equal
+ * Skip empty addresses.
+ * Skip /32 masks - prefix will be installed by in_handle_ifaddr_route().
+ *
+ * Return true on success.
+ */
+static bool
+ia_need_loopback_route(const struct in_ifaddr *ia)
+{
+ struct ifnet *ifp = ia->ia_ifp;
+
+ if ((ifp->if_flags & IFF_LOOPBACK) ||
+ (ia->ia_addr.sin_addr.s_addr == INADDR_ANY))
+ return (false);
+
+ if ((ifp->if_flags & IFF_POINTOPOINT) &&
+ ia->ia_dstaddr.sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr)
+ return (false);
+
+ if (!(ifp->if_flags & IFF_POINTOPOINT) &&
+ (ia->ia_sockmask.sin_addr.s_addr == INADDR_BROADCAST))
+ return (false);
+
+ return (true);
+}
+
+
/*
* Adds or delete interface route corresponding to @ifa.
* There can be multiple options:
@@ -760,10 +810,8 @@
* 192.0.2.0/24 via this interface, using ifa as an address source.
* Note: route to 192.0.2.1 will be installed separately via
* ifa_maintain_loopback_route().
- * 2) Adding addr with "host" mask.
- * Example: 192.0.2.2/32. In this case no action is performed,
- * as the route should be installed by ifa_maintain_loopback_route().
- * Returns 0 to indicate success.
+ * 2) Adding addr with "host" mask to non-p2p interface.
+ * Example: 192.0.2.2/32. Action: add host route via loopback interface.
* 3) Adding address with or without prefix to p2p interface.
* Example: 10.0.0.1/24->10.0.0.2. In this case, all other addresses
* covered by prefix, does not make sense in the context of p2p link.
@@ -774,8 +822,10 @@
* 4) Adding address with or without prefix to loopback interface.
* Example: 192.0.2.1/24. In this case, trafic to non-host addresses cannot
* be forwarded, as it would introduce an infinite cycle.
- * Similar to (2), perform no action and return 0. Loopback route
- * will be installed by ifa_maintain_loopback_route().
+ * Action: install host route via ifa interface, using ia as an
+ * address source.
+ *
+ * Returns 0 on success or errno.
*/
int
in_handle_ifaddr_route(int cmd, struct in_ifaddr *ia)
@@ -786,25 +836,7 @@
struct epoch_tracker et;
int error;
- /* Case 4: ignore loopbacks */
- if (ifa->ifa_ifp->if_flags & IFF_LOOPBACK)
- return (0);
-
- if (ifa->ifa_ifp->if_flags & IFF_POINTOPOINT) {
- /* Case 3: install route towards dst addr */
- daddr = ia->ia_dstaddr.sin_addr;
- pmask = NULL;
- maddr.s_addr = INADDR_BROADCAST;
- } else {
- daddr = ia->ia_addr.sin_addr;
- pmask = &ia->ia_sockmask;
- maddr = pmask->sin_addr;
-
- if (maddr.s_addr == INADDR_BROADCAST) {
- /* Case 2: ignore /32 routes */
- return (0);
- }
- }
+ ia_getrtprefix(ia, &daddr, &maddr);
struct sockaddr_in mask = {
.sin_family = AF_INET,
@@ -812,8 +844,7 @@
.sin_addr = maddr,
};
- if (pmask != NULL)
- pmask = &mask;
+ pmask = (maddr.s_addr != INADDR_BROADCAST) ? &mask : NULL;
struct sockaddr_in dst = {
.sin_family = AF_INET,
@@ -821,56 +852,45 @@
.sin_addr.s_addr = daddr.s_addr & maddr.s_addr,
};
+ struct ifnet *ifp = ia->ia_ifp;
+
+ if ((maddr.s_addr == INADDR_BROADCAST) &&
+ (!(ia->ia_ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)))) {
+ /* Case 2: host route on broadcast interface */
+ ifp = V_loif;
+ }
+
uint32_t fibnum = ifa->ifa_ifp->if_fib;
NET_EPOCH_ENTER(et);
- error = in_handle_prefix_route(fibnum, cmd, &dst, pmask, ifa);
+ error = in_handle_prefix_route(fibnum, cmd, &dst, pmask, ifa, ifp);
NET_EPOCH_EXIT(et);
return (error);
}
-#define rtinitflags(x) \
- ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
- ? RTF_HOST : 0)
-
/*
* Check if we have a route for the given prefix already.
*/
static bool
-in_hasrtprefix(struct in_ifaddr *target, int flags)
+in_hasrtprefix(struct in_ifaddr *target)
{
struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
struct in_addr prefix, mask, p, m;
bool result = false;
- if ((flags & RTF_HOST) != 0) {
- prefix = target->ia_dstaddr.sin_addr;
- mask.s_addr = 0;
- } else {
- prefix = target->ia_addr.sin_addr;
- mask = target->ia_sockmask.sin_addr;
- prefix.s_addr &= mask.s_addr;
- }
+ ia_getrtprefix(target, &prefix, &mask);
IN_IFADDR_RLOCK(&in_ifa_tracker);
/* Look for an existing address with the same prefix, mask, and fib */
CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
- if (rtinitflags(ia)) {
- p = ia->ia_dstaddr.sin_addr;
+ ia_getrtprefix(ia, &p, &m);
- if (prefix.s_addr != p.s_addr)
- continue;
- } else {
- p = ia->ia_addr.sin_addr;
- m = ia->ia_sockmask.sin_addr;
- p.s_addr &= m.s_addr;
+ if (prefix.s_addr != p.s_addr ||
+ mask.s_addr != m.s_addr)
+ continue;
- if (prefix.s_addr != p.s_addr ||
- mask.s_addr != m.s_addr)
- continue;
- }
if (target->ia_ifp->if_fib != ia->ia_ifp->if_fib)
continue;
@@ -889,11 +909,11 @@
}
int
-in_addprefix(struct in_ifaddr *target, int flags)
+in_addprefix(struct in_ifaddr *target, int _unused)
{
int error;
- if (in_hasrtprefix(target, flags)) {
+ if (in_hasrtprefix(target)) {
if (V_nosameprefix)
return (EEXIST);
else {
@@ -967,9 +987,7 @@
/*
* Remove the loopback route to the interface address.
*/
- if ((target->ia_addr.sin_addr.s_addr != INADDR_ANY) &&
- !(target->ia_ifp->if_flags & IFF_LOOPBACK) &&
- (flags & LLE_STATIC)) {
+ if (ia_need_loopback_route(target) && (flags & LLE_STATIC)) {
struct in_ifaddr *eia;
/*
@@ -989,14 +1007,7 @@
}
}
- if (rtinitflags(target)) {
- prefix = target->ia_dstaddr.sin_addr;
- mask.s_addr = 0;
- } else {
- prefix = target->ia_addr.sin_addr;
- mask = target->ia_sockmask.sin_addr;
- prefix.s_addr &= mask.s_addr;
- }
+ ia_getrtprefix(target, &prefix, &mask);
if ((target->ia_flags & IFA_ROUTE) == 0) {
rt_addrmsg(RTM_DELETE, &target->ia_ifa, target->ia_ifp->if_fib);
@@ -1013,20 +1024,11 @@
IN_IFADDR_RLOCK(&in_ifa_tracker);
CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
- if (rtinitflags(ia)) {
- p = ia->ia_dstaddr.sin_addr;
-
- if (prefix.s_addr != p.s_addr)
- continue;
- } else {
- p = ia->ia_addr.sin_addr;
- m = ia->ia_sockmask.sin_addr;
- p.s_addr &= m.s_addr;
+ ia_getrtprefix(ia, &p, &m);
- if (prefix.s_addr != p.s_addr ||
- mask.s_addr != m.s_addr)
- continue;
- }
+ if (prefix.s_addr != p.s_addr ||
+ mask.s_addr != m.s_addr)
+ continue;
if ((ia->ia_ifp->if_flags & IFF_UP) == 0)
continue;
@@ -1077,8 +1079,6 @@
return (error);
}
-#undef rtinitflags
-
void
in_ifscrub_all(void)
{

File Metadata

Mime Type
text/plain
Expires
Fri, Jun 12, 5:43 AM (9 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33900711
Default Alt Text
D28246.id82595.diff (8 KB)

Event Timeline