4fc7f3d56ddd10684aa1d6e5c416d4ba8e3d87f8
[strongswan.git] / src / charon / queues / jobs / send_keepalive_job.c
1 /**
2 * @file send_keepalive_job.c
3 *
4 * @brief Implementation of send_keepalive_job_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23
24 #include <stdlib.h>
25
26 #include "send_keepalive_job.h"
27
28 #include <sa/ike_sa.h>
29 #include <daemon.h>
30
31
32 typedef struct private_send_keepalive_job_t private_send_keepalive_job_t;
33
34 /**
35 * Private data of an send_keepalive_job_t Object
36 */
37 struct private_send_keepalive_job_t {
38 /**
39 * public send_keepalive_job_t interface
40 */
41 send_keepalive_job_t public;
42
43 /**
44 * ID of the IKE_SA which the message belongs to.
45 */
46 ike_sa_id_t *ike_sa_id;
47
48 /**
49 * Logger reference.
50 */
51 logger_t *logger;
52 };
53
54 /**
55 * Implements send_keepalive_job_t.get_type.
56 */
57 static job_type_t get_type(private_send_keepalive_job_t *this)
58 {
59 return SEND_KEEPALIVE;
60 }
61
62 /**
63 * Implementation of job_t.execute.
64 */
65 static status_t execute(private_send_keepalive_job_t *this)
66 {
67 ike_sa_t *ike_sa;
68 status_t status;
69 u_int32_t dt;
70 u_int32_t interval = charon->configuration->get_keepalive_interval(charon->configuration);
71 u_int32_t timeout = charon->configuration->get_keepalive_timeout(charon->configuration);
72 struct timeval last_msg_tv, current_tv;
73 packet_t *packet;
74 host_t *host;
75 connection_t *connection;
76 chunk_t data;
77
78 this->logger->log(this->logger, CONTROL|LEVEL2, "Checking out IKE SA %lld:%lld, role %s",
79 this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
80 this->ike_sa_id->get_responder_spi(this->ike_sa_id),
81 this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
82
83 status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
84 this->ike_sa_id, &ike_sa);
85 if (status != SUCCESS)
86 {
87 this->logger->log(this->logger, ERROR|LEVEL1,
88 "IKE SA could not be checked out. Already deleted?");
89 return DESTROY_ME;
90 }
91
92 last_msg_tv = ike_sa->get_last_msg_tv(ike_sa);
93 if (0 > gettimeofday(&current_tv, NULL) )
94 {
95 this->logger->log(this->logger, ERROR|LEVEL1,
96 "Warning: Failed to get time of day.");
97 }
98 dt = (current_tv.tv_sec - last_msg_tv.tv_sec) * 1000
99 + (current_tv.tv_usec - last_msg_tv.tv_usec) / 1000;
100
101 if (dt >= interval)
102 {
103 packet = packet_create();
104 connection = ike_sa->get_connection(ike_sa);
105 host = connection->get_my_host(connection);
106 packet->set_source(packet, host->clone(host));
107 host = connection->get_other_host(connection);
108 packet->set_destination(packet, host->clone(host));
109 data = chunk_alloc(1);
110 data.ptr[0] = 0xFF;
111 packet->set_data(packet, data);
112 charon->send_queue->add(charon->send_queue, packet);
113 dt = 0;
114 this->logger->log(this->logger, CONTROL|LEVEL1,
115 "NAT keepalive packet scheduled");
116 }
117 charon->event_queue->add_relative(charon->event_queue,
118 (job_t*) this, interval - dt);
119
120 this->logger->log(this->logger, CONTROL|LEVEL2,
121 "Checkin IKE SA %lld:%lld, role %s",
122 this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
123 this->ike_sa_id->get_responder_spi(this->ike_sa_id),
124 this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
125
126 status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
127 if (status != SUCCESS)
128 {
129 this->logger->log(this->logger, ERROR, "Checkin of IKE SA failed!");
130 }
131
132 return SUCCESS;
133 }
134
135 /**
136 * Implements job_t.destroy.
137 */
138 static void destroy(private_send_keepalive_job_t *this)
139 {
140 this->ike_sa_id->destroy(this->ike_sa_id);
141 free(this);
142 }
143
144 /*
145 * Described in header
146 */
147 send_keepalive_job_t *send_keepalive_job_create(ike_sa_id_t *ike_sa_id)
148 {
149 private_send_keepalive_job_t *this = malloc_thing(private_send_keepalive_job_t);
150
151 /* interface functions */
152 this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
153 this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
154 this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
155
156 /* public functions */
157 this->public.destroy = (void (*)(send_keepalive_job_t *)) destroy;
158
159 /* private variables */
160 this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
161 this->logger = logger_manager->get_logger(logger_manager, WORKER);
162
163 return &(this->public);
164 }