diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2021-07-26 14:13:21 +0200 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2021-07-26 14:13:21 +0200 |
commit | 85a820a66fe44b2ae4355e306918f78a55edbc23 (patch) | |
tree | 16cf92f7fbcda1a4b776e564c739da88e879456c | |
parent | 86b273150a47c6f5783db865d1385675f5c4e5a6 (diff) | |
download | passt-85a820a66fe44b2ae4355e306918f78a55edbc23.tar passt-85a820a66fe44b2ae4355e306918f78a55edbc23.tar.gz passt-85a820a66fe44b2ae4355e306918f78a55edbc23.tar.bz2 passt-85a820a66fe44b2ae4355e306918f78a55edbc23.tar.lz passt-85a820a66fe44b2ae4355e306918f78a55edbc23.tar.xz passt-85a820a66fe44b2ae4355e306918f78a55edbc23.tar.zst passt-85a820a66fe44b2ae4355e306918f78a55edbc23.zip |
tap: Don't override address observed from guest with our own notion of it
If a tap protocol handler doesn't consume the full batch of packets
in one go, we already overrode the destination address in the packet
buffer with the address which is configured at start. If we re-enter
the tap handler, we shouldn't use the address from the packet buffers
anymore to set the observed address of the guest: that's not the
address observed from the guest, it's the configured one now.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
-rw-r--r-- | tap.c | 37 |
1 files changed, 22 insertions, 15 deletions
@@ -197,11 +197,12 @@ void tap_ip_send(struct ctx *c, struct in6_addr *src, uint8_t proto, * @msg: Array of messages with the same L3 protocol * @count: Count of messages with the same L3 protocol * @now: Current timestamp + * @first: First call for an IPv4 packet in this batch * * Return: count of packets consumed by handlers */ static int tap4_handler(struct ctx *c, struct tap_msg *msg, size_t count, - struct timespec *now) + struct timespec *now, int first) { char buf_s[INET_ADDRSTRLEN] __attribute((__unused__)); char buf_d[INET_ADDRSTRLEN] __attribute((__unused__)); @@ -230,7 +231,7 @@ static int tap4_handler(struct ctx *c, struct tap_msg *msg, size_t count, iph = (struct iphdr *)(eh + 1); l4h = (char *)iph + iph->ihl * 4; - if (c->addr4_seen != iph->saddr) { + if (first && c->addr4_seen != iph->saddr) { c->addr4_seen = iph->saddr; proto_update_l2_buf(NULL, NULL, &c->addr4_seen); } @@ -307,11 +308,12 @@ static int tap4_handler(struct ctx *c, struct tap_msg *msg, size_t count, * @msg: Array of messages with the same L3 protocol * @count: Count of messages with the same L3 protocol * @now: Current timestamp + * @first: First call for an IPv6 packet in this batch * * Return: count of packets consumed by handlers */ static int tap6_handler(struct ctx *c, struct tap_msg *msg, size_t count, - struct timespec *now) + struct timespec *now, int first) { char buf_s[INET6_ADDRSTRLEN] __attribute((__unused__)); char buf_d[INET6_ADDRSTRLEN] __attribute((__unused__)); @@ -346,13 +348,16 @@ static int tap6_handler(struct ctx *c, struct tap_msg *msg, size_t count, msg[i].l4h = l4h; msg[i].l4_len = len - ((intptr_t)l4h - (intptr_t)eh); - if (IN6_IS_ADDR_LINKLOCAL(&ip6h->saddr)) { - c->addr6_ll_seen = ip6h->saddr; + if (first) { + if (IN6_IS_ADDR_LINKLOCAL(&ip6h->saddr)) { + c->addr6_ll_seen = ip6h->saddr; - if (IN6_IS_ADDR_UNSPECIFIED(&c->addr6_seen)) + if (IN6_IS_ADDR_UNSPECIFIED(&c->addr6_seen)) { + c->addr6_seen = ip6h->saddr; + } + } else { c->addr6_seen = ip6h->saddr; - } else { - c->addr6_seen = ip6h->saddr; + } } ip6h->saddr = c->addr6; @@ -431,7 +436,7 @@ static int tap6_handler(struct ctx *c, struct tap_msg *msg, size_t count, */ static int tap_handler_passt(struct ctx *c, struct timespec *now) { - int msg_count = 0, same, i = 0; + int msg_count = 0, same, i = 0, first_v4 = 1, first_v6 = 1; struct tap_msg msg[TAP_MSGS]; struct ethhdr *eh; char *p = pkt_buf; @@ -483,7 +488,7 @@ static int tap_handler_passt(struct ctx *c, struct timespec *now) switch (ntohs(eh->h_proto)) { case ETH_P_ARP: - tap4_handler(c, msg + i, 1, now); + tap4_handler(c, msg + i, 1, now, 1); i++; break; case ETH_P_IP: @@ -496,7 +501,8 @@ static int tap_handler_passt(struct ctx *c, struct timespec *now) break; } - i += tap4_handler(c, msg + i, same, now); + i += tap4_handler(c, msg + i, same, now, first_v4); + first_v4 = 0; break; case ETH_P_IPV6: for (same = 1; i + same < msg_count && @@ -508,7 +514,8 @@ static int tap_handler_passt(struct ctx *c, struct timespec *now) break; } - i += tap6_handler(c, msg + i, same, now); + i += tap6_handler(c, msg + i, same, now, first_v6); + first_v6 = 0; break; default: i++; @@ -544,13 +551,13 @@ static int tap_handler_pasta(struct ctx *c, struct timespec *now) switch (ntohs(eh->h_proto)) { case ETH_P_ARP: - tap4_handler(c, &msg, 1, now); + tap4_handler(c, &msg, 1, now, 1); break; case ETH_P_IP: - tap4_handler(c, &msg, 1, now); + tap4_handler(c, &msg, 1, now, 1); break; case ETH_P_IPV6: - tap6_handler(c, &msg, 1, now); + tap6_handler(c, &msg, 1, now, 1); break; } } |