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 const 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 net *net,
  42                             struct nf_conntrack_tuple *tuple)
  43{
  44        const struct udphdr *hp;
  45        struct udphdr _hdr;
  46
  47        /* Actually only need first 4 bytes to get ports. */
  48        hp = skb_header_pointer(skb, dataoff, 4, &_hdr);
  49        if (hp == NULL)
  50                return false;
  51
  52        tuple->src.u.udp.port = hp->source;
  53        tuple->dst.u.udp.port = hp->dest;
  54
  55        return true;
  56}
  57
  58static bool udp_invert_tuple(struct nf_conntrack_tuple *tuple,
  59                             const struct nf_conntrack_tuple *orig)
  60{
  61        tuple->src.u.udp.port = orig->dst.u.udp.port;
  62        tuple->dst.u.udp.port = orig->src.u.udp.port;
  63        return true;
  64}
  65
  66static unsigned int *udp_get_timeouts(struct net *net)
  67{
  68        return udp_pernet(net)->timeouts;
  69}
  70
  71/* Returns verdict for packet, and may modify conntracktype */
  72static int udp_packet(struct nf_conn *ct,
  73                      const struct sk_buff *skb,
  74                      unsigned int dataoff,
  75                      enum ip_conntrack_info ctinfo,
  76                      unsigned int *timeouts)
  77{
  78        /* If we've seen traffic both ways, this is some kind of UDP
  79           stream.  Extend timeout. */
  80        if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
  81                nf_ct_refresh_acct(ct, ctinfo, skb,
  82                                   timeouts[UDP_CT_REPLIED]);
  83                /* Also, more likely to be important, and not a probe */
  84                if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
  85                        nf_conntrack_event_cache(IPCT_ASSURED, ct);
  86        } else {
  87                nf_ct_refresh_acct(ct, ctinfo, skb,
  88                                   timeouts[UDP_CT_UNREPLIED]);
  89        }
  90        return NF_ACCEPT;
  91}
  92
  93/* Called when a new connection for this protocol found. */
  94static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
  95                    unsigned int dataoff, unsigned int *timeouts)
  96{
  97        return true;
  98}
  99
 100#ifdef CONFIG_NF_CT_PROTO_UDPLITE
 101static void udplite_error_log(const struct sk_buff *skb, struct net *net,
 102                              u8 pf, const char *msg)
 103{
 104        nf_l4proto_log_invalid(skb, net, pf, IPPROTO_UDPLITE, "%s", msg);
 105}
 106
 107static int udplite_error(struct net *net, struct nf_conn *tmpl,
 108                         struct sk_buff *skb,
 109                         unsigned int dataoff,
 110                         u8 pf, unsigned int hooknum)
 111{
 112        unsigned int udplen = skb->len - dataoff;
 113        const struct udphdr *hdr;
 114        struct udphdr _hdr;
 115        unsigned int cscov;
 116
 117        /* Header is too small? */
 118        hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
 119        if (!hdr) {
 120                udplite_error_log(skb, net, pf, "short packet");
 121                return -NF_ACCEPT;
 122        }
 123
 124        cscov = ntohs(hdr->len);
 125        if (cscov == 0) {
 126                cscov = udplen;
 127        } else if (cscov < sizeof(*hdr) || cscov > udplen) {
 128                udplite_error_log(skb, net, pf, "invalid checksum coverage");
 129                return -NF_ACCEPT;
 130        }
 131
 132        /* UDPLITE mandates checksums */
 133        if (!hdr->check) {
 134                udplite_error_log(skb, net, pf, "checksum missing");
 135                return -NF_ACCEPT;
 136        }
 137
 138        /* Checksum invalid? Ignore. */
 139        if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 140            nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
 141                                pf)) {
 142                udplite_error_log(skb, net, pf, "bad checksum");
 143                return -NF_ACCEPT;
 144        }
 145
 146        return NF_ACCEPT;
 147}
 148#endif
 149
 150static void udp_error_log(const struct sk_buff *skb, struct net *net,
 151                          u8 pf, const char *msg)
 152{
 153        nf_l4proto_log_invalid(skb, net, pf, IPPROTO_UDP, "%s", msg);
 154}
 155
 156static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
 157                     unsigned int dataoff,
 158                     u_int8_t pf,
 159                     unsigned int hooknum)
 160{
 161        unsigned int udplen = skb->len - dataoff;
 162        const struct udphdr *hdr;
 163        struct udphdr _hdr;
 164
 165        /* Header is too small? */
 166        hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
 167        if (hdr == NULL) {
 168                udp_error_log(skb, net, pf, "short packet");
 169                return -NF_ACCEPT;
 170        }
 171
 172        /* Truncated/malformed packets */
 173        if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
 174                udp_error_log(skb, net, pf, "truncated/malformed packet");
 175                return -NF_ACCEPT;
 176        }
 177
 178        /* Packet with no checksum */
 179        if (!hdr->check)
 180                return NF_ACCEPT;
 181
 182        /* Checksum invalid? Ignore.
 183         * We skip checking packets on the outgoing path
 184         * because the checksum is assumed to be correct.
 185         * FIXME: Source route IP option packets --RR */
 186        if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
 187            nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
 188                udp_error_log(skb, net, pf, "bad checksum");
 189                return -NF_ACCEPT;
 190        }
 191
 192        return NF_ACCEPT;
 193}
 194
 195#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
 196
 197#include <linux/netfilter/nfnetlink.h>
 198#include <linux/netfilter/nfnetlink_cttimeout.h>
 199
 200static int udp_timeout_nlattr_to_obj(struct nlattr *tb[],
 201                                     struct net *net, void *data)
 202{
 203        unsigned int *timeouts = data;
 204        struct nf_udp_net *un = udp_pernet(net);
 205
 206        /* set default timeouts for UDP. */
 207        timeouts[UDP_CT_UNREPLIED] = un->timeouts[UDP_CT_UNREPLIED];
 208        timeouts[UDP_CT_REPLIED] = un->timeouts[UDP_CT_REPLIED];
 209
 210        if (tb[CTA_TIMEOUT_UDP_UNREPLIED]) {
 211                timeouts[UDP_CT_UNREPLIED] =
 212                        ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_UNREPLIED])) * HZ;
 213        }
 214        if (tb[CTA_TIMEOUT_UDP_REPLIED]) {
 215                timeouts[UDP_CT_REPLIED] =
 216                        ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_REPLIED])) * HZ;
 217        }
 218        return 0;
 219}
 220
 221static int
 222udp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
 223{
 224        const unsigned int *timeouts = data;
 225
 226        if (nla_put_be32(skb, CTA_TIMEOUT_UDP_UNREPLIED,
 227                         htonl(timeouts[UDP_CT_UNREPLIED] / HZ)) ||
 228            nla_put_be32(skb, CTA_TIMEOUT_UDP_REPLIED,
 229                         htonl(timeouts[UDP_CT_REPLIED] / HZ)))
 230                goto nla_put_failure;
 231        return 0;
 232
 233nla_put_failure:
 234        return -ENOSPC;
 235}
 236
 237static const struct nla_policy
 238udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = {
 239       [CTA_TIMEOUT_UDP_UNREPLIED]      = { .type = NLA_U32 },
 240       [CTA_TIMEOUT_UDP_REPLIED]        = { .type = NLA_U32 },
 241};
 242#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 243
 244#ifdef CONFIG_SYSCTL
 245static struct ctl_table udp_sysctl_table[] = {
 246        {
 247                .procname       = "nf_conntrack_udp_timeout",
 248                .maxlen         = sizeof(unsigned int),
 249                .mode           = 0644,
 250                .proc_handler   = proc_dointvec_jiffies,
 251        },
 252        {
 253                .procname       = "nf_conntrack_udp_timeout_stream",
 254                .maxlen         = sizeof(unsigned int),
 255                .mode           = 0644,
 256                .proc_handler   = proc_dointvec_jiffies,
 257        },
 258        { }
 259};
 260#endif /* CONFIG_SYSCTL */
 261
 262static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn,
 263                                    struct nf_udp_net *un)
 264{
 265#ifdef CONFIG_SYSCTL
 266        if (pn->ctl_table)
 267                return 0;
 268        pn->ctl_table = kmemdup(udp_sysctl_table,
 269                                sizeof(udp_sysctl_table),
 270                                GFP_KERNEL);
 271        if (!pn->ctl_table)
 272                return -ENOMEM;
 273        pn->ctl_table[0].data = &un->timeouts[UDP_CT_UNREPLIED];
 274        pn->ctl_table[1].data = &un->timeouts[UDP_CT_REPLIED];
 275#endif
 276        return 0;
 277}
 278
 279static int udp_init_net(struct net *net, u_int16_t proto)
 280{
 281        struct nf_udp_net *un = udp_pernet(net);
 282        struct nf_proto_net *pn = &un->pn;
 283
 284        if (!pn->users) {
 285                int i;
 286
 287                for (i = 0; i < UDP_CT_MAX; i++)
 288                        un->timeouts[i] = udp_timeouts[i];
 289        }
 290
 291        return udp_kmemdup_sysctl_table(pn, un);
 292}
 293
 294static struct nf_proto_net *udp_get_net_proto(struct net *net)
 295{
 296        return &net->ct.nf_ct_proto.udp.pn;
 297}
 298
 299const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 =
 300{
 301        .l3proto                = PF_INET,
 302        .l4proto                = IPPROTO_UDP,
 303        .allow_clash            = true,
 304        .pkt_to_tuple           = udp_pkt_to_tuple,
 305        .invert_tuple           = udp_invert_tuple,
 306        .packet                 = udp_packet,
 307        .get_timeouts           = udp_get_timeouts,
 308        .new                    = udp_new,
 309        .error                  = udp_error,
 310#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 311        .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 312        .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 313        .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 314        .nla_policy             = nf_ct_port_nla_policy,
 315#endif
 316#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
 317        .ctnl_timeout           = {
 318                .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 319                .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 320                .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 321                .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 322                .nla_policy     = udp_timeout_nla_policy,
 323        },
 324#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 325        .init_net               = udp_init_net,
 326        .get_net_proto          = udp_get_net_proto,
 327};
 328EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4);
 329
 330#ifdef CONFIG_NF_CT_PROTO_UDPLITE
 331const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 =
 332{
 333        .l3proto                = PF_INET,
 334        .l4proto                = IPPROTO_UDPLITE,
 335        .allow_clash            = true,
 336        .pkt_to_tuple           = udp_pkt_to_tuple,
 337        .invert_tuple           = udp_invert_tuple,
 338        .packet                 = udp_packet,
 339        .get_timeouts           = udp_get_timeouts,
 340        .new                    = udp_new,
 341        .error                  = udplite_error,
 342#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 343        .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 344        .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 345        .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 346        .nla_policy             = nf_ct_port_nla_policy,
 347#endif
 348#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
 349        .ctnl_timeout           = {
 350                .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 351                .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 352                .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 353                .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 354                .nla_policy     = udp_timeout_nla_policy,
 355        },
 356#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 357        .init_net               = udp_init_net,
 358        .get_net_proto          = udp_get_net_proto,
 359};
 360EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite4);
 361#endif
 362
 363const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 =
 364{
 365        .l3proto                = PF_INET6,
 366        .l4proto                = IPPROTO_UDP,
 367        .allow_clash            = true,
 368        .pkt_to_tuple           = udp_pkt_to_tuple,
 369        .invert_tuple           = udp_invert_tuple,
 370        .packet                 = udp_packet,
 371        .get_timeouts           = udp_get_timeouts,
 372        .new                    = udp_new,
 373        .error                  = udp_error,
 374#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 375        .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 376        .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 377        .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 378        .nla_policy             = nf_ct_port_nla_policy,
 379#endif
 380#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
 381        .ctnl_timeout           = {
 382                .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 383                .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 384                .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 385                .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 386                .nla_policy     = udp_timeout_nla_policy,
 387        },
 388#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 389        .init_net               = udp_init_net,
 390        .get_net_proto          = udp_get_net_proto,
 391};
 392EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6);
 393
 394#ifdef CONFIG_NF_CT_PROTO_UDPLITE
 395const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 =
 396{
 397        .l3proto                = PF_INET6,
 398        .l4proto                = IPPROTO_UDPLITE,
 399        .allow_clash            = true,
 400        .pkt_to_tuple           = udp_pkt_to_tuple,
 401        .invert_tuple           = udp_invert_tuple,
 402        .packet                 = udp_packet,
 403        .get_timeouts           = udp_get_timeouts,
 404        .new                    = udp_new,
 405        .error                  = udplite_error,
 406#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 407        .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 408        .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 409        .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 410        .nla_policy             = nf_ct_port_nla_policy,
 411#endif
 412#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
 413        .ctnl_timeout           = {
 414                .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 415                .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 416                .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 417                .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 418                .nla_policy     = udp_timeout_nla_policy,
 419        },
 420#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 421        .init_net               = udp_init_net,
 422        .get_net_proto          = udp_get_net_proto,
 423};
 424EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite6);
 425#endif
 426