Merge branch 'xfrm: fix uapi for the default policy'
Nicolas Dichtel says: ==================== This feature has just been merged after the last release, thus it's still time to fix the uapi. As stated in the thread, the uapi is based on some magic values (from the userland POV). Here is a proposal to simplify this uapi and make it clear how to use it. The other problem was the notification: changing the default policy may radically change the packets flows. v2 -> v3: rebase on top of ipsec tree v1 -> v2: fix warnings reported by the kernel test robot ==================== Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
commit
047a749d23
@ -514,9 +514,12 @@ struct xfrm_user_offload {
|
||||
#define XFRM_OFFLOAD_INBOUND 2
|
||||
|
||||
struct xfrm_userpolicy_default {
|
||||
#define XFRM_USERPOLICY_DIRMASK_MAX (sizeof(__u8) * 8)
|
||||
__u8 dirmask;
|
||||
__u8 action;
|
||||
#define XFRM_USERPOLICY_UNSPEC 0
|
||||
#define XFRM_USERPOLICY_BLOCK 1
|
||||
#define XFRM_USERPOLICY_ACCEPT 2
|
||||
__u8 in;
|
||||
__u8 fwd;
|
||||
__u8 out;
|
||||
};
|
||||
|
||||
#ifndef __KERNEL__
|
||||
|
@ -1961,24 +1961,60 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int xfrm_notify_userpolicy(struct net *net)
|
||||
{
|
||||
struct xfrm_userpolicy_default *up;
|
||||
int len = NLMSG_ALIGN(sizeof(*up));
|
||||
struct nlmsghdr *nlh;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = nlmsg_new(len, GFP_ATOMIC);
|
||||
if (skb == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_GETDEFAULT, sizeof(*up), 0);
|
||||
if (nlh == NULL) {
|
||||
kfree_skb(skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
up = nlmsg_data(nlh);
|
||||
up->in = net->xfrm.policy_default & XFRM_POL_DEFAULT_IN ?
|
||||
XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
|
||||
up->fwd = net->xfrm.policy_default & XFRM_POL_DEFAULT_FWD ?
|
||||
XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
|
||||
up->out = net->xfrm.policy_default & XFRM_POL_DEFAULT_OUT ?
|
||||
XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
|
||||
return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_POLICY);
|
||||
}
|
||||
|
||||
static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct nlattr **attrs)
|
||||
{
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct xfrm_userpolicy_default *up = nlmsg_data(nlh);
|
||||
u8 dirmask;
|
||||
u8 old_default = net->xfrm.policy_default;
|
||||
|
||||
if (up->dirmask >= XFRM_USERPOLICY_DIRMASK_MAX)
|
||||
return -EINVAL;
|
||||
if (up->in == XFRM_USERPOLICY_BLOCK)
|
||||
net->xfrm.policy_default |= XFRM_POL_DEFAULT_IN;
|
||||
else if (up->in == XFRM_USERPOLICY_ACCEPT)
|
||||
net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_IN;
|
||||
|
||||
dirmask = (1 << up->dirmask) & XFRM_POL_DEFAULT_MASK;
|
||||
if (up->fwd == XFRM_USERPOLICY_BLOCK)
|
||||
net->xfrm.policy_default |= XFRM_POL_DEFAULT_FWD;
|
||||
else if (up->fwd == XFRM_USERPOLICY_ACCEPT)
|
||||
net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_FWD;
|
||||
|
||||
net->xfrm.policy_default = (old_default & (0xff ^ dirmask))
|
||||
| (up->action << up->dirmask);
|
||||
if (up->out == XFRM_USERPOLICY_BLOCK)
|
||||
net->xfrm.policy_default |= XFRM_POL_DEFAULT_OUT;
|
||||
else if (up->out == XFRM_USERPOLICY_ACCEPT)
|
||||
net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_OUT;
|
||||
|
||||
rt_genid_bump_all(net);
|
||||
|
||||
xfrm_notify_userpolicy(net);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1988,13 +2024,11 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct sk_buff *r_skb;
|
||||
struct nlmsghdr *r_nlh;
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct xfrm_userpolicy_default *r_up, *up;
|
||||
struct xfrm_userpolicy_default *r_up;
|
||||
int len = NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_default));
|
||||
u32 portid = NETLINK_CB(skb).portid;
|
||||
u32 seq = nlh->nlmsg_seq;
|
||||
|
||||
up = nlmsg_data(nlh);
|
||||
|
||||
r_skb = nlmsg_new(len, GFP_ATOMIC);
|
||||
if (!r_skb)
|
||||
return -ENOMEM;
|
||||
@ -2005,15 +2039,14 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (up->dirmask >= XFRM_USERPOLICY_DIRMASK_MAX) {
|
||||
kfree_skb(r_skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r_up = nlmsg_data(r_nlh);
|
||||
|
||||
r_up->action = ((net->xfrm.policy_default & (1 << up->dirmask)) >> up->dirmask);
|
||||
r_up->dirmask = up->dirmask;
|
||||
r_up->in = net->xfrm.policy_default & XFRM_POL_DEFAULT_IN ?
|
||||
XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
|
||||
r_up->fwd = net->xfrm.policy_default & XFRM_POL_DEFAULT_FWD ?
|
||||
XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
|
||||
r_up->out = net->xfrm.policy_default & XFRM_POL_DEFAULT_OUT ?
|
||||
XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
|
||||
nlmsg_end(r_skb, r_nlh);
|
||||
|
||||
return nlmsg_unicast(net->xfrm.nlsk, r_skb, portid);
|
||||
|
Loading…
Reference in New Issue
Block a user