From patchwork Fri Oct 17 20:19:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 4514 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:7d42:b0:72f:f16c:e055 with SMTP id fr2csp4734707mab; Fri, 17 Oct 2025 13:19:29 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCUq+pDUEi1nLiCv85HxzyyZfeeHbRValZUXE3XR866PgBDabLh9Asq1eT9g4Yk5i/iEQuI00/lsowc=@openvpn.net X-Google-Smtp-Source: AGHT+IG7sNi331uMch8b7myy5YrqNpmXNVJiquLqqgK8qSEfx1HK9fXsfzIHblcpfb7EM3juycck X-Received: by 2002:a05:6870:2401:b0:375:dc31:4a9 with SMTP id 586e51a60fabf-3c98d11ed7emr2141079fac.33.1760732369067; Fri, 17 Oct 2025 13:19:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1760732369; cv=none; d=google.com; s=arc-20240605; b=GAH1+jMn6efnS2urHeF5WvZIsST90wctRB2YIaDGxToqXBH3Cj8+/y1Fs05virUHfX FdTRX/EFtXXFe397gTAveOb6G/IkyI7o6wJcu2YuPwP/w2K45SBKcla+XcB/Z7qmZ4Zl H9UR5pNDadLaWThC1FbXU/UGP3dmlJN+p8QNX5NRATlrlv4JXdCxAipx8yJqOvGBhG91 /Dp1OCd8qg035C2HagsxW7qJZWl9xD8OuagDUei0eGTGYt4rQnCvPJxl+4m/cL9WyDir fD2rEFhUYg7X8FXIAhWCcdHJ2kqn3RKFdi7me7YonXgTkUyXP/4Lgliy5zuzA00hNYsm XNMg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:content-transfer-encoding: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=kt0B8y75wlrEH3gwepsrdzI1O8LP/tPmQ7yzV7KX1/E=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=geX8JB52MsgG0ifbtN5jZ/KsigykeJlRrYSxlZAEjaaF4HGXcYUdrqTKaYsLHPZKY9 9zO80fMuAW4AImOJpPYxjIJBwOgY0didkooaYPwJXGGZ00cJdXzurSI49NTpAPG3XPs0 T1+pcuhYydfStVsa8VGLoIQjTTskxPHauEc5ph6NqKw8nV0qutetLSzl/susYJi1wswm p4VroV18rEmfXXKicd1RQFbtd2IfcVDWYr65IrB7BrSPFESFUFDEdyrCeY1sKzS13omD W1jYgXVRaHLqQAnBlrxcOisuO9ZJWQkUrvpBcjuicEKk7xSCAhaiht9pLpYS3vAjnkIj OwfA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=T+gJpREK; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=jNREVvEq; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=Eo4016V6; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 586e51a60fabf-3c9af37875bsi143895fac.380.2025.10.17.13.19.28 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 17 Oct 2025 13:19:29 -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=pass header.i=@lists.sourceforge.net header.s=beta header.b=T+gJpREK; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=jNREVvEq; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=Eo4016V6; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=kt0B8y75wlrEH3gwepsrdzI1O8LP/tPmQ7yzV7KX1/E=; b=T+gJpREKMd3skk33bC61AxYmEn 9AEdLLCY3n/q4zk/hCOS3dg9ajUdqQ48t62XIFVqRztm1Ik/OBpikpJ0O+klVDJQWzZKiJq4eV8To xNcvWRwPc7+Vq33wezuWy9zSXxoKeRg5hClpXA7mWeQPD8WdD8/ktKiXPTitAmc5Jr/c=; Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1v9qv8-0001s4-8H; Fri, 17 Oct 2025 20:19:27 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1v9qv7-0001rq-14 for openvpn-devel@lists.sourceforge.net; Fri, 17 Oct 2025 20:19:25 +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:To:From:Sender:Reply-To:Cc: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=aeLsYvaC89cryYK7bklldKVj+0InKeCAtXpo0QxixBw=; b=jNREVvEq3H2X9AkhMVFkaiP68/ ku9fUuBuUVl05AQlJcB6gOURR3So1TKs8A/zOOYKuIQw1beJ3Qji4cQKULNh+IlKr9mAvSh6meI/G X4gSd+qZvmG+cLHcgCx8sZEo236GEur37KGN+BwYHnQBjRzSnXsfF60z8tyFa6Pb43fs=; 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:To:From:Sender:Reply-To:Cc: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=aeLsYvaC89cryYK7bklldKVj+0InKeCAtXpo0QxixBw=; b=Eo4016V6JjMIHWMO4Mvp7KDKSS Jicg8rLtFtadAUibEg5XUXDMOgnbAVvX37EFvgRl47jP4+0pCL1xXOT7VtrnCU7z/pLXeLzKYL1Kh X6Dd+uFhEDGo1B1V8C+I7WTw5F1pgFTdtKsQAAlMhRxdbeL0SBVLqt7tffAcUA+5p11c=; Received: from [193.149.48.134] (helo=blue.greenie.muc.de) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1v9qv6-0004uV-5u for openvpn-devel@lists.sourceforge.net; Fri, 17 Oct 2025 20:19:25 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.18.1/8.18.1) with ESMTP id 59HKJHa6021711 for ; Fri, 17 Oct 2025 22:19:17 +0200 Received: (from gert@localhost) by blue.greenie.muc.de (8.18.1/8.18.1/Submit) id 59HKJHip021710 for openvpn-devel@lists.sourceforge.net; Fri, 17 Oct 2025 22:19:17 +0200 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Fri, 17 Oct 2025 22:19:12 +0200 Message-ID: <20251017201916.21697-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.49.1 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-2.hosts.colo.sdot.me", 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: From: Marco Baffo When sending a PUSH_UPDATE containing an ifconfig(-ipv6) option, we must add the new IP to the multi_context vhash (hash table of the clients indexed by virtual IPs). Now in addition to adding new cli [...] Content analysis details: (1.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-Headers-End: 1v9qv6-0004uV-5u Subject: [Openvpn-devel] [PATCH v7] PUSH_UPDATE server: remove old IP(s) from vhash after sending a message containing ifconfig(-ipv6) 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: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1845857904315360005?= X-GMAIL-MSGID: =?utf-8?q?1846261704579503344?= From: Marco Baffo When sending a PUSH_UPDATE containing an ifconfig(-ipv6) option, we must add the new IP to the multi_context vhash (hash table of the clients indexed by virtual IPs). Now in addition to adding new client IPs, old IPs are also removed from vhash, allowing for a more complete update. Change-Id: I07a8ddd9026eef64b6f5abde98702a9801616a5f Signed-off-by: Marco Baffo Acked-by: Gert Doering Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1253 --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1253 This mail reflects revision 7 of this Change. Acked-by according to Gerrit (reflected above): Gert Doering diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 2863ff1..558314c 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -4269,46 +4269,144 @@ close_instance(top); } +/* Searches for the address and deletes it if it is owned by the multi_instance */ +static void +multi_unlearn_addr(struct multi_context *m, struct multi_instance *mi, const struct mroute_addr *addr) +{ + struct hash_element *he; + const uint32_t hv = hash_value(m->vhash, addr); + struct hash_bucket *bucket = hash_bucket(m->vhash, hv); + struct multi_route *r = NULL; + + /* if route currently exists, get the instance which owns it */ + he = hash_lookup_fast(m->vhash, bucket, addr, hv); + if (he) + { + r = (struct multi_route *)he->value; + } + + /* if the route does not exist or exists but is not owned by the current instance, return */ + if (!r || r->instance != mi) + { + return; + } + + struct gc_arena gc = gc_new(); + msg(D_MULTI_LOW, "MULTI: Unlearn: %s -> %s", mroute_addr_print(&r->addr, &gc), multi_instance_string(mi, false, &gc)); + learn_address_script(m, NULL, "delete", &r->addr); + hash_remove_by_value(m->vhash, r); + multi_route_del(r); + + gc_free(&gc); +} + +/** + * @param m The multi_context + * @param mi The multi_instance of the client we are updating + * @param a The new IPv4 address in network byte order + */ +static void +multi_unlearn_in_addr_t(struct multi_context *m, struct multi_instance *mi, in_addr_t a) +{ + struct mroute_addr addr; + CLEAR(addr); + + addr.type = MR_ADDR_IPV4; + addr.len = 4; + addr.v4.addr = a; + + multi_unlearn_addr(m, mi, &addr); +} + +/** + * @param m The multi_context + * @param mi The multi_instance of the client we are updating + * @param a6 The new IPv6 address + */ +static void +multi_unlearn_in6_addr(struct multi_context *m, struct multi_instance *mi, struct in6_addr a6) +{ + struct mroute_addr addr; + CLEAR(addr); + + addr.type = MR_ADDR_IPV6; + addr.len = 16; + addr.v6.addr = a6; + + multi_unlearn_addr(m, mi, &addr); +} + +/* Function to unlearn previous ifconfig of a client in the server multi_context after a PUSH_UPDATE */ +void +unlearn_ifconfig(struct multi_context *m, struct multi_instance *mi) +{ + in_addr_t old_addr = 0; + old_addr = htonl(mi->context.c2.push_ifconfig_local); + multi_unlearn_in_addr_t(m, mi, old_addr); + mi->context.c2.push_ifconfig_defined = false; + mi->context.c2.push_ifconfig_local = 0; +} + +/* Function to unlearn previous ifconfig-ipv6 of a client in the server multi_context after a PUSH_UPDATE */ +void +unlearn_ifconfig_ipv6(struct multi_context *m, struct multi_instance *mi) +{ + struct in6_addr old_addr6; + CLEAR(old_addr6); + old_addr6 = mi->context.c2.push_ifconfig_ipv6_local; + multi_unlearn_in6_addr(m, mi, old_addr6); + mi->context.c2.push_ifconfig_ipv6_defined = false; + CLEAR(mi->context.c2.push_ifconfig_ipv6_local); +} + /** * Update the vhash with new IP/IPv6 addresses in the multi_context when a * push-update message containing ifconfig/ifconfig-ipv6 options is sent - * from the server. This function should be called after a push-update - * and old_ip/old_ipv6 are the previous addresses of the client in - * ctx->options.ifconfig_local and ctx->options.ifconfig_ipv6_local. + * from the server. + * + * @param m The multi_context + * @param mi The multi_instance of the client we are updating + * @param new_ip The new IPv4 address or NULL if no change + * @param new_ipv6 The new IPv6 address or NULL if no change */ void -update_vhash(struct multi_context *m, struct multi_instance *mi, const char *old_ip, const char *old_ipv6) +update_vhash(struct multi_context *m, struct multi_instance *mi, const char *new_ip, const char *new_ipv6) { - struct in_addr addr; - struct in6_addr new_ipv6; - - if ((mi->context.options.ifconfig_local && (!old_ip || strcmp(old_ip, mi->context.options.ifconfig_local))) - && inet_pton(AF_INET, mi->context.options.ifconfig_local, &addr) == 1) + if (new_ip) { - in_addr_t new_ip = ntohl(addr.s_addr); + /* Remove old IP */ + if (mi->context.c2.push_ifconfig_defined) + { + unlearn_ifconfig(m, mi); + } /* Add new IP */ - multi_learn_in_addr_t(m, mi, new_ip, -1, true); + struct in_addr new_addr; + CLEAR(new_addr); + if (inet_pton(AF_INET, new_ip, &new_addr) == 1 + && multi_learn_in_addr_t(m, mi, ntohl(new_addr.s_addr), -1, true)) + { + mi->context.c2.push_ifconfig_defined = true; + mi->context.c2.push_ifconfig_local = ntohl(new_addr.s_addr); + } } - /* TO DO: - * else if (old_ip) - * { - * // remove old IP - * } - */ - - if ((mi->context.options.ifconfig_ipv6_local && (!old_ipv6 || strcmp(old_ipv6, mi->context.options.ifconfig_ipv6_local))) - && inet_pton(AF_INET6, mi->context.options.ifconfig_ipv6_local, &new_ipv6) == 1) + if (new_ipv6) { - /* Add new IPv6 */ - multi_learn_in6_addr(m, mi, new_ipv6, -1, true); - } + /* Remove old IPv6 */ + if (mi->context.c2.push_ifconfig_ipv6_defined) + { + unlearn_ifconfig_ipv6(m, mi); + } - /* TO DO: - * else if (old_ipv6) - * { - * // remove old IPv6 - * } - */ + /* Add new IPv6 */ + struct in6_addr new_addr6; + CLEAR(new_addr6); + if (inet_pton(AF_INET6, new_ipv6, &new_addr6) == 1 + && multi_learn_in6_addr(m, mi, new_addr6, -1, true)) + { + mi->context.c2.push_ifconfig_ipv6_defined = true; + mi->context.c2.push_ifconfig_ipv6_local = new_addr6; + } + } } diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index b2b892b..97bbc4a 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -692,6 +692,8 @@ #endif void -update_vhash(struct multi_context *m, struct multi_instance *mi, const char *old_ip, const char *old_ipv6); +update_vhash(struct multi_context *m, struct multi_instance *mi, const char *new_ip, const char *new_ipv6); +void unlearn_ifconfig(struct multi_context *m, struct multi_instance *mi); +void unlearn_ifconfig_ipv6(struct multi_context *m, struct multi_instance *mi); #endif /* MULTI_H */ diff --git a/src/openvpn/push.c b/src/openvpn/push.c index 0c8eb84..2c717c7 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -1118,7 +1118,7 @@ " To be able to process PUSH_UPDATE messages, be sure to use the --disable-dco option."); return PUSH_MSG_ERROR; } - return process_incoming_push_update(c, permission_mask, option_types_found, &buf, false); + return process_push_update(c, &c->options, permission_mask, option_types_found, &buf, false); } else { diff --git a/src/openvpn/push.h b/src/openvpn/push.h index 6b3275e..19a029a 100644 --- a/src/openvpn/push.h +++ b/src/openvpn/push.h @@ -61,11 +61,13 @@ * message has not yet been received. * * @param c The context for the operation. + * @param o The options structure to be updated with the received push options. * @param permission_mask The permission mask specifying which options are allowed to be pulled. * @param option_types_found A pointer to a variable that will be filled with the types of options * found in the message. * @param buf A buffer containing the received message. - * @param msg_sender A boolean indicating if function is called by the message sender (server). + * @param msg_sender A boolean indicating if the message is being processed on the client (false) + * or on the server (true). * * @return * - `PUSH_MSG_UPDATE`: The message was processed successfully, and the updates were applied. @@ -74,9 +76,8 @@ * - `PUSH_MSG_ERROR`: An error occurred during message processing, or the message is invalid. */ -int process_incoming_push_update(struct context *c, unsigned int permission_mask, - unsigned int *option_types_found, struct buffer *buf, - bool msg_sender); +int process_push_update(struct context *c, struct options *o, unsigned int permission_mask, + unsigned int *option_types_found, struct buffer *buf, bool msg_sender); int process_incoming_push_msg(struct context *c, const struct buffer *buffer, bool honor_received_options, unsigned int permission_mask, diff --git a/src/openvpn/push_util.c b/src/openvpn/push_util.c index 25c6ebe..0e86ad3 100644 --- a/src/openvpn/push_util.c +++ b/src/openvpn/push_util.c @@ -16,18 +16,17 @@ #endif int -process_incoming_push_update(struct context *c, unsigned int permission_mask, - unsigned int *option_types_found, struct buffer *buf, - bool msg_sender) +process_push_update(struct context *c, struct options *o, unsigned int permission_mask, + unsigned int *option_types_found, struct buffer *buf, bool msg_sender) { int ret = PUSH_MSG_ERROR; const uint8_t ch = buf_read_u8(buf); if (ch == ',') { - if (apply_push_options(c, &c->options, buf, permission_mask, option_types_found, c->c2.es, + if (apply_push_options(c, o, buf, permission_mask, option_types_found, c->c2.es, true)) { - switch (c->options.push_continuation) + switch (o->push_continuation) { case 0: case 1: @@ -144,13 +143,27 @@ /* send the message(s) prepared to one single client */ static bool -send_single_push_update(struct context *c, struct buffer *msgs, unsigned int *option_types_found) +send_single_push_update(struct multi_context *m, struct multi_instance *mi, struct buffer *msgs) { if (!msgs[0].data || !*(msgs[0].data)) { return false; } + int i = -1; + unsigned int option_types_found = 0; + struct context *c = &mi->context; + struct options o; + CLEAR(o); + + /* Set canary values to detect ifconfig options in push-update messages. + * These placeholder strings will be overwritten to NULL by the option + * parser if -ifconfig or -ifconfig-ipv6 options are present in the + * push-update. + */ + const char *canary = "canary"; + o.ifconfig_local = canary; + o.ifconfig_ipv6_local = canary; while (msgs[++i].data && *(msgs[i].data)) { @@ -159,14 +172,14 @@ return false; } - /* After sending the control message, we update the options - * server-side in the client's context so pushed options like - * ifconfig/ifconfig-ipv6 can actually work. + /* After sending the control message, we parse it, miming the behavior + * of `process_incoming_push_msg()` and we fill an empty `options` struct + * with the new options. If an `ifconfig_local` or `ifconfig_ipv6_local` + * options is found we update the vhash accordingly, so that the pushed + * ifconfig/ifconfig-ipv6 options can actually work. * If we don't do that, packets arriving from the client with the * new address will be rejected and packets for the new address * will not be routed towards the client. - * For the same reason we later update the vhash too in - * `send_push_update()` function. * Using `buf_string_compare_advance()` we mimic the behavior * inside `process_incoming_push_msg()`. However, we don't need * to check the return value here because we just want to `advance`, @@ -176,17 +189,39 @@ */ struct buffer tmp_msg = msgs[i]; buf_string_compare_advance(&tmp_msg, push_update_cmd); - if (process_incoming_push_update(c, pull_permission_mask(c), option_types_found, &tmp_msg, true) == PUSH_MSG_ERROR) + unsigned int permission_mask = pull_permission_mask(c); + if (process_push_update(c, &o, permission_mask, &option_types_found, &tmp_msg, true) == PUSH_MSG_ERROR) { msg(M_WARN, "Failed to process push update message sent to client ID: %u", c->c2.tls_multi->peer_id); - continue; - } - c->options.push_option_types_found |= *option_types_found; - if (!options_postprocess_pull(&c->options, c->c2.es)) - { - msg(M_WARN, "Failed to post-process push update message sent to client ID: %u", c->c2.tls_multi->peer_id); } } + + if (option_types_found & OPT_P_UP) + { + /* -ifconfig */ + if (!o.ifconfig_local && mi->context.c2.push_ifconfig_defined) + { + unlearn_ifconfig(m, mi); + } + /* -ifconfig-ipv6 */ + if (!o.ifconfig_ipv6_local && mi->context.c2.push_ifconfig_ipv6_defined) + { + unlearn_ifconfig_ipv6(m, mi); + } + + if (o.ifconfig_local && !strcmp(o.ifconfig_local, canary)) + { + o.ifconfig_local = NULL; + } + if (o.ifconfig_ipv6_local && !strcmp(o.ifconfig_ipv6_local, canary)) + { + o.ifconfig_ipv6_local = NULL; + } + + /* new ifconfig or new ifconfig-ipv6 */ + update_vhash(m, mi, o.ifconfig_local, o.ifconfig_ipv6_local); + } + return true; } @@ -229,8 +264,6 @@ int msgs_num = (strlen(msg) / safe_cap) + ((strlen(msg) % safe_cap) != 0); struct buffer *msgs = gc_malloc((msgs_num + 1) * sizeof(struct buffer), true, &gc); - unsigned int option_types_found = 0; - msgs[msgs_num].data = NULL; if (!message_splitter(msg, msgs, &gc, safe_cap)) { @@ -255,15 +288,9 @@ return 0; } - const char *old_ip = mi->context.options.ifconfig_local; - const char *old_ipv6 = mi->context.options.ifconfig_ipv6_local; if (!mi->halt - && send_single_push_update(&mi->context, msgs, &option_types_found)) + && send_single_push_update(m, mi, msgs)) { - if (option_types_found & OPT_P_UP) - { - update_vhash(m, mi, old_ip, old_ipv6); - } gc_free(&gc); return 1; } @@ -289,18 +316,11 @@ } /* Type is UPT_BROADCAST so we update every client */ - option_types_found = 0; - const char *old_ip = curr_mi->context.options.ifconfig_local; - const char *old_ipv6 = curr_mi->context.options.ifconfig_ipv6_local; - if (!send_single_push_update(&curr_mi->context, msgs, &option_types_found)) + if (!send_single_push_update(m, curr_mi, msgs)) { msg(M_CLIENT, "ERROR: Peer ID: %u has not been updated", curr_mi->context.c2.tls_multi->peer_id); continue; } - if (option_types_found & OPT_P_UP) - { - update_vhash(m, curr_mi, old_ip, old_ipv6); - } count++; } diff --git a/tests/unit_tests/openvpn/test_push_update_msg.c b/tests/unit_tests/openvpn/test_push_update_msg.c index 60596ed..7fadb69 100644 --- a/tests/unit_tests/openvpn/test_push_update_msg.c +++ b/tests/unit_tests/openvpn/test_push_update_msg.c @@ -29,7 +29,19 @@ } void -update_vhash(struct multi_context *m, struct multi_instance *mi, const char *old_ip, const char *old_ipv6) +unlearn_ifconfig(struct multi_context *m, struct multi_instance *mi) +{ + return; +} + +void +unlearn_ifconfig_ipv6(struct multi_context *m, struct multi_instance *mi) +{ + return; +} + +void +update_vhash(struct multi_context *m, struct multi_instance *mi, const char *new_ip, const char *new_ipv6) { return; } @@ -95,7 +107,7 @@ } else if (honor_received_options && buf_string_compare_advance(&buf, push_update_cmd)) { - return process_incoming_push_update(c, permission_mask, option_types_found, &buf, false); + return process_push_update(c, &c->options, permission_mask, option_types_found, &buf, false); } else {