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
---
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;
--
2.48.1