diff --git a/src/openvpn/dco.h b/src/openvpn/dco.h index 50ebb3591fa..6be20062597 100644 --- a/src/openvpn/dco.h +++ b/src/openvpn/dco.h @@ -104,11 +104,10 @@ bool dco_check_pull_options(int msglevel, const struct options *o); /** * Initialize the DCO context * - * @param mode the instance operating mode (P2P or multi-peer) - * @param dco the context to initialize + * @param c the main instance context * @return true on success, false otherwise */ -bool ovpn_dco_init(int mode, dco_context_t *dco); +bool ovpn_dco_init(struct context *c); /** * Open/create a DCO interface @@ -169,6 +168,7 @@ int init_key_dco_bi(struct tls_multi *multi, struct key_state *ks, * recoverable and should reset the connection */ bool dco_update_keys(dco_context_t *dco, struct tls_multi *multi); + /** * Install a new peer in DCO - to be called by a CLIENT (or P2P) instance * @@ -284,7 +284,7 @@ dco_check_pull_options(int msglevel, const struct options *o) } static inline bool -ovpn_dco_init(int mode, dco_context_t *dco) +ovpn_dco_init(struct context *c) { return true; } diff --git a/src/openvpn/dco_freebsd.c b/src/openvpn/dco_freebsd.c index 13a08319a24..96b75a4d4af 100644 --- a/src/openvpn/dco_freebsd.c +++ b/src/openvpn/dco_freebsd.c @@ -220,9 +220,9 @@ close_fd(dco_context_t *dco) } bool -ovpn_dco_init(int mode, dco_context_t *dco) +ovpn_dco_init(struct context *c) { - if (open_fd(dco) < 0) + if (open_fd(&c->c1.tuntap->dco) < 0) { msg(M_ERR, "Failed to open socket"); return false; diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index b2584b973ce..45564ac8298 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -167,23 +167,19 @@ ovpn_nl_recvmsgs(dco_context_t *dco, const char *prefix) } /** - * Send a prepared netlink message and registers cb as callback if non-null. + * Send a prepared netlink message. * * The method will also free nl_msg * @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, - void *cb_arg, const char *prefix) +ovpn_nl_msg_send(dco_context_t *dco, struct nl_msg *nl_msg, const char *prefix) { dco->status = 1; - 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) @@ -274,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, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -342,6 +338,29 @@ ovpn_nl_cb_error(struct sockaddr_nl (*nla) __attribute__ ((unused)), return NL_STOP; } +static void +ovpn_dco_register(dco_context_t *dco) +{ + msg(D_DCO_DEBUG, __func__); + ovpn_get_mcast_id(dco); + + if (dco->ovpn_dco_mcast_id < 0) + { + msg(M_FATAL, "cannot get mcast group: %s", nl_geterror(dco->ovpn_dco_mcast_id)); + } + + /* Register for ovpn-dco specific multicast messages that the kernel may + * send + */ + int ret = nl_socket_add_membership(dco->nl_sock, dco->ovpn_dco_mcast_id); + if (ret) + { + msg(M_FATAL, "%s: failed to join groups: %d", __func__, ret); + } +} + +static int ovpn_handle_msg(struct nl_msg *msg, void *arg); + static void ovpn_dco_init_netlink(dco_context_t *dco) { @@ -373,11 +392,15 @@ ovpn_dco_init_netlink(dco_context_t *dco) nl_socket_set_cb(dco->nl_sock, dco->nl_cb); + dco->dco_message_peer_id = -1; nl_cb_err(dco->nl_cb, NL_CB_CUSTOM, ovpn_nl_cb_error, &dco->status); nl_cb_set(dco->nl_cb, NL_CB_FINISH, NL_CB_CUSTOM, ovpn_nl_cb_finish, &dco->status); nl_cb_set(dco->nl_cb, NL_CB_ACK, NL_CB_CUSTOM, ovpn_nl_cb_finish, &dco->status); + nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, ovpn_handle_msg, dco); + + ovpn_dco_register(dco); /* The async PACKET messages confuse libnl and it will drop them with * wrong sequence numbers (NLE_SEQ_MISMATCH), so disable libnl's sequence @@ -391,9 +414,11 @@ ovpn_dco_init_netlink(dco_context_t *dco) } bool -ovpn_dco_init(int mode, dco_context_t *dco) +ovpn_dco_init(struct context *c) { - switch (mode) + dco_context_t *dco = &c->c1.tuntap->dco; + + switch (c->mode) { case CM_TOP: dco->ifmode = OVPN_MODE_MP; @@ -406,6 +431,10 @@ ovpn_dco_init(int mode, dco_context_t *dco) default: ASSERT(false); } + /* store pointer to context as it may be required by message + * parsing routines + */ + dco->c = c; ovpn_dco_init_netlink(dco); return true; @@ -423,27 +452,6 @@ ovpn_dco_uninit_netlink(dco_context_t *dco) CLEAR(dco); } -static void -ovpn_dco_register(dco_context_t *dco) -{ - msg(D_DCO_DEBUG, __func__); - ovpn_get_mcast_id(dco); - - if (dco->ovpn_dco_mcast_id < 0) - { - msg(M_ERR, "cannot get mcast group: %s", nl_geterror(dco->ovpn_dco_mcast_id)); - } - - /* Register for ovpn-dco specific multicast messages that the kernel may - * send - */ - int ret = nl_socket_add_membership(dco->nl_sock, dco->ovpn_dco_mcast_id); - if (ret) - { - msg(M_ERR, "%s: failed to join groups: %d", __func__, ret); - } -} - int open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev) { @@ -463,10 +471,6 @@ open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev) msg(M_FATAL, "DCO: cannot retrieve ifindex for interface %s", dev); } - tt->dco.dco_message_peer_id = -1; - - ovpn_dco_register(&tt->dco); - return 0; } @@ -495,7 +499,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, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -519,7 +523,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, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -545,7 +549,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, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -602,7 +606,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, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -631,7 +635,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, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -699,7 +703,7 @@ ovpn_get_mcast_id(dco_context_t *dco) /* Even though 'nlctrl' is a constant, there seem to be no library * provided define for it */ - int ctrlid = genl_ctrl_resolve(dco->nl_sock, "nlctrl"); + dco->ctrlid = genl_ctrl_resolve(dco->nl_sock, "nlctrl"); struct nl_msg *nl_msg = nlmsg_alloc(); if (!nl_msg) @@ -707,124 +711,18 @@ ovpn_get_mcast_id(dco_context_t *dco) return -ENOMEM; } - genlmsg_put(nl_msg, 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0); + genlmsg_put(nl_msg, 0, 0, dco->ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0); 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, dco, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, __func__); nla_put_failure: nlmsg_free(nl_msg); return ret; } -/* This function parses any netlink message sent by ovpn-dco to userspace */ -static int -ovpn_handle_msg(struct nl_msg *msg, void *arg) -{ - dco_context_t *dco = arg; - - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *attrs[OVPN_ATTR_MAX + 1]; - struct nlmsghdr *nlh = nlmsg_hdr(msg); - - if (!genlmsg_valid_hdr(nlh, 0)) - { - msg(D_DCO, "ovpn-dco: invalid header"); - return NL_SKIP; - } - - if (nla_parse(attrs, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL)) - { - msg(D_DCO, "received bogus data from ovpn-dco"); - return NL_SKIP; - } - - /* we must know which interface this message is referring to in order to - * avoid mixing messages for other instances - */ - if (!attrs[OVPN_ATTR_IFINDEX]) - { - msg(D_DCO, "ovpn-dco: Received message without ifindex"); - return NL_SKIP; - } - - uint32_t ifindex = nla_get_u32(attrs[OVPN_ATTR_IFINDEX]); - if (ifindex != dco->ifindex) - { - msg(D_DCO_DEBUG, - "ovpn-dco: ignoring message (type=%d) for foreign ifindex %d", - gnlh->cmd, ifindex); - return NL_SKIP; - } - - /* based on the message type, we parse the subobject contained in the - * message, that stores the type-specific attributes. - * - * the "dco" object is then filled accordingly with the information - * retrieved from the message, so that the rest of the OpenVPN code can - * react as need be. - */ - switch (gnlh->cmd) - { - case OVPN_CMD_DEL_PEER: - { - if (!attrs[OVPN_ATTR_DEL_PEER]) - { - msg(D_DCO, "ovpn-dco: no attributes in OVPN_DEL_PEER message"); - return NL_SKIP; - } - - struct nlattr *dp_attrs[OVPN_DEL_PEER_ATTR_MAX + 1]; - if (nla_parse_nested(dp_attrs, OVPN_DEL_PEER_ATTR_MAX, - attrs[OVPN_ATTR_DEL_PEER], NULL)) - { - msg(D_DCO, "received bogus del peer packet data from ovpn-dco"); - return NL_SKIP; - } - - if (!dp_attrs[OVPN_DEL_PEER_ATTR_REASON]) - { - msg(D_DCO, "ovpn-dco: no reason in DEL_PEER message"); - return NL_SKIP; - } - if (!dp_attrs[OVPN_DEL_PEER_ATTR_PEER_ID]) - { - msg(D_DCO, "ovpn-dco: no peer-id in DEL_PEER message"); - return NL_SKIP; - } - int reason = nla_get_u8(dp_attrs[OVPN_DEL_PEER_ATTR_REASON]); - unsigned int peerid = nla_get_u32(dp_attrs[OVPN_DEL_PEER_ATTR_PEER_ID]); - - msg(D_DCO_DEBUG, "ovpn-dco: received CMD_DEL_PEER, ifindex: %d, peer-id %d, reason: %d", - ifindex, peerid, reason); - dco->dco_message_peer_id = peerid; - dco->dco_del_peer_reason = reason; - dco->dco_message_type = OVPN_CMD_DEL_PEER; - - break; - } - - default: - msg(D_DCO, "ovpn-dco: received unknown command: %d", gnlh->cmd); - dco->dco_message_type = 0; - return NL_SKIP; - } - - return NL_OK; -} - -int -dco_do_read(dco_context_t *dco) -{ - msg(D_DCO_DEBUG, __func__); - nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, ovpn_handle_msg, dco); - - return ovpn_nl_recvmsgs(dco, __func__); -} - static void dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id) { @@ -877,18 +775,21 @@ dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id) } } -int -dco_parse_peer_multi(struct nl_msg *msg, void *arg) +static int +ovpn_handle_peer_multi(dco_context_t *dco, struct nlattr *attrs[]) { - 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); + /* this function assumes openvpn is running in multipeer mode as + * it accesses c->multi + */ + if (dco->ifmode != OVPN_MODE_MP) + { + msg(M_WARN, "%s: can't parse 'multi-peer' message on P2P instance", __func__); + return NL_SKIP; + } - if (!tb[OVPN_ATTR_GET_PEER]) + if (!attrs[OVPN_ATTR_GET_PEER]) { return NL_SKIP; } @@ -896,16 +797,16 @@ dco_parse_peer_multi(struct nl_msg *msg, void *arg) 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); + nla_data(attrs[OVPN_ATTR_GET_PEER]), + nla_len(attrs[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__); + msg(M_WARN, "ovpn-dco: no peer-id provided in (MULTI) PEER_GET reply"); return NL_SKIP; } - struct multi_context *m = arg; + struct multi_context *m = dco->c->multi; uint32_t peer_id = nla_get_u32(tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]); if (peer_id >= m->max_clients || !m->instances[peer_id]) @@ -920,34 +821,12 @@ dco_parse_peer_multi(struct nl_msg *msg, void *arg) return NL_OK; } -int -dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m) -{ - 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; - - int ret = ovpn_nl_msg_send(dco, nl_msg, dco_parse_peer_multi, m, __func__); - - nlmsg_free(nl_msg); - return ret; -} - static int -dco_parse_peer(struct nl_msg *msg, void *arg) +ovpn_handle_peer(dco_context_t *dco, struct nlattr *attrs[]) { - 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]) + if (!attrs[OVPN_ATTR_GET_PEER]) { msg(D_DCO_DEBUG, "%s: malformed reply", __func__); return NL_SKIP; @@ -956,26 +835,194 @@ dco_parse_peer(struct nl_msg *msg, void *arg) 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); + nla_data(attrs[OVPN_ATTR_GET_PEER]), + nla_len(attrs[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__); + msg(M_WARN, "ovpn-dco: no peer-id provided in PEER_GET reply"); 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) + struct context_2 *c2; + + if (dco->ifmode == OVPN_MODE_P2P) + { + c2 = &dco->c->c2; + } + else + { + struct multi_instance *mi = dco->c->multi->instances[peer_id]; + if (!mi) + { + msg(M_WARN, "%s: received data for a non-existing peer %u", __func__, peer_id); + return NL_SKIP; + } + + c2 = &mi->context.c2; + } + + /* at this point this check should never fail for MP mode, + * but it's still fully valid for P2P mode + */ + if (c2->tls_multi->dco_peer_id != peer_id) { return NL_SKIP; } - dco_update_peer_stat(&c->c2, tb_peer, peer_id); + dco_update_peer_stat(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) +{ + dco_context_t *dco = arg; + + struct nlattr *attrs[OVPN_ATTR_MAX + 1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *gnlh = genlmsg_hdr(nlh); + + msg(D_DCO_DEBUG, "ovpn-dco: received netlink message type=%u cmd=%u flags=%#.4x", + nlh->nlmsg_type, gnlh->cmd, nlh->nlmsg_flags); + + /* if we get a message from the NLCTRL family, it means + * this is the reply to the mcast ID resolution request + * and we parse it accordingly. + */ + if (nlh->nlmsg_type == dco->ctrlid) + { + msg(D_DCO_DEBUG, "ovpn-dco: received CTRLID message"); + return mcast_family_handler(msg, dco); + } + + if (!genlmsg_valid_hdr(nlh, 0)) + { + msg(D_DCO, "ovpn-dco: invalid header"); + return NL_SKIP; + } + + if (nla_parse(attrs, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL)) + { + msg(D_DCO, "received bogus data from ovpn-dco"); + return NL_SKIP; + } + + /* based on the message type, we parse the subobject contained in the + * message, that stores the type-specific attributes. + * + * the "dco" object is then filled accordingly with the information + * retrieved from the message, so that the rest of the OpenVPN code can + * react as need be. + */ + switch (gnlh->cmd) + { + case OVPN_CMD_GET_PEER: + { + /* this message is part of a peer list dump, hence triggered + * by a MP/server instance + */ + if (nlh->nlmsg_flags & NLM_F_MULTI) + { + return ovpn_handle_peer_multi(dco, attrs); + } + else + { + return ovpn_handle_peer(dco, attrs); + } + } + + case OVPN_CMD_DEL_PEER: + { + /* we must know which interface this message is referring to in order to + * avoid mixing messages for other instances + */ + if (!attrs[OVPN_ATTR_IFINDEX]) + { + msg(D_DCO, "ovpn-dco: Received message without ifindex"); + return NL_SKIP; + } + + uint32_t ifindex = nla_get_u32(attrs[OVPN_ATTR_IFINDEX]); + if (ifindex != dco->ifindex) + { + msg(D_DCO_DEBUG, + "ovpn-dco: ignoring message (type=%d) for foreign ifindex %d", + gnlh->cmd, ifindex); + return NL_SKIP; + } + if (!attrs[OVPN_ATTR_DEL_PEER]) + { + msg(D_DCO, "ovpn-dco: no attributes in OVPN_DEL_PEER message"); + return NL_SKIP; + } + + struct nlattr *dp_attrs[OVPN_DEL_PEER_ATTR_MAX + 1]; + if (nla_parse_nested(dp_attrs, OVPN_DEL_PEER_ATTR_MAX, + attrs[OVPN_ATTR_DEL_PEER], NULL)) + { + msg(D_DCO, "received bogus del peer packet data from ovpn-dco"); + return NL_SKIP; + } + + if (!dp_attrs[OVPN_DEL_PEER_ATTR_REASON]) + { + msg(D_DCO, "ovpn-dco: no reason in DEL_PEER message"); + return NL_SKIP; + } + if (!dp_attrs[OVPN_DEL_PEER_ATTR_PEER_ID]) + { + msg(D_DCO, "ovpn-dco: no peer-id in DEL_PEER message"); + return NL_SKIP; + } + int reason = nla_get_u8(dp_attrs[OVPN_DEL_PEER_ATTR_REASON]); + unsigned int peerid = nla_get_u32(dp_attrs[OVPN_DEL_PEER_ATTR_PEER_ID]); + + msg(D_DCO_DEBUG, "ovpn-dco: received CMD_DEL_PEER, ifindex: %d, peer-id %d, reason: %d", + ifindex, peerid, reason); + dco->dco_message_peer_id = peerid; + dco->dco_del_peer_reason = reason; + dco->dco_message_type = OVPN_CMD_DEL_PEER; + + break; + } + + default: + msg(D_DCO, "ovpn-dco: received unknown command: %d", gnlh->cmd); + dco->dco_message_type = 0; + return NL_SKIP; + } return NL_OK; } +int +dco_do_read(dco_context_t *dco) +{ + msg(D_DCO_DEBUG, __func__); + + return ovpn_nl_recvmsgs(dco, __func__); +} + +int +dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m) +{ + 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; + + int ret = ovpn_nl_msg_send(dco, nl_msg, __func__); + + nlmsg_free(nl_msg); + return ret; +} + int dco_get_peer_stats(struct context *c) { @@ -995,7 +1042,7 @@ dco_get_peer_stats(struct context *c) 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__); + ret = ovpn_nl_msg_send(dco, nl_msg, __func__); nla_put_failure: nlmsg_free(nl_msg); diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h index 5179912b522..789954d6973 100644 --- a/src/openvpn/dco_linux.h +++ b/src/openvpn/dco_linux.h @@ -43,6 +43,9 @@ typedef struct struct nl_cb *nl_cb; int status; + struct context *c; + int ctrlid; + enum ovpn_mode ifmode; int ovpn_dco_id; diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 0b8f8319de1..bc465db6c69 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -53,7 +53,7 @@ create_dco_handle(const char *devname, struct gc_arena *gc) } bool -ovpn_dco_init(int mode, dco_context_t *dco) +ovpn_dco_init(struct context *c) { return true; } diff --git a/src/openvpn/error.h b/src/openvpn/error.h index ab2872aedce..efe0f4facdc 100644 --- a/src/openvpn/error.h +++ b/src/openvpn/error.h @@ -71,6 +71,7 @@ struct gc_arena; #ifdef _WIN32 #define openvpn_errno() GetLastError() const char *strerror_win32(DWORD errnum, struct gc_arena *gc); + #else #define openvpn_errno() errno #endif diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 1476737efbe..c2cfd240dbb 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -1882,7 +1882,7 @@ do_open_tun(struct context *c, int *error_flags) #endif if (dco_enabled(&c->options)) { - ovpn_dco_init(c->mode, &c->c1.tuntap->dco); + ovpn_dco_init(c); } /* open the tun device */ diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c index 96408d11966..18ce9a518b0 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -792,6 +792,7 @@ tunnel_server_tcp(struct context *top) int status; top->mode = CM_TOP; + top->multi = &multi; context_clear_2(top); /* initialize top-tunnel instance */ @@ -802,10 +803,10 @@ tunnel_server_tcp(struct context *top) } /* initialize global multi_context object */ - multi_init(&multi, top, true); + multi_init(top, true); /* initialize our cloned top object */ - multi_top_init(&multi, top); + multi_top_init(top); /* initialize management interface */ init_management_callback_multi(&multi); diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index 0492311669c..b21fa1039f1 100644 --- a/src/openvpn/mudp.c +++ b/src/openvpn/mudp.c @@ -466,6 +466,7 @@ tunnel_server_udp(struct context *top) struct multi_context multi; top->mode = CM_TOP; + top->multi = &multi; context_clear_2(top); /* initialize top-tunnel instance */ @@ -476,10 +477,10 @@ tunnel_server_udp(struct context *top) } /* initialize global multi_context object */ - multi_init(&multi, top, false); + multi_init(top, false); /* initialize our cloned top object */ - multi_top_init(&multi, top); + multi_top_init(top); /* initialize management interface */ init_management_callback_multi(&multi); diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 94e623ba22e..77f9649854f 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -289,8 +289,9 @@ int_compare_function(const void *key1, const void *key2) * Main initialization function, init multi_context object. */ void -multi_init(struct multi_context *m, struct context *t, bool tcp_mode) +multi_init(struct context *t, bool tcp_mode) { + struct multi_context *m = t->multi; int dev = DEV_TYPE_UNDEF; msg(D_MULTI_LOW, "MULTI: multi_init called, r=%d v=%d", @@ -3838,10 +3839,10 @@ multi_process_per_second_timers_dowork(struct multi_context *m) } void -multi_top_init(struct multi_context *m, struct context *top) +multi_top_init(struct context *top) { - inherit_context_top(&m->top, top); - m->top.c2.buffers = init_context_buffers(&top->c2.frame); + inherit_context_top(&top->multi->top, top); + top->multi->top.c2.buffers = init_context_buffers(&top->c2.frame); } void diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 7167639e869..31433555712 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -260,11 +260,11 @@ const char *multi_instance_string(const struct multi_instance *mi, bool null, st * Called by mtcp.c, mudp.c, or other (to be written) protocol drivers */ -void multi_init(struct multi_context *m, struct context *t, bool tcp_mode); +void multi_init(struct context *t, bool tcp_mode); void multi_uninit(struct multi_context *m); -void multi_top_init(struct multi_context *m, struct context *top); +void multi_top_init(struct context *top); void multi_top_free(struct multi_context *m); diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h index 9cba1c5adf3..3879772668d 100644 --- a/src/openvpn/openvpn.h +++ b/src/openvpn/openvpn.h @@ -492,6 +492,9 @@ struct context * CM_P2P, \c CM_TOP, \c CM_TOP_CLONE, * \c CM_CHILD_UDP, and \c CM_CHILD_TCP. */ + struct multi_context *multi; /**< Pointer to the main P2MP context. + * Non-NULL only when mode == CM_TOP. */ + struct gc_arena gc; /**< Garbage collection arena for * allocations done in the scope of this * context structure. */ diff --git a/src/openvpn/reflect_filter.h b/src/openvpn/reflect_filter.h index 12eb0a15116..a6107671ff4 100644 --- a/src/openvpn/reflect_filter.h +++ b/src/openvpn/reflect_filter.h @@ -72,4 +72,5 @@ initial_rate_limit_init(int max_per_period, int period_length); * free the initial-packet rate limiter structure */ void initial_rate_limit_free(struct initial_packet_rate_limit *irl); + #endif /* ifndef REFLECT_FILTER_H */ diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index 91dbeefe000..4e39aef3dca 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -755,6 +755,7 @@ tun_set(struct tuntap *tt, } const char *tun_stat(const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc); + bool tun_name_is_fixed(const char *dev); static inline bool diff --git a/src/openvpn/xkey_provider.c b/src/openvpn/xkey_provider.c index f69239dde4e..1a75262b76c 100644 --- a/src/openvpn/xkey_provider.c +++ b/src/openvpn/xkey_provider.c @@ -55,7 +55,7 @@ typedef struct do { \ dmsg(f|M_NOLF, "xkey_provider: In %s: ", __func__); \ dmsg(f|M_NOPREFIX, __VA_ARGS__); \ - } while(0) + } while (0) typedef enum { @@ -597,7 +597,7 @@ static const OSSL_DISPATCH rsa_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, {OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))keymgmt_get_params}, {OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))keymgmt_set_params}, - {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, /* same as gettable */ + {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, /* same as gettable */ {OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))rsa_keymgmt_name}, {0, NULL } }; @@ -613,7 +613,7 @@ static const OSSL_DISPATCH ec_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, {OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))keymgmt_get_params}, {OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))keymgmt_set_params}, - {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, /* same as gettable */ + {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, /* same as gettable */ {OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))ec_keymgmt_name}, {0, NULL } }; @@ -629,7 +629,7 @@ static const OSSL_DISPATCH ed448_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, {OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))keymgmt_get_params}, {OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))keymgmt_set_params}, - {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, /* same as gettable */ + {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, /* same as gettable */ {0, NULL } }; @@ -644,7 +644,7 @@ static const OSSL_DISPATCH ed25519_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, {OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))keymgmt_get_params}, {OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))keymgmt_set_params}, - {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, /* same as gettable */ + {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))keymgmt_gettable_params}, /* same as gettable */ {0, NULL } };