linux/net/netfilter/nf_conntrack_proto_generic.c
<<
>>
Prefs
   1/* (C) 1999-2001 Paul `Rusty' Russell
   2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 */
   8
   9#include <linux/types.h>
  10#include <linux/jiffies.h>
  11#include <linux/timer.h>
  12#include <linux/netfilter.h>
  13#include <net/netfilter/nf_conntrack_l4proto.h>
  14
  15static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
  16
  17static inline struct nf_generic_net *generic_pernet(struct net *net)
  18{
  19        return &net->ct.nf_ct_proto.generic;
  20}
  21
  22static bool generic_pkt_to_tuple(const struct sk_buff *skb,
  23                                 unsigned int dataoff,
  24                                 struct nf_conntrack_tuple *tuple)
  25{
  26        tuple->src.u.all = 0;
  27        tuple->dst.u.all = 0;
  28
  29        return true;
  30}
  31
  32static bool generic_invert_tuple(struct nf_conntrack_tuple *tuple,
  33                                 const struct nf_conntrack_tuple *orig)
  34{
  35        tuple->src.u.all = 0;
  36        tuple->dst.u.all = 0;
  37
  38        return true;
  39}
  40
  41/* Print out the per-protocol part of the tuple. */
  42static int generic_print_tuple(struct seq_file *s,
  43                               const struct nf_conntrack_tuple *tuple)
  44{
  45        return 0;
  46}
  47
  48static unsigned int *generic_get_timeouts(struct net *net)
  49{
  50        return &(generic_pernet(net)->timeout);
  51}
  52
  53/* Returns verdict for packet, or -1 for invalid. */
  54static int generic_packet(struct nf_conn *ct,
  55                          const struct sk_buff *skb,
  56                          unsigned int dataoff,
  57                          enum ip_conntrack_info ctinfo,
  58                          u_int8_t pf,
  59                          unsigned int hooknum,
  60                          unsigned int *timeout)
  61{
  62        nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
  63        return NF_ACCEPT;
  64}
  65
  66/* Called when a new connection for this protocol found. */
  67static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb,
  68                        unsigned int dataoff, unsigned int *timeouts)
  69{
  70        return true;
  71}
  72
  73#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
  74
  75#include <linux/netfilter/nfnetlink.h>
  76#include <linux/netfilter/nfnetlink_cttimeout.h>
  77
  78static int generic_timeout_nlattr_to_obj(struct nlattr *tb[],
  79                                         struct net *net, void *data)
  80{
  81        unsigned int *timeout = data;
  82        struct nf_generic_net *gn = generic_pernet(net);
  83
  84        if (tb[CTA_TIMEOUT_GENERIC_TIMEOUT])
  85                *timeout =
  86                    ntohl(nla_get_be32(tb[CTA_TIMEOUT_GENERIC_TIMEOUT])) * HZ;
  87        else {
  88                /* Set default generic timeout. */
  89                *timeout = gn->timeout;
  90        }
  91
  92        return 0;
  93}
  94
  95static int
  96generic_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
  97{
  98        const unsigned int *timeout = data;
  99
 100        if (nla_put_be32(skb, CTA_TIMEOUT_GENERIC_TIMEOUT, htonl(*timeout / HZ)))
 101                goto nla_put_failure;
 102
 103        return 0;
 104
 105nla_put_failure:
 106        return -ENOSPC;
 107}
 108
 109static const struct nla_policy
 110generic_timeout_nla_policy[CTA_TIMEOUT_GENERIC_MAX+1] = {
 111        [CTA_TIMEOUT_GENERIC_TIMEOUT]   = { .type = NLA_U32 },
 112};
 113#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 114
 115#ifdef CONFIG_SYSCTL
 116static struct ctl_table generic_sysctl_table[] = {
 117        {
 118                .procname       = "nf_conntrack_generic_timeout",
 119                .maxlen         = sizeof(unsigned int),
 120                .mode           = 0644,
 121                .proc_handler   = proc_dointvec_jiffies,
 122        },
 123        { }
 124};
 125#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
 126static struct ctl_table generic_compat_sysctl_table[] = {
 127        {
 128                .procname       = "ip_conntrack_generic_timeout",
 129                .maxlen         = sizeof(unsigned int),
 130                .mode           = 0644,
 131                .proc_handler   = proc_dointvec_jiffies,
 132        },
 133        { }
 134};
 135#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 136#endif /* CONFIG_SYSCTL */
 137
 138static int generic_kmemdup_sysctl_table(struct nf_proto_net *pn,
 139                                        struct nf_generic_net *gn)
 140{
 141#ifdef CONFIG_SYSCTL
 142        pn->ctl_table = kmemdup(generic_sysctl_table,
 143                                sizeof(generic_sysctl_table),
 144                                GFP_KERNEL);
 145        if (!pn->ctl_table)
 146                return -ENOMEM;
 147
 148        pn->ctl_table[0].data = &gn->timeout;
 149#endif
 150        return 0;
 151}
 152
 153static int generic_kmemdup_compat_sysctl_table(struct nf_proto_net *pn,
 154                                               struct nf_generic_net *gn)
 155{
 156#ifdef CONFIG_SYSCTL
 157#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
 158        pn->ctl_compat_table = kmemdup(generic_compat_sysctl_table,
 159                                       sizeof(generic_compat_sysctl_table),
 160                                       GFP_KERNEL);
 161        if (!pn->ctl_compat_table)
 162                return -ENOMEM;
 163
 164        pn->ctl_compat_table[0].data = &gn->timeout;
 165#endif
 166#endif
 167        return 0;
 168}
 169
 170static int generic_init_net(struct net *net, u_int16_t proto)
 171{
 172        int ret;
 173        struct nf_generic_net *gn = generic_pernet(net);
 174        struct nf_proto_net *pn = &gn->pn;
 175
 176        gn->timeout = nf_ct_generic_timeout;
 177
 178        ret = generic_kmemdup_compat_sysctl_table(pn, gn);
 179        if (ret < 0)
 180                return ret;
 181
 182        ret = generic_kmemdup_sysctl_table(pn, gn);
 183        if (ret < 0)
 184                nf_ct_kfree_compat_sysctl_table(pn);
 185
 186        return ret;
 187}
 188
 189static struct nf_proto_net *generic_get_net_proto(struct net *net)
 190{
 191        return &net->ct.nf_ct_proto.generic.pn;
 192}
 193
 194struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
 195{
 196        .l3proto                = PF_UNSPEC,
 197        .l4proto                = 255,
 198        .name                   = "unknown",
 199        .pkt_to_tuple           = generic_pkt_to_tuple,
 200        .invert_tuple           = generic_invert_tuple,
 201        .print_tuple            = generic_print_tuple,
 202        .packet                 = generic_packet,
 203        .get_timeouts           = generic_get_timeouts,
 204        .new                    = generic_new,
 205#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
 206        .ctnl_timeout           = {
 207                .nlattr_to_obj  = generic_timeout_nlattr_to_obj,
 208                .obj_to_nlattr  = generic_timeout_obj_to_nlattr,
 209                .nlattr_max     = CTA_TIMEOUT_GENERIC_MAX,
 210                .obj_size       = sizeof(unsigned int),
 211                .nla_policy     = generic_timeout_nla_policy,
 212        },
 213#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 214        .init_net               = generic_init_net,
 215        .get_net_proto          = generic_get_net_proto,
 216};
 217