@@ -337,12 +337,19 @@ 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 to operate on
-
name: ovpn-peer-new-input
subset-of: ovpn
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: peer
nested-attributes: peer-new-input
@@ -352,6 +359,8 @@ attribute-sets:
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: peer
nested-attributes: peer-set-input
@@ -361,6 +370,8 @@ attribute-sets:
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: peer
nested-attributes: peer-del-input
@@ -370,6 +381,8 @@ attribute-sets:
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: keyconf
nested-attributes: keyconf-get
@@ -379,6 +392,8 @@ attribute-sets:
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: keyconf
nested-attributes: keyconf-swap-input
@@ -388,6 +403,8 @@ attribute-sets:
attributes:
-
name: ifindex
+ -
+ name: target-netnsid
-
name: keyconf
nested-attributes: keyconf-del-input
@@ -405,6 +422,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- peer
-
name: peer-set
@@ -417,6 +435,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- peer
-
name: peer-get
@@ -429,6 +448,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- peer
reply:
attributes:
@@ -437,6 +457,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
reply:
attributes:
- peer
@@ -451,6 +472,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- peer
-
name: peer-del-ntf
@@ -469,6 +491,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- keyconf
-
name: key-get
@@ -481,6 +504,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- keyconf
reply:
attributes:
@@ -496,6 +520,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- keyconf
-
name: key-swap-ntf
@@ -515,6 +540,7 @@ operations:
request:
attributes:
- ifindex
+ - target-netnsid
- keyconf
-
@@ -118,55 +118,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),
};
@@ -178,7 +187,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,
},
{
@@ -187,7 +196,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,
},
{
@@ -196,14 +205,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,
},
{
@@ -212,7 +221,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,
},
{
@@ -221,7 +230,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,
},
{
@@ -230,7 +239,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,
},
{
@@ -239,7 +248,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,
},
{
@@ -248,7 +257,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,
},
};
@@ -38,6 +38,7 @@ ovpn_get_dev_from_attrs(struct net *net, const struct genl_info *info,
{
struct ovpn_priv *ovpn;
struct net_device *dev;
+ struct net *target_net = NULL;
int ifindex;
if (GENL_REQ_ATTR_CHECK(info, OVPN_A_IFINDEX))
@@ -45,12 +46,25 @@ ovpn_get_dev_from_attrs(struct net *net, const struct genl_info *info,
ifindex = nla_get_u32(info->attrs[OVPN_A_IFINDEX]);
+ if (info->attrs[OVPN_A_TARGET_NETNSID]) {
+ target_net = get_net_ns_by_id(net, nla_get_s32(info->attrs[OVPN_A_TARGET_NETNSID]));
+ 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 +73,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)