Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ovpn: implement peer add/get/dump/delete via netlink

This change introduces the netlink command needed to add, delete and
retrieve/dump known peers. Userspace is expected to use these commands
to handle known peer lifecycles.

Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-18-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Antonio Quartulli and committed by
Paolo Abeni
1d36a36f f0281c1d

+738 -36
+681 -5
drivers/net/ovpn/netlink.c
··· 7 7 */ 8 8 9 9 #include <linux/netdevice.h> 10 + #include <linux/types.h> 10 11 #include <net/genetlink.h> 11 12 12 13 #include <uapi/linux/ovpn.h> ··· 16 15 #include "main.h" 17 16 #include "netlink.h" 18 17 #include "netlink-gen.h" 18 + #include "bind.h" 19 + #include "peer.h" 20 + #include "socket.h" 19 21 20 22 MODULE_ALIAS_GENL_FAMILY(OVPN_FAMILY_NAME); 21 23 ··· 93 89 netdev_put(ovpn->dev, tracker); 94 90 } 95 91 92 + static bool ovpn_nl_attr_sockaddr_remote(struct nlattr **attrs, 93 + struct sockaddr_storage *ss) 94 + { 95 + struct sockaddr_in6 *sin6; 96 + struct sockaddr_in *sin; 97 + struct in6_addr *in6; 98 + __be16 port = 0; 99 + __be32 *in; 100 + 101 + ss->ss_family = AF_UNSPEC; 102 + 103 + if (attrs[OVPN_A_PEER_REMOTE_PORT]) 104 + port = nla_get_be16(attrs[OVPN_A_PEER_REMOTE_PORT]); 105 + 106 + if (attrs[OVPN_A_PEER_REMOTE_IPV4]) { 107 + ss->ss_family = AF_INET; 108 + in = nla_data(attrs[OVPN_A_PEER_REMOTE_IPV4]); 109 + } else if (attrs[OVPN_A_PEER_REMOTE_IPV6]) { 110 + ss->ss_family = AF_INET6; 111 + in6 = nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]); 112 + } else { 113 + return false; 114 + } 115 + 116 + switch (ss->ss_family) { 117 + case AF_INET6: 118 + /* If this is a regular IPv6 just break and move on, 119 + * otherwise switch to AF_INET and extract the IPv4 accordingly 120 + */ 121 + if (!ipv6_addr_v4mapped(in6)) { 122 + sin6 = (struct sockaddr_in6 *)ss; 123 + sin6->sin6_port = port; 124 + memcpy(&sin6->sin6_addr, in6, sizeof(*in6)); 125 + break; 126 + } 127 + 128 + /* v4-mapped-v6 address */ 129 + ss->ss_family = AF_INET; 130 + in = &in6->s6_addr32[3]; 131 + fallthrough; 132 + case AF_INET: 133 + sin = (struct sockaddr_in *)ss; 134 + sin->sin_port = port; 135 + sin->sin_addr.s_addr = *in; 136 + break; 137 + } 138 + 139 + return true; 140 + } 141 + 142 + static u8 *ovpn_nl_attr_local_ip(struct nlattr **attrs) 143 + { 144 + u8 *addr6; 145 + 146 + if (!attrs[OVPN_A_PEER_LOCAL_IPV4] && !attrs[OVPN_A_PEER_LOCAL_IPV6]) 147 + return NULL; 148 + 149 + if (attrs[OVPN_A_PEER_LOCAL_IPV4]) 150 + return nla_data(attrs[OVPN_A_PEER_LOCAL_IPV4]); 151 + 152 + addr6 = nla_data(attrs[OVPN_A_PEER_LOCAL_IPV6]); 153 + /* this is an IPv4-mapped IPv6 address, therefore extract the actual 154 + * v4 address from the last 4 bytes 155 + */ 156 + if (ipv6_addr_v4mapped((struct in6_addr *)addr6)) 157 + return addr6 + 12; 158 + 159 + return addr6; 160 + } 161 + 162 + static sa_family_t ovpn_nl_family_get(struct nlattr *addr4, 163 + struct nlattr *addr6) 164 + { 165 + if (addr4) 166 + return AF_INET; 167 + 168 + if (addr6) { 169 + if (ipv6_addr_v4mapped((struct in6_addr *)nla_data(addr6))) 170 + return AF_INET; 171 + return AF_INET6; 172 + } 173 + 174 + return AF_UNSPEC; 175 + } 176 + 177 + static int ovpn_nl_peer_precheck(struct ovpn_priv *ovpn, 178 + struct genl_info *info, 179 + struct nlattr **attrs) 180 + { 181 + sa_family_t local_fam, remote_fam; 182 + 183 + if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs, 184 + OVPN_A_PEER_ID)) 185 + return -EINVAL; 186 + 187 + if (attrs[OVPN_A_PEER_REMOTE_IPV4] && attrs[OVPN_A_PEER_REMOTE_IPV6]) { 188 + NL_SET_ERR_MSG_MOD(info->extack, 189 + "cannot specify both remote IPv4 or IPv6 address"); 190 + return -EINVAL; 191 + } 192 + 193 + if (!attrs[OVPN_A_PEER_REMOTE_IPV4] && 194 + !attrs[OVPN_A_PEER_REMOTE_IPV6] && attrs[OVPN_A_PEER_REMOTE_PORT]) { 195 + NL_SET_ERR_MSG_MOD(info->extack, 196 + "cannot specify remote port without IP address"); 197 + return -EINVAL; 198 + } 199 + 200 + if ((attrs[OVPN_A_PEER_REMOTE_IPV4] || 201 + attrs[OVPN_A_PEER_REMOTE_IPV6]) && 202 + !attrs[OVPN_A_PEER_REMOTE_PORT]) { 203 + NL_SET_ERR_MSG_MOD(info->extack, 204 + "cannot specify remote IP address without port"); 205 + return -EINVAL; 206 + } 207 + 208 + if (!attrs[OVPN_A_PEER_REMOTE_IPV4] && 209 + attrs[OVPN_A_PEER_LOCAL_IPV4]) { 210 + NL_SET_ERR_MSG_MOD(info->extack, 211 + "cannot specify local IPv4 address without remote"); 212 + return -EINVAL; 213 + } 214 + 215 + if (!attrs[OVPN_A_PEER_REMOTE_IPV6] && 216 + attrs[OVPN_A_PEER_LOCAL_IPV6]) { 217 + NL_SET_ERR_MSG_MOD(info->extack, 218 + "cannot specify local IPV6 address without remote"); 219 + return -EINVAL; 220 + } 221 + 222 + /* check that local and remote address families are the same even 223 + * after parsing v4mapped IPv6 addresses. 224 + * (if addresses are not provided, family will be AF_UNSPEC and 225 + * the check is skipped) 226 + */ 227 + local_fam = ovpn_nl_family_get(attrs[OVPN_A_PEER_LOCAL_IPV4], 228 + attrs[OVPN_A_PEER_LOCAL_IPV6]); 229 + remote_fam = ovpn_nl_family_get(attrs[OVPN_A_PEER_REMOTE_IPV4], 230 + attrs[OVPN_A_PEER_REMOTE_IPV6]); 231 + if (local_fam != AF_UNSPEC && remote_fam != AF_UNSPEC && 232 + local_fam != remote_fam) { 233 + NL_SET_ERR_MSG_MOD(info->extack, 234 + "mismatching local and remote address families"); 235 + return -EINVAL; 236 + } 237 + 238 + if (remote_fam != AF_INET6 && attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) { 239 + NL_SET_ERR_MSG_MOD(info->extack, 240 + "cannot specify scope id without remote IPv6 address"); 241 + return -EINVAL; 242 + } 243 + 244 + /* VPN IPs are needed only in MP mode for selecting the right peer */ 245 + if (ovpn->mode == OVPN_MODE_P2P && (attrs[OVPN_A_PEER_VPN_IPV4] || 246 + attrs[OVPN_A_PEER_VPN_IPV6])) { 247 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 248 + "unexpected VPN IP in P2P mode"); 249 + return -EINVAL; 250 + } 251 + 252 + if ((attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL] && 253 + !attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT]) || 254 + (!attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL] && 255 + attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT])) { 256 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 257 + "keepalive interval and timeout are required together"); 258 + return -EINVAL; 259 + } 260 + 261 + return 0; 262 + } 263 + 264 + /** 265 + * ovpn_nl_peer_modify - modify the peer attributes according to the incoming msg 266 + * @peer: the peer to modify 267 + * @info: generic netlink info from the user request 268 + * @attrs: the attributes from the user request 269 + * 270 + * Return: a negative error code in case of failure, 0 on success or 1 on 271 + * success and the VPN IPs have been modified (requires rehashing in MP 272 + * mode) 273 + */ 274 + static int ovpn_nl_peer_modify(struct ovpn_peer *peer, struct genl_info *info, 275 + struct nlattr **attrs) 276 + { 277 + struct sockaddr_storage ss = {}; 278 + void *local_ip = NULL; 279 + u32 interv, timeout; 280 + bool rehash = false; 281 + int ret; 282 + 283 + spin_lock_bh(&peer->lock); 284 + 285 + if (ovpn_nl_attr_sockaddr_remote(attrs, &ss)) { 286 + /* we carry the local IP in a generic container. 287 + * ovpn_peer_reset_sockaddr() will properly interpret it 288 + * based on ss.ss_family 289 + */ 290 + local_ip = ovpn_nl_attr_local_ip(attrs); 291 + 292 + /* set peer sockaddr */ 293 + ret = ovpn_peer_reset_sockaddr(peer, &ss, local_ip); 294 + if (ret < 0) { 295 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 296 + "cannot set peer sockaddr: %d", 297 + ret); 298 + goto err_unlock; 299 + } 300 + dst_cache_reset(&peer->dst_cache); 301 + } 302 + 303 + if (attrs[OVPN_A_PEER_VPN_IPV4]) { 304 + rehash = true; 305 + peer->vpn_addrs.ipv4.s_addr = 306 + nla_get_in_addr(attrs[OVPN_A_PEER_VPN_IPV4]); 307 + } 308 + 309 + if (attrs[OVPN_A_PEER_VPN_IPV6]) { 310 + rehash = true; 311 + peer->vpn_addrs.ipv6 = 312 + nla_get_in6_addr(attrs[OVPN_A_PEER_VPN_IPV6]); 313 + } 314 + 315 + /* when setting the keepalive, both parameters have to be configured */ 316 + if (attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL] && 317 + attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT]) { 318 + interv = nla_get_u32(attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL]); 319 + timeout = nla_get_u32(attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT]); 320 + ovpn_peer_keepalive_set(peer, interv, timeout); 321 + } 322 + 323 + netdev_dbg(peer->ovpn->dev, 324 + "modify peer id=%u endpoint=%pIScp VPN-IPv4=%pI4 VPN-IPv6=%pI6c\n", 325 + peer->id, &ss, 326 + &peer->vpn_addrs.ipv4.s_addr, &peer->vpn_addrs.ipv6); 327 + 328 + spin_unlock_bh(&peer->lock); 329 + 330 + return rehash ? 1 : 0; 331 + err_unlock: 332 + spin_unlock_bh(&peer->lock); 333 + return ret; 334 + } 335 + 96 336 int ovpn_nl_peer_new_doit(struct sk_buff *skb, struct genl_info *info) 97 337 { 98 - return -EOPNOTSUPP; 338 + struct nlattr *attrs[OVPN_A_PEER_MAX + 1]; 339 + struct ovpn_priv *ovpn = info->user_ptr[0]; 340 + struct ovpn_socket *ovpn_sock; 341 + struct socket *sock = NULL; 342 + struct ovpn_peer *peer; 343 + u32 sockfd, peer_id; 344 + int ret; 345 + 346 + if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER)) 347 + return -EINVAL; 348 + 349 + ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER], 350 + ovpn_peer_nl_policy, info->extack); 351 + if (ret) 352 + return ret; 353 + 354 + ret = ovpn_nl_peer_precheck(ovpn, info, attrs); 355 + if (ret < 0) 356 + return ret; 357 + 358 + if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs, 359 + OVPN_A_PEER_SOCKET)) 360 + return -EINVAL; 361 + 362 + /* in MP mode VPN IPs are required for selecting the right peer */ 363 + if (ovpn->mode == OVPN_MODE_MP && !attrs[OVPN_A_PEER_VPN_IPV4] && 364 + !attrs[OVPN_A_PEER_VPN_IPV6]) { 365 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 366 + "VPN IP must be provided in MP mode"); 367 + return -EINVAL; 368 + } 369 + 370 + peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]); 371 + peer = ovpn_peer_new(ovpn, peer_id); 372 + if (IS_ERR(peer)) { 373 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 374 + "cannot create new peer object for peer %u: %ld", 375 + peer_id, PTR_ERR(peer)); 376 + return PTR_ERR(peer); 377 + } 378 + 379 + /* lookup the fd in the kernel table and extract the socket object */ 380 + sockfd = nla_get_u32(attrs[OVPN_A_PEER_SOCKET]); 381 + /* sockfd_lookup() increases sock's refcounter */ 382 + sock = sockfd_lookup(sockfd, &ret); 383 + if (!sock) { 384 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 385 + "cannot lookup peer socket (fd=%u): %d", 386 + sockfd, ret); 387 + ret = -ENOTSOCK; 388 + goto peer_release; 389 + } 390 + 391 + /* Only when using UDP as transport protocol the remote endpoint 392 + * can be configured so that ovpn knows where to send packets to. 393 + */ 394 + if (sock->sk->sk_protocol == IPPROTO_UDP && 395 + !attrs[OVPN_A_PEER_REMOTE_IPV4] && 396 + !attrs[OVPN_A_PEER_REMOTE_IPV6]) { 397 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 398 + "missing remote IP address for UDP socket"); 399 + sockfd_put(sock); 400 + ret = -EINVAL; 401 + goto peer_release; 402 + } 403 + 404 + /* In case of TCP, the socket is connected to the peer and ovpn 405 + * will just send bytes over it, without the need to specify a 406 + * destination. 407 + */ 408 + if (sock->sk->sk_protocol == IPPROTO_TCP && 409 + (attrs[OVPN_A_PEER_REMOTE_IPV4] || 410 + attrs[OVPN_A_PEER_REMOTE_IPV6])) { 411 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 412 + "unexpected remote IP address with TCP socket"); 413 + sockfd_put(sock); 414 + ret = -EINVAL; 415 + goto peer_release; 416 + } 417 + 418 + ovpn_sock = ovpn_socket_new(sock, peer); 419 + /* at this point we unconditionally drop the reference to the socket: 420 + * - in case of error, the socket has to be dropped 421 + * - if case of success, the socket is configured and let 422 + * userspace own the reference, so that the latter can 423 + * trigger the final close() 424 + */ 425 + sockfd_put(sock); 426 + if (IS_ERR(ovpn_sock)) { 427 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 428 + "cannot encapsulate socket: %ld", 429 + PTR_ERR(ovpn_sock)); 430 + ret = -ENOTSOCK; 431 + goto peer_release; 432 + } 433 + 434 + rcu_assign_pointer(peer->sock, ovpn_sock); 435 + 436 + ret = ovpn_nl_peer_modify(peer, info, attrs); 437 + if (ret < 0) 438 + goto sock_release; 439 + 440 + ret = ovpn_peer_add(ovpn, peer); 441 + if (ret < 0) { 442 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 443 + "cannot add new peer (id=%u) to hashtable: %d", 444 + peer->id, ret); 445 + goto sock_release; 446 + } 447 + 448 + return 0; 449 + 450 + sock_release: 451 + ovpn_socket_release(peer); 452 + peer_release: 453 + /* release right away because peer was not yet hashed, thus it is not 454 + * used in any context 455 + */ 456 + ovpn_peer_release(peer); 457 + 458 + return ret; 99 459 } 100 460 101 461 int ovpn_nl_peer_set_doit(struct sk_buff *skb, struct genl_info *info) 102 462 { 103 - return -EOPNOTSUPP; 463 + struct nlattr *attrs[OVPN_A_PEER_MAX + 1]; 464 + struct ovpn_priv *ovpn = info->user_ptr[0]; 465 + struct ovpn_socket *sock; 466 + struct ovpn_peer *peer; 467 + u32 peer_id; 468 + int ret; 469 + 470 + if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER)) 471 + return -EINVAL; 472 + 473 + ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER], 474 + ovpn_peer_nl_policy, info->extack); 475 + if (ret) 476 + return ret; 477 + 478 + ret = ovpn_nl_peer_precheck(ovpn, info, attrs); 479 + if (ret < 0) 480 + return ret; 481 + 482 + if (attrs[OVPN_A_PEER_SOCKET]) { 483 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 484 + "socket cannot be modified"); 485 + return -EINVAL; 486 + } 487 + 488 + peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]); 489 + peer = ovpn_peer_get_by_id(ovpn, peer_id); 490 + if (!peer) { 491 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 492 + "cannot find peer with id %u", peer_id); 493 + return -ENOENT; 494 + } 495 + 496 + /* when using a TCP socket the remote IP is not expected */ 497 + rcu_read_lock(); 498 + sock = rcu_dereference(peer->sock); 499 + if (sock && sock->sock->sk->sk_protocol == IPPROTO_TCP && 500 + (attrs[OVPN_A_PEER_REMOTE_IPV4] || 501 + attrs[OVPN_A_PEER_REMOTE_IPV6])) { 502 + rcu_read_unlock(); 503 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 504 + "unexpected remote IP address with TCP socket"); 505 + ovpn_peer_put(peer); 506 + return -EINVAL; 507 + } 508 + rcu_read_unlock(); 509 + 510 + spin_lock_bh(&ovpn->lock); 511 + ret = ovpn_nl_peer_modify(peer, info, attrs); 512 + if (ret < 0) { 513 + spin_unlock_bh(&ovpn->lock); 514 + ovpn_peer_put(peer); 515 + return ret; 516 + } 517 + 518 + /* ret == 1 means that VPN IPv4/6 has been modified and rehashing 519 + * is required 520 + */ 521 + if (ret > 0) 522 + ovpn_peer_hash_vpn_ip(peer); 523 + spin_unlock_bh(&ovpn->lock); 524 + ovpn_peer_put(peer); 525 + 526 + return 0; 527 + } 528 + 529 + static int ovpn_nl_send_peer(struct sk_buff *skb, const struct genl_info *info, 530 + const struct ovpn_peer *peer, u32 portid, u32 seq, 531 + int flags) 532 + { 533 + const struct ovpn_bind *bind; 534 + struct ovpn_socket *sock; 535 + int ret = -EMSGSIZE; 536 + struct nlattr *attr; 537 + __be16 local_port; 538 + void *hdr; 539 + int id; 540 + 541 + hdr = genlmsg_put(skb, portid, seq, &ovpn_nl_family, flags, 542 + OVPN_CMD_PEER_GET); 543 + if (!hdr) 544 + return -ENOBUFS; 545 + 546 + attr = nla_nest_start(skb, OVPN_A_PEER); 547 + if (!attr) 548 + goto err; 549 + 550 + rcu_read_lock(); 551 + sock = rcu_dereference(peer->sock); 552 + if (!sock) { 553 + ret = -EINVAL; 554 + goto err_unlock; 555 + } 556 + 557 + if (!net_eq(genl_info_net(info), sock_net(sock->sock->sk))) { 558 + id = peernet2id_alloc(genl_info_net(info), 559 + sock_net(sock->sock->sk), 560 + GFP_ATOMIC); 561 + if (nla_put_s32(skb, OVPN_A_PEER_SOCKET_NETNSID, id)) 562 + goto err_unlock; 563 + } 564 + local_port = inet_sk(sock->sock->sk)->inet_sport; 565 + rcu_read_unlock(); 566 + 567 + if (nla_put_u32(skb, OVPN_A_PEER_ID, peer->id)) 568 + goto err; 569 + 570 + if (peer->vpn_addrs.ipv4.s_addr != htonl(INADDR_ANY)) 571 + if (nla_put_in_addr(skb, OVPN_A_PEER_VPN_IPV4, 572 + peer->vpn_addrs.ipv4.s_addr)) 573 + goto err; 574 + 575 + if (!ipv6_addr_equal(&peer->vpn_addrs.ipv6, &in6addr_any)) 576 + if (nla_put_in6_addr(skb, OVPN_A_PEER_VPN_IPV6, 577 + &peer->vpn_addrs.ipv6)) 578 + goto err; 579 + 580 + if (nla_put_u32(skb, OVPN_A_PEER_KEEPALIVE_INTERVAL, 581 + peer->keepalive_interval) || 582 + nla_put_u32(skb, OVPN_A_PEER_KEEPALIVE_TIMEOUT, 583 + peer->keepalive_timeout)) 584 + goto err; 585 + 586 + rcu_read_lock(); 587 + bind = rcu_dereference(peer->bind); 588 + if (bind) { 589 + if (bind->remote.in4.sin_family == AF_INET) { 590 + if (nla_put_in_addr(skb, OVPN_A_PEER_REMOTE_IPV4, 591 + bind->remote.in4.sin_addr.s_addr) || 592 + nla_put_net16(skb, OVPN_A_PEER_REMOTE_PORT, 593 + bind->remote.in4.sin_port) || 594 + nla_put_in_addr(skb, OVPN_A_PEER_LOCAL_IPV4, 595 + bind->local.ipv4.s_addr)) 596 + goto err_unlock; 597 + } else if (bind->remote.in4.sin_family == AF_INET6) { 598 + if (nla_put_in6_addr(skb, OVPN_A_PEER_REMOTE_IPV6, 599 + &bind->remote.in6.sin6_addr) || 600 + nla_put_u32(skb, OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID, 601 + bind->remote.in6.sin6_scope_id) || 602 + nla_put_net16(skb, OVPN_A_PEER_REMOTE_PORT, 603 + bind->remote.in6.sin6_port) || 604 + nla_put_in6_addr(skb, OVPN_A_PEER_LOCAL_IPV6, 605 + &bind->local.ipv6)) 606 + goto err_unlock; 607 + } 608 + } 609 + rcu_read_unlock(); 610 + 611 + if (nla_put_net16(skb, OVPN_A_PEER_LOCAL_PORT, local_port) || 612 + /* VPN RX stats */ 613 + nla_put_uint(skb, OVPN_A_PEER_VPN_RX_BYTES, 614 + atomic64_read(&peer->vpn_stats.rx.bytes)) || 615 + nla_put_uint(skb, OVPN_A_PEER_VPN_RX_PACKETS, 616 + atomic64_read(&peer->vpn_stats.rx.packets)) || 617 + /* VPN TX stats */ 618 + nla_put_uint(skb, OVPN_A_PEER_VPN_TX_BYTES, 619 + atomic64_read(&peer->vpn_stats.tx.bytes)) || 620 + nla_put_uint(skb, OVPN_A_PEER_VPN_TX_PACKETS, 621 + atomic64_read(&peer->vpn_stats.tx.packets)) || 622 + /* link RX stats */ 623 + nla_put_uint(skb, OVPN_A_PEER_LINK_RX_BYTES, 624 + atomic64_read(&peer->link_stats.rx.bytes)) || 625 + nla_put_uint(skb, OVPN_A_PEER_LINK_RX_PACKETS, 626 + atomic64_read(&peer->link_stats.rx.packets)) || 627 + /* link TX stats */ 628 + nla_put_uint(skb, OVPN_A_PEER_LINK_TX_BYTES, 629 + atomic64_read(&peer->link_stats.tx.bytes)) || 630 + nla_put_uint(skb, OVPN_A_PEER_LINK_TX_PACKETS, 631 + atomic64_read(&peer->link_stats.tx.packets))) 632 + goto err; 633 + 634 + nla_nest_end(skb, attr); 635 + genlmsg_end(skb, hdr); 636 + 637 + return 0; 638 + err_unlock: 639 + rcu_read_unlock(); 640 + err: 641 + genlmsg_cancel(skb, hdr); 642 + return ret; 104 643 } 105 644 106 645 int ovpn_nl_peer_get_doit(struct sk_buff *skb, struct genl_info *info) 107 646 { 108 - return -EOPNOTSUPP; 647 + struct nlattr *attrs[OVPN_A_PEER_MAX + 1]; 648 + struct ovpn_priv *ovpn = info->user_ptr[0]; 649 + struct ovpn_peer *peer; 650 + struct sk_buff *msg; 651 + u32 peer_id; 652 + int ret; 653 + 654 + if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER)) 655 + return -EINVAL; 656 + 657 + ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER], 658 + ovpn_peer_nl_policy, info->extack); 659 + if (ret) 660 + return ret; 661 + 662 + if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs, 663 + OVPN_A_PEER_ID)) 664 + return -EINVAL; 665 + 666 + peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]); 667 + peer = ovpn_peer_get_by_id(ovpn, peer_id); 668 + if (!peer) { 669 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 670 + "cannot find peer with id %u", peer_id); 671 + return -ENOENT; 672 + } 673 + 674 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 675 + if (!msg) { 676 + ret = -ENOMEM; 677 + goto err; 678 + } 679 + 680 + ret = ovpn_nl_send_peer(msg, info, peer, info->snd_portid, 681 + info->snd_seq, 0); 682 + if (ret < 0) { 683 + nlmsg_free(msg); 684 + goto err; 685 + } 686 + 687 + ret = genlmsg_reply(msg, info); 688 + err: 689 + ovpn_peer_put(peer); 690 + return ret; 109 691 } 110 692 111 693 int ovpn_nl_peer_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 112 694 { 113 - return -EOPNOTSUPP; 695 + const struct genl_info *info = genl_info_dump(cb); 696 + int bkt, last_idx = cb->args[1], dumped = 0; 697 + netdevice_tracker tracker; 698 + struct ovpn_priv *ovpn; 699 + struct ovpn_peer *peer; 700 + 701 + ovpn = ovpn_get_dev_from_attrs(sock_net(cb->skb->sk), info, &tracker); 702 + if (IS_ERR(ovpn)) 703 + return PTR_ERR(ovpn); 704 + 705 + if (ovpn->mode == OVPN_MODE_P2P) { 706 + /* if we already dumped a peer it means we are done */ 707 + if (last_idx) 708 + goto out; 709 + 710 + rcu_read_lock(); 711 + peer = rcu_dereference(ovpn->peer); 712 + if (peer) { 713 + if (ovpn_nl_send_peer(skb, info, peer, 714 + NETLINK_CB(cb->skb).portid, 715 + cb->nlh->nlmsg_seq, 716 + NLM_F_MULTI) == 0) 717 + dumped++; 718 + } 719 + rcu_read_unlock(); 720 + } else { 721 + rcu_read_lock(); 722 + hash_for_each_rcu(ovpn->peers->by_id, bkt, peer, 723 + hash_entry_id) { 724 + /* skip already dumped peers that were dumped by 725 + * previous invocations 726 + */ 727 + if (last_idx > 0) { 728 + last_idx--; 729 + continue; 730 + } 731 + 732 + if (ovpn_nl_send_peer(skb, info, peer, 733 + NETLINK_CB(cb->skb).portid, 734 + cb->nlh->nlmsg_seq, 735 + NLM_F_MULTI) < 0) 736 + break; 737 + 738 + /* count peers being dumped during this invocation */ 739 + dumped++; 740 + } 741 + rcu_read_unlock(); 742 + } 743 + 744 + out: 745 + netdev_put(ovpn->dev, &tracker); 746 + 747 + /* sum up peers dumped in this message, so that at the next invocation 748 + * we can continue from where we left 749 + */ 750 + cb->args[1] += dumped; 751 + return skb->len; 114 752 } 115 753 116 754 int ovpn_nl_peer_del_doit(struct sk_buff *skb, struct genl_info *info) 117 755 { 118 - return -EOPNOTSUPP; 756 + struct nlattr *attrs[OVPN_A_PEER_MAX + 1]; 757 + struct ovpn_priv *ovpn = info->user_ptr[0]; 758 + struct ovpn_peer *peer; 759 + u32 peer_id; 760 + int ret; 761 + 762 + if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER)) 763 + return -EINVAL; 764 + 765 + ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER], 766 + ovpn_peer_nl_policy, info->extack); 767 + if (ret) 768 + return ret; 769 + 770 + if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs, 771 + OVPN_A_PEER_ID)) 772 + return -EINVAL; 773 + 774 + peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]); 775 + peer = ovpn_peer_get_by_id(ovpn, peer_id); 776 + if (!peer) { 777 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 778 + "cannot find peer with id %u", peer_id); 779 + return -ENOENT; 780 + } 781 + 782 + netdev_dbg(ovpn->dev, "del peer %u\n", peer->id); 783 + ret = ovpn_peer_del(peer, OVPN_DEL_PEER_REASON_USERSPACE); 784 + ovpn_peer_put(peer); 785 + 786 + return ret; 119 787 } 120 788 121 789 int ovpn_nl_key_new_doit(struct sk_buff *skb, struct genl_info *info)
+50 -29
drivers/net/ovpn/peer.c
··· 135 135 * 136 136 * Return: 0 on success or a negative error code otherwise 137 137 */ 138 - static int ovpn_peer_reset_sockaddr(struct ovpn_peer *peer, 139 - const struct sockaddr_storage *ss, 140 - const void *local_ip) 138 + int ovpn_peer_reset_sockaddr(struct ovpn_peer *peer, 139 + const struct sockaddr_storage *ss, 140 + const void *local_ip) 141 141 { 142 142 struct ovpn_bind *bind; 143 143 size_t ip_len; ··· 149 149 if (IS_ERR(bind)) 150 150 return PTR_ERR(bind); 151 151 152 - if (ss->ss_family == AF_INET) { 153 - ip_len = sizeof(struct in_addr); 154 - } else if (ss->ss_family == AF_INET6) { 155 - ip_len = sizeof(struct in6_addr); 156 - } else { 157 - net_dbg_ratelimited("%s: invalid family %u for remote endpoint for peer %u\n", 158 - netdev_name(peer->ovpn->dev), 159 - ss->ss_family, peer->id); 160 - kfree(bind); 161 - return -EINVAL; 162 - } 152 + if (local_ip) { 153 + if (ss->ss_family == AF_INET) { 154 + ip_len = sizeof(struct in_addr); 155 + } else if (ss->ss_family == AF_INET6) { 156 + ip_len = sizeof(struct in6_addr); 157 + } else { 158 + net_dbg_ratelimited("%s: invalid family %u for remote endpoint for peer %u\n", 159 + netdev_name(peer->ovpn->dev), 160 + ss->ss_family, peer->id); 161 + kfree(bind); 162 + return -EINVAL; 163 + } 163 164 164 - memcpy(&bind->local, local_ip, ip_len); 165 + memcpy(&bind->local, local_ip, ip_len); 166 + } 165 167 166 168 /* set binding */ 167 169 ovpn_bind_reset(peer, bind); ··· 348 346 * ovpn_peer_release - release peer private members 349 347 * @peer: the peer to release 350 348 */ 351 - static void ovpn_peer_release(struct ovpn_peer *peer) 349 + void ovpn_peer_release(struct ovpn_peer *peer) 352 350 { 353 351 ovpn_crypto_state_release(&peer->crypto); 354 352 spin_lock_bh(&peer->lock); ··· 889 887 return match; 890 888 } 891 889 890 + void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer) 891 + { 892 + struct hlist_nulls_head *nhead; 893 + 894 + lockdep_assert_held(&peer->ovpn->lock); 895 + 896 + /* rehashing makes sense only in multipeer mode */ 897 + if (peer->ovpn->mode != OVPN_MODE_MP) 898 + return; 899 + 900 + if (peer->vpn_addrs.ipv4.s_addr != htonl(INADDR_ANY)) { 901 + /* remove potential old hashing */ 902 + hlist_nulls_del_init_rcu(&peer->hash_entry_addr4); 903 + 904 + nhead = ovpn_get_hash_head(peer->ovpn->peers->by_vpn_addr4, 905 + &peer->vpn_addrs.ipv4, 906 + sizeof(peer->vpn_addrs.ipv4)); 907 + hlist_nulls_add_head_rcu(&peer->hash_entry_addr4, nhead); 908 + } 909 + 910 + if (!ipv6_addr_any(&peer->vpn_addrs.ipv6)) { 911 + /* remove potential old hashing */ 912 + hlist_nulls_del_init_rcu(&peer->hash_entry_addr6); 913 + 914 + nhead = ovpn_get_hash_head(peer->ovpn->peers->by_vpn_addr6, 915 + &peer->vpn_addrs.ipv6, 916 + sizeof(peer->vpn_addrs.ipv6)); 917 + hlist_nulls_add_head_rcu(&peer->hash_entry_addr6, nhead); 918 + } 919 + } 920 + 892 921 /** 893 922 * ovpn_peer_add_mp - add peer to related tables in a MP instance 894 923 * @ovpn: the instance to add the peer to ··· 981 948 ovpn_get_hash_head(ovpn->peers->by_id, &peer->id, 982 949 sizeof(peer->id))); 983 950 984 - if (peer->vpn_addrs.ipv4.s_addr != htonl(INADDR_ANY)) { 985 - nhead = ovpn_get_hash_head(ovpn->peers->by_vpn_addr4, 986 - &peer->vpn_addrs.ipv4, 987 - sizeof(peer->vpn_addrs.ipv4)); 988 - hlist_nulls_add_head_rcu(&peer->hash_entry_addr4, nhead); 989 - } 990 - 991 - if (!ipv6_addr_any(&peer->vpn_addrs.ipv6)) { 992 - nhead = ovpn_get_hash_head(ovpn->peers->by_vpn_addr6, 993 - &peer->vpn_addrs.ipv6, 994 - sizeof(peer->vpn_addrs.ipv6)); 995 - hlist_nulls_add_head_rcu(&peer->hash_entry_addr6, nhead); 996 - } 951 + ovpn_peer_hash_vpn_ip(peer); 997 952 out: 998 953 spin_unlock_bh(&ovpn->lock); 999 954 return ret;
+5
drivers/net/ovpn/peer.h
··· 125 125 return kref_get_unless_zero(&peer->refcount); 126 126 } 127 127 128 + void ovpn_peer_release(struct ovpn_peer *peer); 128 129 void ovpn_peer_release_kref(struct kref *kref); 129 130 130 131 /** ··· 148 147 struct ovpn_peer *ovpn_peer_get_by_id(struct ovpn_priv *ovpn, u32 peer_id); 149 148 struct ovpn_peer *ovpn_peer_get_by_dst(struct ovpn_priv *ovpn, 150 149 struct sk_buff *skb); 150 + void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer); 151 151 bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb, 152 152 struct ovpn_peer *peer); 153 153 ··· 156 154 void ovpn_peer_keepalive_work(struct work_struct *work); 157 155 158 156 void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb); 157 + int ovpn_peer_reset_sockaddr(struct ovpn_peer *peer, 158 + const struct sockaddr_storage *ss, 159 + const void *local_ip); 159 160 160 161 #endif /* _NET_OVPN_OVPNPEER_H_ */
+2 -2
drivers/net/ovpn/socket.c
··· 49 49 * ovpn_socket_release - release resources owned by socket user 50 50 * @peer: peer whose socket should be released 51 51 * 52 - * This function should be invoked when the user is shutting 53 - * down and wants to drop its link to the socket. 52 + * This function should be invoked when the peer is being removed 53 + * and wants to drop its link to the socket. 54 54 * 55 55 * In case of UDP, the detach routine will drop a reference to the 56 56 * ovpn netdev, pointed by the ovpn_socket.