Simplify lle lookup/create api by using addresses instead of sockaddrs.
This commit is contained in:
parent
73b52ad896
commit
d82ed5051c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/routing/; revision=275625
@ -229,9 +229,12 @@ llentry_alloc(struct ifnet *ifp, struct lltable *lt,
|
||||
struct sockaddr_storage *dst)
|
||||
{
|
||||
struct llentry *la;
|
||||
const void *l3addr;
|
||||
|
||||
l3addr = lt->llt_get_sa_addr((struct sockaddr *)dst);
|
||||
|
||||
IF_AFDATA_RLOCK(ifp);
|
||||
la = lt->llt_lookup(lt, LLE_EXCLUSIVE, (struct sockaddr *)dst);
|
||||
la = lt->llt_lookup(lt, LLE_EXCLUSIVE, l3addr);
|
||||
IF_AFDATA_RUNLOCK(ifp);
|
||||
if ((la == NULL) &&
|
||||
(ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
|
||||
@ -441,6 +444,7 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
|
||||
struct ifnet *ifp;
|
||||
struct lltable *llt;
|
||||
struct llentry *lle, *lle_tmp;
|
||||
const void *l3addr;
|
||||
u_int laflags = 0;
|
||||
int error;
|
||||
|
||||
@ -469,6 +473,7 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
|
||||
switch (rtm->rtm_type) {
|
||||
case RTM_ADD:
|
||||
/* Add static LLE */
|
||||
l3addr = llt->llt_get_sa_addr(dst);
|
||||
lle = llt->llt_create(llt, 0, dst);
|
||||
if (lle == NULL)
|
||||
return (ENOMEM);
|
||||
@ -491,7 +496,7 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
|
||||
LLE_WLOCK(lle);
|
||||
/* Check if we already have this lle */
|
||||
/* XXX: Use LLE_UNLOCKED */
|
||||
lle_tmp = llt->llt_lookup(llt, LLE_EXCLUSIVE, dst);
|
||||
lle_tmp = llt->llt_lookup(llt, LLE_EXCLUSIVE, l3addr);
|
||||
if (lle_tmp != NULL) {
|
||||
IF_AFDATA_CFG_WUNLOCK(ifp);
|
||||
LLE_WUNLOCK(lle_tmp);
|
||||
|
@ -148,9 +148,9 @@ struct llentry {
|
||||
#endif
|
||||
|
||||
typedef struct llentry *(llt_lookup_t)(struct lltable *, u_int flags,
|
||||
const struct sockaddr *l3addr);
|
||||
const void *paddr);
|
||||
typedef struct llentry *(llt_create_t)(struct lltable *, u_int flags,
|
||||
const struct sockaddr *l3addr);
|
||||
const void *paddr);
|
||||
typedef int (llt_delete_addr_t)(struct lltable *, u_int flags,
|
||||
const struct sockaddr *l3addr);
|
||||
typedef int (llt_dump_entry_t)(struct lltable *, struct llentry *,
|
||||
@ -164,6 +164,7 @@ typedef void (llt_link_entry_t)(struct lltable *, struct llentry *);
|
||||
typedef void (llt_unlink_entry_t)(struct llentry *);
|
||||
typedef int (llt_prepare_sentry_t)(struct lltable *, struct llentry *,
|
||||
struct rt_addrinfo *);
|
||||
typedef const void *(llt_get_sa_addr_t)(const struct sockaddr *l3addr);
|
||||
|
||||
typedef int (llt_foreach_cb_t)(struct lltable *, struct llentry *, void *);
|
||||
typedef int (llt_foreach_entry_t)(struct lltable *, llt_foreach_cb_t *, void *);
|
||||
@ -186,6 +187,7 @@ struct lltable {
|
||||
llt_link_entry_t *llt_link_entry;
|
||||
llt_unlink_entry_t *llt_unlink_entry;
|
||||
llt_prepare_sentry_t *llt_prepare_static_entry;
|
||||
llt_get_sa_addr_t *llt_get_sa_addr;
|
||||
llt_free_tbl_t *llt_free_tbl;
|
||||
};
|
||||
|
||||
@ -233,18 +235,18 @@ size_t lltable_drop_entry_queue(struct llentry *);
|
||||
*/
|
||||
static __inline struct llentry *
|
||||
lltable_lookup_lle(struct lltable *llt, u_int flags,
|
||||
const struct sockaddr *l3addr)
|
||||
const void *paddr)
|
||||
{
|
||||
|
||||
return llt->llt_lookup(llt, flags, l3addr);
|
||||
return (llt->llt_lookup(llt, flags, paddr));
|
||||
}
|
||||
|
||||
static __inline struct llentry *
|
||||
lltable_create_lle(struct lltable *llt, u_int flags,
|
||||
const struct sockaddr *l3addr)
|
||||
const void *paddr)
|
||||
{
|
||||
|
||||
return llt->llt_create(llt, flags, l3addr);
|
||||
return (llt->llt_create(llt, flags, paddr));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
|
@ -680,7 +680,6 @@ fib6_storelladdr(struct ifnet *ifp, struct in6_addr *dst, int mm_flags,
|
||||
u_char *desten)
|
||||
{
|
||||
struct llentry *ln;
|
||||
struct sockaddr_in6 dst_sa;
|
||||
IF_AFDATA_RUN_TRACKER;
|
||||
|
||||
if (mm_flags & M_MCAST) {
|
||||
@ -688,19 +687,11 @@ fib6_storelladdr(struct ifnet *ifp, struct in6_addr *dst, int mm_flags,
|
||||
return (0);
|
||||
}
|
||||
|
||||
memset(&dst_sa, 0, sizeof(dst_sa));
|
||||
dst_sa.sin6_family = AF_INET6;
|
||||
dst_sa.sin6_len = sizeof(dst_sa);
|
||||
dst_sa.sin6_addr = *dst;
|
||||
dst_sa.sin6_scope_id = ifp->if_index;
|
||||
|
||||
|
||||
/*
|
||||
* the entry should have been created in nd6_store_lladdr
|
||||
*/
|
||||
IF_AFDATA_RUN_RLOCK(ifp);
|
||||
ln = lltable_lookup_lle(LLTABLE6(ifp), LLE_UNLOCKED,
|
||||
(struct sockaddr *)&dst_sa);
|
||||
ln = lltable_lookup_lle6(ifp, LLE_UNLOCKED, dst);
|
||||
|
||||
/*
|
||||
* Perform fast path for the following cases:
|
||||
|
@ -417,8 +417,6 @@ arpresolve_fast(struct ifnet *ifp, struct in_addr dst, u_int mflags,
|
||||
u_char *dst_addr)
|
||||
{
|
||||
struct llentry *la;
|
||||
struct sockaddr_in sin;
|
||||
const struct sockaddr *sa_dst;
|
||||
IF_AFDATA_RUN_TRACKER;
|
||||
|
||||
if (mflags & M_BCAST) {
|
||||
@ -430,14 +428,8 @@ arpresolve_fast(struct ifnet *ifp, struct in_addr dst, u_int mflags,
|
||||
return (0);
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_addr = dst;
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_len = sizeof(sin);
|
||||
sa_dst = (const struct sockaddr *)&sin;
|
||||
|
||||
IF_AFDATA_RUN_RLOCK(ifp);
|
||||
la = lltable_lookup_lle(LLTABLE(ifp), LLE_UNLOCKED, sa_dst);
|
||||
la = lltable_lookup_lle4(ifp, LLE_UNLOCKED, &dst);
|
||||
if (la != NULL && (la->r_flags & RLLE_VALID) != 0) {
|
||||
/* Entry found, let's copy lle info */
|
||||
bcopy(&la->ll_addr, dst_addr, ifp->if_addrlen);
|
||||
@ -503,9 +495,12 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
|
||||
const struct sockaddr *dst, u_char *desten, struct llentry **lle)
|
||||
{
|
||||
struct llentry *la = NULL;
|
||||
struct in_addr dst4;
|
||||
int is_gw;
|
||||
IF_AFDATA_RUN_TRACKER;
|
||||
|
||||
dst4 = SIN(dst)->sin_addr;
|
||||
|
||||
*lle = NULL;
|
||||
if (m != NULL) {
|
||||
if (m->m_flags & M_BCAST) {
|
||||
@ -516,13 +511,13 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
|
||||
}
|
||||
if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) {
|
||||
/* multicast */
|
||||
ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
|
||||
ETHER_MAP_IP_MULTICAST(&dst4, desten);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
IF_AFDATA_RUN_RLOCK(ifp);
|
||||
la = lltable_lookup_lle(LLTABLE(ifp), LLE_UNLOCKED, dst);
|
||||
la = lltable_lookup_lle4(ifp, LLE_UNLOCKED, &dst4);
|
||||
if (la != NULL && (la->r_flags & RLLE_VALID) != 0) {
|
||||
/* Entry found, let's copy lle info */
|
||||
bcopy(&la->ll_addr, desten, ifp->if_addrlen);
|
||||
@ -545,22 +540,23 @@ arpresolve_slow(struct ifnet *ifp, int is_gw, struct mbuf *m,
|
||||
struct llentry *la, *la_tmp;
|
||||
struct mbuf *curr = NULL;
|
||||
struct mbuf *next = NULL;
|
||||
struct in_addr dst4;
|
||||
int create, error;
|
||||
|
||||
create = 0;
|
||||
*lle = NULL;
|
||||
dst4 = SIN(dst)->sin_addr;
|
||||
|
||||
IF_AFDATA_RLOCK(ifp);
|
||||
la = lltable_lookup_lle(LLTABLE(ifp), LLE_EXCLUSIVE, dst);
|
||||
la = lltable_lookup_lle4(ifp, LLE_EXCLUSIVE, &dst4);
|
||||
IF_AFDATA_RUNLOCK(ifp);
|
||||
if (la == NULL && (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
|
||||
create = 1;
|
||||
la = lltable_create_lle(LLTABLE(ifp), 0, dst);
|
||||
la = lltable_create_lle4(ifp, 0, &dst4);
|
||||
if (la != NULL) {
|
||||
IF_AFDATA_CFG_WLOCK(ifp);
|
||||
LLE_WLOCK(la);
|
||||
la_tmp = lltable_lookup_lle(LLTABLE(ifp), LLE_EXCLUSIVE,
|
||||
dst);
|
||||
la_tmp = lltable_lookup_lle4(ifp, LLE_EXCLUSIVE, &dst4);
|
||||
if (la_tmp == NULL) {
|
||||
/*
|
||||
* No entry has been found. Link new one.
|
||||
@ -582,7 +578,7 @@ arpresolve_slow(struct ifnet *ifp, int is_gw, struct mbuf *m,
|
||||
if (create != 0)
|
||||
log(LOG_DEBUG,
|
||||
"arpresolve: can't allocate llinfo for %s on %s\n",
|
||||
inet_ntoa(SIN(dst)->sin_addr), ifp->if_xname);
|
||||
inet_ntoa(dst4), ifp->if_xname);
|
||||
m_freem(m);
|
||||
return (EINVAL);
|
||||
}
|
||||
@ -781,13 +777,8 @@ in_arpinput(struct mbuf *m)
|
||||
int bridged = 0, is_bridge = 0;
|
||||
int carped;
|
||||
struct nhop4_extended nh_ext;
|
||||
struct sockaddr_in sin;
|
||||
struct llentry *la_tmp;
|
||||
|
||||
sin.sin_len = sizeof(struct sockaddr_in);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = 0;
|
||||
|
||||
if (ifp->if_bridge)
|
||||
bridged = 1;
|
||||
if (ifp->if_type == IFT_BRIDGE)
|
||||
@ -938,14 +929,8 @@ in_arpinput(struct mbuf *m)
|
||||
if (ifp->if_flags & IFF_STATICARP)
|
||||
goto reply;
|
||||
|
||||
bzero(&sin, sizeof(sin));
|
||||
sin.sin_len = sizeof(struct sockaddr_in);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr = isaddr;
|
||||
|
||||
IF_AFDATA_CFG_RLOCK(ifp);
|
||||
la = lltable_lookup_lle(LLTABLE(ifp), LLE_EXCLUSIVE,
|
||||
(struct sockaddr *)&sin);
|
||||
la = lltable_lookup_lle4(ifp, LLE_EXCLUSIVE, &isaddr);
|
||||
IF_AFDATA_CFG_RUNLOCK(ifp);
|
||||
if (la != NULL)
|
||||
arp_update_lle(ah, isaddr, ifp, bridged, la);
|
||||
@ -955,14 +940,12 @@ in_arpinput(struct mbuf *m)
|
||||
* Reply to our address, but no lle exists yet.
|
||||
* do we really have to create an entry?
|
||||
*/
|
||||
la = lltable_create_lle(LLTABLE(ifp), 0,
|
||||
(struct sockaddr *)&sin);
|
||||
la = lltable_create_lle4(ifp, 0, &isaddr);
|
||||
if (la != NULL) {
|
||||
IF_AFDATA_CFG_WLOCK(ifp);
|
||||
LLE_WLOCK(la);
|
||||
/* Let's try to search another time */
|
||||
la_tmp = lltable_lookup_lle(LLTABLE(ifp), LLE_EXCLUSIVE,
|
||||
(struct sockaddr *)&sin);
|
||||
la_tmp = lltable_lookup_lle4(ifp, LLE_EXCLUSIVE, &isaddr);
|
||||
if (la_tmp != NULL) {
|
||||
/*
|
||||
* Someone has already inserted another entry.
|
||||
@ -995,10 +978,8 @@ in_arpinput(struct mbuf *m)
|
||||
} else {
|
||||
struct llentry *lle = NULL;
|
||||
|
||||
sin.sin_addr = itaddr;
|
||||
IF_AFDATA_RLOCK(ifp);
|
||||
lle = lltable_lookup_lle(LLTABLE(ifp), 0,
|
||||
(struct sockaddr *)&sin);
|
||||
lle = lltable_lookup_lle4(ifp, 0, &itaddr);
|
||||
IF_AFDATA_RUNLOCK(ifp);
|
||||
|
||||
if ((lle != NULL) && (lle->la_flags & LLE_PUB)) {
|
||||
@ -1013,7 +994,6 @@ in_arpinput(struct mbuf *m)
|
||||
if (!V_arp_proxyall)
|
||||
goto drop;
|
||||
|
||||
sin.sin_addr = itaddr;
|
||||
/* XXX MRT use table 0 for arp reply */
|
||||
if (fib4_lookup_nh_ext(0, itaddr, 0, 0, &nh_ext) != 0)
|
||||
goto drop;
|
||||
@ -1035,7 +1015,6 @@ in_arpinput(struct mbuf *m)
|
||||
* avoids ARP chaos if an interface is connected to the
|
||||
* wrong network.
|
||||
*/
|
||||
sin.sin_addr = isaddr;
|
||||
|
||||
/* XXX MRT use table 0 for arp checks */
|
||||
if (fib4_lookup_nh_ext(0, isaddr, 0, 0, &nh_ext) != 0)
|
||||
@ -1252,8 +1231,7 @@ arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
|
||||
* because the output of the arp utility shows
|
||||
* that L2 entry as permanent
|
||||
*/
|
||||
lle = lltable_create_lle(LLTABLE(ifp), LLE_IFADDR | LLE_STATIC,
|
||||
(struct sockaddr *)IA_SIN(ifa));
|
||||
lle = lltable_create_lle4(ifp, LLE_IFADDR | LLE_STATIC, &addr);
|
||||
if (lle == NULL) {
|
||||
log(LOG_INFO, "arp_ifinit: cannot create arp "
|
||||
"entry for interface address\n");
|
||||
@ -1271,8 +1249,7 @@ arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
|
||||
* Instead of dealing with callouts/flags/etc we simply
|
||||
* delete it and add new one.
|
||||
*/
|
||||
lle_tmp = lltable_lookup_lle(llt, LLE_EXCLUSIVE,
|
||||
(struct sockaddr *)IA_SIN(ifa));
|
||||
lle_tmp = lltable_lookup_lle4(ifp, LLE_EXCLUSIVE, &addr);
|
||||
|
||||
IF_AFDATA_RUN_WLOCK(ifp);
|
||||
if (lle_tmp != NULL)
|
||||
|
@ -117,6 +117,21 @@ struct llentry;
|
||||
struct ifaddr;
|
||||
struct rt_addrinfo;
|
||||
|
||||
#define LLTABLE(ifp) \
|
||||
((struct in_ifinfo *)(ifp)->if_afdata[AF_INET])->ii_llt
|
||||
|
||||
static __inline const void *
|
||||
_check_in_addr_typecast(const struct in_addr *paddr)
|
||||
{
|
||||
|
||||
return ((const void *)paddr);
|
||||
}
|
||||
|
||||
#define lltable_lookup_lle4(i, f, a) \
|
||||
lltable_lookup_lle(LLTABLE(i), (f), _check_in_addr_typecast(a))
|
||||
#define lltable_create_lle4(i, f, a) \
|
||||
lltable_create_lle(LLTABLE(i), (f), _check_in_addr_typecast(a))
|
||||
|
||||
int arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m,
|
||||
const struct sockaddr *dst, u_char *desten, struct llentry **lle);
|
||||
int arpresolve_fast(struct ifnet *ifp, struct in_addr dst, u_int mflags,
|
||||
|
@ -1009,18 +1009,19 @@ in_lltable_free(struct llentry *lle)
|
||||
}
|
||||
|
||||
static struct llentry *
|
||||
in_lltable_new(const struct sockaddr *l3addr, u_int flags)
|
||||
in_lltable_new(struct in_addr addr4, u_int flags)
|
||||
{
|
||||
struct in_llentry *lle;
|
||||
const struct sockaddr_in *l3addr_sin;
|
||||
|
||||
lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
|
||||
if (lle == NULL) /* NB: caller generates msg */
|
||||
return NULL;
|
||||
|
||||
l3addr_sin = (const struct sockaddr_in *)l3addr;
|
||||
lle->base.r_l3addr.addr4 = l3addr_sin->sin_addr;
|
||||
lle->l3_addr4 = *l3addr_sin;
|
||||
lle->base.r_l3addr.addr4 = addr4;
|
||||
/* XXX: Legacy */
|
||||
lle->l3_addr4.sin_len = sizeof(lle->l3_addr4);
|
||||
lle->l3_addr4.sin_family = AF_INET;
|
||||
lle->l3_addr4.sin_addr = addr4;
|
||||
|
||||
/*
|
||||
* For IPv4 this will trigger "arpresolve" to generate
|
||||
@ -1058,15 +1059,10 @@ in_lltable_match_prefix(const struct sockaddr *prefix,
|
||||
}
|
||||
|
||||
static int
|
||||
in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
|
||||
in_lltable_rtcheck(struct ifnet *ifp, u_int flags, struct in_addr dst)
|
||||
{
|
||||
struct nhop4_basic nh4;
|
||||
struct in_addr dst;
|
||||
|
||||
KASSERT(l3addr->sa_family == AF_INET,
|
||||
("sin_family %d", l3addr->sa_family));
|
||||
|
||||
dst = ((struct sockaddr_in *)l3addr)->sin_addr;
|
||||
if (fib4_lookup_nh(ifp->if_fib, dst, 0, 0, &nh4) != 0)
|
||||
return (EINVAL);
|
||||
|
||||
@ -1112,6 +1108,16 @@ in_lltable_hash(const struct llentry *lle)
|
||||
return (in_lltable_hash_dst(lle->r_l3addr.addr4));
|
||||
}
|
||||
|
||||
static const void *
|
||||
in_lltable_get_sa_addr(const struct sockaddr *l3addr)
|
||||
{
|
||||
const struct sockaddr_in *sin;
|
||||
|
||||
sin = (const struct sockaddr_in *)l3addr;
|
||||
|
||||
return ((const void *)&sin->sin_addr);
|
||||
}
|
||||
|
||||
static inline struct llentry *
|
||||
in_lltable_find_dst(struct lltable *llt, struct in_addr dst)
|
||||
{
|
||||
@ -1174,13 +1180,13 @@ in_lltable_delete(struct lltable *llt, u_int flags,
|
||||
}
|
||||
|
||||
static struct llentry *
|
||||
in_lltable_create(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
|
||||
in_lltable_create(struct lltable *llt, u_int flags, const void *paddr)
|
||||
{
|
||||
struct ifnet *ifp = llt->llt_ifp;
|
||||
struct llentry *lle;
|
||||
struct in_addr addr4;
|
||||
|
||||
KASSERT(l3addr->sa_family == AF_INET,
|
||||
("sin_family %d", l3addr->sa_family));
|
||||
addr4 = *((const struct in_addr *)paddr);
|
||||
|
||||
/*
|
||||
* A route that covers the given address must have
|
||||
@ -1188,10 +1194,10 @@ in_lltable_create(struct lltable *llt, u_int flags, const struct sockaddr *l3add
|
||||
* verify this.
|
||||
*/
|
||||
if (!(flags & LLE_IFADDR) &&
|
||||
in_lltable_rtcheck(ifp, flags, l3addr) != 0)
|
||||
in_lltable_rtcheck(ifp, flags, addr4) != 0)
|
||||
return (NULL);
|
||||
|
||||
lle = in_lltable_new(l3addr, flags);
|
||||
lle = in_lltable_new(addr4, flags);
|
||||
if (lle == NULL) {
|
||||
log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
|
||||
return (NULL);
|
||||
@ -1206,7 +1212,7 @@ in_lltable_create(struct lltable *llt, u_int flags, const struct sockaddr *l3add
|
||||
* If found return lle read locked.
|
||||
*/
|
||||
static struct llentry *
|
||||
in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
|
||||
in_lltable_lookup(struct lltable *llt, u_int flags, const void *paddr)
|
||||
{
|
||||
struct llentry *lle;
|
||||
struct in_addr dst;
|
||||
@ -1216,10 +1222,8 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add
|
||||
* by different locks.
|
||||
* IF_AFDATA_LOCK_ASSERT(llt->llt_ifp);
|
||||
*/
|
||||
KASSERT(l3addr->sa_family == AF_INET,
|
||||
("sin_family %d", l3addr->sa_family));
|
||||
|
||||
dst = ((const struct sockaddr_in *)l3addr)->sin_addr;
|
||||
dst = *((const struct in_addr *)paddr);
|
||||
lle = in_lltable_find_dst(llt, dst);
|
||||
|
||||
if (lle == NULL)
|
||||
@ -1312,6 +1316,7 @@ in_domifattach(struct ifnet *ifp)
|
||||
llt->llt_delete_addr = in_lltable_delete;
|
||||
llt->llt_dump_entry = in_lltable_dump_entry;
|
||||
llt->llt_hash = in_lltable_hash;
|
||||
llt->llt_get_sa_addr = in_lltable_get_sa_addr;
|
||||
llt->llt_clear_entry = arp_lltable_clear_entry;
|
||||
llt->llt_match_prefix = in_lltable_match_prefix;
|
||||
llt->llt_prepare_static_entry = arp_lltable_prepare_static_entry;
|
||||
|
@ -96,8 +96,6 @@ struct in_aliasreq {
|
||||
#ifdef _KERNEL
|
||||
extern u_char inetctlerrmap[];
|
||||
|
||||
#define LLTABLE(ifp) \
|
||||
((struct in_ifinfo *)(ifp)->if_afdata[AF_INET])->ii_llt
|
||||
/*
|
||||
* Hash table for IP addresses.
|
||||
*/
|
||||
|
@ -456,22 +456,24 @@ static int
|
||||
toe_nd6_resolve(struct ifnet *ifp, struct sockaddr *sa, uint8_t *lladdr)
|
||||
{
|
||||
struct llentry *lle, *lle_tmp;
|
||||
struct sockaddr_in6 *sin6 = (void *)sa;
|
||||
struct in6_addr *dst;
|
||||
int rc, flags = 0;
|
||||
|
||||
dst = &((struct sockaddr_in6 *)sa)->sin6_addr;
|
||||
|
||||
restart:
|
||||
IF_AFDATA_RLOCK(ifp);
|
||||
lle = lltable_lookup_lle(LLTABLE6(ifp), flags, sa);
|
||||
lle = lltable_lookup_lle6(ifp, flags, dst);
|
||||
IF_AFDATA_RUNLOCK(ifp);
|
||||
if (lle == NULL) {
|
||||
lle = nd6_create(&sin6->sin6_addr, 0, ifp);
|
||||
lle = lltable_create_lle6(ifp, 0, dst);
|
||||
if (lle == NULL)
|
||||
return (ENOMEM); /* Couldn't create entry in cache. */
|
||||
lle->ln_state = ND6_LLINFO_INCOMPLETE;
|
||||
IF_AFDATA_CFG_WLOCK(ifp);
|
||||
LLE_WLOCK(lle);
|
||||
/* Check if the same record was addded */
|
||||
lle_tmp = lltable_lookup_lle(LLTABLE6(ifp), LLE_EXCLUSIVE, sa);
|
||||
lle_tmp = lltable_lookup_lle6(ifp, LLE_EXCLUSIVE, dst);
|
||||
if (lle_tmp == NULL) {
|
||||
/*
|
||||
* No entry has been found. Link new one.
|
||||
@ -487,7 +489,7 @@ toe_nd6_resolve(struct ifnet *ifp, struct sockaddr *sa, uint8_t *lladdr)
|
||||
(long)ND_IFINFO(ifp)->retrans * hz / 1000);
|
||||
LLE_WUNLOCK(lle);
|
||||
|
||||
nd6_ns_output(ifp, NULL, &sin6->sin6_addr, NULL, 0);
|
||||
nd6_ns_output(ifp, NULL, dst, NULL, 0);
|
||||
|
||||
return (EWOULDBLOCK);
|
||||
}
|
||||
|
@ -2064,18 +2064,19 @@ in6_lltable_free(struct llentry *lle)
|
||||
}
|
||||
|
||||
static struct llentry *
|
||||
in6_lltable_new(const struct sockaddr *l3addr, u_int flags)
|
||||
in6_lltable_new(const struct in6_addr *addr6, u_int flags)
|
||||
{
|
||||
struct in6_llentry *lle;
|
||||
const struct sockaddr_in6 *l3addr_sin6;
|
||||
|
||||
lle = malloc(sizeof(struct in6_llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
|
||||
if (lle == NULL) /* NB: caller generates msg */
|
||||
return NULL;
|
||||
|
||||
l3addr_sin6 = (const struct sockaddr_in6 *)l3addr;
|
||||
lle->l3_addr6 = *l3addr_sin6;
|
||||
lle->base.r_l3addr.addr6 = l3addr_sin6->sin6_addr;
|
||||
lle->base.r_l3addr.addr6 = *addr6;
|
||||
/* XXX: legacy */
|
||||
lle->l3_addr6.sin6_family = AF_INET6;
|
||||
lle->l3_addr6.sin6_len = sizeof(lle->l3_addr6);
|
||||
lle->l3_addr6.sin6_addr = *addr6;
|
||||
lle->base.lle_refcnt = 1;
|
||||
lle->base.lle_free = in6_lltable_free;
|
||||
LLE_LOCK_INIT(&lle->base);
|
||||
@ -2103,20 +2104,18 @@ in6_lltable_match_prefix(const struct sockaddr *prefix,
|
||||
static int
|
||||
in6_lltable_rtcheck(struct ifnet *ifp,
|
||||
u_int flags,
|
||||
const struct sockaddr *l3addr)
|
||||
const struct in6_addr *addr6)
|
||||
{
|
||||
struct nhop6_basic nh6;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct in6_addr dst;
|
||||
uint32_t scopeid;
|
||||
int error;
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
|
||||
KASSERT(l3addr->sa_family == AF_INET6,
|
||||
("sin_family %d", l3addr->sa_family));
|
||||
|
||||
/* Our local addresses are always only installed on the default FIB. */
|
||||
|
||||
in6_splitscope(&((struct sockaddr_in6 *)l3addr)->sin6_addr, &dst, &scopeid);
|
||||
in6_splitscope(addr6, &dst, &scopeid);
|
||||
error = fib6_lookup_nh(RT_DEFAULT_FIB, &dst, scopeid, 0, 0, &nh6);
|
||||
if (error != 0 || ((nh6.nh_flags & NHF_GATEWAY) != 0) || nh6.nh_ifp != ifp) {
|
||||
struct ifaddr *ifa;
|
||||
@ -2125,13 +2124,17 @@ in6_lltable_rtcheck(struct ifnet *ifp,
|
||||
* that is not covered by our own prefix.
|
||||
*/
|
||||
/* XXX ifaof_ifpforaddr should take a const param */
|
||||
ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, l3addr), ifp);
|
||||
bzero(&sin6, sizeof(sin6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_len = sizeof(sin6);
|
||||
sin6.sin6_addr = *addr6;
|
||||
ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, &sin6), ifp);
|
||||
if (ifa != NULL) {
|
||||
ifa_free(ifa);
|
||||
return 0;
|
||||
}
|
||||
log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
|
||||
ip6_sprintf(ip6buf, &((const struct sockaddr_in6 *)l3addr)->sin6_addr));
|
||||
ip6_sprintf(ip6buf, addr6));
|
||||
return EINVAL;
|
||||
}
|
||||
return 0;
|
||||
@ -2151,6 +2154,16 @@ in6_lltable_hash(const struct llentry *lle)
|
||||
return (in6_lltable_hash_dst(&lle->r_l3addr.addr6));
|
||||
}
|
||||
|
||||
static const void *
|
||||
in6_lltable_get_sa_addr(const struct sockaddr *l3addr)
|
||||
{
|
||||
const struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (const struct sockaddr_in6 *)l3addr;
|
||||
|
||||
return ((const void *)&sin6->sin6_addr);
|
||||
}
|
||||
|
||||
static inline struct llentry *
|
||||
in6_lltable_find_dst(struct lltable *llt, const struct in6_addr *dst)
|
||||
{
|
||||
@ -2213,26 +2226,25 @@ in6_lltable_delete(struct lltable *llt, u_int flags,
|
||||
|
||||
static struct llentry *
|
||||
in6_lltable_create(struct lltable *llt, u_int flags,
|
||||
const struct sockaddr *l3addr)
|
||||
const void *paddr)
|
||||
{
|
||||
struct ifnet *ifp = llt->llt_ifp;
|
||||
struct llentry *lle;
|
||||
|
||||
KASSERT(l3addr->sa_family == AF_INET6,
|
||||
("sin_family %d", l3addr->sa_family));
|
||||
const struct in6_addr *addr6;
|
||||
|
||||
IF_AFDATA_CFG_UNLOCK_ASSERT(ifp);
|
||||
|
||||
addr6 = (const struct in6_addr *)paddr;
|
||||
/*
|
||||
* A route that covers the given address must have
|
||||
* been installed 1st because we are doing a resolution,
|
||||
* verify this.
|
||||
*/
|
||||
if (!(flags & LLE_IFADDR) &&
|
||||
in6_lltable_rtcheck(ifp, flags, l3addr) != 0)
|
||||
in6_lltable_rtcheck(ifp, flags, addr6) != 0)
|
||||
return NULL;
|
||||
|
||||
lle = in6_lltable_new(l3addr, flags);
|
||||
lle = in6_lltable_new(addr6, flags);
|
||||
if (lle == NULL) {
|
||||
log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
|
||||
return NULL;
|
||||
@ -2244,9 +2256,9 @@ in6_lltable_create(struct lltable *llt, u_int flags,
|
||||
|
||||
static struct llentry *
|
||||
in6_lltable_lookup(struct lltable *llt, u_int flags,
|
||||
const struct sockaddr *l3addr)
|
||||
const void *l3addr)
|
||||
{
|
||||
const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr;
|
||||
const struct in6_addr *dst6;
|
||||
struct llentry *lle;
|
||||
|
||||
/*
|
||||
@ -2254,10 +2266,9 @@ in6_lltable_lookup(struct lltable *llt, u_int flags,
|
||||
* by different locks.
|
||||
* IF_AFDATA_LOCK_ASSERT(llt->llt_ifp);
|
||||
*/
|
||||
KASSERT(l3addr->sa_family == AF_INET6,
|
||||
("sin_family %d", l3addr->sa_family));
|
||||
dst6 = (const struct in6_addr *)l3addr;
|
||||
|
||||
lle = in6_lltable_find_dst(llt, &sin6->sin6_addr);
|
||||
lle = in6_lltable_find_dst(llt, dst6);
|
||||
|
||||
if (lle == NULL)
|
||||
return (NULL);
|
||||
@ -2377,6 +2388,7 @@ in6_domifattach(struct ifnet *ifp)
|
||||
llt->llt_delete_addr = in6_lltable_delete;
|
||||
llt->llt_dump_entry = in6_lltable_dump_entry;
|
||||
llt->llt_hash = in6_lltable_hash;
|
||||
llt->llt_get_sa_addr = in6_lltable_get_sa_addr;
|
||||
llt->llt_clear_entry = nd6_lltable_clear_entry;
|
||||
llt->llt_match_prefix = in6_lltable_match_prefix;
|
||||
llt->llt_prepare_static_entry = nd6_lltable_prepare_static_entry;
|
||||
|
@ -108,8 +108,6 @@ struct in6_ifextra {
|
||||
struct mld_ifinfo *mld_ifinfo;
|
||||
};
|
||||
|
||||
#define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable)
|
||||
|
||||
#if defined(_KERNEL) || defined(_WANT_IFADDR)
|
||||
struct in6_ifaddr {
|
||||
struct ifaddr ia_ifa; /* protocol-independent info */
|
||||
|
@ -889,55 +889,6 @@ nd6_purge(struct ifnet *ifp)
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* the caller acquires and releases the lock on the lltbls
|
||||
* Returns the llentry locked
|
||||
*/
|
||||
struct llentry *
|
||||
nd6_lookup(struct in6_addr *addr6, int flags, struct ifnet *ifp)
|
||||
{
|
||||
struct sockaddr_in6 sin6;
|
||||
struct llentry *ln;
|
||||
int llflags;
|
||||
|
||||
bzero(&sin6, sizeof(sin6));
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_addr = *addr6;
|
||||
|
||||
/*
|
||||
* IF_AFDATA_LOCK_ASSERT(ifp);
|
||||
*/
|
||||
|
||||
llflags = (flags & ND6_EXCLUSIVE) ? LLE_EXCLUSIVE : 0;
|
||||
ln = lltable_lookup_lle(LLTABLE6(ifp), llflags,
|
||||
(struct sockaddr *)&sin6);
|
||||
|
||||
return (ln);
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates and returns new, unlinked and unlocked lle.
|
||||
*/
|
||||
struct llentry *
|
||||
nd6_create(struct in6_addr *addr6, int flags, struct ifnet *ifp)
|
||||
{
|
||||
struct sockaddr_in6 sin6;
|
||||
struct llentry *ln;
|
||||
|
||||
bzero(&sin6, sizeof(sin6));
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_addr = *addr6;
|
||||
|
||||
IF_AFDATA_CFG_UNLOCK_ASSERT(ifp);
|
||||
|
||||
ln = lltable_create_lle(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6);
|
||||
ln->ln_state = ND6_LLINFO_NOSTATE;
|
||||
|
||||
return (ln);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether a given IPv6 address is a neighbor or not, ignoring
|
||||
* the actual neighbor cache. The neighbor cache is ignored in order
|
||||
@ -1295,7 +1246,7 @@ nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force)
|
||||
|
||||
ifp = rt->rt_ifp;
|
||||
IF_AFDATA_RLOCK(ifp);
|
||||
ln = nd6_lookup(dst6, ND6_EXCLUSIVE, NULL);
|
||||
ln = nd6_lookup(dst6, ND6_EXCLUSIVE, ifp);
|
||||
IF_AFDATA_RUNLOCK(ifp);
|
||||
if (ln == NULL)
|
||||
return;
|
||||
@ -1798,9 +1749,11 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
||||
ln = nd6_lookup(from, ND6_EXCLUSIVE, ifp);
|
||||
IF_AFDATA_CFG_RUNLOCK(ifp);
|
||||
if (ln == NULL) {
|
||||
ln = nd6_create(from, 0, ifp);
|
||||
if (ln != NULL)
|
||||
ln = lltable_create_lle6(ifp, 0, from);
|
||||
if (ln != NULL) {
|
||||
LLE_WLOCK(ln);
|
||||
ln->ln_state = ND6_LLINFO_NOSTATE;
|
||||
}
|
||||
is_newentry = 1;
|
||||
} else {
|
||||
/* do nothing if record is static */
|
||||
@ -2204,8 +2157,9 @@ nd6_output_lle(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
|
||||
* the condition below is not very efficient. But we believe
|
||||
* it is tolerable, because this should be a rare case.
|
||||
*/
|
||||
lle = nd6_create(&dst->sin6_addr, 0, ifp);
|
||||
lle = lltable_create_lle6(ifp, 0, &dst->sin6_addr);
|
||||
if (lle != NULL) {
|
||||
lle->ln_state = ND6_LLINFO_NOSTATE;
|
||||
IF_AFDATA_CFG_WLOCK(ifp);
|
||||
LLE_WLOCK(lle);
|
||||
/* Check if the same record was addded */
|
||||
@ -2483,12 +2437,13 @@ nd6_add_ifa_lle(struct in6_ifaddr *ia)
|
||||
struct ifnet *ifp;
|
||||
struct llentry *ln, *ln_tmp;
|
||||
struct lltable *llt;
|
||||
struct in6_addr *addr6;
|
||||
|
||||
ifp = ia->ia_ifa.ifa_ifp;
|
||||
addr6 = &ia->ia_addr.sin6_addr;
|
||||
ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
|
||||
|
||||
ln = lltable_create_lle(LLTABLE6(ifp), LLE_IFADDR,
|
||||
(struct sockaddr *)&ia->ia_addr);
|
||||
ln = lltable_create_lle6(ifp, LLE_IFADDR, addr6);
|
||||
if (ln == NULL)
|
||||
return (ENOBUFS);
|
||||
|
||||
@ -2507,8 +2462,7 @@ nd6_add_ifa_lle(struct in6_ifaddr *ia)
|
||||
* Instead of dealing with callouts/flags/etc we simply
|
||||
* delete it and add new one.
|
||||
*/
|
||||
ln_tmp = lltable_lookup_lle(llt, LLE_EXCLUSIVE,
|
||||
(struct sockaddr *)&ia->ia_addr);
|
||||
ln_tmp = lltable_lookup_lle6(ifp, LLE_EXCLUSIVE, addr6);
|
||||
|
||||
bcopy(IF_LLADDR(ifp), &ln->ll_addr, ifp->if_addrlen);
|
||||
/* Finally, link our lle to the list */
|
||||
@ -2563,8 +2517,10 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
|
||||
const struct sockaddr *dst, u_char *desten, struct llentry **lle)
|
||||
{
|
||||
struct llentry *ln;
|
||||
const struct in6_addr *addr6;
|
||||
|
||||
*lle = NULL;
|
||||
addr6 = &SIN6(dst)->sin6_addr;
|
||||
IF_AFDATA_CFG_UNLOCK_ASSERT(ifp);
|
||||
if (m != NULL && m->m_flags & M_MCAST) {
|
||||
int i;
|
||||
@ -2580,8 +2536,7 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
|
||||
#endif
|
||||
case IFT_BRIDGE:
|
||||
case IFT_ISO88025:
|
||||
ETHER_MAP_IPV6_MULTICAST(&SIN6(dst)->sin6_addr,
|
||||
desten);
|
||||
ETHER_MAP_IPV6_MULTICAST(addr6, desten);
|
||||
return (0);
|
||||
case IFT_IEEE1394:
|
||||
/*
|
||||
@ -2605,7 +2560,7 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
|
||||
* the entry should have been created in nd6_store_lladdr
|
||||
*/
|
||||
IF_AFDATA_RLOCK(ifp);
|
||||
ln = lltable_lookup_lle(LLTABLE6(ifp), 0, dst);
|
||||
ln = lltable_lookup_lle6(ifp, 0, addr6);
|
||||
IF_AFDATA_RUNLOCK(ifp);
|
||||
if ((ln == NULL) || !(ln->la_flags & LLE_VALID)) {
|
||||
if (ln != NULL)
|
||||
|
@ -89,8 +89,6 @@ struct nd_ifinfo {
|
||||
#define ND6_IFF_NO_RADR 0x40
|
||||
#define ND6_IFF_NO_PREFER_IFACE 0x80 /* XXX: not related to ND. */
|
||||
|
||||
#define ND6_EXCLUSIVE LLE_EXCLUSIVE
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define ND_IFINFO(ifp) \
|
||||
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo)
|
||||
@ -389,14 +387,33 @@ void nd6_init(void);
|
||||
#ifdef VIMAGE
|
||||
void nd6_destroy(void);
|
||||
#endif
|
||||
|
||||
#define LLTABLE6(ifp) \
|
||||
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable)
|
||||
|
||||
static __inline const void *
|
||||
_check_in6_addr_typecast(const struct in6_addr *paddr)
|
||||
{
|
||||
|
||||
return ((const void *)paddr);
|
||||
}
|
||||
|
||||
#define lltable_lookup_lle6(i, f, a) \
|
||||
lltable_lookup_lle(LLTABLE6(i), (f), _check_in6_addr_typecast(a))
|
||||
#define lltable_create_lle6(i, f, a) \
|
||||
lltable_create_lle(LLTABLE6(i), (f), _check_in6_addr_typecast(a))
|
||||
|
||||
#define nd6_lookup(a, f, i) lltable_lookup_lle6((i), (f), (a))
|
||||
#define ND6_EXCLUSIVE LLE_EXCLUSIVE
|
||||
|
||||
|
||||
|
||||
struct nd_ifinfo *nd6_ifattach(struct ifnet *);
|
||||
void nd6_ifdetach(struct nd_ifinfo *);
|
||||
int nd6_is_addr_neighbor(struct sockaddr_in6 *, struct ifnet *);
|
||||
void nd6_option_init(void *, int, union nd_opts *);
|
||||
struct nd_opt_hdr *nd6_option(union nd_opts *);
|
||||
int nd6_options(union nd_opts *);
|
||||
struct llentry *nd6_lookup(struct in6_addr *, int, struct ifnet *);
|
||||
struct llentry *nd6_create(struct in6_addr *, int, struct ifnet *);
|
||||
void nd6_setmtu(struct ifnet *);
|
||||
void nd6_llinfo_settimer(struct llentry *, long);
|
||||
void nd6_llinfo_settimer_locked(struct llentry *, long);
|
||||
|
Loading…
Reference in New Issue
Block a user