Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/in.c
Show First 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | |||||
static int in_aifaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *); | static int in_aifaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *); | ||||
static int in_difaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *); | static int in_difaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *); | ||||
static int in_gifaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *); | static int in_gifaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *); | ||||
static void in_socktrim(struct sockaddr_in *); | static void in_socktrim(struct sockaddr_in *); | ||||
static void in_purgemaddrs(struct ifnet *); | static void in_purgemaddrs(struct ifnet *); | ||||
static bool ia_need_loopback_route(const struct in_ifaddr *); | |||||
VNET_DEFINE_STATIC(int, nosameprefix); | VNET_DEFINE_STATIC(int, nosameprefix); | ||||
#define V_nosameprefix VNET(nosameprefix) | #define V_nosameprefix VNET(nosameprefix) | ||||
SYSCTL_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_VNET | CTLFLAG_RW, | ||||
&VNET_NAME(nosameprefix), 0, | &VNET_NAME(nosameprefix), 0, | ||||
"Refuse to create same prefixes on different interfaces"); | "Refuse to create same prefixes on different interfaces"); | ||||
VNET_DECLARE(struct inpcbinfo, ripcbinfo); | VNET_DECLARE(struct inpcbinfo, ripcbinfo); | ||||
#define V_ripcbinfo VNET(ripcbinfo) | #define V_ripcbinfo VNET(ripcbinfo) | ||||
▲ Show 20 Lines • Show All 399 Lines • ▼ Show 20 Lines | if (vhid == 0) { | ||||
error = in_addprefix(ia, flags); | error = in_addprefix(ia, flags); | ||||
if (error) | if (error) | ||||
goto fail1; | goto fail1; | ||||
} | } | ||||
/* | /* | ||||
* Add a loopback route to self. | * Add a loopback route to self. | ||||
*/ | */ | ||||
if (vhid == 0 && (ifp->if_flags & IFF_LOOPBACK) == 0 && | if (vhid == 0 && ia_need_loopback_route(ia)) { | ||||
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)) { | |||||
struct in_ifaddr *eia; | struct in_ifaddr *eia; | ||||
eia = in_localip_more(ia); | eia = in_localip_more(ia); | ||||
if (eia == NULL) { | if (eia == NULL) { | ||||
error = ifa_add_loopback_route((struct ifaddr *)ia, | error = ifa_add_loopback_route((struct ifaddr *)ia, | ||||
(struct sockaddr *)&ia->ia_addr); | (struct sockaddr *)&ia->ia_addr); | ||||
if (error) | if (error) | ||||
▲ Show 20 Lines • Show All 209 Lines • ▼ Show 20 Lines | in_match_ifaddr(const struct rtentry *rt, const struct nhop_object *nh, void *arg) | ||||
if (nh->nh_ifa == (struct ifaddr *)arg) | if (nh->nh_ifa == (struct ifaddr *)arg) | ||||
return (1); | return (1); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
in_handle_prefix_route(uint32_t fibnum, int cmd, | 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(); | NET_EPOCH_ASSERT(); | ||||
/* Prepare gateway */ | /* Prepare gateway */ | ||||
struct sockaddr_dl_short sdl = { | struct sockaddr_dl_short sdl = { | ||||
.sdl_family = AF_LINK, | .sdl_family = AF_LINK, | ||||
.sdl_len = sizeof(struct sockaddr_dl_short), | .sdl_len = sizeof(struct sockaddr_dl_short), | ||||
.sdl_type = ifa->ifa_ifp->if_type, | .sdl_type = ifa->ifa_ifp->if_type, | ||||
.sdl_index = ifa->ifa_ifp->if_index, | .sdl_index = ifa->ifa_ifp->if_index, | ||||
}; | }; | ||||
struct rt_addrinfo info = { | struct rt_addrinfo info = { | ||||
.rti_ifa = ifa, | .rti_ifa = ifa, | ||||
.rti_ifp = ifp, | |||||
.rti_flags = RTF_PINNED | ((netmask != NULL) ? 0 : RTF_HOST), | .rti_flags = RTF_PINNED | ((netmask != NULL) ? 0 : RTF_HOST), | ||||
.rti_info = { | .rti_info = { | ||||
[RTAX_DST] = (struct sockaddr *)dst, | [RTAX_DST] = (struct sockaddr *)dst, | ||||
[RTAX_NETMASK] = (struct sockaddr *)netmask, | [RTAX_NETMASK] = (struct sockaddr *)netmask, | ||||
[RTAX_GATEWAY] = (struct sockaddr *)&sdl, | [RTAX_GATEWAY] = (struct sockaddr *)&sdl, | ||||
}, | }, | ||||
/* Ensure we delete the prefix IFF prefix ifa matches */ | /* Ensure we delete the prefix IFF prefix ifa matches */ | ||||
.rti_filter = in_match_ifaddr, | .rti_filter = in_match_ifaddr, | ||||
.rti_filterdata = ifa, | .rti_filterdata = ifa, | ||||
}; | }; | ||||
return (rib_handle_ifaddr_info(fibnum, cmd, &info)); | return (rib_handle_ifaddr_info(fibnum, cmd, &info)); | ||||
} | } | ||||
/* | /* | ||||
* 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: | * There can be multiple options: | ||||
donner: The comment is misleading. This function checks, if the IP address on the interface is singular… | |||||
Done Inline ActionsIndeed, there is a clash for the "loopback" term. We will always install some loopback route, the question is whether we install it via ifa_maintain_loopback_route() or not. Anyway, I've updated the description, hope it looks more clear now. melifaro: Indeed, there is a clash for the "loopback" term. We will always install some loopback route… | |||||
* 1) Adding addr with prefix on non-p2p/non-lo interface. | * 1) Adding address with prefix on non-p2p/non-loopback interface. | ||||
* Example: 192.0.2.1/24. Action: add route towards | * Example: 192.0.2.1/24. Action: | ||||
* 192.0.2.0/24 via this interface, using ifa as an address source. | * * add "prefix" route towards 192.0.2.0/24 via @ia interface, | ||||
* Note: route to 192.0.2.1 will be installed separately via | * using @ia as an address source. | ||||
* ifa_maintain_loopback_route(). | * * add "loopback" route towards 192.0.2.1 via V_loif, saving | ||||
* 2) Adding addr with "host" mask. | * @ia ifp in the gateway and using @ia as an address source. | ||||
* Example: 192.0.2.2/32. In this case no action is performed, | * | ||||
* as the route should be installed by ifa_maintain_loopback_route(). | * 2) Adding address with /32 mask to non-p2p/non-loopback interface. | ||||
* Returns 0 to indicate success. | * 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. | * 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 | * Example: 10.0.0.1/24->10.0.0.2. Action: | ||||
* covered by prefix, does not make sense in the context of p2p link. | * * add "prefix" host route towards 10.0.0.2 via this interface, using @ia | ||||
* Action: add route towards 10.0.0.2 via this interface, using ifa as an | * as an address source. Note: no sense in installing full /24 as the interface | ||||
* address source. | * is point-to-point. | ||||
* Similar to (1), route to 10.0.0.1 will be installed by | * * add "loopback" route towards 10.0.9.1 via V_loif, saving | ||||
* ifa_maintain_loopback_route(). | * @ia ifp in the gateway and using @ia as an address source. | ||||
* | |||||
* 4) Adding address with or without prefix to loopback interface. | * 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 | * Example: 192.0.2.1/24. Action: | ||||
* be forwarded, as it would introduce an infinite cycle. | * * add "prefix" host route via @ia interface, using @ia as an address source. | ||||
* Similar to (2), perform no action and return 0. Loopback route | * Note: Skip installing /24 prefix as it would introduce TTL loop | ||||
* will be installed by ifa_maintain_loopback_route(). | * 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 | int | ||||
in_handle_ifaddr_route(int cmd, struct in_ifaddr *ia) | in_handle_ifaddr_route(int cmd, struct in_ifaddr *ia) | ||||
{ | { | ||||
struct ifaddr *ifa = &ia->ia_ifa; | struct ifaddr *ifa = &ia->ia_ifa; | ||||
struct in_addr daddr, maddr; | struct in_addr daddr, maddr; | ||||
struct sockaddr_in *pmask; | struct sockaddr_in *pmask; | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
int error; | int error; | ||||
/* Case 4: ignore loopbacks */ | ia_getrtprefix(ia, &daddr, &maddr); | ||||
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); | |||||
} | |||||
} | |||||
struct sockaddr_in mask = { | struct sockaddr_in mask = { | ||||
.sin_family = AF_INET, | .sin_family = AF_INET, | ||||
.sin_len = sizeof(struct sockaddr_in), | .sin_len = sizeof(struct sockaddr_in), | ||||
.sin_addr = maddr, | .sin_addr = maddr, | ||||
}; | }; | ||||
if (pmask != NULL) | pmask = (maddr.s_addr != INADDR_BROADCAST) ? &mask : NULL; | ||||
pmask = &mask; | |||||
struct sockaddr_in dst = { | struct sockaddr_in dst = { | ||||
.sin_family = AF_INET, | .sin_family = AF_INET, | ||||
.sin_len = sizeof(struct sockaddr_in), | .sin_len = sizeof(struct sockaddr_in), | ||||
.sin_addr.s_addr = daddr.s_addr & maddr.s_addr, | .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; | uint32_t fibnum = ifa->ifa_ifp->if_fib; | ||||
NET_EPOCH_ENTER(et); | 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); | NET_EPOCH_EXIT(et); | ||||
return (error); | 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. | * Check if we have a route for the given prefix already. | ||||
*/ | */ | ||||
static bool | static bool | ||||
in_hasrtprefix(struct in_ifaddr *target, int flags) | in_hasrtprefix(struct in_ifaddr *target) | ||||
{ | { | ||||
struct rm_priotracker in_ifa_tracker; | struct rm_priotracker in_ifa_tracker; | ||||
struct in_ifaddr *ia; | struct in_ifaddr *ia; | ||||
struct in_addr prefix, mask, p, m; | struct in_addr prefix, mask, p, m; | ||||
bool result = false; | bool result = false; | ||||
if ((flags & RTF_HOST) != 0) { | ia_getrtprefix(target, &prefix, &mask); | ||||
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; | |||||
} | |||||
IN_IFADDR_RLOCK(&in_ifa_tracker); | IN_IFADDR_RLOCK(&in_ifa_tracker); | ||||
/* Look for an existing address with the same prefix, mask, and fib */ | /* Look for an existing address with the same prefix, mask, and fib */ | ||||
CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { | CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { | ||||
if (rtinitflags(ia)) { | ia_getrtprefix(ia, &p, &m); | ||||
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; | |||||
if (prefix.s_addr != p.s_addr || | if (prefix.s_addr != p.s_addr || | ||||
mask.s_addr != m.s_addr) | mask.s_addr != m.s_addr) | ||||
continue; | continue; | ||||
} | |||||
if (target->ia_ifp->if_fib != ia->ia_ifp->if_fib) | if (target->ia_ifp->if_fib != ia->ia_ifp->if_fib) | ||||
continue; | continue; | ||||
/* | /* | ||||
* If we got a matching prefix route inserted by other | * If we got a matching prefix route inserted by other | ||||
* interface address, we are done here. | * interface address, we are done here. | ||||
*/ | */ | ||||
if (ia->ia_flags & IFA_ROUTE) { | if (ia->ia_flags & IFA_ROUTE) { | ||||
result = true; | result = true; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
IN_IFADDR_RUNLOCK(&in_ifa_tracker); | IN_IFADDR_RUNLOCK(&in_ifa_tracker); | ||||
return (result); | return (result); | ||||
} | } | ||||
int | int | ||||
in_addprefix(struct in_ifaddr *target, int flags) | in_addprefix(struct in_ifaddr *target, int _unused) | ||||
{ | { | ||||
int error; | int error; | ||||
if (in_hasrtprefix(target, flags)) { | if (in_hasrtprefix(target)) { | ||||
if (V_nosameprefix) | if (V_nosameprefix) | ||||
return (EEXIST); | return (EEXIST); | ||||
else { | else { | ||||
rt_addrmsg(RTM_ADD, &target->ia_ifa, | rt_addrmsg(RTM_ADD, &target->ia_ifa, | ||||
target->ia_ifp->if_fib); | target->ia_ifp->if_fib); | ||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | in_scrubprefix(struct in_ifaddr *target, u_int flags) | ||||
struct rm_priotracker in_ifa_tracker; | struct rm_priotracker in_ifa_tracker; | ||||
struct in_ifaddr *ia; | struct in_ifaddr *ia; | ||||
struct in_addr prefix, mask, p, m; | struct in_addr prefix, mask, p, m; | ||||
int error = 0; | int error = 0; | ||||
/* | /* | ||||
* Remove the loopback route to the interface address. | * Remove the loopback route to the interface address. | ||||
*/ | */ | ||||
if ((target->ia_addr.sin_addr.s_addr != INADDR_ANY) && | if (ia_need_loopback_route(target) && (flags & LLE_STATIC)) { | ||||
!(target->ia_ifp->if_flags & IFF_LOOPBACK) && | |||||
(flags & LLE_STATIC)) { | |||||
struct in_ifaddr *eia; | struct in_ifaddr *eia; | ||||
/* | /* | ||||
* XXXME: add fib-aware in_localip. | * XXXME: add fib-aware in_localip. | ||||
* We definitely don't want to switch between | * We definitely don't want to switch between | ||||
* prefixes in different fibs. | * prefixes in different fibs. | ||||
*/ | */ | ||||
eia = in_localip_more(target); | eia = in_localip_more(target); | ||||
if (eia != NULL) { | if (eia != NULL) { | ||||
error = ifa_switch_loopback_route((struct ifaddr *)eia, | error = ifa_switch_loopback_route((struct ifaddr *)eia, | ||||
(struct sockaddr *)&target->ia_addr); | (struct sockaddr *)&target->ia_addr); | ||||
ifa_free(&eia->ia_ifa); | ifa_free(&eia->ia_ifa); | ||||
} else { | } else { | ||||
error = ifa_del_loopback_route((struct ifaddr *)target, | error = ifa_del_loopback_route((struct ifaddr *)target, | ||||
(struct sockaddr *)&target->ia_addr); | (struct sockaddr *)&target->ia_addr); | ||||
} | } | ||||
} | } | ||||
if (rtinitflags(target)) { | ia_getrtprefix(target, &prefix, &mask); | ||||
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; | |||||
} | |||||
if ((target->ia_flags & IFA_ROUTE) == 0) { | if ((target->ia_flags & IFA_ROUTE) == 0) { | ||||
rt_addrmsg(RTM_DELETE, &target->ia_ifa, target->ia_ifp->if_fib); | rt_addrmsg(RTM_DELETE, &target->ia_ifa, target->ia_ifp->if_fib); | ||||
/* | /* | ||||
* Removing address from !IFF_UP interface or | * Removing address from !IFF_UP interface or | ||||
* prefix which exists on other interface (along with route). | * prefix which exists on other interface (along with route). | ||||
* No entries should exist here except target addr. | * No entries should exist here except target addr. | ||||
* Given that, delete this entry only. | * Given that, delete this entry only. | ||||
*/ | */ | ||||
in_scrubprefixlle(target, 0, flags); | in_scrubprefixlle(target, 0, flags); | ||||
return (0); | return (0); | ||||
} | } | ||||
IN_IFADDR_RLOCK(&in_ifa_tracker); | IN_IFADDR_RLOCK(&in_ifa_tracker); | ||||
CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { | CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { | ||||
if (rtinitflags(ia)) { | ia_getrtprefix(ia, &p, &m); | ||||
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; | |||||
if (prefix.s_addr != p.s_addr || | if (prefix.s_addr != p.s_addr || | ||||
mask.s_addr != m.s_addr) | mask.s_addr != m.s_addr) | ||||
continue; | continue; | ||||
} | |||||
if ((ia->ia_ifp->if_flags & IFF_UP) == 0) | if ((ia->ia_ifp->if_flags & IFF_UP) == 0) | ||||
continue; | continue; | ||||
/* | /* | ||||
* If we got a matching prefix address, move IFA_ROUTE and | * If we got a matching prefix address, move IFA_ROUTE and | ||||
* the route itself to it. Make sure that routing daemons | * the route itself to it. Make sure that routing daemons | ||||
* get a heads-up. | * get a heads-up. | ||||
Show All 33 Lines | in_scrubprefix(struct in_ifaddr *target, u_int flags) | ||||
rt_addrmsg(RTM_DELETE, &target->ia_ifa, target->ia_ifp->if_fib); | rt_addrmsg(RTM_DELETE, &target->ia_ifa, target->ia_ifp->if_fib); | ||||
error = in_handle_ifaddr_route(RTM_DELETE, target); | error = in_handle_ifaddr_route(RTM_DELETE, target); | ||||
if (error == 0) | if (error == 0) | ||||
target->ia_flags &= ~IFA_ROUTE; | target->ia_flags &= ~IFA_ROUTE; | ||||
else | else | ||||
log(LOG_INFO, "in_scrubprefix: err=%d, prefix delete failed\n", error); | log(LOG_INFO, "in_scrubprefix: err=%d, prefix delete failed\n", error); | ||||
return (error); | return (error); | ||||
} | } | ||||
#undef rtinitflags | |||||
void | void | ||||
in_ifscrub_all(void) | in_ifscrub_all(void) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct ifaddr *ifa, *nifa; | struct ifaddr *ifa, *nifa; | ||||
struct ifaliasreq ifr; | struct ifaliasreq ifr; | ||||
▲ Show 20 Lines • Show All 606 Lines • Show Last 20 Lines |
The comment is misleading. This function checks, if the IP address on the interface is singular enough to add an additional loopback route for the local host in the attached network,
Of course, all excluded cases do need a loopback route, too. But not an extra one,