root/net/netfilter/nf_conntrack_proto_udp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. udp_get_timeouts
  2. udp_error_log
  3. udp_error
  4. nf_conntrack_udp_packet
  5. udplite_error_log
  6. udplite_error
  7. nf_conntrack_udplite_packet
  8. udp_timeout_nlattr_to_obj
  9. udp_timeout_obj_to_nlattr
  10. nf_conntrack_udp_init_net

   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 
  27 static const unsigned int udp_timeouts[UDP_CT_MAX] = {
  28         [UDP_CT_UNREPLIED]      = 30*HZ,
  29         [UDP_CT_REPLIED]        = 120*HZ,
  30 };
  31 
  32 static unsigned int *udp_get_timeouts(struct net *net)
  33 {
  34         return nf_udp_pernet(net)->timeouts;
  35 }
  36 
  37 static 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 
  45 static 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 */
  85 int 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                 /* Also, more likely to be important, and not a probe */
 116                 if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
 117                         nf_conntrack_event_cache(IPCT_ASSURED, ct);
 118         } else {
 119                 nf_ct_refresh_acct(ct, ctinfo, skb,
 120                                    timeouts[UDP_CT_UNREPLIED]);
 121         }
 122         return NF_ACCEPT;
 123 }
 124 
 125 #ifdef CONFIG_NF_CT_PROTO_UDPLITE
 126 static void udplite_error_log(const struct sk_buff *skb,
 127                               const struct nf_hook_state *state,
 128                               const char *msg)
 129 {
 130         nf_l4proto_log_invalid(skb, state->net, state->pf,
 131                                IPPROTO_UDPLITE, "%s", msg);
 132 }
 133 
 134 static bool udplite_error(struct sk_buff *skb,
 135                           unsigned int dataoff,
 136                           const struct nf_hook_state *state)
 137 {
 138         unsigned int udplen = skb->len - dataoff;
 139         const struct udphdr *hdr;
 140         struct udphdr _hdr;
 141         unsigned int cscov;
 142 
 143         /* Header is too small? */
 144         hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
 145         if (!hdr) {
 146                 udplite_error_log(skb, state, "short packet");
 147                 return true;
 148         }
 149 
 150         cscov = ntohs(hdr->len);
 151         if (cscov == 0) {
 152                 cscov = udplen;
 153         } else if (cscov < sizeof(*hdr) || cscov > udplen) {
 154                 udplite_error_log(skb, state, "invalid checksum coverage");
 155                 return true;
 156         }
 157 
 158         /* UDPLITE mandates checksums */
 159         if (!hdr->check) {
 160                 udplite_error_log(skb, state, "checksum missing");
 161                 return true;
 162         }
 163 
 164         /* Checksum invalid? Ignore. */
 165         if (state->hook == NF_INET_PRE_ROUTING &&
 166             state->net->ct.sysctl_checksum &&
 167             nf_checksum_partial(skb, state->hook, dataoff, cscov, IPPROTO_UDP,
 168                                 state->pf)) {
 169                 udplite_error_log(skb, state, "bad checksum");
 170                 return true;
 171         }
 172 
 173         return false;
 174 }
 175 
 176 /* Returns verdict for packet, and may modify conntracktype */
 177 int nf_conntrack_udplite_packet(struct nf_conn *ct,
 178                                 struct sk_buff *skb,
 179                                 unsigned int dataoff,
 180                                 enum ip_conntrack_info ctinfo,
 181                                 const struct nf_hook_state *state)
 182 {
 183         unsigned int *timeouts;
 184 
 185         if (udplite_error(skb, dataoff, state))
 186                 return -NF_ACCEPT;
 187 
 188         timeouts = nf_ct_timeout_lookup(ct);
 189         if (!timeouts)
 190                 timeouts = udp_get_timeouts(nf_ct_net(ct));
 191 
 192         /* If we've seen traffic both ways, this is some kind of UDP
 193            stream.  Extend timeout. */
 194         if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
 195                 nf_ct_refresh_acct(ct, ctinfo, skb,
 196                                    timeouts[UDP_CT_REPLIED]);
 197                 /* Also, more likely to be important, and not a probe */
 198                 if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
 199                         nf_conntrack_event_cache(IPCT_ASSURED, ct);
 200         } else {
 201                 nf_ct_refresh_acct(ct, ctinfo, skb,
 202                                    timeouts[UDP_CT_UNREPLIED]);
 203         }
 204         return NF_ACCEPT;
 205 }
 206 #endif
 207 
 208 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
 209 
 210 #include <linux/netfilter/nfnetlink.h>
 211 #include <linux/netfilter/nfnetlink_cttimeout.h>
 212 
 213 static int udp_timeout_nlattr_to_obj(struct nlattr *tb[],
 214                                      struct net *net, void *data)
 215 {
 216         unsigned int *timeouts = data;
 217         struct nf_udp_net *un = nf_udp_pernet(net);
 218 
 219         if (!timeouts)
 220                 timeouts = un->timeouts;
 221 
 222         /* set default timeouts for UDP. */
 223         timeouts[UDP_CT_UNREPLIED] = un->timeouts[UDP_CT_UNREPLIED];
 224         timeouts[UDP_CT_REPLIED] = un->timeouts[UDP_CT_REPLIED];
 225 
 226         if (tb[CTA_TIMEOUT_UDP_UNREPLIED]) {
 227                 timeouts[UDP_CT_UNREPLIED] =
 228                         ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_UNREPLIED])) * HZ;
 229         }
 230         if (tb[CTA_TIMEOUT_UDP_REPLIED]) {
 231                 timeouts[UDP_CT_REPLIED] =
 232                         ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_REPLIED])) * HZ;
 233         }
 234         return 0;
 235 }
 236 
 237 static int
 238 udp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
 239 {
 240         const unsigned int *timeouts = data;
 241 
 242         if (nla_put_be32(skb, CTA_TIMEOUT_UDP_UNREPLIED,
 243                          htonl(timeouts[UDP_CT_UNREPLIED] / HZ)) ||
 244             nla_put_be32(skb, CTA_TIMEOUT_UDP_REPLIED,
 245                          htonl(timeouts[UDP_CT_REPLIED] / HZ)))
 246                 goto nla_put_failure;
 247         return 0;
 248 
 249 nla_put_failure:
 250         return -ENOSPC;
 251 }
 252 
 253 static const struct nla_policy
 254 udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = {
 255        [CTA_TIMEOUT_UDP_UNREPLIED]      = { .type = NLA_U32 },
 256        [CTA_TIMEOUT_UDP_REPLIED]        = { .type = NLA_U32 },
 257 };
 258 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
 259 
 260 void nf_conntrack_udp_init_net(struct net *net)
 261 {
 262         struct nf_udp_net *un = nf_udp_pernet(net);
 263         int i;
 264 
 265         for (i = 0; i < UDP_CT_MAX; i++)
 266                 un->timeouts[i] = udp_timeouts[i];
 267 }
 268 
 269 const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp =
 270 {
 271         .l4proto                = IPPROTO_UDP,
 272         .allow_clash            = true,
 273 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 274         .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 275         .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 276         .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 277         .nla_policy             = nf_ct_port_nla_policy,
 278 #endif
 279 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
 280         .ctnl_timeout           = {
 281                 .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 282                 .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 283                 .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 284                 .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 285                 .nla_policy     = udp_timeout_nla_policy,
 286         },
 287 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
 288 };
 289 
 290 #ifdef CONFIG_NF_CT_PROTO_UDPLITE
 291 const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite =
 292 {
 293         .l4proto                = IPPROTO_UDPLITE,
 294         .allow_clash            = true,
 295 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 296         .tuple_to_nlattr        = nf_ct_port_tuple_to_nlattr,
 297         .nlattr_to_tuple        = nf_ct_port_nlattr_to_tuple,
 298         .nlattr_tuple_size      = nf_ct_port_nlattr_tuple_size,
 299         .nla_policy             = nf_ct_port_nla_policy,
 300 #endif
 301 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
 302         .ctnl_timeout           = {
 303                 .nlattr_to_obj  = udp_timeout_nlattr_to_obj,
 304                 .obj_to_nlattr  = udp_timeout_obj_to_nlattr,
 305                 .nlattr_max     = CTA_TIMEOUT_UDP_MAX,
 306                 .obj_size       = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
 307                 .nla_policy     = udp_timeout_nla_policy,
 308         },
 309 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
 310 };
 311 #endif

/* [<][>][^][v][top][bottom][index][help] */