xfrm6_protocol.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /* xfrm6_protocol.c - Generic xfrm protocol multiplexer for ipv6.
  2. *
  3. * Copyright (C) 2013 secunet Security Networks AG
  4. *
  5. * Author:
  6. * Steffen Klassert <steffen.klassert@secunet.com>
  7. *
  8. * Based on:
  9. * net/ipv4/xfrm4_protocol.c
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License
  13. * as published by the Free Software Foundation; either version
  14. * 2 of the License, or (at your option) any later version.
  15. */
  16. #include <linux/init.h>
  17. #include <linux/mutex.h>
  18. #include <linux/skbuff.h>
  19. #include <linux/icmpv6.h>
  20. #include <net/ipv6.h>
  21. #include <net/protocol.h>
  22. #include <net/xfrm.h>
  23. static struct xfrm6_protocol __rcu *esp6_handlers __read_mostly;
  24. static struct xfrm6_protocol __rcu *ah6_handlers __read_mostly;
  25. static struct xfrm6_protocol __rcu *ipcomp6_handlers __read_mostly;
  26. static DEFINE_MUTEX(xfrm6_protocol_mutex);
  27. static inline struct xfrm6_protocol __rcu **proto_handlers(u8 protocol)
  28. {
  29. switch (protocol) {
  30. case IPPROTO_ESP:
  31. return &esp6_handlers;
  32. case IPPROTO_AH:
  33. return &ah6_handlers;
  34. case IPPROTO_COMP:
  35. return &ipcomp6_handlers;
  36. }
  37. return NULL;
  38. }
  39. #define for_each_protocol_rcu(head, handler) \
  40. for (handler = rcu_dereference(head); \
  41. handler != NULL; \
  42. handler = rcu_dereference(handler->next)) \
  43. int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
  44. {
  45. int ret;
  46. struct xfrm6_protocol *handler;
  47. for_each_protocol_rcu(*proto_handlers(protocol), handler)
  48. if ((ret = handler->cb_handler(skb, err)) <= 0)
  49. return ret;
  50. return 0;
  51. }
  52. EXPORT_SYMBOL(xfrm6_rcv_cb);
  53. static int xfrm6_esp_rcv(struct sk_buff *skb)
  54. {
  55. int ret;
  56. struct xfrm6_protocol *handler;
  57. XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
  58. for_each_protocol_rcu(esp6_handlers, handler)
  59. if ((ret = handler->handler(skb)) != -EINVAL)
  60. return ret;
  61. icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
  62. kfree_skb(skb);
  63. return 0;
  64. }
  65. static void xfrm6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
  66. u8 type, u8 code, int offset, __be32 info)
  67. {
  68. struct xfrm6_protocol *handler;
  69. for_each_protocol_rcu(esp6_handlers, handler)
  70. if (!handler->err_handler(skb, opt, type, code, offset, info))
  71. break;
  72. }
  73. static int xfrm6_ah_rcv(struct sk_buff *skb)
  74. {
  75. int ret;
  76. struct xfrm6_protocol *handler;
  77. XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
  78. for_each_protocol_rcu(ah6_handlers, handler)
  79. if ((ret = handler->handler(skb)) != -EINVAL)
  80. return ret;
  81. icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
  82. kfree_skb(skb);
  83. return 0;
  84. }
  85. static void xfrm6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
  86. u8 type, u8 code, int offset, __be32 info)
  87. {
  88. struct xfrm6_protocol *handler;
  89. for_each_protocol_rcu(ah6_handlers, handler)
  90. if (!handler->err_handler(skb, opt, type, code, offset, info))
  91. break;
  92. }
  93. static int xfrm6_ipcomp_rcv(struct sk_buff *skb)
  94. {
  95. int ret;
  96. struct xfrm6_protocol *handler;
  97. XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
  98. for_each_protocol_rcu(ipcomp6_handlers, handler)
  99. if ((ret = handler->handler(skb)) != -EINVAL)
  100. return ret;
  101. icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
  102. kfree_skb(skb);
  103. return 0;
  104. }
  105. static void xfrm6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
  106. u8 type, u8 code, int offset, __be32 info)
  107. {
  108. struct xfrm6_protocol *handler;
  109. for_each_protocol_rcu(ipcomp6_handlers, handler)
  110. if (!handler->err_handler(skb, opt, type, code, offset, info))
  111. break;
  112. }
  113. static const struct inet6_protocol esp6_protocol = {
  114. .handler = xfrm6_esp_rcv,
  115. .err_handler = xfrm6_esp_err,
  116. .flags = INET6_PROTO_NOPOLICY,
  117. };
  118. static const struct inet6_protocol ah6_protocol = {
  119. .handler = xfrm6_ah_rcv,
  120. .err_handler = xfrm6_ah_err,
  121. .flags = INET6_PROTO_NOPOLICY,
  122. };
  123. static const struct inet6_protocol ipcomp6_protocol = {
  124. .handler = xfrm6_ipcomp_rcv,
  125. .err_handler = xfrm6_ipcomp_err,
  126. .flags = INET6_PROTO_NOPOLICY,
  127. };
  128. static struct xfrm_input_afinfo xfrm6_input_afinfo = {
  129. .family = AF_INET6,
  130. .owner = THIS_MODULE,
  131. .callback = xfrm6_rcv_cb,
  132. };
  133. static inline const struct inet6_protocol *netproto(unsigned char protocol)
  134. {
  135. switch (protocol) {
  136. case IPPROTO_ESP:
  137. return &esp6_protocol;
  138. case IPPROTO_AH:
  139. return &ah6_protocol;
  140. case IPPROTO_COMP:
  141. return &ipcomp6_protocol;
  142. }
  143. return NULL;
  144. }
  145. int xfrm6_protocol_register(struct xfrm6_protocol *handler,
  146. unsigned char protocol)
  147. {
  148. struct xfrm6_protocol __rcu **pprev;
  149. struct xfrm6_protocol *t;
  150. bool add_netproto = false;
  151. int ret = -EEXIST;
  152. int priority = handler->priority;
  153. mutex_lock(&xfrm6_protocol_mutex);
  154. if (!rcu_dereference_protected(*proto_handlers(protocol),
  155. lockdep_is_held(&xfrm6_protocol_mutex)))
  156. add_netproto = true;
  157. for (pprev = proto_handlers(protocol);
  158. (t = rcu_dereference_protected(*pprev,
  159. lockdep_is_held(&xfrm6_protocol_mutex))) != NULL;
  160. pprev = &t->next) {
  161. if (t->priority < priority)
  162. break;
  163. if (t->priority == priority)
  164. goto err;
  165. }
  166. handler->next = *pprev;
  167. rcu_assign_pointer(*pprev, handler);
  168. ret = 0;
  169. err:
  170. mutex_unlock(&xfrm6_protocol_mutex);
  171. if (add_netproto) {
  172. if (inet6_add_protocol(netproto(protocol), protocol)) {
  173. pr_err("%s: can't add protocol\n", __func__);
  174. ret = -EAGAIN;
  175. }
  176. }
  177. return ret;
  178. }
  179. EXPORT_SYMBOL(xfrm6_protocol_register);
  180. int xfrm6_protocol_deregister(struct xfrm6_protocol *handler,
  181. unsigned char protocol)
  182. {
  183. struct xfrm6_protocol __rcu **pprev;
  184. struct xfrm6_protocol *t;
  185. int ret = -ENOENT;
  186. mutex_lock(&xfrm6_protocol_mutex);
  187. for (pprev = proto_handlers(protocol);
  188. (t = rcu_dereference_protected(*pprev,
  189. lockdep_is_held(&xfrm6_protocol_mutex))) != NULL;
  190. pprev = &t->next) {
  191. if (t == handler) {
  192. *pprev = handler->next;
  193. ret = 0;
  194. break;
  195. }
  196. }
  197. if (!rcu_dereference_protected(*proto_handlers(protocol),
  198. lockdep_is_held(&xfrm6_protocol_mutex))) {
  199. if (inet6_del_protocol(netproto(protocol), protocol) < 0) {
  200. pr_err("%s: can't remove protocol\n", __func__);
  201. ret = -EAGAIN;
  202. }
  203. }
  204. mutex_unlock(&xfrm6_protocol_mutex);
  205. synchronize_net();
  206. return ret;
  207. }
  208. EXPORT_SYMBOL(xfrm6_protocol_deregister);
  209. int __init xfrm6_protocol_init(void)
  210. {
  211. return xfrm_input_register_afinfo(&xfrm6_input_afinfo);
  212. }
  213. void xfrm6_protocol_fini(void)
  214. {
  215. xfrm_input_unregister_afinfo(&xfrm6_input_afinfo);
  216. }