When using IPv4, if the remote server is not yet in the ARP cache, the MAC resolution will fail and data appear to not be shared via alfred. Add a routine (modified from batctl sources) to request MAC resolution by simply sending a datagram to the discard port (UDP/9). This adds the remote MAC to the ARP cache, resulting in successful MAC resolution.
Signed-off-by: Jonathan Haws jhaws@sdl.usu.edu --- alfred.h | 1 + util.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+)
diff --git a/alfred.h b/alfred.h index eecfdfd..5771483 100644 --- a/alfred.h +++ b/alfred.h @@ -213,3 +213,4 @@ uint16_t get_random_id(void); bool is_valid_ether_addr(uint8_t *addr); int ipv4_arp_request(struct interface *interface, const alfred_addr *addr, struct ether_addr *mac); +void ipv4_request_mac_resolve(const alfred_addr *addr); diff --git a/util.c b/util.c index dd3f00f..a6a98b9 100644 --- a/util.c +++ b/util.c @@ -30,6 +30,7 @@ #include <sys/ioctl.h> #include <sys/time.h> #include <time.h> +#include <unistd.h> #include "alfred.h"
int time_diff(struct timespec *tv1, struct timespec *tv2, @@ -85,6 +86,7 @@ int ipv4_arp_request(struct interface *interface, const alfred_addr *addr, { struct arpreq arpreq; struct sockaddr_in *sin; + int retries = 1;
memset(&arpreq, 0, sizeof(arpreq)); memset(mac, 0, ETH_ALEN); @@ -99,6 +101,14 @@ int ipv4_arp_request(struct interface *interface, const alfred_addr *addr, if (ioctl(interface->netsock, SIOCGARP, &arpreq) < 0) return -1;
+ while (retries-- && !(arpreq.arp_flags & ATF_COM)) { + ipv4_request_mac_resolve(addr); + usleep(200000); + + if (ioctl(interface->netsock, SIOCGARP, &arpreq) < 0) + return -1; + } + if (arpreq.arp_flags & ATF_COM) { memcpy(mac, arpreq.arp_ha.sa_data, sizeof(*mac)); } else { @@ -108,3 +118,26 @@ int ipv4_arp_request(struct interface *interface, const alfred_addr *addr,
return 0; } + +void ipv4_request_mac_resolve(const alfred_addr *addr) +{ + const struct sockaddr *sockaddr; + struct sockaddr_in inet4; + size_t sockaddr_len; + int sock; + char t = 0; + + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) + return; + + memset(&inet4, 0, sizeof(inet4)); + inet4.sin_family = AF_INET; + inet4.sin_port = htons(9); + inet4.sin_addr.s_addr = addr->ipv4.s_addr; + sockaddr = (const struct sockaddr *)&inet4; + sockaddr_len = sizeof(inet4); + + sendto(sock, &t, sizeof(t), 0, sockaddr, sockaddr_len); + close(sock); +}
Please start the subject with "alfred: " when it is a patch for alfred.
On Mittwoch, 24. Oktober 2018 20:35:11 CEST Jonathan Haws wrote:
When using IPv4, if the remote server is not yet in the ARP cache, the MAC resolution will fail and data appear to not be shared via alfred. Add a routine (modified from batctl sources) to request MAC resolution by simply sending a datagram to the discard port (UDP/9). This adds the remote MAC to the ARP cache, resulting in successful MAC resolution.
Signed-off-by: Jonathan Haws jhaws@sdl.usu.edu
Please add the info which commit was fixed by this change right before the Signed-off-by:
Fixes: c7da798113a2 ("alfred: IPv4 multicast distribution support.")
[...]
index eecfdfd..5771483 100644 --- a/alfred.h +++ b/alfred.h @@ -213,3 +213,4 @@ uint16_t get_random_id(void); bool is_valid_ether_addr(uint8_t *addr); int ipv4_arp_request(struct interface *interface, const alfred_addr *addr, struct ether_addr *mac); +void ipv4_request_mac_resolve(const alfred_addr *addr);
This doesn't make sense. The function is in util.c and only called in util.c. So it should be static and not in this header at all.
Kind regards, Sven
On Wed, 2018-10-24 at 20:57 +0200, Sven Eckelmann wrote:
Please start the subject with "alfred: " when it is a patch for alfred.
Right - my mistake. It's been a long time since I last submitted....
On Mittwoch, 24. Oktober 2018 20:35:11 CEST Jonathan Haws wrote:
When using IPv4, if the remote server is not yet in the ARP cache, the MAC resolution will fail and data appear to not be shared via alfred. Add a routine (modified from batctl sources) to request MAC resolution by simply sending a datagram to the discard port (UDP/9). This adds the remote MAC to the ARP cache, resulting in successful MAC resolution.
Signed-off-by: Jonathan Haws jhaws@sdl.usu.edu
Please add the info which commit was fixed by this change right before the Signed-off-by:
Fixes: c7da798113a2 ("alfred: IPv4 multicast distribution support.")
Done.
[...]
index eecfdfd..5771483 100644 --- a/alfred.h +++ b/alfred.h @@ -213,3 +213,4 @@ uint16_t get_random_id(void); bool is_valid_ether_addr(uint8_t *addr); int ipv4_arp_request(struct interface *interface, const alfred_addr *addr, struct ether_addr *mac); +void ipv4_request_mac_resolve(const alfred_addr *addr);
This doesn't make sense. The function is in util.c and only called in util.c. So it should be static and not in this header at all.
You're right - I blindly mimicked the previous ipv4_arp_request routine without thinking about it.
Fixed in v2.
v2 forthcoming...
b.a.t.m.a.n@lists.open-mesh.org