linux/net/netfilter/nf_conntrack_proto_udp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* (C) 1999-2001 Paul `Rusty' Russell
   3 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
   4 * (C) 2006-2012 Patrick McHardy <kaber@trash.net>
   5 */
   6
   7#include <linux/types.h>
   8#include <linux/timer.h>
   9#include <linux/module.h>
  10#include <linux/udp.h>
  11#include <linux/seq_file.h>
  12#include <linux/skbuff.h>
  13#include <linux/ipv6.h>
  14#include <net/ip6_checksum.h>
  15#include <net/checksum.h>
  16
  17#include <linux/netfilter.h>
  18#include <linux/netfilter_ipv4.h>
  19#include <linux/netfilter_ipv6.h>
  20#include <net/netfilter/nf_conntrack_l4proto.h>
  21#include <net/netfilter/nf_conntrack_ecache.h>
  22#include <net/netfilter/nf_conntrack_timeout.h>
  23#include <net/netfilter/nf_log.h>
  24#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
  25#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
  26
  27static const unsigned int udp_timeouts[UDP_CT_MAX] = {
  28        [UDP_CT_UNREPLIED]      = 30*HZ,
  29        [UDP_CT_REPLIED]        = 120*HZ,
  30};
  31
  32static unsigned int *udp_get_timeouts(struct net *net)
  33{
  34        return nf_udp_pernet(net)->timeouts;
  35}
  36
  37static void udp_error_log(const struct sk_buff *skb,
  38                          const struct nf_hook_state *state,
  39                          const char *msg)
  40{
  41        nf_l4proto_log_invalid(skb, state, IPPROTO_UDP, "%s", msg);
  42}
  43
  44static bool udp_error(struct sk_buff *skb,
  45                      unsigned int dataoff,
  46                      const struct nf_hook_state *state)
  47{
  48        unsigned int udplen = skb->len - dataoff;
  49        const struct udphdr *hdr;
  50        struct udphdr _hdr;
  51
  52        /* Header is too small? */
  53        hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
  54        if (!hdr) {
  55                udp_error_log(skb, state, "short packet");
  56                return true;
  57        }
  58
  59        /* Truncated/malformed packets */
  60        if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
  61                udp_error_log(skb, state, "truncated/malformed packet");
  62                return true;
  63        }
  64
  65        /* Packet with no checksum */
  66        if (!hdr->check)
  67                return false;
  68
  69        /* Checksum invalid? Ignore.
  70         * We skip checking packets on the outgoing path
  71         * because the checksum is assumed to be correct.
  72         * FIXME: Source route IP option packets --RR */
  73        if (state->hook == NF_INET_PRE_ROUTING &&
  74            state->net->ct.sysctl_checksum &&
  75            nf_checksum(skb, state->hook, dataoff, IPPROTO_UDP, state->pf)) {
  76                udp_error_log(skb, state, "bad checksum");
  77                return true;
  78        }
  79
  80        return false;
  81}
  82
  83/* Returns verdict for packet, and may modify conntracktype */
  84int nf_conntrack_udp_packet(struct nf_conn *ct,
  85                            struct sk_buff *skb,
  86                            unsigned int dataoff,
  87                            enum ip_conntrack_info ctinfo,
  88                            const struct nf_hook_state *state)
  89{
  90        unsigned int *timeouts;
  91
  92        if (udp_error(skb, dataoff, state))
  93                return -NF_ACCEPT;
  94
  95        timeouts = nf_ct_timeout_lookup(ct);
  96        if (!timeouts)
  97                timeouts = udp_get_timeouts(nf_ct_net(ct));
  98
  99        if (!nf_ct_is_confirmed(ct))
 100                ct->proto.udp.stream_ts = 2 * HZ + jiffies;
 101
 102        /* If we've seen traffic both ways, this is some kind of UDP
 103         * stream. Set Assured.
 104         */
 105        if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
 106                unsigned long extra = timeouts[UDP_CT_UNREPLIED];
 107
 108                /* Still active after two seconds? Extend timeout. */
 109                if (time_after(jiffies, ct->proto.udp.stream_ts))
 110                        extra = timeouts[UDP_CT_REPLIED];
 111
 112                nf_ct_refresh_acct(ct, ctinfo, skb, extra);
 113
 114                /* never set ASSURED for IPS_NAT_CLASH, they time out soon */
 115                if (unlikely((ct->status & IPS_NAT_CLASH)))
 116                        return NF_ACCEPT;
 117
 118                /* Also, more likely to be important, and not a probe */
 119                if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
 120                        nf_conntrack_event_cache(IPCT_ASSURED, ct);
 121        } else {
 122                nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[UDP_CT_UNREPLIED]);
 123        }
 124        return NF_ACCEPT;
 125}
 126
 127#ifdef CONFIG_NF_CT_PROTO_UDPLITE
 128static void udplite_error_log(const struct sk_buff *skb,
 129                              const struct nf_hook_state *state,
 130                              const char *msg)
 131{
 132        nf_l4proto_log_invalid(skb, state, IPPROTO_UDPLITE, "%s", msg);
 133}
 134
 135static bool udplite_error(struct sk_buff *skb,
 136                          unsigned int dataoff,
 137                          const struct nf_hook_state *state)
 138{
 139        unsigned int udplen = skb->len - dataoff;
 140        const struct udphdr *hdr;
 141        struct udphdr _hdr;
 142        unsigned int cscov;
 143
 144        /* Header is too small? */
 145        hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
 146        if (!hdr) {
 147                udplite_error_log(skb, state, "short packet");
 148                return true;
 149        }
 150
 151        cscov = ntohs(hdr->len);
 152        if (cscov == 0) {
 153                cscov = udplen;
 154        } else if (cscov < sizeof(*hdr) || cscov > udplen) {
 155                udplite_error_log(skb, state, "invalid checksum coverage");
 156                return true;
 157        }
 158
 159        /* UDPLITE mandates checksums */
 160        if (!hdr->check) {
 161                udplite_error_log(skb, state, "checksum missing");
 162                return true;
 163        }
 164
 165        /* Checksum invalid? Ignore. */
 166        if (state->hook == NF_INET_PRE_ROUTING &&
 167            state->net->ct.sysctl_checksum &&
 168            nf_checksum_partial(skb, state->hook, dataoff, cscov, IPPROTO_UDP,
 169                                state->pf)) {
 170                udplite_error_log(skb, state, "bad checksum");
 171                return true;
 172        }
 173
 174        return false;
 175}
 176
 177/* Returns verdict for packet, and may modify conntracktype */
 178int nf_conntrack_udplite_packet(struct nf_conn *ct,
 179                                struct sk_buff *skb,
 180                                unsigned int dataoff,
 181                                enum ip_conntrack_info ctinfo,
 182                                const struct nf_hook_state *state)
 183{
 184        unsigned int *timeouts;
 185
 186        if (udplite_error(skb, dataoff, state))
 187                return -NF_ACCEPT;
 188
 189        timeouts = nf_ct_timeout_lookup(ct);
 190        if (!timeouts)
 191                timeouts = udp_get_timeouts(nf_ct_net(ct));
 192
 193        /* If we've seen traffic both ways, this is some kind of UDP
 194           stream.  Extend timeout. */
 195        if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
 196                nf_ct_refresh_acct(ct, ctinfo, skb,
 197                                   timeouts[UDP_CT_REPLIED]);
 198
 199                if (unlikely((ct->status & IPS_NAT_CLASH)))
 200                        return NF_ACCEPT;
 201
 202                /* Also, more likely to be important, and not a probe */
 203                if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
 204                        nf_conntrack_event_cache(IPCT_ASSURED, ct);
 205        } else {
 206                nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[UDP_CT_UNREPLIED]);
 207        }
 208        return NF_ACCEPT;
 209}
 210#endif
 211
 212#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
 213
 214#include <linux/netfilter/nfnetlink.h>
 215#include <linux/netfilter/nfnetlink_cttimeout.h>
 216
 217static int udp_timeout_nlattr_to_obj(struct nlattr *tb[],
 218                                     struct net *net, void *data)
 219{
 220        unsigned int *timeouts = data;
 221        struct nf_udp_net *un = nf_udp_pernet(net);
 222
 223        if (!timeouts)
 224                timeouts = un->timeouts;
 225
 226        /* set default timeouts for UDP. */
 227        timeouts[UDP_CT_UNREPLIED] = un->timeouts[UDP_CT_UNREPLIED];
 228        timeouts[UDP_CT_REPLIED] = un->timeouts[UDP_CT_REPLIED];
 229
 230        if (tb[CTA_TIMEOUT_UDP_UNREPLIED]) {
 231                timeouts[UDP_CT_UNREPLIED] =
 232                        ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_UNREPLIED])) * HZ;
 233        }
 234        if (tb[CTA_TIMEOUT_UDP_REPLIED]) {
 235                timeouts[UDP_CT_REPLIED] =
 236                        ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_REPLIED])) * HZ;
 237        }
 238        return 0;
 239}
 240
 241static int
 242udp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
 243{
 244        const unsigned int *timeouts = data;
 245
 246        if (nla_put_be32(skb, CTA_TIMEOUT_UDP_UNREPLIED,
 247                         htonl(timeouts[UDP_CT_UNREPLIED] / HZ)) ||
 248            nla_put_be32(skb, CTA_TIMEOUT_UDP_REPLIED,
 249                         htonl(timeouts[UDP_CT_REPLIED] / HZ)))
 250                goto nla_put_failure;
 251        return 0;
 252
 253nla_put_failure:
 254        return -ENOSPC;
 255}
 256
 257static const struct nla_policy
 258udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = {
 259       [CTA_TIMEOUT_UDP_UNREPLIED]      = { .type = NLA_U32 },
 260       [CTA_TIMEOUT_UDP_REPLIED]        = { .type = NLA_U32 },
 261};
 262#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
 263
 264void nf_conntrack_udp_init_net(struct net *net)
 265{
 266        struct nf_udp_net *un = nf_udp_pernet(net);
 267        int i;
 268
 269        for (i = 0; i < UDP_CT_MAX; i++)
 270                un->timeouts[i] = udp_timeouts[i];
 271
 272#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
 273        un->offload_timeout = 30 * HZ;
 274#endif
 275}
 276
 277const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp =
 278{
 279        .l4proto                = IPPROTO_UDP,
 280        .allow_clash            = true,
 281#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 282        .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 283        .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 284        .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 285        .nla_policy             = nf_ct_port_nla_policy,
 286#endif
 287#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
 288        .ctnl_timeout           = {
 289                .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 290                .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 291                .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 292                .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 293                .nla_policy     = udp_timeout_nla_policy,
 294        },
 295#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
 296};
 297
 298#ifdef CONFIG_NF_CT_PROTO_UDPLITE
 299const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite =
 300{
 301        .l4proto                = IPPROTO_UDPLITE,
 302        .allow_clash            = true,
 303#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 304        .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 305        .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 306        .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 307        .nla_policy             = nf_ct_port_nla_policy,
 308#endif
 309#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
 310        .ctnl_timeout           = {
 311                .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 312                .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 313                .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 314                .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 315                .nla_policy     = udp_timeout_nla_policy,
 316        },
 317#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
 318};
 319#endif
 320