]> granicus.if.org Git - libnl/commitdiff
add demo program for listen conntrack events
authorLukáš Karas <karas@avast.com>
Fri, 23 Feb 2018 18:20:08 +0000 (19:20 +0100)
committerThomas Haller <thaller@redhat.com>
Fri, 6 Apr 2018 17:27:33 +0000 (19:27 +0200)
Makefile.am
src/.gitignore
src/nf-ct-events.c [new file with mode: 0644]

index e287b17316f8a89d257fbe2ff2832588c6573046..eabad24c3e18d80fd3f2a29d68a77acb9c129a16 100644 (file)
@@ -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)
index 5de9f29301d503f26cfe03f03c2a576a312e7252..223ec5872f6eb971934986e0b7d50a395042eef3 100644 (file)
@@ -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 (file)
index 0000000..a9156b4
--- /dev/null
@@ -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));
+                       }
+               }
+       }
+}