From patchwork Thu Aug 9 19:32:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsha Sharma X-Patchwork-Id: 955773 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="HcFhkyZo"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41mdgh4xdLz9s3Z for ; Fri, 10 Aug 2018 05:32:32 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727009AbeHIV6r (ORCPT ); Thu, 9 Aug 2018 17:58:47 -0400 Received: from mail-pf1-f182.google.com ([209.85.210.182]:46704 "EHLO mail-pf1-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726927AbeHIV6r (ORCPT ); Thu, 9 Aug 2018 17:58:47 -0400 Received: by mail-pf1-f182.google.com with SMTP id u24-v6so3294538pfn.13 for ; Thu, 09 Aug 2018 12:32:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=lkHlsZRAtshEfu7G5RVl7a/aFpKHheFaYE3G8uWOn8k=; b=HcFhkyZoWcFbzFj7sFbpHj+fXghPWriy13mc4lBAySsoMwLiPtYChaIW025FUk3cQH JC5pYzQCF1Z7qfWn3iMYbql+1EQIvGtiFUXvcmaSRT2YcSspO/l6h4MZ2yDOZTCzwR5a DgloIXLzDkrt4k3saNpVkKMc87HZ8HciTmPryndjjP6N+OYvIqSiBMa9FgtmGQUWba8w y0YCzTec++ebhzD59VHCx1dapa6HrN2A67rbFSgiumuiI2QVbQI67Ar9Eucr9W/4bL4/ I/26l3AeV/uIB1cnZngIQOaKM2UBUWamj0EH+FczN/lukhWsHAtuB47wPAusuVWE0ZIV 4nnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=lkHlsZRAtshEfu7G5RVl7a/aFpKHheFaYE3G8uWOn8k=; b=a9VKG1t/MZgH8gym80lPVegjAsIrD/3W5hZGhyOAm57jKMutwNX7NwyHloipOv7Rwl fOMMbr19dOuHKeCuGi4yNiEuMvaaMCNXxE2MlN9kXSHAV7wXSyaQKZn0GuxgdrxBZQMz IMbgxZBbYftnqkk08snEkEB1B9croJqxIiFxo8iVAtepCPXo+BsWmoTVceets5VAw+Xc PLA/0pLnz/RCxImFliuohiQAnXbBZpAL4VSPpAaUyQSEXZXT4/qPNp7fbNU6BWsliryr ss6wx8rD/rkVQPJ7d1gN/aGSaNFH+B9ppqHquHOztYfpXE24dN9gZ6FUq3ontwtF8vQ4 QRZw== X-Gm-Message-State: AOUpUlEfpU+JJCT1iPj+X6sJDCR1lRRn9U3J1eUmqb5Xo5YZSiXJtiCd sxFkeVQSGQlORprUes99aTaP/Uad X-Google-Smtp-Source: AA+uWPzWjwk9U9I3vvOWqiKSpa2/Bw5vHkxOgctN0tg3NNg9l8x4PC1jPKAF2LcDpneMX4BQ5wxGUw== X-Received: by 2002:a63:220d:: with SMTP id i13-v6mr3465896pgi.212.1533843150041; Thu, 09 Aug 2018 12:32:30 -0700 (PDT) Received: from XDDDDD.iitr.ernet.in ([103.37.201.27]) by smtp.gmail.com with ESMTPSA id y63-v6sm11791880pgd.94.2018.08.09.12.32.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 Aug 2018 12:32:29 -0700 (PDT) From: Harsha Sharma To: harshasharmaiitr@gmail.com, pablo@netfilter.org Cc: netfilter-devel@vger.kernel.org Subject: [PATCH libnftnl v5 1/3] src: add ct timeout support Date: Fri, 10 Aug 2018 01:02:16 +0530 Message-Id: <20180809193216.13643-1-harshasharmaiitr@gmail.com> X-Mailer: git-send-email 2.14.1 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Add support for ct timeout objects, used to assign connection tracking timeout policies. Signed-off-by: Harsha Sharma --- Changes in v5: - Remove nftnl_timeout_policy_attr_set_u32 - remove NFTNL_OBJ_CT_TIMEOUT_POLICY - remove nftnl_obj_get_void - minor changes Changes in v4: - updated include/linux/netfilter/nf_tables.h Changes in v3: - minor changes updated with nft patch Changes in v2: - minor changes include/libnftnl/Makefile.am | 3 +- include/libnftnl/cttimeout.h | 39 ++++ include/libnftnl/object.h | 7 + include/linux/netfilter/nf_tables.h | 14 +- include/obj.h | 6 + src/Makefile.am | 1 + src/libnftnl.map | 1 + src/obj/ct_timeout.c | 369 ++++++++++++++++++++++++++++++++++++ src/object.c | 4 +- 9 files changed, 441 insertions(+), 3 deletions(-) create mode 100644 include/libnftnl/cttimeout.h create mode 100644 src/obj/ct_timeout.c diff --git a/include/libnftnl/Makefile.am b/include/libnftnl/Makefile.am index d846a57..a94f414 100644 --- a/include/libnftnl/Makefile.am +++ b/include/libnftnl/Makefile.am @@ -10,4 +10,5 @@ pkginclude_HEADERS = batch.h \ ruleset.h \ common.h \ udata.h \ - gen.h + gen.h \ + cttimeout.h diff --git a/include/libnftnl/cttimeout.h b/include/libnftnl/cttimeout.h new file mode 100644 index 0000000..b29ec57 --- /dev/null +++ b/include/libnftnl/cttimeout.h @@ -0,0 +1,39 @@ +#ifndef _LIBNETFILTER_CTTIMEOUT_H_ +#define _LIBNETFILTER_CTTIMEOUT_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nftnl_obj_ct_timeout; + +enum nftnl_cttimeout_tcp { + NFTNL_CTTIMEOUT_TCP_SYN_SENT = 0, + NFTNL_CTTIMEOUT_TCP_SYN_RECV, + NFTNL_CTTIMEOUT_TCP_ESTABLISHED, + NFTNL_CTTIMEOUT_TCP_FIN_WAIT, + NFTNL_CTTIMEOUT_TCP_CLOSE_WAIT, + NFTNL_CTTIMEOUT_TCP_LAST_ACK, + NFTNL_CTTIMEOUT_TCP_TIME_WAIT, + NFTNL_CTTIMEOUT_TCP_CLOSE, + NFTNL_CTTIMEOUT_TCP_SYN_SENT2, + NFTNL_CTTIMEOUT_TCP_RETRANS, + NFTNL_CTTIMEOUT_TCP_UNACK, + NFTNL_CTTIMEOUT_TCP_MAX +}; + +enum nftnl_cttimeout_udp { + NFTNL_CTTIMEOUT_UDP_UNREPLIED = 0, + NFTNL_CTTIMEOUT_UDP_REPLIED, + NFTNL_CTTIMEOUT_UDP_MAX +}; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/include/libnftnl/object.h b/include/libnftnl/object.h index 6f9edfd..5ed6b98 100644 --- a/include/libnftnl/object.h +++ b/include/libnftnl/object.h @@ -7,6 +7,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -41,6 +42,12 @@ enum { NFTNL_OBJ_CT_HELPER_L4PROTO, }; +enum { + NFTNL_OBJ_CT_TIMEOUT_L3PROTO = NFTNL_OBJ_BASE, + NFTNL_OBJ_CT_TIMEOUT_L4PROTO, + NFTNL_OBJ_CT_TIMEOUT_DATA, +}; + enum { NFTNL_OBJ_LIMIT_RATE = NFTNL_OBJ_BASE, NFTNL_OBJ_LIMIT_UNIT, diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index 6dc00c6..382ca54 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -969,6 +969,7 @@ enum nft_osf_attributes { * @NFT_CT_DST_IP: conntrack layer 3 protocol destination (IPv4 address) * @NFT_CT_SRC_IP6: conntrack layer 3 protocol source (IPv6 address) * @NFT_CT_DST_IP6: conntrack layer 3 protocol destination (IPv6 address) + * @NFT_CT_TIMEOUT: connection tracking timeout policy assigned to conntrack */ enum nft_ct_keys { NFT_CT_STATE, @@ -994,6 +995,7 @@ enum nft_ct_keys { NFT_CT_DST_IP, NFT_CT_SRC_IP6, NFT_CT_DST_IP6, + NFT_CT_TIMEOUT, __NFT_CT_MAX }; #define NFT_CT_MAX (__NFT_CT_MAX - 1) @@ -1395,6 +1397,15 @@ enum nft_ct_helper_attributes { }; #define NFTA_CT_HELPER_MAX (__NFTA_CT_HELPER_MAX - 1) +enum nft_ct_timeout_attributes { + NFTA_CT_TIMEOUT_UNSPEC, + NFTA_CT_TIMEOUT_L3PROTO, + NFTA_CT_TIMEOUT_L4PROTO, + NFTA_CT_TIMEOUT_DATA, + __NFTA_CT_TIMEOUT_MAX, +}; +#define NFTA_CT_TIMEOUT_MAX (__NFTA_CT_TIMEOUT_MAX - 1) + #define NFT_OBJECT_UNSPEC 0 #define NFT_OBJECT_COUNTER 1 #define NFT_OBJECT_QUOTA 2 @@ -1402,7 +1413,8 @@ enum nft_ct_helper_attributes { #define NFT_OBJECT_LIMIT 4 #define NFT_OBJECT_CONNLIMIT 5 #define NFT_OBJECT_TUNNEL 6 -#define __NFT_OBJECT_MAX 7 +#define NFT_OBJECT_CT_TIMEOUT 7 +#define __NFT_OBJECT_MAX 8 #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) /** diff --git a/include/obj.h b/include/obj.h index 9363a69..837a54a 100644 --- a/include/obj.h +++ b/include/obj.h @@ -36,6 +36,11 @@ struct nftnl_obj { uint8_t l4proto; char name[16]; } ct_helper; + struct nftnl_obj_ct_timeout { + uint16_t l3proto; + uint8_t l4proto; + uint32_t *timeout; + } ct_timeout; struct nftnl_obj_limit { uint64_t rate; uint64_t unit; @@ -91,6 +96,7 @@ struct obj_ops { extern struct obj_ops obj_ops_counter; extern struct obj_ops obj_ops_quota; extern struct obj_ops obj_ops_ct_helper; +extern struct obj_ops obj_ops_ct_timeout; extern struct obj_ops obj_ops_limit; extern struct obj_ops obj_ops_tunnel; diff --git a/src/Makefile.am b/src/Makefile.am index 9a1a3c4..b5ec079 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -64,4 +64,5 @@ libnftnl_la_SOURCES = utils.c \ obj/quota.c \ obj/tunnel.c \ obj/limit.c \ + obj/ct_timeout.c \ libnftnl.map diff --git a/src/libnftnl.map b/src/libnftnl.map index 0d6b20c..18c2b7a 100644 --- a/src/libnftnl.map +++ b/src/libnftnl.map @@ -345,4 +345,5 @@ LIBNFTNL_7 { LIBNFTNL_8 { nftnl_rule_list_insert_at; + nftnl_obj_get; } LIBNFTNL_7; diff --git a/src/obj/ct_timeout.c b/src/obj/ct_timeout.c new file mode 100644 index 0000000..9701e99 --- /dev/null +++ b/src/obj/ct_timeout.c @@ -0,0 +1,369 @@ +/* + * (C) 2018 by Harsha Sharma + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include + +#include + +#include "internal.h" +#include +#include +#include + +#include "obj.h" + +static const char *const tcp_state_to_name[] = { + [NFTNL_CTTIMEOUT_TCP_SYN_SENT] = "SYN_SENT", + [NFTNL_CTTIMEOUT_TCP_SYN_RECV] = "SYN_RECV", + [NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = "ESTABLISHED", + [NFTNL_CTTIMEOUT_TCP_FIN_WAIT] = "FIN_WAIT", + [NFTNL_CTTIMEOUT_TCP_CLOSE_WAIT] = "CLOSE_WAIT", + [NFTNL_CTTIMEOUT_TCP_LAST_ACK] = "LAST_ACK", + [NFTNL_CTTIMEOUT_TCP_TIME_WAIT] = "TIME_WAIT", + [NFTNL_CTTIMEOUT_TCP_CLOSE] = "CLOSE", + [NFTNL_CTTIMEOUT_TCP_SYN_SENT2] = "SYN_SENT2", + [NFTNL_CTTIMEOUT_TCP_RETRANS] = "RETRANS", + [NFTNL_CTTIMEOUT_TCP_UNACK] = "UNACKNOWLEDGED", +}; + +static uint32_t tcp_dflt_timeout[] = { + [NFTNL_CTTIMEOUT_TCP_SYN_SENT] = 120, + [NFTNL_CTTIMEOUT_TCP_SYN_RECV] = 60, + [NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = 432000, + [NFTNL_CTTIMEOUT_TCP_FIN_WAIT] = 120, + [NFTNL_CTTIMEOUT_TCP_CLOSE_WAIT] = 60, + [NFTNL_CTTIMEOUT_TCP_LAST_ACK] = 30, + [NFTNL_CTTIMEOUT_TCP_TIME_WAIT] = 120, + [NFTNL_CTTIMEOUT_TCP_CLOSE] = 10, + [NFTNL_CTTIMEOUT_TCP_SYN_SENT2] = 120, + [NFTNL_CTTIMEOUT_TCP_RETRANS] = 300, + [NFTNL_CTTIMEOUT_TCP_UNACK] = 300, +}; + +static const char *const udp_state_to_name[] = { + [NFTNL_CTTIMEOUT_UDP_UNREPLIED] = "UNREPLIED", + [NFTNL_CTTIMEOUT_UDP_REPLIED] = "REPLIED", +}; + +static uint32_t udp_dflt_timeout[] = { + [NFTNL_CTTIMEOUT_UDP_UNREPLIED] = 30, + [NFTNL_CTTIMEOUT_UDP_REPLIED] = 180, +}; + +static struct { + uint32_t attr_max; + const char *const *state_to_name; + uint32_t *dflt_timeout; +} timeout_protocol[IPPROTO_MAX] = { + [IPPROTO_TCP] = { + .attr_max = NFTNL_CTTIMEOUT_TCP_MAX, + .state_to_name = tcp_state_to_name, + .dflt_timeout = tcp_dflt_timeout, + }, + [IPPROTO_UDP] = { + .attr_max = NFTNL_CTTIMEOUT_UDP_MAX, + .state_to_name = udp_state_to_name, + .dflt_timeout = udp_dflt_timeout, + }, +}; + +struct _container_policy_cb { + unsigned int nlattr_max; + void *tb; +}; + +static int +nftnl_timeout_policy_attr_set_u32(struct nftnl_obj *e, + uint32_t type, uint32_t data) +{ + struct nftnl_obj_ct_timeout *t = nftnl_obj_data(e); + size_t timeout_array_size; + + /* Layer 4 protocol needs to be already set. */ + if (!(e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L4PROTO))) + return -1; + if (t->timeout == NULL) { + /* if not supported, default to generic protocol tracker. */ + if (timeout_protocol[t->l4proto].attr_max != 0) { + timeout_array_size = sizeof(uint32_t) * + timeout_protocol[t->l4proto].attr_max; + } else { + timeout_array_size = sizeof(uint32_t) * + timeout_protocol[IPPROTO_RAW].attr_max; + } + t->timeout = calloc(1, timeout_array_size); + if (t->timeout == NULL) + return -1; + } + + /* this state does not exists in this protocol tracker.*/ + if (type > timeout_protocol[t->l4proto].attr_max) + return -1; + + t->timeout[type] = data; + + if (!(e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_DATA))) + e->flags |= (1 << NFTNL_OBJ_CT_TIMEOUT_DATA); + + return 0; +} + +static int +parse_timeout_attr_policy_cb(const struct nlattr *attr, void *data) +{ + struct _container_policy_cb *data_cb = data; + const struct nlattr **tb = data_cb->tb; + uint16_t type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, data_cb->nlattr_max) < 0) + return MNL_CB_OK; + + if (type <= data_cb->nlattr_max) { + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) + abi_breakage(); + tb[type] = attr; + } + return MNL_CB_OK; +} + +static void +timeout_parse_attr_data(struct nftnl_obj *e, + const struct nlattr *nest) +{ + struct nftnl_obj_ct_timeout *t = nftnl_obj_data(e); + unsigned int attr_max = timeout_protocol[t->l4proto].attr_max; + struct nlattr *tb[attr_max]; + struct _container_policy_cb cnt = { + .nlattr_max = attr_max, + .tb = tb, + }; + unsigned int i; + + memset(tb, 0, sizeof(struct nlattr *) * attr_max); + + mnl_attr_parse_nested(nest, parse_timeout_attr_policy_cb, &cnt); + + for (i = 1; i <= attr_max; i++) { + if (tb[i]) { + nftnl_timeout_policy_attr_set_u32(e, i-1, + ntohl(mnl_attr_get_u32(tb[i]))); + } + } +} + +static int nftnl_obj_ct_timeout_set(struct nftnl_obj *e, uint16_t type, + const void *data, uint32_t data_len) +{ + struct nftnl_obj_ct_timeout *timeout = nftnl_obj_data(e); + + switch (type) { + case NFTNL_OBJ_CT_TIMEOUT_L3PROTO: + timeout->l3proto = *((uint16_t *)data); + break; + case NFTNL_OBJ_CT_TIMEOUT_L4PROTO: + timeout->l4proto = *((uint8_t *)data); + break; + case NFTNL_OBJ_CT_TIMEOUT_DATA: + timeout->timeout = ((uint32_t *)data); + break; + default: + return -1; + } + return 0; +} + +static const void *nftnl_obj_ct_timeout_get(const struct nftnl_obj *e, + uint16_t type, uint32_t *data_len) +{ + struct nftnl_obj_ct_timeout *timeout = nftnl_obj_data(e); + + switch (type) { + case NFTNL_OBJ_CT_TIMEOUT_L3PROTO: + *data_len = sizeof(timeout->l3proto); + return &timeout->l3proto; + case NFTNL_OBJ_CT_TIMEOUT_L4PROTO: + *data_len = sizeof(timeout->l4proto); + return &timeout->l4proto; + case NFTNL_OBJ_CT_TIMEOUT_DATA: + *data_len = sizeof(timeout->timeout); + return timeout->timeout; + } + return NULL; +} + +static int nftnl_obj_ct_timeout_cb(const struct nlattr *attr, void *data) +{ + int type = mnl_attr_get_type(attr); + const struct nlattr **tb = data; + + if (mnl_attr_type_valid(attr, NFTA_CT_TIMEOUT_MAX) < 0) + return MNL_CB_OK; + + switch (type) { + case NFTA_CT_TIMEOUT_L3PROTO: + if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) + abi_breakage(); + break; + case NFTA_CT_TIMEOUT_L4PROTO: + if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) + abi_breakage(); + break; + case NFTA_CT_TIMEOUT_DATA: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) + abi_breakage(); + break; + } + + tb[type] = attr; + return MNL_CB_OK; +} + +static void +nftnl_obj_ct_timeout_build(struct nlmsghdr *nlh, const struct nftnl_obj *e) +{ + struct nftnl_obj_ct_timeout *timeout = nftnl_obj_data(e); + struct nlattr *nest; + + if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L3PROTO)) + mnl_attr_put_u16(nlh, NFTA_CT_TIMEOUT_L3PROTO, htons(timeout->l3proto)); + if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L4PROTO)) + mnl_attr_put_u8(nlh, NFTA_CT_TIMEOUT_L4PROTO, timeout->l4proto); + if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_DATA)) { + nest = mnl_attr_nest_start(nlh, NFTA_CT_TIMEOUT_DATA); + for (int i = 0; i < timeout_protocol[timeout->l4proto].attr_max; i++) { + if (timeout->timeout[i]) + mnl_attr_put_u32(nlh, i+1, htonl(timeout->timeout[i])); + } + mnl_attr_nest_end(nlh, nest); + } +} + +static int +nftnl_obj_ct_timeout_parse(struct nftnl_obj *e, struct nlattr *attr) +{ + struct nftnl_obj_ct_timeout *timeout = nftnl_obj_data(e); + struct nlattr *tb[NFTA_CT_TIMEOUT_MAX + 1] = {}; + + if (mnl_attr_parse_nested(attr, nftnl_obj_ct_timeout_cb, tb) < 0) + return -1; + + if (tb[NFTA_CT_TIMEOUT_L3PROTO]) { + timeout->l3proto = ntohs(mnl_attr_get_u16(tb[NFTA_CT_TIMEOUT_L3PROTO])); + e->flags |= (1 << NFTNL_OBJ_CT_TIMEOUT_L3PROTO); + } + if (tb[NFTA_CT_TIMEOUT_L4PROTO]) { + timeout->l4proto = mnl_attr_get_u8(tb[NFTA_CT_TIMEOUT_L4PROTO]); + e->flags |= (1 << NFTNL_OBJ_CT_TIMEOUT_L4PROTO); + } + if (tb[NFTA_CT_TIMEOUT_DATA]) { + timeout_parse_attr_data(e, tb[NFTA_CT_TIMEOUT_DATA]); + e->flags |= (1 << NFTNL_OBJ_CT_TIMEOUT_DATA); + } + return 0; +} + +static int nftnl_obj_ct_timeout_export(char *buf, size_t size, + const struct nftnl_obj *e, int type) +{ + struct nftnl_obj_ct_timeout *timeout = nftnl_obj_data(e); + + NFTNL_BUF_INIT(b, buf, size); + + if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L3PROTO)) + nftnl_buf_u32(&b, type, timeout->l3proto, FAMILY); + if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L4PROTO)) + nftnl_buf_u32(&b, type, timeout->l4proto, "service"); + + return nftnl_buf_done(&b); +} + +static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len, + const struct nftnl_obj *e) +{ + int ret = 0; + int offset = 0, remain = len; + + struct nftnl_obj_ct_timeout *timeout = nftnl_obj_data(e); + + if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L3PROTO)) { + ret = snprintf(buf + offset, len, "family %d ", + timeout->l3proto); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + } + if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L4PROTO)) { + ret = snprintf(buf + offset, len, "protocol %d ", + timeout->l4proto); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + } + if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_DATA)) { + uint8_t l4num = timeout->l4proto; + int i; + + /* default to generic protocol tracker. */ + if (timeout_protocol[timeout->l4proto].attr_max == 0) + l4num = IPPROTO_RAW; + + ret = snprintf(buf + offset, len, "policy = {"); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + for (i = 0; i < timeout_protocol[l4num].attr_max; i++) { + const char *state_name = + timeout_protocol[l4num].state_to_name[i][0] ? + timeout_protocol[l4num].state_to_name[i] : + "UNKNOWN"; + + if (timeout->timeout[i] != timeout_protocol[l4num].dflt_timeout[i]) { + ret = snprintf(buf + offset, len, + "%s = %u,", state_name, timeout->timeout[i]); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + } + } + + ret = snprintf(buf + offset, len, "}"); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + } + buf[offset] = '\0'; + + return ret; + +} + +static int nftnl_obj_ct_timeout_snprintf(char *buf, size_t len, uint32_t type, + uint32_t flags, + const struct nftnl_obj *e) +{ + if (len) + buf[0] = '\0'; + + switch (type) { + case NFTNL_OUTPUT_DEFAULT: + return nftnl_obj_ct_timeout_snprintf_default(buf, len, e); + case NFTNL_OUTPUT_JSON: + return nftnl_obj_ct_timeout_export(buf, len, e, type); + default: + break; + } + return -1; +} + +struct obj_ops obj_ops_ct_timeout = { + .name = "ct_timeout", + .type = NFT_OBJECT_CT_TIMEOUT, + .alloc_len = sizeof(struct nftnl_obj_ct_timeout), + .max_attr = NFTA_CT_TIMEOUT_MAX, + .set = nftnl_obj_ct_timeout_set, + .get = nftnl_obj_ct_timeout_get, + .parse = nftnl_obj_ct_timeout_parse, + .build = nftnl_obj_ct_timeout_build, + .snprintf = nftnl_obj_ct_timeout_snprintf, +}; diff --git a/src/object.c b/src/object.c index 803b056..931f685 100644 --- a/src/object.c +++ b/src/object.c @@ -31,6 +31,7 @@ static struct obj_ops *obj_ops[] = { [NFT_OBJECT_CT_HELPER] = &obj_ops_ct_helper, [NFT_OBJECT_LIMIT] = &obj_ops_limit, [NFT_OBJECT_TUNNEL] = &obj_ops_tunnel, + [NFT_OBJECT_CT_TIMEOUT] = &obj_ops_ct_timeout, }; static struct obj_ops *nftnl_obj_ops_lookup(uint32_t type) @@ -455,7 +456,8 @@ static int nftnl_obj_snprintf_dflt(char *buf, size_t size, obj); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } - ret = snprintf(buf + offset, offset, "]"); + + ret = snprintf(buf + strlen(buf), offset, "]"); SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; From patchwork Thu Aug 9 19:33:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsha Sharma X-Patchwork-Id: 955774 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="URd2DQjD"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41mdhj4g89z9s3Z for ; Fri, 10 Aug 2018 05:33:25 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727025AbeHIV7k (ORCPT ); Thu, 9 Aug 2018 17:59:40 -0400 Received: from mail-pf1-f195.google.com ([209.85.210.195]:41535 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726971AbeHIV7k (ORCPT ); Thu, 9 Aug 2018 17:59:40 -0400 Received: by mail-pf1-f195.google.com with SMTP id y10-v6so3310615pfn.8 for ; Thu, 09 Aug 2018 12:33:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=520bHG4mqOq9kRUZuAyFCMmW0OWw9ZGogpQAv4bvnmQ=; b=URd2DQjDYAB4XsFS03Xll2BspMY4qt5k5HOTcOWw+EOuqXNECC3N29cdWpb+UpjDyY bl57QDE/3WfJk8eoUH8XTUw1k0UQTJ0Ff6FRtRzyY79gdD25LaY6Adfwq33y+AkYGoDd YlWl7xTw/9cbWnFCfN1llYrRcN3clB14rgi2N2bNwSS+AsnjUQ6aniRzEn/0o3GB/Mcp KUbHKjVzQxY9Wj+RF0235eEsFEioQBu2DxGon0R3cINo/LgrkH9a2w38DmcX6twy7kYo gQoEQ6Q1KCib1jEp/WUAjQMOvwqbR98REXc7dKo0tjEgNTkCjWlccMkDxSuNUPsvBwmo eqSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=520bHG4mqOq9kRUZuAyFCMmW0OWw9ZGogpQAv4bvnmQ=; b=mSBmpFOHrCn7xrr/zP6IpLISyHHWVBZJhVHWcEJa2r72J/BsGR+zJEtNp7+mpx2XAy rqzhdWYE8wdeZORpjJ73iuEvrxR1kmJJJ5MiF/ALkxe5a/Q+gp1hKNex6xtCCdTv8evA rhhcY8NqSx8cstrfCh7ZhIjerrsmim4d3XnLsAazsTBrZFkx65dTo3JLZlyDqKsIWkFp zHD4yYgmxwFNHIWN6l+bWz/XKAjhyJ4qgWU1rS++V5Te8S2kut2cn/s1VOmysNZVaWCc gy5NNLzwWTqRcOEzmVlwRN/wOZyBypKN08hAT3Gc6qLKveYOcNzNunOgu6QegvfVjFcV eYHA== X-Gm-Message-State: AOUpUlFJsWs1aIv1rNM56rlH5nniTdlWmiz0w8CdeOHH+tfLL7xS99ZZ aRjUtx6RzvRVNi61T08qtyQ= X-Google-Smtp-Source: AA+uWPxx33iJ9cy7PjI/GAOGKZqKF0hIm8/lUBQU7EVf4C80vnb372hbRfsDQNYO8oSHYZcE2scTMQ== X-Received: by 2002:a62:c288:: with SMTP id w8-v6mr3709976pfk.92.1533843203270; Thu, 09 Aug 2018 12:33:23 -0700 (PDT) Received: from XDDDDD.iitr.ernet.in ([103.37.201.27]) by smtp.gmail.com with ESMTPSA id v17-v6sm9597298pfn.177.2018.08.09.12.33.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 Aug 2018 12:33:22 -0700 (PDT) From: Harsha Sharma To: harshasharmaiitr@gmail.com, pablo@netfilter.org Cc: netfilter-devel@vger.kernel.org Subject: [PATCH libnftnl v5 2/3] examples: add nft-ct-timeout-{add,del,get} Date: Fri, 10 Aug 2018 01:03:15 +0530 Message-Id: <20180809193315.13764-1-harshasharmaiitr@gmail.com> X-Mailer: git-send-email 2.14.1 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Add, list and delete ct timeout objects from specified table Usage e.g.: % ./nft-ct-timeout-add ip filter some-name tcp % ./nft-ct-timeout-get ip filter table filter name some-name use 0 [ ct_timeout family 2 protocol 6 policy = {ESTABLISHED = 111,CLOSE_WAIT = 14, CLOSE = 16}] % ./nft-ct-timeout-del ip filter some-name Signed-off-by: Harsha Sharma --- Changes in v5: - remove nftnl_timeout_policy_attr_set_u32 and use nftnl_obj_set Changes in v4: - No changes Changes in v3: - Change log message with update listing of timeout policies Changes in v2: - Updated timeout policy values examples/Makefile.am | 12 ++++ examples/nft-ct-timeout-add.c | 151 ++++++++++++++++++++++++++++++++++++++++++ examples/nft-ct-timeout-del.c | 124 ++++++++++++++++++++++++++++++++++ examples/nft-ct-timeout-get.c | 150 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 437 insertions(+) create mode 100644 examples/nft-ct-timeout-add.c create mode 100644 examples/nft-ct-timeout-del.c create mode 100644 examples/nft-ct-timeout-get.c diff --git a/examples/Makefile.am b/examples/Makefile.am index 3ec699b..d5584e5 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -25,6 +25,9 @@ check_PROGRAMS = nft-table-add \ nft-obj-add \ nft-obj-get \ nft-obj-del \ + nft-ct-timeout-add \ + nft-ct-timeout-get \ + nft-ct-timeout-del \ nft-flowtable-add \ nft-flowtable-del \ nft-flowtable-get \ @@ -111,6 +114,15 @@ nft_obj_del_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS} nft_obj_get_SOURCES = nft-obj-get.c nft_obj_get_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS} +nft_ct_timeout_add_SOURCES = nft-ct-timeout-add.c +nft_ct_timeout_add_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS} + +nft_ct_timeout_get_SOURCES = nft-ct-timeout-get.c +nft_ct_timeout_get_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS} + +nft_ct_timeout_del_SOURCES = nft-ct-timeout-del.c +nft_ct_timeout_del_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS} + nft_flowtable_add_SOURCES = nft-flowtable-add.c nft_flowtable_add_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS} diff --git a/examples/nft-ct-timeout-add.c b/examples/nft-ct-timeout-add.c new file mode 100644 index 0000000..6727913 --- /dev/null +++ b/examples/nft-ct-timeout-add.c @@ -0,0 +1,151 @@ +/* + * (C) 2012-2016 by Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +static struct nftnl_obj *obj_add_parse(int argc, char *argv[]) +{ + size_t timeout_array_size; + struct nftnl_obj *t; + uint32_t *timeout; + uint16_t family; + uint8_t l4proto; + + if (strcmp(argv[1], "ip") == 0) + family = NFPROTO_IPV4; + else if (strcmp(argv[1], "ip6") == 0) + family = NFPROTO_IPV6; + else if (strcmp(argv[1], "bridge") == 0) + family = NFPROTO_BRIDGE; + else if (strcmp(argv[1], "arp") == 0) + family = NFPROTO_ARP; + else { + fprintf(stderr, "Unknown family: ip, ip6, bridge, arp\n"); + return NULL; + } + + if (strcmp(argv[4], "udp") == 0) + l4proto = IPPROTO_UDP; + else if (strcmp(argv[4], "tcp") == 0) + l4proto = IPPROTO_TCP; + else { + fprintf(stderr, "Unknown layer 4 protocol\n"); + return NULL; + } + + t = nftnl_obj_alloc(); + if (t == NULL) { + perror("OOM"); + return NULL; + } + + timeout_array_size = sizeof(uint32_t) * (NFTNL_CTTIMEOUT_TCP_MAX); + timeout = calloc(1, timeout_array_size); + if (timeout == NULL) { + perror("OOM"); + return NULL; + } + + timeout[NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = 111; + timeout[NFTNL_CTTIMEOUT_TCP_CLOSE] = 16; + timeout[NFTNL_CTTIMEOUT_TCP_CLOSE_WAIT] = 14; + nftnl_obj_set_u32(t, NFTNL_OBJ_FAMILY, family); + nftnl_obj_set_u32(t, NFTNL_OBJ_TYPE, NFT_OBJECT_CT_TIMEOUT); + nftnl_obj_set_str(t, NFTNL_OBJ_TABLE, argv[2]); + nftnl_obj_set_str(t, NFTNL_OBJ_NAME, argv[3]); + nftnl_obj_set_u8(t, NFTNL_OBJ_CT_TIMEOUT_L4PROTO, l4proto); + nftnl_obj_set_u16(t, NFTNL_OBJ_CT_TIMEOUT_L3PROTO, NFPROTO_IPV4); + nftnl_obj_set(t, NFTNL_OBJ_CT_TIMEOUT_DATA, timeout); + return t; + +} + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + uint32_t portid, seq, obj_seq, family; + struct nftnl_obj *t; + struct mnl_nlmsg_batch *batch; + int ret; + + if (argc != 5) { + fprintf(stderr, "%s \n", argv[0]); + exit(EXIT_FAILURE); + } + + t = obj_add_parse(argc, argv); + if (t == NULL) { + exit(EXIT_FAILURE); + } + + seq = time(NULL); + batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); + + nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); + mnl_nlmsg_batch_next(batch); + + obj_seq = seq; + family = nftnl_obj_get_u32(t, NFTNL_OBJ_FAMILY); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWOBJ, family, NLM_F_ACK | NLM_F_CREATE, seq++); + nftnl_obj_nlmsg_build_payload(nlh, t); + nftnl_obj_free(t); + mnl_nlmsg_batch_next(batch); + + nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); + mnl_nlmsg_batch_next(batch); + + 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); + + if (mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch), + mnl_nlmsg_batch_size(batch)) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + mnl_nlmsg_batch_stop(batch); + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + while (ret > 0) { + ret = mnl_cb_run(buf, ret, obj_seq, portid, NULL, NULL); + if (ret <= 0) + break; + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + } + if (ret == -1) { + perror("error"); + exit(EXIT_FAILURE); + } + mnl_socket_close(nl); + + return EXIT_SUCCESS; +} diff --git a/examples/nft-ct-timeout-del.c b/examples/nft-ct-timeout-del.c new file mode 100644 index 0000000..4581c39 --- /dev/null +++ b/examples/nft-ct-timeout-del.c @@ -0,0 +1,124 @@ +/* + * (C) 2012 by Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software has been sponsored by Sophos Astaro + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +static struct nftnl_obj *ct_timeout_del_parse(int argc, char *argv[]) +{ + struct nftnl_obj *t; + uint16_t family; + + if (strcmp(argv[1], "ip") == 0) + family = NFPROTO_IPV4; + else if (strcmp(argv[1], "ip6") == 0) + family = NFPROTO_IPV6; + else if (strcmp(argv[1], "inet") == 0) + family = NFPROTO_INET; + else { + fprintf(stderr, "Unknown family: ip, ip6, inet\n"); + return NULL; + } + + t = nftnl_obj_alloc(); + if (t == NULL) { + perror("OOM"); + return NULL; + } + + nftnl_obj_set_str(t, NFTNL_OBJ_TABLE, argv[2]); + nftnl_obj_set_str(t, NFTNL_OBJ_NAME, argv[3]); + nftnl_obj_set_u32(t, NFTNL_OBJ_TYPE, NFT_OBJECT_CT_TIMEOUT); + nftnl_obj_set_u32(t, NFTNL_OBJ_FAMILY, family); + + return t; +} + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + uint32_t portid, seq, obj_seq, family; + struct nftnl_obj *t; + struct mnl_nlmsg_batch *batch; + int ret; + + if (argc != 4) { + fprintf(stderr, "%s
\n", argv[0]); + exit(EXIT_FAILURE); + } + + t = ct_timeout_del_parse(argc, argv); + if (t == NULL) + exit(EXIT_FAILURE); + + seq = time(NULL); + batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); + + nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); + mnl_nlmsg_batch_next(batch); + + obj_seq = seq; + family = nftnl_obj_get_u32(t, NFTNL_OBJ_FAMILY); + nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_DELOBJ, family, NLM_F_ACK, + seq++); + nftnl_obj_nlmsg_build_payload(nlh, t); + mnl_nlmsg_batch_next(batch); + nftnl_obj_free(t); + + nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); + mnl_nlmsg_batch_next(batch); + + 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); + + if (mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch), + mnl_nlmsg_batch_size(batch)) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + mnl_nlmsg_batch_stop(batch); + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + while (ret > 0) { + ret = mnl_cb_run(buf, ret, obj_seq, portid, NULL, NULL); + if (ret <= 0) + break; + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + } + if (ret == -1) { + perror("error"); + exit(EXIT_FAILURE); + } + mnl_socket_close(nl); + + return EXIT_SUCCESS; +} diff --git a/examples/nft-ct-timeout-get.c b/examples/nft-ct-timeout-get.c new file mode 100644 index 0000000..503c488 --- /dev/null +++ b/examples/nft-ct-timeout-get.c @@ -0,0 +1,150 @@ +/* + * (C) 2012 by Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software has been sponsored by Sophos Astaro + */ + + +#include +#include +#include +#include + +#include +#include + +#include +#include + +static int obj_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nftnl_obj *t; + char buf[4096]; + uint32_t *type = data; + + t = nftnl_obj_alloc(); + if (t == NULL) { + perror("OOM"); + goto err; + } + + if (nftnl_obj_nlmsg_parse(nlh, t) < 0) { + perror("nftnl_obj_nlmsg_parse"); + goto err_free; + } + + nftnl_obj_snprintf(buf, sizeof(buf), t, *type, 0); + printf("%s\n", buf); + +err_free: + nftnl_obj_free(t); +err: + return MNL_CB_OK; +} + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + uint32_t portid, seq, family; + struct nftnl_obj *t = NULL; + int ret; + uint32_t type = NFTNL_OUTPUT_DEFAULT; + + if (argc < 3 || argc > 5) { + fprintf(stderr, "%s
[] []\n", + argv[0]); + return EXIT_FAILURE; + } + + if (strcmp(argv[1], "ip") == 0) + family = NFPROTO_IPV4; + else if (strcmp(argv[1], "ip6") == 0) + family = NFPROTO_IPV6; + else if (strcmp(argv[1], "inet") == 0) + family = NFPROTO_INET; + else if (strcmp(argv[1], "unspec") == 0) + family = NFPROTO_UNSPEC; + else { + fprintf(stderr, "Unknown family: ip, ip6, inet, unspec"); + exit(EXIT_FAILURE); + } + + if (strcmp(argv[argc-1], "xml") == 0) { + type = NFTNL_OUTPUT_XML; + argv[argc-1] = NULL; + argc--; + } else if (strcmp(argv[argc-1], "json") == 0) { + type = NFTNL_OUTPUT_JSON; + argv[argc-1] = NULL; + argc--; + } else if (strcmp(argv[argc - 1], "default") == 0) { + argc--; + } + + if (argc == 3 || argc == 4) { + t = nftnl_obj_alloc(); + if (t == NULL) { + perror("OOM"); + exit(EXIT_FAILURE); + } + } + + seq = time(NULL); + nftnl_obj_set_u32(t, NFTNL_OBJ_TYPE, NFT_OBJECT_CT_TIMEOUT); + if (argc < 4) { + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETOBJ, family, + NLM_F_DUMP, seq); + if (argc == 3) { + nftnl_obj_set(t, NFTNL_OBJ_TABLE, argv[2]); + nftnl_obj_nlmsg_build_payload(nlh, t); + nftnl_obj_free(t); + } + } else { + nftnl_obj_set(t, NFTNL_OBJ_TABLE, argv[2]); + nftnl_obj_set(t, NFTNL_OBJ_NAME, argv[3]); + + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETOBJ, family, + NLM_F_ACK, seq); + nftnl_obj_nlmsg_build_payload(nlh, t); + nftnl_obj_free(t); + } + + 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); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + while (ret > 0) { + ret = mnl_cb_run(buf, ret, seq, portid, obj_cb, &type); + if (ret <= 0) + break; + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + } + if (ret == -1) { + perror("error"); + exit(EXIT_FAILURE); + } + mnl_socket_close(nl); + + return EXIT_SUCCESS; +} From patchwork Thu Aug 9 19:33:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsha Sharma X-Patchwork-Id: 955775 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="nT1PXSFG"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41mdjg02bMz9s3Z for ; Fri, 10 Aug 2018 05:34:15 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727194AbeHIWAa (ORCPT ); Thu, 9 Aug 2018 18:00:30 -0400 Received: from mail-pg1-f175.google.com ([209.85.215.175]:46529 "EHLO mail-pg1-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727048AbeHIWAa (ORCPT ); Thu, 9 Aug 2018 18:00:30 -0400 Received: by mail-pg1-f175.google.com with SMTP id f14-v6so3195992pgv.13 for ; Thu, 09 Aug 2018 12:34:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=LlrXJ1sSCQt2LS4Fk0u2hEYF5ZgpKEq3V/xsZ8eHz/I=; b=nT1PXSFGU5ipUn47TL0z2slRAExT6zQTjVok2maMkyZ9spoO2U1T7xZiT7Q6xsDIXZ UR+vkAFo+bjBSB2iUFNkF/W38EduTvekNRLipmSHKHYJ/LrjkDpeDP32qxmzitKSsukR MSLLjTAFzeW2Mavqt8pLqDktMATTq8DO//QzEbpS+skVTuieKa/hKH2Cz2uB72U+tXUJ S96qoncgmAdB10KtRdT46L0M/LYVF8SzLlPU4dndOtTp0vCiLIeGYMh58ZXHHs6E7xoi B5D5CKpTFSuPNlq1FUiY3hBx83UnjNTA885VCCTOOwip3D/EBGx1ADNnOAYOWQbC/ejl OJ3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=LlrXJ1sSCQt2LS4Fk0u2hEYF5ZgpKEq3V/xsZ8eHz/I=; b=MV+Y1UFMFrorxS+PCnm5PjFtfnxOP01zN6k1Ct74kGOVMvJLBhwS0THmq3T+K70kD1 602m2jO8QAFNgt4y581d6agyV/jAd4uUwJHsLC7kXBTiMCn35BaVl1v3m+n0NBUVGqdn MEqfHYoflRxptNBw5CZsxY2palSRuWM5dQaFZ/P2EEixVYmcdOSk0vDFugifgA0+bT1a V46Qdd0nFPh6fmlDJgqkQj2G8c24qeNpJbsR1SJ23hgAJ0nx5CDv8kpEZVz8smlRsLH+ rXy3z7B/oczzLpYUjNkXi7embby9mxkkeegbYT/rHYvDIzB7Y6cTbCR1IkkNL/j3VrSb bBGw== X-Gm-Message-State: AOUpUlEF6THFyHqGCEQ228/RyYiLsdf96GZvGrEABzcrzPGeLr2a+ten LKrG6uPofIDlrWQbvlnUTZc= X-Google-Smtp-Source: AA+uWPyjJ+cRVnpPloOmPRGvICJgQyLuYVHob+n07RqeS6PAGAH6BkmfNrbNnPTpsclx938NxxhbaQ== X-Received: by 2002:a63:ac57:: with SMTP id z23-v6mr817632pgn.74.1533843252396; Thu, 09 Aug 2018 12:34:12 -0700 (PDT) Received: from XDDDDD.iitr.ernet.in ([103.37.201.27]) by smtp.gmail.com with ESMTPSA id 9-v6sm22401094pfv.53.2018.08.09.12.34.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 Aug 2018 12:34:11 -0700 (PDT) From: Harsha Sharma To: harshasharmaiitr@gmail.com, pablo@netfilter.org Cc: netfilter-devel@vger.kernel.org Subject: [PATCH libnftnl v5 3/3] examples: Add test for assigning timeout objects via rule Date: Fri, 10 Aug 2018 01:03:58 +0530 Message-Id: <20180809193358.13845-1-harshasharmaiitr@gmail.com> X-Mailer: git-send-email 2.14.1 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Usage: ./nft-rule-ct-timeout-add ip filter input some-name ./nft-rule-get ip filter ip filter input 4 [ objref type 7 name some-name ] nft list ruleset ... chain input { ct timeout set "some-name" } Signed-off-by: Harsha Sharma --- Changes in v5: - No changes Changes in v4: - updated objref_imm_type Changes in v3: - No changes Changes in v2: - Add this in example examples/Makefile.am | 6 +- examples/nft-rule-ct-timeout-add.c | 154 +++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 examples/nft-rule-ct-timeout-add.c diff --git a/examples/Makefile.am b/examples/Makefile.am index d5584e5..67f0156 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -37,7 +37,8 @@ check_PROGRAMS = nft-table-add \ nft-ct-helper-add \ nft-ct-helper-get \ nft-ct-helper-del \ - nft-rule-ct-helper-add + nft-rule-ct-helper-add \ + nft-rule-ct-timeout-add nft_table_add_SOURCES = nft-table-add.c nft_table_add_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS} @@ -152,3 +153,6 @@ nft_ct_helper_del_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS} nft_rule_ct_helper_add_SOURCES = nft-rule-ct-helper-add.c nft_rule_ct_helper_add_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS} + +nft_rule_ct_timeout_add_SOURCES = nft-rule-ct-timeout-add.c +nft_rule_ct_timeout_add_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS} diff --git a/examples/nft-rule-ct-timeout-add.c b/examples/nft-rule-ct-timeout-add.c new file mode 100644 index 0000000..d779d9a --- /dev/null +++ b/examples/nft-rule-ct-timeout-add.c @@ -0,0 +1,154 @@ +/* + * (C) 2012 by Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software has been sponsored by Sophos Astaro + */ + +#include +#include +#include +#include /* for offsetof */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +static void add_ct_timeout(struct nftnl_rule *r, const char *obj_name) +{ + struct nftnl_expr *e; + + e = nftnl_expr_alloc("objref"); + if (e == NULL) { + perror("expr objref oom"); + exit(EXIT_FAILURE); + } + nftnl_expr_set_str(e, NFTNL_EXPR_OBJREF_IMM_NAME, obj_name); + nftnl_expr_set_u32(e, NFTNL_EXPR_OBJREF_IMM_TYPE, NFT_OBJECT_CT_TIMEOUT); + + nftnl_rule_add_expr(r, e); +} + +static struct nftnl_rule *setup_rule(uint8_t family, const char *table, + const char *chain, const char *handle, const char *obj_name) +{ + struct nftnl_rule *r = NULL; + uint64_t handle_num; + + r = nftnl_rule_alloc(); + if (r == NULL) { + perror("OOM"); + exit(EXIT_FAILURE); + } + + nftnl_rule_set(r, NFTNL_RULE_TABLE, table); + nftnl_rule_set(r, NFTNL_RULE_CHAIN, chain); + nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family); + + if (handle != NULL) { + handle_num = atoll(handle); + nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle_num); + } + + add_ct_timeout(r, obj_name); + + return r; +} + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + struct nftnl_rule *r; + struct nlmsghdr *nlh; + struct mnl_nlmsg_batch *batch; + uint8_t family; + char buf[MNL_SOCKET_BUFFER_SIZE]; + uint32_t seq = time(NULL); + int ret; + + if (argc < 5 || argc > 6) { + fprintf(stderr, "Usage: %s
\n", argv[0]); + exit(EXIT_FAILURE); + } + if (strcmp(argv[1], "ip") == 0) + family = NFPROTO_IPV4; + else if (strcmp(argv[1], "ip6") == 0) + family = NFPROTO_IPV6; + else { + fprintf(stderr, "Unknown family: ip, ip6\n"); + exit(EXIT_FAILURE); + } + + if (argc != 6) + r = setup_rule(family, argv[2], argv[3], NULL, argv[4]); + else + r = setup_rule(family, argv[2], argv[3], argv[4], argv[5]); + + 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); + } + + batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); + + nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); + mnl_nlmsg_batch_next(batch); + + nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), + NFT_MSG_NEWRULE, + nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY), + NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK, seq++); + + nftnl_rule_nlmsg_build_payload(nlh, r); + nftnl_rule_free(r); + mnl_nlmsg_batch_next(batch); + + nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); + mnl_nlmsg_batch_next(batch); + + ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch), + mnl_nlmsg_batch_size(batch)); + if (ret == -1) { + perror("mnl_socket_sendto"); + exit(EXIT_FAILURE); + } + + mnl_nlmsg_batch_stop(batch); + + 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, mnl_socket_get_portid(nl), NULL, NULL); + if (ret < 0) { + perror("mnl_cb_run"); + exit(EXIT_FAILURE); + } + + mnl_socket_close(nl); + + return EXIT_SUCCESS; +}