mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2025-01-01 00:18:15 +01:00
When an interface address is removed and the last prefix
route is also being deleted, the link-layer address table (arp or nd6) will flush those L2 llinfo entries that match the removed prefix. Reviewed by: kmacy
This commit is contained in:
parent
f6ac50113f
commit
c9d763bf41
@ -195,6 +195,23 @@ lltable_drain(int af)
|
||||
IFNET_RUNLOCK();
|
||||
}
|
||||
|
||||
void
|
||||
lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask)
|
||||
{
|
||||
struct lltable *llt;
|
||||
|
||||
IFNET_RLOCK();
|
||||
SLIST_FOREACH(llt, &lltables, llt_link) {
|
||||
if (llt->llt_af != af)
|
||||
continue;
|
||||
|
||||
llt->llt_prefix_free(llt, prefix, mask);
|
||||
}
|
||||
IFNET_RUNLOCK();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Create a new lltable.
|
||||
*/
|
||||
|
@ -147,6 +147,9 @@ struct lltable {
|
||||
|
||||
struct llentry * (*llt_new)(const struct sockaddr *, u_int);
|
||||
void (*llt_free)(struct lltable *, struct llentry *);
|
||||
void (*llt_prefix_free)(struct lltable *,
|
||||
const struct sockaddr *prefix,
|
||||
const struct sockaddr *mask);
|
||||
struct llentry * (*llt_lookup)(struct lltable *, u_int flags,
|
||||
const struct sockaddr *l3addr);
|
||||
int (*llt_rtcheck)(struct ifnet *,
|
||||
@ -174,6 +177,8 @@ MALLOC_DECLARE(M_LLTABLE);
|
||||
|
||||
struct lltable *lltable_init(struct ifnet *, int);
|
||||
void lltable_free(struct lltable *);
|
||||
void lltable_prefix_free(int, struct sockaddr *,
|
||||
struct sockaddr *);
|
||||
void lltable_drain(int);
|
||||
int lltable_sysctl_dumparp(int, struct sysctl_req *);
|
||||
|
||||
|
@ -1013,6 +1013,7 @@ in_scrubprefix(struct in_ifaddr *target)
|
||||
struct in_ifaddr *ia;
|
||||
struct in_addr prefix, mask, p;
|
||||
int error;
|
||||
struct sockaddr_in prefix0, mask0;
|
||||
struct rt_addrinfo info;
|
||||
struct sockaddr_dl null_sdl;
|
||||
|
||||
@ -1081,6 +1082,20 @@ in_scrubprefix(struct in_ifaddr *target)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* remove all L2 entries on the given prefix
|
||||
*/
|
||||
bzero(&prefix0, sizeof(prefix0));
|
||||
prefix0.sin_len = sizeof(prefix0);
|
||||
prefix0.sin_family = AF_INET;
|
||||
prefix0.sin_addr.s_addr = target->ia_subnet;
|
||||
bzero(&mask0, sizeof(mask0));
|
||||
mask0.sin_len = sizeof(mask0);
|
||||
mask0.sin_family = AF_INET;
|
||||
mask0.sin_addr.s_addr = target->ia_subnetmask;
|
||||
lltable_prefix_free(AF_INET, (struct sockaddr *)&prefix0,
|
||||
(struct sockaddr *)&mask0);
|
||||
|
||||
/*
|
||||
* As no-one seem to have this prefix, we can remove the route.
|
||||
*/
|
||||
@ -1232,6 +1247,34 @@ in_lltable_free(struct lltable *llt, struct llentry *lle)
|
||||
free(lle, M_LLTABLE);
|
||||
}
|
||||
|
||||
|
||||
#define IN_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \
|
||||
(((ntohl((d)->sin_addr.s_addr) ^ (a)->sin_addr.s_addr) & (m)->sin_addr.s_addr)) == 0 )
|
||||
|
||||
static void
|
||||
in_lltable_prefix_free(struct lltable *llt,
|
||||
const struct sockaddr *prefix,
|
||||
const struct sockaddr *mask)
|
||||
{
|
||||
const struct sockaddr_in *pfx = (const struct sockaddr_in *)prefix;
|
||||
const struct sockaddr_in *msk = (const struct sockaddr_in *)mask;
|
||||
struct llentry *lle, *next;
|
||||
register int i;
|
||||
|
||||
for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
|
||||
LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
|
||||
|
||||
if (IN_ARE_MASKED_ADDR_EQUAL((struct sockaddr_in *)L3_ADDR(lle),
|
||||
pfx, msk)) {
|
||||
callout_drain(&lle->la_timer);
|
||||
LLE_WLOCK(lle);
|
||||
llentry_free(lle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
in_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
|
||||
{
|
||||
@ -1422,6 +1465,7 @@ in_domifattach(struct ifnet *ifp)
|
||||
if (llt != NULL) {
|
||||
llt->llt_new = in_lltable_new;
|
||||
llt->llt_free = in_lltable_free;
|
||||
llt->llt_prefix_free = in_lltable_prefix_free;
|
||||
llt->llt_rtcheck = in_lltable_rtcheck;
|
||||
llt->llt_lookup = in_lltable_lookup;
|
||||
llt->llt_dump = in_lltable_dump;
|
||||
|
@ -2284,6 +2284,30 @@ in6_lltable_free(struct lltable *llt, struct llentry *lle)
|
||||
free(lle, M_LLTABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
in6_lltable_prefix_free(struct lltable *llt,
|
||||
const struct sockaddr *prefix,
|
||||
const struct sockaddr *mask)
|
||||
{
|
||||
const struct sockaddr_in6 *pfx = (const struct sockaddr_in6 *)prefix;
|
||||
const struct sockaddr_in6 *msk = (const struct sockaddr_in6 *)mask;
|
||||
struct llentry *lle, *next;
|
||||
register int i;
|
||||
|
||||
for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
|
||||
LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
|
||||
if (IN6_ARE_MASKED_ADDR_EQUAL(
|
||||
&((struct sockaddr_in6 *)L3_ADDR(lle))->sin6_addr,
|
||||
&pfx->sin6_addr,
|
||||
&msk->sin6_addr)) {
|
||||
callout_drain(&lle->la_timer);
|
||||
LLE_WLOCK(lle);
|
||||
llentry_free(lle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
in6_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
|
||||
{
|
||||
@ -2490,6 +2514,7 @@ in6_domifattach(struct ifnet *ifp)
|
||||
if (ext->lltable != NULL) {
|
||||
ext->lltable->llt_new = in6_lltable_new;
|
||||
ext->lltable->llt_free = in6_lltable_free;
|
||||
ext->lltable->llt_prefix_free = in6_lltable_prefix_free;
|
||||
ext->lltable->llt_rtcheck = in6_lltable_rtcheck;
|
||||
ext->lltable->llt_lookup = in6_lltable_lookup;
|
||||
ext->lltable->llt_dump = in6_lltable_dump;
|
||||
|
Loading…
Reference in New Issue
Block a user