xfrm6_state.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * xfrm6_state.c: based on xfrm4_state.c
  3. *
  4. * Authors:
  5. * Mitsuru KANDA @USAGI
  6. * Kazunori MIYAZAWA @USAGI
  7. * Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  8. * IPv6 support
  9. * YOSHIFUJI Hideaki @USAGI
  10. * Split up af-specific portion
  11. *
  12. */
  13. #include <net/xfrm.h>
  14. #include <linux/pfkeyv2.h>
  15. #include <linux/ipsec.h>
  16. #include <net/ipv6.h>
  17. static struct xfrm_state_afinfo xfrm6_state_afinfo;
  18. static void
  19. __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
  20. struct xfrm_tmpl *tmpl,
  21. xfrm_address_t *daddr, xfrm_address_t *saddr)
  22. {
  23. /* Initialize temporary selector matching only
  24. * to current session. */
  25. ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
  26. ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
  27. x->sel.dport = xfrm_flowi_dport(fl);
  28. x->sel.dport_mask = ~0;
  29. x->sel.sport = xfrm_flowi_sport(fl);
  30. x->sel.sport_mask = ~0;
  31. x->sel.prefixlen_d = 128;
  32. x->sel.prefixlen_s = 128;
  33. x->sel.proto = fl->proto;
  34. x->sel.ifindex = fl->oif;
  35. x->id = tmpl->id;
  36. if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
  37. memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr));
  38. memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
  39. if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
  40. memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr));
  41. x->props.mode = tmpl->mode;
  42. x->props.reqid = tmpl->reqid;
  43. x->props.family = AF_INET6;
  44. }
  45. static struct xfrm_state *
  46. __xfrm6_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto)
  47. {
  48. unsigned h = __xfrm6_spi_hash(daddr, spi, proto);
  49. struct xfrm_state *x;
  50. list_for_each_entry(x, xfrm6_state_afinfo.state_byspi+h, byspi) {
  51. if (x->props.family == AF_INET6 &&
  52. spi == x->id.spi &&
  53. ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) &&
  54. proto == x->id.proto) {
  55. xfrm_state_hold(x);
  56. return x;
  57. }
  58. }
  59. return NULL;
  60. }
  61. static struct xfrm_state *
  62. __xfrm6_find_acq(u8 mode, u32 reqid, u8 proto,
  63. xfrm_address_t *daddr, xfrm_address_t *saddr,
  64. int create)
  65. {
  66. struct xfrm_state *x, *x0;
  67. unsigned h = __xfrm6_dst_hash(daddr);
  68. x0 = NULL;
  69. list_for_each_entry(x, xfrm6_state_afinfo.state_bydst+h, bydst) {
  70. if (x->props.family == AF_INET6 &&
  71. ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) &&
  72. mode == x->props.mode &&
  73. proto == x->id.proto &&
  74. ipv6_addr_equal((struct in6_addr *)saddr, (struct in6_addr *)x->props.saddr.a6) &&
  75. reqid == x->props.reqid &&
  76. x->km.state == XFRM_STATE_ACQ &&
  77. !x->id.spi) {
  78. x0 = x;
  79. break;
  80. }
  81. }
  82. if (!x0 && create && (x0 = xfrm_state_alloc()) != NULL) {
  83. ipv6_addr_copy((struct in6_addr *)x0->sel.daddr.a6,
  84. (struct in6_addr *)daddr);
  85. ipv6_addr_copy((struct in6_addr *)x0->sel.saddr.a6,
  86. (struct in6_addr *)saddr);
  87. x0->sel.prefixlen_d = 128;
  88. x0->sel.prefixlen_s = 128;
  89. ipv6_addr_copy((struct in6_addr *)x0->props.saddr.a6,
  90. (struct in6_addr *)saddr);
  91. x0->km.state = XFRM_STATE_ACQ;
  92. ipv6_addr_copy((struct in6_addr *)x0->id.daddr.a6,
  93. (struct in6_addr *)daddr);
  94. x0->id.proto = proto;
  95. x0->props.family = AF_INET6;
  96. x0->props.mode = mode;
  97. x0->props.reqid = reqid;
  98. x0->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
  99. xfrm_state_hold(x0);
  100. x0->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
  101. add_timer(&x0->timer);
  102. xfrm_state_hold(x0);
  103. list_add_tail(&x0->bydst, xfrm6_state_afinfo.state_bydst+h);
  104. wake_up(&km_waitq);
  105. }
  106. if (x0)
  107. xfrm_state_hold(x0);
  108. return x0;
  109. }
  110. static struct xfrm_state_afinfo xfrm6_state_afinfo = {
  111. .family = AF_INET6,
  112. .lock = RW_LOCK_UNLOCKED,
  113. .init_tempsel = __xfrm6_init_tempsel,
  114. .state_lookup = __xfrm6_state_lookup,
  115. .find_acq = __xfrm6_find_acq,
  116. };
  117. void __init xfrm6_state_init(void)
  118. {
  119. xfrm_state_register_afinfo(&xfrm6_state_afinfo);
  120. }
  121. void xfrm6_state_fini(void)
  122. {
  123. xfrm_state_unregister_afinfo(&xfrm6_state_afinfo);
  124. }