当前位置:   article > 正文

strongswan ipsec 向内核下发SA和Policy部分_libstrongswan

libstrongswan

目录

kernel_netlink插件

插件初始化

add_sa和add_policy


kernel_netlink插件

strongswan ipsec 向内核下发SA和Policy部分可以是kernel_netlink插件的方式实现的。

其他的插件有:

Plugin NameDescription
kernel-libipsecIPsec "kernel" interface in user-space using libipsec
kernel-netlinkIPsec/Networking kernel interface using Linux Netlink
kernel-pfkeyIPsec kernel interface using PF_KEY
kernel-wfpIPsec backend for the Windows platform, using the Windows Filtering Platform

libstrongswan/plugins/plugin_loader.c里面会将指定路径下的库文件当做strongswan的插件来加载,所以strongswan会把kernel_netlink编译成库文件,libcharon/Makefile文件中关键内容如下:

Makefile

  1. am__append_108 = plugins/kernel_netlink
  2. #am__append_109 = plugins/kernel_netlink/libstrongswan-kernel-netlink.la
  3. /* file: libcharon/Makefile */

 Makeifle.am

  1. if USE_KERNEL_NETLINK
  2. SUBDIRS += plugins/kernel_netlink
  3. if MONOLITHIC
  4. libcharon_la_LIBADD += plugins/kernel_netlink/libstrongswan-kernel-netlink.la
  5. endif
  6. endif

 根据上述Makefile编译生成的libstrongswan-kernel-netlink.so文件如下:

  1. strongswan$ grep kernel_netlink_plugin_create . -r
  2. Binary file ./src/libcharon/plugins/kernel_netlink/.libs/libstrongswan-kernel-netlink.so matches
  3. Binary file ./src/libcharon/plugins/kernel_netlink/.libs/kernel_netlink_plugin.o matches
  4. ./src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c:plugin_t *kernel_netlink_plugin_create()

 libstrongswan/plugins/plugin_loader.c文件中 _load_plugins函数会遍历路径下的库文件来加载kenel-netlink插件。

  1. METHOD(plugin_loader_t, load_plugins, bool, private_plugin_loader_t *this, char *list);
  2. plugin_loader_t *plugin_loader_create()
  3. {
  4. private_plugin_loader_t *this;
  5. INIT(this,
  6. .public = {
  7. .add_static_features = _add_static_features,
  8. .load = _load_plugins,
  9. .add_path = _add_path,
  10. .reload = _reload,
  11. .unload = _unload,
  12. .create_plugin_enumerator = _create_plugin_enumerator,
  13. .has_feature = _has_feature,
  14. .loaded_plugins = _loaded_plugins,
  15. .status = _status,
  16. .destroy = _destroy,
  17. },
  18. .plugins = linked_list_create(),
  19. .loaded = linked_list_create(),
  20. .features = hashlist_create(
  21. (hashtable_hash_t)registered_feature_hash,
  22. (hashtable_equals_t)registered_feature_equals, 64),
  23. .get_features = dlsym(RTLD_DEFAULT, "plugin_loader_feature_filter"),
  24. );
  25. if (!this->get_features)
  26. {
  27. this->get_features = get_features_default;
  28. }
  29. return &this->public;
  30. }
  31. /* file: libstrongswan/plugins/plugin_loader.c */

插件初始化

插件注册函数为kernel_ipsec_register();

  1. # grep kernel_ipsec_register . -r
  2. ./plugins/kernel_wfp/kernel_wfp_plugin.c: PLUGIN_CALLBACK(kernel_ipsec_register, kernel_wfp_ipsec_create),
  3. ./plugins/load_tester/load_tester_plugin.c: PLUGIN_CALLBACK(kernel_ipsec_register, load_tester_ipsec_create),
  4. ./plugins/kernel_pfkey/kernel_pfkey_plugin.c: PLUGIN_CALLBACK(kernel_ipsec_register, kernel_pfkey_ipsec_create),
  5. ./plugins/kernel_netlink/kernel_netlink_plugin.c: PLUGIN_CALLBACK(kernel_ipsec_register, kernel_netlink_ipsec_create),
  6. ./plugins/kernel_libipsec/kernel_libipsec_plugin.c: PLUGIN_CALLBACK(kernel_ipsec_register, kernel_libipsec_ipsec_create),
  7. ./kernel/kernel_ipsec.c:bool kernel_ipsec_register(plugin_t *plugin, plugin_feature_t *feature,
  8. ./kernel/kernel_ipsec.h:bool kernel_ipsec_register(plugin_t *plugin, plugin_feature_t *feature,

 kernel_netlink插件中关键函数为kernel_netlink_plugin_create();

  1. METHOD(plugin_t, get_features, int,
  2. private_kernel_netlink_plugin_t *this, plugin_feature_t *features[])
  3. {
  4. static plugin_feature_t f[] = {
  5. PLUGIN_CALLBACK(kernel_ipsec_register, kernel_netlink_ipsec_create),
  6. PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
  7. PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create),
  8. PLUGIN_PROVIDE(CUSTOM, "kernel-net"),
  9. };
  10. *features = f;
  11. return countof(f);
  12. }
  13. plugin_t *kernel_netlink_plugin_create()
  14. {
  15. private_kernel_netlink_plugin_t *this;
  16. ......
  17. INIT(this,
  18. .public = {
  19. .plugin = {
  20. .get_name = _get_name,
  21. .get_features = _get_features,
  22. .reload = _reload,
  23. .destroy = _destroy,
  24. },
  25. },
  26. );
  27. reload(this);
  28. return &this->public.plugin;
  29. }
  30. /* file: libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c */

 kernel_netlink_ipsec_create会对SA和Policy的管理接口初始化并初始化xfrm的用户态socket。

  1. kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
  2. {
  3. private_kernel_netlink_ipsec_t *this;
  4. bool register_for_events = TRUE;
  5. INIT(this,
  6. .public = {
  7. .interface = {
  8. .get_features = _get_features,
  9. .get_spi = _get_spi,
  10. .get_cpi = _get_cpi,
  11. .add_sa = _add_sa,
  12. .update_sa = _update_sa,
  13. .query_sa = _query_sa,
  14. .del_sa = _del_sa,
  15. .flush_sas = _flush_sas,
  16. .add_policy = _add_policy,
  17. .query_policy = _query_policy,
  18. .del_policy = _del_policy,
  19. .flush_policies = _flush_policies,
  20. .bypass_socket = _bypass_socket,
  21. .enable_udp_decap = _enable_udp_decap,
  22. .destroy = _destroy,
  23. },
  24. },
  25. .policies = hashtable_create((hashtable_hash_t)policy_hash,
  26. (hashtable_equals_t)policy_equals, 32),
  27. .sas = hashtable_create((hashtable_hash_t)ipsec_sa_hash,
  28. (hashtable_equals_t)ipsec_sa_equals, 32),
  29. .bypass = array_create(sizeof(bypass_t), 0),
  30. .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
  31. .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
  32. .get_priority = dlsym(RTLD_DEFAULT,
  33. "kernel_netlink_get_priority_custom"),
  34. .policy_update = lib->settings->get_bool(lib->settings,
  35. "%s.plugins.kernel-netlink.policy_update", FALSE, lib->ns),
  36. .install_routes = lib->settings->get_bool(lib->settings,
  37. "%s.install_routes", TRUE, lib->ns),
  38. .proto_port_transport = lib->settings->get_bool(lib->settings,
  39. "%s.plugins.kernel-netlink.set_proto_port_transport_sa",
  40. FALSE, lib->ns),
  41. );
  42. if (streq(lib->ns, "starter"))
  43. { /* starter has no threads, so we do not register for kernel events */
  44. register_for_events = FALSE;
  45. }
  46. this->socket_xfrm = netlink_socket_create(NETLINK_XFRM, xfrm_msg_names,
  47. lib->settings->get_bool(lib->settings,
  48. "%s.plugins.kernel-netlink.parallel_xfrm", FALSE, lib->ns));
  49. if (!this->socket_xfrm)
  50. {
  51. destroy(this);
  52. return NULL;
  53. }
  54. setup_spd_hash_thresh(this, "ipv4", XFRMA_SPD_IPV4_HTHRESH, 32);
  55. setup_spd_hash_thresh(this, "ipv6", XFRMA_SPD_IPV6_HTHRESH, 128);
  56. if (register_for_events)
  57. {
  58. struct sockaddr_nl addr;
  59. memset(&addr, 0, sizeof(addr));
  60. addr.nl_family = AF_NETLINK;
  61. /* create and bind XFRM socket for ACQUIRE, EXPIRE, MIGRATE & MAPPING */
  62. this->socket_xfrm_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
  63. if (this->socket_xfrm_events <= 0)
  64. {
  65. DBG1(DBG_KNL, "unable to create XFRM event socket: %s (%d)",
  66. strerror(errno), errno);
  67. destroy(this);
  68. return NULL;
  69. }
  70. addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) |
  71. XFRMNLGRP(MIGRATE) | XFRMNLGRP(MAPPING);
  72. if (bind(this->socket_xfrm_events, (struct sockaddr*)&addr, sizeof(addr)))
  73. {
  74. DBG1(DBG_KNL, "unable to bind XFRM event socket: %s (%d)",
  75. strerror(errno), errno);
  76. destroy(this);
  77. return NULL;
  78. }
  79. lib->watcher->add(lib->watcher, this->socket_xfrm_events, WATCHER_READ,
  80. (watcher_cb_t)receive_events, this);
  81. }
  82. netlink_find_offload_feature(lib->settings->get_str(lib->settings,
  83. "%s.plugins.kernel-netlink.hw_offload_feature_interface",
  84. "lo", lib->ns));
  85. return &this->public;
  86. }
  87. /* file: libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c */

add_sa和add_policy

_add_sa();的实现函数为,根据SA数据,组装成NetLink消息体下发给内核

  1. METHOD(kernel_ipsec_t, add_sa, status_t,
  2. private_kernel_netlink_ipsec_t *this, kernel_ipsec_sa_id_t *id,
  3. kernel_ipsec_add_sa_t *data)
  4. {
  5. netlink_buf_t request;
  6. const char *alg_name;
  7. char markstr[32] = "";
  8. struct nlmsghdr *hdr;
  9. struct xfrm_usersa_info *sa;
  10. uint16_t icv_size = 64, ipcomp = data->ipcomp;
  11. ipsec_mode_t mode = data->mode, original_mode = data->mode;
  12. traffic_selector_t *first_src_ts, *first_dst_ts;
  13. status_t status = FAILED;
  14. .......
  15. memset(&request, 0, sizeof(request));
  16. format_mark(markstr, sizeof(markstr), id->mark);
  17. ......
  18. hdr = &request.hdr;
  19. hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
  20. hdr->nlmsg_type = data->update ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
  21. hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
  22. sa = NLMSG_DATA(hdr);
  23. host2xfrm(id->src, &sa->saddr);
  24. host2xfrm(id->dst, &sa->id.daddr);
  25. sa->id.spi = id->spi;
  26. sa->id.proto = id->proto;
  27. sa->family = id->src->get_family(id->src);
  28. sa->mode = mode2kernel(mode);
  29. if (!data->copy_df)
  30. {
  31. sa->flags |= XFRM_STATE_NOPMTUDISC;
  32. }
  33. if (!data->copy_ecn)
  34. {
  35. sa->flags |= XFRM_STATE_NOECN;
  36. }
  37. if (data->inbound)
  38. {
  39. switch (data->copy_dscp)
  40. {
  41. case DSCP_COPY_YES:
  42. case DSCP_COPY_IN_ONLY:
  43. sa->flags |= XFRM_STATE_DECAP_DSCP;
  44. break;
  45. default:
  46. break;
  47. }
  48. }
  49. else
  50. {
  51. switch (data->copy_dscp)
  52. {
  53. case DSCP_COPY_IN_ONLY:
  54. case DSCP_COPY_NO:
  55. {
  56. /* currently the only extra flag */
  57. if (!add_uint32(hdr, sizeof(request), XFRMA_SA_EXTRA_FLAGS,
  58. XFRM_SA_XFLAG_DONT_ENCAP_DSCP))
  59. {
  60. goto failed;
  61. }
  62. break;
  63. }
  64. default:
  65. break;
  66. }
  67. }
  68. switch (mode)
  69. {
  70. case MODE_TUNNEL:
  71. sa->flags |= XFRM_STATE_AF_UNSPEC;
  72. break;
  73. case MODE_BEET:
  74. case MODE_TRANSPORT:
  75. if (original_mode == MODE_TUNNEL)
  76. { /* don't install selectors for switched SAs. because only one
  77. * selector can be installed other traffic would get dropped */
  78. break;
  79. }
  80. if (data->src_ts->get_first(data->src_ts,
  81. (void**)&first_src_ts) == SUCCESS &&
  82. data->dst_ts->get_first(data->dst_ts,
  83. (void**)&first_dst_ts) == SUCCESS)
  84. {
  85. sa->sel = ts2selector(first_src_ts, first_dst_ts,
  86. data->interface);
  87. if (!this->proto_port_transport)
  88. {
  89. /* don't install proto/port on SA. This would break
  90. * potential secondary SAs for the same address using a
  91. * different prot/port. */
  92. sa->sel.proto = 0;
  93. sa->sel.dport = sa->sel.dport_mask = 0;
  94. sa->sel.sport = sa->sel.sport_mask = 0;
  95. }
  96. }
  97. break;
  98. default:
  99. break;
  100. }
  101. if (id->proto == IPPROTO_AH && sa->family == AF_INET)
  102. { /* use alignment to 4 bytes for IPv4 instead of the incorrect 8 byte
  103. * alignment that's used by default but is only valid for IPv6 */
  104. sa->flags |= XFRM_STATE_ALIGN4;
  105. }
  106. sa->reqid = data->reqid;
  107. sa->lft.soft_byte_limit = XFRM_LIMIT(data->lifetime->bytes.rekey);
  108. sa->lft.hard_byte_limit = XFRM_LIMIT(data->lifetime->bytes.life);
  109. sa->lft.soft_packet_limit = XFRM_LIMIT(data->lifetime->packets.rekey);
  110. sa->lft.hard_packet_limit = XFRM_LIMIT(data->lifetime->packets.life);
  111. /* we use lifetimes since added, not since used */
  112. sa->lft.soft_add_expires_seconds = data->lifetime->time.rekey;
  113. sa->lft.hard_add_expires_seconds = data->lifetime->time.life;
  114. sa->lft.soft_use_expires_seconds = 0;
  115. sa->lft.hard_use_expires_seconds = 0;
  116. switch (data->enc_alg)
  117. {
  118. case ENCR_UNDEFINED:
  119. /* no encryption */
  120. break;
  121. case ENCR_AES_CCM_ICV16:
  122. case ENCR_AES_GCM_ICV16:
  123. case ENCR_NULL_AUTH_AES_GMAC:
  124. case ENCR_CAMELLIA_CCM_ICV16:
  125. case ENCR_CHACHA20_POLY1305:
  126. icv_size += 32;
  127. /* FALL */
  128. case ENCR_AES_CCM_ICV12:
  129. case ENCR_AES_GCM_ICV12:
  130. case ENCR_CAMELLIA_CCM_ICV12:
  131. icv_size += 32;
  132. /* FALL */
  133. case ENCR_AES_CCM_ICV8:
  134. case ENCR_AES_GCM_ICV8:
  135. case ENCR_CAMELLIA_CCM_ICV8:
  136. {
  137. struct xfrm_algo_aead *algo;
  138. alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, data->enc_alg);
  139. if (alg_name == NULL)
  140. {
  141. DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
  142. encryption_algorithm_names, data->enc_alg);
  143. goto failed;
  144. }
  145. DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
  146. encryption_algorithm_names, data->enc_alg,
  147. data->enc_key.len * 8);
  148. algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AEAD,
  149. sizeof(*algo) + data->enc_key.len);
  150. if (!algo)
  151. {
  152. goto failed;
  153. }
  154. algo->alg_key_len = data->enc_key.len * 8;
  155. algo->alg_icv_len = icv_size;
  156. strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
  157. algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
  158. memcpy(algo->alg_key, data->enc_key.ptr, data->enc_key.len);
  159. break;
  160. }
  161. default:
  162. {
  163. struct xfrm_algo *algo;
  164. alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, data->enc_alg);
  165. if (alg_name == NULL)
  166. {
  167. DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
  168. encryption_algorithm_names, data->enc_alg);
  169. goto failed;
  170. }
  171. DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
  172. encryption_algorithm_names, data->enc_alg,
  173. data->enc_key.len * 8);
  174. algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_CRYPT,
  175. sizeof(*algo) + data->enc_key.len);
  176. if (!algo)
  177. {
  178. goto failed;
  179. }
  180. algo->alg_key_len = data->enc_key.len * 8;
  181. strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
  182. algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
  183. memcpy(algo->alg_key, data->enc_key.ptr, data->enc_key.len);
  184. }
  185. }
  186. if (data->int_alg != AUTH_UNDEFINED)
  187. {
  188. u_int trunc_len = 0;
  189. alg_name = lookup_algorithm(INTEGRITY_ALGORITHM, data->int_alg);
  190. if (alg_name == NULL)
  191. {
  192. DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
  193. integrity_algorithm_names, data->int_alg);
  194. goto failed;
  195. }
  196. DBG2(DBG_KNL, " using integrity algorithm %N with key size %d",
  197. integrity_algorithm_names, data->int_alg, data->int_key.len * 8);
  198. switch (data->int_alg)
  199. {
  200. case AUTH_HMAC_MD5_128:
  201. case AUTH_HMAC_SHA2_256_128:
  202. trunc_len = 128;
  203. break;
  204. case AUTH_HMAC_SHA1_160:
  205. trunc_len = 160;
  206. break;
  207. case AUTH_HMAC_SHA2_256_256:
  208. trunc_len = 256;
  209. break;
  210. case AUTH_HMAC_SHA2_384_384:
  211. trunc_len = 384;
  212. break;
  213. case AUTH_HMAC_SHA2_512_512:
  214. trunc_len = 512;
  215. break;
  216. default:
  217. break;
  218. }
  219. ......
  220. if (data->encap)
  221. {
  222. struct xfrm_encap_tmpl *tmpl;
  223. tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
  224. if (!tmpl)
  225. {
  226. goto failed;
  227. }
  228. tmpl->encap_type = UDP_ENCAP_ESPINUDP;
  229. tmpl->encap_sport = htons(id->src->get_port(id->src));
  230. tmpl->encap_dport = htons(id->dst->get_port(id->dst));
  231. memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
  232. /* encap_oa could probably be derived from the
  233. * traffic selectors [rfc4306, p39]. In the netlink kernel
  234. * implementation pluto does the same as we do here but it uses
  235. * encap_oa in the pfkey implementation.
  236. * BUT as /usr/src/linux/net/key/af_key.c indicates the kernel ignores
  237. * it anyway
  238. * -> does that mean that NAT-T encap doesn't work in transport mode?
  239. * No. The reason the kernel ignores NAT-OA is that it recomputes
  240. * (or, rather, just ignores) the checksum. If packets pass the IPsec
  241. * checks it marks them "checksum ok" so OA isn't needed. */
  242. }
  243. if (id->if_id && !add_uint32(hdr, sizeof(request), XFRMA_IF_ID, id->if_id))
  244. {
  245. goto failed;
  246. }
  247. if (data->tfc && id->proto == IPPROTO_ESP && mode == MODE_TUNNEL)
  248. { /* the kernel supports TFC padding only for tunnel mode ESP SAs */
  249. if (!add_uint32(hdr, sizeof(request), XFRMA_TFCPAD, data->tfc))
  250. {
  251. goto failed;
  252. }
  253. }
  254. ......
  255. status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
  256. if (status == NOT_FOUND && data->update)
  257. {
  258. DBG1(DBG_KNL, "allocated SPI not found anymore, try to add SAD entry");
  259. hdr->nlmsg_type = XFRM_MSG_NEWSA;
  260. status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
  261. }
  262. ......
  263. status = SUCCESS;
  264. failed:
  265. memwipe(&request, sizeof(request));
  266. return status;
  267. }
  268. /* file: libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c */

_add_policy的实现函数为,函数中会调用add_policy_internal();最终通过NeiLink message来向内核下发policy。

  1. METHOD(kernel_ipsec_t, add_policy, status_t,
  2. private_kernel_netlink_ipsec_t *this, kernel_ipsec_policy_id_t *id,
  3. kernel_ipsec_manage_policy_t *data)
  4. {
  5. policy_entry_t *policy, *current;
  6. policy_sa_t *assigned_sa, *current_sa;
  7. enumerator_t *enumerator;
  8. bool found = FALSE, update = TRUE;
  9. char markstr[32] = "";
  10. uint32_t cur_priority = 0;
  11. int use_count;
  12. /* create a policy */
  13. INIT(policy,
  14. .sel = ts2selector(id->src_ts, id->dst_ts, id->interface),
  15. .mark = id->mark.value & id->mark.mask,
  16. .if_id = id->if_id,
  17. .direction = id->dir,
  18. .reqid = data->sa->reqid,
  19. );
  20. format_mark(markstr, sizeof(markstr), id->mark);
  21. /* find the policy, which matches EXACTLY */
  22. this->mutex->lock(this->mutex);
  23. current = this->policies->get(this->policies, policy);
  24. if (current)
  25. {
  26. if (current->reqid && data->sa->reqid &&
  27. current->reqid != data->sa->reqid)
  28. {
  29. DBG1(DBG_CFG, "unable to install policy %R === %R %N%s for reqid "
  30. "%u, the same policy for reqid %u exists",
  31. id->src_ts, id->dst_ts, policy_dir_names, id->dir, markstr,
  32. data->sa->reqid, current->reqid);
  33. policy_entry_destroy(this, policy);
  34. this->mutex->unlock(this->mutex);
  35. return INVALID_STATE;
  36. }
  37. /* use existing policy */
  38. DBG2(DBG_KNL, "policy %R === %R %N%s already exists, increasing "
  39. "refcount", id->src_ts, id->dst_ts, policy_dir_names, id->dir,
  40. markstr);
  41. policy_entry_destroy(this, policy);
  42. policy = current;
  43. found = TRUE;
  44. policy->waiting++;
  45. while (policy->working)
  46. {
  47. this->condvar->wait(this->condvar, this->mutex);
  48. }
  49. policy->waiting--;
  50. policy->working = TRUE;
  51. }
  52. else
  53. { /* use the new one, if we have no such policy */
  54. policy->used_by = linked_list_create();
  55. this->policies->put(this->policies, policy, policy);
  56. }
  57. /* cache the assigned IPsec SA */
  58. assigned_sa = policy_sa_create(this, id->dir, data->type, data->src,
  59. data->dst, id->src_ts, id->dst_ts, id->mark,
  60. id->if_id, data->sa);
  61. assigned_sa->auto_priority = get_priority(policy, data->prio, id->interface);
  62. assigned_sa->priority = this->get_priority ? this->get_priority(id, data)
  63. : data->manual_prio;
  64. assigned_sa->priority = assigned_sa->priority ?: assigned_sa->auto_priority;
  65. /* insert the SA according to its priority */
  66. enumerator = policy->used_by->create_enumerator(policy->used_by);
  67. while (enumerator->enumerate(enumerator, (void**)&current_sa))
  68. {
  69. if (current_sa->priority > assigned_sa->priority)
  70. {
  71. break;
  72. }
  73. if (current_sa->priority == assigned_sa->priority)
  74. {
  75. /* in case of equal manual prios order SAs by automatic priority */
  76. if (current_sa->auto_priority > assigned_sa->auto_priority)
  77. {
  78. break;
  79. }
  80. /* prefer SAs with a reqid over those without */
  81. if (current_sa->auto_priority == assigned_sa->auto_priority &&
  82. (!current_sa->sa->cfg.reqid || assigned_sa->sa->cfg.reqid))
  83. {
  84. break;
  85. }
  86. }
  87. if (update)
  88. {
  89. cur_priority = current_sa->priority;
  90. update = FALSE;
  91. }
  92. }
  93. policy->used_by->insert_before(policy->used_by, enumerator, assigned_sa);
  94. enumerator->destroy(enumerator);
  95. use_count = policy->used_by->get_count(policy->used_by);
  96. if (!update)
  97. { /* we don't update the policy if the priority is lower than that of
  98. * the currently installed one */
  99. policy_change_done(this, policy);
  100. DBG2(DBG_KNL, "not updating policy %R === %R %N%s [priority %u, "
  101. "refcount %d]", id->src_ts, id->dst_ts, policy_dir_names,
  102. id->dir, markstr, cur_priority, use_count);
  103. return SUCCESS;
  104. }
  105. policy->reqid = assigned_sa->sa->cfg.reqid;
  106. if (this->policy_update)
  107. {
  108. found = TRUE;
  109. }
  110. DBG2(DBG_KNL, "%s policy %R === %R %N%s [priority %u, refcount %d]",
  111. found ? "updating" : "adding", id->src_ts, id->dst_ts,
  112. policy_dir_names, id->dir, markstr, assigned_sa->priority, use_count);
  113. if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS)
  114. {
  115. DBG1(DBG_KNL, "unable to %s policy %R === %R %N%s",
  116. found ? "update" : "add", id->src_ts, id->dst_ts,
  117. policy_dir_names, id->dir, markstr);
  118. return FAILED;
  119. }
  120. return SUCCESS;
  121. }
  122. /* file: libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c */

参考资料:

[ipsec][strongswan] strongswan源码分析--(一)SA整体分析 - toong - 博客园 (cnblogs.com)icon-default.png?t=M276https://www.cnblogs.com/hugetong/p/11143366.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/805286
推荐阅读
相关标签
  

闽ICP备14008679号