Some modules such as SCTP supplies a valid route entry as an input argument

to ip_output(). The destionation is represented in a sockaddr{} object
that may contain other pieces of information, e.g., port number. This
same destination sockaddr{} object may be passed into L2 code, which
could be used to create a L2 entry. Since there exists a L2 table per
address family, the L2 lookup function can make address family specific
comparison instead of the generic bcmp() operation over the entire
sockaddr{} structure.

Note in the IPv6 case the sin6_scope_id is not compared because the
address is currently stored in the embedded form inside the kernel.
The in6_lltable_lookup() has to account for the scope-id if this
storage format were to change in the future.
This commit is contained in:
Qing Li 2009-01-03 00:27:28 +00:00
parent bcca92c0e5
commit dc49549713
2 changed files with 17 additions and 37 deletions

View File

@ -1106,9 +1106,10 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add
hashkey = sin->sin_addr.s_addr;
lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
LIST_FOREACH(lle, lleh, lle_next) {
struct sockaddr_in *sa2 = (struct sockaddr_in *)L3_ADDR(lle);
if (lle->la_flags & LLE_DELETED)
continue;
if (bcmp(L3_ADDR(lle), l3addr, sizeof(struct sockaddr_in)) == 0)
if (sa2->sin_addr.s_addr == sin->sin_addr.s_addr)
break;
}
if (lle == NULL) {

View File

@ -1533,52 +1533,29 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
* XXX: the logic below rejects assigning multiple addresses on a p2p
* interface that share the same destination.
*/
#if 0 /* QL - verify */
plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
ia->ia_dstaddr.sin6_family == AF_INET6) {
if (!(ia->ia_flags & IFA_ROUTE) && plen == 128) {
struct sockaddr *dstaddr;
int rtflags = RTF_UP | RTF_HOST;
struct rtentry *rt = NULL, **rtp = NULL;
if (nd6_need_cache(ifp) != 0) {
rtp = &rt;
}
/*
* use the interface address if configuring an
* interface address with a /128 prefix len
*/
if (ia->ia_dstaddr.sin6_family == AF_INET6)
dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
else
dstaddr = (struct sockaddr *)&ia->ia_addr;
error = rtrequest(RTM_ADD,
(struct sockaddr *)&ia->ia_dstaddr,
(struct sockaddr *)dstaddr,
(struct sockaddr *)&ia->ia_addr,
(struct sockaddr *)&ia->ia_prefixmask,
ia->ia_flags | rtflags, rtp);
ia->ia_flags | rtflags, NULL);
if (error != 0)
return (error);
if (rt != NULL) {
struct llinfo_nd6 *ln;
RT_LOCK(rt);
ln = (struct llinfo_nd6 *)rt->rt_llinfo;
if (ln != NULL) {
/*
* Set the state to STALE because we don't
* have to perform address resolution on this
* link.
*/
ln->ln_state = ND6_LLINFO_STALE;
}
RT_REMREF(rt);
RT_UNLOCK(rt);
}
ia->ia_flags |= IFA_ROUTE;
}
#else
plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
ia->ia_dstaddr.sin6_family == AF_INET6) {
if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,
RTF_UP | RTF_HOST)) != 0)
return (error);
ia->ia_flags |= IFA_ROUTE;
}
#endif
/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
if (newhost) {
@ -2171,9 +2148,11 @@ in6_lltable_lookup(struct lltable *llt, u_int flags,
hashkey = sin6->sin6_addr.s6_addr32[3];
lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
LIST_FOREACH(lle, lleh, lle_next) {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)L3_ADDR(lle);
if (lle->la_flags & LLE_DELETED)
continue;
if (bcmp(L3_ADDR(lle), l3addr, l3addr->sa_len) == 0)
if (bcmp(&sa6->sin6_addr, &sin6->sin6_addr,
sizeof(struct in6_addr)) == 0)
break;
}