4 new sysctls to avoid ipv6 DoS attacks from OpenBSD
This commit is contained in:
parent
2c4ba053cf
commit
443eb0a284
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: sysctl.7,v 1.72 2012/06/22 14:54:35 christos Exp $
|
||||
.\" $NetBSD: sysctl.7,v 1.73 2012/06/23 03:13:41 christos Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
|
@ -29,7 +29,7 @@
|
|||
.\"
|
||||
.\" @(#)sysctl.3 8.4 (Berkeley) 5/9/95
|
||||
.\"
|
||||
.Dd June 20, 2012
|
||||
.Dd June 22, 2012
|
||||
.Dt SYSCTL 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -1614,9 +1614,13 @@ The currently defined protocols and names are:
|
|||
.It ip6 log_interval integer yes
|
||||
.It ip6 lowportmax integer yes
|
||||
.It ip6 lowportmin integer yes
|
||||
.It ip6 maxdynroutes integer yes
|
||||
.It ip6 maxifprefixes integer yes
|
||||
.It ip6 maxifdefrouters integer yes
|
||||
.It ip6 maxflows integer yes
|
||||
.It ip6 maxfragpackets integer yes
|
||||
.It ip6 maxfrags integer yes
|
||||
.It ip6 neighborgcthresh integer yes
|
||||
.It ip6 redirect integer yes
|
||||
.It ip6 rr_prune integer yes
|
||||
.It ip6 use_deprecated integer yes
|
||||
|
@ -1715,6 +1719,18 @@ The lowest port number to use for TCP and UDP reserved port allocation.
|
|||
This cannot be set to less than 0 or greater than 1024, and must
|
||||
be smaller than
|
||||
.Li ip6.lowportmax .
|
||||
.It Li ip6.maxdynroutes
|
||||
Maximum number of routes created by redirect.
|
||||
Set it to negative to disable.
|
||||
The default value is 4096.
|
||||
.It Li ip6.maxifprefixes
|
||||
Maximum number of prefixes created by route advertisements per interface.
|
||||
Set it to negative to disable.
|
||||
The default value is 16.
|
||||
.It Li ip6.maxifdefrouters 16
|
||||
Maximum number of default routers created by route advertisements per interface.
|
||||
Set it to negative to disable.
|
||||
The default value is 16.
|
||||
.It Li ip6.maxflows
|
||||
IPv6 Fast Forwarding is enabled by default.
|
||||
If set to 0, IPv6 Fast Forwarding is disabled.
|
||||
|
@ -1731,6 +1747,10 @@ The maximum number of fragments the node will accept.
|
|||
0 means that the node will not accept any fragments.
|
||||
\-1 means that the node will accept as many fragments as it receives.
|
||||
The flag is provided basically for avoiding possible DoS attacks.
|
||||
.It Li ip6.neighborgcthresh
|
||||
Maximum number of entries in neighbor cache.
|
||||
Set to negative to disable.
|
||||
The default value is 2048.
|
||||
.It Li ip6.redirect
|
||||
If set to 1, ICMPv6 redirects may be sent by the node.
|
||||
This option is ignored unless the node is routing IP packets,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: icmp6.c,v 1.160 2012/03/22 20:34:40 drochner Exp $ */
|
||||
/* $NetBSD: icmp6.c,v 1.161 2012/06/23 03:14:03 christos Exp $ */
|
||||
/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.160 2012/03/22 20:34:40 drochner Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.161 2012/06/23 03:14:03 christos Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -2279,6 +2279,8 @@ icmp6_redirect_input(struct mbuf *m, int off)
|
|||
* (there will be additional hops, though).
|
||||
*/
|
||||
rtcount = rt_timer_count(icmp6_redirect_timeout_q);
|
||||
if (0 <= ip6_maxdynroutes && rtcount >= ip6_maxdynroutes)
|
||||
goto freeit;
|
||||
if (0 <= icmp6_redirect_hiwat && rtcount > icmp6_redirect_hiwat)
|
||||
return;
|
||||
else if (0 <= icmp6_redirect_lowat &&
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6.c,v 1.160 2012/03/13 18:40:59 elad Exp $ */
|
||||
/* $NetBSD: in6.c,v 1.161 2012/06/23 03:14:03 christos Exp $ */
|
||||
/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.160 2012/03/13 18:40:59 elad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.161 2012/06/23 03:14:03 christos Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_pfil_hooks.h"
|
||||
|
@ -2283,6 +2283,8 @@ in6_domifattach(struct ifnet *ifp)
|
|||
|
||||
ext->nd_ifinfo = nd6_ifattach(ifp);
|
||||
ext->scope6_id = scope6_ifattach(ifp);
|
||||
ext->nprefixes = 0;
|
||||
ext->ndefrouters = 0;
|
||||
return ext;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6_proto.c,v 1.96 2012/03/22 20:34:40 drochner Exp $ */
|
||||
/* $NetBSD: in6_proto.c,v 1.97 2012/06/23 03:14:03 christos Exp $ */
|
||||
/* $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.96 2012/03/22 20:34:40 drochner Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.97 2012/06/23 03:14:03 christos Exp $");
|
||||
|
||||
#include "opt_gateway.h"
|
||||
#include "opt_inet.h"
|
||||
|
@ -439,6 +439,10 @@ int ip6_rr_prune = 5; /* router renumbering prefix
|
|||
* walk list every 5 sec. */
|
||||
int ip6_mcast_pmtu = 0; /* enable pMTU discovery for multicast? */
|
||||
int ip6_v6only = 1;
|
||||
int ip6_neighborgcthresh = 2048; /* Threshold # of NDP entries for GC */
|
||||
int ip6_maxifprefixes = 16; /* Max acceptable prefixes via RA per IF */
|
||||
int ip6_maxifdefrouters = 16; /* Max acceptable def routers via RA */
|
||||
int ip6_maxdynroutes = 4096; /* Max # of routes created via redirect */
|
||||
|
||||
int ip6_keepfaith = 0;
|
||||
time_t ip6_log_time = 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6_var.h,v 1.64 2009/01/15 23:22:15 christos Exp $ */
|
||||
/* $NetBSD: in6_var.h,v 1.65 2012/06/23 03:14:03 christos Exp $ */
|
||||
/* $KAME: in6_var.h,v 1.81 2002/06/08 11:16:51 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -94,6 +94,8 @@ struct in6_ifextra {
|
|||
struct icmp6_ifstat *icmp6_ifstat;
|
||||
struct nd_ifinfo *nd_ifinfo;
|
||||
struct scope6_id *scope6_id;
|
||||
int nprefixes;
|
||||
int ndefrouters;
|
||||
};
|
||||
|
||||
struct in6_ifaddr {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip6_input.c,v 1.138 2012/06/22 14:54:35 christos Exp $ */
|
||||
/* $NetBSD: ip6_input.c,v 1.139 2012/06/23 03:14:04 christos Exp $ */
|
||||
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.138 2012/06/22 14:54:35 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.139 2012/06/23 03:14:04 christos Exp $");
|
||||
|
||||
#include "opt_gateway.h"
|
||||
#include "opt_inet.h"
|
||||
|
@ -1977,6 +1977,38 @@ sysctl_net_inet6_ip6_setup(struct sysctllog **clog)
|
|||
SYSCTL_DESCR("selected algorithm"),
|
||||
sysctl_rfc6056_selected6, 0, NULL, RFC6056_MAXLEN,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
sysctl_createv(clog, 0, NULL, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
|
||||
CTLTYPE_INT, "neighborgcthresh",
|
||||
SYSCTL_DESCR("Maximum number of entries in neighbor"
|
||||
" cache"),
|
||||
NULL, 1, &ip6_neighborgcthresh, 0,
|
||||
CTL_NET, PF_INET6, IPPROTO_IPV6,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
sysctl_createv(clog, 0, NULL, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
|
||||
CTLTYPE_INT, "maxifprefixes",
|
||||
SYSCTL_DESCR("Maximum number of prefixes created by"
|
||||
" route advertisement per interface"),
|
||||
NULL, 1, &ip6_maxifprefixes, 0,
|
||||
CTL_NET, PF_INET6, IPPROTO_IPV6,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
sysctl_createv(clog, 0, NULL, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
|
||||
CTLTYPE_INT, "maxifdefrouters",
|
||||
SYSCTL_DESCR("Maximum number of default routers created"
|
||||
" by route advertisement per interface"),
|
||||
NULL, 1, &ip6_maxifdefrouters, 0,
|
||||
CTL_NET, PF_INET6, IPPROTO_IPV6,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
sysctl_createv(clog, 0, NULL, NULL,
|
||||
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
|
||||
CTLTYPE_INT, "maxdynroutes",
|
||||
SYSCTL_DESCR("Maximum number of routes created via"
|
||||
" redirect"),
|
||||
NULL, 1, &ip6_maxdynroutes, 0,
|
||||
CTL_NET, PF_INET6, IPPROTO_IPV6,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip6_var.h,v 1.58 2012/01/19 13:19:34 liamjfoy Exp $ */
|
||||
/* $NetBSD: ip6_var.h,v 1.59 2012/06/23 03:14:04 christos Exp $ */
|
||||
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -272,6 +272,11 @@ extern int ip6_rr_prune; /* router renumbering prefix
|
|||
* walk list every 5 sec. */
|
||||
extern int ip6_mcast_pmtu; /* enable pMTU discovery for multicast? */
|
||||
extern int ip6_v6only;
|
||||
extern int ip6_neighborgcthresh; /* Threshold # of NDP entries for GC */
|
||||
extern int ip6_maxifprefixes; /* Max acceptable prefixes via RA per IF */
|
||||
extern int ip6_maxifdefrouters; /* Max acceptable def routers via RA */
|
||||
extern int ip6_maxdynroutes; /* Max # of routes created via redirect */
|
||||
|
||||
|
||||
extern struct socket *ip6_mrouter; /* multicast routing daemon */
|
||||
extern int ip6_sendredirects; /* send IP redirects when forwarding? */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nd6.c,v 1.142 2012/03/22 20:34:41 drochner Exp $ */
|
||||
/* $NetBSD: nd6.c,v 1.143 2012/06/23 03:14:04 christos Exp $ */
|
||||
/* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.142 2012/03/22 20:34:41 drochner Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.143 2012/06/23 03:14:04 christos Exp $");
|
||||
|
||||
#include "opt_ipsec.h"
|
||||
|
||||
|
@ -131,6 +131,16 @@ static int fill_prlist(void *, size_t *, size_t);
|
|||
|
||||
MALLOC_DEFINE(M_IP6NDP, "NDP", "IPv6 Neighbour Discovery");
|
||||
|
||||
#define LN_DEQUEUE(ln) do { \
|
||||
(ln)->ln_next->ln_prev = (ln)->ln_prev; \
|
||||
(ln)->ln_prev->ln_next = (ln)->ln_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define LN_INSERTHEAD(ln) do { \
|
||||
(ln)->ln_next = llinfo_nd6.ln_next; \
|
||||
llinfo_nd6.ln_next = (ln); \
|
||||
(ln)->ln_prev = &llinfo_nd6; \
|
||||
(ln)->ln_next->ln_prev = (ln); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
void
|
||||
nd6_init(void)
|
||||
{
|
||||
|
@ -473,6 +483,7 @@ nd6_llinfo_timer(void *arg)
|
|||
}
|
||||
break;
|
||||
|
||||
case ND6_LLINFO_PURGE:
|
||||
case ND6_LLINFO_STALE:
|
||||
/* Garbage Collection(RFC 2461 5.3) */
|
||||
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||
|
@ -1332,6 +1343,35 @@ nd6_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
ln->ln_prev = &llinfo_nd6;
|
||||
ln->ln_next->ln_prev = ln;
|
||||
|
||||
/*
|
||||
* If we have too many cache entries, initiate immediate
|
||||
* purging for some "less recently used" entries. Note that
|
||||
* we cannot directly call nd6_free() here because it would
|
||||
* cause re-entering rtable related routines triggering an LOR
|
||||
* problem for FreeBSD.
|
||||
*/
|
||||
if (ip6_neighborgcthresh >= 0 &&
|
||||
nd6_inuse >= ip6_neighborgcthresh) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10 && llinfo_nd6.ln_prev != ln; i++) {
|
||||
struct llinfo_nd6 *ln_end = llinfo_nd6.ln_prev;
|
||||
|
||||
/* Move this entry to the head */
|
||||
LN_DEQUEUE(ln_end);
|
||||
LN_INSERTHEAD(ln_end);
|
||||
|
||||
if (ND6_LLINFO_PERMANENT(ln_end))
|
||||
continue;
|
||||
|
||||
if (ln_end->ln_state > ND6_LLINFO_INCOMPLETE)
|
||||
ln_end->ln_state = ND6_LLINFO_STALE;
|
||||
else
|
||||
ln_end->ln_state = ND6_LLINFO_PURGE;
|
||||
nd6_llinfo_settimer(ln_end, 0);
|
||||
}
|
||||
}
|
||||
|
||||
RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
|
||||
/*
|
||||
* check if rt_getkey(rt) is an address assigned
|
||||
|
@ -2043,6 +2083,14 @@ nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0,
|
|||
goto sendpkt; /* send anyway */
|
||||
}
|
||||
|
||||
/*
|
||||
* Move this entry to the head of the queue so that it is less likely
|
||||
* for this entry to be a target of forced garbage collection (see
|
||||
* nd6_rtrequest()).
|
||||
*/
|
||||
LN_DEQUEUE(ln);
|
||||
LN_INSERTHEAD(ln);
|
||||
|
||||
/* We don't have to do link-layer address resolution on a p2p link. */
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
|
||||
ln->ln_state < ND6_LLINFO_REACHABLE) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nd6.h,v 1.56 2011/11/19 22:51:29 tls Exp $ */
|
||||
/* $NetBSD: nd6.h,v 1.57 2012/06/23 03:14:04 christos Exp $ */
|
||||
/* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -51,6 +51,7 @@ struct llinfo_nd6 {
|
|||
struct callout ln_timer_ch;
|
||||
};
|
||||
|
||||
#define ND6_LLINFO_PURGE -3
|
||||
#define ND6_LLINFO_NOSTATE -2
|
||||
/*
|
||||
* We don't need the WAITDELETE state any more, but we keep the definition
|
||||
|
@ -303,6 +304,8 @@ struct nd_prefix {
|
|||
int ndpr_refcnt; /* reference couter from addresses */
|
||||
};
|
||||
|
||||
#define ndpr_next ndpr_entry.le_next
|
||||
|
||||
#define ndpr_raf ndpr_flags
|
||||
#define ndpr_raf_onlink ndpr_flags.onlink
|
||||
#define ndpr_raf_auto ndpr_flags.autonomous
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nd6_rtr.c,v 1.82 2011/11/19 22:51:29 tls Exp $ */
|
||||
/* $NetBSD: nd6_rtr.c,v 1.83 2012/06/23 03:14:04 christos Exp $ */
|
||||
/* $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.82 2011/11/19 22:51:29 tls Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.83 2012/06/23 03:14:04 christos Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -79,8 +79,9 @@ static void defrouter_delreq(struct nd_defrouter *);
|
|||
static void nd6_rtmsg(int, struct rtentry *);
|
||||
|
||||
static int in6_init_prefix_ltimes(struct nd_prefix *);
|
||||
static void in6_init_address_ltimes(struct nd_prefix *ndpr,
|
||||
struct in6_addrlifetime *lt6);
|
||||
static void in6_init_address_ltimes(struct nd_prefix *,
|
||||
struct in6_addrlifetime *);
|
||||
static void purge_detached(struct ifnet *);
|
||||
|
||||
static int rt6_deleteroute(struct rtentry *, void *);
|
||||
|
||||
|
@ -488,6 +489,7 @@ defrtrlist_del(struct nd_defrouter *dr)
|
|||
struct nd_ifinfo *ndi = ND_IFINFO(dr->ifp);
|
||||
struct nd_defrouter *deldr = NULL;
|
||||
struct nd_prefix *pr;
|
||||
struct in6_ifextra *ext = dr->ifp->if_afdata[AF_INET6];
|
||||
|
||||
/*
|
||||
* Flush all the routing table entries that use the router
|
||||
|
@ -521,6 +523,12 @@ defrtrlist_del(struct nd_defrouter *dr)
|
|||
if (deldr)
|
||||
defrouter_select();
|
||||
|
||||
ext->ndefrouters--;
|
||||
if (ext->ndefrouters < 0) {
|
||||
log(LOG_WARNING, "defrtrlist_del: negative count on %s\n",
|
||||
dr->ifp->if_xname);
|
||||
}
|
||||
|
||||
free(dr, M_IP6NDP);
|
||||
}
|
||||
|
||||
|
@ -777,6 +785,13 @@ defrtrlist_update(struct nd_defrouter *new)
|
|||
return (dr);
|
||||
}
|
||||
|
||||
struct in6_ifextra *ext = new->ifp->if_afdata[AF_INET6];
|
||||
if (ip6_maxifdefrouters >= 0 &&
|
||||
ext->ndefrouters >= ip6_maxifdefrouters) {
|
||||
splx(s);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* entry does not exist */
|
||||
if (new->rtlifetime == 0) {
|
||||
splx(s);
|
||||
|
@ -818,6 +833,8 @@ insert:
|
|||
|
||||
defrouter_select();
|
||||
|
||||
ext->ndefrouters++;
|
||||
|
||||
splx(s);
|
||||
|
||||
return (n);
|
||||
|
@ -875,6 +892,43 @@ nd6_prefix_lookup(struct nd_prefixctl *key)
|
|||
return (search);
|
||||
}
|
||||
|
||||
static void
|
||||
purge_detached(struct ifnet *ifp)
|
||||
{
|
||||
struct nd_prefix *pr, *pr_next;
|
||||
struct in6_ifaddr *ia;
|
||||
struct ifaddr *ifa, *ifa_next;
|
||||
|
||||
for (pr = nd_prefix.lh_first; pr; pr = pr_next) {
|
||||
pr_next = pr->ndpr_next;
|
||||
|
||||
/*
|
||||
* This function is called when we need to make more room for
|
||||
* new prefixes rather than keeping old, possibly stale ones.
|
||||
* Detached prefixes would be a good candidate; if all routers
|
||||
* that advertised the prefix expired, the prefix is also
|
||||
* probably stale.
|
||||
*/
|
||||
if (pr->ndpr_ifp != ifp ||
|
||||
IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr) ||
|
||||
((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
|
||||
!LIST_EMPTY(&pr->ndpr_advrtrs)))
|
||||
continue;
|
||||
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa_next) {
|
||||
ifa_next = ifa->ifa_list.tqe_next;
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
ia = (struct in6_ifaddr *)ifa;
|
||||
if ((ia->ia6_flags & IN6_IFF_AUTOCONF) ==
|
||||
IN6_IFF_AUTOCONF && ia->ia6_ndpr == pr) {
|
||||
in6_purgeaddr(ifa);
|
||||
}
|
||||
}
|
||||
if (pr->ndpr_refcnt == 0)
|
||||
prelist_remove(pr);
|
||||
}
|
||||
}
|
||||
int
|
||||
nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr,
|
||||
struct nd_prefix **newp)
|
||||
|
@ -882,6 +936,14 @@ nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr,
|
|||
struct nd_prefix *new = NULL;
|
||||
int i, s;
|
||||
int error;
|
||||
struct in6_ifextra *ext = pr->ndpr_ifp->if_afdata[AF_INET6];
|
||||
|
||||
if (ip6_maxifprefixes >= 0) {
|
||||
if (ext->nprefixes >= ip6_maxifprefixes / 2)
|
||||
purge_detached(pr->ndpr_ifp);
|
||||
if (ext->nprefixes >= ip6_maxifprefixes)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
new = malloc(sizeof(*new), M_IP6NDP, M_NOWAIT|M_ZERO);
|
||||
|
@ -930,6 +992,8 @@ nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr,
|
|||
if (dr)
|
||||
pfxrtr_add(new, dr);
|
||||
|
||||
ext->nprefixes++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -938,6 +1002,7 @@ prelist_remove(struct nd_prefix *pr)
|
|||
{
|
||||
struct nd_pfxrouter *pfr, *next;
|
||||
int e, s;
|
||||
struct in6_ifextra *ext = pr->ndpr_ifp->if_afdata[AF_INET6];
|
||||
|
||||
/* make sure to invalidate the prefix until it is really freed. */
|
||||
pr->ndpr_vltime = 0;
|
||||
|
@ -972,6 +1037,12 @@ prelist_remove(struct nd_prefix *pr)
|
|||
|
||||
free(pfr, M_IP6NDP);
|
||||
}
|
||||
|
||||
ext->nprefixes--;
|
||||
if (ext->nprefixes < 0) {
|
||||
log(LOG_WARNING, "prelist_remove: negative count on %s\n",
|
||||
pr->ndpr_ifp->if_xname);
|
||||
}
|
||||
splx(s);
|
||||
|
||||
free(pr, M_IP6NDP);
|
||||
|
|
Loading…
Reference in New Issue