@@ -341,12 +341,20 @@ attribute-sets:
type: nest
doc: Peer specific cipher configuration
nested-attributes: keyconf
+ -
+ name: target-netnsid
+ type: s32
+ doc: >-
+ ID of the network namespace containing the ovpn interface, relative to
+ the network namespace of the requesting Netlink socket
-
name: ovpn-peer-new-input
subset-of: ovpn
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: peer
nested-attributes: peer-new-input
@@ -356,6 +364,8 @@ attribute-sets:
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: peer
nested-attributes: peer-set-input
@@ -365,6 +375,8 @@ attribute-sets:
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: peer
nested-attributes: peer-del-input
@@ -374,6 +386,8 @@ attribute-sets:
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: keyconf
nested-attributes: keyconf-get
@@ -383,6 +397,8 @@ attribute-sets:
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: keyconf
nested-attributes: keyconf-swap-input
@@ -392,6 +408,8 @@ attribute-sets:
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: keyconf
nested-attributes: keyconf-del-input
@@ -409,6 +427,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- peer
-
name: peer-set
@@ -421,6 +440,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- peer
-
name: peer-get
@@ -433,6 +453,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- peer
reply:
attributes:
@@ -441,6 +462,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
reply:
attributes:
- peer
@@ -455,6 +477,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- peer
-
name: peer-del-ntf
@@ -473,6 +496,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- keyconf
-
name: key-get
@@ -485,6 +509,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- keyconf
reply:
attributes:
@@ -500,6 +525,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- keyconf
-
name: key-swap-ntf
@@ -519,6 +545,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- keyconf
-
@@ -126,55 +126,64 @@ const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_TX_ID + 1] = {
};
/* OVPN_CMD_PEER_NEW - do */
-static const struct nla_policy ovpn_peer_new_nl_policy[OVPN_A_PEER + 1] = {
+static const struct nla_policy ovpn_peer_new_nl_policy[OVPN_A_TARGET_NETNSID + 1] = {
[OVPN_A_IFINDEX] = { .type = NLA_U32, },
+ [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, },
[OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_new_input_nl_policy),
};
/* OVPN_CMD_PEER_SET - do */
-static const struct nla_policy ovpn_peer_set_nl_policy[OVPN_A_PEER + 1] = {
+static const struct nla_policy ovpn_peer_set_nl_policy[OVPN_A_TARGET_NETNSID + 1] = {
[OVPN_A_IFINDEX] = { .type = NLA_U32, },
+ [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, },
[OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_set_input_nl_policy),
};
/* OVPN_CMD_PEER_GET - do */
-static const struct nla_policy ovpn_peer_get_do_nl_policy[OVPN_A_PEER + 1] = {
+static const struct nla_policy ovpn_peer_get_do_nl_policy[OVPN_A_TARGET_NETNSID + 1] = {
[OVPN_A_IFINDEX] = { .type = NLA_U32, },
+ [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, },
[OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy),
};
/* OVPN_CMD_PEER_GET - dump */
-static const struct nla_policy ovpn_peer_get_dump_nl_policy[OVPN_A_IFINDEX + 1] = {
+static const struct nla_policy ovpn_peer_get_dump_nl_policy[OVPN_A_TARGET_NETNSID + 1] = {
[OVPN_A_IFINDEX] = { .type = NLA_U32, },
+ [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, },
};
/* OVPN_CMD_PEER_DEL - do */
-static const struct nla_policy ovpn_peer_del_nl_policy[OVPN_A_PEER + 1] = {
+static const struct nla_policy ovpn_peer_del_nl_policy[OVPN_A_TARGET_NETNSID + 1] = {
[OVPN_A_IFINDEX] = { .type = NLA_U32, },
+ [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, },
[OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_del_input_nl_policy),
};
/* OVPN_CMD_KEY_NEW - do */
-static const struct nla_policy ovpn_key_new_nl_policy[OVPN_A_KEYCONF + 1] = {
+static const struct nla_policy ovpn_key_new_nl_policy[OVPN_A_TARGET_NETNSID + 1] = {
[OVPN_A_IFINDEX] = { .type = NLA_U32, },
+ [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, },
[OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_nl_policy),
};
/* OVPN_CMD_KEY_GET - do */
-static const struct nla_policy ovpn_key_get_nl_policy[OVPN_A_KEYCONF + 1] = {
+static const struct nla_policy ovpn_key_get_nl_policy[OVPN_A_TARGET_NETNSID + 1] = {
[OVPN_A_IFINDEX] = { .type = NLA_U32, },
+ [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, },
[OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_get_nl_policy),
};
/* OVPN_CMD_KEY_SWAP - do */
-static const struct nla_policy ovpn_key_swap_nl_policy[OVPN_A_KEYCONF + 1] = {
+static const struct nla_policy ovpn_key_swap_nl_policy[OVPN_A_TARGET_NETNSID + 1] = {
[OVPN_A_IFINDEX] = { .type = NLA_U32, },
+ [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, },
[OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_swap_input_nl_policy),
};
/* OVPN_CMD_KEY_DEL - do */
-static const struct nla_policy ovpn_key_del_nl_policy[OVPN_A_KEYCONF + 1] = {
+static const struct nla_policy ovpn_key_del_nl_policy[OVPN_A_TARGET_NETNSID + 1] = {
[OVPN_A_IFINDEX] = { .type = NLA_U32, },
+ [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, },
[OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_del_input_nl_policy),
};
@@ -186,7 +195,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = {
.doit = ovpn_nl_peer_new_doit,
.post_doit = ovpn_nl_post_doit,
.policy = ovpn_peer_new_nl_policy,
- .maxattr = OVPN_A_PEER,
+ .maxattr = OVPN_A_TARGET_NETNSID,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
@@ -195,7 +204,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = {
.doit = ovpn_nl_peer_set_doit,
.post_doit = ovpn_nl_post_doit,
.policy = ovpn_peer_set_nl_policy,
- .maxattr = OVPN_A_PEER,
+ .maxattr = OVPN_A_TARGET_NETNSID,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
@@ -204,14 +213,14 @@ static const struct genl_split_ops ovpn_nl_ops[] = {
.doit = ovpn_nl_peer_get_doit,
.post_doit = ovpn_nl_post_doit,
.policy = ovpn_peer_get_do_nl_policy,
- .maxattr = OVPN_A_PEER,
+ .maxattr = OVPN_A_TARGET_NETNSID,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
.cmd = OVPN_CMD_PEER_GET,
.dumpit = ovpn_nl_peer_get_dumpit,
.policy = ovpn_peer_get_dump_nl_policy,
- .maxattr = OVPN_A_IFINDEX,
+ .maxattr = OVPN_A_TARGET_NETNSID,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP,
},
{
@@ -220,7 +229,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = {
.doit = ovpn_nl_peer_del_doit,
.post_doit = ovpn_nl_post_doit,
.policy = ovpn_peer_del_nl_policy,
- .maxattr = OVPN_A_PEER,
+ .maxattr = OVPN_A_TARGET_NETNSID,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
@@ -229,7 +238,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = {
.doit = ovpn_nl_key_new_doit,
.post_doit = ovpn_nl_post_doit,
.policy = ovpn_key_new_nl_policy,
- .maxattr = OVPN_A_KEYCONF,
+ .maxattr = OVPN_A_TARGET_NETNSID,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
@@ -238,7 +247,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = {
.doit = ovpn_nl_key_get_doit,
.post_doit = ovpn_nl_post_doit,
.policy = ovpn_key_get_nl_policy,
- .maxattr = OVPN_A_KEYCONF,
+ .maxattr = OVPN_A_TARGET_NETNSID,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
@@ -247,7 +256,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = {
.doit = ovpn_nl_key_swap_doit,
.post_doit = ovpn_nl_post_doit,
.policy = ovpn_key_swap_nl_policy,
- .maxattr = OVPN_A_KEYCONF,
+ .maxattr = OVPN_A_TARGET_NETNSID,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
@@ -256,7 +265,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = {
.doit = ovpn_nl_key_del_doit,
.post_doit = ovpn_nl_post_doit,
.policy = ovpn_key_del_nl_policy,
- .maxattr = OVPN_A_KEYCONF,
+ .maxattr = OVPN_A_TARGET_NETNSID,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
};
@@ -36,21 +36,37 @@ static struct ovpn_priv *
ovpn_get_dev_from_attrs(struct net *net, const struct genl_info *info,
netdevice_tracker *tracker)
{
+ struct net *target_net = NULL;
struct ovpn_priv *ovpn;
struct net_device *dev;
- int ifindex;
+ int ifindex, target_id;
if (GENL_REQ_ATTR_CHECK(info, OVPN_A_IFINDEX))
return ERR_PTR(-EINVAL);
ifindex = nla_get_u32(info->attrs[OVPN_A_IFINDEX]);
+ if (info->attrs[OVPN_A_TARGET_NETNSID]) {
+ /* Target netns IDs are relative to the requesting Netlink socket */
+ target_id = nla_get_s32(info->attrs[OVPN_A_TARGET_NETNSID]);
+ target_net = get_net_ns_by_id(net, target_id);
+ if (!target_net) {
+ NL_SET_ERR_MSG_MOD(info->extack,
+ "invalid target network namespace ID");
+ NL_SET_BAD_ATTR(info->extack,
+ info->attrs[OVPN_A_TARGET_NETNSID]);
+ return ERR_PTR(-EINVAL);
+ }
+ net = target_net;
+ }
+
rcu_read_lock();
dev = dev_get_by_index_rcu(net, ifindex);
if (!dev) {
rcu_read_unlock();
NL_SET_ERR_MSG_MOD(info->extack,
"ifindex does not match any interface");
+ put_net(target_net);
return ERR_PTR(-ENODEV);
}
@@ -59,12 +75,14 @@ ovpn_get_dev_from_attrs(struct net *net, const struct genl_info *info,
NL_SET_ERR_MSG_MOD(info->extack,
"specified interface is not ovpn");
NL_SET_BAD_ATTR(info->extack, info->attrs[OVPN_A_IFINDEX]);
+ put_net(target_net);
return ERR_PTR(-EINVAL);
}
ovpn = netdev_priv(dev);
netdev_hold(dev, tracker, GFP_ATOMIC);
rcu_read_unlock();
+ put_net(target_net);
return ovpn;
}
@@ -85,6 +85,7 @@ enum {
OVPN_A_IFINDEX = 1,
OVPN_A_PEER,
OVPN_A_KEYCONF,
+ OVPN_A_TARGET_NETNSID,
__OVPN_A_MAX,
OVPN_A_MAX = (__OVPN_A_MAX - 1)