aboutgitcodebugslistschat
path: root/udp.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2022-02-20 03:47:19 +0100
committerStefano Brivio <sbrivio@redhat.com>2022-02-21 13:41:13 +0100
commit9afd87b7334d8ea9cd7ca35b9f838a21ef093eaa (patch)
treec1230aa7f8ae582c546ea9cb3f6dceec93ec29b9 /udp.c
parent89678c515755403277938e34984f3faf4863d593 (diff)
downloadpasst-9afd87b7334d8ea9cd7ca35b9f838a21ef093eaa.tar
passt-9afd87b7334d8ea9cd7ca35b9f838a21ef093eaa.tar.gz
passt-9afd87b7334d8ea9cd7ca35b9f838a21ef093eaa.tar.bz2
passt-9afd87b7334d8ea9cd7ca35b9f838a21ef093eaa.tar.lz
passt-9afd87b7334d8ea9cd7ca35b9f838a21ef093eaa.tar.xz
passt-9afd87b7334d8ea9cd7ca35b9f838a21ef093eaa.tar.zst
passt-9afd87b7334d8ea9cd7ca35b9f838a21ef093eaa.zip
udp: Allow loopback connections from host using configured unicast address
Likely for testing purposes only: allow connections from host to guest or namespace using, as connection target, the configured, possibly global unicast address. In this case, we have to map the destination address to a link-local address, and for port-based tracked responses, the source address needs to be again the unicast address: not loopback, not link-local. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'udp.c')
-rw-r--r--udp.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/udp.c b/udp.c
index 2fc52d3..8129a89 100644
--- a/udp.c
+++ b/udp.c
@@ -125,13 +125,15 @@
* @sock: Socket bound to source port used as index
* @ts: Activity timestamp from tap, used for socket aging
* @ts_local: Timestamp of tap packet to gateway address, aging for local bind
- * @loopback: Whether local bind should use loopback address as source
+ * @loopback: Whether local bind maps to loopback address as source
+ * @gua: Whether local bind maps to configured unicast address as source
*/
struct udp_tap_port {
int sock;
time_t ts;
time_t ts_local;
int loopback;
+ int gua;
};
/**
@@ -701,10 +703,13 @@ void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
b->ip6h.saddr = b->s_in6.sin6_addr;
} else if (IN6_IS_ADDR_LOOPBACK(&b->s_in6.sin6_addr) ||
!memcmp(&b->s_in6.sin6_addr, &c->addr6_seen,
+ sizeof(c->addr6)) ||
+ !memcmp(&b->s_in6.sin6_addr, &c->addr6,
sizeof(c->addr6))) {
in_port_t src = htons(b->s_in6.sin6_port);
b->ip6h.daddr = c->addr6_ll_seen;
+
if (IN6_IS_ADDR_LINKLOCAL(&c->gw6))
b->ip6h.saddr = c->gw6;
else
@@ -717,6 +722,12 @@ void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
else
udp_tap_map[V6][src].loopback = 0;
+ if (!memcmp(&b->s_in6.sin6_addr, &c->addr6,
+ sizeof(c->addr6)))
+ udp_tap_map[V6][src].gua = 1;
+ else
+ udp_tap_map[V6][src].gua = 0;
+
bitmap_set(udp_act[V6][UDP_ACT_TAP], src);
} else if (!IN6_IS_ADDR_UNSPECIFIED(&c->dns6_fwd) &&
!memcmp(&b->s_in6.sin6_addr, &c->dns6_fwd,
@@ -987,6 +998,8 @@ int udp_tap_handler(struct ctx *c, int af, void *addr,
if (!udp_tap_map[V6][dst].ts_local ||
udp_tap_map[V6][dst].loopback)
s_in6.sin6_addr = in6addr_loopback;
+ else if (udp_tap_map[V6][dst].gua)
+ s_in6.sin6_addr = c->addr6;
else
s_in6.sin6_addr = c->addr6_seen;
} else if (!memcmp(addr, &c->dns6_fwd, sizeof(c->dns6_fwd)) &&
@@ -1212,8 +1225,11 @@ static void udp_timer_one(struct ctx *c, int v6, enum udp_act_type type,
if (ts->tv_sec - tp->ts > UDP_CONN_TIMEOUT)
s = tp->sock;
- if (ts->tv_sec - tp->ts_local > UDP_CONN_TIMEOUT)
+ if (ts->tv_sec - tp->ts_local > UDP_CONN_TIMEOUT) {
tp->ts_local = 0;
+ tp->loopback = 0;
+ tp->gua = 0;
+ }
break;
case UDP_ACT_INIT_CONN: