From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: passt.top; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=An9ja1h/; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by passt.top (Postfix) with ESMTPS id 5AEDD5A068E for ; Mon, 15 Dec 2025 02:55:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1765763701; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=IUXCpj4fL7h2yIRwznjGjUcOyImh+dEGTfAE0hpb0AM=; b=An9ja1h/FN//zjG2n351VOqpTVREzOvL2+Tm42kKu/ckel+/vz7uyD9inSNZ9UXWZPgil7 QmZPKuT1kRu/+YucABlpNwbdKukVFaiVleUeCe2hYc4TbovRK0eQw2yWMSZQd0fHjVWkdm wtctsXgRHY4iqcPqY+3ZYGIav3zHil8= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-464-QvLGQZ_UPSiIbVMlckMLgQ-1; Sun, 14 Dec 2025 20:54:58 -0500 X-MC-Unique: QvLGQZ_UPSiIbVMlckMLgQ-1 X-Mimecast-MFC-AGG-ID: QvLGQZ_UPSiIbVMlckMLgQ_1765763697 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 482861956061; Mon, 15 Dec 2025 01:54:57 +0000 (UTC) Received: from jmaloy-thinkpadp16vgen1.rmtcaqc.csb (unknown [10.22.88.123]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 51E4B30001A2; Mon, 15 Dec 2025 01:54:56 +0000 (UTC) From: Jon Maloy To: sbrivio@redhat.com, dgibson@redhat.com, david@gibson.dropbear.id.au, jmaloy@redhat.com, passt-dev@passt.top Subject: [RFC 11/12] netlink: Prevent host route events from overwriting guest-configured gateway Date: Sun, 14 Dec 2025 20:54:40 -0500 Message-ID: <20251215015441.887736-12-jmaloy@redhat.com> In-Reply-To: <20251215015441.887736-1-jmaloy@redhat.com> References: <20251215015441.887736-1-jmaloy@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: BjBjkvQO81tVJExjXYN3edbQPyZKwWKpdsaZ3PFreHU_1765763697 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true Message-ID-Hash: AWRE3OH5SEDDF623BJ2ZZBK5N4Y5YTB3 X-Message-ID-Hash: AWRE3OH5SEDDF623BJ2ZZBK5N4Y5YTB3 X-MailFrom: jmaloy@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: We add a new context flag 'guest_gw_from_ns' to track if the gateway was configured from the guest side, something that might have happened either via the -g option or by a namespace-side netlink event. When set, host side route events will not be permitted to overwrite the guest's gateway configuration. This gives any gateway setting from the guest side precedence over any ditto coming from the host side. Signed-off-by: Jon Maloy --- conf.c | 2 ++ netlink.c | 15 +++++++++++++-- passt.h | 4 ++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/conf.c b/conf.c index 0a4a28a..f26637c 100644 --- a/conf.c +++ b/conf.c @@ -1891,6 +1891,7 @@ void conf(struct ctx *c, int argc, char **argv) !IN6_IS_ADDR_LOOPBACK(&c->ip6.guest_gw)) { if (c->mode == MODE_PASTA) c->ip6.no_copy_routes = true; + c->ip6.guest_gw_from_ns = true; break; } @@ -1900,6 +1901,7 @@ void conf(struct ctx *c, int argc, char **argv) !IN4_IS_ADDR_LOOPBACK(&c->ip4.guest_gw)) { if (c->mode == MODE_PASTA) c->ip4.no_copy_routes = true; + c->ip4.guest_gw_from_ns = true; break; } diff --git a/netlink.c b/netlink.c index d049239..de04fb7 100644 --- a/netlink.c +++ b/netlink.c @@ -490,6 +490,9 @@ static void nl_linkaddr_host_msg_read(struct ctx *c, const struct nlmsghdr *nh) if (rtm->rtm_family == AF_INET) { char buf[INET_ADDRSTRLEN]; + if (c->ip4.guest_gw_from_ns) + return; + if (!is_new) { c->ip4.guest_gw = (struct in_addr){ 0 }; c->ip4.our_tap_addr = (struct in_addr){ 0 }; @@ -503,6 +506,9 @@ static void nl_linkaddr_host_msg_read(struct ctx *c, const struct nlmsghdr *nh) } else if (rtm->rtm_family == AF_INET6) { char buf[INET6_ADDRSTRLEN]; + if (c->ip6.guest_gw_from_ns) + return; + if (!is_new) { c->ip6.guest_gw = (struct in6_addr){ 0 }; return; @@ -658,15 +664,20 @@ static void nl_linkaddr_msg_read(struct ctx *c, const struct nlmsghdr *nh) if (is_new) { c->ip4.guest_gw = *(struct in_addr *)gw; c->ip4.our_tap_addr = c->ip4.guest_gw; + c->ip4.guest_gw_from_ns = true; } else { c->ip4.guest_gw = (struct in_addr){ 0 }; c->ip4.our_tap_addr = (struct in_addr){ 0 }; + c->ip4.guest_gw_from_ns = false; } } else if (rtm->rtm_family == AF_INET6) { - if (is_new) + if (is_new) { c->ip6.guest_gw = *(struct in6_addr *)gw; - else + c->ip6.guest_gw_from_ns = true; + } else { c->ip6.guest_gw = (struct in6_addr){ 0 }; + c->ip6.guest_gw_from_ns = false; + } } } } diff --git a/passt.h b/passt.h index 70ccaf1..5e7bc99 100644 --- a/passt.h +++ b/passt.h @@ -82,6 +82,7 @@ enum passt_modes { * @ifname_out: Optional interface name to bind outbound sockets to * @no_copy_routes: Don't copy all routes when configuring target namespace * @no_copy_addrs: Don't copy all addresses when configuring namespace + * @guest_gw_from_ns: Gateway was set from namespace (config or ns event) */ struct ip4_ctx { /* PIF_TAP addresses */ @@ -104,6 +105,7 @@ struct ip4_ctx { bool no_copy_routes; bool no_copy_addrs; + bool guest_gw_from_ns; }; /** @@ -125,6 +127,7 @@ struct ip4_ctx { * @ifname_out: Optional interface name to bind outbound sockets to * @no_copy_routes: Don't copy all routes when configuring target namespace * @no_copy_addrs: Don't copy all addresses when configuring namespace + * @guest_gw_from_ns: Gateway was set from namespace (config or ns event) */ struct ip6_ctx { /* PIF_TAP addresses */ @@ -148,6 +151,7 @@ struct ip6_ctx { bool no_copy_routes; bool no_copy_addrs; + bool guest_gw_from_ns; }; #include -- 2.51.1