Use MAC addr of interface when sending packets
authorJoseph C. Lehner <joseph.c.lehner@gmail.com>
Fri, 29 Jan 2016 21:05:24 +0000 (23:05 +0200)
committerJoseph C. Lehner <joseph.c.lehner@gmail.com>
Fri, 29 Jan 2016 21:05:24 +0000 (23:05 +0200)
ethsock.c
ethsock.h
nmrp.c

index 97d2cb51d2ee38381a832dca45efa45b0b12571f..40d992c008c27bebf021aa6d205ce88160a94be7 100644 (file)
--- a/ethsock.c
+++ b/ethsock.c
@@ -1,3 +1,8 @@
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <net/if_dl.h>
+#include <stdbool.h>
+#include <ifaddrs.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -13,8 +18,54 @@ struct ethsock
        pcap_t *pcap;
        struct timeval timeout;
        int fd;
+       uint8_t hwaddr[6];
 };
 
+static bool ethsock_fill_hwaddr(struct ethsock *sock, const char *interface)
+{
+       struct ifaddrs *ifas, *ifa;
+       void *src;
+       bool found;
+
+       if (getifaddrs(&ifas) != 0) {
+               perror("getifaddrs");
+               return false;
+       }
+
+       found = false;
+
+       for (ifa = ifas; ifa; ifa = ifa->ifa_next) {
+               if (!strcmp(ifa->ifa_name, interface)) {
+#ifdef __linux__
+                       if (ifa->ifa_addr->sa_family != AF_PACKET) {
+                               continue;
+                       }
+                       src = ((struct sockaddr_ll*)ifa->ifa_addr)->sll_addr;
+#else
+                       if (ifa->ifa_addr->sa_family != AF_LINK) {
+                               continue;
+                       }
+                       src = LLADDR((struct sockaddr_dl*)ifa->ifa_addr);
+#endif
+                       memcpy(sock->hwaddr, src, 6);
+                       found = true;
+                       break;
+               }
+       }
+
+       if (!found) {
+               fprintf(stderr, "Failed to get MAC address of interface %s.\n", interface);
+       }
+
+       freeifaddrs(ifas);
+       return found;
+}
+
+inline uint8_t *ethsock_get_hwaddr(struct ethsock *sock)
+{
+       return sock->hwaddr;
+}
+
 struct ethsock *ethsock_create(const char *interface, uint16_t protocol)
 {
        char buf[PCAP_ERRBUF_SIZE];
@@ -28,11 +79,15 @@ struct ethsock *ethsock_create(const char *interface, uint16_t protocol)
                return NULL;
        }
 
+       if (!ethsock_fill_hwaddr(sock, interface)) {
+               goto cleanup_malloc;
+       }
+
        buf[0] = '\0';
 
        sock->pcap = pcap_open_live(interface, BUFSIZ, 1, 1, buf);
        if (!sock->pcap) {
-               fprintf(stderr, "pcap_open_live: %s\n", buf);
+               fprintf(stderr, "%s\n", buf);
                goto cleanup_malloc;
        }
 
index 458a2d5c17675eaeadc07c7fc3cc057b03a46fa3..6e2c50f35983659679cb8ba54a6012e91ad78429 100644 (file)
--- a/ethsock.h
+++ b/ethsock.h
@@ -7,3 +7,4 @@ int ethsock_close(struct ethsock *sock);
 int ethsock_send(struct ethsock *sock, void *buf, size_t len);
 ssize_t ethsock_recv(struct ethsock *sock, void *buf, size_t len);
 int ethsock_set_timeout(struct ethsock *sock, unsigned msec);
+uint8_t *ethsock_get_hwaddr(struct ethsock *sock);
diff --git a/nmrp.c b/nmrp.c
index dd2388f5bc3e98616f75541d68d6fd8770d2fc25..43519fcdc3551d72664a4f81a504183ffc0211d9 100644 (file)
--- a/nmrp.c
+++ b/nmrp.c
@@ -249,7 +249,7 @@ static const char *spinner = "\\|/-";
 int nmrp_do(struct nmrpd_args *args)
 {
        struct nmrp_pkt tx, rx;
-       uint8_t src[6], dest[6];
+       uint8_t *src, dest[6];
        struct in_addr ipaddr, ipmask;
        time_t beg;
        int i, err, ulreqs, expect;
@@ -291,6 +291,11 @@ int nmrp_do(struct nmrpd_args *args)
                return 1;
        }
 
+       src = ethsock_get_hwaddr(sock);
+       if (!src) {
+               return 1;
+       }
+
        memcpy(tx.eh.ether_shost, src, 6);
        memcpy(tx.eh.ether_dhost, dest, 6);
        tx.eh.ether_type = htons(ETH_P_NMRP);