From 7ea731b0e8582ff67ef2703e05c4a45220da538c Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 15 Apr 2012 21:49:49 +0200 Subject: examples: add example using libmnl and the new low-level API (expectation) This patch adds the following examples: nfexp-mnl-dump nfexp-mnl-event Basically, we re-use the existing object oriented handling and we provide full control on the netlink socket at the same time. Signed-off-by: Pablo Neira Ayuso --- examples/Makefile.am | 12 ++++++- examples/nfexp-mnl-dump.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++ examples/nfexp-mnl-event.c | 79 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 examples/nfexp-mnl-dump.c create mode 100644 examples/nfexp-mnl-event.c (limited to 'examples') diff --git a/examples/Makefile.am b/examples/Makefile.am index 684998b..55bd750 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -5,7 +5,9 @@ check_PROGRAMS = nfct-mnl-create \ nfct-mnl-dump \ nfct-mnl-event \ nfct-mnl-flush \ - nfct-mnl-get + nfct-mnl-get \ + nfexp-mnl-dump \ + nfexp-mnl-event nfct_mnl_create_SOURCES = nfct-mnl-create.c nfct_mnl_create_LDADD = ../src/libnetfilter_conntrack.la @@ -30,3 +32,11 @@ nfct_mnl_flush_LDFLAGS = -dynamic -ldl -lmnl nfct_mnl_get_SOURCES = nfct-mnl-get.c nfct_mnl_get_LDADD = ../src/libnetfilter_conntrack.la nfct_mnl_get_LDFLAGS = -dynamic -ldl -lmnl + +nfexp_mnl_dump_SOURCES = nfexp-mnl-dump.c +nfexp_mnl_dump_LDADD = ../src/libnetfilter_conntrack.la +nfexp_mnl_dump_LDFLAGS = -dynamic -ldl -lmnl + +nfexp_mnl_event_SOURCES = nfexp-mnl-event.c +nfexp_mnl_event_LDADD = ../src/libnetfilter_conntrack.la +nfexp_mnl_event_LDFLAGS = -dynamic -ldl -lmnl diff --git a/examples/nfexp-mnl-dump.c b/examples/nfexp-mnl-dump.c new file mode 100644 index 0000000..b44c7d8 --- /dev/null +++ b/examples/nfexp-mnl-dump.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include + +#include +#include + +static int data_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nf_expect *exp; + uint32_t type = NFCT_T_UNKNOWN; + char buf[4096]; + + exp = nfexp_new(); + if (exp == NULL) + return MNL_CB_OK; + + if (nfexp_nlmsg_parse(nlh, exp) < 0) { + perror("failed to parse message from kernel"); + return MNL_CB_ERROR; + } + + nfexp_snprintf(buf, sizeof(buf), exp, type, NFCT_O_DEFAULT, 0); + printf("%s\n", buf); + + nfexp_destroy(exp); + + return MNL_CB_OK; +} + +int main(void) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + struct nfgenmsg *nfh; + uint32_t seq, portid; + int ret; + + nl = mnl_socket_open(NETLINK_NETFILTER); + if (nl == NULL) { + perror("mnl_socket_open"); + 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); + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK_EXP << 8) | IPCTNL_MSG_EXP_GET; + nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP|NLM_F_ACK; + 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; + + ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); + if (ret == -1) { + perror("mnl_socket_recvfrom"); + exit(EXIT_FAILURE); + } + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + while (1) { + 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)); + } + if (ret == -1) { + perror("mnl_socket_recvfrom"); + exit(EXIT_FAILURE); + } + + mnl_socket_close(nl); + + return 0; +} diff --git a/examples/nfexp-mnl-event.c b/examples/nfexp-mnl-event.c new file mode 100644 index 0000000..5de97ec --- /dev/null +++ b/examples/nfexp-mnl-event.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include + +#include +#include + +static int data_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nf_expect *exp; + uint32_t type = NFCT_T_UNKNOWN; + char buf[4096]; + + switch(nlh->nlmsg_type & 0xFF) { + case IPCTNL_MSG_EXP_NEW: + if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL)) + type = NFCT_T_NEW; + else + type = NFCT_T_UPDATE; + break; + case IPCTNL_MSG_EXP_DELETE: + type = NFCT_T_DESTROY; + break; + } + + exp = nfexp_new(); + if (exp == NULL) + return MNL_CB_OK; + + nfexp_nlmsg_parse(nlh, exp); + + nfexp_snprintf(buf, sizeof(buf), exp, + type, NFCT_O_DEFAULT, 0); + printf("%s\n", buf); + + nfexp_destroy(exp); + + return MNL_CB_OK; +} + +int main(void) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + int ret; + + nl = mnl_socket_open(NETLINK_NETFILTER); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_bind(nl, NF_NETLINK_CONNTRACK_EXP_NEW | + NF_NETLINK_CONNTRACK_EXP_UPDATE | + NF_NETLINK_CONNTRACK_EXP_DESTROY, + MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + + while (1) { + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + if (ret == -1) { + perror("mnl_socket_recvfrom"); + exit(EXIT_FAILURE); + } + + ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL); + if (ret == -1) { + perror("mnl_cb_run"); + exit(EXIT_FAILURE); + } + } + + mnl_socket_close(nl); + + return 0; +} -- cgit v1.2.3