Browse code

dco_linux: fix peer stats parsing with new ovpn kernel module

The new ovpn kernel module has changed the netlink attribute
type of the fields containing the pkt/bytes counters in the
peer stats.

We moved from uint64 to uint (a dynamic type can be either
32 or 64 bits), therefore the parsing code must be adapted
accordingly.

While at it, also fix the peer object parsing in the P2P code path.

The fix can be verified by enabling --status with verb 6 and
watching the counters increasing:

2025-05-16 22:23:56 us=649488 dco_get_peer_stats_multi
2025-05-16 22:23:56 us=651008 dco_parse_peer_multi: parsing message...
2025-05-16 22:23:56 us=651734 dco_update_peer_stat / dco_read_bytes: 116280
2025-05-16 22:23:56 us=652682 dco_update_peer_stat / dco_write_bytes: 115776
2025-05-16 22:23:56 us=653467 dco_update_peer_stat / tun_read_bytes: 90048
2025-05-16 22:23:56 us=654110 dco_update_peer_stat / tun_write_bytes: 90048

Change-Id: I104b4adeb9f65cce3487b82f35470174acba92bc
Github: closes OpenVPN/openvpn#746
Signed-off-by: Antonio Quartulli <antonio@mandelbit.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20250517083231.27977-1-gert@greenie.muc.de>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg31666.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Antonio Quartulli authored on 2025/05/17 17:32:23
Showing 1 changed files
... ...
@@ -908,12 +908,26 @@ dco_do_read(dco_context_t *dco)
908 908
     return ovpn_nl_recvmsgs(dco, __func__);
909 909
 }
910 910
 
911
+/* libnl < 3.11.0 does not implement nla_get_uint() */
912
+static uint64_t
913
+ovpn_nla_get_uint(struct nlattr *attr)
914
+{
915
+    if (nla_len(attr) == sizeof(uint32_t))
916
+    {
917
+        return nla_get_u32(attr);
918
+    }
919
+    else
920
+    {
921
+        return nla_get_u64(attr);
922
+    }
923
+}
924
+
911 925
 static void
912 926
 dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id)
913 927
 {
914 928
     if (tb[OVPN_A_PEER_LINK_RX_BYTES])
915 929
     {
916
-        c2->dco_read_bytes = nla_get_u64(tb[OVPN_A_PEER_LINK_RX_BYTES]);
930
+        c2->dco_read_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_LINK_RX_BYTES]);
917 931
         msg(D_DCO_DEBUG, "%s / dco_read_bytes: " counter_format, __func__,
918 932
             c2->dco_read_bytes);
919 933
     }
... ...
@@ -925,7 +939,7 @@ dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id)
925 925
 
926 926
     if (tb[OVPN_A_PEER_LINK_TX_BYTES])
927 927
     {
928
-        c2->dco_write_bytes = nla_get_u64(tb[OVPN_A_PEER_LINK_TX_BYTES]);
928
+        c2->dco_write_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_LINK_TX_BYTES]);
929 929
         msg(D_DCO_DEBUG, "%s / dco_write_bytes: " counter_format, __func__,
930 930
             c2->dco_write_bytes);
931 931
     }
... ...
@@ -937,7 +951,7 @@ dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id)
937 937
 
938 938
     if (tb[OVPN_A_PEER_VPN_RX_BYTES])
939 939
     {
940
-        c2->tun_read_bytes = nla_get_u64(tb[OVPN_A_PEER_VPN_RX_BYTES]);
940
+        c2->tun_read_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_VPN_RX_BYTES]);
941 941
         msg(D_DCO_DEBUG, "%s / tun_read_bytes: " counter_format, __func__,
942 942
             c2->tun_read_bytes);
943 943
     }
... ...
@@ -949,7 +963,7 @@ dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id)
949 949
 
950 950
     if (tb[OVPN_A_PEER_VPN_TX_BYTES])
951 951
     {
952
-        c2->tun_write_bytes = nla_get_u64(tb[OVPN_A_PEER_VPN_TX_BYTES]);
952
+        c2->tun_write_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_VPN_TX_BYTES]);
953 953
         msg(D_DCO_DEBUG, "%s / tun_write_bytes: " counter_format, __func__,
954 954
             c2->tun_write_bytes);
955 955
     }
... ...
@@ -1028,12 +1042,12 @@ static int
1028 1028
 dco_parse_peer(struct nl_msg *msg, void *arg)
1029 1029
 {
1030 1030
     struct context *c = arg;
1031
-    struct nlattr *tb[OVPN_A_MAX];
1031
+    struct nlattr *tb[OVPN_A_MAX + 1];
1032 1032
     struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1033 1033
 
1034 1034
     msg(D_DCO_DEBUG, "%s: parsing message...", __func__);
1035 1035
 
1036
-    nla_parse(tb, OVPN_A_PEER_MAX, genlmsg_attrdata(gnlh, 0),
1036
+    nla_parse(tb, OVPN_A_MAX, genlmsg_attrdata(gnlh, 0),
1037 1037
               genlmsg_attrlen(gnlh, 0), NULL);
1038 1038
 
1039 1039
     if (!tb[OVPN_A_PEER])
... ...
@@ -1043,10 +1057,7 @@ dco_parse_peer(struct nl_msg *msg, void *arg)
1043 1043
     }
1044 1044
 
1045 1045
     struct nlattr *tb_peer[OVPN_A_PEER_MAX + 1];
1046
-
1047
-    nla_parse(tb_peer, OVPN_A_PEER,
1048
-              nla_data(tb[OVPN_A_PEER]),
1049
-              nla_len(tb[OVPN_A_PEER]), NULL);
1046
+    nla_parse_nested(tb_peer, OVPN_A_PEER_MAX, tb[OVPN_A_PEER], NULL);
1050 1047
 
1051 1048
     if (!tb_peer[OVPN_A_PEER_ID])
1052 1049
     {