Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet6/in6.c
Show First 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | |||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/socketvar.h> | #include <sys/socketvar.h> | ||||
#include <sys/sockio.h> | #include <sys/sockio.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/priv.h> | #include <sys/priv.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/protosw.h> | |||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/rmlock.h> | #include <sys/rmlock.h> | ||||
#include <sys/syslog.h> | #include <sys/syslog.h> | ||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_var.h> | #include <net/if_var.h> | ||||
▲ Show 20 Lines • Show All 637 Lines • ▼ Show 20 Lines | aifaddr_out: | ||||
error = 0; | error = 0; | ||||
out: | out: | ||||
if (ia != NULL) | if (ia != NULL) | ||||
ifa_free(&ia->ia_ifa); | ifa_free(&ia->ia_ifa); | ||||
return (error); | return (error); | ||||
} | } | ||||
static struct in6_multi_mship * | |||||
in6_joingroup_legacy(struct ifnet *ifp, const struct in6_addr *mcaddr, | |||||
int *errorp, int delay) | |||||
{ | |||||
struct in6_multi_mship *imm; | |||||
int error; | |||||
imm = malloc(sizeof(*imm), M_IP6MADDR, M_NOWAIT); | |||||
if (imm == NULL) { | |||||
*errorp = ENOBUFS; | |||||
return (NULL); | |||||
} | |||||
delay = (delay * PR_FASTHZ) / hz; | |||||
error = in6_joingroup(ifp, mcaddr, NULL, &imm->i6mm_maddr, delay); | |||||
if (error) { | |||||
*errorp = error; | |||||
free(imm, M_IP6MADDR); | |||||
return (NULL); | |||||
} | |||||
return (imm); | |||||
} | |||||
/* | /* | ||||
* Join necessary multicast groups. Factored out from in6_update_ifa(). | * Join necessary multicast groups. Factored out from in6_update_ifa(). | ||||
* This entire work should only be done once, for the default FIB. | * This entire work should only be done once, for the default FIB. | ||||
*/ | */ | ||||
static int | static int | ||||
in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra, | in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra, | ||||
struct in6_ifaddr *ia, int flags, struct in6_multi **in6m_sol) | struct in6_ifaddr *ia, int flags, struct in6_multi **in6m_sol) | ||||
{ | { | ||||
Show All 20 Lines | if ((flags & IN6_IFAUPDATE_DADDELAY)) { | ||||
/* | /* | ||||
* We need a random delay for DAD on the address being | * We need a random delay for DAD on the address being | ||||
* configured. It also means delaying transmission of the | * configured. It also means delaying transmission of the | ||||
* corresponding MLD report to avoid report collision. | * corresponding MLD report to avoid report collision. | ||||
* [RFC 4861, Section 6.3.7] | * [RFC 4861, Section 6.3.7] | ||||
*/ | */ | ||||
delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz); | delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz); | ||||
} | } | ||||
imm = in6_joingroup(ifp, &mltaddr, &error, delay); | imm = in6_joingroup_legacy(ifp, &mltaddr, &error, delay); | ||||
if (imm == NULL) { | if (imm == NULL) { | ||||
nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " | nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " | ||||
"(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr), | "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr), | ||||
if_name(ifp), error)); | if_name(ifp), error)); | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); | LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); | ||||
*in6m_sol = imm->i6mm_maddr; | *in6m_sol = imm->i6mm_maddr; | ||||
/* | /* | ||||
* Join link-local all-nodes address. | * Join link-local all-nodes address. | ||||
*/ | */ | ||||
mltaddr = in6addr_linklocal_allnodes; | mltaddr = in6addr_linklocal_allnodes; | ||||
if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) | if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) | ||||
goto cleanup; /* XXX: should not fail */ | goto cleanup; /* XXX: should not fail */ | ||||
imm = in6_joingroup(ifp, &mltaddr, &error, 0); | imm = in6_joingroup_legacy(ifp, &mltaddr, &error, 0); | ||||
if (imm == NULL) { | if (imm == NULL) { | ||||
nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " | nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " | ||||
"(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr), | "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr), | ||||
if_name(ifp), error)); | if_name(ifp), error)); | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); | LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); | ||||
/* | /* | ||||
* Join node information group address. | * Join node information group address. | ||||
*/ | */ | ||||
delay = 0; | delay = 0; | ||||
if ((flags & IN6_IFAUPDATE_DADDELAY)) { | if ((flags & IN6_IFAUPDATE_DADDELAY)) { | ||||
/* | /* | ||||
* The spec does not say anything about delay for this group, | * The spec does not say anything about delay for this group, | ||||
* but the same logic should apply. | * but the same logic should apply. | ||||
*/ | */ | ||||
delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz); | delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz); | ||||
} | } | ||||
if (in6_nigroup(ifp, NULL, -1, &mltaddr) == 0) { | if (in6_nigroup(ifp, NULL, -1, &mltaddr) == 0) { | ||||
/* XXX jinmei */ | /* XXX jinmei */ | ||||
imm = in6_joingroup(ifp, &mltaddr, &error, delay); | imm = in6_joingroup_legacy(ifp, &mltaddr, &error, delay); | ||||
if (imm == NULL) | if (imm == NULL) | ||||
nd6log((LOG_WARNING, | nd6log((LOG_WARNING, | ||||
"%s: in6_joingroup failed for %s on %s " | "%s: in6_joingroup failed for %s on %s " | ||||
"(errno=%d)\n", __func__, ip6_sprintf(ip6buf, | "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, | ||||
&mltaddr), if_name(ifp), error)); | &mltaddr), if_name(ifp), error)); | ||||
/* XXX not very fatal, go on... */ | /* XXX not very fatal, go on... */ | ||||
else | else | ||||
LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); | LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); | ||||
} | } | ||||
if (V_icmp6_nodeinfo_oldmcprefix && | if (V_icmp6_nodeinfo_oldmcprefix && | ||||
in6_nigroup_oldmcprefix(ifp, NULL, -1, &mltaddr) == 0) { | in6_nigroup_oldmcprefix(ifp, NULL, -1, &mltaddr) == 0) { | ||||
imm = in6_joingroup(ifp, &mltaddr, &error, delay); | imm = in6_joingroup_legacy(ifp, &mltaddr, &error, delay); | ||||
if (imm == NULL) | if (imm == NULL) | ||||
nd6log((LOG_WARNING, | nd6log((LOG_WARNING, | ||||
"%s: in6_joingroup failed for %s on %s " | "%s: in6_joingroup failed for %s on %s " | ||||
"(errno=%d)\n", __func__, ip6_sprintf(ip6buf, | "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, | ||||
&mltaddr), if_name(ifp), error)); | &mltaddr), if_name(ifp), error)); | ||||
/* XXX not very fatal, go on... */ | /* XXX not very fatal, go on... */ | ||||
else | else | ||||
LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); | LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); | ||||
} | } | ||||
/* | /* | ||||
* Join interface-local all-nodes address. | * Join interface-local all-nodes address. | ||||
* (ff01::1%ifN, and ff01::%ifN/32) | * (ff01::1%ifN, and ff01::%ifN/32) | ||||
*/ | */ | ||||
mltaddr = in6addr_nodelocal_allnodes; | mltaddr = in6addr_nodelocal_allnodes; | ||||
if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) | if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) | ||||
goto cleanup; /* XXX: should not fail */ | goto cleanup; /* XXX: should not fail */ | ||||
imm = in6_joingroup(ifp, &mltaddr, &error, 0); | imm = in6_joingroup_legacy(ifp, &mltaddr, &error, 0); | ||||
if (imm == NULL) { | if (imm == NULL) { | ||||
nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " | nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " | ||||
"(errno=%d)\n", __func__, ip6_sprintf(ip6buf, | "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, | ||||
&mltaddr), if_name(ifp), error)); | &mltaddr), if_name(ifp), error)); | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); | LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); | ||||
▲ Show 20 Lines • Show All 418 Lines • ▼ Show 20 Lines | in6_purgeaddr(struct ifaddr *ifa) | ||||
} | } | ||||
/* stop DAD processing */ | /* stop DAD processing */ | ||||
nd6_dad_stop(ifa); | nd6_dad_stop(ifa); | ||||
/* Leave multicast groups. */ | /* Leave multicast groups. */ | ||||
while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) { | while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) { | ||||
LIST_REMOVE(imm, i6mm_chain); | LIST_REMOVE(imm, i6mm_chain); | ||||
in6_leavegroup(imm); | if (imm->i6mm_maddr != NULL) | ||||
in6_leavegroup(imm->i6mm_maddr, NULL); | |||||
free(imm, M_IP6MADDR); | |||||
} | } | ||||
plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */ | plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */ | ||||
if ((ia->ia_flags & IFA_ROUTE) && plen == 128) { | if ((ia->ia_flags & IFA_ROUTE) && plen == 128) { | ||||
error = rtinit(&(ia->ia_ifa), RTM_DELETE, ia->ia_flags | | error = rtinit(&(ia->ia_ifa), RTM_DELETE, ia->ia_flags | | ||||
(ia->ia_dstaddr.sin6_family == AF_INET6 ? RTF_HOST : 0)); | (ia->ia_dstaddr.sin6_family == AF_INET6 ? RTF_HOST : 0)); | ||||
if (error != 0) | if (error != 0) | ||||
log(LOG_INFO, "%s: err=%d, destination address delete " | log(LOG_INFO, "%s: err=%d, destination address delete " | ||||
"failed\n", __func__, error); | "failed\n", __func__, error); | ||||
▲ Show 20 Lines • Show All 1,240 Lines • Show Last 20 Lines |