IPv6 prefix assignment bug fixes.
(1)When all related IPv6 addresses are removed, then remove the associated IPv6 prefix. (2)When multiple IPv6 link local addrs exist for a same interface , then let its IPv6 prefix have multiple interface id, and create multiple IPv6 global addrs with same interface id. (3)When a new IPv6 link local addr is assigned for an interface, then let its IPv6 prefix also have the interface id of the new IPv6 link local addr, and create new IPv6 global addrs with same interface id. Approved by: jkh
This commit is contained in:
parent
f70608d097
commit
eb70be25c7
@ -89,11 +89,14 @@ struct rr_prhead rr_prefix;
|
||||
|
||||
#include <net/net_osdep.h>
|
||||
|
||||
static void add_each_addr __P((struct socket *so, struct rr_prefix *rpp,
|
||||
struct rp_addr *rap));
|
||||
static int create_ra_entry __P((struct rp_addr **rapp));
|
||||
static int add_each_prefix __P((struct socket *so,
|
||||
struct rr_prefix *rpp));
|
||||
static void free_rp_entries __P((struct rr_prefix *rpp));
|
||||
static int link_stray_ia6s __P((struct rr_prefix *rpp));
|
||||
static void rp_remove __P((struct rr_prefix *rpp));
|
||||
|
||||
/*
|
||||
* Copy bits from src to tgt, from off bit for len bits.
|
||||
@ -399,6 +402,33 @@ assigne_ra_entry(struct rr_prefix *rpp, int iilen, struct in6_ifaddr *ia)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
in6_prefix_add_llifid(int iilen, struct in6_ifaddr *ia)
|
||||
{
|
||||
struct rr_prefix *rpp;
|
||||
struct rp_addr *rap;
|
||||
struct socket so;
|
||||
int error, s;
|
||||
|
||||
if ((error = create_ra_entry(&rap)) != 0)
|
||||
return(error);
|
||||
/* copy interface id part */
|
||||
bit_copy((caddr_t)&rap->ra_ifid, sizeof(rap->ra_ifid) << 3,
|
||||
(caddr_t)IA6_IN6(ia), sizeof(*IA6_IN6(ia)) << 3,
|
||||
64, (sizeof(rap->ra_ifid) << 3) - 64);
|
||||
/* XXX: init dummy so */
|
||||
bzero(&so, sizeof(so));
|
||||
/* insert into list */
|
||||
LIST_FOREACH(rpp, &rr_prefix, rp_entry) {
|
||||
s = splnet();
|
||||
LIST_INSERT_HEAD(&rpp->rp_addrhead, rap, ra_entry);
|
||||
splx(s);
|
||||
add_each_addr(&so, rpp, rap);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
in6_prefix_add_ifid(int iilen, struct in6_ifaddr *ia)
|
||||
{
|
||||
@ -407,6 +437,8 @@ in6_prefix_add_ifid(int iilen, struct in6_ifaddr *ia)
|
||||
struct rp_addr *rap;
|
||||
int error = 0;
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia)))
|
||||
return(in6_prefix_add_llifid(iilen, ia));
|
||||
ifpr = in6_prefixwithifp(ia->ia_ifp, plen, IA6_IN6(ia));
|
||||
if (ifpr == NULL) {
|
||||
struct rr_prefix rp;
|
||||
@ -492,6 +524,8 @@ in6_prefix_remove_ifid(int iilen, struct in6_ifaddr *ia)
|
||||
splx(s);
|
||||
free(rap, M_RR_ADDR);
|
||||
}
|
||||
if (LIST_EMPTY(&ifpr2rp(ia->ia6_ifpr)->rp_addrhead))
|
||||
rp_remove(ifpr2rp(ia->ia6_ifpr));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1035,11 +1069,17 @@ in6_prefix_ioctl(struct socket *so, u_long cmd, caddr_t data,
|
||||
free_rp_entries(&rp_tmp);
|
||||
break;
|
||||
}
|
||||
ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp);
|
||||
if (ifa != NULL) {
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
|
||||
if (ifa->ifa_addr == NULL)
|
||||
continue; /* just for safety */
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa)) == 0)
|
||||
continue;
|
||||
|
||||
if ((error = create_ra_entry(&rap)) != 0) {
|
||||
free_rp_entries(&rp_tmp);
|
||||
break;
|
||||
goto bad;
|
||||
}
|
||||
/* copy interface id part */
|
||||
bit_copy((caddr_t)&rap->ra_ifid,
|
||||
@ -1066,6 +1106,7 @@ in6_prefix_ioctl(struct socket *so, u_long cmd, caddr_t data,
|
||||
error = delete_each_prefix(so, rpp, ipr->ipr_origin);
|
||||
break;
|
||||
}
|
||||
bad:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user