* [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