[commits] [batctl] next: batctl: Reduce IPv4 focus of mac resolve functions (daf6aa6)

postmaster at open-mesh.org postmaster at open-mesh.org
Tue Sep 24 14:08:29 CEST 2013


Repository : ssh://git@open-mesh.org/batctl

On branch  : next

>---------------------------------------------------------------

commit daf6aa6aaa5ff5c3fad2b565b10c3ab9e79762b4
Author: Sven Eckelmann <sven at narfation.org>
Date:   Sun Sep 22 16:42:24 2013 +0200

    batctl: Reduce IPv4 focus of mac resolve functions
    
    The first implementation of the IP translation functions in
    cb75e019e74fc11f9547dadd51abbf3c9df2c5e7 ("batctl: Allow to use IPv4 addresses
    for ping/traceroute") had is focus on implementing it only for IPv4. This is a
    limitation when other layer 3 protocols are used.
    
    For example, a port to IPv6 would either have to copy the functionality or do a
    major refactoring when implementing the it resolv functionality. This is not
    necessary when the functions already expect different layer 3 protocols in the
    first place and make it easy to find the right place to modify them.
    
    Signed-off-by: Sven Eckelmann <sven at narfation.org>


>---------------------------------------------------------------

daf6aa6aaa5ff5c3fad2b565b10c3ab9e79762b4
 functions.c |   86 +++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 63 insertions(+), 23 deletions(-)

diff --git a/functions.c b/functions.c
index 1a33d6d..e4aeb72 100644
--- a/functions.c
+++ b/functions.c
@@ -416,49 +416,68 @@ out:
 	return mac_result;
 }
 
-static uint32_t resolve_ipv4(const char *asc)
+static int resolve_l3addr(int ai_family, const char *asc, void *l3addr)
 {
 	int ret;
 	struct addrinfo hints;
 	struct addrinfo *res;
 	struct sockaddr_in *inet4;
-	uint32_t addr = 0;
 
 	memset(&hints, 0, sizeof(hints));
-	hints.ai_family = AF_INET;
+	hints.ai_family = ai_family;
 	ret = getaddrinfo(asc, NULL, &hints, &res);
 	if (ret)
-		return 0;
+		return -EADDRNOTAVAIL;
 
 	if (res) {
-		inet4 = (struct sockaddr_in *)res->ai_addr;
-		addr = inet4->sin_addr.s_addr;
+		switch (ai_family) {
+		case AF_INET:
+			inet4 = (struct sockaddr_in *)res->ai_addr;
+			memcpy(l3addr, &inet4->sin_addr.s_addr,
+			       sizeof(inet4->sin_addr.s_addr));
+			break;
+		default:
+			ret = -EINVAL;
+		}
 	}
 
 	freeaddrinfo(res);
-	return addr;
+	return ret;
 }
 
-static void request_arp(uint32_t ipv4_addr)
+static void request_mac_resolve(int ai_family, const void *l3addr)
 {
+	const struct sockaddr *sockaddr;
 	struct sockaddr_in inet4;
+	size_t sockaddr_len;
 	int sock;
 	char t = 0;
 
-	memset(&inet4, 0, sizeof(inet4));
-	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	sock = socket(ai_family, SOCK_DGRAM, IPPROTO_UDP);
 	if (sock < 0)
 		return;
 
-	inet4.sin_family = AF_INET;
-	inet4.sin_port = htons(9);
-	inet4.sin_addr.s_addr = ipv4_addr;
-	sendto(sock, &t, sizeof(t), 0, (const struct sockaddr *)&inet4,
-	       sizeof(inet4));
+	switch (ai_family) {
+	case AF_INET:
+		memset(&inet4, 0, sizeof(inet4));
+		inet4.sin_family = ai_family;
+		inet4.sin_port = htons(9);
+		memcpy(&inet4.sin_addr.s_addr, l3addr,
+		       sizeof(inet4.sin_addr.s_addr));
+		sockaddr = (const struct sockaddr *)&inet4;
+		sockaddr_len = sizeof(inet4);
+		break;
+	default:
+		close(sock);
+		return;
+	}
+
+	sendto(sock, &t, sizeof(t), 0, sockaddr, sockaddr_len);
 	close(sock);
 }
 
-static struct ether_addr *resolve_mac_from_arp(uint32_t ipv4_addr)
+static struct ether_addr *resolve_mac_from_cache(int ai_family,
+						 const void *l3addr)
 {
 	struct ether_addr mac_empty;
 	struct ether_addr *mac_result = NULL, *mac_tmp = NULL;
@@ -471,7 +490,12 @@ static struct ether_addr *resolve_mac_from_arp(uint32_t ipv4_addr)
 	size_t column;
 	char *token, *input, *saveptr;
 	int line_invalid;
+	uint32_t ipv4_addr;
+
+	if (ai_family != AF_INET)
+		return NULL;
 
+	memcpy(&ipv4_addr, l3addr, sizeof(ipv4_addr));
 	memset(&mac_empty, 0, sizeof(mac_empty));
 
 	f = fopen("/proc/net/arp", "r");
@@ -527,20 +551,30 @@ static struct ether_addr *resolve_mac_from_arp(uint32_t ipv4_addr)
 	return mac_result;
 }
 
-static struct ether_addr *resolve_mac_from_ipv4(const char *asc)
+static struct ether_addr *resolve_mac_from_addr(int ai_family, const char *asc)
 {
-	uint32_t ipv4_addr;
+	uint8_t ipv4_addr[4];
+	void *l3addr;
+	int ret;
 	int retries = 5;
 	struct ether_addr *mac_result = NULL;
 
-	ipv4_addr = resolve_ipv4(asc);
-	if (!ipv4_addr)
+	switch (ai_family) {
+	case AF_INET:
+		l3addr = ipv4_addr;
+		break;
+	default:
+		return NULL;
+	}
+
+	ret = resolve_l3addr(ai_family, asc, l3addr);
+	if (ret < 0)
 		return NULL;
 
 	while (retries-- && !mac_result) {
-		mac_result = resolve_mac_from_arp(ipv4_addr);
+		mac_result = resolve_mac_from_cache(ai_family, l3addr);
 		if (!mac_result) {
-			request_arp(ipv4_addr);
+			request_mac_resolve(ai_family, l3addr);
 			usleep(200000);
 		}
 	}
@@ -551,12 +585,18 @@ static struct ether_addr *resolve_mac_from_ipv4(const char *asc)
 struct ether_addr *resolve_mac(const char *asc)
 {
 	struct ether_addr *mac_result = NULL;
+	static const int ai_families[] = {AF_INET};
+	size_t i;
 
 	mac_result = ether_aton(asc);
 	if (mac_result)
 		goto out;
 
-	mac_result = resolve_mac_from_ipv4(asc);
+	for (i = 0; i < sizeof(ai_families) / sizeof(*ai_families); i++) {
+		mac_result = resolve_mac_from_addr(ai_families[i], asc);
+		if (mac_result)
+			goto out;
+	}
 
 out:
 	return mac_result;



More information about the commits mailing list