Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F159166077
D28246.id82655.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D28246.id82655.diff
View Options
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,
@@ -753,29 +754,105 @@
}
/*
- * Adds or delete interface route corresponding to @ifa.
+ * Routing table interaction with interface addresses.
+ *
+ * In general, two types of routes needs to be installed:
+ * a) "interface" or "prefix" route, telling user that the addresses
+ * behind the ifa prefix are reached directly.
+ * b) "loopback" route installed for the ifa address, telling user that
+ * the address belongs to local system.
+ *
+ * Handling for (a) and (b) differs in multi-fib aspects, hence they
+ * are implemented in different functions below.
+ *
+ * The cases above may intersect - /32 interface aliases results in
+ * the same prefix produced by (a) and (b). This blurs the definition
+ * of the "loopback" route and complicate interactions. The interaction
+ * table is defined below. The case numbers are used in the multiple
+ * functions below to refer to the particular test case.
+ *
* There can be multiple options:
- * 1) Adding addr with prefix on non-p2p/non-lo interface.
- * Example: 192.0.2.1/24. Action: add route towards
- * 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.
+ * 1) Adding address with prefix on non-p2p/non-loopback interface.
+ * Example: 192.0.2.1/24. Action:
+ * * add "prefix" route towards 192.0.2.0/24 via @ia interface,
+ * using @ia as an address source.
+ * * add "loopback" route towards 192.0.2.1 via V_loif, saving
+ * @ia ifp in the gateway and using @ia as an address source.
+ *
+ * 2) Adding address with /32 mask to non-p2p/non-loopback interface.
+ * Example: 192.0.2.2/32. Action:
+ * * add "prefix" host route via V_loif, using @ia as an address source.
+ *
* 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.
- * Action: add route towards 10.0.0.2 via this interface, using ifa as an
- * address source.
- * Similar to (1), route to 10.0.0.1 will be installed by
- * ifa_maintain_loopback_route().
+ * Example: 10.0.0.1/24->10.0.0.2. Action:
+ * * add "prefix" host route towards 10.0.0.2 via this interface, using @ia
+ * as an address source. Note: no sense in installing full /24 as the interface
+ * is point-to-point.
+ * * add "loopback" route towards 10.0.9.1 via V_loif, saving
+ * @ia ifp in the gateway and using @ia as an address source.
+ *
* 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().
+ * Example: 192.0.2.1/24. Action:
+ * * add "prefix" host route via @ia interface, using @ia as an address source.
+ * Note: Skip installing /24 prefix as it would introduce TTL loop
+ * for the traffic destined to these addresses.
+ */
+
+/*
+ * Checks if @ia needs to install loopback route to @ia address via
+ * ifa_maintain_loopback_route().
+ *
+ * Return true on success.
+ */
+static bool
+ia_need_loopback_route(const struct in_ifaddr *ia)
+{
+ struct ifnet *ifp = ia->ia_ifp;
+
+ /* Case 4: Skip loopback interfaces */
+ if ((ifp->if_flags & IFF_LOOPBACK) ||
+ (ia->ia_addr.sin_addr.s_addr == INADDR_ANY))
+ return (false);
+
+ /* Clash avoidance: Skip p2p interfaces with both addresses are equal */
+ if ((ifp->if_flags & IFF_POINTOPOINT) &&
+ ia->ia_dstaddr.sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr)
+ return (false);
+
+ /* Case 2: skip /32 prefixes */
+ if (!(ifp->if_flags & IFF_POINTOPOINT) &&
+ (ia->ia_sockmask.sin_addr.s_addr == INADDR_BROADCAST))
+ return (false);
+
+ return (true);
+}
+
+/*
+ * Calculate "prefix" route corresponding to @ia.
+ */
+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) {
+ /* Case 3: return host route for dstaddr */
+ *prefix = ia->ia_dstaddr.sin_addr;
+ mask->s_addr = INADDR_BROADCAST;
+ } else if (ia->ia_ifp->if_flags & IFF_LOOPBACK) {
+ /* Case 4: return host route for ifaddr */
+ *prefix = ia->ia_addr.sin_addr;
+ mask->s_addr = INADDR_BROADCAST;
+ } else {
+ /* Cases 1,2: return actual ia prefix */
+ *prefix = ia->ia_addr.sin_addr;
+ *mask = ia->ia_sockmask.sin_addr;
+ prefix->s_addr &= mask->s_addr;
+ }
+}
+
+/*
+ * Adds or delete interface "prefix" route corresponding to @ifa.
+ * Returns 0 on success or errno.
*/
int
in_handle_ifaddr_route(int cmd, struct in_ifaddr *ia)
@@ -786,25 +863,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 +871,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 +879,44 @@
.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 +935,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 +1013,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 +1033,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 +1050,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;
+ 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 ((ia->ia_ifp->if_flags & IFF_UP) == 0)
continue;
@@ -1077,8 +1105,6 @@
return (error);
}
-#undef rtinitflags
-
void
in_ifscrub_all(void)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jun 11, 8:33 PM (4 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33889988
Default Alt Text
D28246.id82655.diff (10 KB)
Attached To
Mode
D28246: Further refactor IPv4 interface route creation.
Attached
Detach File
Event Timeline
Log In to Comment