summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukáš Karas <karas@avast.com>2018-02-23 18:20:08 (GMT)
committerThomas Haller <thaller@redhat.com>2018-04-06 17:27:33 (GMT)
commit6c6c74a7889cf121eedd398ae015bb8e38f1a94d (patch)
tree372395dda2f2b3f58ec65afd3e5dcb4c30d650c7
parent90034bfd497f5054f2b8eb4862345e3477527541 (diff)
downloadlibnl-6c6c74a7889cf121eedd398ae015bb8e38f1a94d.zip
libnl-6c6c74a7889cf121eedd398ae015bb8e38f1a94d.tar.gz
libnl-6c6c74a7889cf121eedd398ae015bb8e38f1a94d.tar.bz2
add demo program for listen conntrack events
-rw-r--r--Makefile.am3
-rw-r--r--src/.gitignore1
-rw-r--r--src/nf-ct-events.c115
3 files changed, 119 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index e287b17..eabad24 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -628,6 +628,7 @@ cli_programs = \
src/idiag-socket-details \
src/nf-ct-add \
src/nf-ct-list \
+ src/nf-ct-events \
src/nf-exp-add \
src/nf-exp-delete \
src/nf-exp-list \
@@ -691,6 +692,8 @@ src_idiag_socket_details_CPPFLAGS = $(src_cppflags)
src_idiag_socket_details_LDADD = $(src_ldadd)
src_nf_ct_add_CPPFLAGS = $(src_cppflags)
src_nf_ct_add_LDADD = $(src_ldadd)
+src_nf_ct_events_CPPFLAGS = $(src_cppflags)
+src_nf_ct_events_LDADD = $(src_ldadd)
src_nf_ct_list_CPPFLAGS = $(src_cppflags)
src_nf_ct_list_LDADD = $(src_ldadd)
src_nf_exp_add_CPPFLAGS = $(src_cppflags)
diff --git a/src/.gitignore b/src/.gitignore
index 5de9f29..223ec58 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,6 +1,7 @@
genl-ctrl-list
/nf-ct-add
nf-ct-list
+nf-ct-events
nf-exp-list
nf-exp-add
nf-exp-delete
diff --git a/src/nf-ct-events.c b/src/nf-ct-events.c
new file mode 100644
index 0000000..a9156b4
--- /dev/null
+++ b/src/nf-ct-events.c
@@ -0,0 +1,115 @@
+/*
+ * src/nf-ct-events.c Listen on Conntrack Events
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2018 Avast software
+ */
+
+#include <netlink/cli/utils.h>
+#include <netlink/cli/ct.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+struct private_nl_object
+{
+ int ce_refcnt;
+ struct nl_object_ops * ce_ops;
+ struct nl_cache * ce_cache;
+ struct nl_list_head ce_list;
+ int ce_msgtype;
+ int ce_flags;
+ uint64_t ce_mask;
+};
+
+static void nf_conntrack_parse_callback(struct nl_object *obj, void *opaque)
+{
+ struct nl_dump_params params = {
+ .dp_fd = stdout,
+ .dp_type = NL_DUMP_DETAILS,
+ };
+
+ nl_object_dump(obj, &params);
+}
+
+static int nf_conntrack_event_callback(struct nl_msg *msg, void *opaque)
+{
+ int err;
+ struct nlmsghdr *hdr = nlmsg_hdr(msg);
+
+ enum cntl_msg_types type = (enum cntl_msg_types) NFNL_MSG_TYPE(hdr->nlmsg_type);
+
+ int flags = hdr->nlmsg_flags;
+
+ if (type == IPCTNL_MSG_CT_DELETE) {
+ printf("DELETE ");
+ } else if (type == IPCTNL_MSG_CT_NEW) {
+ if (flags & (NLM_F_CREATE|NLM_F_EXCL)) {
+ printf("NEW ");
+ } else {
+ printf("UPDATE ");
+ }
+ } else {
+ printf("UNKNOWN ");
+ }
+
+ if ((err = nl_msg_parse(msg, &nf_conntrack_parse_callback, opaque)) < 0) {
+ nl_cli_fatal(err, "nl_msg_parse: %s", nl_geterror(err));
+ }
+ /* Continue with next event */
+ return NL_OK;
+}
+
+int main(int argc, char *argv[])
+{
+ struct nl_sock *socket;
+ int err;
+
+ socket = nl_cli_alloc_socket();
+ if (socket == NULL) {
+ nl_cli_fatal(ENOBUFS, "Unable to allocate netlink socket");
+ }
+
+ /*
+ * Disable sequence number checking.
+ * This is required to allow messages to be processed which were not requested by
+ * a preceding request message, e.g. netlink events.
+ */
+ nl_socket_disable_seq_check(socket);
+
+ /* subscribe conntrack events */
+ nl_join_groups(socket, NF_NETLINK_CONNTRACK_NEW |
+ NF_NETLINK_CONNTRACK_UPDATE |
+ NF_NETLINK_CONNTRACK_DESTROY |
+ NF_NETLINK_CONNTRACK_EXP_NEW |
+ NF_NETLINK_CONNTRACK_EXP_UPDATE |
+ NF_NETLINK_CONNTRACK_EXP_DESTROY);
+
+ nl_cli_connect(socket, NETLINK_NETFILTER);
+
+ nl_socket_modify_cb(socket, NL_CB_VALID, NL_CB_CUSTOM, &nf_conntrack_event_callback, 0);
+
+ while (1) {
+
+ errno = 0;
+ if ((err = nl_recvmsgs_default(socket)) < 0) {
+ switch (errno) {
+ case ENOBUFS:
+ // just print warning
+ fprintf(stderr, "Lost events because of ENOBUFS\n");
+ break;
+ case EAGAIN:
+ case EINTR:
+ // continue reading
+ break;
+ default:
+ nl_cli_fatal(err, "Failed to receive: %s", nl_geterror(err));
+ }
+ }
+ }
+}