summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am4
-rw-r--r--configure.in2
-rw-r--r--include/libnfnetlink/libnfnetlink.h19
-rw-r--r--src/Makefile.am4
-rw-r--r--src/iftable.c204
-rw-r--r--src/rtnl.c114
-rw-r--r--src/rtnl.h22
-rw-r--r--utils/Makefile.am7
-rw-r--r--utils/iftest.c31
9 files changed, 284 insertions, 123 deletions
diff --git a/Makefile.am b/Makefile.am
index a3fd156..86f4aae 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,8 +4,8 @@ AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
EXTRA_DIST = $(man_MANS) debian
-SUBDIRS = src include
-DIST_SUBDIRS = src include
+SUBDIRS = src include utils
+DIST_SUBDIRS = src include utils
man_MANS = #nfnetlink.3
diff --git a/configure.in b/configure.in
index 1479df1..1d5d1ee 100644
--- a/configure.in
+++ b/configure.in
@@ -22,4 +22,4 @@ dnl--------------------------------
dnl Output the makefile
-AC_OUTPUT(Makefile src/Makefile include/Makefile include/libnfnetlink/Makefile libnfnetlink.pc)
+AC_OUTPUT(Makefile src/Makefile include/Makefile include/libnfnetlink/Makefile utils/Makefile libnfnetlink.pc)
diff --git a/include/libnfnetlink/libnfnetlink.h b/include/libnfnetlink/libnfnetlink.h
index 28c0666..78985b5 100644
--- a/include/libnfnetlink/libnfnetlink.h
+++ b/include/libnfnetlink/libnfnetlink.h
@@ -175,6 +175,25 @@ extern unsigned int nfnl_rcvbufsiz(struct nfnl_handle *h, unsigned int size);
extern void nfnl_dump_packet(struct nlmsghdr *, int, char *);
+/*
+ * index to interface name API
+ */
+
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+
+struct nlif_handle;
+
+struct nlif_handle *nlif_open(void);
+void nlif_close(struct nlif_handle *orig);
+int nlif_fd(struct nlif_handle *nlif_handle);
+int nlif_query(struct nlif_handle *nlif_handle);
+int nlif_catch(struct nlif_handle *nlif_handle);
+int nlif_index2name(struct nlif_handle *nlif_handle,
+ unsigned int index,
+ char *name);
+
/* Pablo: What is the equivalence of be64_to_cpu in userspace?
*
* Harald: Good question. I don't think there's a standard way [yet?],
diff --git a/src/Makefile.am b/src/Makefile.am
index 3e25c76..def8175 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,4 +8,6 @@ lib_LTLIBRARIES = libnfnetlink.la
libnfnetlink_la_LDFLAGS = -Wc,-nostartfiles \
-version-info $(LIBVERSION)
-libnfnetlink_la_SOURCES = libnfnetlink.c
+libnfnetlink_la_SOURCES = libnfnetlink.c iftable.c rtnl.c
+
+noinst_HEADERS = iftable.h rtnl.c
diff --git a/src/iftable.c b/src/iftable.c
index 9c28a36..e97d2ba 100644
--- a/src/iftable.c
+++ b/src/iftable.c
@@ -19,6 +19,7 @@
#include <linux/netdevice.h>
+#include <libnfnetlink/libnfnetlink.h>
#include "rtnl.h"
#define iftb_log(x, ...)
@@ -34,27 +35,12 @@ struct ifindex_map {
char name[16];
};
-static struct ifindex_map *ifindex_map[16];
-
-/* iftable_dump - Dump the interface table to a given file stream
- * @outfd: file stream to which table should be dumped
- */
-int iftable_dump(FILE *outfd)
-{
- int i;
-
- for (i = 0; i < 16; i++) {
- struct ifindex_map *im;
- for (im = ifindex_map[i]; im; im = im->next) {
- fprintf(outfd, "%u %s", im->index, im->name);
- if (!(im->flags & IFF_UP))
- fputs(" DOWN", outfd);
- fputc('\n', outfd);
- }
- }
- fflush(outfd);
- return 0;
-}
+struct nlif_handle {
+ struct ifindex_map *ifindex_map[16];
+ struct rtnl_handle *rtnl_handle;
+ struct rtnl_handler *ifadd_handler;
+ struct rtnl_handler *ifdel_handler;
+};
/* iftable_add - Add/Update an entry to/in the interface table
* @n: netlink message header of a RTM_NEWLINK message
@@ -69,6 +55,7 @@ int iftable_add(struct nlmsghdr *n, void *arg)
struct ifinfomsg *ifi_msg = NLMSG_DATA(n);
struct ifindex_map *im, **imp;
struct rtattr *cb[IFLA_MAX+1];
+ struct nlif_handle *nlif_handle = (struct nlif_handle *)arg;
if (n->nlmsg_type != RTM_NEWLINK)
return -1;
@@ -87,7 +74,8 @@ int iftable_add(struct nlmsghdr *n, void *arg)
}
hash = ifi_msg->ifi_index&0xF;
- for (imp = &ifindex_map[hash]; (im=*imp)!=NULL; imp = &im->next) {
+ for (imp = &((nlif_handle->ifindex_map)[hash]);
+ (im=*imp)!=NULL; imp = &im->next) {
if (im->index == ifi_msg->ifi_index) {
iftb_log(LOG_DEBUG,
"updating iftable (ifindex=%u)", im->index);
@@ -136,7 +124,9 @@ int iftable_del(struct nlmsghdr *n, void *arg)
{
struct ifinfomsg *ifi_msg = NLMSG_DATA(n);
struct rtattr *cb[IFLA_MAX+1];
- struct ifindex_map *im;
+ struct nlif_handle *nlif_handle = (struct nlif_handle *)arg;
+ struct ifindex_map *im, *ima, **imp;
+ unsigned int hash;
if (n->nlmsg_type != RTM_DELLINK) {
iftb_log(LOG_ERROR,
@@ -153,27 +143,53 @@ int iftable_del(struct nlmsghdr *n, void *arg)
memset(&cb, 0, sizeof(cb));
rtnl_parse_rtattr(cb, IFLA_MAX, IFLA_RTA(ifi_msg), IFLA_PAYLOAD(n));
- /* FIXME */
+ /* \todo Really suppress entry */
+ hash = ifi_msg->ifi_index&0xF;
+ for (ima = NULL, imp = &((nlif_handle->ifindex_map)[hash]);
+ (im=*imp)!=NULL; imp = &im->next, ima=im) {
+ if (im->index == ifi_msg->ifi_index) {
+ iftb_log(LOG_DEBUG,
+ "deleting iftable (ifindex=%u)", im->index);
+ break;
+ }
+ }
+
+ if (!im)
+ return 0;
+
+ if (ima)
+ ima->next = *imp;
+ else
+ (nlif_handle->ifindex_map)[hash] = *imp;
+ free(im);
return 1;
}
-
-/* ifindex_2name - get the name for an ifindex
- * @index: ifindex to be resolved
+
+/** Get the name for an ifindex
*
- * Return value: character string containing name of interface
+ * \param nlif_handle A pointer to a ::nlif_handle created
+ * \param index ifindex to be resolved
+ * \param name interface name, pass a buffer of IFNAMSIZ size
+ * \return -1 on error, 1 on success
*/
-char *ifindex_2name(unsigned int index)
+int nlif_index2name(struct nlif_handle *nlif_handle,
+ unsigned int index,
+ char *name)
{
struct ifindex_map *im;
- if (index == 0)
- return "*";
- for (im = ifindex_map[index&0xF]; im; im = im->next)
- if (im->index == index)
- return im->name;
+ if (index == 0) {
+ strcpy(name, "*");
+ return 1;
+ }
+ for (im = (nlif_handle->ifindex_map)[index&0xF]; im; im = im->next)
+ if (im->index == index) {
+ strcpy(name, im->name);
+ return 1;
+ }
- return NULL;
+ return -1;
}
/* iftable_up - Determine whether a given interface is UP
@@ -181,11 +197,11 @@ char *ifindex_2name(unsigned int index)
*
* Return value: -1 if interface unknown, 1 if interface up, 0 if not.
*/
-int iftable_up(unsigned int index)
+int iftable_up(struct nlif_handle *nlif_handle, unsigned int index)
{
struct ifindex_map *im;
- for (im = ifindex_map[index&0xF]; im; im = im->next) {
+ for (im = nlif_handle->ifindex_map[index&0xF]; im; im = im->next) {
if (im->index == index) {
if (im->flags & IFF_UP)
return 1;
@@ -196,34 +212,49 @@ int iftable_up(unsigned int index)
return -1;
}
-static struct rtnl_handler handlers[] = {
- { .nlmsg_type = RTM_NEWLINK, .handlefn = &iftable_add },
- { .nlmsg_type = RTM_DELLINK, .handlefn = &iftable_del },
-};
-
-static int init_or_fini(int fini)
+static struct nlif_handle *init_or_fini(struct nlif_handle *orig)
{
+ struct nlif_handle *nlif_handle;
int ret = 0;
- if (fini)
+ if (orig) {
+ nlif_handle = orig;
goto cleanup;
+ }
+
+
+ nlif_handle = calloc(1, sizeof(struct nlif_handle));
+ if (!nlif_handle)
+ goto cleanup_none;
- if (rtnl_handler_register(&handlers[0]) < 0) {
+ nlif_handle->ifadd_handler = calloc(1, sizeof(struct rtnl_handler));
+ nlif_handle->ifadd_handler->nlmsg_type = RTM_NEWLINK;
+ nlif_handle->ifadd_handler->handlefn = &iftable_add;
+ nlif_handle->ifadd_handler->arg = nlif_handle;
+ nlif_handle->ifdel_handler = calloc(1, sizeof(struct rtnl_handler));
+ nlif_handle->ifdel_handler->nlmsg_type = RTM_DELLINK;
+ nlif_handle->ifdel_handler->handlefn = &iftable_del;
+ nlif_handle->ifdel_handler->arg = nlif_handle;
+
+ nlif_handle->rtnl_handle = rtnl_init();
+
+ if (! nlif_handle->rtnl_handle)
+ goto cleanup_none;
+
+ if (rtnl_handler_register(nlif_handle->rtnl_handle,
+ nlif_handle->ifadd_handler) < 0) {
ret = -1;
goto cleanup_none;
}
- if (rtnl_handler_register(&handlers[1]) < 0) {
+ if (rtnl_handler_register(nlif_handle->rtnl_handle,
+ nlif_handle->ifdel_handler) < 0) {
ret = -1;
goto cleanup_0;
}
- if (rtnl_dump_type(RTM_GETLINK) < 0) {
- ret = -1;
- goto cleanup_1;
- }
- return 0;
+ return nlif_handle;
#if 0
if (rtnl_wilddump_requet(rtnl_fd, AF_UNSPEC, RTM_GETLINK) < 0) {
@@ -234,28 +265,77 @@ static int init_or_fini(int fini)
#endif
cleanup:
-
-cleanup_1:
- rtnl_handler_unregister(&handlers[1]);
+ rtnl_handler_unregister(nlif_handle->rtnl_handle,
+ nlif_handle->ifadd_handler);
+ free(nlif_handle->ifadd_handler);
cleanup_0:
- rtnl_handler_unregister(&handlers[0]);
+ rtnl_handler_unregister(nlif_handle->rtnl_handle,
+ nlif_handle->ifdel_handler);
+ free(nlif_handle->ifdel_handler);
+ rtnl_fini(nlif_handle->rtnl_handle);
+ free(nlif_handle);
+
cleanup_none:
- return ret;
+ return nlif_handle;
}
-/* iftable_init - Initialize interface table
+/** Initialize interface table
+ *
+ * Initialize rtnl interface and interface table
+ * Call this before any nlif_* function
+ *
+ * \return file descriptor to netlink socket
*/
-int iftable_init(void)
+struct nlif_handle *nlif_open(void)
{
iftb_log(LOG_DEBUG, "%s", __FUNCTION__);
- return init_or_fini(0);
+ return init_or_fini(NULL);
}
-/* iftable_fini - Destructor of interface table
+/** Destructor of interface table
+ *
+ * \param nlif_handle A pointer to a ::nlif_handle created
+ * via nlif_open()
*/
-void iftable_fini(void)
+void nlif_close(struct nlif_handle *nlif_handle)
{
- init_or_fini(1);
+ init_or_fini(nlif_handle);
}
+/** Receive message from netlink and update interface table
+ *
+ * \param nlif_handle A pointer to a ::nlif_handle created
+ * \return 0 if OK
+ */
+int nlif_catch(struct nlif_handle *nlif_handle)
+{
+ if (nlif_handle && nlif_handle->rtnl_handle)
+ return rtnl_receive(nlif_handle->rtnl_handle);
+ else
+ return -1;
+}
+/**
+ * nlif_query - request a dump of interfaces available in the system
+ * @h: pointer to a valid nlif_handler
+ */
+int nlif_query(struct nlif_handle *h)
+{
+ if (rtnl_dump_type(h->rtnl_handle, RTM_GETLINK) < 0)
+ return -1;
+
+ return nlif_catch(h);
+}
+
+/** Returns socket descriptor for the netlink socket
+ *
+ * \param nlif_handle A pointer to a ::nlif_handle created
+ * \return The fd or -1 if there's an error
+ */
+int nlif_fd(struct nlif_handle *nlif_handle)
+{
+ if (nlif_handle && nlif_handle->rtnl_handle)
+ return nlif_handle->rtnl_handle->rtnl_fd;
+ else
+ return -1;
+}
diff --git a/src/rtnl.c b/src/rtnl.c
index 50c3d42..be1e77e 100644
--- a/src/rtnl.c
+++ b/src/rtnl.c
@@ -1,6 +1,8 @@
/* rtnl - rtnetlink utility functions
*
* (C) 2004 by Astaro AG, written by Harald Welte <hwelte@astaro.com>
+ *
+ * Adapted to nfnetlink by Eric Leblond <eric@inl.fr>
*
* This software is free software and licensed under GNU GPLv2.
*
@@ -26,26 +28,22 @@
#define rtnl_log(x, ...)
-static int rtnl_fd;
-static int rtnl_seq = 0;
-static int rtnl_dump;
-static struct sockaddr_nl rtnl_local;
-
-static struct rtnl_handler *handlers = NULL;
-
-static inline struct rtnl_handler *find_handler(u_int16_t type)
+static inline struct rtnl_handler *
+find_handler(struct rtnl_handle *rtnl_handle, u_int16_t type)
{
struct rtnl_handler *h;
- for (h = handlers; h; h = h->next) {
+ for (h = rtnl_handle->handlers; h; h = h->next) {
if (h->nlmsg_type == type)
return h;
}
return NULL;
}
-static int call_handler(u_int16_t type, struct nlmsghdr *hdr)
+static int call_handler(struct rtnl_handle *rtnl_handle,
+ u_int16_t type,
+ struct nlmsghdr *hdr)
{
- struct rtnl_handler *h = find_handler(type);
+ struct rtnl_handler *h = find_handler(rtnl_handle, type);
if (!h) {
rtnl_log(LOG_DEBUG, "no registered handler for type %u",
@@ -59,31 +57,33 @@ static int call_handler(u_int16_t type, struct nlmsghdr *hdr)
/* rtnl_handler_register - register handler for given nlmsg type
* @hdlr: handler structure
*/
-int rtnl_handler_register(struct rtnl_handler *hdlr)
+int rtnl_handler_register(struct rtnl_handle *rtnl_handle,
+ struct rtnl_handler *hdlr)
{
rtnl_log(LOG_DEBUG, "registering handler for type %u",
hdlr->nlmsg_type);
- hdlr->next = handlers;
- handlers = hdlr;
+ hdlr->next = rtnl_handle->handlers;
+ rtnl_handle->handlers = hdlr;
return 1;
}
/* rtnl_handler_unregister - unregister handler for given nlmst type
* @hdlr: handler structure
*/
-int rtnl_handler_unregister(struct rtnl_handler *hdlr)
+int rtnl_handler_unregister(struct rtnl_handle *rtnl_handle,
+ struct rtnl_handler *hdlr)
{
struct rtnl_handler *h, *prev = NULL;
rtnl_log(LOG_DEBUG, "unregistering handler for type %u",
hdlr->nlmsg_type);
- for (h = handlers; h; h = h->next) {
+ for (h = rtnl_handle->handlers; h; h = h->next) {
if (h == hdlr) {
if (prev)
prev->next = h->next;
else
- handlers = h->next;
+ rtnl_handle->handlers = h->next;
return 1;
}
prev = h;
@@ -107,7 +107,7 @@ int rtnl_parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
/* rtnl_dump_type - ask rtnetlink to dump a specific table
* @type: type of table to be dumped
*/
-int rtnl_dump_type(unsigned int type)
+int rtnl_dump_type(struct rtnl_handle *rtnl_handle, unsigned int type)
{
struct {
struct nlmsghdr nlh;
@@ -123,15 +123,15 @@ int rtnl_dump_type(unsigned int type)
req.nlh.nlmsg_type = type;
req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
req.nlh.nlmsg_pid = 0;
- req.nlh.nlmsg_seq = rtnl_dump = ++rtnl_seq;
+ req.nlh.nlmsg_seq = rtnl_handle->rtnl_dump = ++(rtnl_handle->rtnl_seq);
req.g.rtgen_family = AF_INET;
- return sendto(rtnl_fd, (void*)&req, sizeof(req), 0,
+ return sendto(rtnl_handle->rtnl_fd, (void*)&req, sizeof(req), 0,
(struct sockaddr*)&nladdr, sizeof(nladdr));
}
/* rtnl_receive - receive netlink packets from rtnetlink socket */
-int rtnl_receive()
+int rtnl_receive(struct rtnl_handle *rtnl_handle)
{
int status;
char buf[8192];
@@ -146,7 +146,7 @@ int rtnl_receive()
0
};
- status = recvmsg(rtnl_fd, &msg, 0);
+ status = recvmsg(rtnl_handle->rtnl_fd, &msg, 0);
if (status < 0) {
if (errno == EINTR)
return 0;
@@ -184,7 +184,7 @@ int rtnl_receive()
return -1;
}
- if (call_handler(h->nlmsg_type, h) == 0)
+ if (call_handler(rtnl_handle, h->nlmsg_type, h) == 0)
rtnl_log(LOG_NOTICE, "unhandled nlmsg_type %u",
h->nlmsg_type);
h = NLMSG_NEXT(h, status);
@@ -193,54 +193,68 @@ int rtnl_receive()
}
/* rtnl_init - constructor of rtnetlink module */
-int rtnl_init(void)
+struct rtnl_handle *rtnl_init(void)
{
- int addr_len;
+ unsigned int addr_len;
+ struct rtnl_handle *rtnl_handle = calloc(1, sizeof(struct rtnl_handle));
+
+ if (! rtnl_handle)
+ return NULL;
+
+ rtnl_handle->rtnl_seq = 0;
+ rtnl_handle->handlers = NULL;
- rtnl_local.nl_pid = getpid();
- rtnl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (rtnl_fd < 0) {
+ rtnl_handle->rtnl_local.nl_pid = getpid();
+ rtnl_handle->rtnl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (rtnl_handle->rtnl_fd < 0) {
rtnl_log(LOG_ERROR, "unable to create rtnetlink socket");
- return -1;
+ free(rtnl_handle);
+ return NULL;
}
- memset(&rtnl_local, 0, sizeof(rtnl_local));
- rtnl_local.nl_family = AF_NETLINK;
- rtnl_local.nl_groups = RTMGRP_IPV4_ROUTE|RTMGRP_IPV4_IFADDR|RTMGRP_LINK;
-
- if (bind(rtnl_fd, (struct sockaddr *)&rtnl_local, sizeof(rtnl_local)) < 0) {
+ memset(&(rtnl_handle->rtnl_local), 0, sizeof(rtnl_handle->rtnl_local));
+ rtnl_handle->rtnl_local.nl_family = AF_NETLINK;
+ rtnl_handle->rtnl_local.nl_groups =
+ RTMGRP_IPV4_ROUTE|RTMGRP_IPV4_IFADDR|RTMGRP_LINK;
+ if (bind(rtnl_handle->rtnl_fd,
+ (struct sockaddr *)&(rtnl_handle->rtnl_local),
+ sizeof(rtnl_handle->rtnl_local)) < 0) {
rtnl_log(LOG_ERROR, "unable to bind rtnetlink socket");
- return -1;
+ free(rtnl_handle);
+ return NULL;
}
- addr_len = sizeof(rtnl_local);
- if (getsockname(rtnl_fd, (struct sockaddr *)&rtnl_local,
+ addr_len = sizeof(rtnl_handle->rtnl_local);
+ if (getsockname(rtnl_handle->rtnl_fd,
+ (struct sockaddr *)&(rtnl_handle->rtnl_local),
&addr_len) < 0) {
rtnl_log(LOG_ERROR, "cannot gescockname(rtnl_socket)");
- return -1;
+ free(rtnl_handle);
+ return NULL;
}
- if (addr_len != sizeof(rtnl_local)) {
+ if (addr_len != sizeof(rtnl_handle->rtnl_local)) {
rtnl_log(LOG_ERROR, "invalid address size %u", addr_len);
- return -1;
+ free(rtnl_handle);
+ return NULL;
}
- if (rtnl_local.nl_family != AF_NETLINK) {
- rtnl_log(LOG_ERROR, "invalid AF %u", rtnl_local.nl_family);
- return -1;
+ if (rtnl_handle->rtnl_local.nl_family != AF_NETLINK) {
+ rtnl_log(LOG_ERROR, "invalid AF %u",
+ rtnl_handle->rtnl_local.nl_family);
+ free(rtnl_handle);
+ return NULL;
}
- rtnl_seq = time(NULL);
+ rtnl_handle->rtnl_seq = time(NULL);
- return rtnl_fd;
+ return rtnl_handle;
}
/* rtnl_fini - destructor of rtnetlink module */
-void rtnl_fini(void)
+void rtnl_fini(struct rtnl_handle *rtnl_handle)
{
- close(rtnl_fd);
+ close(rtnl_handle->rtnl_fd);
+ free(rtnl_handle);
return;
}
-
-
-
diff --git a/src/rtnl.h b/src/rtnl.h
index 5eeb043..b6644e6 100644
--- a/src/rtnl.h
+++ b/src/rtnl.h
@@ -12,17 +12,25 @@ struct rtnl_handler {
void *arg;
};
+struct rtnl_handle {
+ int rtnl_fd;
+ int rtnl_seq;
+ int rtnl_dump;
+ struct sockaddr_nl rtnl_local;
+ struct rtnl_handler *handlers;
+};
/* api for handler plugins */
-int rtnl_handler_register(struct rtnl_handler *hdlr);
-int rtnl_handler_unregister(struct rtnl_handler *hdlr);
+int rtnl_handler_register(struct rtnl_handle *rtnl_handle,
+ struct rtnl_handler *hdlr);
+int rtnl_handler_unregister(struct rtnl_handle *rtnl_handle,
+ struct rtnl_handler *hdlr);
int rtnl_parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
-int rtnl_dump_type(unsigned int type);
+int rtnl_dump_type(struct rtnl_handle *rtnl_handle, unsigned int type);
/* api for core program */
-int rtnl_init(void);
-void rtnl_fini(void);
-int rtnl_receive();
-
+struct rtnl_handle *rtnl_init(void);
+void rtnl_fini(struct rtnl_handle *rtnl_handle);
+int rtnl_receive(struct rtnl_handle *rtnl_handle);
#endif
diff --git a/utils/Makefile.am b/utils/Makefile.am
new file mode 100644
index 0000000..51ed390
--- /dev/null
+++ b/utils/Makefile.am
@@ -0,0 +1,7 @@
+include $(top_srcdir)/Make_global.am
+
+bin_PROGRAMS = iftest
+
+iftest_SOURCES = iftest.c
+iftest_LDADD = ../src/libnfnetlink.la
+iftest_LDFLAGS = -dynamic -ldl
diff --git a/utils/iftest.c b/utils/iftest.c
new file mode 100644
index 0000000..61d066a
--- /dev/null
+++ b/utils/iftest.c
@@ -0,0 +1,31 @@
+/* simple test for index to interface name API */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <libnfnetlink/libnfnetlink.h>
+
+int main()
+{
+ int i;
+ struct nlif_handle *h;
+
+ h = nlif_open();
+ if (h == NULL) {
+ perror("nlif_open");
+ exit(EXIT_FAILURE);
+ }
+
+ nlif_query(h);
+
+ for (i=0; i<64; i++) {
+ char name[IFNAMSIZ];
+
+ if (nlif_index2name(h, i, name) == -1)
+ continue;
+ printf("index (%d) is %s\n", i, name);
+ }
+
+ nlif_close(h);
+}