Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102976012
D24035.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D24035.diff
View Options
Index: sys/netinet6/in6.c
===================================================================
--- sys/netinet6/in6.c
+++ sys/netinet6/in6.c
@@ -104,6 +104,7 @@
#include <netinet/ip_carp.h>
#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/nd6.h>
#include <netinet6/mld6_var.h>
@@ -125,6 +126,14 @@
VNET_DECLARE(int, icmp6_nodeinfo_oldmcprefix);
#define V_icmp6_nodeinfo_oldmcprefix VNET(icmp6_nodeinfo_oldmcprefix)
+SYSCTL_DECL(_net_inet6_icmp6);
+
+static int in6_llt_max_entries;
+SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, in6_llt_max_entries,
+ CTLFLAG_RW, &in6_llt_max_entries, 0,
+ "Maximum number of IPv6 neighbour entries per interface. "
+ "0 accept unlimited.");
+
/*
* Definitions of some costant IP6 addresses.
*/
@@ -164,7 +173,22 @@
#define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa))
#define ia62ifa(ia6) (&((ia6)->ia_ifa))
+void
+in6_init(void)
+{
+ /*
+ * physmem is the number of physical memory in pages. This means that
+ * up to 16GB we are scaling the number of table entries according to
+ * memory (1 table entry for each MB of physical memory). That way a
+ * small devices might not be overloaded as quickly in case of a flood
+ * as would big servers be. We ensure that there is a minimum of 128
+ * entries in all cases per-interface and cap the default value at
+ * 16k neighbour entries to avoid the DoS problem.
+ */
+ in6_llt_max_entries = max(128, min(physmem / 256, 16384));
+}
+
void
in6_newaddrmsg(struct in6_ifaddr *ia, int cmd)
{
@@ -2420,6 +2444,8 @@
llt = lltable_allocate_htbl(IN6_LLTBL_DEFAULT_HSIZE);
llt->llt_af = AF_INET6;
llt->llt_ifp = ifp;
+ /* XXX-BZ re-think SYSCTL_PROC to update? Make it more integrated? */
+ llt->llt_maxentries = in6_llt_max_entries;
llt->llt_lookup = in6_lltable_lookup;
llt->llt_alloc_entry = in6_lltable_alloc;
Index: sys/netinet6/nd6.h
===================================================================
--- sys/netinet6/nd6.h
+++ sys/netinet6/nd6.h
@@ -352,6 +352,9 @@
#define nd_opts_last nd_opt_each.last
#define nd_opts_done nd_opt_each.done
+/* in6.c */
+void in6_init(void);
+
/* XXX: need nd6_var.h?? */
/* nd6.c */
void nd6_init(void);
Index: sys/netinet6/nd6.c
===================================================================
--- sys/netinet6/nd6.c
+++ sys/netinet6/nd6.c
@@ -231,6 +231,8 @@
nd6_dad_init();
if (IS_DEFAULT_VNET(curvnet)) {
+ in6_init();
+
lle_event_eh = EVENTHANDLER_REGISTER(lle_event, nd6_lle_event,
NULL, EVENTHANDLER_PRI_ANY);
iflladdr_event_eh = EVENTHANDLER_REGISTER(iflladdr_event,
@@ -1929,7 +1931,7 @@
struct mbuf *chain = NULL;
u_char linkhdr[LLE_MAX_LINKHDR];
size_t linkhdrsize;
- int lladdr_off;
+ int linked, lladdr_off;
NET_EPOCH_ASSERT();
IF_AFDATA_UNLOCK_ASSERT(ifp);
@@ -1976,8 +1978,14 @@
LLE_WLOCK(ln);
/* Prefer any existing lle over newly-created one */
ln_tmp = nd6_lookup(from, LLE_EXCLUSIVE, ifp);
- if (ln_tmp == NULL)
- lltable_link_entry(LLTABLE6(ifp), ln);
+ if (ln_tmp == NULL) {
+ linked = lltable_link_entry(LLTABLE6(ifp), ln);
+ if (linked < 0) {
+ IF_AFDATA_WUNLOCK(ifp);
+ lltable_free_entry(LLTABLE6(ifp), ln);
+ return;
+ }
+ }
IF_AFDATA_WUNLOCK(ifp);
if (ln_tmp == NULL) {
/* No existing lle, mark as new entry (6,7) */
@@ -2285,7 +2293,7 @@
{
struct llentry *lle = NULL, *lle_tmp;
struct in6_addr *psrc, src;
- int send_ns, ll_len;
+ int linked, send_ns, ll_len;
char *lladdr;
NET_EPOCH_ASSERT();
@@ -2320,8 +2328,12 @@
/* Prefer any existing entry over newly-created one */
lle_tmp = nd6_lookup(&dst->sin6_addr, LLE_EXCLUSIVE, ifp);
if (lle_tmp == NULL)
- lltable_link_entry(LLTABLE6(ifp), lle);
+ linked = lltable_link_entry(LLTABLE6(ifp), lle);
IF_AFDATA_WUNLOCK(ifp);
+ if (lle_tmp == NULL && linked < 0) {
+ lltable_free_entry(LLTABLE6(ifp), lle);
+ lle = NULL;
+ }
if (lle_tmp != NULL) {
lltable_free_entry(LLTABLE6(ifp), lle);
lle = lle_tmp;
@@ -2506,6 +2518,7 @@
struct ifnet *ifp;
struct llentry *ln, *ln_tmp;
struct sockaddr *dst;
+ int error, linked;
ifp = ia->ia_ifa.ifa_ifp;
if (nd6_need_cache(ifp) == 0)
@@ -2517,24 +2530,44 @@
if (ln == NULL)
return (ENOBUFS);
+ error = 0;
IF_AFDATA_WLOCK(ifp);
LLE_WLOCK(ln);
- /* Unlink any entry if exists */
+ /*
+ * Historically we would unlink any entry if it existed and then link
+ * the new one. Given we could still fail linking after unlink (e.g.,
+ * if the table limits were lowered) we are going through some extra
+ * complications here so that we do not change the status-quo in case
+ * we cannot link the new entry.
+ * It may seem that we could link before lookup but that could change
+ * out later lookup result. This is why the order is: lookup, link,
+ * unlink, announce (in the non-error case).
+ */
ln_tmp = lla_lookup(LLTABLE6(ifp), LLE_EXCLUSIVE, dst);
- if (ln_tmp != NULL)
- lltable_unlink_entry(LLTABLE6(ifp), ln_tmp);
- lltable_link_entry(LLTABLE6(ifp), ln);
+ linked = lltable_link_entry(LLTABLE6(ifp), ln);
+ if (linked < 0) {
+ lltable_free_entry(LLTABLE6(ifp), ln);
+ error = ENOBUFS;
+ }
+ if (ln_tmp != NULL) {
+ if (error == 0)
+ lltable_unlink_entry(LLTABLE6(ifp), ln_tmp);
+ else
+ LLE_WUNLOCK(ln_tmp);
+ }
IF_AFDATA_WUNLOCK(ifp);
- if (ln_tmp != NULL)
- EVENTHANDLER_INVOKE(lle_event, ln_tmp, LLENTRY_EXPIRED);
- EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
+ if (error == 0) {
+ if (ln_tmp != NULL)
+ EVENTHANDLER_INVOKE(lle_event, ln_tmp, LLENTRY_EXPIRED);
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
- LLE_WUNLOCK(ln);
- if (ln_tmp != NULL)
- llentry_free(ln_tmp);
+ LLE_WUNLOCK(ln);
+ if (ln_tmp != NULL)
+ llentry_free(ln_tmp);
+ }
- return (0);
+ return (error);
}
/*
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 20, 9:40 AM (20 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14735175
Default Alt Text
D24035.diff (5 KB)
Attached To
Mode
D24035: IPv6 neighbour entries resource limits
Attached
Detach File
Event Timeline
Log In to Comment