root/net/ipv4/xfrm4_output.c

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

DEFINITIONS

This source file includes following definitions.
  1. xfrm4_tunnel_check_size
  2. xfrm4_extract_output
  3. xfrm4_output_finish
  4. __xfrm4_output
  5. xfrm4_output
  6. xfrm4_local_error

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * xfrm4_output.c - Common IPsec encapsulation code for IPv4.
   4  * Copyright (c) 2004 Herbert Xu <herbert@gondor.apana.org.au>
   5  */
   6 
   7 #include <linux/if_ether.h>
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/skbuff.h>
  11 #include <linux/netfilter_ipv4.h>
  12 #include <net/dst.h>
  13 #include <net/ip.h>
  14 #include <net/xfrm.h>
  15 #include <net/icmp.h>
  16 
  17 static int xfrm4_tunnel_check_size(struct sk_buff *skb)
  18 {
  19         int mtu, ret = 0;
  20 
  21         if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE)
  22                 goto out;
  23 
  24         if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->ignore_df)
  25                 goto out;
  26 
  27         mtu = dst_mtu(skb_dst(skb));
  28         if ((!skb_is_gso(skb) && skb->len > mtu) ||
  29             (skb_is_gso(skb) &&
  30              !skb_gso_validate_network_len(skb, ip_skb_dst_mtu(skb->sk, skb)))) {
  31                 skb->protocol = htons(ETH_P_IP);
  32 
  33                 if (skb->sk)
  34                         xfrm_local_error(skb, mtu);
  35                 else
  36                         icmp_send(skb, ICMP_DEST_UNREACH,
  37                                   ICMP_FRAG_NEEDED, htonl(mtu));
  38                 ret = -EMSGSIZE;
  39         }
  40 out:
  41         return ret;
  42 }
  43 
  44 int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb)
  45 {
  46         int err;
  47 
  48         err = xfrm4_tunnel_check_size(skb);
  49         if (err)
  50                 return err;
  51 
  52         XFRM_MODE_SKB_CB(skb)->protocol = ip_hdr(skb)->protocol;
  53 
  54         return xfrm4_extract_header(skb);
  55 }
  56 
  57 int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb)
  58 {
  59         memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
  60 
  61         IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
  62 
  63         return xfrm_output(sk, skb);
  64 }
  65 
  66 static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
  67 {
  68         struct xfrm_state *x = skb_dst(skb)->xfrm;
  69         const struct xfrm_state_afinfo *afinfo;
  70         int ret = -EAFNOSUPPORT;
  71 
  72 #ifdef CONFIG_NETFILTER
  73         if (!x) {
  74                 IPCB(skb)->flags |= IPSKB_REROUTED;
  75                 return dst_output(net, sk, skb);
  76         }
  77 #endif
  78 
  79         rcu_read_lock();
  80         afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
  81         if (likely(afinfo))
  82                 ret = afinfo->output_finish(sk, skb);
  83         else
  84                 kfree_skb(skb);
  85         rcu_read_unlock();
  86 
  87         return ret;
  88 }
  89 
  90 int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
  91 {
  92         return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,
  93                             net, sk, skb, NULL, skb_dst(skb)->dev,
  94                             __xfrm4_output,
  95                             !(IPCB(skb)->flags & IPSKB_REROUTED));
  96 }
  97 
  98 void xfrm4_local_error(struct sk_buff *skb, u32 mtu)
  99 {
 100         struct iphdr *hdr;
 101 
 102         hdr = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb);
 103         ip_local_error(skb->sk, EMSGSIZE, hdr->daddr,
 104                        inet_sk(skb->sk)->inet_dport, mtu);
 105 }

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