From c9f0ec3227d4861afe7dd8aa4c2eb55ed095586c Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Wed, 21 Aug 2024 14:20:08 +1000
Subject: util: Correct sock_l4() binding for link local addresses

When binding an IPv6 socket in sock_l4() we need to supply a scope id
if the address is link-local.  We check for this by comparing the
given address to c->ip6.addr_ll.  This is correct only by accident:
while c->ip6.addr_ll is typically set to the host interface's link
local address, the actual purpose of it is to provide a link local
address for passt's private use on the tap interface.

Instead set the scope id for any link-local address we're binding to.
We're going to need something and this is what makes sense for sockets
on the host.  It doesn't make sense for PIF_SPLICE sockets, but those
should always have loopback, not link-local addresses.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
---
 util.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/util.c b/util.c
index 7cb2c10..f9f8113 100644
--- a/util.c
+++ b/util.c
@@ -199,8 +199,7 @@ int sock_l4(const struct ctx *c, sa_family_t af, enum epoll_type type,
 		if (bind_addr) {
 			addr6.sin6_addr = *(struct in6_addr *)bind_addr;
 
-			if (!memcmp(bind_addr, &c->ip6.addr_ll,
-			    sizeof(c->ip6.addr_ll)))
+			if (IN6_IS_ADDR_LINKLOCAL(bind_addr))
 				addr6.sin6_scope_id = c->ifi6;
 		}
 		return sock_l4_sa(c, type, &addr6, sizeof(addr6), ifname,
-- 
cgit v1.2.3