From patchwork Wed Mar 22 10:06:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 3148 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7300:2310:b0:9f:bfa4:120f with SMTP id r16csp3070621dye; Wed, 22 Mar 2023 03:07:33 -0700 (PDT) X-Google-Smtp-Source: AK7set8dM3KDChhGe1nE+8a/MMvzQnXmmtgzJeaiiZ5zHGRXKF290cWJSL0lEi+L6rMHF7pn7m42 X-Received: by 2002:aa7:9696:0:b0:628:0:7939 with SMTP id f22-20020aa79696000000b0062800007939mr2570982pfk.26.1679479653132; Wed, 22 Mar 2023 03:07:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1679479653; cv=none; d=google.com; s=arc-20160816; b=H1FEb6sJ1XwlL2R6uwQ9FWAfqdf0anc4M479ujEMYVb0+0+hfo6u9qiKy4xHnAf1Ip Ir8By+ArvjtGb2HCLjEIssfxPtVI5iss5f6b/y/yBpsC1qTDcG6l8BGEkA2XcJbCOpEd MJu8VtyhpJityxuxuJZXQgdhOxCynaY5Xj1oyB1Pic58oxGiWaO9OU6B6wOilGMlyCw3 YdIPsiDLEUYGPbWCMuIcIXsGwMldht1XUSskxGLpzZRViV/RJgAHPRUoPqEJ4q2l7Xnf f8IvtuyDlF0jqtf27PIokyPS2pqf8ycu1y6FWZERSwtIK2JdHNeTlNaUM8EM6DCSF+5g y1uA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:content-transfer-encoding:cc:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature; bh=WmKdqYR0hb8rF2TfXGd3Or93QSRm9IMHIbDpJjfVvCE=; b=OubCfi0PvTiS+K9xXBdfy/KmH7+ptq5m6v58fwerKFZAKgoJvjEsMewHJGUVYCW5cF /7oO7hbFweF0Z2Rr8ZCOjjThgFW+oRI9mA1ySwybbLBAzbabTf+vXG0j0Yttb5UPJGez 4aF4dMl/+xcVdzTrS4QMdjVWen3HI/A6lPONhx+gSu/rgDjCrIw/BFNwyMFD/q2zepX4 ORSMPWsEOsXClptYe3G+W8S3ThAdUjiOeLy8lE6TXj0js5Hmbl8KxkKGAcm5D0r3lHTP m9NYmnNcRl3YSMyBRrqPx25qy6MDJpIy7MY5GEx0+Ztc4G5FxffDTJ/ZgoSlFYMo4x2T p5GA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=ZW96POZ3; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=A4CJdj2G; dkim=fail header.i=@unstable.cc header.s=20220809-q8oc header.b=DqcyAKc8; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net Received: from lists.sourceforge.net ([216.105.38.7]) by mx.google.com with ESMTPS id m62-20020a632641000000b00502fd2d2901si16012874pgm.343.2023.03.22.03.07.32 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Mar 2023 03:07:33 -0700 (PDT) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=ZW96POZ3; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=A4CJdj2G; dkim=fail header.i=@unstable.cc header.s=20220809-q8oc header.b=DqcyAKc8; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1pevMk-0001bv-CY; Wed, 22 Mar 2023 10:06:46 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1pevMi-0001bd-Uw for openvpn-devel@lists.sourceforge.net; Wed, 22 Mar 2023 10:06:45 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=Rpyqbw3TJcDw8w4umdNaPnFo+mUKRS64sgh+UBNftTU=; b=ZW96POZ3Yp1tVnypEtVxJRYZPs LhXa6PgY43zmIyD2/0LDAUSrFWjffSxnkco8sFTTADC0C0LRWd/ZUdHyLkSoznOghq1HNLPOiT9WQ saXYFqGcTg6PQgj+lbCYAohvLwpFfl9E475sRc4UrmJJdOnauCaz+y3rICX4nvuVj1iQ=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=Rpyqbw3TJcDw8w4umdNaPnFo+mUKRS64sgh+UBNftTU=; b=A4CJdj2GwicWUaW4ERPyhqJSyh m62Uml7uuouLbkuY89tYNQlFWWKLuctkDNiEM9pJ+ZfUxYfonr7uJqAiUj1bFdWTDtq2+Ulgxi7zf dw0KRXLY/fVR0IwOvg4H1ajBsvJXcHUWyIC4ee6LkWd9BTHROcKkVO84JYWMs2reppzQ=; Received: from mailout-l3b-97.contactoffice.com ([212.3.242.97]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1pevMf-00GQeb-Sg for openvpn-devel@lists.sourceforge.net; Wed, 22 Mar 2023 10:06:45 +0000 Received: from smtpauth2.co-bxl (smtpauth2.co-bxl [10.2.0.24]) by mailout-l3b-97.contactoffice.com (Postfix) with ESMTP id 4FF59996; Wed, 22 Mar 2023 11:06:34 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1679479594; s=20220809-q8oc; d=unstable.cc; i=a@unstable.cc; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; l=9972; bh=Rpyqbw3TJcDw8w4umdNaPnFo+mUKRS64sgh+UBNftTU=; b=DqcyAKc8vA26kg2oK3HF/iWWvTqxLR8T29J7ykN8tpYESERfcU8ra1mgyiG/MhNa dnlUOL3TjdtKwHY6u54bH1GBFTjyQNyBRrZoub29Dnxive+oDYRmMmoKIQ3Rff4c3Is MbVLsWR0373wGeZwx82Sm7A6noKsvAf+Qfqyanl9qKzdqbUFitsYSHnYfADPjemnliU 0RRTk4fnPse3cZ7/ZCsmswdTT6eaiChyvEHyrp9iQQ3E1edOIAMf/K5Wm80CgUPaQv8 VXzl38jBwC93hVc/U9a7B5s4JXfODlTVI8fgscTkOrUA7XS5yhlzySwXW335DWhfHOt PCo1/AtrVQ== Received: by smtp.mailfence.com with ESMTPSA ; Wed, 22 Mar 2023 11:06:30 +0100 (CET) From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Wed, 22 Mar 2023 11:06:10 +0100 Message-Id: <20230322100610.14234-2-a@unstable.cc> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321230807.1382-1-a@unstable.cc> References: <20230322100610.14234-1-a@unstable.cc> MIME-Version: 1.0 X-Spam-Flag: NO X-Spam-Status: No, hits=-1.0 required=4.7 symbols=ALL_TRUSTED device=10.2.0.21 X-ContactOffice-Account: com:375058688 X-Spam-Score: -0.9 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-1.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: With this API it is possible to retrieve the stats for a specific peer or for all peers and then update the userspace counters with the value reported by DCO. Change-Id: Ia3990b86b1be7ca844fb1674b39ce0d60528ccff Signed-off-by: Antonio Quartulli --- Content analysis details: (-0.9 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at https://www.dnswl.org/, low trust [212.3.242.97 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-Headers-End: 1pevMf-00GQeb-Sg Subject: [Openvpn-devel] [PATCH v3] dco-linux: implement dco_get_peer_stats{, multi} API X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1760930818475245873?= X-GMAIL-MSGID: =?utf-8?q?1761062056625158080?= With this API it is possible to retrieve the stats for a specific peer or for all peers and then update the userspace counters with the value reported by DCO. Change-Id: Ia3990b86b1be7ca844fb1674b39ce0d60528ccff Signed-off-by: Antonio Quartulli --- Changes from v1: * use m->instances[] instead of iterating over m->hash Changes from v2: * added boundary check on peer-id --- src/openvpn/dco_linux.c | 190 ++++++++++++++++++++++++++++++++--- src/openvpn/ovpn_dco_linux.h | 14 ++- 2 files changed, 186 insertions(+), 18 deletions(-) diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 47961849..8e7b4eab 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -41,6 +41,7 @@ #include "tun.h" #include "ssl.h" #include "fdmisc.h" +#include "multi.h" #include "ssl_verify.h" #include "ovpn_dco_linux.h" @@ -168,16 +169,17 @@ ovpn_nl_recvmsgs(dco_context_t *dco, const char *prefix) * @param dco The dco context to use * @param nl_msg the message to use * @param cb An optional callback if the caller expects an answer + * @param cb_arg An optional param to pass to the callback * @param prefix A prefix to report in the error message to give the user context * @return status of sending the message */ static int ovpn_nl_msg_send(dco_context_t *dco, struct nl_msg *nl_msg, ovpn_nl_cb cb, - const char *prefix) + void *cb_arg, const char *prefix) { dco->status = 1; - nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, cb, dco); + nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, cb, cb_arg); nl_send_auto(dco->nl_sock, nl_msg); while (dco->status == 1) @@ -268,7 +270,7 @@ dco_new_peer(dco_context_t *dco, unsigned int peerid, int sd, } nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -489,7 +491,7 @@ dco_swap_keys(dco_context_t *dco, unsigned int peerid) NLA_PUT_U32(nl_msg, OVPN_SWAP_KEYS_ATTR_PEER_ID, peerid); nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -513,7 +515,7 @@ dco_del_peer(dco_context_t *dco, unsigned int peerid) NLA_PUT_U32(nl_msg, OVPN_DEL_PEER_ATTR_PEER_ID, peerid); nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -539,7 +541,7 @@ dco_del_key(dco_context_t *dco, unsigned int peerid, NLA_PUT_U8(nl_msg, OVPN_DEL_KEY_ATTR_KEY_SLOT, slot); nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -596,7 +598,7 @@ dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -625,7 +627,7 @@ dco_set_peer(dco_context_t *dco, unsigned int peerid, keepalive_timeout); nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -706,7 +708,7 @@ ovpn_get_mcast_id(dco_context_t *dco) int ret = -EMSGSIZE; NLA_PUT_STRING(nl_msg, CTRL_ATTR_FAMILY_NAME, OVPN_NL_NAME); - ret = ovpn_nl_msg_send(dco, nl_msg, mcast_family_handler, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, mcast_family_handler, dco, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -819,18 +821,180 @@ dco_do_read(dco_context_t *dco) return ovpn_nl_recvmsgs(dco, __func__); } +static void +dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id) +{ + if (tb[OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES]) + { + c2->dco_read_bytes = nla_get_u64(tb[OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES]); + msg(D_DCO_DEBUG, "%s / dco_read_bytes: %lu", __func__, + c2->dco_read_bytes); + } + else + { + msg(M_WARN, "%s: no link RX bytes provided in reply for peer %u", + __func__, id); + } + + if (tb[OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES]) + { + c2->dco_write_bytes = nla_get_u64(tb[OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES]); + msg(D_DCO_DEBUG, "%s / dco_write_bytes: %lu", __func__, + c2->dco_write_bytes); + } + else + { + msg(M_WARN, "%s: no link TX bytes provided in reply for peer %u", + __func__, id); + } + + if (tb[OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES]) + { + c2->tun_read_bytes = nla_get_u64(tb[OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES]); + msg(D_DCO_DEBUG, "%s / tun_read_bytes: %lu", __func__, + c2->tun_read_bytes); + } + else + { + msg(M_WARN, "%s: no VPN RX bytes provided in reply for peer %u", + __func__, id); + } + + if (tb[OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES]) + { + c2->tun_write_bytes = nla_get_u64(tb[OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES]); + msg(D_DCO_DEBUG, "%s / tun_write_bytes: %lu", __func__, + c2->tun_write_bytes); + } + else + { + msg(M_WARN, "%s: no VPN TX bytes provided in reply for peer %u", + __func__, id); + } +} + +int +dco_parse_peer_multi(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[OVPN_ATTR_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + + msg(D_DCO_DEBUG, "%s: parsing message...", __func__); + + nla_parse(tb, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[OVPN_ATTR_GET_PEER]) + { + return NL_SKIP; + } + + struct nlattr *tb_peer[OVPN_GET_PEER_RESP_ATTR_MAX + 1]; + + nla_parse(tb_peer, OVPN_GET_PEER_RESP_ATTR_MAX, + nla_data(tb[OVPN_ATTR_GET_PEER]), + nla_len(tb[OVPN_ATTR_GET_PEER]), NULL); + + if (!tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]) + { + msg(M_WARN, "%s: no peer-id provided in reply", __func__); + return NL_SKIP; + } + + struct multi_context *m = arg; + uint32_t peer_id = nla_get_u32(tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]); + if (peer_id >= m->max_clients) + { + msg(M_WARN, "%s: cannot retrieve stats for peer %u. ID is invalid (out of bound)!", + __func__, peer_id); + return NL_SKIP; + } + + struct multi_instance *mi = m->instances[peer_id]; + if (!mi) + { + msg(D_DCO_DEBUG, "%s: peer %d returned by kernel, but not found locally", + __func__, peer_id); + return NL_SKIP; + } + + dco_update_peer_stat(&mi->context.c2, tb_peer, peer_id); + + return NL_OK; +} + int dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m) { - /* Not implemented. */ - return 0; + msg(D_DCO_DEBUG, "%s", __func__); + + struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_GET_PEER); + + nlmsg_hdr(nl_msg)->nlmsg_flags |= NLM_F_DUMP; + + return ovpn_nl_msg_send(dco, nl_msg, dco_parse_peer_multi, m, __func__); +} + +static int +dco_parse_peer(struct nl_msg *msg, void *arg) +{ + struct context *c = arg; + struct nlattr *tb[OVPN_ATTR_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + + msg(D_DCO_DEBUG, "%s: parsing message...", __func__); + + nla_parse(tb, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[OVPN_ATTR_GET_PEER]) + { + msg(D_DCO_DEBUG, "%s: malformed reply", __func__); + return NL_SKIP; + } + + struct nlattr *tb_peer[OVPN_GET_PEER_RESP_ATTR_MAX + 1]; + + nla_parse(tb_peer, OVPN_GET_PEER_RESP_ATTR_MAX, + nla_data(tb[OVPN_ATTR_GET_PEER]), + nla_len(tb[OVPN_ATTR_GET_PEER]), NULL); + + if (!tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]) + { + msg(M_WARN, "%s: no peer-id provided in reply", __func__); + return NL_SKIP; + } + + uint32_t peer_id = nla_get_u32(tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]); + if (c->c2.tls_multi->dco_peer_id != peer_id) + { + return NL_SKIP; + } + + dco_update_peer_stat(&c->c2, tb_peer, peer_id); + + return NL_OK; } int dco_get_peer_stats(struct context *c) { - /* Not implemented. */ - return 0; + uint32_t peer_id = c->c2.tls_multi->dco_peer_id; + msg(D_DCO_DEBUG, "%s: peer-id %d", __func__, peer_id); + + dco_context_t *dco = &c->c1.tuntap->dco; + struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_GET_PEER); + struct nlattr *attr = nla_nest_start(nl_msg, OVPN_ATTR_GET_PEER); + int ret = -EMSGSIZE; + + NLA_PUT_U32(nl_msg, OVPN_GET_PEER_ATTR_PEER_ID, peer_id); + nla_nest_end(nl_msg, attr); + + ret = ovpn_nl_msg_send(dco, nl_msg, dco_parse_peer, c, __func__); + +nla_put_failure: + nlmsg_free(nl_msg); + return ret; } bool diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index d3fd9a89..73e19b59 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -2,7 +2,7 @@ /* * OpenVPN data channel accelerator * - * Copyright (C) 2019-2022 OpenVPN, Inc. + * Copyright (C) 2019-2023 OpenVPN, Inc. * * Author: James Yonan * Antonio Quartulli @@ -188,10 +188,14 @@ enum ovpn_netlink_get_peer_response_attrs { OVPN_GET_PEER_RESP_ATTR_LOCAL_PORT, OVPN_GET_PEER_RESP_ATTR_KEEPALIVE_INTERVAL, OVPN_GET_PEER_RESP_ATTR_KEEPALIVE_TIMEOUT, - OVPN_GET_PEER_RESP_ATTR_RX_BYTES, - OVPN_GET_PEER_RESP_ATTR_TX_BYTES, - OVPN_GET_PEER_RESP_ATTR_RX_PACKETS, - OVPN_GET_PEER_RESP_ATTR_TX_PACKETS, + OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES, + OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES, + OVPN_GET_PEER_RESP_ATTR_VPN_RX_PACKETS, + OVPN_GET_PEER_RESP_ATTR_VPN_TX_PACKETS, + OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES, + OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES, + OVPN_GET_PEER_RESP_ATTR_LINK_RX_PACKETS, + OVPN_GET_PEER_RESP_ATTR_LINK_TX_PACKETS, __OVPN_GET_PEER_RESP_ATTR_AFTER_LAST, OVPN_GET_PEER_RESP_ATTR_MAX = __OVPN_GET_PEER_RESP_ATTR_AFTER_LAST - 1,