b.a.t.m.a.n.lists.open-mesh.org archive mirror
 help / color / mirror / Atom feed
* [B.A.T.M.A.N.] [PATCH 0/3] batctl: Use libnl(-tiny) for netlink communication
@ 2014-01-06 19:35 Sven Eckelmann
  2014-01-06 19:37 ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Avoid name clash "rtnl_open" with libnl Sven Eckelmann
  2014-01-16 21:11 ` [B.A.T.M.A.N.] [PATCH 0/3] batctl: Use libnl(-tiny) for netlink communication Antonio Quartulli
  0 siblings, 2 replies; 10+ messages in thread
From: Sven Eckelmann @ 2014-01-06 19:35 UTC (permalink / raw)
  To: B.A.T.M.A.N

[-- Attachment #1: Type: text/plain, Size: 1222 bytes --]

Hi,

the current release 2014.0.0 made some problems for me because Debian the new 
function "rtnl_open" conflicted with libnl-3.0. libnl-3.0 was used in the 
Debian package to follow the Debian policy chapter 4 about duplicated code.

Using libnl should not be a problem for any linux system because everyone uses 
it when wireless configuration is done. For example libnl-tiny is already used 
by the normal OpenWrt system in base system packages:

 * netifd
 * swconfig
 * authsae
 * hostapd
 * iproute2
 * iw
 * iwinfo

So it is nearly impossible to not have installed ;)

An additional benefit is the already tested code, better type checks and more 
linear code instead of lot of loops to parse the data.

The Makefile is written in such a way that it:

 * tries to find pkg-config (can be overwritten by setting PKG_CONFIG as
    environment variable/make parameter)
 * tries to find the libnl CFLAGS + LDLIBS (can be avoided by setting
    LIBNL_CFLAGS/LIBNL_LDLIBS as environment variable/make parameter)
 ** the search for the CFLAGS + LDLIBS is done using pkg-config using the
    library name libnl-3.0 (this can be changed by setting LIBNL_NAME
    as environment variable/make parameter)

Kind regards,
	Sven

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [B.A.T.M.A.N.] [PATCH 1/3] batctl: Avoid name clash "rtnl_open" with libnl
  2014-01-06 19:35 [B.A.T.M.A.N.] [PATCH 0/3] batctl: Use libnl(-tiny) for netlink communication Sven Eckelmann
@ 2014-01-06 19:37 ` Sven Eckelmann
  2014-01-06 19:37   ` [B.A.T.M.A.N.] [PATCH 2/3] batctl: Use libnl to implement mac resolver Sven Eckelmann
                     ` (2 more replies)
  2014-01-16 21:11 ` [B.A.T.M.A.N.] [PATCH 0/3] batctl: Use libnl(-tiny) for netlink communication Antonio Quartulli
  1 sibling, 3 replies; 10+ messages in thread
From: Sven Eckelmann @ 2014-01-06 19:37 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

libnl is used in Debian to avoid code duplication which should be avoided to
reduce maintenance and security risks. This library already provides a
function called rtnl_open and therefore has a name clash with the self defined
function.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
 functions.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/functions.c b/functions.c
index 8894df4..10a7f86 100644
--- a/functions.c
+++ b/functions.c
@@ -499,13 +499,13 @@ static void request_mac_resolve(int ai_family, const void *l3addr)
 }
 
 /**
- * rtnl_open - open a socket to rtnl and send a request
+ * batadv_rtnl_open - open a socket to rtnl and send a request
  * @nh: the header of the request to send
  * @protocol: the protocol to use when opening the socket
  *
  * Return 0 on success or a negative error code otherwise
  */
-static int rtnl_open(void *req, int protocol)
+static int batadv_rtnl_open(void *req, int protocol)
 {
 	static uint32_t nr_call = 0;
 	uint32_t pid = (++nr_call + getpid()) & 0x3FFFFF;
@@ -555,7 +555,7 @@ static int resolve_mac_from_cache_open(int ai_family)
 	nlreq.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
 	nlreq.msg.ndm_family = ai_family;
 
-	return rtnl_open(&nlreq, NETLINK_ROUTE);
+	return batadv_rtnl_open(&nlreq, NETLINK_ROUTE);
 }
 
 static ssize_t resolve_mac_from_cache_dump(int sock, void **buf, size_t *buflen)
@@ -890,7 +890,7 @@ static int vlan_get_link_open(const char *ifname)
 	nlreq.ifi.ifi_family = AF_UNSPEC;
 	nlreq.ifi.ifi_index = if_nametoindex(ifname);
 
-	return rtnl_open(&nlreq, 0);
+	return batadv_rtnl_open(&nlreq, 0);
 }
 
 /**
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [B.A.T.M.A.N.] [PATCH 2/3] batctl: Use libnl to implement mac resolver
  2014-01-06 19:37 ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Avoid name clash "rtnl_open" with libnl Sven Eckelmann
@ 2014-01-06 19:37   ` Sven Eckelmann
  2014-01-23  8:21     ` Marek Lindner
  2014-01-06 19:37   ` [B.A.T.M.A.N.] [PATCH 3/3] batctl: Use libnl to implement vlan parent device resolver Sven Eckelmann
  2014-01-23  7:28   ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Avoid name clash "rtnl_open" with libnl Marek Lindner
  2 siblings, 1 reply; 10+ messages in thread
From: Sven Eckelmann @ 2014-01-06 19:37 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

It is not necessary to have code duplicated which is already available in
libraries like libnl-3.0 or libnl-tiny. This is done to reduce maintenance and
security risks.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
 Makefile    |  18 ++++
 functions.c | 312 +++++++++++++++++++++++++-----------------------------------
 2 files changed, 149 insertions(+), 181 deletions(-)

diff --git a/Makefile b/Makefile
index fc0925d..0eb71a1 100755
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,24 @@ ifndef V
 endif
 endif
 
+ifeq ($(origin PKG_CONFIG), undefined)
+  PKG_CONFIG = pkg-config
+  ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),)
+    $(error $(PKG_CONFIG) not found)
+  endif
+endif
+
+ifeq ($(origin LIBNL_CFLAGS) $(origin LIBNL_LDLIBS), undefined undefined)
+  LIBNL_NAME ?= libnl-3.0
+  ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBNL_NAME) 2>/dev/null),)
+    $(error No $(LIBNL_NAME) development libraries found!)
+  endif
+  LIBNL_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBNL_NAME))
+  LIBNL_LDLIBS +=  $(shell $(PKG_CONFIG) --libs $(LIBNL_NAME))
+endif
+CFLAGS += $(LIBNL_CFLAGS)
+LDLIBS += $(LIBNL_LDLIBS)
+
 # standard build tools
 ifeq ($(CONFIG_BATCTL_BISECT),y)
 OBJ += $(OBJ_BISECT)
diff --git a/functions.c b/functions.c
index 10a7f86..c21431c 100644
--- a/functions.c
+++ b/functions.c
@@ -38,9 +38,13 @@
 #include <net/ethernet.h>
 #include <linux/rtnetlink.h>
 #include <linux/neighbour.h>
-#include <sys/uio.h>
 #include <errno.h>
 #include <net/if.h>
+#include <netlink/socket.h>
+#include <netlink/netlink.h>
+#include <netlink/handlers.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
 
 #include "main.h"
 #include "functions.h"
@@ -457,47 +461,6 @@ static int resolve_l3addr(int ai_family, const char *asc, void *l3addr)
 	return ret;
 }
 
-static void request_mac_resolve(int ai_family, const void *l3addr)
-{
-	const struct sockaddr *sockaddr;
-	struct sockaddr_in inet4;
-	struct sockaddr_in6 inet6;
-	size_t sockaddr_len;
-	int sock;
-	char t = 0;
-
-	sock = socket(ai_family, SOCK_DGRAM, IPPROTO_UDP);
-	if (sock < 0)
-		return;
-
-	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;
-	case AF_INET6:
-		memset(&inet6, 0, sizeof(inet6));
-		inet6.sin6_family = ai_family;
-		inet6.sin6_port = htons(9);
-		memcpy(&inet6.sin6_addr.s6_addr, l3addr,
-		       sizeof(inet6.sin6_addr.s6_addr));
-		sockaddr = (const struct sockaddr *)&inet6;
-		sockaddr_len = sizeof(inet6);
-		break;
-	default:
-		close(sock);
-		return;
-	}
-
-	sendto(sock, &t, sizeof(t), 0, sockaddr, sockaddr_len);
-	close(sock);
-}
-
 /**
  * batadv_rtnl_open - open a socket to rtnl and send a request
  * @nh: the header of the request to send
@@ -542,178 +505,165 @@ outclose:
 	return ret;
 }
 
-static int resolve_mac_from_cache_open(int ai_family)
+static void request_mac_resolve(int ai_family, const void *l3addr)
 {
-	struct {
-		struct nlmsghdr hdr;
-		struct ndmsg msg;
-	} nlreq;
-
-	memset(&nlreq, 0, sizeof(nlreq));
-	nlreq.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(nlreq.msg));
-	nlreq.hdr.nlmsg_type = RTM_GETNEIGH;
-	nlreq.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
-	nlreq.msg.ndm_family = ai_family;
+	const struct sockaddr *sockaddr;
+	struct sockaddr_in inet4;
+	struct sockaddr_in6 inet6;
+	size_t sockaddr_len;
+	int sock;
+	char t = 0;
 
-	return batadv_rtnl_open(&nlreq, NETLINK_ROUTE);
-}
+	sock = socket(ai_family, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock < 0)
+		return;
 
-static ssize_t resolve_mac_from_cache_dump(int sock, void **buf, size_t *buflen)
-{
-	struct iovec iov;
-	struct msghdr msg;
-	ssize_t ret = -1;
-	int flags = MSG_PEEK | MSG_TRUNC;
+	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;
+	case AF_INET6:
+		memset(&inet6, 0, sizeof(inet6));
+		inet6.sin6_family = ai_family;
+		inet6.sin6_port = htons(9);
+		memcpy(&inet6.sin6_addr.s6_addr, l3addr,
+		       sizeof(inet6.sin6_addr.s6_addr));
+		sockaddr = (const struct sockaddr *)&inet6;
+		sockaddr_len = sizeof(inet6);
+		break;
+	default:
+		close(sock);
+		return;
+	}
 
-	memset(&msg, 0, sizeof(msg));
-	memset(&iov, 0, sizeof(iov));
+	sendto(sock, &t, sizeof(t), 0, sockaddr, sockaddr_len);
+	close(sock);
+}
 
-	msg.msg_iov = &iov;
-	msg.msg_iovlen = 1;
-	msg.msg_controllen = 0;
-	msg.msg_control = NULL;
-	msg.msg_flags = 0;
+struct resolve_mac_nl_arg {
+	int ai_family;
+	const void *l3addr;
+	struct ether_addr *mac_result;
+	int found;
+};
 
-	iov.iov_len = *buflen;
-	iov.iov_base = *buf;
+static struct nla_policy neigh_policy[NDA_MAX+1] = {
+	[NDA_CACHEINFO] = { .minlen = sizeof(struct nda_cacheinfo) },
+	[NDA_PROBES]    = { .type = NLA_U32 },
+};
 
-	ret = recvmsg(sock, &msg, flags);
+static int resolve_mac_from_parse(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *tb[NDA_MAX + 1];
+	struct ndmsg *nm;
+	int ret;
+	int l3_len;
+	struct resolve_mac_nl_arg *nl_arg = arg;
+	uint8_t *mac;
+	uint8_t *l3addr;
+
+	nm = nlmsg_data(nlmsg_hdr(msg));
+	ret = nlmsg_parse(nlmsg_hdr(msg), sizeof(*nm), tb, NDA_MAX,
+			  neigh_policy);
 	if (ret < 0)
 		goto err;
 
-	if (msg.msg_flags & MSG_TRUNC) {
-		if ((size_t)ret <= *buflen) {
-			ret = -ENOBUFS;
-			goto err;
-		}
-
-		while (*buflen <= (size_t)ret) {
-			if (*buflen == 0)
-				*buflen = 1;
-			*buflen *= 2;
-		}
+	if (nl_arg->ai_family != nm->ndm_family)
+		goto err;
 
-		*buf = realloc(*buf, *buflen);
-		if (!*buf) {
-			ret = -ENOMEM;
-			*buflen = 0;
-			goto err;
-		}
+	switch (nl_arg->ai_family) {
+	case AF_INET:
+		l3_len = 4;
+		break;
+	case AF_INET6:
+		l3_len = 16;
+		break;
+	default:
+		l3_len = 0;
 	}
-	flags = 0;
 
-	ret = recvmsg(sock, &msg, flags);
-	if (ret < 0)
+	if (l3_len == 0)
 		goto err;
 
-	return ret;
-err:
-	free(*buf);
-	*buf = NULL;
-	return ret;
-}
+	if (!tb[NDA_LLADDR] || !tb[NDA_DST])
+		goto err;
 
-static int resolve_mac_from_cache_parse(struct ndmsg *ndmsg, size_t len_payload,
-					struct ether_addr *mac_addr,
-					uint8_t *l3addr,
-					size_t l3_len)
-{
-	int l3found, llfound;
-	struct rtattr *rtattr;
-	struct ether_addr mac_empty;
-
-	l3found = 0;
-	llfound = 0;
-	memset(&mac_empty, 0, sizeof(mac_empty));
-
-	for (rtattr = RTM_RTA(ndmsg); RTA_OK(rtattr, len_payload);
-		rtattr = RTA_NEXT(rtattr, len_payload)) {
-		switch (rtattr->rta_type) {
-		case NDA_DST:
-			memcpy(l3addr, RTA_DATA(rtattr), l3_len);
-			l3found = 1;
-			break;
-		case NDA_LLADDR:
-			memcpy(mac_addr, RTA_DATA(rtattr), ETH_ALEN);
-			if (memcmp(mac_addr, &mac_empty,
-					sizeof(mac_empty)) == 0)
-				llfound = 0;
-			else
-				llfound = 1;
-			break;
-		}
+	if (nla_len(tb[NDA_LLADDR]) != ETH_ALEN)
+		goto err;
+
+	if (nla_len(tb[NDA_DST]) != l3_len)
+		goto err;
+
+	mac = nla_data(tb[NDA_LLADDR]);
+	l3addr = nla_data(tb[NDA_DST]);
+
+	if (memcmp(nl_arg->l3addr, l3addr, l3_len) == 0) {
+		memcpy(nl_arg->mac_result, mac, ETH_ALEN);
+		nl_arg->found = 1;
 	}
 
-	return l3found && llfound;
+err:
+	if (nl_arg->found)
+		return NL_STOP;
+	else
+		return NL_OK;
 }
 
 static struct ether_addr *resolve_mac_from_cache(int ai_family,
 						 const void *l3addr)
 {
-	uint8_t l3addr_tmp[16];
-	static struct ether_addr mac_tmp;
+	struct nl_sock *sock;
 	struct ether_addr *mac_result = NULL;
-	void *buf = NULL;
-	size_t buflen;
-	struct nlmsghdr *nh;
-	ssize_t len;
-	size_t l3_len, mlen;
-	int socknl;
-	int parsed;
-	int finished = 0;
-
-	switch (ai_family) {
-	case AF_INET:
-		l3_len = 4;
-		break;
-	case AF_INET6:
-		l3_len = 16;
-		break;
-	default:
-		l3_len = 0;
-	}
-
-	buflen = 8192;
-	buf = malloc(buflen);
-	if (!buf)
+	static struct ether_addr mac_tmp;
+	int ret;
+	struct rtgenmsg gmsg = {
+		.rtgen_family = ai_family,
+	};
+	struct nl_cb *cb = NULL;
+	struct resolve_mac_nl_arg arg = {
+		.ai_family = ai_family,
+		.l3addr = l3addr,
+		.mac_result = &mac_tmp,
+		.found = 0,
+	};
+
+	sock = nl_socket_alloc();
+	if (!sock)
 		goto err;
 
-	socknl = resolve_mac_from_cache_open(ai_family);
-	if (socknl < 0)
+	ret = nl_connect(sock, NETLINK_ROUTE);
+	if (ret < 0)
 		goto err;
 
+	ret = nl_send_simple(sock, RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_DUMP,
+			     &gmsg, sizeof(gmsg));
+	if (ret < 0)
+		goto err;
 
-	while (!finished) {
-		len = resolve_mac_from_cache_dump(socknl, &buf, &buflen);
-		if (len < 0)
-			goto err_sock;
-		mlen = len;
+	cb = nl_cb_alloc(NL_CB_DEFAULT);
+	if (!cb)
+		goto err;
 
-		for (nh = buf; NLMSG_OK(nh, mlen); nh = NLMSG_NEXT(nh, mlen)) {
-			if (nh->nlmsg_type == NLMSG_DONE) {
-				finished = 1;
-				break;
-			}
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, resolve_mac_from_parse, &arg);
+	ret = nl_recvmsgs(sock, cb);
+	if (ret < 0)
+		goto err;
 
-			parsed = resolve_mac_from_cache_parse(NLMSG_DATA(nh),
-							      RTM_PAYLOAD(nh),
-							      &mac_tmp,
-							      l3addr_tmp,
-							      l3_len);
-			if (parsed) {
-				if (memcmp(&l3addr_tmp, l3addr, l3_len) == 0) {
-					mac_result = &mac_tmp;
-					finished = 1;
-					break;
-				}
-			}
-		}
-	}
+	if (arg.found)
+		mac_result = &mac_tmp;
 
-err_sock:
-	close(socknl);
 err:
-	free(buf);
+	if (cb)
+		nl_cb_put(cb);
+	if (sock)
+		nl_socket_free(sock);
+
 	return mac_result;
 }
 
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [B.A.T.M.A.N.] [PATCH 3/3] batctl: Use libnl to implement vlan parent device resolver
  2014-01-06 19:37 ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Avoid name clash "rtnl_open" with libnl Sven Eckelmann
  2014-01-06 19:37   ` [B.A.T.M.A.N.] [PATCH 2/3] batctl: Use libnl to implement mac resolver Sven Eckelmann
@ 2014-01-06 19:37   ` Sven Eckelmann
  2014-01-27  6:22     ` Marek Lindner
  2014-01-23  7:28   ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Avoid name clash "rtnl_open" with libnl Marek Lindner
  2 siblings, 1 reply; 10+ messages in thread
From: Sven Eckelmann @ 2014-01-06 19:37 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

It is not necessary to have code duplicated which is already available in
libraries like libnl-3.0 or libnl-tiny. This is done to reduce maintenance and
security risks.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
 functions.c | 274 ++++++++++++++++++++++++------------------------------------
 1 file changed, 110 insertions(+), 164 deletions(-)

diff --git a/functions.c b/functions.c
index c21431c..36804bd 100644
--- a/functions.c
+++ b/functions.c
@@ -461,50 +461,6 @@ static int resolve_l3addr(int ai_family, const char *asc, void *l3addr)
 	return ret;
 }
 
-/**
- * batadv_rtnl_open - open a socket to rtnl and send a request
- * @nh: the header of the request to send
- * @protocol: the protocol to use when opening the socket
- *
- * Return 0 on success or a negative error code otherwise
- */
-static int batadv_rtnl_open(void *req, int protocol)
-{
-	static uint32_t nr_call = 0;
-	uint32_t pid = (++nr_call + getpid()) & 0x3FFFFF;
-	struct sockaddr_nl addrnl;
-	struct nlmsghdr *nh;
-	int socknl;
-	int ret;
-
-	memset(&addrnl, 0, sizeof(addrnl));
-	addrnl.nl_family = AF_NETLINK;
-	addrnl.nl_pid = pid;
-	addrnl.nl_groups = 0;
-
-	socknl = socket(AF_NETLINK, SOCK_RAW, protocol);
-	if (socknl < 0)
-		goto out;
-
-	ret = bind(socknl, (struct sockaddr*)&addrnl, sizeof(addrnl));
-	if (ret < 0)
-		goto outclose;
-
-	/* the nlmsghdr object must always be the first member in the req
-	 * structure
-	 */
-	nh = (struct nlmsghdr *)req;
-
-	ret = send(socknl, nh, nh->nlmsg_len, 0);
-	if (ret < 0)
-		goto outclose;
-out:
-	return socknl;
-outclose:
-	close(socknl);
-	return ret;
-}
-
 static void request_mac_resolve(int ai_family, const void *l3addr)
 {
 	const struct sockaddr *sockaddr;
@@ -722,125 +678,95 @@ out:
 	return mac_result;
 }
 
+struct vlan_get_link_nl_arg {
+	char *iface;
+	int vid;
+};
+
+static struct nla_policy info_data_link_policy[IFLA_MAX + 1] = {
+	[IFLA_LINKINFO]	= { .type = NLA_NESTED },
+	[IFLA_LINK]	= { .type = NLA_U32 },
+};
+
+static struct nla_policy info_data_link_info_policy[IFLA_INFO_MAX + 1] = {
+	[IFLA_INFO_DATA]	= { .type = NLA_NESTED },
+};
+
+static struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = {
+	[IFLA_VLAN_ID]		= { .type = NLA_U16 },
+};
+
 /**
  * vlan_get_link_parse - parse a get_link rtnl message and extract the important
  *  data
- * @nh: the reply header
- * @iface: pointer to the buffer where the link interface has to be stored (it
- *  is allocated by this function)
+ * @msg: the reply msg
+ * @arg: pointer to the buffer which will store the return values
  *
- * Return the vid in case of success or -1 otherwise
+ * Saves the vid  in arg::vid in case of success or -1 otherwise
  */
-static int vlan_get_link_parse(struct nlmsghdr *nh, char **iface)
+static int vlan_get_link_parse(struct nl_msg *msg, void *arg)
 {
-	struct ifinfomsg *ifi = NLMSG_DATA(nh);
-	size_t vlan_len, info_len, len = nh->nlmsg_len;
-	struct rtattr *rta, *info, *vlan;
-	int idx = -1, vid = -1;
-
-	*iface = NULL;
-
-	rta = IFLA_RTA(ifi);
-	while (RTA_OK(rta, len)) {
-		/* check if the interface is a vlan */
-		if (rta->rta_type == IFLA_LINKINFO) {
-			info = RTA_DATA(rta);
-			info_len = RTA_PAYLOAD(rta);
-
-			while (RTA_OK(info, info_len)) {
-				if (info->rta_type == IFLA_INFO_KIND &&
-				    strcmp(RTA_DATA(info), "vlan"))
-					goto err;
-
-				if (info->rta_type == IFLA_INFO_DATA) {
-					vlan = RTA_DATA(info);
-					vlan_len = RTA_PAYLOAD(info);
-
-					while (RTA_OK(vlan, vlan_len)) {
-						if (vlan->rta_type == IFLA_VLAN_ID)
-							vid = *(int *)RTA_DATA(vlan);
-						vlan = RTA_NEXT(vlan, vlan_len);
-					}
-				}
-				info = RTA_NEXT(info, info_len);
-			}
-		}
+	struct vlan_get_link_nl_arg *nl_arg = arg;
+	struct nlmsghdr *n = nlmsg_hdr(msg);
+	struct nlattr *tb[IFLA_MAX + 1];
+	struct nlattr *li[IFLA_INFO_MAX + 1];
+	struct nlattr *vi[IFLA_VLAN_MAX + 1];
+	int ret;
+	int idx;
 
-		/* extract the name of the "link" interface */
-		if (rta->rta_type == IFLA_LINK) {
-			idx = *(int *)RTA_DATA(rta);
+	if (!nlmsg_valid_hdr(n, sizeof(struct ifinfomsg)))
+		return -NLE_MSG_TOOSHORT;
 
-			*iface = malloc(IFNAMSIZ + 1);
-			if (!if_indextoname(idx, *iface))
-				goto err;
-		}
-		rta = RTA_NEXT(rta, len);
-	}
+	ret = nlmsg_parse(n, sizeof(struct ifinfomsg), tb, IFLA_MAX,
+			  info_data_link_policy);
+	if (ret < 0)
+		return ret;
 
-	if (vid == -1)
-		goto err;
+	if (!tb[IFLA_LINK])
+		return -NLE_MISSING_ATTR;
 
-	if (idx <= 0)
-		goto err;
+	/* parse subattributes linkinfo */
+	if (!tb[IFLA_LINKINFO])
+		return -NLE_MISSING_ATTR;
 
-	return vid;
-err:
-	free(*iface);
-	return -1;
-}
+	ret = nla_parse_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO],
+			       info_data_link_info_policy);
+	if (ret < 0)
+		return ret;
 
-/**
- * vlan_get_link_dump - receive and dump a get_link rtnl reply
- * @sock: the socket to listen for the reply on
- * @buf: buffer where the reply has to be dumped to
- * @buflen: length of the buffer
- *
- * Returns the amount of dumped bytes
- */
-static ssize_t vlan_get_link_dump(int sock, void *buf, size_t buflen)
-{
-	struct sockaddr_nl nladdr;
-	struct msghdr msg;
-	struct iovec iov;
+	if (!li[IFLA_INFO_KIND])
+		return -NLE_MISSING_ATTR;
 
-	memset(&msg, 0, sizeof(msg));
-	memset(&iov, 0, sizeof(iov));
+	if (strcmp(nla_data(li[IFLA_INFO_KIND]), "vlan") != 0)
+		goto err;
 
-	msg.msg_iov = &iov;
-	msg.msg_iovlen = 1;
-	msg.msg_controllen = 0;
-	msg.msg_control = NULL;
-	msg.msg_flags = 0;
-	msg.msg_name = &nladdr;
-	msg.msg_namelen = sizeof(nladdr);
+	/* parse subattributes info_data for vlan */
+	if (!li[IFLA_INFO_DATA])
+		return -NLE_MISSING_ATTR;
 
-	iov.iov_len = buflen;
-	iov.iov_base = buf;
+	ret = nla_parse_nested(vi, IFLA_VLAN_MAX, li[IFLA_INFO_DATA],
+			       vlan_policy);
+	if (ret < 0)
+		return ret;
 
-	return recvmsg(sock, &msg, 0);
-}
+	if (!vi[IFLA_VLAN_ID])
+		return -NLE_MISSING_ATTR;
 
-/**
- * vlan_get_link_open - send a get_link request
- * @ifname: the interface to query
- *
- * Returns 0 in case of success or a negative error code otherwise
- */
-static int vlan_get_link_open(const char *ifname)
-{
-	struct {
-		struct nlmsghdr hdr;
-		struct ifinfomsg ifi;
-	} nlreq;
-
-	memset(&nlreq, 0, sizeof(nlreq));
-	nlreq.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(nlreq.ifi));
-	nlreq.hdr.nlmsg_type = RTM_GETLINK;
-	nlreq.hdr.nlmsg_flags = NLM_F_REQUEST;
-	nlreq.ifi.ifi_family = AF_UNSPEC;
-	nlreq.ifi.ifi_index = if_nametoindex(ifname);
-
-	return batadv_rtnl_open(&nlreq, 0);
+	/* get parent link name */
+	idx = *(int *)nla_data(tb[IFLA_LINK]);
+	free(nl_arg->iface);
+	nl_arg->iface = malloc(IFNAMSIZ + 1);
+	if (!if_indextoname(idx, nl_arg->iface))
+		goto err;
+
+	/* get the corresponding vid */
+	nl_arg->vid = *(int *)nla_data(vi[IFLA_VLAN_ID]);
+
+err:
+	if (nl_arg->vid >= 0)
+		return NL_STOP;
+	else
+		return NL_OK;
 }
 
 /**
@@ -853,29 +779,49 @@ static int vlan_get_link_open(const char *ifname)
  */
 int vlan_get_link(const char *ifname, char **parent)
 {
-	int vid = -1, socknl;
-	void *buf = NULL;
-	size_t buflen;
-	ssize_t len;
-
-	buflen = 8192;
-	buf = malloc(buflen);
-	if (!buf)
+	struct nl_sock *sock;
+	int ret;
+	struct ifinfomsg ifinfo = {
+		.ifi_family = AF_UNSPEC,
+		.ifi_index = if_nametoindex(ifname),
+	};
+	struct nl_cb *cb = NULL;
+	struct vlan_get_link_nl_arg arg = {
+		.iface = NULL,
+		.vid = -1,
+	};
+
+	*parent = NULL;
+
+	sock = nl_socket_alloc();
+	if (!sock)
+		goto err;
+
+	ret = nl_connect(sock, NETLINK_ROUTE);
+	if (ret < 0)
+		goto err;
+
+	ret = nl_send_simple(sock, RTM_GETLINK, NLM_F_REQUEST,
+			     &ifinfo, sizeof(ifinfo));
+	if (ret < 0)
 		goto err;
 
-	socknl = vlan_get_link_open(ifname);
-	if (socknl < 0)
+	cb = nl_cb_alloc(NL_CB_DEFAULT);
+	if (!cb)
 		goto err;
 
-	len = vlan_get_link_dump(socknl, buf, buflen);
-	if (len < 0)
-		goto err_sock;
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, vlan_get_link_parse, &arg);
+	ret = nl_recvmsgs(sock, cb);
+	if (ret < 0)
+		goto err;
 
-	vid = vlan_get_link_parse(buf, parent);
+	*parent = arg.iface;
 
-err_sock:
-	close(socknl);
 err:
-	free(buf);
-	return vid;
+	if (cb)
+		nl_cb_put(cb);
+	if (sock)
+		nl_socket_free(sock);
+
+	return arg.vid;
 }
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCH 0/3] batctl: Use libnl(-tiny) for netlink communication
  2014-01-06 19:35 [B.A.T.M.A.N.] [PATCH 0/3] batctl: Use libnl(-tiny) for netlink communication Sven Eckelmann
  2014-01-06 19:37 ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Avoid name clash "rtnl_open" with libnl Sven Eckelmann
@ 2014-01-16 21:11 ` Antonio Quartulli
  2014-01-17  9:37   ` Sven Eckelmann
  1 sibling, 1 reply; 10+ messages in thread
From: Antonio Quartulli @ 2014-01-16 21:11 UTC (permalink / raw)
  To: Sven Eckelmann; +Cc: The list for a Better Approach To Mobile Ad-hoc Networking

[-- Attachment #1: Type: text/plain, Size: 1174 bytes --]

Hi Sven,

On 06/01/14 20:35, Sven Eckelmann wrote:
> Hi,
> 
> the current release 2014.0.0 made some problems for me because Debian the new 
> function "rtnl_open" conflicted with libnl-3.0. libnl-3.0 was used in the 
> Debian package to follow the Debian policy chapter 4 about duplicated code.
> 
> Using libnl should not be a problem for any linux system because everyone uses 
> it when wireless configuration is done. For example libnl-tiny is already used 
> by the normal OpenWrt system in base system packages:

I think that it may still be the case that we want to compile batctl on
an host without libnl.

In the end batman-adv can run on Ethernet and we may have an embedded
system with no wifi which has no libnl at all.

I was wondering....what if we check if libnl is installed or not and in
case it is missing we disable the address translation and vlan operations?
In this way we can add the dependency to libnl and avoid code
duplication but at the same time we keep libnl-free users happy.

I think batctl can be useful for many things, also if libnl is not
installed.

What do you think?

Cheers,

-- 
Antonio Quartulli


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCH 0/3] batctl: Use libnl(-tiny) for netlink communication
  2014-01-16 21:11 ` [B.A.T.M.A.N.] [PATCH 0/3] batctl: Use libnl(-tiny) for netlink communication Antonio Quartulli
@ 2014-01-17  9:37   ` Sven Eckelmann
  2014-01-19 10:20     ` Antonio Quartulli
  0 siblings, 1 reply; 10+ messages in thread
From: Sven Eckelmann @ 2014-01-17  9:37 UTC (permalink / raw)
  To: Antonio Quartulli
  Cc: The list for a Better Approach To Mobile Ad-hoc Networking

[-- Attachment #1: Type: text/plain, Size: 1012 bytes --]

On Thursday 16 January 2014 22:11:38 Antonio Quartulli wrote:
> I think that it may still be the case that we want to compile batctl on
> an host without libnl.

We == "I have this use case"?

> In the end batman-adv can run on Ethernet and we may have an embedded
> system with no wifi which has no libnl at all.

(Now a little bit sarcasm): batctl can also run without batman-adv, please 
allow to drop the useless sysfs/debugfs stuff ;)

> I was wondering....what if we check if libnl is installed or not and in
> case it is missing we disable the address translation and vlan operations?
> In this way we can add the dependency to libnl and avoid code
> duplication but at the same time we keep libnl-free users happy.

I agree that it is possible but would like to avoid to provide a "fallback" 
because it justs adds more complexity without an actual use case (please 
correct me but I don't see it right now).

If you still think it is necessary then please feel free to add it later.

Kind regards,
	Sven

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCH 0/3] batctl: Use libnl(-tiny) for netlink communication
  2014-01-17  9:37   ` Sven Eckelmann
@ 2014-01-19 10:20     ` Antonio Quartulli
  0 siblings, 0 replies; 10+ messages in thread
From: Antonio Quartulli @ 2014-01-19 10:20 UTC (permalink / raw)
  To: The list for a Better Approach To Mobile Ad-hoc Networking

[-- Attachment #1: Type: text/plain, Size: 1418 bytes --]

On 17/01/14 10:37, Sven Eckelmann wrote:
> On Thursday 16 January 2014 22:11:38 Antonio Quartulli wrote:
>> I think that it may still be the case that we want to compile batctl on
>> an host without libnl.
> 
> We == "I have this use case"?
> 
>> In the end batman-adv can run on Ethernet and we may have an embedded
>> system with no wifi which has no libnl at all.
> 
> (Now a little bit sarcasm): batctl can also run without batman-adv, please 
> allow to drop the useless sysfs/debugfs stuff ;)
> 
>> I was wondering....what if we check if libnl is installed or not and in
>> case it is missing we disable the address translation and vlan operations?
>> In this way we can add the dependency to libnl and avoid code
>> duplication but at the same time we keep libnl-free users happy.
> 
> I agree that it is possible but would like to avoid to provide a "fallback" 
> because it justs adds more complexity without an actual use case (please 
> correct me but I don't see it right now).
> 

My use case was only about an embedded device (e.g. raspberry pi) having
an Eth connection but no wireless at all, thus it may not have libnl.

> If you still think it is necessary then please feel free to add it later.
> 

Anyway I agree with you: that requires too much complexity for a very
little gain.

I like this patchset as it is.

Thanks.

Cheers,


-- 
Antonio Quartulli


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCH 1/3] batctl: Avoid name clash "rtnl_open" with libnl
  2014-01-06 19:37 ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Avoid name clash "rtnl_open" with libnl Sven Eckelmann
  2014-01-06 19:37   ` [B.A.T.M.A.N.] [PATCH 2/3] batctl: Use libnl to implement mac resolver Sven Eckelmann
  2014-01-06 19:37   ` [B.A.T.M.A.N.] [PATCH 3/3] batctl: Use libnl to implement vlan parent device resolver Sven Eckelmann
@ 2014-01-23  7:28   ` Marek Lindner
  2 siblings, 0 replies; 10+ messages in thread
From: Marek Lindner @ 2014-01-23  7:28 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

[-- Attachment #1: Type: text/plain, Size: 488 bytes --]

On Monday 06 January 2014 20:37:22 Sven Eckelmann wrote:
> libnl is used in Debian to avoid code duplication which should be avoided to
> reduce maintenance and security risks. This library already provides a
> function called rtnl_open and therefore has a name clash with the self
> defined function.
> 
> Signed-off-by: Sven Eckelmann <sven@narfation.org>
> ---
>  functions.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)

Applied in revision f8eb19d.

Thanks,
Marek

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCH 2/3] batctl: Use libnl to implement mac resolver
  2014-01-06 19:37   ` [B.A.T.M.A.N.] [PATCH 2/3] batctl: Use libnl to implement mac resolver Sven Eckelmann
@ 2014-01-23  8:21     ` Marek Lindner
  0 siblings, 0 replies; 10+ messages in thread
From: Marek Lindner @ 2014-01-23  8:21 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

[-- Attachment #1: Type: text/plain, Size: 504 bytes --]

On Monday 06 January 2014 20:37:23 Sven Eckelmann wrote:
> It is not necessary to have code duplicated which is already available in
> libraries like libnl-3.0 or libnl-tiny. This is done to reduce maintenance
> and security risks.
> 
> Signed-off-by: Sven Eckelmann <sven@narfation.org>
> ---
>  Makefile    |  18 ++++
>  functions.c | 312
> +++++++++++++++++++++++++----------------------------------- 2 files
> changed, 149 insertions(+), 181 deletions(-)

Applied in revision 6212797.

Cheers,
Marek

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCH 3/3] batctl: Use libnl to implement vlan parent device resolver
  2014-01-06 19:37   ` [B.A.T.M.A.N.] [PATCH 3/3] batctl: Use libnl to implement vlan parent device resolver Sven Eckelmann
@ 2014-01-27  6:22     ` Marek Lindner
  0 siblings, 0 replies; 10+ messages in thread
From: Marek Lindner @ 2014-01-27  6:22 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

[-- Attachment #1: Type: text/plain, Size: 477 bytes --]

On Monday 06 January 2014 20:37:24 Sven Eckelmann wrote:
> It is not necessary to have code duplicated which is already available in
> libraries like libnl-3.0 or libnl-tiny. This is done to reduce maintenance
> and security risks.
> 
> Signed-off-by: Sven Eckelmann <sven@narfation.org>
> ---
>  functions.c | 274
> ++++++++++++++++++++++++------------------------------------ 1 file
> changed, 110 insertions(+), 164 deletions(-)

Applied in revision b8eaea8.

Thanks,
Marek

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2014-01-27  6:22 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-06 19:35 [B.A.T.M.A.N.] [PATCH 0/3] batctl: Use libnl(-tiny) for netlink communication Sven Eckelmann
2014-01-06 19:37 ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Avoid name clash "rtnl_open" with libnl Sven Eckelmann
2014-01-06 19:37   ` [B.A.T.M.A.N.] [PATCH 2/3] batctl: Use libnl to implement mac resolver Sven Eckelmann
2014-01-23  8:21     ` Marek Lindner
2014-01-06 19:37   ` [B.A.T.M.A.N.] [PATCH 3/3] batctl: Use libnl to implement vlan parent device resolver Sven Eckelmann
2014-01-27  6:22     ` Marek Lindner
2014-01-23  7:28   ` [B.A.T.M.A.N.] [PATCH 1/3] batctl: Avoid name clash "rtnl_open" with libnl Marek Lindner
2014-01-16 21:11 ` [B.A.T.M.A.N.] [PATCH 0/3] batctl: Use libnl(-tiny) for netlink communication Antonio Quartulli
2014-01-17  9:37   ` Sven Eckelmann
2014-01-19 10:20     ` Antonio Quartulli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).