summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2014-09-26 15:45:22 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2014-09-26 15:45:22 +0200
commitb63d267e79a54b1c1f0c3e987a28535055d5f574 (patch)
tree6301befdbbf64762983cf70cfa7f6e2532c5fba1
parentd90524202c9484f2851dbe192847f71dadc22ce5 (diff)
downloadfastd-b63d267e79a54b1c1f0c3e987a28535055d5f574.tar
fastd-b63d267e79a54b1c1f0c3e987a28535055d5f574.zip
Don't forward frames with local destination MAC address
-rw-r--r--src/peer.c18
-rw-r--r--src/peer.h2
-rw-r--r--src/send.c14
3 files changed, 23 insertions, 11 deletions
diff --git a/src/peer.c b/src/peer.c
index 03e5716..7a05dbd 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -862,7 +862,7 @@ static int peer_eth_addr_cmp(const fastd_peer_eth_addr_t *addr1, const fastd_pee
void fastd_peer_eth_addr_add(fastd_peer_t *peer, fastd_eth_addr_t addr) {
int min = 0, max = VECTOR_LEN(ctx.eth_addrs);
- if (!fastd_peer_is_established(peer))
+ if (peer && !fastd_peer_is_established(peer))
exit_bug("tried to learn ethernet address on non-established peer");
while (max > min) {
@@ -884,18 +884,22 @@ void fastd_peer_eth_addr_add(fastd_peer_t *peer, fastd_eth_addr_t addr) {
VECTOR_INSERT(ctx.eth_addrs, ((fastd_peer_eth_addr_t) {addr, peer, ctx.now + ETH_ADDR_STALE_TIME}), min);
- pr_debug("learned new MAC address %E on peer %P", &addr, peer);
+ if (peer)
+ pr_debug("learned new MAC address %E on peer %P", &addr, peer);
+ else
+ pr_debug("learned new local MAC address %E", &addr);
}
/** Finds the peer that is associated with a given MAC address */
-fastd_peer_t * fastd_peer_find_by_eth_addr(const fastd_eth_addr_t addr) {
+bool fastd_peer_find_by_eth_addr(const fastd_eth_addr_t addr, fastd_peer_t **peer) {
const fastd_peer_eth_addr_t key = {.addr = addr};
fastd_peer_eth_addr_t *peer_eth_addr = VECTOR_BSEARCH(&key, ctx.eth_addrs, peer_eth_addr_cmp);
- if (peer_eth_addr)
- return peer_eth_addr->peer;
- else
- return NULL;
+ if (!peer_eth_addr)
+ return false;
+
+ *peer = peer_eth_addr->peer;
+ return true;
}
/**
diff --git a/src/peer.h b/src/peer.h
index 30c9156..ca03e2f 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -271,7 +271,7 @@ static inline bool fastd_eth_addr_is_unicast(fastd_eth_addr_t addr) {
}
void fastd_peer_eth_addr_add(fastd_peer_t *peer, fastd_eth_addr_t addr);
-fastd_peer_t * fastd_peer_find_by_eth_addr(fastd_eth_addr_t addr);
+bool fastd_peer_find_by_eth_addr(const fastd_eth_addr_t addr, fastd_peer_t **peer);
void fastd_peer_handle_handshake_queue(void);
void fastd_peer_maintenance(void);
diff --git a/src/send.c b/src/send.c
index 19f0649..8b9aae7 100644
--- a/src/send.c
+++ b/src/send.c
@@ -206,16 +206,24 @@ static inline bool send_data_tap_single(fastd_buffer_t buffer, fastd_peer_t *sou
return true;
}
+ if (!source) {
+ fastd_eth_addr_t src_addr = fastd_buffer_source_address(buffer);
+
+ if (fastd_eth_addr_is_unicast(src_addr))
+ fastd_peer_eth_addr_add(NULL, src_addr);
+ }
+
fastd_eth_addr_t dest_addr = fastd_buffer_dest_address(buffer);
if (!fastd_eth_addr_is_unicast(dest_addr))
return false;
- fastd_peer_t *dest = fastd_peer_find_by_eth_addr(dest_addr);
+ fastd_peer_t *dest;
+ bool found = fastd_peer_find_by_eth_addr(dest_addr, &dest);
- if (!dest)
+ if (!found)
return false;
- if (dest == source) {
+ if (!dest || dest == source) {
fastd_buffer_free(buffer);
return true;
}