Fix deletion of ifaddr lle entries when deleting prefix from interface in

down state.

Regression appeared in r287789, where the "prefix has no corresponding
  installed route" case was forgotten. Additionally, lltable_delete_addr()
  was called with incorrect byte order (default is network for lltable code).
While here, improve comments on given cases and byte order.

PR:		203573
Submitted by:	phk
This commit is contained in:
Alexander V. Chernikov 2015-10-18 12:26:25 +00:00
parent c0a598da45
commit 26a6057525
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=289501

View File

@ -734,14 +734,10 @@ in_scrubprefixlle(struct in_ifaddr *ia, int all, u_int flags)
struct sockaddr *saddr, *smask;
struct ifnet *ifp;
/*
* remove all L2 entries on the given prefix
*/
saddr = (struct sockaddr *)&addr;
bzero(&addr, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = ntohl(ia->ia_addr.sin_addr.s_addr);
smask = (struct sockaddr *)&mask;
bzero(&mask, sizeof(mask));
mask.sin_len = sizeof(mask);
@ -749,10 +745,21 @@ in_scrubprefixlle(struct in_ifaddr *ia, int all, u_int flags)
mask.sin_addr.s_addr = ia->ia_subnetmask;
ifp = ia->ia_ifp;
if (all)
if (all) {
/*
* Remove all L2 entries matching given prefix.
* Convert address to host representation to avoid
* doing this on every callback. ia_subnetmask is already
* stored in host representation.
*/
addr.sin_addr.s_addr = ntohl(ia->ia_addr.sin_addr.s_addr);
lltable_prefix_free(AF_INET, saddr, smask, flags);
else
} else {
/* Remove interface address only */
addr.sin_addr.s_addr = ia->ia_addr.sin_addr.s_addr;
lltable_delete_addr(LLTABLE(ifp), LLE_IFADDR, saddr);
}
}
/*
@ -808,6 +815,14 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS :
target->ia_ifp->if_fib;
rt_addrmsg(RTM_DELETE, &target->ia_ifa, fibnum);
/*
* Removing address from !IFF_UP interface or
* prefix which exists on other interface (along with route).
* No entries should exist here except target addr.
* Given that, delete this entry only.
*/
in_scrubprefixlle(target, 0, flags);
return (0);
}