summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2012-08-20 13:21:51 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2012-08-20 13:23:20 +0200
commit65ec7cfa590700fbab9657727a9b19e8d58158fc (patch)
treedc5dfeed9b8b07ee22ccbc63dfc7d3cdc26d42a7
parent1385fc1bdc6ae8ac3ccb206af2d9dee4a70ba9c8 (diff)
downloadlibmnl-nl-mmap.tar.gz
examples: rtnl_route_dump: add memory mapped netlink supportnl-mmap
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--examples/rtnl/rtnl-route-dump.c67
1 files changed, 61 insertions, 6 deletions
diff --git a/examples/rtnl/rtnl-route-dump.c b/examples/rtnl/rtnl-route-dump.c
index a798515..2d8e19b 100644
--- a/examples/rtnl/rtnl-route-dump.c
+++ b/examples/rtnl/rtnl-route-dump.c
@@ -4,6 +4,8 @@
#include <string.h>
#include <unistd.h>
#include <time.h>
+#include <poll.h>
+#include <errno.h>
#include <arpa/inet.h>
#include <libmnl/libmnl.h>
@@ -285,12 +287,34 @@ static int data_cb(const struct nlmsghdr *nlh, void *data)
return MNL_CB_OK;
}
+static int mnl_socket_poll(struct mnl_socket *nl)
+{
+ struct pollfd pfds[1];
+
+ while (1) {
+ pfds[0].fd = mnl_socket_get_fd(nl);
+ pfds[0].events = POLLIN | POLLERR;
+ pfds[0].revents = 0;
+
+ if (poll(pfds, 1, -1) < 0 && errno != -EINTR)
+ return -1;
+
+ if (pfds[0].revents & POLLIN)
+ return 0;
+ if (pfds[0].revents & POLLERR)
+ return -1;
+ }
+}
+
int main(int argc, char *argv[])
{
struct mnl_socket *nl;
char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nl_mmap_hdr *hdr;
struct nlmsghdr *nlh;
struct rtmsg *rtm;
+ ssize_t len;
+ void *ptr;
int ret;
unsigned int seq, portid;
@@ -316,6 +340,11 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
+ if (mnl_socket_set_ring(nl, 0, 0) < 0) {
+ perror("mnl_socket_set_ring");
+ exit(EXIT_FAILURE);
+ }
+
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
perror("mnl_socket_bind");
exit(EXIT_FAILURE);
@@ -327,13 +356,39 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
- while (ret > 0) {
- ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
- if (ret <= MNL_CB_STOP)
- break;
- ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
+ while (1) {
+ ret = mnl_socket_poll(nl);
+ if (ret < 0) {
+ perror("mnl_socket_poll");
+ exit(EXIT_FAILURE);
+ }
+
+ while (1) {
+ hdr = mnl_socket_get_frame(nl, MNL_RING_RX);
+
+ if (hdr->nm_status == NL_MMAP_STATUS_VALID) {
+ ptr = (void *)hdr + NL_MMAP_HDRLEN;
+ len = hdr->nm_len;
+ if (len == 0)
+ goto next;
+ } else if (hdr->nm_status == NL_MMAP_STATUS_COPY) {
+ len = recv(mnl_socket_get_fd(nl),
+ buf, sizeof(buf), MSG_DONTWAIT);
+ if (len <= 0)
+ break;
+ ptr = buf;
+ } else
+ break;
+
+ ret = mnl_cb_run(ptr, len, seq, portid, data_cb, NULL);
+ if (ret <= MNL_CB_STOP)
+ goto end;
+next:
+ hdr->nm_status = NL_MMAP_STATUS_UNUSED;
+ mnl_socket_advance_ring(nl, MNL_RING_RX);
+ }
}
+end:
if (ret == -1) {
perror("error");
exit(EXIT_FAILURE);