xfrm4_output.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. #include <linux/compiler.h>
  11. #include <linux/skbuff.h>
  12. #include <linux/spinlock.h>
  13. #include <linux/netfilter_ipv4.h>
  14. #include <net/inet_ecn.h>
  15. #include <net/ip.h>
  16. #include <net/xfrm.h>
  17. #include <net/icmp.h>
  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. int flags;
  37. iph = skb->nh.iph;
  38. skb->h.ipiph = iph;
  39. skb->nh.raw = skb_push(skb, x->props.header_len);
  40. top_iph = skb->nh.iph;
  41. if (!x->props.mode) {
  42. skb->h.raw += iph->ihl*4;
  43. memmove(top_iph, iph, iph->ihl*4);
  44. return;
  45. }
  46. top_iph->ihl = 5;
  47. top_iph->version = 4;
  48. /* DS disclosed */
  49. top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
  50. flags = x->props.flags;
  51. if (flags & XFRM_STATE_NOECN)
  52. IP_ECN_clear(top_iph);
  53. top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
  54. 0 : (iph->frag_off & htons(IP_DF));
  55. if (!top_iph->frag_off)
  56. __ip_select_ident(top_iph, dst, 0);
  57. top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
  58. top_iph->saddr = x->props.saddr.a4;
  59. top_iph->daddr = x->id.daddr.a4;
  60. top_iph->protocol = IPPROTO_IPIP;
  61. memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
  62. }
  63. static int xfrm4_tunnel_check_size(struct sk_buff *skb)
  64. {
  65. int mtu, ret = 0;
  66. struct dst_entry *dst;
  67. struct iphdr *iph = skb->nh.iph;
  68. if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE)
  69. goto out;
  70. IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
  71. if (!(iph->frag_off & htons(IP_DF)) || skb->local_df)
  72. goto out;
  73. dst = skb->dst;
  74. mtu = dst_mtu(dst);
  75. if (skb->len > mtu) {
  76. icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
  77. ret = -EMSGSIZE;
  78. }
  79. out:
  80. return ret;
  81. }
  82. static int xfrm4_output_one(struct sk_buff *skb)
  83. {
  84. struct dst_entry *dst = skb->dst;
  85. struct xfrm_state *x = dst->xfrm;
  86. int err;
  87. if (skb->ip_summed == CHECKSUM_HW) {
  88. err = skb_checksum_help(skb, 0);
  89. if (err)
  90. goto error_nolock;
  91. }
  92. if (x->props.mode) {
  93. err = xfrm4_tunnel_check_size(skb);
  94. if (err)
  95. goto error_nolock;
  96. }
  97. do {
  98. spin_lock_bh(&x->lock);
  99. err = xfrm_state_check(x, skb);
  100. if (err)
  101. goto error;
  102. xfrm4_encap(skb);
  103. err = x->type->output(x, skb);
  104. if (err)
  105. goto error;
  106. x->curlft.bytes += skb->len;
  107. x->curlft.packets++;
  108. spin_unlock_bh(&x->lock);
  109. if (!(skb->dst = dst_pop(dst))) {
  110. err = -EHOSTUNREACH;
  111. goto error_nolock;
  112. }
  113. dst = skb->dst;
  114. x = dst->xfrm;
  115. } while (x && !x->props.mode);
  116. IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
  117. err = 0;
  118. out_exit:
  119. return err;
  120. error:
  121. spin_unlock_bh(&x->lock);
  122. error_nolock:
  123. kfree_skb(skb);
  124. goto out_exit;
  125. }
  126. int xfrm4_output_finish(struct sk_buff *skb)
  127. {
  128. int err;
  129. while (likely((err = xfrm4_output_one(skb)) == 0)) {
  130. nf_reset(skb);
  131. err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, &skb, NULL,
  132. skb->dst->dev, dst_output);
  133. if (unlikely(err != 1))
  134. break;
  135. if (!skb->dst->xfrm)
  136. return dst_output(skb);
  137. err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,
  138. skb->dst->dev, xfrm4_output_finish);
  139. if (unlikely(err != 1))
  140. break;
  141. }
  142. return err;
  143. }
  144. int xfrm4_output(struct sk_buff *skb)
  145. {
  146. return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
  147. xfrm4_output_finish);
  148. }