@@ -812,6 +812,150 @@
return false;
}
+/* 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 = 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);
+ }
+ else
+ {
+ msg(M_WARN, "%s: no link RX bytes provided in reply for peer %u",
+ __func__, id);
+ }
+
+ if (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);
+ }
+ else
+ {
+ msg(M_WARN, "%s: no link TX bytes provided in reply for peer %u",
+ __func__, id);
+ }
+
+ if (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);
+ }
+ else
+ {
+ msg(M_WARN, "%s: no VPN RX bytes provided in reply for peer %u",
+ __func__, id);
+ }
+
+ if (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);
+ }
+ else
+ {
+ msg(M_WARN, "%s: no VPN TX bytes provided in reply for peer %u",
+ __func__, id);
+ }
+}
+
+static int
+dco_parse_peer_multi(struct nl_msg *msg, void *arg)
+{
+ 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_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (!tb[OVPN_A_PEER])
+ {
+ return NL_SKIP;
+ }
+
+ struct nlattr *tb_peer[OVPN_A_PEER_MAX + 1];
+ nla_parse_nested(tb_peer, OVPN_A_PEER_MAX, tb[OVPN_A_PEER], NULL);
+
+ if (!tb_peer[OVPN_A_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_A_PEER_ID]);
+
+ if (peer_id >= m->max_clients || !m->instances[peer_id])
+ {
+ msg(M_WARN, "%s: cannot store DCO stats for peer %u", __func__,
+ peer_id);
+ return NL_SKIP;
+ }
+
+ dco_update_peer_stat(&m->instances[peer_id]->context.c2, tb_peer, peer_id);
+
+ return NL_OK;
+}
+
+static int
+dco_parse_peer(struct nl_msg *msg, void *arg)
+{
+ struct context *c = arg;
+ 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_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (!tb[OVPN_A_PEER])
+ {
+ msg(D_DCO_DEBUG, "%s: malformed reply", __func__);
+ return NL_SKIP;
+ }
+
+ struct nlattr *tb_peer[OVPN_A_PEER_MAX + 1];
+ nla_parse_nested(tb_peer, OVPN_A_PEER_MAX, tb[OVPN_A_PEER], NULL);
+
+ if (!tb_peer[OVPN_A_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_A_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;
+}
+
/* This function parses any netlink message sent by ovpn-dco to userspace */
static int
ovpn_handle_msg(struct nl_msg *msg, void *arg)
@@ -994,112 +1138,6 @@
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 = 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);
- }
- else
- {
- msg(M_WARN, "%s: no link RX bytes provided in reply for peer %u",
- __func__, id);
- }
-
- if (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);
- }
- else
- {
- msg(M_WARN, "%s: no link TX bytes provided in reply for peer %u",
- __func__, id);
- }
-
- if (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);
- }
- else
- {
- msg(M_WARN, "%s: no VPN RX bytes provided in reply for peer %u",
- __func__, id);
- }
-
- if (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);
- }
- 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_A_MAX + 1];
- struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
-
- msg(D_DCO_DEBUG, "%s: parsing message...", __func__);
-
- nla_parse(tb, OVPN_A_MAX, genlmsg_attrdata(gnlh, 0),
- genlmsg_attrlen(gnlh, 0), NULL);
-
- if (!tb[OVPN_A_PEER])
- {
- return NL_SKIP;
- }
-
- struct nlattr *tb_peer[OVPN_A_PEER_MAX + 1];
- nla_parse_nested(tb_peer, OVPN_A_PEER_MAX, tb[OVPN_A_PEER], NULL);
-
- if (!tb_peer[OVPN_A_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_A_PEER_ID]);
-
- if (peer_id >= m->max_clients || !m->instances[peer_id])
- {
- msg(M_WARN, "%s: cannot store DCO stats for peer %u", __func__,
- peer_id);
- return NL_SKIP;
- }
-
- dco_update_peer_stat(&m->instances[peer_id]->context.c2, tb_peer, peer_id);
-
- return NL_OK;
-}
-
int
dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m,
const bool raise_sigusr1_on_err)
@@ -1124,44 +1162,6 @@
return ret;
}
-static int
-dco_parse_peer(struct nl_msg *msg, void *arg)
-{
- struct context *c = arg;
- 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_MAX, genlmsg_attrdata(gnlh, 0),
- genlmsg_attrlen(gnlh, 0), NULL);
-
- if (!tb[OVPN_A_PEER])
- {
- msg(D_DCO_DEBUG, "%s: malformed reply", __func__);
- return NL_SKIP;
- }
-
- struct nlattr *tb_peer[OVPN_A_PEER_MAX + 1];
- nla_parse_nested(tb_peer, OVPN_A_PEER_MAX, tb[OVPN_A_PEER], NULL);
-
- if (!tb_peer[OVPN_A_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_A_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, const bool raise_sigusr1_on_err)
{