1b7a63391SAntonio Quartulli // SPDX-License-Identifier: GPL-2.0
2b7a63391SAntonio Quartulli /* OpenVPN data channel offload
3b7a63391SAntonio Quartulli *
4b7a63391SAntonio Quartulli * Copyright (C) 2020-2025 OpenVPN, Inc.
5b7a63391SAntonio Quartulli *
6b7a63391SAntonio Quartulli * Author: Antonio Quartulli <antonio@openvpn.net>
7b7a63391SAntonio Quartulli */
8b7a63391SAntonio Quartulli
9b7a63391SAntonio Quartulli #include <linux/netdevice.h>
101d36a36fSAntonio Quartulli #include <linux/types.h>
11b7a63391SAntonio Quartulli #include <net/genetlink.h>
12b7a63391SAntonio Quartulli
13b7a63391SAntonio Quartulli #include <uapi/linux/ovpn.h>
14b7a63391SAntonio Quartulli
15b7a63391SAntonio Quartulli #include "ovpnpriv.h"
16b7a63391SAntonio Quartulli #include "main.h"
17b7a63391SAntonio Quartulli #include "netlink.h"
18b7a63391SAntonio Quartulli #include "netlink-gen.h"
191d36a36fSAntonio Quartulli #include "bind.h"
20203e2bf5SAntonio Quartulli #include "crypto.h"
211d36a36fSAntonio Quartulli #include "peer.h"
221d36a36fSAntonio Quartulli #include "socket.h"
23b7a63391SAntonio Quartulli
24b7a63391SAntonio Quartulli MODULE_ALIAS_GENL_FAMILY(OVPN_FAMILY_NAME);
25b7a63391SAntonio Quartulli
26b7a63391SAntonio Quartulli /**
27b7a63391SAntonio Quartulli * ovpn_get_dev_from_attrs - retrieve the ovpn private data from the netdevice
28b7a63391SAntonio Quartulli * a netlink message is targeting
29b7a63391SAntonio Quartulli * @net: network namespace where to look for the interface
30b7a63391SAntonio Quartulli * @info: generic netlink info from the user request
31b7a63391SAntonio Quartulli * @tracker: tracker object to be used for the netdev reference acquisition
32b7a63391SAntonio Quartulli *
33b7a63391SAntonio Quartulli * Return: the ovpn private data, if found, or an error otherwise
34b7a63391SAntonio Quartulli */
35b7a63391SAntonio Quartulli static struct ovpn_priv *
ovpn_get_dev_from_attrs(struct net * net,const struct genl_info * info,netdevice_tracker * tracker)36b7a63391SAntonio Quartulli ovpn_get_dev_from_attrs(struct net *net, const struct genl_info *info,
37b7a63391SAntonio Quartulli netdevice_tracker *tracker)
38b7a63391SAntonio Quartulli {
39b7a63391SAntonio Quartulli struct ovpn_priv *ovpn;
40b7a63391SAntonio Quartulli struct net_device *dev;
41b7a63391SAntonio Quartulli int ifindex;
42b7a63391SAntonio Quartulli
43b7a63391SAntonio Quartulli if (GENL_REQ_ATTR_CHECK(info, OVPN_A_IFINDEX))
44b7a63391SAntonio Quartulli return ERR_PTR(-EINVAL);
45b7a63391SAntonio Quartulli
46b7a63391SAntonio Quartulli ifindex = nla_get_u32(info->attrs[OVPN_A_IFINDEX]);
47b7a63391SAntonio Quartulli
48b7a63391SAntonio Quartulli rcu_read_lock();
49b7a63391SAntonio Quartulli dev = dev_get_by_index_rcu(net, ifindex);
50b7a63391SAntonio Quartulli if (!dev) {
51b7a63391SAntonio Quartulli rcu_read_unlock();
52b7a63391SAntonio Quartulli NL_SET_ERR_MSG_MOD(info->extack,
53b7a63391SAntonio Quartulli "ifindex does not match any interface");
54b7a63391SAntonio Quartulli return ERR_PTR(-ENODEV);
55b7a63391SAntonio Quartulli }
56b7a63391SAntonio Quartulli
57b7a63391SAntonio Quartulli if (!ovpn_dev_is_valid(dev)) {
58b7a63391SAntonio Quartulli rcu_read_unlock();
59b7a63391SAntonio Quartulli NL_SET_ERR_MSG_MOD(info->extack,
60b7a63391SAntonio Quartulli "specified interface is not ovpn");
61b7a63391SAntonio Quartulli NL_SET_BAD_ATTR(info->extack, info->attrs[OVPN_A_IFINDEX]);
62b7a63391SAntonio Quartulli return ERR_PTR(-EINVAL);
63b7a63391SAntonio Quartulli }
64b7a63391SAntonio Quartulli
65b7a63391SAntonio Quartulli ovpn = netdev_priv(dev);
66b7a63391SAntonio Quartulli netdev_hold(dev, tracker, GFP_ATOMIC);
67b7a63391SAntonio Quartulli rcu_read_unlock();
68b7a63391SAntonio Quartulli
69b7a63391SAntonio Quartulli return ovpn;
70b7a63391SAntonio Quartulli }
71b7a63391SAntonio Quartulli
ovpn_nl_pre_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)72b7a63391SAntonio Quartulli int ovpn_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
73b7a63391SAntonio Quartulli struct genl_info *info)
74b7a63391SAntonio Quartulli {
75b7a63391SAntonio Quartulli netdevice_tracker *tracker = (netdevice_tracker *)&info->user_ptr[1];
76b7a63391SAntonio Quartulli struct ovpn_priv *ovpn = ovpn_get_dev_from_attrs(genl_info_net(info),
77b7a63391SAntonio Quartulli info, tracker);
78b7a63391SAntonio Quartulli
79b7a63391SAntonio Quartulli if (IS_ERR(ovpn))
80b7a63391SAntonio Quartulli return PTR_ERR(ovpn);
81b7a63391SAntonio Quartulli
82b7a63391SAntonio Quartulli info->user_ptr[0] = ovpn;
83b7a63391SAntonio Quartulli
84b7a63391SAntonio Quartulli return 0;
85b7a63391SAntonio Quartulli }
86b7a63391SAntonio Quartulli
ovpn_nl_post_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)87b7a63391SAntonio Quartulli void ovpn_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
88b7a63391SAntonio Quartulli struct genl_info *info)
89b7a63391SAntonio Quartulli {
90b7a63391SAntonio Quartulli netdevice_tracker *tracker = (netdevice_tracker *)&info->user_ptr[1];
91b7a63391SAntonio Quartulli struct ovpn_priv *ovpn = info->user_ptr[0];
92b7a63391SAntonio Quartulli
93b7a63391SAntonio Quartulli if (ovpn)
94b7a63391SAntonio Quartulli netdev_put(ovpn->dev, tracker);
95b7a63391SAntonio Quartulli }
96b7a63391SAntonio Quartulli
ovpn_nl_attr_sockaddr_remote(struct nlattr ** attrs,struct sockaddr_storage * ss)971d36a36fSAntonio Quartulli static bool ovpn_nl_attr_sockaddr_remote(struct nlattr **attrs,
981d36a36fSAntonio Quartulli struct sockaddr_storage *ss)
991d36a36fSAntonio Quartulli {
1001d36a36fSAntonio Quartulli struct sockaddr_in6 *sin6;
1011d36a36fSAntonio Quartulli struct sockaddr_in *sin;
1021d36a36fSAntonio Quartulli struct in6_addr *in6;
1031d36a36fSAntonio Quartulli __be16 port = 0;
1041d36a36fSAntonio Quartulli __be32 *in;
1051d36a36fSAntonio Quartulli
1061d36a36fSAntonio Quartulli ss->ss_family = AF_UNSPEC;
1071d36a36fSAntonio Quartulli
1081d36a36fSAntonio Quartulli if (attrs[OVPN_A_PEER_REMOTE_PORT])
1091d36a36fSAntonio Quartulli port = nla_get_be16(attrs[OVPN_A_PEER_REMOTE_PORT]);
1101d36a36fSAntonio Quartulli
1111d36a36fSAntonio Quartulli if (attrs[OVPN_A_PEER_REMOTE_IPV4]) {
1121d36a36fSAntonio Quartulli ss->ss_family = AF_INET;
1131d36a36fSAntonio Quartulli in = nla_data(attrs[OVPN_A_PEER_REMOTE_IPV4]);
1141d36a36fSAntonio Quartulli } else if (attrs[OVPN_A_PEER_REMOTE_IPV6]) {
1151d36a36fSAntonio Quartulli ss->ss_family = AF_INET6;
1161d36a36fSAntonio Quartulli in6 = nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]);
1171d36a36fSAntonio Quartulli } else {
1181d36a36fSAntonio Quartulli return false;
1191d36a36fSAntonio Quartulli }
1201d36a36fSAntonio Quartulli
1211d36a36fSAntonio Quartulli switch (ss->ss_family) {
1221d36a36fSAntonio Quartulli case AF_INET6:
1231d36a36fSAntonio Quartulli /* If this is a regular IPv6 just break and move on,
1241d36a36fSAntonio Quartulli * otherwise switch to AF_INET and extract the IPv4 accordingly
1251d36a36fSAntonio Quartulli */
1261d36a36fSAntonio Quartulli if (!ipv6_addr_v4mapped(in6)) {
1271d36a36fSAntonio Quartulli sin6 = (struct sockaddr_in6 *)ss;
1281d36a36fSAntonio Quartulli sin6->sin6_port = port;
1291d36a36fSAntonio Quartulli memcpy(&sin6->sin6_addr, in6, sizeof(*in6));
1301d36a36fSAntonio Quartulli break;
1311d36a36fSAntonio Quartulli }
1321d36a36fSAntonio Quartulli
1331d36a36fSAntonio Quartulli /* v4-mapped-v6 address */
1341d36a36fSAntonio Quartulli ss->ss_family = AF_INET;
1351d36a36fSAntonio Quartulli in = &in6->s6_addr32[3];
1361d36a36fSAntonio Quartulli fallthrough;
1371d36a36fSAntonio Quartulli case AF_INET:
1381d36a36fSAntonio Quartulli sin = (struct sockaddr_in *)ss;
1391d36a36fSAntonio Quartulli sin->sin_port = port;
1401d36a36fSAntonio Quartulli sin->sin_addr.s_addr = *in;
1411d36a36fSAntonio Quartulli break;
1421d36a36fSAntonio Quartulli }
1431d36a36fSAntonio Quartulli
1441d36a36fSAntonio Quartulli return true;
1451d36a36fSAntonio Quartulli }
1461d36a36fSAntonio Quartulli
ovpn_nl_attr_local_ip(struct nlattr ** attrs)1471d36a36fSAntonio Quartulli static u8 *ovpn_nl_attr_local_ip(struct nlattr **attrs)
1481d36a36fSAntonio Quartulli {
1491d36a36fSAntonio Quartulli u8 *addr6;
1501d36a36fSAntonio Quartulli
1511d36a36fSAntonio Quartulli if (!attrs[OVPN_A_PEER_LOCAL_IPV4] && !attrs[OVPN_A_PEER_LOCAL_IPV6])
1521d36a36fSAntonio Quartulli return NULL;
1531d36a36fSAntonio Quartulli
1541d36a36fSAntonio Quartulli if (attrs[OVPN_A_PEER_LOCAL_IPV4])
1551d36a36fSAntonio Quartulli return nla_data(attrs[OVPN_A_PEER_LOCAL_IPV4]);
1561d36a36fSAntonio Quartulli
1571d36a36fSAntonio Quartulli addr6 = nla_data(attrs[OVPN_A_PEER_LOCAL_IPV6]);
1581d36a36fSAntonio Quartulli /* this is an IPv4-mapped IPv6 address, therefore extract the actual
1591d36a36fSAntonio Quartulli * v4 address from the last 4 bytes
1601d36a36fSAntonio Quartulli */
1611d36a36fSAntonio Quartulli if (ipv6_addr_v4mapped((struct in6_addr *)addr6))
1621d36a36fSAntonio Quartulli return addr6 + 12;
1631d36a36fSAntonio Quartulli
1641d36a36fSAntonio Quartulli return addr6;
1651d36a36fSAntonio Quartulli }
1661d36a36fSAntonio Quartulli
ovpn_nl_family_get(struct nlattr * addr4,struct nlattr * addr6)1671d36a36fSAntonio Quartulli static sa_family_t ovpn_nl_family_get(struct nlattr *addr4,
1681d36a36fSAntonio Quartulli struct nlattr *addr6)
1691d36a36fSAntonio Quartulli {
1701d36a36fSAntonio Quartulli if (addr4)
1711d36a36fSAntonio Quartulli return AF_INET;
1721d36a36fSAntonio Quartulli
1731d36a36fSAntonio Quartulli if (addr6) {
1741d36a36fSAntonio Quartulli if (ipv6_addr_v4mapped((struct in6_addr *)nla_data(addr6)))
1751d36a36fSAntonio Quartulli return AF_INET;
1761d36a36fSAntonio Quartulli return AF_INET6;
1771d36a36fSAntonio Quartulli }
1781d36a36fSAntonio Quartulli
1791d36a36fSAntonio Quartulli return AF_UNSPEC;
1801d36a36fSAntonio Quartulli }
1811d36a36fSAntonio Quartulli
ovpn_nl_peer_precheck(struct ovpn_priv * ovpn,struct genl_info * info,struct nlattr ** attrs)1821d36a36fSAntonio Quartulli static int ovpn_nl_peer_precheck(struct ovpn_priv *ovpn,
1831d36a36fSAntonio Quartulli struct genl_info *info,
1841d36a36fSAntonio Quartulli struct nlattr **attrs)
1851d36a36fSAntonio Quartulli {
1861d36a36fSAntonio Quartulli sa_family_t local_fam, remote_fam;
1871d36a36fSAntonio Quartulli
1881d36a36fSAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs,
1891d36a36fSAntonio Quartulli OVPN_A_PEER_ID))
1901d36a36fSAntonio Quartulli return -EINVAL;
1911d36a36fSAntonio Quartulli
1921d36a36fSAntonio Quartulli if (attrs[OVPN_A_PEER_REMOTE_IPV4] && attrs[OVPN_A_PEER_REMOTE_IPV6]) {
1931d36a36fSAntonio Quartulli NL_SET_ERR_MSG_MOD(info->extack,
1941d36a36fSAntonio Quartulli "cannot specify both remote IPv4 or IPv6 address");
1951d36a36fSAntonio Quartulli return -EINVAL;
1961d36a36fSAntonio Quartulli }
1971d36a36fSAntonio Quartulli
1981d36a36fSAntonio Quartulli if (!attrs[OVPN_A_PEER_REMOTE_IPV4] &&
1991d36a36fSAntonio Quartulli !attrs[OVPN_A_PEER_REMOTE_IPV6] && attrs[OVPN_A_PEER_REMOTE_PORT]) {
2001d36a36fSAntonio Quartulli NL_SET_ERR_MSG_MOD(info->extack,
2011d36a36fSAntonio Quartulli "cannot specify remote port without IP address");
2021d36a36fSAntonio Quartulli return -EINVAL;
2031d36a36fSAntonio Quartulli }
2041d36a36fSAntonio Quartulli
2051d36a36fSAntonio Quartulli if ((attrs[OVPN_A_PEER_REMOTE_IPV4] ||
2061d36a36fSAntonio Quartulli attrs[OVPN_A_PEER_REMOTE_IPV6]) &&
2071d36a36fSAntonio Quartulli !attrs[OVPN_A_PEER_REMOTE_PORT]) {
2081d36a36fSAntonio Quartulli NL_SET_ERR_MSG_MOD(info->extack,
2091d36a36fSAntonio Quartulli "cannot specify remote IP address without port");
2101d36a36fSAntonio Quartulli return -EINVAL;
2111d36a36fSAntonio Quartulli }
2121d36a36fSAntonio Quartulli
2131d36a36fSAntonio Quartulli if (!attrs[OVPN_A_PEER_REMOTE_IPV4] &&
2141d36a36fSAntonio Quartulli attrs[OVPN_A_PEER_LOCAL_IPV4]) {
2151d36a36fSAntonio Quartulli NL_SET_ERR_MSG_MOD(info->extack,
2161d36a36fSAntonio Quartulli "cannot specify local IPv4 address without remote");
2171d36a36fSAntonio Quartulli return -EINVAL;
2181d36a36fSAntonio Quartulli }
2191d36a36fSAntonio Quartulli
2201d36a36fSAntonio Quartulli if (!attrs[OVPN_A_PEER_REMOTE_IPV6] &&
2211d36a36fSAntonio Quartulli attrs[OVPN_A_PEER_LOCAL_IPV6]) {
2221d36a36fSAntonio Quartulli NL_SET_ERR_MSG_MOD(info->extack,
2231d36a36fSAntonio Quartulli "cannot specify local IPV6 address without remote");
2241d36a36fSAntonio Quartulli return -EINVAL;
2251d36a36fSAntonio Quartulli }
2261d36a36fSAntonio Quartulli
2271d36a36fSAntonio Quartulli /* check that local and remote address families are the same even
2281d36a36fSAntonio Quartulli * after parsing v4mapped IPv6 addresses.
2291d36a36fSAntonio Quartulli * (if addresses are not provided, family will be AF_UNSPEC and
2301d36a36fSAntonio Quartulli * the check is skipped)
2311d36a36fSAntonio Quartulli */
2321d36a36fSAntonio Quartulli local_fam = ovpn_nl_family_get(attrs[OVPN_A_PEER_LOCAL_IPV4],
2331d36a36fSAntonio Quartulli attrs[OVPN_A_PEER_LOCAL_IPV6]);
2341d36a36fSAntonio Quartulli remote_fam = ovpn_nl_family_get(attrs[OVPN_A_PEER_REMOTE_IPV4],
2351d36a36fSAntonio Quartulli attrs[OVPN_A_PEER_REMOTE_IPV6]);
2361d36a36fSAntonio Quartulli if (local_fam != AF_UNSPEC && remote_fam != AF_UNSPEC &&
2371d36a36fSAntonio Quartulli local_fam != remote_fam) {
2381d36a36fSAntonio Quartulli NL_SET_ERR_MSG_MOD(info->extack,
2391d36a36fSAntonio Quartulli "mismatching local and remote address families");
2401d36a36fSAntonio Quartulli return -EINVAL;
2411d36a36fSAntonio Quartulli }
2421d36a36fSAntonio Quartulli
2431d36a36fSAntonio Quartulli if (remote_fam != AF_INET6 && attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) {
2441d36a36fSAntonio Quartulli NL_SET_ERR_MSG_MOD(info->extack,
2451d36a36fSAntonio Quartulli "cannot specify scope id without remote IPv6 address");
2461d36a36fSAntonio Quartulli return -EINVAL;
2471d36a36fSAntonio Quartulli }
2481d36a36fSAntonio Quartulli
2491d36a36fSAntonio Quartulli /* VPN IPs are needed only in MP mode for selecting the right peer */
2501d36a36fSAntonio Quartulli if (ovpn->mode == OVPN_MODE_P2P && (attrs[OVPN_A_PEER_VPN_IPV4] ||
2511d36a36fSAntonio Quartulli attrs[OVPN_A_PEER_VPN_IPV6])) {
2521d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
2531d36a36fSAntonio Quartulli "unexpected VPN IP in P2P mode");
2541d36a36fSAntonio Quartulli return -EINVAL;
2551d36a36fSAntonio Quartulli }
2561d36a36fSAntonio Quartulli
2571d36a36fSAntonio Quartulli if ((attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL] &&
2581d36a36fSAntonio Quartulli !attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT]) ||
2591d36a36fSAntonio Quartulli (!attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL] &&
2601d36a36fSAntonio Quartulli attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT])) {
2611d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
2621d36a36fSAntonio Quartulli "keepalive interval and timeout are required together");
2631d36a36fSAntonio Quartulli return -EINVAL;
2641d36a36fSAntonio Quartulli }
2651d36a36fSAntonio Quartulli
2661d36a36fSAntonio Quartulli return 0;
2671d36a36fSAntonio Quartulli }
2681d36a36fSAntonio Quartulli
2691d36a36fSAntonio Quartulli /**
2701d36a36fSAntonio Quartulli * ovpn_nl_peer_modify - modify the peer attributes according to the incoming msg
2711d36a36fSAntonio Quartulli * @peer: the peer to modify
2721d36a36fSAntonio Quartulli * @info: generic netlink info from the user request
2731d36a36fSAntonio Quartulli * @attrs: the attributes from the user request
2741d36a36fSAntonio Quartulli *
2751d36a36fSAntonio Quartulli * Return: a negative error code in case of failure, 0 on success or 1 on
2761d36a36fSAntonio Quartulli * success and the VPN IPs have been modified (requires rehashing in MP
2771d36a36fSAntonio Quartulli * mode)
2781d36a36fSAntonio Quartulli */
ovpn_nl_peer_modify(struct ovpn_peer * peer,struct genl_info * info,struct nlattr ** attrs)2791d36a36fSAntonio Quartulli static int ovpn_nl_peer_modify(struct ovpn_peer *peer, struct genl_info *info,
2801d36a36fSAntonio Quartulli struct nlattr **attrs)
2811d36a36fSAntonio Quartulli {
2821d36a36fSAntonio Quartulli struct sockaddr_storage ss = {};
2831d36a36fSAntonio Quartulli void *local_ip = NULL;
2841d36a36fSAntonio Quartulli u32 interv, timeout;
2851d36a36fSAntonio Quartulli bool rehash = false;
2861d36a36fSAntonio Quartulli int ret;
2871d36a36fSAntonio Quartulli
2881d36a36fSAntonio Quartulli spin_lock_bh(&peer->lock);
2891d36a36fSAntonio Quartulli
2901d36a36fSAntonio Quartulli if (ovpn_nl_attr_sockaddr_remote(attrs, &ss)) {
2911d36a36fSAntonio Quartulli /* we carry the local IP in a generic container.
2921d36a36fSAntonio Quartulli * ovpn_peer_reset_sockaddr() will properly interpret it
2931d36a36fSAntonio Quartulli * based on ss.ss_family
2941d36a36fSAntonio Quartulli */
2951d36a36fSAntonio Quartulli local_ip = ovpn_nl_attr_local_ip(attrs);
2961d36a36fSAntonio Quartulli
2971d36a36fSAntonio Quartulli /* set peer sockaddr */
2981d36a36fSAntonio Quartulli ret = ovpn_peer_reset_sockaddr(peer, &ss, local_ip);
2991d36a36fSAntonio Quartulli if (ret < 0) {
3001d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
3011d36a36fSAntonio Quartulli "cannot set peer sockaddr: %d",
3021d36a36fSAntonio Quartulli ret);
3031d36a36fSAntonio Quartulli goto err_unlock;
3041d36a36fSAntonio Quartulli }
3051d36a36fSAntonio Quartulli dst_cache_reset(&peer->dst_cache);
3061d36a36fSAntonio Quartulli }
3071d36a36fSAntonio Quartulli
3081d36a36fSAntonio Quartulli if (attrs[OVPN_A_PEER_VPN_IPV4]) {
3091d36a36fSAntonio Quartulli rehash = true;
3101d36a36fSAntonio Quartulli peer->vpn_addrs.ipv4.s_addr =
3111d36a36fSAntonio Quartulli nla_get_in_addr(attrs[OVPN_A_PEER_VPN_IPV4]);
3121d36a36fSAntonio Quartulli }
3131d36a36fSAntonio Quartulli
3141d36a36fSAntonio Quartulli if (attrs[OVPN_A_PEER_VPN_IPV6]) {
3151d36a36fSAntonio Quartulli rehash = true;
3161d36a36fSAntonio Quartulli peer->vpn_addrs.ipv6 =
3171d36a36fSAntonio Quartulli nla_get_in6_addr(attrs[OVPN_A_PEER_VPN_IPV6]);
3181d36a36fSAntonio Quartulli }
3191d36a36fSAntonio Quartulli
3201d36a36fSAntonio Quartulli /* when setting the keepalive, both parameters have to be configured */
3211d36a36fSAntonio Quartulli if (attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL] &&
3221d36a36fSAntonio Quartulli attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT]) {
3231d36a36fSAntonio Quartulli interv = nla_get_u32(attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL]);
3241d36a36fSAntonio Quartulli timeout = nla_get_u32(attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT]);
3251d36a36fSAntonio Quartulli ovpn_peer_keepalive_set(peer, interv, timeout);
3261d36a36fSAntonio Quartulli }
3271d36a36fSAntonio Quartulli
3281d36a36fSAntonio Quartulli netdev_dbg(peer->ovpn->dev,
3291d36a36fSAntonio Quartulli "modify peer id=%u endpoint=%pIScp VPN-IPv4=%pI4 VPN-IPv6=%pI6c\n",
3301d36a36fSAntonio Quartulli peer->id, &ss,
3311d36a36fSAntonio Quartulli &peer->vpn_addrs.ipv4.s_addr, &peer->vpn_addrs.ipv6);
3321d36a36fSAntonio Quartulli
3331d36a36fSAntonio Quartulli spin_unlock_bh(&peer->lock);
3341d36a36fSAntonio Quartulli
3351d36a36fSAntonio Quartulli return rehash ? 1 : 0;
3361d36a36fSAntonio Quartulli err_unlock:
3371d36a36fSAntonio Quartulli spin_unlock_bh(&peer->lock);
3381d36a36fSAntonio Quartulli return ret;
3391d36a36fSAntonio Quartulli }
3401d36a36fSAntonio Quartulli
ovpn_nl_peer_new_doit(struct sk_buff * skb,struct genl_info * info)341b7a63391SAntonio Quartulli int ovpn_nl_peer_new_doit(struct sk_buff *skb, struct genl_info *info)
342b7a63391SAntonio Quartulli {
3431d36a36fSAntonio Quartulli struct nlattr *attrs[OVPN_A_PEER_MAX + 1];
3441d36a36fSAntonio Quartulli struct ovpn_priv *ovpn = info->user_ptr[0];
3451d36a36fSAntonio Quartulli struct ovpn_socket *ovpn_sock;
3461d36a36fSAntonio Quartulli struct socket *sock = NULL;
3471d36a36fSAntonio Quartulli struct ovpn_peer *peer;
3481d36a36fSAntonio Quartulli u32 sockfd, peer_id;
3491d36a36fSAntonio Quartulli int ret;
3501d36a36fSAntonio Quartulli
3511d36a36fSAntonio Quartulli if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER))
3521d36a36fSAntonio Quartulli return -EINVAL;
3531d36a36fSAntonio Quartulli
3541d36a36fSAntonio Quartulli ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER],
3551d36a36fSAntonio Quartulli ovpn_peer_nl_policy, info->extack);
3561d36a36fSAntonio Quartulli if (ret)
3571d36a36fSAntonio Quartulli return ret;
3581d36a36fSAntonio Quartulli
3591d36a36fSAntonio Quartulli ret = ovpn_nl_peer_precheck(ovpn, info, attrs);
3601d36a36fSAntonio Quartulli if (ret < 0)
3611d36a36fSAntonio Quartulli return ret;
3621d36a36fSAntonio Quartulli
3631d36a36fSAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs,
3641d36a36fSAntonio Quartulli OVPN_A_PEER_SOCKET))
3651d36a36fSAntonio Quartulli return -EINVAL;
3661d36a36fSAntonio Quartulli
3671d36a36fSAntonio Quartulli /* in MP mode VPN IPs are required for selecting the right peer */
3681d36a36fSAntonio Quartulli if (ovpn->mode == OVPN_MODE_MP && !attrs[OVPN_A_PEER_VPN_IPV4] &&
3691d36a36fSAntonio Quartulli !attrs[OVPN_A_PEER_VPN_IPV6]) {
3701d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
3711d36a36fSAntonio Quartulli "VPN IP must be provided in MP mode");
3721d36a36fSAntonio Quartulli return -EINVAL;
3731d36a36fSAntonio Quartulli }
3741d36a36fSAntonio Quartulli
3751d36a36fSAntonio Quartulli peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]);
3761d36a36fSAntonio Quartulli peer = ovpn_peer_new(ovpn, peer_id);
3771d36a36fSAntonio Quartulli if (IS_ERR(peer)) {
3781d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
3791d36a36fSAntonio Quartulli "cannot create new peer object for peer %u: %ld",
3801d36a36fSAntonio Quartulli peer_id, PTR_ERR(peer));
3811d36a36fSAntonio Quartulli return PTR_ERR(peer);
3821d36a36fSAntonio Quartulli }
3831d36a36fSAntonio Quartulli
3841d36a36fSAntonio Quartulli /* lookup the fd in the kernel table and extract the socket object */
3851d36a36fSAntonio Quartulli sockfd = nla_get_u32(attrs[OVPN_A_PEER_SOCKET]);
3861d36a36fSAntonio Quartulli /* sockfd_lookup() increases sock's refcounter */
3871d36a36fSAntonio Quartulli sock = sockfd_lookup(sockfd, &ret);
3881d36a36fSAntonio Quartulli if (!sock) {
3891d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
3901d36a36fSAntonio Quartulli "cannot lookup peer socket (fd=%u): %d",
3911d36a36fSAntonio Quartulli sockfd, ret);
3921d36a36fSAntonio Quartulli ret = -ENOTSOCK;
3931d36a36fSAntonio Quartulli goto peer_release;
3941d36a36fSAntonio Quartulli }
3951d36a36fSAntonio Quartulli
3961d36a36fSAntonio Quartulli /* Only when using UDP as transport protocol the remote endpoint
3971d36a36fSAntonio Quartulli * can be configured so that ovpn knows where to send packets to.
3981d36a36fSAntonio Quartulli */
3991d36a36fSAntonio Quartulli if (sock->sk->sk_protocol == IPPROTO_UDP &&
4001d36a36fSAntonio Quartulli !attrs[OVPN_A_PEER_REMOTE_IPV4] &&
4011d36a36fSAntonio Quartulli !attrs[OVPN_A_PEER_REMOTE_IPV6]) {
4021d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
4031d36a36fSAntonio Quartulli "missing remote IP address for UDP socket");
4041d36a36fSAntonio Quartulli sockfd_put(sock);
4051d36a36fSAntonio Quartulli ret = -EINVAL;
4061d36a36fSAntonio Quartulli goto peer_release;
4071d36a36fSAntonio Quartulli }
4081d36a36fSAntonio Quartulli
4091d36a36fSAntonio Quartulli /* In case of TCP, the socket is connected to the peer and ovpn
4101d36a36fSAntonio Quartulli * will just send bytes over it, without the need to specify a
4111d36a36fSAntonio Quartulli * destination.
4121d36a36fSAntonio Quartulli */
4131d36a36fSAntonio Quartulli if (sock->sk->sk_protocol == IPPROTO_TCP &&
4141d36a36fSAntonio Quartulli (attrs[OVPN_A_PEER_REMOTE_IPV4] ||
4151d36a36fSAntonio Quartulli attrs[OVPN_A_PEER_REMOTE_IPV6])) {
4161d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
4171d36a36fSAntonio Quartulli "unexpected remote IP address with TCP socket");
4181d36a36fSAntonio Quartulli sockfd_put(sock);
4191d36a36fSAntonio Quartulli ret = -EINVAL;
4201d36a36fSAntonio Quartulli goto peer_release;
4211d36a36fSAntonio Quartulli }
4221d36a36fSAntonio Quartulli
4231d36a36fSAntonio Quartulli ovpn_sock = ovpn_socket_new(sock, peer);
4241d36a36fSAntonio Quartulli /* at this point we unconditionally drop the reference to the socket:
4251d36a36fSAntonio Quartulli * - in case of error, the socket has to be dropped
4261d36a36fSAntonio Quartulli * - if case of success, the socket is configured and let
4271d36a36fSAntonio Quartulli * userspace own the reference, so that the latter can
4281d36a36fSAntonio Quartulli * trigger the final close()
4291d36a36fSAntonio Quartulli */
4301d36a36fSAntonio Quartulli sockfd_put(sock);
4311d36a36fSAntonio Quartulli if (IS_ERR(ovpn_sock)) {
4321d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
4331d36a36fSAntonio Quartulli "cannot encapsulate socket: %ld",
4341d36a36fSAntonio Quartulli PTR_ERR(ovpn_sock));
4351d36a36fSAntonio Quartulli ret = -ENOTSOCK;
4361d36a36fSAntonio Quartulli goto peer_release;
4371d36a36fSAntonio Quartulli }
4381d36a36fSAntonio Quartulli
4391d36a36fSAntonio Quartulli rcu_assign_pointer(peer->sock, ovpn_sock);
4401d36a36fSAntonio Quartulli
4411d36a36fSAntonio Quartulli ret = ovpn_nl_peer_modify(peer, info, attrs);
4421d36a36fSAntonio Quartulli if (ret < 0)
4431d36a36fSAntonio Quartulli goto sock_release;
4441d36a36fSAntonio Quartulli
4451d36a36fSAntonio Quartulli ret = ovpn_peer_add(ovpn, peer);
4461d36a36fSAntonio Quartulli if (ret < 0) {
4471d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
4481d36a36fSAntonio Quartulli "cannot add new peer (id=%u) to hashtable: %d",
4491d36a36fSAntonio Quartulli peer->id, ret);
4501d36a36fSAntonio Quartulli goto sock_release;
4511d36a36fSAntonio Quartulli }
4521d36a36fSAntonio Quartulli
4531d36a36fSAntonio Quartulli return 0;
4541d36a36fSAntonio Quartulli
4551d36a36fSAntonio Quartulli sock_release:
4561d36a36fSAntonio Quartulli ovpn_socket_release(peer);
4571d36a36fSAntonio Quartulli peer_release:
4581d36a36fSAntonio Quartulli /* release right away because peer was not yet hashed, thus it is not
4591d36a36fSAntonio Quartulli * used in any context
4601d36a36fSAntonio Quartulli */
4611d36a36fSAntonio Quartulli ovpn_peer_release(peer);
4621d36a36fSAntonio Quartulli
4631d36a36fSAntonio Quartulli return ret;
464b7a63391SAntonio Quartulli }
465b7a63391SAntonio Quartulli
ovpn_nl_peer_set_doit(struct sk_buff * skb,struct genl_info * info)466b7a63391SAntonio Quartulli int ovpn_nl_peer_set_doit(struct sk_buff *skb, struct genl_info *info)
467b7a63391SAntonio Quartulli {
4681d36a36fSAntonio Quartulli struct nlattr *attrs[OVPN_A_PEER_MAX + 1];
4691d36a36fSAntonio Quartulli struct ovpn_priv *ovpn = info->user_ptr[0];
4701d36a36fSAntonio Quartulli struct ovpn_socket *sock;
4711d36a36fSAntonio Quartulli struct ovpn_peer *peer;
4721d36a36fSAntonio Quartulli u32 peer_id;
4731d36a36fSAntonio Quartulli int ret;
4741d36a36fSAntonio Quartulli
4751d36a36fSAntonio Quartulli if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER))
4761d36a36fSAntonio Quartulli return -EINVAL;
4771d36a36fSAntonio Quartulli
4781d36a36fSAntonio Quartulli ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER],
4791d36a36fSAntonio Quartulli ovpn_peer_nl_policy, info->extack);
4801d36a36fSAntonio Quartulli if (ret)
4811d36a36fSAntonio Quartulli return ret;
4821d36a36fSAntonio Quartulli
4831d36a36fSAntonio Quartulli ret = ovpn_nl_peer_precheck(ovpn, info, attrs);
4841d36a36fSAntonio Quartulli if (ret < 0)
4851d36a36fSAntonio Quartulli return ret;
4861d36a36fSAntonio Quartulli
4871d36a36fSAntonio Quartulli if (attrs[OVPN_A_PEER_SOCKET]) {
4881d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
4891d36a36fSAntonio Quartulli "socket cannot be modified");
4901d36a36fSAntonio Quartulli return -EINVAL;
4911d36a36fSAntonio Quartulli }
4921d36a36fSAntonio Quartulli
4931d36a36fSAntonio Quartulli peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]);
4941d36a36fSAntonio Quartulli peer = ovpn_peer_get_by_id(ovpn, peer_id);
4951d36a36fSAntonio Quartulli if (!peer) {
4961d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
4971d36a36fSAntonio Quartulli "cannot find peer with id %u", peer_id);
4981d36a36fSAntonio Quartulli return -ENOENT;
4991d36a36fSAntonio Quartulli }
5001d36a36fSAntonio Quartulli
5011d36a36fSAntonio Quartulli /* when using a TCP socket the remote IP is not expected */
5021d36a36fSAntonio Quartulli rcu_read_lock();
5031d36a36fSAntonio Quartulli sock = rcu_dereference(peer->sock);
504*ba499a07SAntonio Quartulli if (sock && sock->sk->sk_protocol == IPPROTO_TCP &&
5051d36a36fSAntonio Quartulli (attrs[OVPN_A_PEER_REMOTE_IPV4] ||
5061d36a36fSAntonio Quartulli attrs[OVPN_A_PEER_REMOTE_IPV6])) {
5071d36a36fSAntonio Quartulli rcu_read_unlock();
5081d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
5091d36a36fSAntonio Quartulli "unexpected remote IP address with TCP socket");
5101d36a36fSAntonio Quartulli ovpn_peer_put(peer);
5111d36a36fSAntonio Quartulli return -EINVAL;
5121d36a36fSAntonio Quartulli }
5131d36a36fSAntonio Quartulli rcu_read_unlock();
5141d36a36fSAntonio Quartulli
5151d36a36fSAntonio Quartulli spin_lock_bh(&ovpn->lock);
5161d36a36fSAntonio Quartulli ret = ovpn_nl_peer_modify(peer, info, attrs);
5171d36a36fSAntonio Quartulli if (ret < 0) {
5181d36a36fSAntonio Quartulli spin_unlock_bh(&ovpn->lock);
5191d36a36fSAntonio Quartulli ovpn_peer_put(peer);
5201d36a36fSAntonio Quartulli return ret;
5211d36a36fSAntonio Quartulli }
5221d36a36fSAntonio Quartulli
5231d36a36fSAntonio Quartulli /* ret == 1 means that VPN IPv4/6 has been modified and rehashing
5241d36a36fSAntonio Quartulli * is required
5251d36a36fSAntonio Quartulli */
5261d36a36fSAntonio Quartulli if (ret > 0)
5271d36a36fSAntonio Quartulli ovpn_peer_hash_vpn_ip(peer);
5281d36a36fSAntonio Quartulli spin_unlock_bh(&ovpn->lock);
5291d36a36fSAntonio Quartulli ovpn_peer_put(peer);
5301d36a36fSAntonio Quartulli
5311d36a36fSAntonio Quartulli return 0;
5321d36a36fSAntonio Quartulli }
5331d36a36fSAntonio Quartulli
ovpn_nl_send_peer(struct sk_buff * skb,const struct genl_info * info,const struct ovpn_peer * peer,u32 portid,u32 seq,int flags)5341d36a36fSAntonio Quartulli static int ovpn_nl_send_peer(struct sk_buff *skb, const struct genl_info *info,
5351d36a36fSAntonio Quartulli const struct ovpn_peer *peer, u32 portid, u32 seq,
5361d36a36fSAntonio Quartulli int flags)
5371d36a36fSAntonio Quartulli {
5381d36a36fSAntonio Quartulli const struct ovpn_bind *bind;
5391d36a36fSAntonio Quartulli struct ovpn_socket *sock;
5401d36a36fSAntonio Quartulli int ret = -EMSGSIZE;
5411d36a36fSAntonio Quartulli struct nlattr *attr;
5421d36a36fSAntonio Quartulli __be16 local_port;
5431d36a36fSAntonio Quartulli void *hdr;
5441d36a36fSAntonio Quartulli int id;
5451d36a36fSAntonio Quartulli
5461d36a36fSAntonio Quartulli hdr = genlmsg_put(skb, portid, seq, &ovpn_nl_family, flags,
5471d36a36fSAntonio Quartulli OVPN_CMD_PEER_GET);
5481d36a36fSAntonio Quartulli if (!hdr)
5491d36a36fSAntonio Quartulli return -ENOBUFS;
5501d36a36fSAntonio Quartulli
5511d36a36fSAntonio Quartulli attr = nla_nest_start(skb, OVPN_A_PEER);
5521d36a36fSAntonio Quartulli if (!attr)
5531d36a36fSAntonio Quartulli goto err;
5541d36a36fSAntonio Quartulli
5551d36a36fSAntonio Quartulli rcu_read_lock();
5561d36a36fSAntonio Quartulli sock = rcu_dereference(peer->sock);
5571d36a36fSAntonio Quartulli if (!sock) {
5581d36a36fSAntonio Quartulli ret = -EINVAL;
5591d36a36fSAntonio Quartulli goto err_unlock;
5601d36a36fSAntonio Quartulli }
5611d36a36fSAntonio Quartulli
562*ba499a07SAntonio Quartulli if (!net_eq(genl_info_net(info), sock_net(sock->sk))) {
5631d36a36fSAntonio Quartulli id = peernet2id_alloc(genl_info_net(info),
564*ba499a07SAntonio Quartulli sock_net(sock->sk),
5651d36a36fSAntonio Quartulli GFP_ATOMIC);
5661d36a36fSAntonio Quartulli if (nla_put_s32(skb, OVPN_A_PEER_SOCKET_NETNSID, id))
5671d36a36fSAntonio Quartulli goto err_unlock;
5681d36a36fSAntonio Quartulli }
569*ba499a07SAntonio Quartulli local_port = inet_sk(sock->sk)->inet_sport;
5701d36a36fSAntonio Quartulli rcu_read_unlock();
5711d36a36fSAntonio Quartulli
5721d36a36fSAntonio Quartulli if (nla_put_u32(skb, OVPN_A_PEER_ID, peer->id))
5731d36a36fSAntonio Quartulli goto err;
5741d36a36fSAntonio Quartulli
5751d36a36fSAntonio Quartulli if (peer->vpn_addrs.ipv4.s_addr != htonl(INADDR_ANY))
5761d36a36fSAntonio Quartulli if (nla_put_in_addr(skb, OVPN_A_PEER_VPN_IPV4,
5771d36a36fSAntonio Quartulli peer->vpn_addrs.ipv4.s_addr))
5781d36a36fSAntonio Quartulli goto err;
5791d36a36fSAntonio Quartulli
5801d36a36fSAntonio Quartulli if (!ipv6_addr_equal(&peer->vpn_addrs.ipv6, &in6addr_any))
5811d36a36fSAntonio Quartulli if (nla_put_in6_addr(skb, OVPN_A_PEER_VPN_IPV6,
5821d36a36fSAntonio Quartulli &peer->vpn_addrs.ipv6))
5831d36a36fSAntonio Quartulli goto err;
5841d36a36fSAntonio Quartulli
5851d36a36fSAntonio Quartulli if (nla_put_u32(skb, OVPN_A_PEER_KEEPALIVE_INTERVAL,
5861d36a36fSAntonio Quartulli peer->keepalive_interval) ||
5871d36a36fSAntonio Quartulli nla_put_u32(skb, OVPN_A_PEER_KEEPALIVE_TIMEOUT,
5881d36a36fSAntonio Quartulli peer->keepalive_timeout))
5891d36a36fSAntonio Quartulli goto err;
5901d36a36fSAntonio Quartulli
5911d36a36fSAntonio Quartulli rcu_read_lock();
5921d36a36fSAntonio Quartulli bind = rcu_dereference(peer->bind);
5931d36a36fSAntonio Quartulli if (bind) {
5941d36a36fSAntonio Quartulli if (bind->remote.in4.sin_family == AF_INET) {
5951d36a36fSAntonio Quartulli if (nla_put_in_addr(skb, OVPN_A_PEER_REMOTE_IPV4,
5961d36a36fSAntonio Quartulli bind->remote.in4.sin_addr.s_addr) ||
5971d36a36fSAntonio Quartulli nla_put_net16(skb, OVPN_A_PEER_REMOTE_PORT,
5981d36a36fSAntonio Quartulli bind->remote.in4.sin_port) ||
5991d36a36fSAntonio Quartulli nla_put_in_addr(skb, OVPN_A_PEER_LOCAL_IPV4,
6001d36a36fSAntonio Quartulli bind->local.ipv4.s_addr))
6011d36a36fSAntonio Quartulli goto err_unlock;
6021d36a36fSAntonio Quartulli } else if (bind->remote.in4.sin_family == AF_INET6) {
6031d36a36fSAntonio Quartulli if (nla_put_in6_addr(skb, OVPN_A_PEER_REMOTE_IPV6,
6041d36a36fSAntonio Quartulli &bind->remote.in6.sin6_addr) ||
6051d36a36fSAntonio Quartulli nla_put_u32(skb, OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID,
6061d36a36fSAntonio Quartulli bind->remote.in6.sin6_scope_id) ||
6071d36a36fSAntonio Quartulli nla_put_net16(skb, OVPN_A_PEER_REMOTE_PORT,
6081d36a36fSAntonio Quartulli bind->remote.in6.sin6_port) ||
6091d36a36fSAntonio Quartulli nla_put_in6_addr(skb, OVPN_A_PEER_LOCAL_IPV6,
6101d36a36fSAntonio Quartulli &bind->local.ipv6))
6111d36a36fSAntonio Quartulli goto err_unlock;
6121d36a36fSAntonio Quartulli }
6131d36a36fSAntonio Quartulli }
6141d36a36fSAntonio Quartulli rcu_read_unlock();
6151d36a36fSAntonio Quartulli
6161d36a36fSAntonio Quartulli if (nla_put_net16(skb, OVPN_A_PEER_LOCAL_PORT, local_port) ||
6171d36a36fSAntonio Quartulli /* VPN RX stats */
6181d36a36fSAntonio Quartulli nla_put_uint(skb, OVPN_A_PEER_VPN_RX_BYTES,
6191d36a36fSAntonio Quartulli atomic64_read(&peer->vpn_stats.rx.bytes)) ||
6201d36a36fSAntonio Quartulli nla_put_uint(skb, OVPN_A_PEER_VPN_RX_PACKETS,
6211d36a36fSAntonio Quartulli atomic64_read(&peer->vpn_stats.rx.packets)) ||
6221d36a36fSAntonio Quartulli /* VPN TX stats */
6231d36a36fSAntonio Quartulli nla_put_uint(skb, OVPN_A_PEER_VPN_TX_BYTES,
6241d36a36fSAntonio Quartulli atomic64_read(&peer->vpn_stats.tx.bytes)) ||
6251d36a36fSAntonio Quartulli nla_put_uint(skb, OVPN_A_PEER_VPN_TX_PACKETS,
6261d36a36fSAntonio Quartulli atomic64_read(&peer->vpn_stats.tx.packets)) ||
6271d36a36fSAntonio Quartulli /* link RX stats */
6281d36a36fSAntonio Quartulli nla_put_uint(skb, OVPN_A_PEER_LINK_RX_BYTES,
6291d36a36fSAntonio Quartulli atomic64_read(&peer->link_stats.rx.bytes)) ||
6301d36a36fSAntonio Quartulli nla_put_uint(skb, OVPN_A_PEER_LINK_RX_PACKETS,
6311d36a36fSAntonio Quartulli atomic64_read(&peer->link_stats.rx.packets)) ||
6321d36a36fSAntonio Quartulli /* link TX stats */
6331d36a36fSAntonio Quartulli nla_put_uint(skb, OVPN_A_PEER_LINK_TX_BYTES,
6341d36a36fSAntonio Quartulli atomic64_read(&peer->link_stats.tx.bytes)) ||
6351d36a36fSAntonio Quartulli nla_put_uint(skb, OVPN_A_PEER_LINK_TX_PACKETS,
6361d36a36fSAntonio Quartulli atomic64_read(&peer->link_stats.tx.packets)))
6371d36a36fSAntonio Quartulli goto err;
6381d36a36fSAntonio Quartulli
6391d36a36fSAntonio Quartulli nla_nest_end(skb, attr);
6401d36a36fSAntonio Quartulli genlmsg_end(skb, hdr);
6411d36a36fSAntonio Quartulli
6421d36a36fSAntonio Quartulli return 0;
6431d36a36fSAntonio Quartulli err_unlock:
6441d36a36fSAntonio Quartulli rcu_read_unlock();
6451d36a36fSAntonio Quartulli err:
6461d36a36fSAntonio Quartulli genlmsg_cancel(skb, hdr);
6471d36a36fSAntonio Quartulli return ret;
648b7a63391SAntonio Quartulli }
649b7a63391SAntonio Quartulli
ovpn_nl_peer_get_doit(struct sk_buff * skb,struct genl_info * info)650b7a63391SAntonio Quartulli int ovpn_nl_peer_get_doit(struct sk_buff *skb, struct genl_info *info)
651b7a63391SAntonio Quartulli {
6521d36a36fSAntonio Quartulli struct nlattr *attrs[OVPN_A_PEER_MAX + 1];
6531d36a36fSAntonio Quartulli struct ovpn_priv *ovpn = info->user_ptr[0];
6541d36a36fSAntonio Quartulli struct ovpn_peer *peer;
6551d36a36fSAntonio Quartulli struct sk_buff *msg;
6561d36a36fSAntonio Quartulli u32 peer_id;
6571d36a36fSAntonio Quartulli int ret;
6581d36a36fSAntonio Quartulli
6591d36a36fSAntonio Quartulli if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER))
6601d36a36fSAntonio Quartulli return -EINVAL;
6611d36a36fSAntonio Quartulli
6621d36a36fSAntonio Quartulli ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER],
6631d36a36fSAntonio Quartulli ovpn_peer_nl_policy, info->extack);
6641d36a36fSAntonio Quartulli if (ret)
6651d36a36fSAntonio Quartulli return ret;
6661d36a36fSAntonio Quartulli
6671d36a36fSAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs,
6681d36a36fSAntonio Quartulli OVPN_A_PEER_ID))
6691d36a36fSAntonio Quartulli return -EINVAL;
6701d36a36fSAntonio Quartulli
6711d36a36fSAntonio Quartulli peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]);
6721d36a36fSAntonio Quartulli peer = ovpn_peer_get_by_id(ovpn, peer_id);
6731d36a36fSAntonio Quartulli if (!peer) {
6741d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
6751d36a36fSAntonio Quartulli "cannot find peer with id %u", peer_id);
6761d36a36fSAntonio Quartulli return -ENOENT;
6771d36a36fSAntonio Quartulli }
6781d36a36fSAntonio Quartulli
6791d36a36fSAntonio Quartulli msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6801d36a36fSAntonio Quartulli if (!msg) {
6811d36a36fSAntonio Quartulli ret = -ENOMEM;
6821d36a36fSAntonio Quartulli goto err;
6831d36a36fSAntonio Quartulli }
6841d36a36fSAntonio Quartulli
6851d36a36fSAntonio Quartulli ret = ovpn_nl_send_peer(msg, info, peer, info->snd_portid,
6861d36a36fSAntonio Quartulli info->snd_seq, 0);
6871d36a36fSAntonio Quartulli if (ret < 0) {
6881d36a36fSAntonio Quartulli nlmsg_free(msg);
6891d36a36fSAntonio Quartulli goto err;
6901d36a36fSAntonio Quartulli }
6911d36a36fSAntonio Quartulli
6921d36a36fSAntonio Quartulli ret = genlmsg_reply(msg, info);
6931d36a36fSAntonio Quartulli err:
6941d36a36fSAntonio Quartulli ovpn_peer_put(peer);
6951d36a36fSAntonio Quartulli return ret;
696b7a63391SAntonio Quartulli }
697b7a63391SAntonio Quartulli
ovpn_nl_peer_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)698b7a63391SAntonio Quartulli int ovpn_nl_peer_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
699b7a63391SAntonio Quartulli {
7001d36a36fSAntonio Quartulli const struct genl_info *info = genl_info_dump(cb);
7011d36a36fSAntonio Quartulli int bkt, last_idx = cb->args[1], dumped = 0;
7021d36a36fSAntonio Quartulli netdevice_tracker tracker;
7031d36a36fSAntonio Quartulli struct ovpn_priv *ovpn;
7041d36a36fSAntonio Quartulli struct ovpn_peer *peer;
7051d36a36fSAntonio Quartulli
7061d36a36fSAntonio Quartulli ovpn = ovpn_get_dev_from_attrs(sock_net(cb->skb->sk), info, &tracker);
7071d36a36fSAntonio Quartulli if (IS_ERR(ovpn))
7081d36a36fSAntonio Quartulli return PTR_ERR(ovpn);
7091d36a36fSAntonio Quartulli
7101d36a36fSAntonio Quartulli if (ovpn->mode == OVPN_MODE_P2P) {
7111d36a36fSAntonio Quartulli /* if we already dumped a peer it means we are done */
7121d36a36fSAntonio Quartulli if (last_idx)
7131d36a36fSAntonio Quartulli goto out;
7141d36a36fSAntonio Quartulli
7151d36a36fSAntonio Quartulli rcu_read_lock();
7161d36a36fSAntonio Quartulli peer = rcu_dereference(ovpn->peer);
7171d36a36fSAntonio Quartulli if (peer) {
7181d36a36fSAntonio Quartulli if (ovpn_nl_send_peer(skb, info, peer,
7191d36a36fSAntonio Quartulli NETLINK_CB(cb->skb).portid,
7201d36a36fSAntonio Quartulli cb->nlh->nlmsg_seq,
7211d36a36fSAntonio Quartulli NLM_F_MULTI) == 0)
7221d36a36fSAntonio Quartulli dumped++;
7231d36a36fSAntonio Quartulli }
7241d36a36fSAntonio Quartulli rcu_read_unlock();
7251d36a36fSAntonio Quartulli } else {
7261d36a36fSAntonio Quartulli rcu_read_lock();
7271d36a36fSAntonio Quartulli hash_for_each_rcu(ovpn->peers->by_id, bkt, peer,
7281d36a36fSAntonio Quartulli hash_entry_id) {
7291d36a36fSAntonio Quartulli /* skip already dumped peers that were dumped by
7301d36a36fSAntonio Quartulli * previous invocations
7311d36a36fSAntonio Quartulli */
7321d36a36fSAntonio Quartulli if (last_idx > 0) {
7331d36a36fSAntonio Quartulli last_idx--;
7341d36a36fSAntonio Quartulli continue;
7351d36a36fSAntonio Quartulli }
7361d36a36fSAntonio Quartulli
7371d36a36fSAntonio Quartulli if (ovpn_nl_send_peer(skb, info, peer,
7381d36a36fSAntonio Quartulli NETLINK_CB(cb->skb).portid,
7391d36a36fSAntonio Quartulli cb->nlh->nlmsg_seq,
7401d36a36fSAntonio Quartulli NLM_F_MULTI) < 0)
7411d36a36fSAntonio Quartulli break;
7421d36a36fSAntonio Quartulli
7431d36a36fSAntonio Quartulli /* count peers being dumped during this invocation */
7441d36a36fSAntonio Quartulli dumped++;
7451d36a36fSAntonio Quartulli }
7461d36a36fSAntonio Quartulli rcu_read_unlock();
7471d36a36fSAntonio Quartulli }
7481d36a36fSAntonio Quartulli
7491d36a36fSAntonio Quartulli out:
7501d36a36fSAntonio Quartulli netdev_put(ovpn->dev, &tracker);
7511d36a36fSAntonio Quartulli
7521d36a36fSAntonio Quartulli /* sum up peers dumped in this message, so that at the next invocation
7531d36a36fSAntonio Quartulli * we can continue from where we left
7541d36a36fSAntonio Quartulli */
7551d36a36fSAntonio Quartulli cb->args[1] += dumped;
7561d36a36fSAntonio Quartulli return skb->len;
757b7a63391SAntonio Quartulli }
758b7a63391SAntonio Quartulli
ovpn_nl_peer_del_doit(struct sk_buff * skb,struct genl_info * info)759b7a63391SAntonio Quartulli int ovpn_nl_peer_del_doit(struct sk_buff *skb, struct genl_info *info)
760b7a63391SAntonio Quartulli {
7611d36a36fSAntonio Quartulli struct nlattr *attrs[OVPN_A_PEER_MAX + 1];
7621d36a36fSAntonio Quartulli struct ovpn_priv *ovpn = info->user_ptr[0];
7631d36a36fSAntonio Quartulli struct ovpn_peer *peer;
7641d36a36fSAntonio Quartulli u32 peer_id;
7651d36a36fSAntonio Quartulli int ret;
7661d36a36fSAntonio Quartulli
7671d36a36fSAntonio Quartulli if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER))
7681d36a36fSAntonio Quartulli return -EINVAL;
7691d36a36fSAntonio Quartulli
7701d36a36fSAntonio Quartulli ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER],
7711d36a36fSAntonio Quartulli ovpn_peer_nl_policy, info->extack);
7721d36a36fSAntonio Quartulli if (ret)
7731d36a36fSAntonio Quartulli return ret;
7741d36a36fSAntonio Quartulli
7751d36a36fSAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs,
7761d36a36fSAntonio Quartulli OVPN_A_PEER_ID))
7771d36a36fSAntonio Quartulli return -EINVAL;
7781d36a36fSAntonio Quartulli
7791d36a36fSAntonio Quartulli peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]);
7801d36a36fSAntonio Quartulli peer = ovpn_peer_get_by_id(ovpn, peer_id);
7811d36a36fSAntonio Quartulli if (!peer) {
7821d36a36fSAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
7831d36a36fSAntonio Quartulli "cannot find peer with id %u", peer_id);
7841d36a36fSAntonio Quartulli return -ENOENT;
7851d36a36fSAntonio Quartulli }
7861d36a36fSAntonio Quartulli
7871d36a36fSAntonio Quartulli netdev_dbg(ovpn->dev, "del peer %u\n", peer->id);
7881d36a36fSAntonio Quartulli ret = ovpn_peer_del(peer, OVPN_DEL_PEER_REASON_USERSPACE);
7891d36a36fSAntonio Quartulli ovpn_peer_put(peer);
7901d36a36fSAntonio Quartulli
7911d36a36fSAntonio Quartulli return ret;
792b7a63391SAntonio Quartulli }
793b7a63391SAntonio Quartulli
ovpn_nl_get_key_dir(struct genl_info * info,struct nlattr * key,enum ovpn_cipher_alg cipher,struct ovpn_key_direction * dir)794203e2bf5SAntonio Quartulli static int ovpn_nl_get_key_dir(struct genl_info *info, struct nlattr *key,
795203e2bf5SAntonio Quartulli enum ovpn_cipher_alg cipher,
796203e2bf5SAntonio Quartulli struct ovpn_key_direction *dir)
797203e2bf5SAntonio Quartulli {
798203e2bf5SAntonio Quartulli struct nlattr *attrs[OVPN_A_KEYDIR_MAX + 1];
799203e2bf5SAntonio Quartulli int ret;
800203e2bf5SAntonio Quartulli
801203e2bf5SAntonio Quartulli ret = nla_parse_nested(attrs, OVPN_A_KEYDIR_MAX, key,
802203e2bf5SAntonio Quartulli ovpn_keydir_nl_policy, info->extack);
803203e2bf5SAntonio Quartulli if (ret)
804203e2bf5SAntonio Quartulli return ret;
805203e2bf5SAntonio Quartulli
806203e2bf5SAntonio Quartulli switch (cipher) {
807203e2bf5SAntonio Quartulli case OVPN_CIPHER_ALG_AES_GCM:
808203e2bf5SAntonio Quartulli case OVPN_CIPHER_ALG_CHACHA20_POLY1305:
809203e2bf5SAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, key, attrs,
810203e2bf5SAntonio Quartulli OVPN_A_KEYDIR_CIPHER_KEY) ||
811203e2bf5SAntonio Quartulli NL_REQ_ATTR_CHECK(info->extack, key, attrs,
812203e2bf5SAntonio Quartulli OVPN_A_KEYDIR_NONCE_TAIL))
813203e2bf5SAntonio Quartulli return -EINVAL;
814203e2bf5SAntonio Quartulli
815203e2bf5SAntonio Quartulli dir->cipher_key = nla_data(attrs[OVPN_A_KEYDIR_CIPHER_KEY]);
816203e2bf5SAntonio Quartulli dir->cipher_key_size = nla_len(attrs[OVPN_A_KEYDIR_CIPHER_KEY]);
817203e2bf5SAntonio Quartulli
818203e2bf5SAntonio Quartulli /* These algorithms require a 96bit nonce,
819203e2bf5SAntonio Quartulli * Construct it by combining 4-bytes packet id and
820203e2bf5SAntonio Quartulli * 8-bytes nonce-tail from userspace
821203e2bf5SAntonio Quartulli */
822203e2bf5SAntonio Quartulli dir->nonce_tail = nla_data(attrs[OVPN_A_KEYDIR_NONCE_TAIL]);
823203e2bf5SAntonio Quartulli dir->nonce_tail_size = nla_len(attrs[OVPN_A_KEYDIR_NONCE_TAIL]);
824203e2bf5SAntonio Quartulli break;
825203e2bf5SAntonio Quartulli default:
826203e2bf5SAntonio Quartulli NL_SET_ERR_MSG_MOD(info->extack, "unsupported cipher");
827203e2bf5SAntonio Quartulli return -EINVAL;
828203e2bf5SAntonio Quartulli }
829203e2bf5SAntonio Quartulli
830203e2bf5SAntonio Quartulli return 0;
831203e2bf5SAntonio Quartulli }
832203e2bf5SAntonio Quartulli
833203e2bf5SAntonio Quartulli /**
834203e2bf5SAntonio Quartulli * ovpn_nl_key_new_doit - configure a new key for the specified peer
835203e2bf5SAntonio Quartulli * @skb: incoming netlink message
836203e2bf5SAntonio Quartulli * @info: genetlink metadata
837203e2bf5SAntonio Quartulli *
838203e2bf5SAntonio Quartulli * This function allows the user to install a new key in the peer crypto
839203e2bf5SAntonio Quartulli * state.
840203e2bf5SAntonio Quartulli * Each peer has two 'slots', namely 'primary' and 'secondary', where
841203e2bf5SAntonio Quartulli * keys can be installed. The key in the 'primary' slot is used for
842203e2bf5SAntonio Quartulli * encryption, while both keys can be used for decryption by matching the
843203e2bf5SAntonio Quartulli * key ID carried in the incoming packet.
844203e2bf5SAntonio Quartulli *
845203e2bf5SAntonio Quartulli * The user is responsible for rotating keys when necessary. The user
846203e2bf5SAntonio Quartulli * may fetch peer traffic statistics via netlink in order to better
847203e2bf5SAntonio Quartulli * identify the right time to rotate keys.
848203e2bf5SAntonio Quartulli * The renegotiation follows these steps:
849203e2bf5SAntonio Quartulli * 1. a new key is computed by the user and is installed in the 'secondary'
850203e2bf5SAntonio Quartulli * slot
851203e2bf5SAntonio Quartulli * 2. at user discretion (usually after a predetermined time) 'primary' and
852203e2bf5SAntonio Quartulli * 'secondary' contents are swapped and the new key starts being used for
853203e2bf5SAntonio Quartulli * encryption, while the old key is kept around for decryption of late
854203e2bf5SAntonio Quartulli * packets.
855203e2bf5SAntonio Quartulli *
856203e2bf5SAntonio Quartulli * Return: 0 on success or a negative error code otherwise.
857203e2bf5SAntonio Quartulli */
ovpn_nl_key_new_doit(struct sk_buff * skb,struct genl_info * info)858b7a63391SAntonio Quartulli int ovpn_nl_key_new_doit(struct sk_buff *skb, struct genl_info *info)
859b7a63391SAntonio Quartulli {
860203e2bf5SAntonio Quartulli struct nlattr *attrs[OVPN_A_KEYCONF_MAX + 1];
861203e2bf5SAntonio Quartulli struct ovpn_priv *ovpn = info->user_ptr[0];
862203e2bf5SAntonio Quartulli struct ovpn_peer_key_reset pkr;
863203e2bf5SAntonio Quartulli struct ovpn_peer *peer;
864203e2bf5SAntonio Quartulli u32 peer_id;
865203e2bf5SAntonio Quartulli int ret;
866203e2bf5SAntonio Quartulli
867203e2bf5SAntonio Quartulli if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF))
868203e2bf5SAntonio Quartulli return -EINVAL;
869203e2bf5SAntonio Quartulli
870203e2bf5SAntonio Quartulli ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX,
871203e2bf5SAntonio Quartulli info->attrs[OVPN_A_KEYCONF],
872203e2bf5SAntonio Quartulli ovpn_keyconf_nl_policy, info->extack);
873203e2bf5SAntonio Quartulli if (ret)
874203e2bf5SAntonio Quartulli return ret;
875203e2bf5SAntonio Quartulli
876203e2bf5SAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
877203e2bf5SAntonio Quartulli OVPN_A_KEYCONF_PEER_ID))
878203e2bf5SAntonio Quartulli return -EINVAL;
879203e2bf5SAntonio Quartulli
880203e2bf5SAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
881203e2bf5SAntonio Quartulli OVPN_A_KEYCONF_SLOT) ||
882203e2bf5SAntonio Quartulli NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
883203e2bf5SAntonio Quartulli OVPN_A_KEYCONF_KEY_ID) ||
884203e2bf5SAntonio Quartulli NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
885203e2bf5SAntonio Quartulli OVPN_A_KEYCONF_CIPHER_ALG) ||
886203e2bf5SAntonio Quartulli NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
887203e2bf5SAntonio Quartulli OVPN_A_KEYCONF_ENCRYPT_DIR) ||
888203e2bf5SAntonio Quartulli NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
889203e2bf5SAntonio Quartulli OVPN_A_KEYCONF_DECRYPT_DIR))
890203e2bf5SAntonio Quartulli return -EINVAL;
891203e2bf5SAntonio Quartulli
892203e2bf5SAntonio Quartulli pkr.slot = nla_get_u32(attrs[OVPN_A_KEYCONF_SLOT]);
893203e2bf5SAntonio Quartulli pkr.key.key_id = nla_get_u32(attrs[OVPN_A_KEYCONF_KEY_ID]);
894203e2bf5SAntonio Quartulli pkr.key.cipher_alg = nla_get_u32(attrs[OVPN_A_KEYCONF_CIPHER_ALG]);
895203e2bf5SAntonio Quartulli
896203e2bf5SAntonio Quartulli ret = ovpn_nl_get_key_dir(info, attrs[OVPN_A_KEYCONF_ENCRYPT_DIR],
897203e2bf5SAntonio Quartulli pkr.key.cipher_alg, &pkr.key.encrypt);
898203e2bf5SAntonio Quartulli if (ret < 0)
899203e2bf5SAntonio Quartulli return ret;
900203e2bf5SAntonio Quartulli
901203e2bf5SAntonio Quartulli ret = ovpn_nl_get_key_dir(info, attrs[OVPN_A_KEYCONF_DECRYPT_DIR],
902203e2bf5SAntonio Quartulli pkr.key.cipher_alg, &pkr.key.decrypt);
903203e2bf5SAntonio Quartulli if (ret < 0)
904203e2bf5SAntonio Quartulli return ret;
905203e2bf5SAntonio Quartulli
906203e2bf5SAntonio Quartulli peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]);
907203e2bf5SAntonio Quartulli peer = ovpn_peer_get_by_id(ovpn, peer_id);
908203e2bf5SAntonio Quartulli if (!peer) {
909203e2bf5SAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
910203e2bf5SAntonio Quartulli "no peer with id %u to set key for",
911203e2bf5SAntonio Quartulli peer_id);
912203e2bf5SAntonio Quartulli return -ENOENT;
913203e2bf5SAntonio Quartulli }
914203e2bf5SAntonio Quartulli
915203e2bf5SAntonio Quartulli ret = ovpn_crypto_state_reset(&peer->crypto, &pkr);
916203e2bf5SAntonio Quartulli if (ret < 0) {
917203e2bf5SAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
918203e2bf5SAntonio Quartulli "cannot install new key for peer %u",
919203e2bf5SAntonio Quartulli peer_id);
920203e2bf5SAntonio Quartulli goto out;
921203e2bf5SAntonio Quartulli }
922203e2bf5SAntonio Quartulli
923203e2bf5SAntonio Quartulli netdev_dbg(ovpn->dev, "new key installed (id=%u) for peer %u\n",
924203e2bf5SAntonio Quartulli pkr.key.key_id, peer_id);
925203e2bf5SAntonio Quartulli out:
926203e2bf5SAntonio Quartulli ovpn_peer_put(peer);
927203e2bf5SAntonio Quartulli return ret;
928203e2bf5SAntonio Quartulli }
929203e2bf5SAntonio Quartulli
ovpn_nl_send_key(struct sk_buff * skb,const struct genl_info * info,u32 peer_id,enum ovpn_key_slot slot,const struct ovpn_key_config * keyconf)930203e2bf5SAntonio Quartulli static int ovpn_nl_send_key(struct sk_buff *skb, const struct genl_info *info,
931203e2bf5SAntonio Quartulli u32 peer_id, enum ovpn_key_slot slot,
932203e2bf5SAntonio Quartulli const struct ovpn_key_config *keyconf)
933203e2bf5SAntonio Quartulli {
934203e2bf5SAntonio Quartulli struct nlattr *attr;
935203e2bf5SAntonio Quartulli void *hdr;
936203e2bf5SAntonio Quartulli
937203e2bf5SAntonio Quartulli hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, &ovpn_nl_family,
938203e2bf5SAntonio Quartulli 0, OVPN_CMD_KEY_GET);
939203e2bf5SAntonio Quartulli if (!hdr)
940203e2bf5SAntonio Quartulli return -ENOBUFS;
941203e2bf5SAntonio Quartulli
942203e2bf5SAntonio Quartulli attr = nla_nest_start(skb, OVPN_A_KEYCONF);
943203e2bf5SAntonio Quartulli if (!attr)
944203e2bf5SAntonio Quartulli goto err;
945203e2bf5SAntonio Quartulli
946203e2bf5SAntonio Quartulli if (nla_put_u32(skb, OVPN_A_KEYCONF_PEER_ID, peer_id))
947203e2bf5SAntonio Quartulli goto err;
948203e2bf5SAntonio Quartulli
949203e2bf5SAntonio Quartulli if (nla_put_u32(skb, OVPN_A_KEYCONF_SLOT, slot) ||
950203e2bf5SAntonio Quartulli nla_put_u32(skb, OVPN_A_KEYCONF_KEY_ID, keyconf->key_id) ||
951203e2bf5SAntonio Quartulli nla_put_u32(skb, OVPN_A_KEYCONF_CIPHER_ALG, keyconf->cipher_alg))
952203e2bf5SAntonio Quartulli goto err;
953203e2bf5SAntonio Quartulli
954203e2bf5SAntonio Quartulli nla_nest_end(skb, attr);
955203e2bf5SAntonio Quartulli genlmsg_end(skb, hdr);
956203e2bf5SAntonio Quartulli
957203e2bf5SAntonio Quartulli return 0;
958203e2bf5SAntonio Quartulli err:
959203e2bf5SAntonio Quartulli genlmsg_cancel(skb, hdr);
960203e2bf5SAntonio Quartulli return -EMSGSIZE;
961b7a63391SAntonio Quartulli }
962b7a63391SAntonio Quartulli
ovpn_nl_key_get_doit(struct sk_buff * skb,struct genl_info * info)963b7a63391SAntonio Quartulli int ovpn_nl_key_get_doit(struct sk_buff *skb, struct genl_info *info)
964b7a63391SAntonio Quartulli {
965203e2bf5SAntonio Quartulli struct nlattr *attrs[OVPN_A_KEYCONF_MAX + 1];
966203e2bf5SAntonio Quartulli struct ovpn_priv *ovpn = info->user_ptr[0];
967203e2bf5SAntonio Quartulli struct ovpn_key_config keyconf = { 0 };
968203e2bf5SAntonio Quartulli enum ovpn_key_slot slot;
969203e2bf5SAntonio Quartulli struct ovpn_peer *peer;
970203e2bf5SAntonio Quartulli struct sk_buff *msg;
971203e2bf5SAntonio Quartulli u32 peer_id;
972203e2bf5SAntonio Quartulli int ret;
973203e2bf5SAntonio Quartulli
974203e2bf5SAntonio Quartulli if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF))
975203e2bf5SAntonio Quartulli return -EINVAL;
976203e2bf5SAntonio Quartulli
977203e2bf5SAntonio Quartulli ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX,
978203e2bf5SAntonio Quartulli info->attrs[OVPN_A_KEYCONF],
979203e2bf5SAntonio Quartulli ovpn_keyconf_nl_policy, info->extack);
980203e2bf5SAntonio Quartulli if (ret)
981203e2bf5SAntonio Quartulli return ret;
982203e2bf5SAntonio Quartulli
983203e2bf5SAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
984203e2bf5SAntonio Quartulli OVPN_A_KEYCONF_PEER_ID))
985203e2bf5SAntonio Quartulli return -EINVAL;
986203e2bf5SAntonio Quartulli
987203e2bf5SAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
988203e2bf5SAntonio Quartulli OVPN_A_KEYCONF_SLOT))
989203e2bf5SAntonio Quartulli return -EINVAL;
990203e2bf5SAntonio Quartulli
991203e2bf5SAntonio Quartulli peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]);
992203e2bf5SAntonio Quartulli peer = ovpn_peer_get_by_id(ovpn, peer_id);
993203e2bf5SAntonio Quartulli if (!peer) {
994203e2bf5SAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
995203e2bf5SAntonio Quartulli "cannot find peer with id %u", peer_id);
996203e2bf5SAntonio Quartulli return -ENOENT;
997203e2bf5SAntonio Quartulli }
998203e2bf5SAntonio Quartulli
999203e2bf5SAntonio Quartulli slot = nla_get_u32(attrs[OVPN_A_KEYCONF_SLOT]);
1000203e2bf5SAntonio Quartulli
1001203e2bf5SAntonio Quartulli ret = ovpn_crypto_config_get(&peer->crypto, slot, &keyconf);
1002203e2bf5SAntonio Quartulli if (ret < 0) {
1003203e2bf5SAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
1004203e2bf5SAntonio Quartulli "cannot extract key from slot %u for peer %u",
1005203e2bf5SAntonio Quartulli slot, peer_id);
1006203e2bf5SAntonio Quartulli goto err;
1007203e2bf5SAntonio Quartulli }
1008203e2bf5SAntonio Quartulli
1009203e2bf5SAntonio Quartulli msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1010203e2bf5SAntonio Quartulli if (!msg) {
1011203e2bf5SAntonio Quartulli ret = -ENOMEM;
1012203e2bf5SAntonio Quartulli goto err;
1013203e2bf5SAntonio Quartulli }
1014203e2bf5SAntonio Quartulli
1015203e2bf5SAntonio Quartulli ret = ovpn_nl_send_key(msg, info, peer->id, slot, &keyconf);
1016203e2bf5SAntonio Quartulli if (ret < 0) {
1017203e2bf5SAntonio Quartulli nlmsg_free(msg);
1018203e2bf5SAntonio Quartulli goto err;
1019203e2bf5SAntonio Quartulli }
1020203e2bf5SAntonio Quartulli
1021203e2bf5SAntonio Quartulli ret = genlmsg_reply(msg, info);
1022203e2bf5SAntonio Quartulli err:
1023203e2bf5SAntonio Quartulli ovpn_peer_put(peer);
1024203e2bf5SAntonio Quartulli return ret;
1025b7a63391SAntonio Quartulli }
1026b7a63391SAntonio Quartulli
ovpn_nl_key_swap_doit(struct sk_buff * skb,struct genl_info * info)1027b7a63391SAntonio Quartulli int ovpn_nl_key_swap_doit(struct sk_buff *skb, struct genl_info *info)
1028b7a63391SAntonio Quartulli {
1029203e2bf5SAntonio Quartulli struct ovpn_priv *ovpn = info->user_ptr[0];
1030203e2bf5SAntonio Quartulli struct nlattr *attrs[OVPN_A_PEER_MAX + 1];
1031203e2bf5SAntonio Quartulli struct ovpn_peer *peer;
1032203e2bf5SAntonio Quartulli u32 peer_id;
1033203e2bf5SAntonio Quartulli int ret;
1034203e2bf5SAntonio Quartulli
1035203e2bf5SAntonio Quartulli if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF))
1036203e2bf5SAntonio Quartulli return -EINVAL;
1037203e2bf5SAntonio Quartulli
1038203e2bf5SAntonio Quartulli ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX,
1039203e2bf5SAntonio Quartulli info->attrs[OVPN_A_KEYCONF],
1040203e2bf5SAntonio Quartulli ovpn_keyconf_nl_policy, info->extack);
1041203e2bf5SAntonio Quartulli if (ret)
1042203e2bf5SAntonio Quartulli return ret;
1043203e2bf5SAntonio Quartulli
1044203e2bf5SAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
1045203e2bf5SAntonio Quartulli OVPN_A_KEYCONF_PEER_ID))
1046203e2bf5SAntonio Quartulli return -EINVAL;
1047203e2bf5SAntonio Quartulli
1048203e2bf5SAntonio Quartulli peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]);
1049203e2bf5SAntonio Quartulli peer = ovpn_peer_get_by_id(ovpn, peer_id);
1050203e2bf5SAntonio Quartulli if (!peer) {
1051203e2bf5SAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
1052203e2bf5SAntonio Quartulli "no peer with id %u to swap keys for",
1053203e2bf5SAntonio Quartulli peer_id);
1054203e2bf5SAntonio Quartulli return -ENOENT;
1055203e2bf5SAntonio Quartulli }
1056203e2bf5SAntonio Quartulli
1057203e2bf5SAntonio Quartulli ovpn_crypto_key_slots_swap(&peer->crypto);
1058203e2bf5SAntonio Quartulli ovpn_peer_put(peer);
1059203e2bf5SAntonio Quartulli
1060203e2bf5SAntonio Quartulli return 0;
1061b7a63391SAntonio Quartulli }
1062b7a63391SAntonio Quartulli
ovpn_nl_key_del_doit(struct sk_buff * skb,struct genl_info * info)1063b7a63391SAntonio Quartulli int ovpn_nl_key_del_doit(struct sk_buff *skb, struct genl_info *info)
1064b7a63391SAntonio Quartulli {
1065203e2bf5SAntonio Quartulli struct nlattr *attrs[OVPN_A_KEYCONF_MAX + 1];
1066203e2bf5SAntonio Quartulli struct ovpn_priv *ovpn = info->user_ptr[0];
1067203e2bf5SAntonio Quartulli enum ovpn_key_slot slot;
1068203e2bf5SAntonio Quartulli struct ovpn_peer *peer;
1069203e2bf5SAntonio Quartulli u32 peer_id;
1070203e2bf5SAntonio Quartulli int ret;
1071203e2bf5SAntonio Quartulli
1072203e2bf5SAntonio Quartulli if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF))
1073203e2bf5SAntonio Quartulli return -EINVAL;
1074203e2bf5SAntonio Quartulli
1075203e2bf5SAntonio Quartulli ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX,
1076203e2bf5SAntonio Quartulli info->attrs[OVPN_A_KEYCONF],
1077203e2bf5SAntonio Quartulli ovpn_keyconf_nl_policy, info->extack);
1078203e2bf5SAntonio Quartulli if (ret)
1079203e2bf5SAntonio Quartulli return ret;
1080203e2bf5SAntonio Quartulli
1081203e2bf5SAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
1082203e2bf5SAntonio Quartulli OVPN_A_KEYCONF_PEER_ID))
1083203e2bf5SAntonio Quartulli return -EINVAL;
1084203e2bf5SAntonio Quartulli
1085203e2bf5SAntonio Quartulli if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
1086203e2bf5SAntonio Quartulli OVPN_A_KEYCONF_SLOT))
1087203e2bf5SAntonio Quartulli return -EINVAL;
1088203e2bf5SAntonio Quartulli
1089203e2bf5SAntonio Quartulli peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]);
1090203e2bf5SAntonio Quartulli slot = nla_get_u32(attrs[OVPN_A_KEYCONF_SLOT]);
1091203e2bf5SAntonio Quartulli
1092203e2bf5SAntonio Quartulli peer = ovpn_peer_get_by_id(ovpn, peer_id);
1093203e2bf5SAntonio Quartulli if (!peer) {
1094203e2bf5SAntonio Quartulli NL_SET_ERR_MSG_FMT_MOD(info->extack,
1095203e2bf5SAntonio Quartulli "no peer with id %u to delete key for",
1096203e2bf5SAntonio Quartulli peer_id);
1097203e2bf5SAntonio Quartulli return -ENOENT;
1098203e2bf5SAntonio Quartulli }
1099203e2bf5SAntonio Quartulli
1100203e2bf5SAntonio Quartulli ovpn_crypto_key_slot_delete(&peer->crypto, slot);
1101203e2bf5SAntonio Quartulli ovpn_peer_put(peer);
1102203e2bf5SAntonio Quartulli
1103203e2bf5SAntonio Quartulli return 0;
1104b7a63391SAntonio Quartulli }
1105b7a63391SAntonio Quartulli
1106b7a63391SAntonio Quartulli /**
1107a215d253SAntonio Quartulli * ovpn_nl_peer_del_notify - notify userspace about peer being deleted
1108a215d253SAntonio Quartulli * @peer: the peer being deleted
1109a215d253SAntonio Quartulli *
1110a215d253SAntonio Quartulli * Return: 0 on success or a negative error code otherwise
1111a215d253SAntonio Quartulli */
ovpn_nl_peer_del_notify(struct ovpn_peer * peer)1112a215d253SAntonio Quartulli int ovpn_nl_peer_del_notify(struct ovpn_peer *peer)
1113a215d253SAntonio Quartulli {
1114a215d253SAntonio Quartulli struct ovpn_socket *sock;
1115a215d253SAntonio Quartulli struct sk_buff *msg;
1116a215d253SAntonio Quartulli struct nlattr *attr;
1117a215d253SAntonio Quartulli int ret = -EMSGSIZE;
1118a215d253SAntonio Quartulli void *hdr;
1119a215d253SAntonio Quartulli
1120a215d253SAntonio Quartulli netdev_info(peer->ovpn->dev, "deleting peer with id %u, reason %d\n",
1121a215d253SAntonio Quartulli peer->id, peer->delete_reason);
1122a215d253SAntonio Quartulli
1123a215d253SAntonio Quartulli msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
1124a215d253SAntonio Quartulli if (!msg)
1125a215d253SAntonio Quartulli return -ENOMEM;
1126a215d253SAntonio Quartulli
1127a215d253SAntonio Quartulli hdr = genlmsg_put(msg, 0, 0, &ovpn_nl_family, 0, OVPN_CMD_PEER_DEL_NTF);
1128a215d253SAntonio Quartulli if (!hdr) {
1129a215d253SAntonio Quartulli ret = -ENOBUFS;
1130a215d253SAntonio Quartulli goto err_free_msg;
1131a215d253SAntonio Quartulli }
1132a215d253SAntonio Quartulli
1133a215d253SAntonio Quartulli if (nla_put_u32(msg, OVPN_A_IFINDEX, peer->ovpn->dev->ifindex))
1134a215d253SAntonio Quartulli goto err_cancel_msg;
1135a215d253SAntonio Quartulli
1136a215d253SAntonio Quartulli attr = nla_nest_start(msg, OVPN_A_PEER);
1137a215d253SAntonio Quartulli if (!attr)
1138a215d253SAntonio Quartulli goto err_cancel_msg;
1139a215d253SAntonio Quartulli
1140a215d253SAntonio Quartulli if (nla_put_u32(msg, OVPN_A_PEER_DEL_REASON, peer->delete_reason))
1141a215d253SAntonio Quartulli goto err_cancel_msg;
1142a215d253SAntonio Quartulli
1143a215d253SAntonio Quartulli if (nla_put_u32(msg, OVPN_A_PEER_ID, peer->id))
1144a215d253SAntonio Quartulli goto err_cancel_msg;
1145a215d253SAntonio Quartulli
1146a215d253SAntonio Quartulli nla_nest_end(msg, attr);
1147a215d253SAntonio Quartulli
1148a215d253SAntonio Quartulli genlmsg_end(msg, hdr);
1149a215d253SAntonio Quartulli
1150a215d253SAntonio Quartulli rcu_read_lock();
1151a215d253SAntonio Quartulli sock = rcu_dereference(peer->sock);
1152a215d253SAntonio Quartulli if (!sock) {
1153a215d253SAntonio Quartulli ret = -EINVAL;
1154a215d253SAntonio Quartulli goto err_unlock;
1155a215d253SAntonio Quartulli }
1156*ba499a07SAntonio Quartulli genlmsg_multicast_netns(&ovpn_nl_family, sock_net(sock->sk), msg, 0,
1157*ba499a07SAntonio Quartulli OVPN_NLGRP_PEERS, GFP_ATOMIC);
1158a215d253SAntonio Quartulli rcu_read_unlock();
1159a215d253SAntonio Quartulli
1160a215d253SAntonio Quartulli return 0;
1161a215d253SAntonio Quartulli
1162a215d253SAntonio Quartulli err_unlock:
1163a215d253SAntonio Quartulli rcu_read_unlock();
1164a215d253SAntonio Quartulli err_cancel_msg:
1165a215d253SAntonio Quartulli genlmsg_cancel(msg, hdr);
1166a215d253SAntonio Quartulli err_free_msg:
1167a215d253SAntonio Quartulli nlmsg_free(msg);
1168a215d253SAntonio Quartulli return ret;
1169a215d253SAntonio Quartulli }
1170a215d253SAntonio Quartulli
1171a215d253SAntonio Quartulli /**
117289d3c0e4SAntonio Quartulli * ovpn_nl_key_swap_notify - notify userspace peer's key must be renewed
117389d3c0e4SAntonio Quartulli * @peer: the peer whose key needs to be renewed
117489d3c0e4SAntonio Quartulli * @key_id: the ID of the key that needs to be renewed
117589d3c0e4SAntonio Quartulli *
117689d3c0e4SAntonio Quartulli * Return: 0 on success or a negative error code otherwise
117789d3c0e4SAntonio Quartulli */
ovpn_nl_key_swap_notify(struct ovpn_peer * peer,u8 key_id)117889d3c0e4SAntonio Quartulli int ovpn_nl_key_swap_notify(struct ovpn_peer *peer, u8 key_id)
117989d3c0e4SAntonio Quartulli {
118089d3c0e4SAntonio Quartulli struct ovpn_socket *sock;
118189d3c0e4SAntonio Quartulli struct nlattr *k_attr;
118289d3c0e4SAntonio Quartulli struct sk_buff *msg;
118389d3c0e4SAntonio Quartulli int ret = -EMSGSIZE;
118489d3c0e4SAntonio Quartulli void *hdr;
118589d3c0e4SAntonio Quartulli
118689d3c0e4SAntonio Quartulli netdev_info(peer->ovpn->dev, "peer with id %u must rekey - primary key unusable.\n",
118789d3c0e4SAntonio Quartulli peer->id);
118889d3c0e4SAntonio Quartulli
118989d3c0e4SAntonio Quartulli msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
119089d3c0e4SAntonio Quartulli if (!msg)
119189d3c0e4SAntonio Quartulli return -ENOMEM;
119289d3c0e4SAntonio Quartulli
119389d3c0e4SAntonio Quartulli hdr = genlmsg_put(msg, 0, 0, &ovpn_nl_family, 0, OVPN_CMD_KEY_SWAP_NTF);
119489d3c0e4SAntonio Quartulli if (!hdr) {
119589d3c0e4SAntonio Quartulli ret = -ENOBUFS;
119689d3c0e4SAntonio Quartulli goto err_free_msg;
119789d3c0e4SAntonio Quartulli }
119889d3c0e4SAntonio Quartulli
119989d3c0e4SAntonio Quartulli if (nla_put_u32(msg, OVPN_A_IFINDEX, peer->ovpn->dev->ifindex))
120089d3c0e4SAntonio Quartulli goto err_cancel_msg;
120189d3c0e4SAntonio Quartulli
120289d3c0e4SAntonio Quartulli k_attr = nla_nest_start(msg, OVPN_A_KEYCONF);
120389d3c0e4SAntonio Quartulli if (!k_attr)
120489d3c0e4SAntonio Quartulli goto err_cancel_msg;
120589d3c0e4SAntonio Quartulli
120689d3c0e4SAntonio Quartulli if (nla_put_u32(msg, OVPN_A_KEYCONF_PEER_ID, peer->id))
120789d3c0e4SAntonio Quartulli goto err_cancel_msg;
120889d3c0e4SAntonio Quartulli
120989d3c0e4SAntonio Quartulli if (nla_put_u16(msg, OVPN_A_KEYCONF_KEY_ID, key_id))
121089d3c0e4SAntonio Quartulli goto err_cancel_msg;
121189d3c0e4SAntonio Quartulli
121289d3c0e4SAntonio Quartulli nla_nest_end(msg, k_attr);
121389d3c0e4SAntonio Quartulli genlmsg_end(msg, hdr);
121489d3c0e4SAntonio Quartulli
121589d3c0e4SAntonio Quartulli rcu_read_lock();
121689d3c0e4SAntonio Quartulli sock = rcu_dereference(peer->sock);
121789d3c0e4SAntonio Quartulli if (!sock) {
121889d3c0e4SAntonio Quartulli ret = -EINVAL;
121989d3c0e4SAntonio Quartulli goto err_unlock;
122089d3c0e4SAntonio Quartulli }
1221*ba499a07SAntonio Quartulli genlmsg_multicast_netns(&ovpn_nl_family, sock_net(sock->sk), msg, 0,
1222*ba499a07SAntonio Quartulli OVPN_NLGRP_PEERS, GFP_ATOMIC);
122389d3c0e4SAntonio Quartulli rcu_read_unlock();
122489d3c0e4SAntonio Quartulli
122589d3c0e4SAntonio Quartulli return 0;
122689d3c0e4SAntonio Quartulli err_unlock:
122789d3c0e4SAntonio Quartulli rcu_read_unlock();
122889d3c0e4SAntonio Quartulli err_cancel_msg:
122989d3c0e4SAntonio Quartulli genlmsg_cancel(msg, hdr);
123089d3c0e4SAntonio Quartulli err_free_msg:
123189d3c0e4SAntonio Quartulli nlmsg_free(msg);
123289d3c0e4SAntonio Quartulli return ret;
123389d3c0e4SAntonio Quartulli }
123489d3c0e4SAntonio Quartulli
123589d3c0e4SAntonio Quartulli /**
1236b7a63391SAntonio Quartulli * ovpn_nl_register - perform any needed registration in the NL subsustem
1237b7a63391SAntonio Quartulli *
1238b7a63391SAntonio Quartulli * Return: 0 on success, a negative error code otherwise
1239b7a63391SAntonio Quartulli */
ovpn_nl_register(void)1240b7a63391SAntonio Quartulli int __init ovpn_nl_register(void)
1241b7a63391SAntonio Quartulli {
1242b7a63391SAntonio Quartulli int ret = genl_register_family(&ovpn_nl_family);
1243b7a63391SAntonio Quartulli
1244b7a63391SAntonio Quartulli if (ret) {
1245b7a63391SAntonio Quartulli pr_err("ovpn: genl_register_family failed: %d\n", ret);
1246b7a63391SAntonio Quartulli return ret;
1247b7a63391SAntonio Quartulli }
1248b7a63391SAntonio Quartulli
1249b7a63391SAntonio Quartulli return 0;
1250b7a63391SAntonio Quartulli }
1251b7a63391SAntonio Quartulli
1252b7a63391SAntonio Quartulli /**
1253b7a63391SAntonio Quartulli * ovpn_nl_unregister - undo any module wide netlink registration
1254b7a63391SAntonio Quartulli */
ovpn_nl_unregister(void)1255b7a63391SAntonio Quartulli void ovpn_nl_unregister(void)
1256b7a63391SAntonio Quartulli {
1257b7a63391SAntonio Quartulli genl_unregister_family(&ovpn_nl_family);
1258b7a63391SAntonio Quartulli }
1259