Commit c21c7b41 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji Committed by David S. Miller

[IPV6]: Allow per-device max addresses configurable via sysctl.

parent c2e514bc
...@@ -667,6 +667,13 @@ regen_max_retry - INTEGER ...@@ -667,6 +667,13 @@ regen_max_retry - INTEGER
valid temporary addresses. valid temporary addresses.
Default: 5 Default: 5
max_addresses - INTEGER
Number of maximum addresses per interface. 0 disables limitation.
It is recommended not set too large value (or 0) because it would
be too easy way to crash kernel to allow to create too much of
autoconfigured addresses.
Default: 16
icmp/*: icmp/*:
ratelimit - INTEGER ratelimit - INTEGER
Limit the maximal rates for sending ICMPv6 packets. Limit the maximal rates for sending ICMPv6 packets.
......
...@@ -143,6 +143,7 @@ struct ipv6_devconf { ...@@ -143,6 +143,7 @@ struct ipv6_devconf {
__s32 regen_max_retry; __s32 regen_max_retry;
__s32 max_desync_factor; __s32 max_desync_factor;
#endif #endif
__s32 max_addresses;
void *sysctl; void *sysctl;
}; };
...@@ -165,6 +166,7 @@ enum { ...@@ -165,6 +166,7 @@ enum {
DEVCONF_REGEN_MAX_RETRY, DEVCONF_REGEN_MAX_RETRY,
DEVCONF_MAX_DESYNC_FACTOR, DEVCONF_MAX_DESYNC_FACTOR,
#endif #endif
DEVCONF_MAX_ADDRESSES,
DEVCONF_MAX DEVCONF_MAX
}; };
......
...@@ -418,7 +418,8 @@ enum { ...@@ -418,7 +418,8 @@ enum {
NET_IPV6_TEMP_VALID_LFT=12, NET_IPV6_TEMP_VALID_LFT=12,
NET_IPV6_TEMP_PREFERED_LFT=13, NET_IPV6_TEMP_PREFERED_LFT=13,
NET_IPV6_REGEN_MAX_RETRY=14, NET_IPV6_REGEN_MAX_RETRY=14,
NET_IPV6_MAX_DESYNC_FACTOR=15 NET_IPV6_MAX_DESYNC_FACTOR=15,
NET_IPV6_MAX_ADDRESSES=16
}; };
/* /proc/sys/net/ipv6/icmp */ /* /proc/sys/net/ipv6/icmp */
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#define ADDR_CHECK_FREQUENCY (120*HZ) #define ADDR_CHECK_FREQUENCY (120*HZ)
#define IPV6_MAX_ADDRESSES 16
struct prefix_info { struct prefix_info {
__u8 type; __u8 type;
__u8 length; __u8 length;
......
...@@ -81,8 +81,6 @@ ...@@ -81,8 +81,6 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#define IPV6_MAX_ADDRESSES 16
/* Set to 3 to get tracing... */ /* Set to 3 to get tracing... */
#define ACONF_DEBUG 2 #define ACONF_DEBUG 2
...@@ -162,6 +160,7 @@ struct ipv6_devconf ipv6_devconf = { ...@@ -162,6 +160,7 @@ struct ipv6_devconf ipv6_devconf = {
.regen_max_retry = REGEN_MAX_RETRY, .regen_max_retry = REGEN_MAX_RETRY,
.max_desync_factor = MAX_DESYNC_FACTOR, .max_desync_factor = MAX_DESYNC_FACTOR,
#endif #endif
.max_addresses = IPV6_MAX_ADDRESSES,
}; };
static struct ipv6_devconf ipv6_devconf_dflt = { static struct ipv6_devconf ipv6_devconf_dflt = {
...@@ -182,6 +181,7 @@ static struct ipv6_devconf ipv6_devconf_dflt = { ...@@ -182,6 +181,7 @@ static struct ipv6_devconf ipv6_devconf_dflt = {
.regen_max_retry = REGEN_MAX_RETRY, .regen_max_retry = REGEN_MAX_RETRY,
.max_desync_factor = MAX_DESYNC_FACTOR, .max_desync_factor = MAX_DESYNC_FACTOR,
#endif #endif
.max_addresses = IPV6_MAX_ADDRESSES,
}; };
/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
...@@ -633,6 +633,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i ...@@ -633,6 +633,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
unsigned long tmp_prefered_lft, tmp_valid_lft; unsigned long tmp_prefered_lft, tmp_valid_lft;
int tmp_plen; int tmp_plen;
int ret = 0; int ret = 0;
int max_addresses;
if (ift) { if (ift) {
spin_lock_bh(&ift->lock); spin_lock_bh(&ift->lock);
...@@ -688,9 +689,11 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i ...@@ -688,9 +689,11 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
ifp->prefered_lft, ifp->prefered_lft,
idev->cnf.temp_prefered_lft - desync_factor / HZ); idev->cnf.temp_prefered_lft - desync_factor / HZ);
tmp_plen = ifp->prefix_len; tmp_plen = ifp->prefix_len;
max_addresses = idev->cnf.max_addresses;
write_unlock(&idev->lock); write_unlock(&idev->lock);
spin_unlock_bh(&ifp->lock); spin_unlock_bh(&ifp->lock);
ift = ipv6_count_addresses(idev) < IPV6_MAX_ADDRESSES ? ift = !max_addresses ||
ipv6_count_addresses(idev) < max_addresses ?
ipv6_add_addr(idev, &addr, tmp_plen, ipv6_add_addr(idev, &addr, tmp_plen,
ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, IFA_F_TEMPORARY) : 0; ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, IFA_F_TEMPORARY) : 0;
if (!ift || IS_ERR(ift)) { if (!ift || IS_ERR(ift)) {
...@@ -1393,10 +1396,13 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) ...@@ -1393,10 +1396,13 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
ifp = ipv6_get_ifaddr(&addr, dev); ifp = ipv6_get_ifaddr(&addr, dev);
if (ifp == NULL && valid_lft) { if (ifp == NULL && valid_lft) {
int max_addresses = in6_dev->cnf.max_addresses;
/* Do not allow to create too much of autoconfigured /* Do not allow to create too much of autoconfigured
* addresses; this would be too easy way to crash kernel. * addresses; this would be too easy way to crash kernel.
*/ */
if (ipv6_count_addresses(in6_dev) < IPV6_MAX_ADDRESSES) if (!max_addresses ||
ipv6_count_addresses(in6_dev) < max_addresses)
ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len, ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len,
addr_type&IPV6_ADDR_SCOPE_MASK, 0); addr_type&IPV6_ADDR_SCOPE_MASK, 0);
...@@ -2740,6 +2746,7 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, ...@@ -2740,6 +2746,7 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
array[DEVCONF_REGEN_MAX_RETRY] = cnf->regen_max_retry; array[DEVCONF_REGEN_MAX_RETRY] = cnf->regen_max_retry;
array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor; array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
#endif #endif
array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
} }
static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
...@@ -3165,6 +3172,14 @@ static struct addrconf_sysctl_table ...@@ -3165,6 +3172,14 @@ static struct addrconf_sysctl_table
.proc_handler = &proc_dointvec, .proc_handler = &proc_dointvec,
}, },
#endif #endif
{
.ctl_name = NET_IPV6_MAX_ADDRESSES,
.procname = "max_addresses",
.data = &ipv6_devconf.max_addresses,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
}, },
.addrconf_dev = { .addrconf_dev = {
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment