Commit df789fe7 authored by David Forster's avatar David Forster Committed by David S. Miller

ipv6: Provide ipv6 version of "disable_policy" sysctl

This provides equivalent functionality to the existing ipv4
"disable_policy" systcl. ie. Allows IPsec processing to be skipped
on terminating packets on a per-interface basis.
Signed-off-by: default avatarDavid Forster <dforster@brocade.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 88da73a3
...@@ -70,6 +70,7 @@ struct ipv6_devconf { ...@@ -70,6 +70,7 @@ struct ipv6_devconf {
#endif #endif
__u32 enhanced_dad; __u32 enhanced_dad;
__u32 addr_gen_mode; __u32 addr_gen_mode;
__s32 disable_policy;
struct ctl_table_header *sysctl_header; struct ctl_table_header *sysctl_header;
}; };
......
...@@ -183,6 +183,7 @@ enum { ...@@ -183,6 +183,7 @@ enum {
DEVCONF_SEG6_REQUIRE_HMAC, DEVCONF_SEG6_REQUIRE_HMAC,
DEVCONF_ENHANCED_DAD, DEVCONF_ENHANCED_DAD,
DEVCONF_ADDR_GEN_MODE, DEVCONF_ADDR_GEN_MODE,
DEVCONF_DISABLE_POLICY,
DEVCONF_MAX DEVCONF_MAX
}; };
......
...@@ -245,6 +245,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = { ...@@ -245,6 +245,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
#endif #endif
.enhanced_dad = 1, .enhanced_dad = 1,
.addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64, .addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64,
.disable_policy = 0,
}; };
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
...@@ -297,6 +298,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { ...@@ -297,6 +298,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
#endif #endif
.enhanced_dad = 1, .enhanced_dad = 1,
.addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64, .addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64,
.disable_policy = 0,
}; };
/* Check if a valid qdisc is available */ /* Check if a valid qdisc is available */
...@@ -944,6 +946,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, ...@@ -944,6 +946,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
const struct in6_addr *peer_addr, int pfxlen, const struct in6_addr *peer_addr, int pfxlen,
int scope, u32 flags, u32 valid_lft, u32 prefered_lft) int scope, u32 flags, u32 valid_lft, u32 prefered_lft)
{ {
struct net *net = dev_net(idev->dev);
struct inet6_ifaddr *ifa = NULL; struct inet6_ifaddr *ifa = NULL;
struct rt6_info *rt; struct rt6_info *rt;
unsigned int hash; unsigned int hash;
...@@ -990,6 +993,10 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, ...@@ -990,6 +993,10 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
goto out; goto out;
} }
if (net->ipv6.devconf_all->disable_policy ||
idev->cnf.disable_policy)
rt->dst.flags |= DST_NOPOLICY;
neigh_parms_data_state_setall(idev->nd_parms); neigh_parms_data_state_setall(idev->nd_parms);
ifa->addr = *addr; ifa->addr = *addr;
...@@ -5003,6 +5010,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, ...@@ -5003,6 +5010,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
#endif #endif
array[DEVCONF_ENHANCED_DAD] = cnf->enhanced_dad; array[DEVCONF_ENHANCED_DAD] = cnf->enhanced_dad;
array[DEVCONF_ADDR_GEN_MODE] = cnf->addr_gen_mode; array[DEVCONF_ADDR_GEN_MODE] = cnf->addr_gen_mode;
array[DEVCONF_DISABLE_POLICY] = cnf->disable_policy;
} }
static inline size_t inet6_ifla6_size(void) static inline size_t inet6_ifla6_size(void)
...@@ -5827,6 +5835,105 @@ int addrconf_sysctl_ignore_routes_with_linkdown(struct ctl_table *ctl, ...@@ -5827,6 +5835,105 @@ int addrconf_sysctl_ignore_routes_with_linkdown(struct ctl_table *ctl,
return ret; return ret;
} }
static
void addrconf_set_nopolicy(struct rt6_info *rt, int action)
{
if (rt) {
if (action)
rt->dst.flags |= DST_NOPOLICY;
else
rt->dst.flags &= ~DST_NOPOLICY;
}
}
static
void addrconf_disable_policy_idev(struct inet6_dev *idev, int val)
{
struct inet6_ifaddr *ifa;
read_lock_bh(&idev->lock);
list_for_each_entry(ifa, &idev->addr_list, if_list) {
spin_lock(&ifa->lock);
if (ifa->rt) {
struct rt6_info *rt = ifa->rt;
struct fib6_table *table = rt->rt6i_table;
int cpu;
read_lock(&table->tb6_lock);
addrconf_set_nopolicy(ifa->rt, val);
if (rt->rt6i_pcpu) {
for_each_possible_cpu(cpu) {
struct rt6_info **rtp;
rtp = per_cpu_ptr(rt->rt6i_pcpu, cpu);
addrconf_set_nopolicy(*rtp, val);
}
}
read_unlock(&table->tb6_lock);
}
spin_unlock(&ifa->lock);
}
read_unlock_bh(&idev->lock);
}
static
int addrconf_disable_policy(struct ctl_table *ctl, int *valp, int val)
{
struct inet6_dev *idev;
struct net *net;
if (!rtnl_trylock())
return restart_syscall();
*valp = val;
net = (struct net *)ctl->extra2;
if (valp == &net->ipv6.devconf_dflt->disable_policy) {
rtnl_unlock();
return 0;
}
if (valp == &net->ipv6.devconf_all->disable_policy) {
struct net_device *dev;
for_each_netdev(net, dev) {
idev = __in6_dev_get(dev);
if (idev)
addrconf_disable_policy_idev(idev, val);
}
} else {
idev = (struct inet6_dev *)ctl->extra1;
addrconf_disable_policy_idev(idev, val);
}
rtnl_unlock();
return 0;
}
static
int addrconf_sysctl_disable_policy(struct ctl_table *ctl, int write,
void __user *buffer, size_t *lenp,
loff_t *ppos)
{
int *valp = ctl->data;
int val = *valp;
loff_t pos = *ppos;
struct ctl_table lctl;
int ret;
lctl = *ctl;
lctl.data = &val;
ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
if (write && (*valp != val))
ret = addrconf_disable_policy(ctl, valp, val);
if (ret)
*ppos = pos;
return ret;
}
static int minus_one = -1; static int minus_one = -1;
static const int one = 1; static const int one = 1;
static const int two_five_five = 255; static const int two_five_five = 255;
...@@ -6184,6 +6291,13 @@ static const struct ctl_table addrconf_sysctl[] = { ...@@ -6184,6 +6291,13 @@ static const struct ctl_table addrconf_sysctl[] = {
.mode = 0644, .mode = 0644,
.proc_handler = addrconf_sysctl_addr_gen_mode, .proc_handler = addrconf_sysctl_addr_gen_mode,
}, },
{
.procname = "disable_policy",
.data = &ipv6_devconf.disable_policy,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = addrconf_sysctl_disable_policy,
},
{ {
/* sentinel */ /* sentinel */
} }
......
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