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: David Forster <dforster@brocade.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
88da73a3a5
commit
df789fe752
@ -70,6 +70,7 @@ struct ipv6_devconf {
|
||||
#endif
|
||||
__u32 enhanced_dad;
|
||||
__u32 addr_gen_mode;
|
||||
__s32 disable_policy;
|
||||
|
||||
struct ctl_table_header *sysctl_header;
|
||||
};
|
||||
|
@ -183,6 +183,7 @@ enum {
|
||||
DEVCONF_SEG6_REQUIRE_HMAC,
|
||||
DEVCONF_ENHANCED_DAD,
|
||||
DEVCONF_ADDR_GEN_MODE,
|
||||
DEVCONF_DISABLE_POLICY,
|
||||
DEVCONF_MAX
|
||||
};
|
||||
|
||||
|
@ -245,6 +245,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
|
||||
#endif
|
||||
.enhanced_dad = 1,
|
||||
.addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64,
|
||||
.disable_policy = 0,
|
||||
};
|
||||
|
||||
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
|
||||
@ -297,6 +298,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
|
||||
#endif
|
||||
.enhanced_dad = 1,
|
||||
.addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64,
|
||||
.disable_policy = 0,
|
||||
};
|
||||
|
||||
/* Check if a valid qdisc is available */
|
||||
@ -944,6 +946,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
|
||||
const struct in6_addr *peer_addr, int pfxlen,
|
||||
int scope, u32 flags, u32 valid_lft, u32 prefered_lft)
|
||||
{
|
||||
struct net *net = dev_net(idev->dev);
|
||||
struct inet6_ifaddr *ifa = NULL;
|
||||
struct rt6_info *rt;
|
||||
unsigned int hash;
|
||||
@ -990,6 +993,10 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
|
||||
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);
|
||||
|
||||
ifa->addr = *addr;
|
||||
@ -5003,6 +5010,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
|
||||
#endif
|
||||
array[DEVCONF_ENHANCED_DAD] = cnf->enhanced_dad;
|
||||
array[DEVCONF_ADDR_GEN_MODE] = cnf->addr_gen_mode;
|
||||
array[DEVCONF_DISABLE_POLICY] = cnf->disable_policy;
|
||||
}
|
||||
|
||||
static inline size_t inet6_ifla6_size(void)
|
||||
@ -5827,6 +5835,105 @@ int addrconf_sysctl_ignore_routes_with_linkdown(struct ctl_table *ctl,
|
||||
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 const int one = 1;
|
||||
static const int two_five_five = 255;
|
||||
@ -6184,6 +6291,13 @@ static const struct ctl_table addrconf_sysctl[] = {
|
||||
.mode = 0644,
|
||||
.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 */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user