inactivity_job.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (C) 2010 Martin Willi
  3. * HSR Hochschule fuer Technik Rapperswil
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  12. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. * for more details.
  14. */
  15. #include "inactivity_job.h"
  16. #include <daemon.h>
  17. typedef struct private_inactivity_job_t private_inactivity_job_t;
  18. /**
  19. * Private data of an inactivity_job_t object.
  20. */
  21. struct private_inactivity_job_t {
  22. /**
  23. * Public inactivity_job_t interface.
  24. */
  25. inactivity_job_t public;
  26. /**
  27. * Unique CHILD_SA identifier to check
  28. */
  29. uint32_t id;
  30. /**
  31. * Inactivity timeout
  32. */
  33. uint32_t timeout;
  34. /**
  35. * Close IKE_SA if last remaining CHILD inactive?
  36. */
  37. bool close_ike;
  38. };
  39. METHOD(job_t, destroy, void,
  40. private_inactivity_job_t *this)
  41. {
  42. free(this);
  43. }
  44. METHOD(job_t, execute, job_requeue_t,
  45. private_inactivity_job_t *this)
  46. {
  47. ike_sa_t *ike_sa;
  48. uint32_t reschedule = 0;
  49. ike_sa = charon->child_sa_manager->checkout_by_id(charon->child_sa_manager,
  50. this->id, NULL);
  51. if (ike_sa)
  52. {
  53. enumerator_t *enumerator;
  54. child_sa_t *child_sa;
  55. uint32_t delete = 0;
  56. protocol_id_t proto = 0;
  57. int children = 0;
  58. status_t status = SUCCESS;
  59. enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
  60. while (enumerator->enumerate(enumerator, &child_sa))
  61. {
  62. if (child_sa->get_unique_id(child_sa) == this->id)
  63. {
  64. time_t in, out, install, diff;
  65. child_sa->get_usestats(child_sa, TRUE, &in, NULL, NULL);
  66. child_sa->get_usestats(child_sa, FALSE, &out, NULL, NULL);
  67. install = child_sa->get_installtime(child_sa);
  68. diff = time_monotonic(NULL) - max(max(in, out), install);
  69. if (diff >= this->timeout)
  70. {
  71. delete = child_sa->get_spi(child_sa, TRUE);
  72. proto = child_sa->get_protocol(child_sa);
  73. }
  74. else
  75. {
  76. reschedule = this->timeout - diff;
  77. }
  78. }
  79. children++;
  80. }
  81. enumerator->destroy(enumerator);
  82. if (delete)
  83. {
  84. if (children == 1 && this->close_ike)
  85. {
  86. DBG1(DBG_JOB, "deleting IKE_SA after %d seconds "
  87. "of CHILD_SA inactivity", this->timeout);
  88. status = ike_sa->delete(ike_sa, FALSE);
  89. }
  90. else
  91. {
  92. DBG1(DBG_JOB, "deleting CHILD_SA after %d seconds "
  93. "of inactivity", this->timeout);
  94. status = ike_sa->delete_child_sa(ike_sa, proto, delete, FALSE);
  95. }
  96. }
  97. if (status == DESTROY_ME)
  98. {
  99. charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
  100. ike_sa);
  101. }
  102. else
  103. {
  104. charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
  105. }
  106. }
  107. if (reschedule)
  108. {
  109. return JOB_RESCHEDULE(reschedule);
  110. }
  111. return JOB_REQUEUE_NONE;
  112. }
  113. METHOD(job_t, get_priority, job_priority_t,
  114. private_inactivity_job_t *this)
  115. {
  116. return JOB_PRIO_MEDIUM;
  117. }
  118. /**
  119. * See header
  120. */
  121. inactivity_job_t *inactivity_job_create(uint32_t unique_id, uint32_t timeout,
  122. bool close_ike)
  123. {
  124. private_inactivity_job_t *this;
  125. INIT(this,
  126. .public = {
  127. .job_interface = {
  128. .execute = _execute,
  129. .get_priority = _get_priority,
  130. .destroy = _destroy,
  131. },
  132. },
  133. .id = unique_id,
  134. .timeout = timeout,
  135. .close_ike = close_ike,
  136. );
  137. return &this->public;
  138. }