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