aboutgitcodebugslistschat
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2021-07-26 14:13:21 +0200
committerStefano Brivio <sbrivio@redhat.com>2021-07-26 14:13:21 +0200
commit85a820a66fe44b2ae4355e306918f78a55edbc23 (patch)
tree16cf92f7fbcda1a4b776e564c739da88e879456c
parent86b273150a47c6f5783db865d1385675f5c4e5a6 (diff)
downloadpasst-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.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/tap.c b/tap.c
index 9fc84c1..e31a419 100644
--- a/tap.c
+++ b/tap.c
@@ -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;
}
}