linux/net/netfilter/nf_conntrack_proto_udp.c
<<
>>
Prefs
   1/* (C) 1999-2001 Paul `Rusty' Russell
   2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
   3 * (C) 2006-2012 Patrick McHardy <kaber@trash.net>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 */
   9
  10#include <linux/types.h>
  11#include <linux/timer.h>
  12#include <linux/module.h>
  13#include <linux/udp.h>
  14#include <linux/seq_file.h>
  15#include <linux/skbuff.h>
  16#include <linux/ipv6.h>
  17#include <net/ip6_checksum.h>
  18#include <net/checksum.h>
  19
  20#include <linux/netfilter.h>
  21#include <linux/netfilter_ipv4.h>
  22#include <linux/netfilter_ipv6.h>
  23#include <net/netfilter/nf_conntrack_l4proto.h>
  24#include <net/netfilter/nf_conntrack_ecache.h>
  25#include <net/netfilter/nf_log.h>
  26#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
  27#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
  28
  29static unsigned int udp_timeouts[UDP_CT_MAX] = {
  30        [UDP_CT_UNREPLIED]      = 30*HZ,
  31        [UDP_CT_REPLIED]        = 180*HZ,
  32};
  33
  34static inline struct nf_udp_net *udp_pernet(struct net *net)
  35{
  36        return &net->ct.nf_ct_proto.udp;
  37}
  38
  39static bool udp_pkt_to_tuple(const struct sk_buff *skb,
  40                             unsigned int dataoff,
  41                             struct nf_conntrack_tuple *tuple)
  42{
  43        const struct udphdr *hp;
  44        struct udphdr _hdr;
  45
  46        /* Actually only need first 8 bytes. */
  47        hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
  48        if (hp == NULL)
  49                return false;
  50
  51        tuple->src.u.udp.port = hp->source;
  52        tuple->dst.u.udp.port = hp->dest;
  53
  54        return true;
  55}
  56
  57static bool udp_invert_tuple(struct nf_conntrack_tuple *tuple,
  58                             const struct nf_conntrack_tuple *orig)
  59{
  60        tuple->src.u.udp.port = orig->dst.u.udp.port;
  61        tuple->dst.u.udp.port = orig->src.u.udp.port;
  62        return true;
  63}
  64
  65/* Print out the per-protocol part of the tuple. */
  66static int udp_print_tuple(struct seq_file *s,
  67                           const struct nf_conntrack_tuple *tuple)
  68{
  69        return seq_printf(s, "sport=%hu dport=%hu ",
  70                          ntohs(tuple->src.u.udp.port),
  71                          ntohs(tuple->dst.u.udp.port));
  72}
  73
  74static unsigned int *udp_get_timeouts(struct net *net)
  75{
  76        return udp_pernet(net)->timeouts;
  77}
  78
  79/* Returns verdict for packet, and may modify conntracktype */
  80static int udp_packet(struct nf_conn *ct,
  81                      const struct sk_buff *skb,
  82                      unsigned int dataoff,
  83                      enum ip_conntrack_info ctinfo,
  84                      u_int8_t pf,
  85                      unsigned int hooknum,
  86                      unsigned int *timeouts)
  87{
  88        /* If we've seen traffic both ways, this is some kind of UDP
  89           stream.  Extend timeout. */
  90        if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
  91                nf_ct_refresh_acct(ct, ctinfo, skb,
  92                                   timeouts[UDP_CT_REPLIED]);
  93                /* Also, more likely to be important, and not a probe */
  94                if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
  95                        nf_conntrack_event_cache(IPCT_ASSURED, ct);
  96        } else {
  97                nf_ct_refresh_acct(ct, ctinfo, skb,
  98                                   timeouts[UDP_CT_UNREPLIED]);
  99        }
 100        return NF_ACCEPT;
 101}
 102
 103/* Called when a new connection for this protocol found. */
 104static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
 105                    unsigned int dataoff, unsigned int *timeouts)
 106{
 107        return true;
 108}
 109
 110#ifdef CONFIG_NF_CT_PROTO_UDPLITE
 111static int udplite_error(struct net *net, struct nf_conn *tmpl,
 112                         struct sk_buff *skb,
 113                         unsigned int dataoff,
 114                         u8 pf, unsigned int hooknum)
 115{
 116        unsigned int udplen = skb->len - dataoff;
 117        const struct udphdr *hdr;
 118        struct udphdr _hdr;
 119        unsigned int cscov;
 120
 121        /* Header is too small? */
 122        hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
 123        if (!hdr) {
 124                if (LOG_INVALID(net, IPPROTO_UDPLITE))
 125                        nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 126                                      "nf_ct_udplite: short packet ");
 127                return -NF_ACCEPT;
 128        }
 129
 130        cscov = ntohs(hdr->len);
 131        if (cscov == 0) {
 132                cscov = udplen;
 133        } else if (cscov < sizeof(*hdr) || cscov > udplen) {
 134                if (LOG_INVALID(net, IPPROTO_UDPLITE))
 135                        nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 136                                      "nf_ct_udplite: invalid checksum coverage ");
 137                return -NF_ACCEPT;
 138        }
 139
 140        /* UDPLITE mandates checksums */
 141        if (!hdr->check) {
 142                if (LOG_INVALID(net, IPPROTO_UDPLITE))
 143                        nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 144                                      "nf_ct_udplite: checksum missing ");
 145                return -NF_ACCEPT;
 146        }
 147
 148        /* Checksum invalid? Ignore. */
 149        if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 150            nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
 151                                pf)) {
 152                if (LOG_INVALID(net, IPPROTO_UDPLITE))
 153                        nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 154                                      "nf_ct_udplite: bad UDPLite checksum ");
 155                return -NF_ACCEPT;
 156        }
 157
 158        return NF_ACCEPT;
 159}
 160#endif
 161
 162static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
 163                     unsigned int dataoff,
 164                     u_int8_t pf,
 165                     unsigned int hooknum)
 166{
 167        unsigned int udplen = skb->len - dataoff;
 168        const struct udphdr *hdr;
 169        struct udphdr _hdr;
 170
 171        /* Header is too small? */
 172        hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
 173        if (hdr == NULL) {
 174                if (LOG_INVALID(net, IPPROTO_UDP))
 175                        nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 176                                      "nf_ct_udp: short packet ");
 177                return -NF_ACCEPT;
 178        }
 179
 180        /* Truncated/malformed packets */
 181        if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
 182                if (LOG_INVALID(net, IPPROTO_UDP))
 183                        nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 184                                "nf_ct_udp: truncated/malformed packet ");
 185                return -NF_ACCEPT;
 186        }
 187
 188        /* Packet with no checksum */
 189        if (!hdr->check)
 190                return NF_ACCEPT;
 191
 192        /* Checksum invalid? Ignore.
 193         * We skip checking packets on the outgoing path
 194         * because the checksum is assumed to be correct.
 195         * FIXME: Source route IP option packets --RR */
 196        if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 197            nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
 198                if (LOG_INVALID(net, IPPROTO_UDP))
 199                        nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
 200                                "nf_ct_udp: bad UDP checksum ");
 201                return -NF_ACCEPT;
 202        }
 203
 204        return NF_ACCEPT;
 205}
 206
 207#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
 208
 209#include <linux/netfilter/nfnetlink.h>
 210#include <linux/netfilter/nfnetlink_cttimeout.h>
 211
 212static int udp_timeout_nlattr_to_obj(struct nlattr *tb[],
 213                                     struct net *net, void *data)
 214{
 215        unsigned int *timeouts = data;
 216        struct nf_udp_net *un = udp_pernet(net);
 217
 218        /* set default timeouts for UDP. */
 219        timeouts[UDP_CT_UNREPLIED] = un->timeouts[UDP_CT_UNREPLIED];
 220        timeouts[UDP_CT_REPLIED] = un->timeouts[UDP_CT_REPLIED];
 221
 222        if (tb[CTA_TIMEOUT_UDP_UNREPLIED]) {
 223                timeouts[UDP_CT_UNREPLIED] =
 224                        ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_UNREPLIED])) * HZ;
 225        }
 226        if (tb[CTA_TIMEOUT_UDP_REPLIED]) {
 227                timeouts[UDP_CT_REPLIED] =
 228                        ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_REPLIED])) * HZ;
 229        }
 230        return 0;
 231}
 232
 233static int
 234udp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
 235{
 236        const unsigned int *timeouts = data;
 237
 238        if (nla_put_be32(skb, CTA_TIMEOUT_UDP_UNREPLIED,
 239                         htonl(timeouts[UDP_CT_UNREPLIED] / HZ)) ||
 240            nla_put_be32(skb, CTA_TIMEOUT_UDP_REPLIED,
 241                         htonl(timeouts[UDP_CT_REPLIED] / HZ)))
 242                goto nla_put_failure;
 243        return 0;
 244
 245nla_put_failure:
 246        return -ENOSPC;
 247}
 248
 249static const struct nla_policy
 250udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = {
 251       [CTA_TIMEOUT_UDP_UNREPLIED]      = { .type = NLA_U32 },
 252       [CTA_TIMEOUT_UDP_REPLIED]        = { .type = NLA_U32 },
 253};
 254#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 255
 256#ifdef CONFIG_SYSCTL
 257static struct ctl_table udp_sysctl_table[] = {
 258        {
 259                .procname       = "nf_conntrack_udp_timeout",
 260                .maxlen         = sizeof(unsigned int),
 261                .mode           = 0644,
 262                .proc_handler   = proc_dointvec_jiffies,
 263        },
 264        {
 265                .procname       = "nf_conntrack_udp_timeout_stream",
 266                .maxlen         = sizeof(unsigned int),
 267                .mode           = 0644,
 268                .proc_handler   = proc_dointvec_jiffies,
 269        },
 270        { }
 271};
 272#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
 273static struct ctl_table udp_compat_sysctl_table[] = {
 274        {
 275                .procname       = "ip_conntrack_udp_timeout",
 276                .maxlen         = sizeof(unsigned int),
 277                .mode           = 0644,
 278                .proc_handler   = proc_dointvec_jiffies,
 279        },
 280        {
 281                .procname       = "ip_conntrack_udp_timeout_stream",
 282                .maxlen         = sizeof(unsigned int),
 283                .mode           = 0644,
 284                .proc_handler   = proc_dointvec_jiffies,
 285        },
 286        { }
 287};
 288#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 289#endif /* CONFIG_SYSCTL */
 290
 291static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn,
 292                                    struct nf_udp_net *un)
 293{
 294#ifdef CONFIG_SYSCTL
 295        if (pn->ctl_table)
 296                return 0;
 297        pn->ctl_table = kmemdup(udp_sysctl_table,
 298                                sizeof(udp_sysctl_table),
 299                                GFP_KERNEL);
 300        if (!pn->ctl_table)
 301                return -ENOMEM;
 302        pn->ctl_table[0].data = &un->timeouts[UDP_CT_UNREPLIED];
 303        pn->ctl_table[1].data = &un->timeouts[UDP_CT_REPLIED];
 304#endif
 305        return 0;
 306}
 307
 308static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn,
 309                                           struct nf_udp_net *un)
 310{
 311#ifdef CONFIG_SYSCTL
 312#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
 313        pn->ctl_compat_table = kmemdup(udp_compat_sysctl_table,
 314                                       sizeof(udp_compat_sysctl_table),
 315                                       GFP_KERNEL);
 316        if (!pn->ctl_compat_table)
 317                return -ENOMEM;
 318
 319        pn->ctl_compat_table[0].data = &un->timeouts[UDP_CT_UNREPLIED];
 320        pn->ctl_compat_table[1].data = &un->timeouts[UDP_CT_REPLIED];
 321#endif
 322#endif
 323        return 0;
 324}
 325
 326static int udp_init_net(struct net *net, u_int16_t proto)
 327{
 328        int ret;
 329        struct nf_udp_net *un = udp_pernet(net);
 330        struct nf_proto_net *pn = &un->pn;
 331
 332        if (!pn->users) {
 333                int i;
 334
 335                for (i = 0; i < UDP_CT_MAX; i++)
 336                        un->timeouts[i] = udp_timeouts[i];
 337        }
 338
 339        if (proto == AF_INET) {
 340                ret = udp_kmemdup_compat_sysctl_table(pn, un);
 341                if (ret < 0)
 342                        return ret;
 343
 344                ret = udp_kmemdup_sysctl_table(pn, un);
 345                if (ret < 0)
 346                        nf_ct_kfree_compat_sysctl_table(pn);
 347        } else
 348                ret = udp_kmemdup_sysctl_table(pn, un);
 349
 350        return ret;
 351}
 352
 353static struct nf_proto_net *udp_get_net_proto(struct net *net)
 354{
 355        return &net->ct.nf_ct_proto.udp.pn;
 356}
 357
 358struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
 359{
 360        .l3proto                = PF_INET,
 361        .l4proto                = IPPROTO_UDP,
 362        .name                   = "udp",
 363        .pkt_to_tuple           = udp_pkt_to_tuple,
 364        .invert_tuple           = udp_invert_tuple,
 365        .print_tuple            = udp_print_tuple,
 366        .packet                 = udp_packet,
 367        .get_timeouts           = udp_get_timeouts,
 368        .new                    = udp_new,
 369        .error                  = udp_error,
 370#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 371        .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 372        .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 373        .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 374        .nla_policy             = nf_ct_port_nla_policy,
 375#endif
 376#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
 377        .ctnl_timeout           = {
 378                .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 379                .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 380                .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 381                .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 382                .nla_policy     = udp_timeout_nla_policy,
 383        },
 384#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 385        .init_net               = udp_init_net,
 386        .get_net_proto          = udp_get_net_proto,
 387};
 388EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4);
 389
 390#ifdef CONFIG_NF_CT_PROTO_UDPLITE
 391struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
 392{
 393        .l3proto                = PF_INET,
 394        .l4proto                = IPPROTO_UDPLITE,
 395        .name                   = "udplite",
 396        .pkt_to_tuple           = udp_pkt_to_tuple,
 397        .invert_tuple           = udp_invert_tuple,
 398        .print_tuple            = udp_print_tuple,
 399        .packet                 = udp_packet,
 400        .get_timeouts           = udp_get_timeouts,
 401        .new                    = udp_new,
 402        .error                  = udplite_error,
 403#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 404        .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 405        .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 406        .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 407        .nla_policy             = nf_ct_port_nla_policy,
 408#endif
 409#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
 410        .ctnl_timeout           = {
 411                .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 412                .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 413                .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 414                .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 415                .nla_policy     = udp_timeout_nla_policy,
 416        },
 417#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 418        .init_net               = udp_init_net,
 419        .get_net_proto          = udp_get_net_proto,
 420};
 421EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite4);
 422#endif
 423
 424struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =
 425{
 426        .l3proto                = PF_INET6,
 427        .l4proto                = IPPROTO_UDP,
 428        .name                   = "udp",
 429        .pkt_to_tuple           = udp_pkt_to_tuple,
 430        .invert_tuple           = udp_invert_tuple,
 431        .print_tuple            = udp_print_tuple,
 432        .packet                 = udp_packet,
 433        .get_timeouts           = udp_get_timeouts,
 434        .new                    = udp_new,
 435        .error                  = udp_error,
 436#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 437        .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 438        .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 439        .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 440        .nla_policy             = nf_ct_port_nla_policy,
 441#endif
 442#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
 443        .ctnl_timeout           = {
 444                .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 445                .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 446                .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 447                .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 448                .nla_policy     = udp_timeout_nla_policy,
 449        },
 450#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 451        .init_net               = udp_init_net,
 452        .get_net_proto          = udp_get_net_proto,
 453};
 454EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6);
 455
 456#ifdef CONFIG_NF_CT_PROTO_UDPLITE
 457struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
 458{
 459        .l3proto                = PF_INET6,
 460        .l4proto                = IPPROTO_UDPLITE,
 461        .name                   = "udplite",
 462        .pkt_to_tuple           = udp_pkt_to_tuple,
 463        .invert_tuple           = udp_invert_tuple,
 464        .print_tuple            = udp_print_tuple,
 465        .packet                 = udp_packet,
 466        .get_timeouts           = udp_get_timeouts,
 467        .new                    = udp_new,
 468        .error                  = udplite_error,
 469#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 470        .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 471        .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 472        .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 473        .nla_policy             = nf_ct_port_nla_policy,
 474#endif
 475#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
 476        .ctnl_timeout           = {
 477                .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 478                .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 479                .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 480                .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 481                .nla_policy     = udp_timeout_nla_policy,
 482        },
 483#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 484        .init_net               = udp_init_net,
 485        .get_net_proto          = udp_get_net_proto,
 486};
 487EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite6);
 488#endif
 489