1 /* 2 * xfrm4_output.c - Common IPsec encapsulation code for IPv4. 3 * Copyright (c) 2004 Herbert Xu <herbert@gondor.apana.org.au> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 8 * 2 of the License, or (at your option) any later version. 9 */ 10 11 #include <linux/skbuff.h> 12 #include <linux/spinlock.h> 13 #include <net/inet_ecn.h> 14 #include <net/ip.h> 15 #include <net/xfrm.h> 16 #include <net/icmp.h> 17 18 /* Add encapsulation header. 19 * 20 * In transport mode, the IP header will be moved forward to make space 21 * for the encapsulation header. 22 * 23 * In tunnel mode, the top IP header will be constructed per RFC 2401. 24 * The following fields in it shall be filled in by x->type->output: 25 * tot_len 26 * check 27 * 28 * On exit, skb->h will be set to the start of the payload to be processed 29 * by x->type->output and skb->nh will be set to the top IP header. 30 */ 31 static void xfrm4_encap(struct sk_buff *skb) 32 { 33 struct dst_entry *dst = skb->dst; 34 struct xfrm_state *x = dst->xfrm; 35 struct iphdr *iph, *top_iph; 36 37 iph = skb->nh.iph; 38 skb->h.ipiph = iph; 39 40 skb->nh.raw = skb_push(skb, x->props.header_len); 41 top_iph = skb->nh.iph; 42 43 if (!x->props.mode) { 44 skb->h.raw += iph->ihl*4; 45 memmove(top_iph, iph, iph->ihl*4); 46 return; 47 } 48 49 top_iph->ihl = 5; 50 top_iph->version = 4; 51 52 /* DS disclosed */ 53 top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos); 54 if (x->props.flags & XFRM_STATE_NOECN) 55 IP_ECN_clear(top_iph); 56 57 top_iph->frag_off = iph->frag_off & htons(IP_DF); 58 if (!top_iph->frag_off) 59 __ip_select_ident(top_iph, dst, 0); 60 61 top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT); 62 63 top_iph->saddr = x->props.saddr.a4; 64 top_iph->daddr = x->id.daddr.a4; 65 top_iph->protocol = IPPROTO_IPIP; 66 67 memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); 68 } 69 70 static int xfrm4_tunnel_check_size(struct sk_buff *skb) 71 { 72 int mtu, ret = 0; 73 struct dst_entry *dst; 74 struct iphdr *iph = skb->nh.iph; 75 76 if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE) 77 goto out; 78 79 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE; 80 81 if (!(iph->frag_off & htons(IP_DF)) || skb->local_df) 82 goto out; 83 84 dst = skb->dst; 85 mtu = dst_mtu(dst); 86 if (skb->len > mtu) { 87 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); 88 ret = -EMSGSIZE; 89 } 90 out: 91 return ret; 92 } 93 94 int xfrm4_output(struct sk_buff *skb) 95 { 96 struct dst_entry *dst = skb->dst; 97 struct xfrm_state *x = dst->xfrm; 98 int err; 99 100 if (skb->ip_summed == CHECKSUM_HW) { 101 err = skb_checksum_help(skb, 0); 102 if (err) 103 goto error_nolock; 104 } 105 106 if (x->props.mode) { 107 err = xfrm4_tunnel_check_size(skb); 108 if (err) 109 goto error_nolock; 110 } 111 112 spin_lock_bh(&x->lock); 113 err = xfrm_state_check(x, skb); 114 if (err) 115 goto error; 116 117 xfrm4_encap(skb); 118 119 err = x->type->output(x, skb); 120 if (err) 121 goto error; 122 123 x->curlft.bytes += skb->len; 124 x->curlft.packets++; 125 126 spin_unlock_bh(&x->lock); 127 128 if (!(skb->dst = dst_pop(dst))) { 129 err = -EHOSTUNREACH; 130 goto error_nolock; 131 } 132 err = NET_XMIT_BYPASS; 133 134 out_exit: 135 return err; 136 error: 137 spin_unlock_bh(&x->lock); 138 error_nolock: 139 kfree_skb(skb); 140 goto out_exit; 141 } 142