fou6.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include <linux/module.h>
  2. #include <linux/errno.h>
  3. #include <linux/socket.h>
  4. #include <linux/skbuff.h>
  5. #include <linux/ip.h>
  6. #include <linux/udp.h>
  7. #include <linux/types.h>
  8. #include <linux/kernel.h>
  9. #include <net/fou.h>
  10. #include <net/ip.h>
  11. #include <net/ip6_tunnel.h>
  12. #include <net/ip6_checksum.h>
  13. #include <net/protocol.h>
  14. #include <net/udp.h>
  15. #include <net/udp_tunnel.h>
  16. static void fou6_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e,
  17. struct flowi6 *fl6, u8 *protocol, __be16 sport)
  18. {
  19. struct udphdr *uh;
  20. skb_push(skb, sizeof(struct udphdr));
  21. skb_reset_transport_header(skb);
  22. uh = udp_hdr(skb);
  23. uh->dest = e->dport;
  24. uh->source = sport;
  25. uh->len = htons(skb->len);
  26. udp6_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM6), skb,
  27. &fl6->saddr, &fl6->daddr, skb->len);
  28. *protocol = IPPROTO_UDP;
  29. }
  30. int fou6_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
  31. u8 *protocol, struct flowi6 *fl6)
  32. {
  33. __be16 sport;
  34. int err;
  35. int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM6 ?
  36. SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
  37. err = __fou_build_header(skb, e, protocol, &sport, type);
  38. if (err)
  39. return err;
  40. fou6_build_udp(skb, e, fl6, protocol, sport);
  41. return 0;
  42. }
  43. EXPORT_SYMBOL(fou6_build_header);
  44. int gue6_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
  45. u8 *protocol, struct flowi6 *fl6)
  46. {
  47. __be16 sport;
  48. int err;
  49. int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM6 ?
  50. SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
  51. err = __gue_build_header(skb, e, protocol, &sport, type);
  52. if (err)
  53. return err;
  54. fou6_build_udp(skb, e, fl6, protocol, sport);
  55. return 0;
  56. }
  57. EXPORT_SYMBOL(gue6_build_header);
  58. #if IS_ENABLED(CONFIG_IPV6_FOU_TUNNEL)
  59. static const struct ip6_tnl_encap_ops fou_ip6tun_ops = {
  60. .encap_hlen = fou_encap_hlen,
  61. .build_header = fou6_build_header,
  62. };
  63. static const struct ip6_tnl_encap_ops gue_ip6tun_ops = {
  64. .encap_hlen = gue_encap_hlen,
  65. .build_header = gue6_build_header,
  66. };
  67. static int ip6_tnl_encap_add_fou_ops(void)
  68. {
  69. int ret;
  70. ret = ip6_tnl_encap_add_ops(&fou_ip6tun_ops, TUNNEL_ENCAP_FOU);
  71. if (ret < 0) {
  72. pr_err("can't add fou6 ops\n");
  73. return ret;
  74. }
  75. ret = ip6_tnl_encap_add_ops(&gue_ip6tun_ops, TUNNEL_ENCAP_GUE);
  76. if (ret < 0) {
  77. pr_err("can't add gue6 ops\n");
  78. ip6_tnl_encap_del_ops(&fou_ip6tun_ops, TUNNEL_ENCAP_FOU);
  79. return ret;
  80. }
  81. return 0;
  82. }
  83. static void ip6_tnl_encap_del_fou_ops(void)
  84. {
  85. ip6_tnl_encap_del_ops(&fou_ip6tun_ops, TUNNEL_ENCAP_FOU);
  86. ip6_tnl_encap_del_ops(&gue_ip6tun_ops, TUNNEL_ENCAP_GUE);
  87. }
  88. #else
  89. static int ip6_tnl_encap_add_fou_ops(void)
  90. {
  91. return 0;
  92. }
  93. static void ip6_tnl_encap_del_fou_ops(void)
  94. {
  95. }
  96. #endif
  97. static int __init fou6_init(void)
  98. {
  99. int ret;
  100. ret = ip6_tnl_encap_add_fou_ops();
  101. return ret;
  102. }
  103. static void __exit fou6_fini(void)
  104. {
  105. ip6_tnl_encap_del_fou_ops();
  106. }
  107. module_init(fou6_init);
  108. module_exit(fou6_fini);
  109. MODULE_AUTHOR("Tom Herbert <therbert@google.com>");
  110. MODULE_LICENSE("GPL");