diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index a5f9e06c..3f7965e6 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -908,12 +908,26 @@ dco_do_read(dco_context_t *dco) return ovpn_nl_recvmsgs(dco, __func__); } +/* libnl < 3.11.0 does not implement nla_get_uint() */ +static uint64_t +ovpn_nla_get_uint(struct nlattr *attr) +{ + if (nla_len(attr) == sizeof(uint32_t)) + { + return nla_get_u32(attr); + } + else + { + return nla_get_u64(attr); + } +} + static void dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id) { if (tb[OVPN_A_PEER_LINK_RX_BYTES]) { - c2->dco_read_bytes = nla_get_u64(tb[OVPN_A_PEER_LINK_RX_BYTES]); + c2->dco_read_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_LINK_RX_BYTES]); msg(D_DCO_DEBUG, "%s / dco_read_bytes: " counter_format, __func__, c2->dco_read_bytes); } @@ -925,7 +939,7 @@ dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id) if (tb[OVPN_A_PEER_LINK_TX_BYTES]) { - c2->dco_write_bytes = nla_get_u64(tb[OVPN_A_PEER_LINK_TX_BYTES]); + c2->dco_write_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_LINK_TX_BYTES]); msg(D_DCO_DEBUG, "%s / dco_write_bytes: " counter_format, __func__, c2->dco_write_bytes); } @@ -937,7 +951,7 @@ dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id) if (tb[OVPN_A_PEER_VPN_RX_BYTES]) { - c2->tun_read_bytes = nla_get_u64(tb[OVPN_A_PEER_VPN_RX_BYTES]); + c2->tun_read_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_VPN_RX_BYTES]); msg(D_DCO_DEBUG, "%s / tun_read_bytes: " counter_format, __func__, c2->tun_read_bytes); } @@ -949,7 +963,7 @@ dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id) if (tb[OVPN_A_PEER_VPN_TX_BYTES]) { - c2->tun_write_bytes = nla_get_u64(tb[OVPN_A_PEER_VPN_TX_BYTES]); + c2->tun_write_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_VPN_TX_BYTES]); msg(D_DCO_DEBUG, "%s / tun_write_bytes: " counter_format, __func__, c2->tun_write_bytes); } @@ -1028,12 +1042,12 @@ static int dco_parse_peer(struct nl_msg *msg, void *arg) { struct context *c = arg; - struct nlattr *tb[OVPN_A_MAX]; + struct nlattr *tb[OVPN_A_MAX + 1]; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); msg(D_DCO_DEBUG, "%s: parsing message...", __func__); - nla_parse(tb, OVPN_A_PEER_MAX, genlmsg_attrdata(gnlh, 0), + nla_parse(tb, OVPN_A_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (!tb[OVPN_A_PEER]) @@ -1043,10 +1057,7 @@ dco_parse_peer(struct nl_msg *msg, void *arg) } struct nlattr *tb_peer[OVPN_A_PEER_MAX + 1]; - - nla_parse(tb_peer, OVPN_A_PEER, - nla_data(tb[OVPN_A_PEER]), - nla_len(tb[OVPN_A_PEER]), NULL); + nla_parse_nested(tb_peer, OVPN_A_PEER_MAX, tb[OVPN_A_PEER], NULL); if (!tb_peer[OVPN_A_PEER_ID]) {