All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ken-ichirou MATSUZAWA <chamaken@gmail.com>
To: Pablo Neira Ayuso <pablo@netfilter.org>, netfilter-devel@vger.kernel.org
Subject: [libmnl PATCH 7/9] examples: add for mmap nonmin2
Date: Sun, 08 Dec 2013 00:15:13 +0900	[thread overview]
Message-ID: <87k3fg8zge.wl%chamaken@gmail.com> (raw)


Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>

---
 configure.ac                            |   2 +-
 examples/mmap/Makefile.am               |   2 +-
 examples/mmap/nonmin2/Makefile.am       |  19 ++
 examples/mmap/nonmin2/nf-log.c          | 269 ++++++++++++++++++++++
 examples/mmap/nonmin2/nfct-dump.c       | 333 ++++++++++++++++++++++++++++
 examples/mmap/nonmin2/rtnl-addr-dump.c  | 158 +++++++++++++
 examples/mmap/nonmin2/rtnl-route-dump.c | 381 ++++++++++++++++++++++++++++++++
 7 files changed, 1162 insertions(+), 2 deletions(-)
 create mode 100644 examples/mmap/nonmin2/Makefile.am
 create mode 100644 examples/mmap/nonmin2/nf-log.c
 create mode 100644 examples/mmap/nonmin2/nfct-dump.c
 create mode 100644 examples/mmap/nonmin2/rtnl-addr-dump.c
 create mode 100644 examples/mmap/nonmin2/rtnl-route-dump.c

diff --git a/configure.ac b/configure.ac
index 08350b9..535c998 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,5 +27,5 @@ regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
 	-Wformat=2 -pipe"
 AC_SUBST([regular_CPPFLAGS])
 AC_SUBST([regular_CFLAGS])
-AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/libmnl/Makefile include/linux/Makefile include/linux/netfilter/Makefile examples/Makefile examples/genl/Makefile examples/kobject/Makefile examples/netfilter/Makefile examples/rtnl/Makefile examples/mmap/Makefile examples/mmap/min/Makefile examples/mmap/nonmin1/Makefile libmnl.pc doxygen.cfg])
+AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/libmnl/Makefile include/linux/Makefile include/linux/netfilter/Makefile examples/Makefile examples/genl/Makefile examples/kobject/Makefile examples/netfilter/Makefile examples/rtnl/Makefile examples/mmap/Makefile examples/mmap/min/Makefile examples/mmap/nonmin1/Makefile examples/mmap/nonmin2/Makefile libmnl.pc doxygen.cfg])
 AC_OUTPUT
diff --git a/examples/mmap/Makefile.am b/examples/mmap/Makefile.am
index 1a7ee6f..0645260 100644
--- a/examples/mmap/Makefile.am
+++ b/examples/mmap/Makefile.am
@@ -1 +1 @@
-SUBDIRS = min nonmin1
+SUBDIRS = min nonmin1 nonmin2
diff --git a/examples/mmap/nonmin2/Makefile.am b/examples/mmap/nonmin2/Makefile.am
new file mode 100644
index 0000000..962eddc
--- /dev/null
+++ b/examples/mmap/nonmin2/Makefile.am
@@ -0,0 +1,19 @@
+include $(top_srcdir)/Make_global.am
+
+check_PROGRAMS = nf-log \
+		 nfct-dump \
+		 rtnl-addr-dump \
+		 rtnl-route-dump
+
+nf_log_SOURCES = nf-log.c
+nf_log_LDADD = ../../../src/libmnl.la
+
+nfct_dump_SOURCES = nfct-dump.c
+nfct_dump_LDADD = ../../../src/libmnl.la
+
+rtnl_addr_dump_SOURCES = rtnl-addr-dump.c
+rtnl_addr_dump_LDADD = ../../../src/libmnl.la
+
+rtnl_route_dump_SOURCES = rtnl-route-dump.c
+rtnl_route_dump_LDADD = ../../../src/libmnl.la
+
diff --git a/examples/mmap/nonmin2/nf-log.c b/examples/mmap/nonmin2/nf-log.c
new file mode 100644
index 0000000..71bbca0
--- /dev/null
+++ b/examples/mmap/nonmin2/nf-log.c
@@ -0,0 +1,269 @@
+/* This example is placed in the public domain. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <poll.h>
+
+#include <libmnl/libmnl.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+
+#ifndef aligned_be64
+#define aligned_be64 u_int64_t __attribute__((aligned(8)))
+#endif
+
+#include <linux/netfilter/nfnetlink_log.h>
+
+static int parse_attr_cb(const struct nlattr *attr, void *data)
+{
+	const struct nlattr **tb = data;
+	int type = mnl_attr_get_type(attr);
+
+	/* skip unsupported attribute in user-space */
+	if (mnl_attr_type_valid(attr, NFULA_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch(type) {
+	case NFULA_MARK:
+	case NFULA_IFINDEX_INDEV:
+	case NFULA_IFINDEX_OUTDEV:
+	case NFULA_IFINDEX_PHYSINDEV:
+	case NFULA_IFINDEX_PHYSOUTDEV:
+		if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	case NFULA_TIMESTAMP:
+		if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
+		    sizeof(struct nfulnl_msg_packet_timestamp)) < 0) {
+			perror("mnl_attr_validate2");
+			return MNL_CB_ERROR;
+		}
+		break;
+	case NFULA_HWADDR:
+		if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
+		    sizeof(struct nfulnl_msg_packet_hw)) < 0) {
+			perror("mnl_attr_validate2");
+			return MNL_CB_ERROR;
+		}
+		break;
+	case NFULA_PREFIX:
+		if (mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	case NFULA_PAYLOAD:
+		break;
+	}
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static int log_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nlattr *tb[NFULA_MAX+1] = {};
+	struct nfulnl_msg_packet_hdr *ph = NULL;
+	const char *prefix = NULL;
+	uint32_t mark = 0;
+
+	mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb);
+	if (tb[NFULA_PACKET_HDR])
+		ph = mnl_attr_get_payload(tb[NFULA_PACKET_HDR]);
+	if (tb[NFULA_PREFIX])
+		prefix = mnl_attr_get_str(tb[NFULA_PREFIX]);
+	if (tb[NFULA_MARK])
+		mark = ntohl(mnl_attr_get_u32(tb[NFULA_MARK]));
+
+	printf("log received (prefix=\"%s\" hw=0x%04x hook=%u mark=%u)\n",
+		prefix ? prefix : "", ntohs(ph->hw_protocol), ph->hook,
+		mark);
+
+	return MNL_CB_OK;
+}
+
+static int nflog_build_cfg_pf_request(void *buf, void *data)
+{
+	uint8_t command = *(uint8_t *)data;
+
+	struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
+	nlh->nlmsg_type	= (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
+	nlh->nlmsg_flags = NLM_F_REQUEST;
+
+	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
+	nfg->nfgen_family = AF_INET;
+	nfg->version = NFNETLINK_V0;
+
+	struct nfulnl_msg_config_cmd cmd = {
+		.command = command,
+	};
+	mnl_attr_put(nlh, NFULA_CFG_CMD, sizeof(cmd), &cmd);
+
+	return nlh->nlmsg_len;
+}
+
+struct cfg_request {
+	uint8_t command;
+	int qnum;
+};
+
+static int nflog_build_cfg_request(void *buf, void *data)
+{
+	uint8_t command = ((struct cfg_request *)data)->command;
+	int qnum = ((struct cfg_request *)data)->qnum;
+	struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
+
+	nlh->nlmsg_type	= (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
+	nlh->nlmsg_flags = NLM_F_REQUEST;
+
+	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
+	nfg->nfgen_family = AF_INET;
+	nfg->version = NFNETLINK_V0;
+	nfg->res_id = htons(qnum);
+
+	struct nfulnl_msg_config_cmd cmd = {
+		.command = command,
+	};
+	mnl_attr_put(nlh, NFULA_CFG_CMD, sizeof(cmd), &cmd);
+
+	return nlh->nlmsg_len;
+}
+
+struct cfg_params {
+	uint8_t mode;
+	int range;
+	int qnum;
+};
+
+static int nflog_build_cfg_params(void *buf, void *data)
+{
+	uint8_t mode = ((struct cfg_params *)data)->mode;
+	int range = ((struct cfg_params *)data)->range;
+	int qnum = ((struct cfg_params *)data)->qnum;
+	struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
+
+	nlh->nlmsg_type	= (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
+	nlh->nlmsg_flags = NLM_F_REQUEST;
+
+	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
+	nfg->nfgen_family = AF_UNSPEC;
+	nfg->version = NFNETLINK_V0;
+	nfg->res_id = htons(qnum);
+
+	struct nfulnl_msg_config_mode params = {
+		.copy_range = htonl(range),
+		.copy_mode = mode,
+	};
+	mnl_attr_put(nlh, NFULA_CFG_MODE, sizeof(params), &params);
+
+	return nlh->nlmsg_len;
+}
+
+int main(int argc, char *argv[])
+{
+	struct mnl_socket *nl;
+	struct mnl_ring_socket *nlm;
+	struct nl_mmap_req nlmr = MNL_MMAP_DEFAULT_REQ;
+	int ret;
+	unsigned int portid, qnum;
+	uint8_t pf_cmd;
+	struct cfg_request cfg_request;
+	struct cfg_params cfg_params;
+
+	if (argc != 2) {
+		printf("Usage: %s [queue_num]\n", argv[0]);
+		exit(EXIT_FAILURE);
+	}
+	qnum = atoi(argv[1]);
+
+	nl = mnl_socket_open(NETLINK_NETFILTER);
+	if (nl == NULL) {
+		perror("mnl_socket_open");
+		exit(EXIT_FAILURE);
+	}
+
+	nlm = mnl_ring_map(nl, &nlmr, &nlmr);
+	if (nlm == NULL) {
+		perror("mnl_ring_map");
+		exit(EXIT_FAILURE);
+	}
+
+	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
+		perror("mnl_socket_bind");
+		exit(EXIT_FAILURE);
+	}
+	portid = mnl_socket_get_portid(nl);
+
+	pf_cmd = NFULNL_CFG_CMD_PF_UNBIND;
+	if (mnl_ring_build_frame(nlm, nflog_build_cfg_pf_request, &pf_cmd) <= 0) {
+		perror("mnl_ring_build_frame");
+		exit(EXIT_FAILURE);
+	}
+	/*
+	 * nframes++;
+	 * assert(nframes < nlmr.nm_frame_nr);
+	 */
+	if (mnl_ring_send(nlm) < 0) {
+		perror("mnl_ring_send");
+		exit(EXIT_FAILURE);
+	}
+	mnl_ring_advance(nlm, MNL_RING_TX);
+
+	pf_cmd = NFULNL_CFG_CMD_PF_BIND;
+	if (mnl_ring_build_frame(nlm, nflog_build_cfg_pf_request, &pf_cmd) < 0) {
+		perror("mnl_ring_build_frame");
+		exit(EXIT_FAILURE);
+	}
+	if (mnl_ring_send(nlm) < 0) {
+		perror("mnl_ring_send");
+		exit(EXIT_FAILURE);
+	}
+	mnl_ring_advance(nlm, MNL_RING_TX);
+
+	cfg_request = (struct cfg_request){
+		.command = NFULNL_CFG_CMD_BIND,
+		.qnum = qnum
+	};
+	if (mnl_ring_build_frame(nlm, nflog_build_cfg_request, &cfg_request) < 0) {
+		perror("mnl_ring_build_frame");
+		exit(EXIT_FAILURE);
+	}
+	if (mnl_ring_send(nlm) < 0) {
+		perror("mnl_ring_send");
+		exit(EXIT_FAILURE);
+	}
+	mnl_ring_advance(nlm, MNL_RING_TX);
+
+	cfg_params = (struct cfg_params){
+		.mode = NFULNL_COPY_PACKET,
+		.range = 0xFFFF,
+		.qnum = qnum
+	};
+	if (mnl_ring_build_frame(nlm, nflog_build_cfg_params, &cfg_params) <= 0) {
+		perror("mnl_ring_build_frame");
+		exit(EXIT_FAILURE);
+	}
+	if (mnl_ring_send(nlm) < 0) {
+		perror("mnl_ring_send");
+		exit(EXIT_FAILURE);
+	}
+	mnl_ring_advance(nlm, MNL_RING_TX);
+
+	while ((ret = mnl_ring_parse_frame(nlm, 0, portid, log_cb, NULL)) >= 0)
+	       ;
+
+	if (ret == -1) {
+		perror("error");
+		exit(EXIT_FAILURE);
+	}
+
+	mnl_ring_unmap(nlm);
+	mnl_socket_close(nl);
+
+	return 0;
+}
diff --git a/examples/mmap/nonmin2/nfct-dump.c b/examples/mmap/nonmin2/nfct-dump.c
new file mode 100644
index 0000000..02e6110
--- /dev/null
+++ b/examples/mmap/nonmin2/nfct-dump.c
@@ -0,0 +1,333 @@
+/* This example is placed in the public domain. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <arpa/inet.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <poll.h>
+
+#include <libmnl/libmnl.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+static int parse_counters_cb(const struct nlattr *attr, void *data)
+{
+	const struct nlattr **tb = data;
+	int type = mnl_attr_get_type(attr);
+
+	if (mnl_attr_type_valid(attr, CTA_COUNTERS_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch(type) {
+	case CTA_COUNTERS_PACKETS:
+	case CTA_COUNTERS_BYTES:
+		if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	}
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static void print_counters(const struct nlattr *nest)
+{
+	struct nlattr *tb[CTA_COUNTERS_MAX+1] = {};
+
+	mnl_attr_parse_nested(nest, parse_counters_cb, tb);
+	if (tb[CTA_COUNTERS_PACKETS]) {
+		printf("packets=%"PRIu64" ",
+		       be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_PACKETS])));
+	}
+	if (tb[CTA_COUNTERS_BYTES]) {
+		printf("bytes=%"PRIu64" ",
+		       be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_BYTES])));
+	}
+}
+
+static int parse_ip_cb(const struct nlattr *attr, void *data)
+{
+	const struct nlattr **tb = data;
+	int type = mnl_attr_get_type(attr);
+
+	if (mnl_attr_type_valid(attr, CTA_IP_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch(type) {
+	case CTA_IP_V4_SRC:
+	case CTA_IP_V4_DST:
+		if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	case CTA_IP_V6_SRC:
+	case CTA_IP_V6_DST:
+		if (mnl_attr_validate2(attr, MNL_TYPE_BINARY,
+				       sizeof(struct in6_addr)) < 0) {
+			perror("mnl_attr_validate2");
+			return MNL_CB_ERROR;
+		}
+		break;
+	}
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static void print_ip(const struct nlattr *nest)
+{
+	struct nlattr *tb[CTA_IP_MAX+1] = {};
+
+	mnl_attr_parse_nested(nest, parse_ip_cb, tb);
+	if (tb[CTA_IP_V4_SRC]) {
+		struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_SRC]);
+		printf("src=%s ", inet_ntoa(*in));
+	}
+	if (tb[CTA_IP_V4_DST]) {
+		struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_DST]);
+		printf("dst=%s ", inet_ntoa(*in));
+	}
+	if (tb[CTA_IP_V6_SRC]) {
+		struct in6_addr *in = mnl_attr_get_payload(tb[CTA_IP_V6_SRC]);
+		char out[INET6_ADDRSTRLEN];
+
+		if (!inet_ntop(AF_INET6, in, out, sizeof(out)))
+			printf("src=%s ", out);
+	}
+	if (tb[CTA_IP_V6_DST]) {
+		struct in6_addr *in = mnl_attr_get_payload(tb[CTA_IP_V6_DST]);
+		char out[INET6_ADDRSTRLEN];
+
+		if (!inet_ntop(AF_INET6, in, out, sizeof(out)))
+			printf("dst=%s ", out);
+	}
+}
+
+static int parse_proto_cb(const struct nlattr *attr, void *data)
+{
+	const struct nlattr **tb = data;
+	int type = mnl_attr_get_type(attr);
+
+	if (mnl_attr_type_valid(attr, CTA_PROTO_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch(type) {
+	case CTA_PROTO_NUM:
+	case CTA_PROTO_ICMP_TYPE:
+	case CTA_PROTO_ICMP_CODE:
+		if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	case CTA_PROTO_SRC_PORT:
+	case CTA_PROTO_DST_PORT:
+	case CTA_PROTO_ICMP_ID:
+		if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	}
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static void print_proto(const struct nlattr *nest)
+{
+	struct nlattr *tb[CTA_PROTO_MAX+1] = {};
+
+	mnl_attr_parse_nested(nest, parse_proto_cb, tb);
+	if (tb[CTA_PROTO_NUM]) {
+		printf("proto=%u ", mnl_attr_get_u8(tb[CTA_PROTO_NUM]));
+	}
+	if (tb[CTA_PROTO_SRC_PORT]) {
+		printf("sport=%u ",
+			ntohs(mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT])));
+	}
+	if (tb[CTA_PROTO_DST_PORT]) {
+		printf("dport=%u ",
+			ntohs(mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT])));
+	}
+	if (tb[CTA_PROTO_ICMP_ID]) {
+		printf("id=%u ",
+			ntohs(mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID])));
+	}
+	if (tb[CTA_PROTO_ICMP_TYPE]) {
+		printf("type=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
+	}
+	if (tb[CTA_PROTO_ICMP_CODE]) {
+		printf("code=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE]));
+	}
+}
+
+static int parse_tuple_cb(const struct nlattr *attr, void *data)
+{
+	const struct nlattr **tb = data;
+	int type = mnl_attr_get_type(attr);
+
+	if (mnl_attr_type_valid(attr, CTA_TUPLE_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch(type) {
+	case CTA_TUPLE_IP:
+		if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	case CTA_TUPLE_PROTO:
+		if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	}
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static void print_tuple(const struct nlattr *nest)
+{
+	struct nlattr *tb[CTA_TUPLE_MAX+1] = {};
+
+	mnl_attr_parse_nested(nest, parse_tuple_cb, tb);
+	if (tb[CTA_TUPLE_IP]) {
+		print_ip(tb[CTA_TUPLE_IP]);
+	}
+	if (tb[CTA_TUPLE_PROTO]) {
+		print_proto(tb[CTA_TUPLE_PROTO]);
+	}
+}
+
+static int data_attr_cb(const struct nlattr *attr, void *data)
+{
+	const struct nlattr **tb = data;
+	int type = mnl_attr_get_type(attr);
+
+	if (mnl_attr_type_valid(attr, CTA_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch(type) {
+	case CTA_TUPLE_ORIG:
+	case CTA_COUNTERS_ORIG:
+	case CTA_COUNTERS_REPLY:
+		if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	case CTA_TIMEOUT:
+	case CTA_MARK:
+	case CTA_SECMARK:
+		if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	}
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static int data_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nlattr *tb[CTA_MAX+1] = {};
+	struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
+
+	mnl_attr_parse(nlh, sizeof(*nfg), data_attr_cb, tb);
+	if (tb[CTA_TUPLE_ORIG])
+		print_tuple(tb[CTA_TUPLE_ORIG]);
+
+	if (tb[CTA_MARK])
+		printf("mark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_MARK])));
+
+	if (tb[CTA_SECMARK])
+		printf("secmark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_SECMARK])));
+
+	if (tb[CTA_COUNTERS_ORIG]) {
+		printf("original ");
+		print_counters(tb[CTA_COUNTERS_ORIG]);
+	}
+
+	if (tb[CTA_COUNTERS_REPLY]) {
+		printf("reply ");
+		print_counters(tb[CTA_COUNTERS_REPLY]);
+	}
+
+	printf("\n");
+	return MNL_CB_OK;
+}
+
+static int build_cb(void *buf, void *data)
+{
+	struct nlmsghdr *nlh;
+	struct nfgenmsg *nfh;
+	unsigned int seq = *(unsigned int *)data;
+
+	nlh = mnl_nlmsg_put_header(buf);
+	nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET;
+	nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
+	nlh->nlmsg_seq = seq = time(NULL);
+
+	nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
+	nfh->nfgen_family = AF_INET;
+	nfh->version = NFNETLINK_V0;
+	nfh->res_id = 0;
+
+	return nlh->nlmsg_len;
+}
+
+int main(void)
+{
+	struct mnl_socket *nl;
+	struct mnl_ring_socket *nlm;
+	struct nl_mmap_req nlmr = MNL_MMAP_DEFAULT_REQ;
+	int ret;
+	uint32_t seq, portid;
+
+	nl = mnl_socket_open(NETLINK_NETFILTER);
+	if (nl == NULL) {
+		perror("mnl_socket_open");
+		exit(EXIT_FAILURE);
+	}
+
+	nlm = mnl_ring_map(nl, &nlmr, &nlmr);
+	if (nlm == NULL) {
+		perror("mnl_ring_map");
+		exit(EXIT_FAILURE);
+	}
+
+	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
+		perror("mnl_socket_bind");
+		exit(EXIT_FAILURE);
+	}
+	portid = mnl_socket_get_portid(nl);
+
+	if (mnl_ring_build_frame(nlm, build_cb, &seq) <= 0) {
+		perror("mnl_ring_build_frame");
+		exit(EXIT_FAILURE);
+	}
+
+	if (mnl_ring_send(nlm) < 0) {
+		perror("mnl_socket_send");
+		exit(EXIT_FAILURE);
+	}
+	mnl_ring_advance(nlm, MNL_RING_TX);
+
+	while ((ret = mnl_ring_parse_frame(nlm, seq, portid, data_cb, NULL)) > 0)
+		;
+
+	if (ret == -1) {
+		perror("error");
+		exit(EXIT_FAILURE);
+	}
+
+	mnl_ring_unmap(nlm);
+	mnl_socket_close(nl);
+
+	return 0;
+}
diff --git a/examples/mmap/nonmin2/rtnl-addr-dump.c b/examples/mmap/nonmin2/rtnl-addr-dump.c
new file mode 100644
index 0000000..34700d8
--- /dev/null
+++ b/examples/mmap/nonmin2/rtnl-addr-dump.c
@@ -0,0 +1,158 @@
+/* This example is placed in the public domain. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <arpa/inet.h>
+
+#include <libmnl/libmnl.h>
+#include <linux/if.h>
+#include <linux/if_link.h>
+#include <linux/rtnetlink.h>
+
+static int data_attr_cb(const struct nlattr *attr, void *data)
+{
+	const struct nlattr **tb = data;
+	int type = mnl_attr_get_type(attr);
+
+	/* skip unsupported attribute in user-space */
+	if (mnl_attr_type_valid(attr, IFA_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch(type) {
+	case IFA_ADDRESS:
+		if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	}
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static int data_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nlattr *tb[IFLA_MAX+1] = {};
+	struct ifaddrmsg *ifa = mnl_nlmsg_get_payload(nlh);
+
+	printf("index=%d family=%d ", ifa->ifa_index, ifa->ifa_family);
+
+	mnl_attr_parse(nlh, sizeof(*ifa), data_attr_cb, tb);
+	printf("addr=");
+	if (tb[IFA_ADDRESS]) {
+		void *addr = mnl_attr_get_payload(tb[IFA_ADDRESS]);
+		char out[INET6_ADDRSTRLEN];
+
+		if (inet_ntop(ifa->ifa_family, addr, out, sizeof(out)))
+			printf("%s ", out);
+	}
+	printf("scope=");
+	switch(ifa->ifa_scope) {
+	case 0:
+		printf("global ");
+		break;
+	case 200:
+		printf("site ");
+		break;
+	case 253:
+		printf("link ");
+		break;
+	case 254:
+		printf("host ");
+		break;
+	case 255:
+		printf("nowhere ");
+		break;
+	default:
+		printf("%d ", ifa->ifa_scope);
+		break;
+	}
+
+	printf("\n");
+	return MNL_CB_OK;
+}
+
+struct seq_family {
+	unsigned char family;
+	unsigned int seq;
+};
+
+static int build_cb(void *buf, void *data)
+{
+	struct nlmsghdr *nlh;
+	struct rtgenmsg *rt;
+	struct seq_family *sf = (struct seq_family *)data;
+
+	nlh = mnl_nlmsg_put_header(buf);
+	nlh->nlmsg_type = RTM_GETADDR;
+	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+	nlh->nlmsg_seq = sf->seq;
+	rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg));
+	rt->rtgen_family = sf->family;
+
+	return nlh->nlmsg_len;
+}
+
+int main(int argc, char *argv[])
+{
+	struct mnl_socket *nl;
+	struct mnl_ring_socket *nlm;
+	struct nl_mmap_req nlmr = MNL_MMAP_DEFAULT_REQ;
+	int ret;
+	unsigned int portid;
+	struct seq_family sf;
+
+	if (argc != 2) {
+		fprintf(stderr, "Usage: %s <inet|inet6>\n", argv[0]);
+		exit(EXIT_FAILURE);
+	}
+	if (strcmp(argv[1], "inet") == 0)
+		sf.family = AF_INET;
+	else if (strcmp(argv[1], "inet6") == 0)
+		sf.family = AF_INET6;
+
+	nl = mnl_socket_open(NETLINK_ROUTE);
+	if (nl == NULL) {
+		perror("mnl_socket_open");
+		exit(EXIT_FAILURE);
+	}
+
+	nlm = mnl_ring_map(nl, &nlmr, &nlmr);
+	if (nlm == NULL) {
+		perror("mnl_ring_map");
+		exit(EXIT_FAILURE);
+	}
+
+	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
+		perror("mnl_socket_bind");
+		exit(EXIT_FAILURE);
+	}
+	portid = mnl_socket_get_portid(nl);
+
+	sf.seq = time(NULL);
+	if (mnl_ring_build_frame(nlm, build_cb, &sf) <= 0) {
+		perror("mnl_ring_build_frame");
+		exit(EXIT_FAILURE);
+	}
+
+	if (mnl_ring_send(nlm) < 0) {
+		perror("mnl_ring_send");
+		exit(EXIT_FAILURE);
+	}
+	mnl_ring_advance(nlm, MNL_RING_TX);
+
+	while ((ret = mnl_ring_parse_frame(nlm, sf.seq, portid, data_cb, NULL)) > 0)
+		;
+
+	if (ret == -1) {
+		perror("error");
+		exit(EXIT_FAILURE);
+	}
+
+	mnl_ring_unmap(nlm);
+	mnl_socket_close(nl);
+
+	return 0;
+}
diff --git a/examples/mmap/nonmin2/rtnl-route-dump.c b/examples/mmap/nonmin2/rtnl-route-dump.c
new file mode 100644
index 0000000..28b09f9
--- /dev/null
+++ b/examples/mmap/nonmin2/rtnl-route-dump.c
@@ -0,0 +1,381 @@
+/* This example is placed in the public domain. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include <libmnl/libmnl.h>
+#include <linux/if.h>
+#include <linux/if_link.h>
+#include <linux/rtnetlink.h>
+
+static int data_attr_cb2(const struct nlattr *attr, void *data)
+{
+	const struct nlattr **tb = data;
+
+	/* skip unsupported attribute in user-space */
+	if (mnl_attr_type_valid(attr, RTAX_MAX) < 0)
+		return MNL_CB_OK;
+
+	if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
+		perror("mnl_attr_validate");
+		return MNL_CB_ERROR;
+	}
+
+	tb[mnl_attr_get_type(attr)] = attr;
+	return MNL_CB_OK;
+}
+
+static void attributes_show_ipv4(struct nlattr *tb[])
+{
+	if (tb[RTA_TABLE]) {
+		printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
+	}
+	if (tb[RTA_DST]) {
+		struct in_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
+		printf("dst=%s ", inet_ntoa(*addr));
+	}
+	if (tb[RTA_SRC]) {
+		struct in_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
+		printf("src=%s ", inet_ntoa(*addr));
+	}
+	if (tb[RTA_OIF]) {
+		printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
+	}
+	if (tb[RTA_FLOW]) {
+		printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
+	}
+	if (tb[RTA_PREFSRC]) {
+		struct in_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
+		printf("prefsrc=%s ", inet_ntoa(*addr));
+	}
+	if (tb[RTA_GATEWAY]) {
+		struct in_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
+		printf("gw=%s ", inet_ntoa(*addr));
+	}
+	if (tb[RTA_PRIORITY]) {
+		printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY]));
+	}
+	if (tb[RTA_METRICS]) {
+		int i;
+		struct nlattr *tbx[RTAX_MAX+1] = {};
+
+		mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);
+
+		for (i=0; i<RTAX_MAX; i++) {
+			if (tbx[i]) {
+				printf("metrics[%d]=%u ",
+					i, mnl_attr_get_u32(tbx[i]));
+			}
+		}
+	}
+}
+
+/* like inet_ntoa(), not reentrant */
+static const char *inet6_ntoa(struct in6_addr in6)
+{
+	static char buf[INET6_ADDRSTRLEN];
+
+	return inet_ntop(AF_INET6, &in6.s6_addr, buf, sizeof(buf));
+}
+
+static void attributes_show_ipv6(struct nlattr *tb[])
+{
+	if (tb[RTA_TABLE]) {
+		printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
+	}
+	if (tb[RTA_DST]) {
+		struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
+		printf("dst=%s ", inet6_ntoa(*addr));
+	}
+	if (tb[RTA_SRC]) {
+		struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
+		printf("src=%s ", inet6_ntoa(*addr));
+	}
+	if (tb[RTA_OIF]) {
+		printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
+	}
+	if (tb[RTA_FLOW]) {
+		printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
+	}
+	if (tb[RTA_PREFSRC]) {
+		struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
+		printf("prefsrc=%s ", inet6_ntoa(*addr));
+	}
+	if (tb[RTA_GATEWAY]) {
+		struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
+		printf("gw=%s ", inet6_ntoa(*addr));
+	}
+	if (tb[RTA_PRIORITY]) {
+		printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY]));
+	}
+	if (tb[RTA_METRICS]) {
+		int i;
+		struct nlattr *tbx[RTAX_MAX+1] = {};
+
+		mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);
+
+		for (i=0; i<RTAX_MAX; i++) {
+			if (tbx[i]) {
+				printf("metrics[%d]=%u ",
+					i, mnl_attr_get_u32(tbx[i]));
+			}
+		}
+	}
+}
+
+static int data_ipv4_attr_cb(const struct nlattr *attr, void *data)
+{
+	const struct nlattr **tb = data;
+	int type = mnl_attr_get_type(attr);
+
+	/* skip unsupported attribute in user-space */
+	if (mnl_attr_type_valid(attr, RTA_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch(type) {
+	case RTA_TABLE:
+	case RTA_DST:
+	case RTA_SRC:
+	case RTA_OIF:
+	case RTA_FLOW:
+	case RTA_PREFSRC:
+	case RTA_GATEWAY:
+	case RTA_PRIORITY:
+		if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	case RTA_METRICS:
+		if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	}
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static int data_ipv6_attr_cb(const struct nlattr *attr, void *data)
+{
+	const struct nlattr **tb = data;
+	int type = mnl_attr_get_type(attr);
+
+	/* skip unsupported attribute in user-space */
+	if (mnl_attr_type_valid(attr, RTA_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch(type) {
+	case RTA_TABLE:
+	case RTA_OIF:
+	case RTA_FLOW:
+	case RTA_PRIORITY:
+		if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	case RTA_DST:
+	case RTA_SRC:
+	case RTA_PREFSRC:
+	case RTA_GATEWAY:
+		if (mnl_attr_validate2(attr, MNL_TYPE_BINARY,
+					sizeof(struct in6_addr)) < 0) {
+			perror("mnl_attr_validate2");
+			return MNL_CB_ERROR;
+		}
+		break;
+	case RTA_METRICS:
+		if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
+			perror("mnl_attr_validate");
+			return MNL_CB_ERROR;
+		}
+		break;
+	}
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static int data_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nlattr *tb[RTA_MAX+1] = {};
+	struct rtmsg *rm = mnl_nlmsg_get_payload(nlh);
+
+	/* protocol family = AF_INET | AF_INET6 */
+	printf("family=%u ", rm->rtm_family);
+
+	/* destination CIDR, eg. 24 or 32 for IPv4 */
+	printf("dst_len=%u ", rm->rtm_dst_len);
+
+	/* source CIDR */
+	printf("src_len=%u ", rm->rtm_src_len);
+
+	/* type of service (TOS), eg. 0 */
+	printf("tos=%u ", rm->rtm_tos);
+
+	/* table id:
+	 *	RT_TABLE_UNSPEC		= 0
+	 *
+	 * 	... user defined values ...
+	 *
+	 *	RT_TABLE_COMPAT		= 252
+	 *	RT_TABLE_DEFAULT	= 253
+	 *	RT_TABLE_MAIN		= 254
+	 *	RT_TABLE_LOCAL		= 255
+	 *	RT_TABLE_MAX		= 0xFFFFFFFF
+	 *
+	 * Synonimous attribute: RTA_TABLE.
+	 */
+	printf("table=%u ", rm->rtm_table);
+
+	/* type:
+	 * 	RTN_UNSPEC	= 0
+	 * 	RTN_UNICAST	= 1
+	 * 	RTN_LOCAL	= 2
+	 * 	RTN_BROADCAST	= 3
+	 *	RTN_ANYCAST	= 4
+	 *	RTN_MULTICAST	= 5
+	 *	RTN_BLACKHOLE	= 6
+	 *	RTN_UNREACHABLE	= 7
+	 *	RTN_PROHIBIT	= 8
+	 *	RTN_THROW	= 9
+	 *	RTN_NAT		= 10
+	 *	RTN_XRESOLVE	= 11
+	 *	__RTN_MAX	= 12
+	 */
+	printf("type=%u ", rm->rtm_type);
+
+	/* scope:
+	 * 	RT_SCOPE_UNIVERSE	= 0   : everywhere in the universe
+	 *
+	 *      ... user defined values ...
+	 *
+	 * 	RT_SCOPE_SITE		= 200
+	 * 	RT_SCOPE_LINK		= 253 : destination attached to link
+	 * 	RT_SCOPE_HOST		= 254 : local address
+	 * 	RT_SCOPE_NOWHERE	= 255 : not existing destination
+	 */
+	printf("scope=%u ", rm->rtm_scope);
+
+	/* protocol:
+	 * 	RTPROT_UNSPEC	= 0
+	 * 	RTPROT_REDIRECT = 1
+	 * 	RTPROT_KERNEL	= 2 : route installed by kernel
+	 * 	RTPROT_BOOT	= 3 : route installed during boot
+	 * 	RTPROT_STATIC	= 4 : route installed by administrator
+	 *
+	 * Values >= RTPROT_STATIC are not interpreted by kernel, they are
+	 * just user-defined.
+	 */
+	printf("proto=%u ", rm->rtm_protocol);
+
+	/* flags:
+	 * 	RTM_F_NOTIFY	= 0x100: notify user of route change
+	 * 	RTM_F_CLONED	= 0x200: this route is cloned
+	 * 	RTM_F_EQUALIZE	= 0x400: Multipath equalizer: NI
+	 * 	RTM_F_PREFIX	= 0x800: Prefix addresses
+	 */
+	printf("flags=%x ", rm->rtm_flags);
+
+	switch(rm->rtm_family) {
+	case AF_INET:
+		mnl_attr_parse(nlh, sizeof(*rm), data_ipv4_attr_cb, tb);
+		attributes_show_ipv4(tb);
+		break;
+	case AF_INET6:
+		mnl_attr_parse(nlh, sizeof(*rm), data_ipv6_attr_cb, tb);
+		attributes_show_ipv6(tb);
+		break;
+	}
+
+	printf("\n");
+	return MNL_CB_OK;
+}
+
+struct seq_family {
+	unsigned char family;
+	unsigned int seq;
+};
+
+static int build_cb(void *buf, void *data)
+{
+	struct nlmsghdr *nlh;
+	struct rtmsg *rtm;
+	struct seq_family *sf = (struct seq_family *)data;
+
+	nlh = mnl_nlmsg_put_header(buf);
+	nlh->nlmsg_type = RTM_GETROUTE;
+	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+	nlh->nlmsg_seq = sf->seq;
+	rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg));
+	rtm->rtm_family = sf->family;
+
+	return nlh->nlmsg_len;
+}
+	
+int main(int argc, char *argv[])
+{
+	struct mnl_socket *nl;
+	struct mnl_ring_socket *nlm;
+	struct nl_mmap_req nlmr = MNL_MMAP_DEFAULT_REQ;
+	int ret;
+	unsigned int portid;
+	struct seq_family sf;
+
+	if (argc != 2) {
+		fprintf(stderr, "Usage: %s <inet|inet6>\n", argv[0]);
+		exit(EXIT_FAILURE);
+	}
+
+	if (strcmp(argv[1], "inet") == 0)
+		sf.family = AF_INET;
+	else if (strcmp(argv[1], "inet6") == 0)
+		sf.family = AF_INET6;
+
+	nl = mnl_socket_open(NETLINK_ROUTE);
+	if (nl == NULL) {
+		perror("mnl_socket_open");
+		exit(EXIT_FAILURE);
+	}
+
+	nlm = mnl_ring_map(nl, &nlmr, &nlmr);
+	if (nlm == NULL) {
+		perror("mnl_ring_map");
+		exit(EXIT_FAILURE);
+	}
+
+	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
+		perror("mnl_socket_bind");
+		exit(EXIT_FAILURE);
+	}
+	portid = mnl_socket_get_portid(nl);
+
+	if (mnl_ring_build_frame(nlm, build_cb, &sf) <= 0) {
+		perror("mnl_ring_build_frame");
+		exit(EXIT_FAILURE);
+	}
+
+	if (mnl_ring_send(nlm) < 0) {
+		perror("mnl_ring_send");
+		exit(EXIT_FAILURE);
+	}
+	mnl_ring_advance(nlm, MNL_RING_TX);
+
+	while ((ret = mnl_ring_parse_frame(nlm, sf.seq, portid, data_cb, NULL)) > 0)
+		;
+
+	if (ret == -1) {
+		perror("error");
+		exit(EXIT_FAILURE);
+	}
+
+	mnl_ring_unmap(nlm);
+	mnl_socket_close(nl);
+
+	return 0;
+}
-- 
1.8.4.rc3


                 reply	other threads:[~2013-12-07 15:15 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87k3fg8zge.wl%chamaken@gmail.com \
    --to=chamaken@gmail.com \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pablo@netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.