144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/netfilter/ct.c Conntrack 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2007 Philip Craig <philipc@snapgear.com> 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2007 Secure Computing Corporation 12596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy * Copyright (c= 2008 Patrick McHardy <kaber@trash.net> 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup nfnl 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup ct Conntrack 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @brief 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <byteswap.h> 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <sys/types.h> 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/netfilter/nfnetlink_conntrack.h> 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/attr.h> 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netfilter/nfnl.h> 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netfilter/ct.h> 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf 3144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops nfnl_ct_ops; 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf#if __BYTE_ORDER == __BIG_ENDIAN 3444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic uint64_t ntohll(uint64_t x) 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf return x; 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf#elif __BYTE_ORDER == __LITTLE_ENDIAN 3944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic uint64_t ntohll(uint64_t x) 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf return __bswap_64(x); 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf 4544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy ct_policy[CTA_MAX+1] = { 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_TUPLE_ORIG] = { .type = NLA_NESTED }, 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_TUPLE_REPLY] = { .type = NLA_NESTED }, 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_STATUS] = { .type = NLA_U32 }, 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTOINFO] = { .type = NLA_NESTED }, 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf //[CTA_HELP] 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf //[CTA_NAT_SRC] 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_TIMEOUT] = { .type = NLA_U32 }, 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_MARK] = { .type = NLA_U32 }, 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_COUNTERS_ORIG] = { .type = NLA_NESTED }, 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_COUNTERS_REPLY] = { .type = NLA_NESTED }, 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_USE] = { .type = NLA_U32 }, 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_ID] = { .type = NLA_U32 }, 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf //[CTA_NAT_DST] 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf 6144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = { 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_TUPLE_IP] = { .type = NLA_NESTED }, 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_TUPLE_PROTO] = { .type = NLA_NESTED }, 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf 6644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = { 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_IP_V4_SRC] = { .type = NLA_U32 }, 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_IP_V4_DST] = { .type = NLA_U32 }, 6944d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_IP_V6_SRC] = { .minlen = 16 }, 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_IP_V6_DST] = { .minlen = 16 }, 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf 7344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = { 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTO_NUM] = { .type = NLA_U8 }, 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 }, 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTO_DST_PORT] = { .type = NLA_U16 }, 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 }, 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 }, 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 }, 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 }, 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTO_ICMPV6_TYPE] = { .type = NLA_U8 }, 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 }, 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 8444d362409d5469aed47d19e7908d19bd194493aThomas Graf 8544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = { 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED }, 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf 8944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = { 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 }, 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 }, 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf 9844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = { 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_COUNTERS_PACKETS] = { .type = NLA_U64 }, 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_COUNTERS_BYTES] = { .type = NLA_U64 }, 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 }, 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf [CTA_COUNTERS32_BYTES] = { .type = NLA_U32 }, 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf 10544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr) 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[CTA_IP_MAX+1]; 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_addr *addr; 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy); 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_IP_V4_SRC]) { 116eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET); 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr == NULL) 118eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout_enomem; 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nfnl_ct_set_src(ct, repl, addr); 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(addr); 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_IP_V4_DST]) { 125eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET); 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr == NULL) 127eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout_enomem; 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nfnl_ct_set_dst(ct, repl, addr); 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(addr); 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 13144d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_IP_V6_SRC]) { 134eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6); 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr == NULL) 136eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout_enomem; 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nfnl_ct_set_src(ct, repl, addr); 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(addr); 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_IP_V6_DST]) { 143eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6); 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (addr == NULL) 145eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf goto errout_enomem; 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nfnl_ct_set_dst(ct, repl, addr); 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_addr_put(addr); 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 14944d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 15044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf 154eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graferrout_enomem: 1558a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOMEM; 15644d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf 16044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr) 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[CTA_PROTO_MAX+1]; 16344d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 16444d362409d5469aed47d19e7908d19bd194493aThomas Graf 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy); 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 16744d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf 16944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!repl && tb[CTA_PROTO_NUM]) 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM])); 17144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_PROTO_SRC_PORT]) 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_src_port(ct, repl, 173337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT]))); 17444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_PROTO_DST_PORT]) 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_dst_port(ct, repl, 176337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT]))); 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_PROTO_ICMP_ID]) 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_icmp_id(ct, repl, 179337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID]))); 18044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_PROTO_ICMP_TYPE]) 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_icmp_type(ct, repl, 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_get_u8(tb[CTA_PROTO_ICMP_TYPE])); 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_PROTO_ICMP_CODE]) 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_icmp_code(ct, repl, 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_get_u8(tb[CTA_PROTO_ICMP_CODE])); 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf 19044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr) 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[CTA_TUPLE_MAX+1]; 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy); 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf 19944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_TUPLE_IP]) { 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]); 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_TUPLE_PROTO]) { 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]); 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 21244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf 21444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr) 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1]; 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr, 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf ct_protoinfo_tcp_policy); 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_PROTOINFO_TCP_STATE]) 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_tcp_state(ct, 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE])); 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf 23144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr) 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[CTA_PROTOINFO_MAX+1]; 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf ct_protoinfo_policy); 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_PROTOINFO_TCP]) { 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]); 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 24644d362409d5469aed47d19e7908d19bd194493aThomas Graf 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf 25044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr) 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[CTA_COUNTERS_MAX+1]; 25344d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy); 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_COUNTERS_PACKETS]) 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_packets(ct, repl, 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS]))); 26244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_COUNTERS32_PACKETS]) 26344d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_packets(ct, repl, 26444d362409d5469aed47d19e7908d19bd194493aThomas Graf ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS]))); 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_COUNTERS_BYTES]) 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_bytes(ct, repl, 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES]))); 26844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_COUNTERS32_BYTES]) 26944d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_bytes(ct, repl, 27044d362409d5469aed47d19e7908d19bd194493aThomas Graf ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES]))); 27144d362409d5469aed47d19e7908d19bd194493aThomas Graf 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 27344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 27444d362409d5469aed47d19e7908d19bd194493aThomas Graf 27544d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnlmsg_ct_group(struct nlmsghdr *nlh) 27644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 27744d362409d5469aed47d19e7908d19bd194493aThomas Graf switch (nfnlmsg_subtype(nlh)) { 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf case IPCTNL_MSG_CT_NEW: 27944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL)) 28044d362409d5469aed47d19e7908d19bd194493aThomas Graf return NFNLGRP_CONNTRACK_NEW; 28144d362409d5469aed47d19e7908d19bd194493aThomas Graf else 28244d362409d5469aed47d19e7908d19bd194493aThomas Graf return NFNLGRP_CONNTRACK_UPDATE; 28344d362409d5469aed47d19e7908d19bd194493aThomas Graf case IPCTNL_MSG_CT_DELETE: 28444d362409d5469aed47d19e7908d19bd194493aThomas Graf return NFNLGRP_CONNTRACK_DESTROY; 28544d362409d5469aed47d19e7908d19bd194493aThomas Graf default: 28644d362409d5469aed47d19e7908d19bd194493aThomas Graf return NFNLGRP_NONE; 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 28844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 28944d362409d5469aed47d19e7908d19bd194493aThomas Graf 2908a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result) 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 29244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nfnl_ct *ct; 29344d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[CTA_MAX+1]; 29444d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 29544d362409d5469aed47d19e7908d19bd194493aThomas Graf 29644d362409d5469aed47d19e7908d19bd194493aThomas Graf ct = nfnl_ct_alloc(); 29744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!ct) 2988a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 29944d362409d5469aed47d19e7908d19bd194493aThomas Graf 30044d362409d5469aed47d19e7908d19bd194493aThomas Graf ct->ce_msgtype = nlh->nlmsg_type; 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf 30244d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX, 30344d362409d5469aed47d19e7908d19bd194493aThomas Graf ct_policy); 30444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 30544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 30644d362409d5469aed47d19e7908d19bd194493aThomas Graf 30744d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_family(ct, nfnlmsg_family(nlh)); 30844d362409d5469aed47d19e7908d19bd194493aThomas Graf 30944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_TUPLE_ORIG]) { 31044d362409d5469aed47d19e7908d19bd194493aThomas Graf err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]); 31144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 31244d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 31344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 31444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_TUPLE_REPLY]) { 31544d362409d5469aed47d19e7908d19bd194493aThomas Graf err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]); 31644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 31744d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 31844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 31944d362409d5469aed47d19e7908d19bd194493aThomas Graf 32044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_PROTOINFO]) { 32144d362409d5469aed47d19e7908d19bd194493aThomas Graf err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]); 32244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 32344d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 32444d362409d5469aed47d19e7908d19bd194493aThomas Graf } 32544d362409d5469aed47d19e7908d19bd194493aThomas Graf 32644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_STATUS]) 32744d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS]))); 32844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_TIMEOUT]) 32944d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT]))); 33044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_MARK]) 33144d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK]))); 33244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_USE]) 33344d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE]))); 33444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_ID]) 33544d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID]))); 33644d362409d5469aed47d19e7908d19bd194493aThomas Graf 33744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_COUNTERS_ORIG]) { 33844d362409d5469aed47d19e7908d19bd194493aThomas Graf err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]); 33944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 34044d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 34144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 34244d362409d5469aed47d19e7908d19bd194493aThomas Graf 34344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[CTA_COUNTERS_REPLY]) { 34444d362409d5469aed47d19e7908d19bd194493aThomas Graf err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]); 34544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 34644d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 34744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 34844d362409d5469aed47d19e7908d19bd194493aThomas Graf 3498a3efffa5b3fde252675239914118664d36a2c24Thomas Graf *result = ct; 3508a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return 0; 35144d362409d5469aed47d19e7908d19bd194493aThomas Graf 35244d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 35344d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_put(ct); 3548a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 35644d362409d5469aed47d19e7908d19bd194493aThomas Graf 35744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 3583040a1d6254465bed9e44e4d1bf279c2c50cd16aThomas Graf struct nlmsghdr *nlh, struct nl_parser_param *pp) 35944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 36044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nfnl_ct *ct; 36144d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 36244d362409d5469aed47d19e7908d19bd194493aThomas Graf 3638a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0) 3648a3efffa5b3fde252675239914118664d36a2c24Thomas Graf goto errout; 36544d362409d5469aed47d19e7908d19bd194493aThomas Graf 36644d362409d5469aed47d19e7908d19bd194493aThomas Graf err = pp->pp_cb((struct nl_object *) ct, pp); 36744d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 36844d362409d5469aed47d19e7908d19bd194493aThomas Graf nfnl_ct_put(ct); 36944d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 37044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 37144d362409d5469aed47d19e7908d19bd194493aThomas Graf 3721155370f520cb64657e25153255cf7dc1424317fThomas Grafint nfnl_ct_dump_request(struct nl_sock *sk) 37344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 3741155370f520cb64657e25153255cf7dc1424317fThomas Graf return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET, 37544d362409d5469aed47d19e7908d19bd194493aThomas Graf NLM_F_DUMP, AF_UNSPEC, 0); 37644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 37744d362409d5469aed47d19e7908d19bd194493aThomas Graf 3781155370f520cb64657e25153255cf7dc1424317fThomas Grafstatic int ct_request_update(struct nl_cache *cache, struct nl_sock *sk) 37944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 3801155370f520cb64657e25153255cf7dc1424317fThomas Graf return nfnl_ct_dump_request(sk); 38144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 38244d362409d5469aed47d19e7908d19bd194493aThomas Graf 383596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardystatic int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct, 384596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy int repl) 385596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy{ 386596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy struct nlattr *tuple, *ip, *proto; 387596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy struct nl_addr *addr; 388596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy int family; 389596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 390596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy family = nfnl_ct_get_family(ct); 391596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 392596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG); 393596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (!tuple) 394596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy goto nla_put_failure; 395596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 396596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy ip = nla_nest_start(msg, CTA_TUPLE_IP); 397596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (!ip) 398596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy goto nla_put_failure; 399596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 400596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy addr = nfnl_ct_get_src(ct, repl); 401596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (addr) 402596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy NLA_PUT_ADDR(msg, 403596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC, 404596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy addr); 405596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 406596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy addr = nfnl_ct_get_dst(ct, repl); 407596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (addr) 408596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy NLA_PUT_ADDR(msg, 409596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST, 410596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy addr); 411596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 412596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy nla_nest_end(msg, ip); 413596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 414596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy proto = nla_nest_start(msg, CTA_TUPLE_PROTO); 415596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (!proto) 416596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy goto nla_put_failure; 417596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 418596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (nfnl_ct_test_proto(ct)) 419596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct)); 420596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 421596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (nfnl_ct_test_src_port(ct, repl)) 422596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT, 423337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf htons(nfnl_ct_get_src_port(ct, repl))); 424596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 425596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (nfnl_ct_test_dst_port(ct, repl)) 426596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy NLA_PUT_U16(msg, CTA_PROTO_DST_PORT, 427337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf htons(nfnl_ct_get_dst_port(ct, repl))); 428596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 429596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (nfnl_ct_test_icmp_id(ct, repl)) 430596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID, 431337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf htons(nfnl_ct_get_icmp_id(ct, repl))); 432596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 433596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (nfnl_ct_test_icmp_type(ct, repl)) 434596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE, 435596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy nfnl_ct_get_icmp_type(ct, repl)); 436596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 437596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (nfnl_ct_test_icmp_code(ct, repl)) 438596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE, 439596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy nfnl_ct_get_icmp_code(ct, repl)); 440596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 441596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy nla_nest_end(msg, proto); 442596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 443596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy nla_nest_end(msg, tuple); 444596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy return 0; 445596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 446596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardynla_put_failure: 4478a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MSGSIZE; 448596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy} 449596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 4508a3efffa5b3fde252675239914118664d36a2c24Thomas Grafstatic int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags, 4518a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 452596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy{ 453596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy struct nl_msg *msg; 4548a3efffa5b3fde252675239914118664d36a2c24Thomas Graf int err; 455596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 456596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags, 457596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy nfnl_ct_get_family(ct), 0); 458596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (msg == NULL) 4598a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 460596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 4618a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0) 462596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy goto err_out; 463596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 4648a3efffa5b3fde252675239914118664d36a2c24Thomas Graf *result = msg; 4658a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return 0; 466596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 467596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardyerr_out: 468596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy nlmsg_free(msg); 4698a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 470596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy} 471596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 4728a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags, 4738a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 474596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy{ 4758a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result); 476596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy} 477596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 4781155370f520cb64657e25153255cf7dc1424317fThomas Grafint nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) 479596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy{ 480596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy struct nl_msg *msg; 481596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy int err; 482596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 4838a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0) 4848a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 485596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 4861155370f520cb64657e25153255cf7dc1424317fThomas Graf err = nl_send_auto_complete(sk, msg); 487596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy nlmsg_free(msg); 488596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (err < 0) 489596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy return err; 490596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 491cfcfca070355b246028df60da79813f09ed65755Thomas Graf return wait_for_ack(sk); 492596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy} 493596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 4948a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags, 4958a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 496596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy{ 4978a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result); 498596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy} 499596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 5001155370f520cb64657e25153255cf7dc1424317fThomas Grafint nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) 501596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy{ 502596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy struct nl_msg *msg; 503596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy int err; 504596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 5058a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0) 5068a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 507596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 5081155370f520cb64657e25153255cf7dc1424317fThomas Graf err = nl_send_auto_complete(sk, msg); 509596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy nlmsg_free(msg); 510596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (err < 0) 511596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy return err; 512596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 513cfcfca070355b246028df60da79813f09ed65755Thomas Graf return wait_for_ack(sk); 514596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy} 515596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 5168a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags, 5178a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 518596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy{ 5198a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result); 520596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy} 521596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 5221155370f520cb64657e25153255cf7dc1424317fThomas Grafint nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) 523596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy{ 524596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy struct nl_msg *msg; 525596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy int err; 526596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 5278a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0) 5288a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 529596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 5301155370f520cb64657e25153255cf7dc1424317fThomas Graf err = nl_send_auto_complete(sk, msg); 531596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy nlmsg_free(msg); 532596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy if (err < 0) 533596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy return err; 534596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 535cfcfca070355b246028df60da79813f09ed65755Thomas Graf return wait_for_ack(sk); 536596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy} 537596d3bc2e9a55d36667abc9b1339b875abd4e11aPatrick McHardy 53844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 53944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Cache Management 54044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 54144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 54244d362409d5469aed47d19e7908d19bd194493aThomas Graf 54344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 54444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build a conntrack cache holding all conntrack currently in the kernel 5451155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 5468a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg result Pointer to store resulting cache. 54744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 54844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocates a new cache, initializes it properly and updates it to 54944d362409d5469aed47d19e7908d19bd194493aThomas Graf * contain all conntracks currently in the kernel. 55044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 5518a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @return 0 on success or a negative error code. 55244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 5531155370f520cb64657e25153255cf7dc1424317fThomas Grafint nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result) 55444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 5551155370f520cb64657e25153255cf7dc1424317fThomas Graf return nl_cache_alloc_and_fill(&nfnl_ct_ops, sk, result); 55644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 55744d362409d5469aed47d19e7908d19bd194493aThomas Graf 55844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 55944d362409d5469aed47d19e7908d19bd194493aThomas Graf 56044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 56144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Conntrack Addition 56244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 56344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 56444d362409d5469aed47d19e7908d19bd194493aThomas Graf 56544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 56644d362409d5469aed47d19e7908d19bd194493aThomas Graf 56744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_af_group ct_groups[] = { 56844d362409d5469aed47d19e7908d19bd194493aThomas Graf { AF_UNSPEC, NFNLGRP_CONNTRACK_NEW }, 56944d362409d5469aed47d19e7908d19bd194493aThomas Graf { AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE }, 57044d362409d5469aed47d19e7908d19bd194493aThomas Graf { AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY }, 57144d362409d5469aed47d19e7908d19bd194493aThomas Graf { END_OF_GROUP_LIST }, 57244d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 57344d362409d5469aed47d19e7908d19bd194493aThomas Graf 57444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type)) 57544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops nfnl_ct_ops = { 57644d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_name = "netfilter/ct", 57744d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_hdrsize = NFNL_HDRLEN, 57844d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msgtypes = { 57944d362409d5469aed47d19e7908d19bd194493aThomas Graf { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" }, 58044d362409d5469aed47d19e7908d19bd194493aThomas Graf { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" }, 58144d362409d5469aed47d19e7908d19bd194493aThomas Graf { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" }, 58244d362409d5469aed47d19e7908d19bd194493aThomas Graf END_OF_MSGTYPES_LIST, 58344d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 58444d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_protocol = NETLINK_NETFILTER, 58544d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_groups = ct_groups, 58644d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_request_update = ct_request_update, 58744d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msg_parser = ct_msg_parser, 58844d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_obj_ops = &ct_obj_ops, 58944d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 59044d362409d5469aed47d19e7908d19bd194493aThomas Graf 59144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init ct_init(void) 59244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 59344d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_mngt_register(&nfnl_ct_ops); 59444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 59544d362409d5469aed47d19e7908d19bd194493aThomas Graf 59644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __exit ct_exit(void) 59744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 59844d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_mngt_unregister(&nfnl_ct_ops); 59944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 60044d362409d5469aed47d19e7908d19bd194493aThomas Graf 60144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 602