]> git.ipfire.org Git - thirdparty/libnl.git/commitdiff
netfilter/ct: expand CT parameters that can be used in add/delete operations
authorRich Fought <rmf.aero@gmail.com>
Thu, 27 Feb 2014 00:02:13 +0000 (16:02 -0800)
committerThomas Haller <thaller@redhat.com>
Mon, 14 Apr 2014 17:20:53 +0000 (19:20 +0200)
This expands functionality for manipulating conntracks over netlink by
adding other attributes to nfnl_ct_build_message(). Added a command link
program to add conntracks.

https://github.com/thom311/libnl/pull/55

[thaller@redhat.com: cleaned up whitespace from original patch]
Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Thomas Haller <thaller@redhat.com>
include/netlink/cli/ct.h
include/netlink/netfilter/ct.h
lib/netfilter/ct.c
lib/netfilter/ct_obj.c
src/Makefile.am
src/lib/ct.c
src/nf-ct-add.c [new file with mode: 0644]

index bed776b18a4e9f8741fb2ee895689e7cc0327a0a..ebe7c9dc879c640db55fefae7b0956be5cbd931d 100644 (file)
@@ -30,5 +30,6 @@ extern void nl_cli_ct_parse_src_port(struct nfnl_ct *, int, char *);
 extern void nl_cli_ct_parse_dst_port(struct nfnl_ct *, int, char *);
 extern void nl_cli_ct_parse_tcp_state(struct nfnl_ct *, char *);
 extern void nl_cli_ct_parse_status(struct nfnl_ct *, char *);
+extern void nl_cli_ct_parse_zone(struct nfnl_ct *, char *);
 
 #endif
index 31deeb46fd64cc675189329583207dcbfbd17672..ef5d0355052df8f16d99a7e83e88808f82b12f45 100644 (file)
@@ -70,6 +70,7 @@ extern int    nfnl_ct_str2tcp_state(const char *name);
 
 extern void    nfnl_ct_set_status(struct nfnl_ct *, uint32_t);
 extern void    nfnl_ct_unset_status(struct nfnl_ct *, uint32_t);
+extern int     nfnl_ct_test_status(const struct nfnl_ct *ct);
 extern uint32_t        nfnl_ct_get_status(const struct nfnl_ct *);
 extern char *  nfnl_ct_status2str(int, char *, size_t);
 extern int     nfnl_ct_str2status(const char *);
index 130f4b1137017aac08f2b81992bf2b3a117f3f54..04f9d01685d1c382fb91ee56f4c14173287dee09 100644 (file)
@@ -35,11 +35,19 @@ static uint64_t ntohll(uint64_t x)
 {
        return x;
 }
+static uint64_t htonll(uint64_t x)
+{
+       return x;
+}
 #elif __BYTE_ORDER == __LITTLE_ENDIAN
 static uint64_t ntohll(uint64_t x)
 {
        return bswap_64(x);
 }
+static uint64_t htonll(uint64_t x)
+{
+       return bswap_64(x);
+}
 #endif
 
 static struct nla_policy ct_policy[CTA_MAX+1] = {
@@ -520,9 +528,31 @@ static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags,
        if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0)
                goto err_out;
 
+       /* REPLY tuple is optional, dont add unless at least src/dst specified */
+
+       if ( nfnl_ct_get_src(ct, 1) && nfnl_ct_get_dst(ct, 1) )
+               if ((err = nfnl_ct_build_tuple(msg, ct, 1)) < 0)
+                       goto err_out;
+
+       if (nfnl_ct_test_status(ct))
+               NLA_PUT_U32(msg, CTA_STATUS, htonl(nfnl_ct_get_status(ct)));
+
+       if (nfnl_ct_test_timeout(ct))
+               NLA_PUT_U32(msg, CTA_TIMEOUT, htonl(nfnl_ct_get_timeout(ct)));
+
+       if (nfnl_ct_test_mark(ct))
+               NLA_PUT_U32(msg, CTA_MARK, htonl(nfnl_ct_get_mark(ct)));
+
+       if (nfnl_ct_test_id(ct))
+               NLA_PUT_U32(msg, CTA_ID, htonl(nfnl_ct_get_id(ct)));
+
+       if (nfnl_ct_test_zone(ct))
+               NLA_PUT_U16(msg, CTA_ZONE, htons(nfnl_ct_get_zone(ct)));
+
        *result = msg;
        return 0;
 
+nla_put_failure:
 err_out:
        nlmsg_free(msg);
        return err;
index 48e07822ecd27334c942a17ed5e0866ac344a30d..61b6a31b8d74ba416f8b0109c00bd96a8d7e7d7b 100644 (file)
@@ -494,6 +494,11 @@ void nfnl_ct_unset_status(struct nfnl_ct *ct, uint32_t status)
        ct->ce_mask |= CT_ATTR_STATUS;
 }
 
+int nfnl_ct_test_status(const struct nfnl_ct *ct)
+{
+       return !!(ct->ce_mask & CT_ATTR_STATUS);
+}
+
 uint32_t nfnl_ct_get_status(const struct nfnl_ct *ct)
 {
        return ct->ct_status;
index b2b7fc7fae33df7bb846b1411c31bddc20744974..f8ac4ca03a1549b09cd69e70f39d159afafe6525 100644 (file)
@@ -23,7 +23,7 @@ sbin_PROGRAMS = \
        nl-link-list
 
 noinst_PROGRAMS = \
-       nf-ct-list nf-log nf-queue nf-monitor \
+       nf-ct-list nf-ct-add nf-log nf-queue nf-monitor \
        nf-exp-list nf-exp-add nf-exp-delete \
        nl-addr-add nl-addr-delete nl-addr-list \
        nl-link-set nl-link-stats \
@@ -44,6 +44,7 @@ noinst_PROGRAMS = \
 genl_ctrl_list_SOURCES = genl-ctrl-list.c 
 
 nf_ct_list_SOURCES = nf-ct-list.c 
+nf_ct_add_SOURCES = nf-ct-add.c
 nf_log_SOURCES = nf-log.c
 nf_queue_SOURCES = nf-queue.c 
 nf_monitor_SOURCES = nf-monitor.c
index 5bab08f7937ddeba742e0b573c9b43c3b1385240..c90387802e6735e6acdbf07c89d07b53d45a0cd8 100644 (file)
@@ -137,6 +137,12 @@ void nl_cli_ct_parse_status(struct nfnl_ct *ct, char *arg)
        nfnl_ct_set_status(ct, status);
 }
 
+void nl_cli_ct_parse_zone(struct nfnl_ct *ct, char *arg)
+{
+       uint32_t zone = nl_cli_parse_u32(arg);
+       nfnl_ct_set_zone(ct, zone);
+}
+
 #if 0
                } else if (arg_match("origicmpid")) {
                        if (argc > ++idx)
diff --git a/src/nf-ct-add.c b/src/nf-ct-add.c
new file mode 100644 (file)
index 0000000..8ad4c53
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * src/nf-ct-list.c     List Conntrack Entries
+ *
+ *     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) 2003-2009 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
+ * Copyright (c) 2007 Secure Computing Corporation
+ */
+
+#include <netlink/cli/utils.h>
+#include <netlink/cli/ct.h>
+
+static int quiet = 0;
+
+static void print_usage(void)
+{
+       printf(
+       "Usage: nf-ct-add [OPTION]... [CONNTRACK ENTRY]\n"
+       "\n"
+       "Options\n"
+       " -q, --quiet           Do not print informal notifications.\n"
+       " -h, --help            Show this help\n"
+       " -v, --version         Show versioning information\n"
+       "\n"
+       "Conntrack Selection\n"
+       " -p, --proto=PROTOCOL    Protocol\n"
+       "     --orig-src=ADDR     Original source address\n"
+       "     --orig-sport=PORT   Original source port\n"
+       "     --orig-dst=ADDR     Original destination address\n"
+       "     --orig-dport=PORT   Original destination port\n"
+       "     --reply-src=ADDR    Reply source address\n"
+       "     --reply-sport=PORT  Reply source port\n"
+       "     --reply-dst=ADDR    Reply destination address\n"
+       "     --reply-dport=PORT  Reply destination port\n"
+       " -F, --family=FAMILY     Address family\n"
+       "     --mark=NUM          Mark value\n"
+       "     --timeout=NUM       Timeout value\n"
+       "     --status            Bitset representing status of connection.\n"
+       "     --zone=NUM          Zone value\n"
+       );
+       exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+       struct nl_sock *sock;
+       struct nfnl_ct *ct;
+       struct nl_dump_params params = {
+               .dp_type = NL_DUMP_LINE,
+               .dp_fd = stdout,
+       };
+       int err, nlflags = NLM_F_CREATE;
+
+       ct = nl_cli_ct_alloc();
+
+       for (;;) {
+               int c, optidx = 0;
+               enum {
+                       ARG_ORIG_SRC = 257,
+                       ARG_ORIG_SPORT = 258,
+                       ARG_ORIG_DST,
+                       ARG_ORIG_DPORT,
+                       ARG_REPLY_SRC,
+                       ARG_REPLY_SPORT,
+                       ARG_REPLY_DST,
+                       ARG_REPLY_DPORT,
+                       ARG_MARK,
+                       ARG_TIMEOUT,
+                       ARG_STATUS,
+                       ARG_ZONE,
+               };
+               static struct option long_opts[] = {
+                       { "quiet", 0, 0, 'q' },
+                       { "help", 0, 0, 'h' },
+                       { "version", 0, 0, 'v' },
+                       { "proto", 1, 0, 'p' },
+                       { "orig-src", 1, 0, ARG_ORIG_SRC },
+                       { "orig-sport", 1, 0, ARG_ORIG_SPORT },
+                       { "orig-dst", 1, 0, ARG_ORIG_DST },
+                       { "orig-dport", 1, 0, ARG_ORIG_DPORT },
+                       { "reply-src", 1, 0, ARG_REPLY_SRC },
+                       { "reply-sport", 1, 0, ARG_REPLY_SPORT },
+                       { "reply-dst", 1, 0, ARG_REPLY_DST },
+                       { "reply-dport", 1, 0, ARG_REPLY_DPORT },
+                       { "family", 1, 0, 'F' },
+                       { "mark", 1, 0, ARG_MARK },
+                       { "timeout", 1, 0, ARG_TIMEOUT },
+                       { "status", 1, 0, ARG_STATUS },
+                       { "zone", 1, 0, ARG_ZONE },
+                       { 0, 0, 0, 0 }
+               };
+
+               c = getopt_long(argc, argv, "46q:hv:p:F:", long_opts, &optidx);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+               case '?': exit(NLE_INVAL);
+               case 'q': quiet = 1; break;
+               case '4': nfnl_ct_set_family(ct, AF_INET); break;
+               case '6': nfnl_ct_set_family(ct, AF_INET6); break;
+               case 'h': print_usage(); break;
+               case 'v': nl_cli_print_version(); break;
+               case 'p': nl_cli_ct_parse_protocol(ct, optarg); break;
+               case ARG_ORIG_SRC: nl_cli_ct_parse_src(ct, 0, optarg); break;
+               case ARG_ORIG_SPORT: nl_cli_ct_parse_src_port(ct, 0, optarg); break;
+               case ARG_ORIG_DST: nl_cli_ct_parse_dst(ct, 0, optarg); break;
+               case ARG_ORIG_DPORT: nl_cli_ct_parse_dst_port(ct, 0, optarg); break;
+               case ARG_REPLY_SRC: nl_cli_ct_parse_src(ct, 1, optarg); break;
+               case ARG_REPLY_SPORT: nl_cli_ct_parse_src_port(ct, 1, optarg); break;
+               case ARG_REPLY_DST: nl_cli_ct_parse_dst(ct, 1, optarg); break;
+               case ARG_REPLY_DPORT: nl_cli_ct_parse_dst_port(ct, 1, optarg); break;
+               case 'F': nl_cli_ct_parse_family(ct, optarg); break;
+               case ARG_MARK: nl_cli_ct_parse_mark(ct, optarg); break;
+               case ARG_TIMEOUT: nl_cli_ct_parse_timeout(ct, optarg); break;
+               case ARG_STATUS: nl_cli_ct_parse_status(ct, optarg); break;
+               case ARG_ZONE: nl_cli_ct_parse_zone(ct, optarg); break;
+               }
+       }
+
+       if (!quiet) {
+               printf("Adding ");
+               nl_object_dump(OBJ_CAST(ct), &params);
+       }
+
+       sock = nl_cli_alloc_socket();
+       nl_cli_connect(sock, NETLINK_NETFILTER);
+
+       if ((err = nfnl_ct_add(sock, ct, nlflags)) < 0)
+               nl_cli_fatal(err, "Unable to add conntrack: %s", nl_geterror(err));
+
+       if (!quiet) {
+               printf("Added ");
+               nl_object_dump(OBJ_CAST(ct), &params);
+       }
+
+       return 0;
+}