Simplify nd6_cache_lladdr:
* Move isRouter calculation code to separate nd6_is_router() function. * Make nd6_cache_lladdr() return void: its return value hasn't been used since r53541 KAME import in 1999. Sponsored by: Yandex LLC
This commit is contained in:
parent
aafbd0257a
commit
0e2dcee6b2
@ -1592,6 +1592,85 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculates new isRouter value based on provided parameters and
|
||||||
|
* returns it.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
nd6_is_router(int type, int code, int is_new, int old_addr, int new_addr,
|
||||||
|
int ln_router)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ICMP6 type dependent behavior.
|
||||||
|
*
|
||||||
|
* NS: clear IsRouter if new entry
|
||||||
|
* RS: clear IsRouter
|
||||||
|
* RA: set IsRouter if there's lladdr
|
||||||
|
* redir: clear IsRouter if new entry
|
||||||
|
*
|
||||||
|
* RA case, (1):
|
||||||
|
* The spec says that we must set IsRouter in the following cases:
|
||||||
|
* - If lladdr exist, set IsRouter. This means (1-5).
|
||||||
|
* - If it is old entry (!newentry), set IsRouter. This means (7).
|
||||||
|
* So, based on the spec, in (1-5) and (7) cases we must set IsRouter.
|
||||||
|
* A quetion arises for (1) case. (1) case has no lladdr in the
|
||||||
|
* neighbor cache, this is similar to (6).
|
||||||
|
* This case is rare but we figured that we MUST NOT set IsRouter.
|
||||||
|
*
|
||||||
|
* newentry olladdr lladdr llchange NS RS RA redir
|
||||||
|
* D R
|
||||||
|
* 0 n n -- (1) c ? s
|
||||||
|
* 0 y n -- (2) c s s
|
||||||
|
* 0 n y -- (3) c s s
|
||||||
|
* 0 y y n (4) c s s
|
||||||
|
* 0 y y y (5) c s s
|
||||||
|
* 1 -- n -- (6) c c c s
|
||||||
|
* 1 -- y -- (7) c c s c s
|
||||||
|
*
|
||||||
|
* (c=clear s=set)
|
||||||
|
*/
|
||||||
|
switch (type & 0xff) {
|
||||||
|
case ND_NEIGHBOR_SOLICIT:
|
||||||
|
/*
|
||||||
|
* New entry must have is_router flag cleared.
|
||||||
|
*/
|
||||||
|
if (is_new) /* (6-7) */
|
||||||
|
ln_router = 0;
|
||||||
|
break;
|
||||||
|
case ND_REDIRECT:
|
||||||
|
/*
|
||||||
|
* If the icmp is a redirect to a better router, always set the
|
||||||
|
* is_router flag. Otherwise, if the entry is newly created,
|
||||||
|
* clear the flag. [RFC 2461, sec 8.3]
|
||||||
|
*/
|
||||||
|
if (code == ND_REDIRECT_ROUTER)
|
||||||
|
ln_router = 1;
|
||||||
|
else {
|
||||||
|
if (is_new) /* (6-7) */
|
||||||
|
ln_router = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ND_ROUTER_SOLICIT:
|
||||||
|
/*
|
||||||
|
* is_router flag must always be cleared.
|
||||||
|
*/
|
||||||
|
ln_router = 0;
|
||||||
|
break;
|
||||||
|
case ND_ROUTER_ADVERT:
|
||||||
|
/*
|
||||||
|
* Mark an entry with lladdr as a router.
|
||||||
|
*/
|
||||||
|
if ((!is_new && (old_addr || new_addr)) || /* (2-5) */
|
||||||
|
(is_new && new_addr)) { /* (7) */
|
||||||
|
ln_router = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ln_router);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create neighbor cache entry and cache link-layer address,
|
* Create neighbor cache entry and cache link-layer address,
|
||||||
* on reception of inbound ND6 packets. (RS/RA/NS/redirect)
|
* on reception of inbound ND6 packets. (RS/RA/NS/redirect)
|
||||||
@ -1599,11 +1678,8 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
|
|||||||
* type - ICMP6 type
|
* type - ICMP6 type
|
||||||
* code - type dependent information
|
* code - type dependent information
|
||||||
*
|
*
|
||||||
* XXXXX
|
|
||||||
* The caller of this function already acquired the ndp
|
|
||||||
* cache table lock because the cache entry is returned.
|
|
||||||
*/
|
*/
|
||||||
struct llentry *
|
void
|
||||||
nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
||||||
int lladdrlen, int type, int code)
|
int lladdrlen, int type, int code)
|
||||||
{
|
{
|
||||||
@ -1617,7 +1693,6 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
|||||||
uint16_t router = 0;
|
uint16_t router = 0;
|
||||||
struct sockaddr_in6 sin6;
|
struct sockaddr_in6 sin6;
|
||||||
struct mbuf *chain = NULL;
|
struct mbuf *chain = NULL;
|
||||||
int static_route = 0;
|
|
||||||
|
|
||||||
IF_AFDATA_UNLOCK_ASSERT(ifp);
|
IF_AFDATA_UNLOCK_ASSERT(ifp);
|
||||||
|
|
||||||
@ -1626,7 +1701,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
|||||||
|
|
||||||
/* nothing must be updated for unspecified address */
|
/* nothing must be updated for unspecified address */
|
||||||
if (IN6_IS_ADDR_UNSPECIFIED(from))
|
if (IN6_IS_ADDR_UNSPECIFIED(from))
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validation about ifp->if_addrlen and lladdrlen must be done in
|
* Validation about ifp->if_addrlen and lladdrlen must be done in
|
||||||
@ -1646,7 +1721,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
|||||||
flags |= ND6_EXCLUSIVE;
|
flags |= ND6_EXCLUSIVE;
|
||||||
ln = nd6_alloc(from, 0, ifp);
|
ln = nd6_alloc(from, 0, ifp);
|
||||||
if (ln == NULL)
|
if (ln == NULL)
|
||||||
return (NULL);
|
return;
|
||||||
IF_AFDATA_WLOCK(ifp);
|
IF_AFDATA_WLOCK(ifp);
|
||||||
LLE_WLOCK(ln);
|
LLE_WLOCK(ln);
|
||||||
/* Prefer any existing lle over newly-created one */
|
/* Prefer any existing lle over newly-created one */
|
||||||
@ -1665,8 +1740,11 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
|||||||
}
|
}
|
||||||
/* do nothing if static ndp is set */
|
/* do nothing if static ndp is set */
|
||||||
if ((ln->la_flags & LLE_STATIC)) {
|
if ((ln->la_flags & LLE_STATIC)) {
|
||||||
static_route = 1;
|
if (flags & ND6_EXCLUSIVE)
|
||||||
goto done;
|
LLE_WUNLOCK(ln);
|
||||||
|
else
|
||||||
|
LLE_RUNLOCK(ln);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
olladdr = (ln->la_flags & LLE_VALID) ? 1 : 0;
|
olladdr = (ln->la_flags & LLE_VALID) ? 1 : 0;
|
||||||
@ -1727,85 +1805,20 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Calculates new router status */
|
||||||
* ICMP6 type dependent behavior.
|
router = nd6_is_router(type, code, is_newentry, olladdr,
|
||||||
*
|
lladdr != NULL ? 1 : 0, ln->ln_router);
|
||||||
* NS: clear IsRouter if new entry
|
|
||||||
* RS: clear IsRouter
|
|
||||||
* RA: set IsRouter if there's lladdr
|
|
||||||
* redir: clear IsRouter if new entry
|
|
||||||
*
|
|
||||||
* RA case, (1):
|
|
||||||
* The spec says that we must set IsRouter in the following cases:
|
|
||||||
* - If lladdr exist, set IsRouter. This means (1-5).
|
|
||||||
* - If it is old entry (!newentry), set IsRouter. This means (7).
|
|
||||||
* So, based on the spec, in (1-5) and (7) cases we must set IsRouter.
|
|
||||||
* A quetion arises for (1) case. (1) case has no lladdr in the
|
|
||||||
* neighbor cache, this is similar to (6).
|
|
||||||
* This case is rare but we figured that we MUST NOT set IsRouter.
|
|
||||||
*
|
|
||||||
* newentry olladdr lladdr llchange NS RS RA redir
|
|
||||||
* D R
|
|
||||||
* 0 n n -- (1) c ? s
|
|
||||||
* 0 y n -- (2) c s s
|
|
||||||
* 0 n y -- (3) c s s
|
|
||||||
* 0 y y n (4) c s s
|
|
||||||
* 0 y y y (5) c s s
|
|
||||||
* 1 -- n -- (6) c c c s
|
|
||||||
* 1 -- y -- (7) c c s c s
|
|
||||||
*
|
|
||||||
* (c=clear s=set)
|
|
||||||
*/
|
|
||||||
switch (type & 0xff) {
|
|
||||||
case ND_NEIGHBOR_SOLICIT:
|
|
||||||
/*
|
|
||||||
* New entry must have is_router flag cleared.
|
|
||||||
*/
|
|
||||||
if (is_newentry) /* (6-7) */
|
|
||||||
ln->ln_router = 0;
|
|
||||||
break;
|
|
||||||
case ND_REDIRECT:
|
|
||||||
/*
|
|
||||||
* If the icmp is a redirect to a better router, always set the
|
|
||||||
* is_router flag. Otherwise, if the entry is newly created,
|
|
||||||
* clear the flag. [RFC 2461, sec 8.3]
|
|
||||||
*/
|
|
||||||
if (code == ND_REDIRECT_ROUTER)
|
|
||||||
ln->ln_router = 1;
|
|
||||||
else {
|
|
||||||
if (is_newentry) /* (6-7) */
|
|
||||||
ln->ln_router = 0;
|
|
||||||
ln->la_flags |= LLE_REDIRECT;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ND_ROUTER_SOLICIT:
|
|
||||||
/*
|
|
||||||
* is_router flag must always be cleared.
|
|
||||||
*/
|
|
||||||
ln->ln_router = 0;
|
|
||||||
break;
|
|
||||||
case ND_ROUTER_ADVERT:
|
|
||||||
/*
|
|
||||||
* Mark an entry with lladdr as a router.
|
|
||||||
*/
|
|
||||||
if ((!is_newentry && (olladdr || lladdr)) || /* (2-5) */
|
|
||||||
(is_newentry && lladdr)) { /* (7) */
|
|
||||||
ln->ln_router = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ln != NULL) {
|
ln->ln_router = router;
|
||||||
static_route = (ln->la_flags & LLE_STATIC);
|
/* Mark non-router redirects with special flag */
|
||||||
router = ln->ln_router;
|
if ((type & 0xFF) == ND_REDIRECT && code != ND_REDIRECT_ROUTER)
|
||||||
|
ln->la_flags |= LLE_REDIRECT;
|
||||||
|
|
||||||
|
if (flags & ND6_EXCLUSIVE)
|
||||||
|
LLE_WUNLOCK(ln);
|
||||||
|
else
|
||||||
|
LLE_RUNLOCK(ln);
|
||||||
|
|
||||||
if (flags & ND6_EXCLUSIVE)
|
|
||||||
LLE_WUNLOCK(ln);
|
|
||||||
else
|
|
||||||
LLE_RUNLOCK(ln);
|
|
||||||
if (static_route)
|
|
||||||
ln = NULL;
|
|
||||||
}
|
|
||||||
if (chain != NULL)
|
if (chain != NULL)
|
||||||
nd6_flush_holdchain(ifp, ifp, chain, &sin6);
|
nd6_flush_holdchain(ifp, ifp, chain, &sin6);
|
||||||
|
|
||||||
@ -1831,18 +1844,6 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
|||||||
*/
|
*/
|
||||||
defrouter_select();
|
defrouter_select();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ln);
|
|
||||||
done:
|
|
||||||
if (ln != NULL) {
|
|
||||||
if (flags & ND6_EXCLUSIVE)
|
|
||||||
LLE_WUNLOCK(ln);
|
|
||||||
else
|
|
||||||
LLE_RUNLOCK(ln);
|
|
||||||
if (static_route)
|
|
||||||
ln = NULL;
|
|
||||||
}
|
|
||||||
return (ln);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -417,7 +417,7 @@ void nd6_nud_hint(struct rtentry *, struct in6_addr *, int);
|
|||||||
int nd6_resolve(struct ifnet *, struct rtentry *, struct mbuf *,
|
int nd6_resolve(struct ifnet *, struct rtentry *, struct mbuf *,
|
||||||
struct sockaddr *, u_char *);
|
struct sockaddr *, u_char *);
|
||||||
int nd6_ioctl(u_long, caddr_t, struct ifnet *);
|
int nd6_ioctl(u_long, caddr_t, struct ifnet *);
|
||||||
struct llentry *nd6_cache_lladdr(struct ifnet *, struct in6_addr *,
|
void nd6_cache_lladdr(struct ifnet *, struct in6_addr *,
|
||||||
char *, int, int, int);
|
char *, int, int, int);
|
||||||
int nd6_output(struct ifnet *, struct ifnet *, struct mbuf *,
|
int nd6_output(struct ifnet *, struct ifnet *, struct mbuf *,
|
||||||
struct sockaddr_in6 *, struct rtentry *);
|
struct sockaddr_in6 *, struct rtentry *);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user