* [0/4] use true mac address of LAN local remote hosts
@ 2025-06-07 1:11 Jon Maloy
2025-06-07 1:11 ` [1/4] netlink: Add function to extract mac addresses from arp table Jon Maloy
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Jon Maloy @ 2025-06-07 1:11 UTC (permalink / raw)
To: sbrivio, dgibson, jmaloy, passt-dev
Bug #120 asks us to use the true MAC addresses of LAN local
remote hosts, since some programs use this information.
These commits introduces this for ARP, NTP, UDP and TCP,
while it is still missing for ICMP.
Jon Maloy (4):
netlink: Add function to extract mac addresses from arp table
arp: respond with true mac address of LAN local remote hosts
udp: forward external source mac address through tap interface
tcp: forward external source mac address through tap interface
arp.c | 9 ++++++++
flow.c | 13 ++++++++++-
flow.h | 2 ++
fwd.c | 2 +-
fwd.h | 3 ++-
ndp.c | 11 ++++++++++
netlink.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++
netlink.h | 1 +
tcp.c | 5 ++++-
tcp_buf.c | 27 +++++++++++------------
tcp_internal.h | 2 +-
tcp_vu.c | 5 ++---
udp.c | 29 +++++++++++--------------
13 files changed, 130 insertions(+), 38 deletions(-)
--
2.48.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [1/4] netlink: Add function to extract mac addresses from arp table
2025-06-07 1:11 [0/4] use true mac address of LAN local remote hosts Jon Maloy
@ 2025-06-07 1:11 ` Jon Maloy
2025-06-07 1:11 ` [2/4] arp: respond with true mac address of LAN local remote hosts Jon Maloy
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Jon Maloy @ 2025-06-07 1:11 UTC (permalink / raw)
To: sbrivio, dgibson, jmaloy, passt-dev
The solution to bug #120 requires the ability to translate from
an IP address to its corresponding MAC address in cases where
those are present in the ARP/NTP table.
We add this feature here.
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
netlink.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
netlink.h | 1 +
2 files changed, 60 insertions(+)
diff --git a/netlink.c b/netlink.c
index ee9325a..625b60c 100644
--- a/netlink.c
+++ b/netlink.c
@@ -800,6 +800,65 @@ int nl_addr_get(int s, unsigned int ifi, sa_family_t af,
return status;
}
+/**
+ * nl_mac_get() - Get mac address corresponding to given IP address
+ * @s: Netlink socket
+ * @addr: IPv4 or IPv6 address
+ * @mac: Array to place the returned MAC address
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int nl_mac_get(int s, const union inany_addr *addr, unsigned char *mac)
+{
+ struct nlmsghdr *nlh;
+ char buf[NLBUFSIZ];
+ const void *ip;
+ ssize_t status;
+ uint32_t seq;
+ int alen;
+ struct {
+ struct nlmsghdr nlh;
+ struct ndmsg ndm;
+ } req;
+
+ if (IN6_IS_ADDR_V4MAPPED(&addr->a6)) {
+ ip = &addr->v4mapped.a4;
+ alen = sizeof(struct in_addr);
+ req.ndm.ndm_family = AF_INET;
+ } else {
+ ip = &addr->a6;
+ alen = sizeof(struct in6_addr);
+ req.ndm.ndm_family = AF_INET6;
+ }
+
+ seq = nl_send(s, &req, RTM_GETNEIGH, NLM_F_DUMP, sizeof(req));
+ nl_foreach_oftype(nlh, status, s, buf, seq, RTM_NEWNEIGH) {
+ struct ndmsg *ndm = NLMSG_DATA(nlh);
+ struct rtattr *attr = (struct rtattr *)(ndm + 1);
+ int attrlen = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ndm));
+ unsigned char *lladdr = NULL;
+ void *neigh_ip = NULL;
+
+ for (; RTA_OK(attr, attrlen); attr = RTA_NEXT(attr, attrlen)) {
+ if (attr->rta_type == NDA_DST)
+ neigh_ip = RTA_DATA(attr);
+ else if (attr->rta_type == NDA_LLADDR)
+ lladdr = RTA_DATA(attr);
+ }
+
+ if (!neigh_ip || !lladdr)
+ continue;
+
+ if (!memcmp(neigh_ip, ip, alen)) {
+ memcpy(mac, lladdr, ETH_ALEN);
+ return 0;
+ }
+ }
+ memcpy(mac, MAC_OUR_LAA, ETH_ALEN);
+
+ return status;
+}
+
/**
* nl_addr_get_ll() - Get first IPv6 link-local address for a given interface
* @s: Netlink socket
diff --git a/netlink.h b/netlink.h
index b51e99c..2f674d7 100644
--- a/netlink.h
+++ b/netlink.h
@@ -17,6 +17,7 @@ int nl_route_dup(int s_src, unsigned int ifi_src,
int s_dst, unsigned int ifi_dst, sa_family_t af);
int nl_addr_get(int s, unsigned int ifi, sa_family_t af,
void *addr, int *prefix_len, void *addr_l);
+int nl_mac_get(int s, const union inany_addr *addr, unsigned char *mac);
int nl_addr_set(int s, unsigned int ifi, sa_family_t af,
const void *addr, int prefix_len);
int nl_addr_get_ll(int s, unsigned int ifi, struct in6_addr *addr);
--
@@ -17,6 +17,7 @@ int nl_route_dup(int s_src, unsigned int ifi_src,
int s_dst, unsigned int ifi_dst, sa_family_t af);
int nl_addr_get(int s, unsigned int ifi, sa_family_t af,
void *addr, int *prefix_len, void *addr_l);
+int nl_mac_get(int s, const union inany_addr *addr, unsigned char *mac);
int nl_addr_set(int s, unsigned int ifi, sa_family_t af,
const void *addr, int prefix_len);
int nl_addr_get_ll(int s, unsigned int ifi, struct in6_addr *addr);
--
2.48.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [2/4] arp: respond with true mac address of LAN local remote hosts
2025-06-07 1:11 [0/4] use true mac address of LAN local remote hosts Jon Maloy
2025-06-07 1:11 ` [1/4] netlink: Add function to extract mac addresses from arp table Jon Maloy
@ 2025-06-07 1:11 ` Jon Maloy
2025-06-07 1:11 ` [3/4] udp: forward external source mac address through tap interface Jon Maloy
2025-06-07 1:11 ` [4/4] tcp: " Jon Maloy
3 siblings, 0 replies; 5+ messages in thread
From: Jon Maloy @ 2025-06-07 1:11 UTC (permalink / raw)
To: sbrivio, dgibson, jmaloy, passt-dev
When we receive an ARP or NTP request over the tap interface for a
host on the local network, we respond with that host's real mac
address.
The local host, which is acting as a proxy for the default gateway,
is still exempted from this rule.
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
arp.c | 9 +++++++++
fwd.c | 2 +-
fwd.h | 3 ++-
ndp.c | 11 +++++++++++
4 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/arp.c b/arp.c
index fc482bb..fbd8219 100644
--- a/arp.c
+++ b/arp.c
@@ -29,6 +29,7 @@
#include "dhcp.h"
#include "passt.h"
#include "tap.h"
+#include "netlink.h"
/**
* arp() - Check if this is a supported ARP message, reply as needed
@@ -39,6 +40,8 @@
*/
int arp(const struct ctx *c, const struct pool *p)
{
+ union inany_addr translated;
+ union inany_addr addr;
unsigned char swap[4];
struct ethhdr *eh;
struct arphdr *ah;
@@ -72,6 +75,12 @@ int arp(const struct ctx *c, const struct pool *p)
memcpy(am->tha, am->sha, sizeof(am->tha));
memcpy(am->sha, c->our_tap_mac, sizeof(am->sha));
+ /* If remote host on local network - respond with its mac address */
+ inany_from_af(&addr, AF_INET, am->tip);
+ nat_outbound(c, &addr, &translated);
+ if (!memcmp(&addr, &translated, sizeof(addr)))
+ nl_mac_get(nl_sock, &addr, am->sha);
+
memcpy(swap, am->tip, sizeof(am->tip));
memcpy(am->tip, am->sip, sizeof(am->tip));
memcpy(am->sip, swap, sizeof(am->sip));
diff --git a/fwd.c b/fwd.c
index 250cf56..02ebc9d 100644
--- a/fwd.c
+++ b/fwd.c
@@ -332,7 +332,7 @@ static bool fwd_guest_accessible(const struct ctx *c,
* Only handles translations that depend *only* on the address. Anything
* related to specific ports or flows is handled elsewhere.
*/
-static void nat_outbound(const struct ctx *c, const union inany_addr *addr,
+void nat_outbound(const struct ctx *c, const union inany_addr *addr,
union inany_addr *translated)
{
if (inany_equals4(addr, &c->ip4.map_host_loopback))
diff --git a/fwd.h b/fwd.h
index 0458a3c..61632f2 100644
--- a/fwd.h
+++ b/fwd.h
@@ -56,5 +56,6 @@ uint8_t fwd_nat_from_splice(const struct ctx *c, uint8_t proto,
const struct flowside *ini, struct flowside *tgt);
uint8_t fwd_nat_from_host(const struct ctx *c, uint8_t proto,
const struct flowside *ini, struct flowside *tgt);
-
+void nat_outbound(const struct ctx *c, const union inany_addr *addr,
+ union inany_addr *translated);
#endif /* FWD_H */
diff --git a/ndp.c b/ndp.c
index 3e15494..d702f37 100644
--- a/ndp.c
+++ b/ndp.c
@@ -32,6 +32,7 @@
#include "passt.h"
#include "tap.h"
#include "log.h"
+#include "netlink.h"
#define RT_LIFETIME 65535
@@ -196,6 +197,9 @@ static void ndp_send(const struct ctx *c, const struct in6_addr *dst,
static void ndp_na(const struct ctx *c, const struct in6_addr *dst,
const struct in6_addr *addr)
{
+ union inany_addr translated;
+ union inany_addr addr_any;
+
struct ndp_na na = {
.ih = {
.icmp6_type = NA,
@@ -215,6 +219,13 @@ static void ndp_na(const struct ctx *c, const struct in6_addr *dst,
memcpy(na.target_l2_addr.mac, c->our_tap_mac, ETH_ALEN);
+ /* If remote host on local network - respond with its mac address */
+ inany_from_af(&addr_any, AF_INET6, addr);
+ nat_outbound(c, &addr_any, &translated);
+
+ if (!memcmp(&addr_any, &translated, sizeof(addr_any)))
+ nl_mac_get(nl_sock, &addr_any, na.target_l2_addr.mac);
+
ndp_send(c, dst, &na, sizeof(na));
}
--
@@ -32,6 +32,7 @@
#include "passt.h"
#include "tap.h"
#include "log.h"
+#include "netlink.h"
#define RT_LIFETIME 65535
@@ -196,6 +197,9 @@ static void ndp_send(const struct ctx *c, const struct in6_addr *dst,
static void ndp_na(const struct ctx *c, const struct in6_addr *dst,
const struct in6_addr *addr)
{
+ union inany_addr translated;
+ union inany_addr addr_any;
+
struct ndp_na na = {
.ih = {
.icmp6_type = NA,
@@ -215,6 +219,13 @@ static void ndp_na(const struct ctx *c, const struct in6_addr *dst,
memcpy(na.target_l2_addr.mac, c->our_tap_mac, ETH_ALEN);
+ /* If remote host on local network - respond with its mac address */
+ inany_from_af(&addr_any, AF_INET6, addr);
+ nat_outbound(c, &addr_any, &translated);
+
+ if (!memcmp(&addr_any, &translated, sizeof(addr_any)))
+ nl_mac_get(nl_sock, &addr_any, na.target_l2_addr.mac);
+
ndp_send(c, dst, &na, sizeof(na));
}
--
2.48.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [3/4] udp: forward external source mac address through tap interface
2025-06-07 1:11 [0/4] use true mac address of LAN local remote hosts Jon Maloy
2025-06-07 1:11 ` [1/4] netlink: Add function to extract mac addresses from arp table Jon Maloy
2025-06-07 1:11 ` [2/4] arp: respond with true mac address of LAN local remote hosts Jon Maloy
@ 2025-06-07 1:11 ` Jon Maloy
2025-06-07 1:11 ` [4/4] tcp: " Jon Maloy
3 siblings, 0 replies; 5+ messages in thread
From: Jon Maloy @ 2025-06-07 1:11 UTC (permalink / raw)
To: sbrivio, dgibson, jmaloy, passt-dev
We forward the incoming mac address through the tap interface when
receiving incoming packets from network local hosts. Packets from
the local host are excepted from this rule, and are still forwarded
with the default passt/pasta mac address as source.
This is a part of the solution to bug #120
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
flow.c | 13 ++++++++++++-
flow.h | 2 ++
udp.c | 29 +++++++++++++----------------
3 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/flow.c b/flow.c
index da5c813..e31b86e 100644
--- a/flow.c
+++ b/flow.c
@@ -20,6 +20,7 @@
#include "flow.h"
#include "flow_table.h"
#include "repair.h"
+#include "netlink.h"
const char *flow_state_str[] = {
[FLOW_STATE_FREE] = "FREE",
@@ -438,7 +439,7 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow,
{
char estr[INANY_ADDRSTRLEN], fstr[INANY_ADDRSTRLEN];
struct flow_common *f = &flow->f;
- const struct flowside *ini = &f->side[INISIDE];
+ struct flowside *ini = &f->side[INISIDE];
struct flowside *tgt = &f->side[TGTSIDE];
uint8_t tgtpif = PIF_NONE;
@@ -446,10 +447,16 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow,
ASSERT(f->type == FLOW_TYPE_NONE);
ASSERT(f->pif[INISIDE] != PIF_NONE && f->pif[TGTSIDE] == PIF_NONE);
ASSERT(flow->f.state == FLOW_STATE_INI);
+ memcpy(ini->mac, MAC_OUR_LAA, ETH_ALEN);
+ memcpy(tgt->mac, MAC_OUR_LAA, ETH_ALEN);
switch (f->pif[INISIDE]) {
case PIF_TAP:
tgtpif = fwd_nat_from_tap(c, proto, ini, tgt);
+
+ /* If remote host on local network - insert its mac address */
+ if (!memcmp(&tgt->eaddr, &ini->oaddr, sizeof(ini->oaddr)))
+ nl_mac_get(nl_sock, &ini->oaddr, ini->mac);
break;
case PIF_SPLICE:
@@ -458,6 +465,10 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow,
case PIF_HOST:
tgtpif = fwd_nat_from_host(c, proto, ini, tgt);
+
+ /* If remote host on local network - insert its mac address */
+ if (!memcmp(&tgt->oaddr, &ini->eaddr, sizeof(ini->eaddr)))
+ nl_mac_get(nl_sock, &tgt->oaddr, tgt->mac);
break;
default:
diff --git a/flow.h b/flow.h
index cac618a..916951b 100644
--- a/flow.h
+++ b/flow.h
@@ -143,12 +143,14 @@ extern const uint8_t flow_proto[];
* @oaddr: Our address (local address from passt's PoV)
* @eport: Endpoint port
* @oport: Our port
+ * @mac: MAC address of remote endpoint
*/
struct flowside {
union inany_addr oaddr;
union inany_addr eaddr;
in_port_t oport;
in_port_t eport;
+ unsigned char mac[6];
};
/**
diff --git a/udp.c b/udp.c
index 65a52e0..ae8fbaf 100644
--- a/udp.c
+++ b/udp.c
@@ -133,11 +133,8 @@ static int udp_splice_init[IP_VERSIONS][NUM_PORTS];
/* UDP header and data for inbound messages */
static struct udp_payload_t udp_payload[UDP_MAX_FRAMES];
-/* Ethernet header for IPv4 frames */
-static struct ethhdr udp4_eth_hdr;
-
-/* Ethernet header for IPv6 frames */
-static struct ethhdr udp6_eth_hdr;
+/* Ethernet headers for IPv4 and IPv6 frames */
+static struct ethhdr udp_eth_hdr[UDP_MAX_FRAMES];
/**
* struct udp_meta_t - Pre-cooked headers for UDP packets
@@ -214,8 +211,10 @@ void udp_portmap_clear(void)
*/
void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s)
{
- eth_update_mac(&udp4_eth_hdr, eth_d, eth_s);
- eth_update_mac(&udp6_eth_hdr, eth_d, eth_s);
+ int i;
+
+ for (i = 0; i < UDP_MAX_FRAMES; i++)
+ eth_update_mac(&udp_eth_hdr[i], eth_d, eth_s);
}
/**
@@ -238,6 +237,7 @@ static void udp_iov_init_one(const struct ctx *c, size_t i)
*siov = IOV_OF_LVALUE(payload->data);
+ tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(udp_eth_hdr[i]);
tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &meta->taph);
tiov[UDP_IOV_PAYLOAD].iov_base = payload;
@@ -253,9 +253,6 @@ static void udp_iov_init(const struct ctx *c)
{
size_t i;
- udp4_eth_hdr.h_proto = htons_constant(ETH_P_IP);
- udp6_eth_hdr.h_proto = htons_constant(ETH_P_IPV6);
-
for (i = 0; i < UDP_MAX_FRAMES; i++)
udp_iov_init_one(c, i);
}
@@ -362,21 +359,21 @@ static void udp_tap_prepare(const struct mmsghdr *mmh,
struct iovec (*tap_iov)[UDP_NUM_IOVS] = &udp_l2_iov[idx];
struct udp_payload_t *bp = &udp_payload[idx];
struct udp_meta_t *bm = &udp_meta[idx];
+ struct ethhdr *eh = (*tap_iov)[UDP_IOV_ETH].iov_base;
size_t l4len;
+ eth_update_mac(eh, 0, toside->mac);
if (!inany_v4(&toside->eaddr) || !inany_v4(&toside->oaddr)) {
l4len = udp_update_hdr6(&bm->ip6h, bp, toside,
mmh[idx].msg_len, no_udp_csum);
- tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip6h) +
- sizeof(udp6_eth_hdr));
- (*tap_iov)[UDP_IOV_ETH] = IOV_OF_LVALUE(udp6_eth_hdr);
+ tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip6h) + ETH_HLEN);
+ eh->h_proto = htons_constant(ETH_P_IPV6);
(*tap_iov)[UDP_IOV_IP] = IOV_OF_LVALUE(bm->ip6h);
} else {
l4len = udp_update_hdr4(&bm->ip4h, bp, toside,
mmh[idx].msg_len, no_udp_csum);
- tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip4h) +
- sizeof(udp4_eth_hdr));
- (*tap_iov)[UDP_IOV_ETH] = IOV_OF_LVALUE(udp4_eth_hdr);
+ tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip4h) + ETH_HLEN);
+ eh->h_proto = htons_constant(ETH_P_IP);
(*tap_iov)[UDP_IOV_IP] = IOV_OF_LVALUE(bm->ip4h);
}
(*tap_iov)[UDP_IOV_PAYLOAD].iov_len = l4len;
--
@@ -133,11 +133,8 @@ static int udp_splice_init[IP_VERSIONS][NUM_PORTS];
/* UDP header and data for inbound messages */
static struct udp_payload_t udp_payload[UDP_MAX_FRAMES];
-/* Ethernet header for IPv4 frames */
-static struct ethhdr udp4_eth_hdr;
-
-/* Ethernet header for IPv6 frames */
-static struct ethhdr udp6_eth_hdr;
+/* Ethernet headers for IPv4 and IPv6 frames */
+static struct ethhdr udp_eth_hdr[UDP_MAX_FRAMES];
/**
* struct udp_meta_t - Pre-cooked headers for UDP packets
@@ -214,8 +211,10 @@ void udp_portmap_clear(void)
*/
void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s)
{
- eth_update_mac(&udp4_eth_hdr, eth_d, eth_s);
- eth_update_mac(&udp6_eth_hdr, eth_d, eth_s);
+ int i;
+
+ for (i = 0; i < UDP_MAX_FRAMES; i++)
+ eth_update_mac(&udp_eth_hdr[i], eth_d, eth_s);
}
/**
@@ -238,6 +237,7 @@ static void udp_iov_init_one(const struct ctx *c, size_t i)
*siov = IOV_OF_LVALUE(payload->data);
+ tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(udp_eth_hdr[i]);
tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &meta->taph);
tiov[UDP_IOV_PAYLOAD].iov_base = payload;
@@ -253,9 +253,6 @@ static void udp_iov_init(const struct ctx *c)
{
size_t i;
- udp4_eth_hdr.h_proto = htons_constant(ETH_P_IP);
- udp6_eth_hdr.h_proto = htons_constant(ETH_P_IPV6);
-
for (i = 0; i < UDP_MAX_FRAMES; i++)
udp_iov_init_one(c, i);
}
@@ -362,21 +359,21 @@ static void udp_tap_prepare(const struct mmsghdr *mmh,
struct iovec (*tap_iov)[UDP_NUM_IOVS] = &udp_l2_iov[idx];
struct udp_payload_t *bp = &udp_payload[idx];
struct udp_meta_t *bm = &udp_meta[idx];
+ struct ethhdr *eh = (*tap_iov)[UDP_IOV_ETH].iov_base;
size_t l4len;
+ eth_update_mac(eh, 0, toside->mac);
if (!inany_v4(&toside->eaddr) || !inany_v4(&toside->oaddr)) {
l4len = udp_update_hdr6(&bm->ip6h, bp, toside,
mmh[idx].msg_len, no_udp_csum);
- tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip6h) +
- sizeof(udp6_eth_hdr));
- (*tap_iov)[UDP_IOV_ETH] = IOV_OF_LVALUE(udp6_eth_hdr);
+ tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip6h) + ETH_HLEN);
+ eh->h_proto = htons_constant(ETH_P_IPV6);
(*tap_iov)[UDP_IOV_IP] = IOV_OF_LVALUE(bm->ip6h);
} else {
l4len = udp_update_hdr4(&bm->ip4h, bp, toside,
mmh[idx].msg_len, no_udp_csum);
- tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip4h) +
- sizeof(udp4_eth_hdr));
- (*tap_iov)[UDP_IOV_ETH] = IOV_OF_LVALUE(udp4_eth_hdr);
+ tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip4h) + ETH_HLEN);
+ eh->h_proto = htons_constant(ETH_P_IP);
(*tap_iov)[UDP_IOV_IP] = IOV_OF_LVALUE(bm->ip4h);
}
(*tap_iov)[UDP_IOV_PAYLOAD].iov_len = l4len;
--
2.48.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [4/4] tcp: forward external source mac address through tap interface
2025-06-07 1:11 [0/4] use true mac address of LAN local remote hosts Jon Maloy
` (2 preceding siblings ...)
2025-06-07 1:11 ` [3/4] udp: forward external source mac address through tap interface Jon Maloy
@ 2025-06-07 1:11 ` Jon Maloy
3 siblings, 0 replies; 5+ messages in thread
From: Jon Maloy @ 2025-06-07 1:11 UTC (permalink / raw)
To: sbrivio, dgibson, jmaloy, passt-dev
We forward the incoming mac address through the tap interface when
receiving incoming packets from network local hosts. Packets from
the local host are excepted from this rule, and are still forwarded
with the default passt/pasta mac address as source.
This is a part of the solution to bug #120
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
tcp.c | 5 ++++-
tcp_buf.c | 27 +++++++++++++--------------
tcp_internal.h | 2 +-
tcp_vu.c | 5 ++---
4 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/tcp.c b/tcp.c
index f43c1e2..777f345 100644
--- a/tcp.c
+++ b/tcp.c
@@ -920,7 +920,7 @@ static void tcp_fill_header(struct tcphdr *th,
* @no_tcp_csum: Do not set TCP checksum
*/
void tcp_fill_headers(const struct tcp_tap_conn *conn,
- struct tap_hdr *taph,
+ struct tap_hdr *taph, struct ethhdr *eh,
struct iphdr *ip4h, struct ipv6hdr *ip6h,
struct tcphdr *th, struct iov_tail *payload,
const uint16_t *ip4_check, uint32_t seq, bool no_tcp_csum)
@@ -952,6 +952,7 @@ void tcp_fill_headers(const struct tcp_tap_conn *conn,
psum = proto_ipv4_header_psum(l4len, IPPROTO_TCP,
*src4, *dst4);
}
+ eh->h_proto = htons_constant(ETH_P_IP);
}
if (ip6h) {
@@ -972,7 +973,9 @@ void tcp_fill_headers(const struct tcp_tap_conn *conn,
&ip6h->saddr,
&ip6h->daddr);
}
+ eh->h_proto = htons_constant(ETH_P_IPV6);
}
+ eth_update_mac(eh, 0, tapside->mac);
tcp_fill_header(th, conn, seq);
diff --git a/tcp_buf.c b/tcp_buf.c
index d1fca67..2dbeca2 100644
--- a/tcp_buf.c
+++ b/tcp_buf.c
@@ -40,8 +40,7 @@
/* Static buffers */
/* Ethernet header for IPv4 and IPv6 frames */
-static struct ethhdr tcp4_eth_src;
-static struct ethhdr tcp6_eth_src;
+static struct ethhdr tcp_eth_hdr[TCP_FRAMES_MEM];
static struct tap_hdr tcp_payload_tap_hdr[TCP_FRAMES_MEM];
@@ -71,8 +70,10 @@ static struct iovec tcp_l2_iov[TCP_FRAMES_MEM][TCP_NUM_IOVS];
*/
void tcp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s)
{
- eth_update_mac(&tcp4_eth_src, eth_d, eth_s);
- eth_update_mac(&tcp6_eth_src, eth_d, eth_s);
+ int i;
+
+ for (i = 0; i < TCP_FRAMES_MEM; i ++)
+ eth_update_mac(&tcp_eth_hdr[i], eth_d, eth_s);
}
/**
@@ -85,8 +86,8 @@ void tcp_sock_iov_init(const struct ctx *c)
struct iphdr iph = L2_BUF_IP4_INIT(IPPROTO_TCP);
int i;
- tcp6_eth_src.h_proto = htons_constant(ETH_P_IPV6);
- tcp4_eth_src.h_proto = htons_constant(ETH_P_IP);
+ for (i = 0; i < TCP_FRAMES_MEM; i ++)
+ eth_update_mac(&tcp_eth_hdr[i], NULL, c->our_tap_mac);
for (i = 0; i < ARRAY_SIZE(tcp_payload); i++) {
tcp6_payload_ip[i] = ip6;
@@ -164,6 +165,7 @@ static void tcp_l2_buf_fill_headers(const struct tcp_tap_conn *conn,
struct tap_hdr *taph = iov[TCP_IOV_TAP].iov_base;
const struct flowside *tapside = TAPFLOW(conn);
const struct in_addr *a4 = inany_v4(&tapside->oaddr);
+ struct ethhdr *eh = iov[TCP_IOV_ETH].iov_base;
struct ipv6hdr *ip6h = NULL;
struct iphdr *ip4h = NULL;
@@ -172,7 +174,7 @@ static void tcp_l2_buf_fill_headers(const struct tcp_tap_conn *conn,
else
ip6h = iov[TCP_IOV_IP].iov_base;
- tcp_fill_headers(conn, taph, ip4h, ip6h, th, &tail,
+ tcp_fill_headers(conn, taph, eh, ip4h, ip6h, th, &tail,
check, seq, no_tcp_csum);
}
@@ -194,14 +196,12 @@ int tcp_buf_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
int ret;
iov = tcp_l2_iov[tcp_payload_used];
- if (CONN_V4(conn)) {
+ if (CONN_V4(conn))
iov[TCP_IOV_IP] = IOV_OF_LVALUE(tcp4_payload_ip[tcp_payload_used]);
- iov[TCP_IOV_ETH].iov_base = &tcp4_eth_src;
- } else {
+ else
iov[TCP_IOV_IP] = IOV_OF_LVALUE(tcp6_payload_ip[tcp_payload_used]);
- iov[TCP_IOV_ETH].iov_base = &tcp6_eth_src;
- }
+ iov[TCP_IOV_ETH] = IOV_OF_LVALUE(tcp_eth_hdr[tcp_payload_used]);
payload = iov[TCP_IOV_PAYLOAD].iov_base;
seq = conn->seq_to_tap;
ret = tcp_prepare_flags(c, conn, flags, &payload->th,
@@ -259,11 +259,10 @@ static void tcp_data_to_tap(const struct ctx *c, struct tcp_tap_conn *conn,
check = &iph->check;
}
iov[TCP_IOV_IP] = IOV_OF_LVALUE(tcp4_payload_ip[tcp_payload_used]);
- iov[TCP_IOV_ETH].iov_base = &tcp4_eth_src;
} else if (CONN_V6(conn)) {
iov[TCP_IOV_IP] = IOV_OF_LVALUE(tcp6_payload_ip[tcp_payload_used]);
- iov[TCP_IOV_ETH].iov_base = &tcp6_eth_src;
}
+ iov[TCP_IOV_ETH].iov_base = &tcp_eth_hdr[tcp_payload_used];
payload = iov[TCP_IOV_PAYLOAD].iov_base;
payload->th.th_off = sizeof(struct tcphdr) / 4;
payload->th.th_x2 = 0;
diff --git a/tcp_internal.h b/tcp_internal.h
index 36c6533..6c2d1ef 100644
--- a/tcp_internal.h
+++ b/tcp_internal.h
@@ -167,7 +167,7 @@ void tcp_rst_do(const struct ctx *c, struct tcp_tap_conn *conn);
struct tcp_info_linux;
void tcp_fill_headers(const struct tcp_tap_conn *conn,
- struct tap_hdr *taph,
+ struct tap_hdr *taph, struct ethhdr *eh,
struct iphdr *ip4h, struct ipv6hdr *ip6h,
struct tcphdr *th, struct iov_tail *payload,
const uint16_t *ip4_check, uint32_t seq, bool no_tcp_csum);
diff --git a/tcp_vu.c b/tcp_vu.c
index f3914c7..da1fb37 100644
--- a/tcp_vu.c
+++ b/tcp_vu.c
@@ -135,7 +135,7 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
flags_elem[0].in_sg[0].iov_len = hdrlen + optlen;
payload = IOV_TAIL(flags_elem[0].in_sg, 1, hdrlen);
- tcp_fill_headers(conn, NULL, ip4h, ip6h, th, &payload,
+ tcp_fill_headers(conn, NULL, eh, ip4h, ip6h, th, &payload,
NULL, seq, !*c->pcap);
if (*c->pcap) {
@@ -315,7 +315,6 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn,
eh = vu_eth(base);
memcpy(eh->h_dest, c->guest_mac, sizeof(eh->h_dest));
- memcpy(eh->h_source, c->our_tap_mac, sizeof(eh->h_source));
/* initialize header */
@@ -339,7 +338,7 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn,
th->ack = 1;
th->psh = push;
- tcp_fill_headers(conn, NULL, ip4h, ip6h, th, &payload,
+ tcp_fill_headers(conn, NULL, eh, ip4h, ip6h, th, &payload,
*check, conn->seq_to_tap, no_tcp_csum);
if (ip4h)
*check = &ip4h->check;
--
@@ -135,7 +135,7 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
flags_elem[0].in_sg[0].iov_len = hdrlen + optlen;
payload = IOV_TAIL(flags_elem[0].in_sg, 1, hdrlen);
- tcp_fill_headers(conn, NULL, ip4h, ip6h, th, &payload,
+ tcp_fill_headers(conn, NULL, eh, ip4h, ip6h, th, &payload,
NULL, seq, !*c->pcap);
if (*c->pcap) {
@@ -315,7 +315,6 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn,
eh = vu_eth(base);
memcpy(eh->h_dest, c->guest_mac, sizeof(eh->h_dest));
- memcpy(eh->h_source, c->our_tap_mac, sizeof(eh->h_source));
/* initialize header */
@@ -339,7 +338,7 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn,
th->ack = 1;
th->psh = push;
- tcp_fill_headers(conn, NULL, ip4h, ip6h, th, &payload,
+ tcp_fill_headers(conn, NULL, eh, ip4h, ip6h, th, &payload,
*check, conn->seq_to_tap, no_tcp_csum);
if (ip4h)
*check = &ip4h->check;
--
2.48.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-06-07 1:12 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-06-07 1:11 [0/4] use true mac address of LAN local remote hosts Jon Maloy
2025-06-07 1:11 ` [1/4] netlink: Add function to extract mac addresses from arp table Jon Maloy
2025-06-07 1:11 ` [2/4] arp: respond with true mac address of LAN local remote hosts Jon Maloy
2025-06-07 1:11 ` [3/4] udp: forward external source mac address through tap interface Jon Maloy
2025-06-07 1:11 ` [4/4] tcp: " Jon Maloy
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).