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"); return ERR_PTR(-ENODEV);
}
if (!ovpn_dev_is_valid(dev)) {
rcu_read_unlock();
NL_SET_ERR_MSG_MOD(info->extack, "specified interface is not ovpn");
NL_SET_BAD_ATTR(info->extack, info->attrs[OVPN_A_IFINDEX]); return ERR_PTR(-EINVAL);
}
switch (ss->ss_family) { case AF_INET6: /* If this is a regular IPv6 just break and move on, *otherwiseswitchtoAF_INETandextracttheIPv4accordingly
*/ if (!ipv6_addr_v4mapped(in6)) {
sin6 = (struct sockaddr_in6 *)ss;
sin6->sin6_port = port;
memcpy(&sin6->sin6_addr, in6, sizeof(*in6)); break;
}
/* v4-mapped-v6 address */
ss->ss_family = AF_INET;
in = &in6->s6_addr32[3];
fallthrough; case AF_INET:
sin = (struct sockaddr_in *)ss;
sin->sin_port = port;
sin->sin_addr.s_addr = *in; break;
}
if (!attrs[OVPN_A_PEER_LOCAL_IPV4] && !attrs[OVPN_A_PEER_LOCAL_IPV6]) return NULL;
if (attrs[OVPN_A_PEER_LOCAL_IPV4]) return nla_data(attrs[OVPN_A_PEER_LOCAL_IPV4]);
addr6 = nla_data(attrs[OVPN_A_PEER_LOCAL_IPV6]); /* this is an IPv4-mapped IPv6 address, therefore extract the actual *v4addressfromthelast4bytes
*/ if (ipv6_addr_v4mapped((struct in6_addr *)addr6)) return addr6 + 12;
if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs,
OVPN_A_PEER_ID)) return -EINVAL;
if (attrs[OVPN_A_PEER_REMOTE_IPV4] && attrs[OVPN_A_PEER_REMOTE_IPV6]) {
NL_SET_ERR_MSG_MOD(info->extack, "cannot specify both remote IPv4 or IPv6 address"); return -EINVAL;
}
if (!attrs[OVPN_A_PEER_REMOTE_IPV4] &&
!attrs[OVPN_A_PEER_REMOTE_IPV6] && attrs[OVPN_A_PEER_REMOTE_PORT]) {
NL_SET_ERR_MSG_MOD(info->extack, "cannot specify remote port without IP address"); return -EINVAL;
}
if ((attrs[OVPN_A_PEER_REMOTE_IPV4] ||
attrs[OVPN_A_PEER_REMOTE_IPV6]) &&
!attrs[OVPN_A_PEER_REMOTE_PORT]) {
NL_SET_ERR_MSG_MOD(info->extack, "cannot specify remote IP address without port"); return -EINVAL;
}
if (!attrs[OVPN_A_PEER_REMOTE_IPV4] &&
attrs[OVPN_A_PEER_LOCAL_IPV4]) {
NL_SET_ERR_MSG_MOD(info->extack, "cannot specify local IPv4 address without remote"); return -EINVAL;
}
if (!attrs[OVPN_A_PEER_REMOTE_IPV6] &&
attrs[OVPN_A_PEER_LOCAL_IPV6]) {
NL_SET_ERR_MSG_MOD(info->extack, "cannot specify local IPV6 address without remote"); return -EINVAL;
}
/* check that local and remote address families are the same even *afterparsingv4mappedIPv6addresses. *(ifaddressesarenotprovided,familywillbeAF_UNSPECand *thecheckisskipped)
*/
local_fam = ovpn_nl_family_get(attrs[OVPN_A_PEER_LOCAL_IPV4],
attrs[OVPN_A_PEER_LOCAL_IPV6]);
remote_fam = ovpn_nl_family_get(attrs[OVPN_A_PEER_REMOTE_IPV4],
attrs[OVPN_A_PEER_REMOTE_IPV6]); if (local_fam != AF_UNSPEC && remote_fam != AF_UNSPEC &&
local_fam != remote_fam) {
NL_SET_ERR_MSG_MOD(info->extack, "mismatching local and remote address families"); return -EINVAL;
}
if (remote_fam != AF_INET6 && attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) {
NL_SET_ERR_MSG_MOD(info->extack, "cannot specify scope id without remote IPv6 address"); return -EINVAL;
}
/* VPN IPs are needed only in MP mode for selecting the right peer */ if (ovpn->mode == OVPN_MODE_P2P && (attrs[OVPN_A_PEER_VPN_IPV4] ||
attrs[OVPN_A_PEER_VPN_IPV6])) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "unexpected VPN IP in P2P mode"); return -EINVAL;
}
if ((attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL] &&
!attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT]) ||
(!attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL] &&
attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT])) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "keepalive interval and timeout are required together"); return -EINVAL;
}
if (ovpn_nl_attr_sockaddr_remote(attrs, &ss)) { /* we carry the local IP in a generic container. *ovpn_peer_reset_sockaddr()willproperlyinterpretit *basedonss.ss_family
*/
local_ip = ovpn_nl_attr_local_ip(attrs);
/* set peer sockaddr */
ret = ovpn_peer_reset_sockaddr(peer, &ss, local_ip); if (ret < 0) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "cannot set peer sockaddr: %d",
ret); goto err_unlock;
}
dst_cache_reset(&peer->dst_cache);
}
if (attrs[OVPN_A_PEER_VPN_IPV4]) {
rehash = true;
peer->vpn_addrs.ipv4.s_addr =
nla_get_in_addr(attrs[OVPN_A_PEER_VPN_IPV4]);
}
if (attrs[OVPN_A_PEER_VPN_IPV6]) {
rehash = true;
peer->vpn_addrs.ipv6 =
nla_get_in6_addr(attrs[OVPN_A_PEER_VPN_IPV6]);
}
/* when setting the keepalive, both parameters have to be configured */ if (attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL] &&
attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT]) {
interv = nla_get_u32(attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL]);
timeout = nla_get_u32(attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT]);
ovpn_peer_keepalive_set(peer, interv, timeout);
}
if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER)) return -EINVAL;
ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER],
ovpn_peer_new_input_nl_policy, info->extack); if (ret) return ret;
ret = ovpn_nl_peer_precheck(ovpn, info, attrs); if (ret < 0) return ret;
if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs,
OVPN_A_PEER_SOCKET)) return -EINVAL;
/* in MP mode VPN IPs are required for selecting the right peer */ if (ovpn->mode == OVPN_MODE_MP && !attrs[OVPN_A_PEER_VPN_IPV4] &&
!attrs[OVPN_A_PEER_VPN_IPV6]) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "VPN IP must be provided in MP mode"); return -EINVAL;
}
peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]);
peer = ovpn_peer_new(ovpn, peer_id); if (IS_ERR(peer)) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "cannot create new peer object for peer %u: %ld",
peer_id, PTR_ERR(peer)); return PTR_ERR(peer);
}
/* lookup the fd in the kernel table and extract the socket object */
sockfd = nla_get_u32(attrs[OVPN_A_PEER_SOCKET]); /* sockfd_lookup() increases sock's refcounter */
sock = sockfd_lookup(sockfd, &ret); if (!sock) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "cannot lookup peer socket (fd=%u): %d",
sockfd, ret);
ret = -ENOTSOCK; goto peer_release;
}
/* Only when using UDP as transport protocol the remote endpoint *canbeconfiguredsothatovpnknowswheretosendpacketsto.
*/ if (sock->sk->sk_protocol == IPPROTO_UDP &&
!attrs[OVPN_A_PEER_REMOTE_IPV4] &&
!attrs[OVPN_A_PEER_REMOTE_IPV6]) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "missing remote IP address for UDP socket");
sockfd_put(sock);
ret = -EINVAL; goto peer_release;
}
/* In case of TCP, the socket is connected to the peer and ovpn *willjustsendbytesoverit,withouttheneedtospecifya *destination.
*/ if (sock->sk->sk_protocol == IPPROTO_TCP &&
(attrs[OVPN_A_PEER_REMOTE_IPV4] ||
attrs[OVPN_A_PEER_REMOTE_IPV6])) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "unexpected remote IP address with TCP socket");
sockfd_put(sock);
ret = -EINVAL; goto peer_release;
}
ovpn_sock = ovpn_socket_new(sock, peer); /* at this point we unconditionally drop the reference to the socket: *-incaseoferror,thesockethastobedropped *-ifcaseofsuccess,thesocketisconfiguredandlet *userspaceownthereference,sothatthelattercan *triggerthefinalclose()
*/
sockfd_put(sock); if (IS_ERR(ovpn_sock)) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "cannot encapsulate socket: %ld",
PTR_ERR(ovpn_sock));
ret = -ENOTSOCK; goto peer_release;
}
rcu_assign_pointer(peer->sock, ovpn_sock);
ret = ovpn_nl_peer_modify(peer, info, attrs); if (ret < 0) goto sock_release;
ret = ovpn_peer_add(ovpn, peer); if (ret < 0) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "cannot add new peer (id=%u) to hashtable: %d",
peer->id, ret); goto sock_release;
}
return0;
sock_release:
ovpn_socket_release(peer);
peer_release: /* release right away because peer was not yet hashed, thus it is not *usedinanycontext
*/
ovpn_peer_release(peer);
if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER)) return -EINVAL;
ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER],
ovpn_peer_set_input_nl_policy, info->extack); if (ret) return ret;
ret = ovpn_nl_peer_precheck(ovpn, info, attrs); if (ret < 0) return ret;
if (attrs[OVPN_A_PEER_SOCKET]) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "socket cannot be modified"); return -EINVAL;
}
peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]);
peer = ovpn_peer_get_by_id(ovpn, peer_id); if (!peer) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "cannot find peer with id %u", peer_id); return -ENOENT;
}
/* when using a TCP socket the remote IP is not expected */
rcu_read_lock();
sock = rcu_dereference(peer->sock); if (sock && sock->sk->sk_protocol == IPPROTO_TCP &&
(attrs[OVPN_A_PEER_REMOTE_IPV4] ||
attrs[OVPN_A_PEER_REMOTE_IPV6])) {
rcu_read_unlock();
NL_SET_ERR_MSG_FMT_MOD(info->extack, "unexpected remote IP address with TCP socket");
ovpn_peer_put(peer); return -EINVAL;
}
rcu_read_unlock();
spin_lock_bh(&ovpn->lock);
ret = ovpn_nl_peer_modify(peer, info, attrs); if (ret < 0) {
spin_unlock_bh(&ovpn->lock);
ovpn_peer_put(peer); return ret;
}
/* ret == 1 means that VPN IPv4/6 has been modified and rehashing *isrequired
*/ if (ret > 0)
ovpn_peer_hash_vpn_ip(peer);
spin_unlock_bh(&ovpn->lock);
ovpn_peer_put(peer);
return0;
}
staticint ovpn_nl_send_peer(struct sk_buff *skb, conststruct genl_info *info, conststruct ovpn_peer *peer, u32 portid, u32 seq, int flags)
{ conststruct ovpn_bind *bind; struct ovpn_socket *sock; int ret = -EMSGSIZE; struct nlattr *attr;
__be16 local_port; void *hdr; int id;
if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER)) return -EINVAL;
ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER],
ovpn_peer_nl_policy, info->extack); if (ret) return ret;
if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs,
OVPN_A_PEER_ID)) return -EINVAL;
/* OVPN_CMD_PEER_GET expects only the PEER_ID, therefore *ensurethattheuserhasn'tspecifiedanyotherattribute. * *Unfortunatelythischeckcannotbeperformedvianetlink *spec/policyandmustbeopen-coded.
*/ for (i = 0; i < OVPN_A_PEER_MAX + 1; i++) { if (i == OVPN_A_PEER_ID) continue;
ret = ovpn_nl_get_key_dir(info, attrs[OVPN_A_KEYCONF_ENCRYPT_DIR],
pkr.key.cipher_alg, &pkr.key.encrypt); if (ret < 0) return ret;
ret = ovpn_nl_get_key_dir(info, attrs[OVPN_A_KEYCONF_DECRYPT_DIR],
pkr.key.cipher_alg, &pkr.key.decrypt); if (ret < 0) return ret;
peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]);
peer = ovpn_peer_get_by_id(ovpn, peer_id); if (!peer) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "no peer with id %u to set key for",
peer_id); return -ENOENT;
}
ret = ovpn_crypto_state_reset(&peer->crypto, &pkr); if (ret < 0) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "cannot install new key for peer %u",
peer_id); goto out;
}
netdev_dbg(ovpn->dev, "new key installed (id=%u) for peer %u\n",
pkr.key.key_id, peer_id);
out:
ovpn_peer_put(peer); return ret;
}
if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF)) return -EINVAL;
ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX,
info->attrs[OVPN_A_KEYCONF],
ovpn_keyconf_get_nl_policy, info->extack); if (ret) return ret;
if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
OVPN_A_KEYCONF_PEER_ID)) return -EINVAL;
if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
OVPN_A_KEYCONF_SLOT)) return -EINVAL;
/* OVPN_CMD_KEY_GET expects only the PEER_ID and the SLOT, therefore *ensurethattheuserhasn'tspecifiedanyotherattribute. * *Unfortunatelythischeckcannotbeperformedvianetlink *spec/policyandmustbeopen-coded.
*/ for (i = 0; i < OVPN_A_KEYCONF_MAX + 1; i++) { if (i == OVPN_A_KEYCONF_PEER_ID ||
i == OVPN_A_KEYCONF_SLOT) continue;
if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF)) return -EINVAL;
ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX,
info->attrs[OVPN_A_KEYCONF],
ovpn_keyconf_swap_input_nl_policy, info->extack); if (ret) return ret;
if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_KEYCONF], attrs,
OVPN_A_KEYCONF_PEER_ID)) return -EINVAL;
peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]);
peer = ovpn_peer_get_by_id(ovpn, peer_id); if (!peer) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "no peer with id %u to swap keys for",
peer_id); return -ENOENT;
}
peer = ovpn_peer_get_by_id(ovpn, peer_id); if (!peer) {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "no peer with id %u to delete key for",
peer_id); return -ENOENT;
}
/** *ovpn_nl_register-performanyneededregistrationintheNLsubsustem * *Return:0onsuccess,anegativeerrorcodeotherwise
*/ int __init ovpn_nl_register(void)
{ int ret = genl_register_family(&ovpn_nl_family);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.