diff options
author | Lukáš Karas <karas@avast.com> | 2018-02-23 18:20:08 (GMT) |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-04-06 17:27:33 (GMT) |
commit | 6c6c74a7889cf121eedd398ae015bb8e38f1a94d (patch) | |
tree | 372395dda2f2b3f58ec65afd3e5dcb4c30d650c7 | |
parent | 90034bfd497f5054f2b8eb4862345e3477527541 (diff) | |
download | libnl-6c6c74a7889cf121eedd398ae015bb8e38f1a94d.zip libnl-6c6c74a7889cf121eedd398ae015bb8e38f1a94d.tar.gz libnl-6c6c74a7889cf121eedd398ae015bb8e38f1a94d.tar.bz2 |
add demo program for listen conntrack events
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | src/.gitignore | 1 | ||||
-rw-r--r-- | src/nf-ct-events.c | 115 |
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, ¶ms); +} + +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)); + } + } + } +} |