[alfred] Request MAC resolution for IPv4 address not in ARP cache
Commit Message
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(+)
Comments
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...
@@ -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);
@@ -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);
+}