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>
This commit is contained in:
Stefano Brivio 2021-07-26 14:13:21 +02:00
parent 86b273150a
commit 85a820a66f

29
tap.c
View file

@ -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 * @msg: Array of messages with the same L3 protocol
* @count: Count of messages with the same L3 protocol * @count: Count of messages with the same L3 protocol
* @now: Current timestamp * @now: Current timestamp
* @first: First call for an IPv4 packet in this batch
* *
* Return: count of packets consumed by handlers * Return: count of packets consumed by handlers
*/ */
static int tap4_handler(struct ctx *c, struct tap_msg *msg, size_t count, 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_s[INET_ADDRSTRLEN] __attribute((__unused__));
char buf_d[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); iph = (struct iphdr *)(eh + 1);
l4h = (char *)iph + iph->ihl * 4; l4h = (char *)iph + iph->ihl * 4;
if (c->addr4_seen != iph->saddr) { if (first && c->addr4_seen != iph->saddr) {
c->addr4_seen = iph->saddr; c->addr4_seen = iph->saddr;
proto_update_l2_buf(NULL, NULL, &c->addr4_seen); 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 * @msg: Array of messages with the same L3 protocol
* @count: Count of messages with the same L3 protocol * @count: Count of messages with the same L3 protocol
* @now: Current timestamp * @now: Current timestamp
* @first: First call for an IPv6 packet in this batch
* *
* Return: count of packets consumed by handlers * Return: count of packets consumed by handlers
*/ */
static int tap6_handler(struct ctx *c, struct tap_msg *msg, size_t count, 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_s[INET6_ADDRSTRLEN] __attribute((__unused__));
char buf_d[INET6_ADDRSTRLEN] __attribute((__unused__)); char buf_d[INET6_ADDRSTRLEN] __attribute((__unused__));
@ -346,14 +348,17 @@ static int tap6_handler(struct ctx *c, struct tap_msg *msg, size_t count,
msg[i].l4h = l4h; msg[i].l4h = l4h;
msg[i].l4_len = len - ((intptr_t)l4h - (intptr_t)eh); msg[i].l4_len = len - ((intptr_t)l4h - (intptr_t)eh);
if (first) {
if (IN6_IS_ADDR_LINKLOCAL(&ip6h->saddr)) { if (IN6_IS_ADDR_LINKLOCAL(&ip6h->saddr)) {
c->addr6_ll_seen = 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; c->addr6_seen = ip6h->saddr;
}
} else { } else {
c->addr6_seen = ip6h->saddr; c->addr6_seen = ip6h->saddr;
} }
}
ip6h->saddr = c->addr6; 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) 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 tap_msg msg[TAP_MSGS];
struct ethhdr *eh; struct ethhdr *eh;
char *p = pkt_buf; char *p = pkt_buf;
@ -483,7 +488,7 @@ static int tap_handler_passt(struct ctx *c, struct timespec *now)
switch (ntohs(eh->h_proto)) { switch (ntohs(eh->h_proto)) {
case ETH_P_ARP: case ETH_P_ARP:
tap4_handler(c, msg + i, 1, now); tap4_handler(c, msg + i, 1, now, 1);
i++; i++;
break; break;
case ETH_P_IP: case ETH_P_IP:
@ -496,7 +501,8 @@ static int tap_handler_passt(struct ctx *c, struct timespec *now)
break; break;
} }
i += tap4_handler(c, msg + i, same, now); i += tap4_handler(c, msg + i, same, now, first_v4);
first_v4 = 0;
break; break;
case ETH_P_IPV6: case ETH_P_IPV6:
for (same = 1; i + same < msg_count && for (same = 1; i + same < msg_count &&
@ -508,7 +514,8 @@ static int tap_handler_passt(struct ctx *c, struct timespec *now)
break; break;
} }
i += tap6_handler(c, msg + i, same, now); i += tap6_handler(c, msg + i, same, now, first_v6);
first_v6 = 0;
break; break;
default: default:
i++; i++;
@ -544,13 +551,13 @@ static int tap_handler_pasta(struct ctx *c, struct timespec *now)
switch (ntohs(eh->h_proto)) { switch (ntohs(eh->h_proto)) {
case ETH_P_ARP: case ETH_P_ARP:
tap4_handler(c, &msg, 1, now); tap4_handler(c, &msg, 1, now, 1);
break; break;
case ETH_P_IP: case ETH_P_IP:
tap4_handler(c, &msg, 1, now); tap4_handler(c, &msg, 1, now, 1);
break; break;
case ETH_P_IPV6: case ETH_P_IPV6:
tap6_handler(c, &msg, 1, now); tap6_handler(c, &msg, 1, now, 1);
break; break;
} }
} }