Revert r292275 & r292379
glebius has concerns about these changes so reverting those can be discussed and addressed. Sponsored by: Multiplay
This commit is contained in:
parent
2a952cf258
commit
d6e82913c1
24
sys/net/if.c
24
sys/net/if.c
@ -126,7 +126,7 @@ SX_SYSINIT(ifdescr_sx, &ifdescr_sx, "ifnet descr");
|
||||
|
||||
void (*bridge_linkstate_p)(struct ifnet *ifp);
|
||||
void (*ng_ether_link_state_p)(struct ifnet *ifp, int state);
|
||||
void (*lagg_linkstate_p)(struct ifnet *ifp);
|
||||
void (*lagg_linkstate_p)(struct ifnet *ifp, int state);
|
||||
/* These are external hooks for CARP. */
|
||||
void (*carp_linkstate_p)(struct ifnet *ifp);
|
||||
void (*carp_demote_adj_p)(int, char *);
|
||||
@ -1984,8 +1984,6 @@ if_unroute(struct ifnet *ifp, int flag, int fam)
|
||||
|
||||
if (ifp->if_carp)
|
||||
(*carp_linkstate_p)(ifp);
|
||||
if (ifp->if_lagg)
|
||||
(*lagg_linkstate_p)(ifp);
|
||||
rt_ifmsg(ifp);
|
||||
}
|
||||
|
||||
@ -2007,8 +2005,6 @@ if_route(struct ifnet *ifp, int flag, int fam)
|
||||
pfctlinput(PRC_IFUP, ifa->ifa_addr);
|
||||
if (ifp->if_carp)
|
||||
(*carp_linkstate_p)(ifp);
|
||||
if (ifp->if_lagg)
|
||||
(*lagg_linkstate_p)(ifp);
|
||||
rt_ifmsg(ifp);
|
||||
#ifdef INET6
|
||||
in6_if_up(ifp);
|
||||
@ -2023,27 +2019,17 @@ int (*vlan_tag_p)(struct ifnet *, uint16_t *);
|
||||
int (*vlan_setcookie_p)(struct ifnet *, void *);
|
||||
void *(*vlan_cookie_p)(struct ifnet *);
|
||||
|
||||
void
|
||||
if_link_state_change(struct ifnet *ifp, int link_state)
|
||||
{
|
||||
|
||||
return if_link_state_change_cond(ifp, link_state, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a change in the interface link state. To avoid LORs
|
||||
* between driver lock and upper layer locks, as well as possible
|
||||
* recursions, we post event to taskqueue, and all job
|
||||
* is done in static do_link_state_change().
|
||||
*
|
||||
* If the current link state matches link_state and force isn't
|
||||
* specified no action is taken.
|
||||
*/
|
||||
void
|
||||
if_link_state_change_cond(struct ifnet *ifp, int link_state, int force)
|
||||
if_link_state_change(struct ifnet *ifp, int link_state)
|
||||
{
|
||||
|
||||
if (ifp->if_link_state == link_state && !force)
|
||||
/* Return if state hasn't changed. */
|
||||
if (ifp->if_link_state == link_state)
|
||||
return;
|
||||
|
||||
ifp->if_link_state = link_state;
|
||||
@ -2071,7 +2057,7 @@ do_link_state_change(void *arg, int pending)
|
||||
if (ifp->if_bridge)
|
||||
(*bridge_linkstate_p)(ifp);
|
||||
if (ifp->if_lagg)
|
||||
(*lagg_linkstate_p)(ifp);
|
||||
(*lagg_linkstate_p)(ifp, link_state);
|
||||
|
||||
if (IS_DEFAULT_VNET(curvnet))
|
||||
devctl_notify("IFNET", ifp->if_xname,
|
||||
|
@ -106,7 +106,7 @@ static int lagg_port_create(struct lagg_softc *, struct ifnet *);
|
||||
static int lagg_port_destroy(struct lagg_port *, int);
|
||||
static struct mbuf *lagg_input(struct ifnet *, struct mbuf *);
|
||||
static void lagg_linkstate(struct lagg_softc *);
|
||||
static void lagg_port_state(struct ifnet *);
|
||||
static void lagg_port_state(struct ifnet *, int);
|
||||
static int lagg_port_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static int lagg_port_output(struct ifnet *, struct mbuf *,
|
||||
const struct sockaddr *, struct route *);
|
||||
@ -1774,12 +1774,7 @@ lagg_linkstate(struct lagg_softc *sc)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Force state change to ensure ifnet_link_event is generated allowing
|
||||
* protocols to notify other nodes of potential address move.
|
||||
*/
|
||||
if_link_state_change_cond(sc->sc_ifp, new_link, 1);
|
||||
if_link_state_change(sc->sc_ifp, new_link);
|
||||
|
||||
/* Update if_baudrate to reflect the max possible speed */
|
||||
switch (sc->sc_proto) {
|
||||
@ -1802,7 +1797,7 @@ lagg_linkstate(struct lagg_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
lagg_port_state(struct ifnet *ifp)
|
||||
lagg_port_state(struct ifnet *ifp, int state)
|
||||
{
|
||||
struct lagg_port *lp = (struct lagg_port *)ifp->if_lagg;
|
||||
struct lagg_softc *sc = NULL;
|
||||
@ -1818,7 +1813,7 @@ lagg_port_state(struct ifnet *ifp)
|
||||
LAGG_WUNLOCK(sc);
|
||||
}
|
||||
|
||||
static struct lagg_port *
|
||||
struct lagg_port *
|
||||
lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp)
|
||||
{
|
||||
struct lagg_port *lp_next, *rval = NULL;
|
||||
|
@ -281,7 +281,7 @@ struct lagg_port {
|
||||
#define LAGG_UNLOCK_ASSERT(_sc) rm_assert(&(_sc)->sc_mtx, RA_UNLOCKED)
|
||||
|
||||
extern struct mbuf *(*lagg_input_p)(struct ifnet *, struct mbuf *);
|
||||
extern void (*lagg_linkstate_p)(struct ifnet *);
|
||||
extern void (*lagg_linkstate_p)(struct ifnet *, int );
|
||||
|
||||
int lagg_enqueue(struct ifnet *, struct mbuf *);
|
||||
|
||||
|
@ -500,7 +500,6 @@ struct ifmultiaddr *
|
||||
void if_free(struct ifnet *);
|
||||
void if_initname(struct ifnet *, const char *, int);
|
||||
void if_link_state_change(struct ifnet *, int);
|
||||
void if_link_state_change_cond(struct ifnet *, int, int);
|
||||
int if_printf(struct ifnet *, const char *, ...) __printflike(2, 3);
|
||||
void if_ref(struct ifnet *);
|
||||
void if_rele(struct ifnet *);
|
||||
|
@ -107,7 +107,6 @@ VNET_PCPUSTAT_SYSUNINIT(arpstat);
|
||||
#endif /* VIMAGE */
|
||||
|
||||
static VNET_DEFINE(int, arp_maxhold) = 1;
|
||||
static VNET_DEFINE(int, arp_on_link) = 1;
|
||||
|
||||
#define V_arpt_keep VNET(arpt_keep)
|
||||
#define V_arpt_down VNET(arpt_down)
|
||||
@ -115,7 +114,6 @@ static VNET_DEFINE(int, arp_on_link) = 1;
|
||||
#define V_arp_maxtries VNET(arp_maxtries)
|
||||
#define V_arp_proxyall VNET(arp_proxyall)
|
||||
#define V_arp_maxhold VNET(arp_maxhold)
|
||||
#define V_arp_on_link VNET(arp_on_link)
|
||||
|
||||
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_VNET | CTLFLAG_RW,
|
||||
&VNET_NAME(arpt_keep), 0,
|
||||
@ -138,9 +136,6 @@ SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_log_per_second,
|
||||
CTLFLAG_RW, &arp_maxpps, 0,
|
||||
"Maximum number of remotely triggered ARP messages that can be "
|
||||
"logged per second");
|
||||
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, arp_on_link, CTLFLAG_VNET | CTLFLAG_RW,
|
||||
&VNET_NAME(arp_on_link), 0,
|
||||
"Send gratuitous ARP's on interface link up events");
|
||||
|
||||
#define ARP_LOG(pri, ...) do { \
|
||||
if (ppsratecheck(&arp_lastlog, &arp_curpps, arp_maxpps)) \
|
||||
@ -161,7 +156,6 @@ static void arp_mark_lle_reachable(struct llentry *la);
|
||||
static void arp_iflladdr(void *arg __unused, struct ifnet *ifp);
|
||||
|
||||
static eventhandler_tag iflladdr_tag;
|
||||
static eventhandler_tag ifnet_link_event_tag;
|
||||
|
||||
static const struct netisr_handler arp_nh = {
|
||||
.nh_name = "arp",
|
||||
@ -1190,99 +1184,43 @@ arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
|
||||
|
||||
if (ntohl(dst_in->sin_addr.s_addr) == INADDR_ANY)
|
||||
return;
|
||||
arp_announce_addr(ifp, &dst_in->sin_addr, IF_LLADDR(ifp));
|
||||
arp_announce_ifaddr(ifp, dst_in->sin_addr, IF_LLADDR(ifp));
|
||||
|
||||
arp_add_ifa_lle(ifp, dst);
|
||||
}
|
||||
|
||||
void __noinline
|
||||
arp_announce_addr(struct ifnet *ifp, const struct in_addr *addr, u_char *enaddr)
|
||||
void
|
||||
arp_announce_ifaddr(struct ifnet *ifp, struct in_addr addr, u_char *enaddr)
|
||||
{
|
||||
|
||||
if (ntohl(addr->s_addr) != INADDR_ANY)
|
||||
arprequest(ifp, addr, addr, enaddr);
|
||||
if (ntohl(addr.s_addr) != INADDR_ANY)
|
||||
arprequest(ifp, &addr, &addr, enaddr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send gratuitous ARPs for all interfaces addresses to notify other nodes of
|
||||
* changes.
|
||||
*
|
||||
* This is a noop if the interface isn't up or has been flagged for no ARP.
|
||||
* Sends gratuitous ARPs for each ifaddr to notify other
|
||||
* nodes about the address change.
|
||||
*/
|
||||
void __noinline
|
||||
arp_announce(struct ifnet *ifp)
|
||||
static __noinline void
|
||||
arp_handle_ifllchange(struct ifnet *ifp)
|
||||
{
|
||||
int i, cnt, entries;
|
||||
u_char *lladdr;
|
||||
struct ifaddr *ifa;
|
||||
struct in_addr *addr, *head;
|
||||
|
||||
if (!(ifp->if_flags & IFF_UP) || (ifp->if_flags & IFF_NOARP) ||
|
||||
ifp->if_addr == NULL)
|
||||
return;
|
||||
|
||||
entries = 8;
|
||||
cnt = 0;
|
||||
head = malloc(sizeof(*addr) * entries, M_TEMP, M_NOWAIT);
|
||||
if (head == NULL) {
|
||||
log(LOG_INFO, "arp_announce: malloc %d entries failed\n",
|
||||
entries);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Take a copy then process to avoid locking issues. */
|
||||
IF_ADDR_RLOCK(ifp);
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET)
|
||||
continue;
|
||||
|
||||
if (cnt == entries) {
|
||||
addr = (struct in_addr *)realloc(head, sizeof(*addr) *
|
||||
(entries + 8), M_TEMP, M_NOWAIT);
|
||||
if (addr == NULL) {
|
||||
log(LOG_INFO, "arp_announce: realloc to %d "
|
||||
"entries failed\n", entries + 8);
|
||||
/* Process what we have. */
|
||||
break;
|
||||
}
|
||||
entries += 8;
|
||||
head = addr;
|
||||
}
|
||||
|
||||
addr = head + cnt;
|
||||
bcopy(IFA_IN(ifa), addr, sizeof(*addr));
|
||||
cnt++;
|
||||
if (ifa->ifa_addr->sa_family == AF_INET)
|
||||
arp_ifinit(ifp, ifa);
|
||||
}
|
||||
IF_ADDR_RUNLOCK(ifp);
|
||||
|
||||
if (cnt > 0) {
|
||||
lladdr = IF_LLADDR(ifp);
|
||||
for (i = 0; i < cnt; i++) {
|
||||
arp_announce_addr(ifp, head + i, lladdr);
|
||||
}
|
||||
}
|
||||
free(head, M_TEMP);
|
||||
}
|
||||
|
||||
/*
|
||||
* A handler for interface linkstate change events.
|
||||
*/
|
||||
static void
|
||||
arp_ifnet_link_event(void *arg __unused, struct ifnet *ifp, int linkstate)
|
||||
{
|
||||
|
||||
if (linkstate == LINK_STATE_UP && V_arp_on_link)
|
||||
arp_announce(ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
* A handler for interface link layer address change events.
|
||||
* A handler for interface link layer address change event.
|
||||
*/
|
||||
static __noinline void
|
||||
arp_iflladdr(void *arg __unused, struct ifnet *ifp)
|
||||
{
|
||||
|
||||
arp_announce(ifp);
|
||||
if ((ifp->if_flags & IFF_UP) != 0)
|
||||
arp_handle_ifllchange(ifp);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1290,12 +1228,8 @@ arp_init(void)
|
||||
{
|
||||
|
||||
netisr_register(&arp_nh);
|
||||
|
||||
if (IS_DEFAULT_VNET(curvnet)) {
|
||||
if (IS_DEFAULT_VNET(curvnet))
|
||||
iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event,
|
||||
arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
|
||||
ifnet_link_event_tag = EVENTHANDLER_REGISTER(ifnet_link_event,
|
||||
arp_ifnet_link_event, 0, EVENTHANDLER_PRI_ANY);
|
||||
}
|
||||
}
|
||||
SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0);
|
||||
|
@ -119,8 +119,7 @@ int arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
|
||||
void arprequest(struct ifnet *, const struct in_addr *,
|
||||
const struct in_addr *, u_char *);
|
||||
void arp_ifinit(struct ifnet *, struct ifaddr *);
|
||||
void arp_announce(struct ifnet *);
|
||||
void arp_announce_addr(struct ifnet *, const struct in_addr *addr, u_char *);
|
||||
void arp_announce_ifaddr(struct ifnet *, struct in_addr addr, u_char *);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -129,9 +129,6 @@ extern struct rmlock in_ifaddr_lock;
|
||||
#define IN_IFADDR_WLOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_WLOCKED)
|
||||
#define IN_IFADDR_WUNLOCK() rm_wunlock(&in_ifaddr_lock)
|
||||
|
||||
#define IFA_IN(ifa) \
|
||||
(&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr)
|
||||
|
||||
/*
|
||||
* Macro for finding the internet address structure (in_ifaddr)
|
||||
* corresponding to one of our IP addresses (in_addr).
|
||||
|
@ -1009,12 +1009,13 @@ static void
|
||||
carp_send_arp(struct carp_softc *sc)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
struct in_addr addr;
|
||||
|
||||
CARP_FOREACH_IFA(sc, ifa) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET)
|
||||
continue;
|
||||
arp_announce_addr(sc->sc_carpdev, IFA_IN(ifa),
|
||||
LLADDR(&sc->sc_addr));
|
||||
addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
|
||||
arp_announce_ifaddr(sc->sc_carpdev, addr, LLADDR(&sc->sc_addr));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1036,16 +1037,18 @@ carp_iamatch(struct ifaddr *ifa, uint8_t **enaddr)
|
||||
static void
|
||||
carp_send_na(struct carp_softc *sc)
|
||||
{
|
||||
static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
|
||||
struct ifaddr *ifa;
|
||||
struct in6_addr *in6;
|
||||
|
||||
CARP_FOREACH_IFA(sc, ifa) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6 ||
|
||||
IFA_ND6_NA_UNSOLICITED_SKIP(ifa))
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
|
||||
nd6_na_output_unsolicited_addr(sc->sc_carpdev, IFA_IN6(ifa),
|
||||
IFA_ND6_NA_BASE_FLAGS(sc->sc_carpdev, ifa));
|
||||
DELAY(nd6_na_unsolicited_addr_delay(ifa));
|
||||
in6 = IFA_IN6(ifa);
|
||||
nd6_na_output(sc->sc_carpdev, &mcast, in6,
|
||||
ND_NA_FLAG_OVERRIDE, 1, NULL);
|
||||
DELAY(1000); /* XXX */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ VNET_DECLARE(int, icmp6_nodeinfo_oldmcprefix);
|
||||
#define V_icmp6_nodeinfo_oldmcprefix VNET(icmp6_nodeinfo_oldmcprefix)
|
||||
|
||||
/*
|
||||
* Definitions of some constant IP6 addresses.
|
||||
* Definitions of some costant IP6 addresses.
|
||||
*/
|
||||
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
|
||||
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
|
||||
|
@ -399,16 +399,6 @@ struct in6_rrenumreq {
|
||||
#define IA6_SIN6(ia) (&((ia)->ia_addr))
|
||||
#define IA6_DSTSIN6(ia) (&((ia)->ia_dstaddr))
|
||||
#define IFA_IN6(x) (&((struct sockaddr_in6 *)((x)->ifa_addr))->sin6_addr)
|
||||
#define IFA_IN6_FLAGS(ifa) ((struct in6_ifaddr *)ifa)->ia6_flags
|
||||
#define IFA_ND6_NA_BASE_FLAGS(ifp, ifa) \
|
||||
(IFA_IN6_FLAGS(ifa) & IN6_IFF_ANYCAST ? 0 : ND_NA_FLAG_OVERRIDE) | \
|
||||
((V_ip6_forwarding && !(ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && \
|
||||
V_ip6_norbit_raif)) ? ND_NA_FLAG_ROUTER : 0)
|
||||
#define IFA_ND6_NA_UNSOLICITED_SKIP(ifa) \
|
||||
(IFA_IN6_FLAGS(ifa) & (IN6_IFF_DUPLICATED | IN6_IFF_DEPRECATED | \
|
||||
IN6_IFF_TENTATIVE)) != 0
|
||||
#define IN6_MAX_ANYCAST_DELAY_TIME_MS 1000000
|
||||
#define IN6_BROADCAST_DELAY_TIME_MS 1000
|
||||
#define IFA_DSTIN6(x) (&((struct sockaddr_in6 *)((x)->ifa_dstaddr))->sin6_addr)
|
||||
|
||||
#define IFPR_IN6(x) (&((struct sockaddr_in6 *)((x)->ifpr_prefix))->sin6_addr)
|
||||
|
@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
@ -103,12 +102,8 @@ VNET_DEFINE(int, nd6_maxnudhint) = 0; /* max # of subsequent upper
|
||||
* layer hints */
|
||||
static VNET_DEFINE(int, nd6_maxqueuelen) = 1; /* max pkts cached in unresolved
|
||||
* ND entries */
|
||||
|
||||
static VNET_DEFINE(int, nd6_on_link) = 1; /* Send unsolicited ND's on link up */
|
||||
|
||||
#define V_nd6_maxndopt VNET(nd6_maxndopt)
|
||||
#define V_nd6_maxqueuelen VNET(nd6_maxqueuelen)
|
||||
#define V_nd6_on_link VNET(nd6_on_link)
|
||||
|
||||
#ifdef ND6_DEBUG
|
||||
VNET_DEFINE(int, nd6_debug) = 1;
|
||||
@ -117,7 +112,6 @@ VNET_DEFINE(int, nd6_debug) = 0;
|
||||
#endif
|
||||
|
||||
static eventhandler_tag lle_event_eh;
|
||||
static eventhandler_tag ifnet_link_event_eh;
|
||||
|
||||
/* for debugging? */
|
||||
#if 0
|
||||
@ -202,14 +196,6 @@ nd6_lle_event(void *arg __unused, struct llentry *lle, int evt)
|
||||
type == RTM_ADD ? RTF_UP: 0), 0, RT_DEFAULT_FIB);
|
||||
}
|
||||
|
||||
static void
|
||||
nd6_ifnet_link_event(void *arg __unused, struct ifnet *ifp, int linkstate)
|
||||
{
|
||||
|
||||
if (linkstate == LINK_STATE_UP && V_nd6_on_link)
|
||||
nd6_na_output_unsolicited(ifp);
|
||||
}
|
||||
|
||||
void
|
||||
nd6_init(void)
|
||||
{
|
||||
@ -225,12 +211,9 @@ nd6_init(void)
|
||||
nd6_slowtimo, curvnet);
|
||||
|
||||
nd6_dad_init();
|
||||
if (IS_DEFAULT_VNET(curvnet)) {
|
||||
if (IS_DEFAULT_VNET(curvnet))
|
||||
lle_event_eh = EVENTHANDLER_REGISTER(lle_event, nd6_lle_event,
|
||||
NULL, EVENTHANDLER_PRI_ANY);
|
||||
ifnet_link_event_eh = EVENTHANDLER_REGISTER(ifnet_link_event,
|
||||
nd6_ifnet_link_event, NULL, EVENTHANDLER_PRI_ANY);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VIMAGE
|
||||
@ -240,10 +223,8 @@ nd6_destroy()
|
||||
|
||||
callout_drain(&V_nd6_slowtimo_ch);
|
||||
callout_drain(&V_nd6_timer_ch);
|
||||
if (IS_DEFAULT_VNET(curvnet)) {
|
||||
if (IS_DEFAULT_VNET(curvnet))
|
||||
EVENTHANDLER_DEREGISTER(lle_event, lle_event_eh);
|
||||
EVENTHANDLER_DEREGISTER(ifnet_link_event, ifnet_link_event_eh);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2476,18 +2457,13 @@ static int nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS);
|
||||
SYSCTL_DECL(_net_inet6_icmp6);
|
||||
#endif
|
||||
SYSCTL_NODE(_net_inet6_icmp6, ICMPV6CTL_ND6_DRLIST, nd6_drlist,
|
||||
CTLFLAG_RD, nd6_sysctl_drlist, "List default routers");
|
||||
CTLFLAG_RD, nd6_sysctl_drlist, "");
|
||||
SYSCTL_NODE(_net_inet6_icmp6, ICMPV6CTL_ND6_PRLIST, nd6_prlist,
|
||||
CTLFLAG_RD, nd6_sysctl_prlist, "List prefixes");
|
||||
CTLFLAG_RD, nd6_sysctl_prlist, "");
|
||||
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXQLEN, nd6_maxqueuelen,
|
||||
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_maxqueuelen), 1,
|
||||
"Max packets cached in unresolved ND entries");
|
||||
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_maxqueuelen), 1, "");
|
||||
SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, nd6_gctimer,
|
||||
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_gctimer), (60 * 60 * 24),
|
||||
"Interface in seconds between garbage collection passes");
|
||||
SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, nd6_on_link, CTLFLAG_VNET | CTLFLAG_RW,
|
||||
&VNET_NAME(nd6_on_link), 0,
|
||||
"Send unsolicited neighbor discovery on interface link up events");
|
||||
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_gctimer), (60 * 60 * 24), "");
|
||||
|
||||
static int
|
||||
nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS)
|
||||
|
@ -398,10 +398,6 @@ void nd6_init(void);
|
||||
#ifdef VIMAGE
|
||||
void nd6_destroy(void);
|
||||
#endif
|
||||
void nd6_na_output_unsolicited(struct ifnet *);
|
||||
void nd6_na_output_unsolicited_addr(struct ifnet *, const struct in6_addr *,
|
||||
u_long);
|
||||
int nd6_na_unsolicited_addr_delay(struct ifaddr *);
|
||||
struct nd_ifinfo *nd6_ifattach(struct ifnet *);
|
||||
void nd6_ifdetach(struct nd_ifinfo *);
|
||||
int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *);
|
||||
|
@ -124,16 +124,20 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
||||
struct in6_addr saddr6 = ip6->ip6_src;
|
||||
struct in6_addr daddr6 = ip6->ip6_dst;
|
||||
struct in6_addr taddr6;
|
||||
struct in6_addr myaddr6;
|
||||
char *lladdr = NULL;
|
||||
struct ifaddr *ifa = NULL;
|
||||
u_long flags;
|
||||
int lladdrlen = 0;
|
||||
int proxy = 0;
|
||||
int anycast = 0, proxy = 0, tentative = 0;
|
||||
int tlladdr;
|
||||
int rflag;
|
||||
union nd_opts ndopts;
|
||||
struct sockaddr_dl proxydl;
|
||||
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
|
||||
|
||||
rflag = (V_ip6_forwarding) ? ND_NA_FLAG_ROUTER : 0;
|
||||
if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && V_ip6_norbit_raif)
|
||||
rflag = 0;
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, off, icmp6len,);
|
||||
nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
|
||||
@ -225,7 +229,10 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
||||
* In implementation, we add target link-layer address by default.
|
||||
* We do not add one in MUST NOT cases.
|
||||
*/
|
||||
tlladdr = !IN6_IS_ADDR_MULTICAST(&daddr6);
|
||||
if (!IN6_IS_ADDR_MULTICAST(&daddr6))
|
||||
tlladdr = 0;
|
||||
else
|
||||
tlladdr = 1;
|
||||
|
||||
/*
|
||||
* Target address (taddr6) must be either:
|
||||
@ -282,6 +289,9 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
||||
*/
|
||||
goto freeit;
|
||||
}
|
||||
myaddr6 = *IFA_IN6(ifa);
|
||||
anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST;
|
||||
tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE;
|
||||
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED)
|
||||
goto freeit;
|
||||
|
||||
@ -293,7 +303,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &saddr6)) {
|
||||
if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) {
|
||||
nd6log((LOG_INFO, "nd6_ns_input: duplicate IP6 address %s\n",
|
||||
ip6_sprintf(ip6bufs, &saddr6)));
|
||||
goto freeit;
|
||||
@ -311,7 +321,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
||||
*
|
||||
* The processing is defined in RFC 2462.
|
||||
*/
|
||||
if (IFA_IN6_FLAGS(ifa) & IN6_IFF_TENTATIVE) {
|
||||
if (tentative) {
|
||||
/*
|
||||
* If source address is unspecified address, it is for
|
||||
* duplicate address detection.
|
||||
@ -325,10 +335,6 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
||||
goto freeit;
|
||||
}
|
||||
|
||||
flags = IFA_ND6_NA_BASE_FLAGS(ifp, ifa);
|
||||
if (proxy || !tlladdr)
|
||||
flags &= ~ND_NA_FLAG_OVERRIDE;
|
||||
|
||||
/*
|
||||
* If the source address is unspecified address, entries must not
|
||||
* be created or updated.
|
||||
@ -343,16 +349,20 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
||||
in6_all = in6addr_linklocal_allnodes;
|
||||
if (in6_setscope(&in6_all, ifp, NULL) != 0)
|
||||
goto bad;
|
||||
nd6_na_output_fib(ifp, &in6_all, &taddr6, flags, tlladdr,
|
||||
proxy ? (struct sockaddr *)&proxydl : NULL, M_GETFIB(m));
|
||||
nd6_na_output_fib(ifp, &in6_all, &taddr6,
|
||||
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
|
||||
rflag, tlladdr, proxy ? (struct sockaddr *)&proxydl : NULL,
|
||||
M_GETFIB(m));
|
||||
goto freeit;
|
||||
}
|
||||
|
||||
nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen,
|
||||
ND_NEIGHBOR_SOLICIT, 0);
|
||||
|
||||
nd6_na_output_fib(ifp, &saddr6, &taddr6, flags | ND_NA_FLAG_SOLICITED,
|
||||
tlladdr, proxy ? (struct sockaddr *)&proxydl : NULL, M_GETFIB(m));
|
||||
nd6_na_output_fib(ifp, &saddr6, &taddr6,
|
||||
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
|
||||
rflag | ND_NA_FLAG_SOLICITED, tlladdr,
|
||||
proxy ? (struct sockaddr *)&proxydl : NULL, M_GETFIB(m));
|
||||
freeit:
|
||||
if (ifa != NULL)
|
||||
ifa_free(ifa);
|
||||
@ -1587,111 +1597,3 @@ nd6_dad_na_input(struct ifaddr *ifa)
|
||||
nd6_dad_rele(dp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send unsolicited neighbor advertisements for all interface addresses to
|
||||
* notify other nodes of changes.
|
||||
*
|
||||
* This is a noop if the interface isn't up.
|
||||
*/
|
||||
void __noinline
|
||||
nd6_na_output_unsolicited(struct ifnet *ifp)
|
||||
{
|
||||
int i, cnt, entries;
|
||||
struct ifaddr *ifa;
|
||||
struct ann {
|
||||
struct in6_addr addr;
|
||||
u_long flags;
|
||||
int delay;
|
||||
} *ann1, *head;
|
||||
|
||||
if (!(ifp->if_flags & IFF_UP))
|
||||
return;
|
||||
|
||||
entries = 8;
|
||||
cnt = 0;
|
||||
head = malloc(sizeof(struct ann) * entries, M_TEMP, M_WAITOK);
|
||||
|
||||
/* Take a copy then process to avoid locking issues. */
|
||||
IF_ADDR_RLOCK(ifp);
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6 ||
|
||||
IFA_ND6_NA_UNSOLICITED_SKIP(ifa))
|
||||
continue;
|
||||
|
||||
if (cnt == entries) {
|
||||
ann1 = (struct ann*)realloc(head, sizeof(struct ann) *
|
||||
(entries + 8), M_TEMP, M_NOWAIT);
|
||||
if (ann1 == NULL) {
|
||||
log(LOG_INFO, "nd6_announce: realloc to %d "
|
||||
"entries failed\n", entries + 8);
|
||||
/* Process what we have. */
|
||||
break;
|
||||
}
|
||||
entries += 8;
|
||||
head = ann1;
|
||||
}
|
||||
|
||||
ann1 = head + cnt;
|
||||
bcopy(IFA_IN6(ifa), &ann1->addr, sizeof(ann1->addr));
|
||||
ann1->flags = IFA_ND6_NA_BASE_FLAGS(ifp, ifa);
|
||||
ann1->delay = nd6_na_unsolicited_addr_delay(ifa);
|
||||
cnt++;
|
||||
}
|
||||
IF_ADDR_RUNLOCK(ifp);
|
||||
|
||||
for (i = 0; i < cnt;) {
|
||||
ann1 = head + i;
|
||||
nd6_na_output_unsolicited_addr(ifp, &ann1->addr, ann1->flags);
|
||||
i++;
|
||||
if (i == cnt)
|
||||
break;
|
||||
/* XXX DELAY needs to be done in taskqueue to avoid stalling. */
|
||||
//DELAY(ann1->delay);
|
||||
}
|
||||
free(head, M_TEMP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the delay required for announcements of the address as per RFC 4861.
|
||||
*/
|
||||
int
|
||||
nd6_na_unsolicited_addr_delay(struct ifaddr *ifa)
|
||||
{
|
||||
|
||||
if (IFA_IN6_FLAGS(ifa) & IN6_IFF_ANYCAST) {
|
||||
/*
|
||||
* Random value between 0 and MAX_ANYCAST_DELAY_TIME
|
||||
* as per section 7.2.7.
|
||||
*/
|
||||
return (random() % IN6_MAX_ANYCAST_DELAY_TIME_MS);
|
||||
}
|
||||
|
||||
/* Small delay as per section 7.2.6. */
|
||||
return (IN6_BROADCAST_DELAY_TIME_MS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send an unsolicited neighbor advertisement for an address to notify other
|
||||
* nodes of changes.
|
||||
*/
|
||||
void __noinline
|
||||
nd6_na_output_unsolicited_addr(struct ifnet *ifp, const struct in6_addr *addr,
|
||||
u_long flags)
|
||||
{
|
||||
int error;
|
||||
struct in6_addr mcast;
|
||||
|
||||
mcast = in6addr_linklocal_allnodes;
|
||||
if ((error = in6_setscope(&mcast, ifp, NULL)) != 0) {
|
||||
/*
|
||||
* This shouldn't by possible as the only error is for loopback
|
||||
* address which we're not using.
|
||||
*/
|
||||
log(LOG_INFO, "in6_setscope: on mcast failed: %d\n", error);
|
||||
return;
|
||||
}
|
||||
nd6_na_output(ifp, &mcast, addr, flags, 1, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user