add priority management for kernel policy
[strongswan.git] / src / charon / queues / jobs / incoming_packet_job.c
1 /**
2 * @file incoming_packet_job.h
3 *
4 * @brief Implementation of incoming_packet_job_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24
25 #include "incoming_packet_job.h"
26
27 #include <daemon.h>
28
29 typedef struct private_incoming_packet_job_t private_incoming_packet_job_t;
30
31 /**
32 * Private data of an incoming_packet_job_t Object
33 */
34 struct private_incoming_packet_job_t {
35 /**
36 * public incoming_packet_job_t interface
37 */
38 incoming_packet_job_t public;
39
40 /**
41 * Assigned packet
42 */
43 packet_t *packet;
44
45 /**
46 * logger
47 */
48 logger_t *logger;
49 };
50
51 /**
52 * Implements job_t.get_type.
53 */
54 static job_type_t get_type(private_incoming_packet_job_t *this)
55 {
56 return INCOMING_PACKET;
57 }
58
59 /**
60 * send a notify back to the sender
61 */
62 static void send_notify_response(private_incoming_packet_job_t *this,
63 message_t *request,
64 notify_type_t type)
65 {
66 notify_payload_t *notify;
67 message_t *response;
68 host_t *src, *dst;
69 packet_t *packet;
70 ike_sa_id_t *ike_sa_id;
71
72 ike_sa_id = request->get_ike_sa_id(request);
73 ike_sa_id = ike_sa_id->clone(ike_sa_id);
74 ike_sa_id->switch_initiator(ike_sa_id);
75
76 response = message_create();
77 dst = request->get_source(request);
78 src = request->get_destination(request);
79 response->set_source(response, src->clone(src));
80 response->set_destination(response, dst->clone(dst));
81 response->set_exchange_type(response, request->get_exchange_type(request));
82 response->set_request(response, FALSE);
83 response->set_message_id(response, 0);
84 response->set_ike_sa_id(response, ike_sa_id);
85 ike_sa_id->destroy(ike_sa_id);
86 notify = notify_payload_create_from_protocol_and_type(PROTO_NONE, type);
87 response->add_payload(response, (payload_t *)notify);
88 /* generation may fail, as most messages need a crypter/signer.
89 * TODO: Use transforms implementing the "NULL" algorithm */
90 if (response->generate(response, NULL, NULL, &packet) != SUCCESS)
91 {
92 response->destroy(response);
93 return;
94 }
95 this->logger->log(this->logger, CONTROL, "sending %s notify",
96 mapping_find(notify_type_m, type));
97 charon->send_queue->add(charon->send_queue, packet);
98 response->destroy(response);
99 return;
100 }
101
102 /**
103 * Implementation of job_t.execute.
104 */
105 static status_t execute(private_incoming_packet_job_t *this)
106 {
107 message_t *message;
108 ike_sa_t *ike_sa;
109 ike_sa_id_t *ike_sa_id;
110 status_t status;
111 host_t *src, *dst;
112
113 message = message_create_from_packet(this->packet->clone(this->packet));
114 src = message->get_source(message);
115 dst = message->get_destination(message);
116 this->logger->log(this->logger, CONTROL, "received packet: from %s[%d] to %s[%d]",
117 src->get_string(src), src->get_port(src),
118 dst->get_string(dst), dst->get_port(dst));
119
120 status = message->parse_header(message);
121 if (status != SUCCESS)
122 {
123 this->logger->log(this->logger, ERROR, "received message with invalid IKE header, ignored");
124 message->destroy(message);
125 return DESTROY_ME;
126 }
127
128 if ((message->get_major_version(message) != IKE_MAJOR_VERSION) ||
129 (message->get_minor_version(message) != IKE_MINOR_VERSION))
130 {
131 this->logger->log(this->logger, ERROR,
132 "received a packet with IKE version %d.%d, not supported",
133 message->get_major_version(message),
134 message->get_minor_version(message));
135 if ((message->get_exchange_type(message) == IKE_SA_INIT) && (message->get_request(message)))
136 {
137 send_notify_response(this, message, INVALID_MAJOR_VERSION);
138 }
139 message->destroy(message);
140 return DESTROY_ME;
141 }
142
143 ike_sa_id = message->get_ike_sa_id(message);
144 ike_sa_id = ike_sa_id->clone(ike_sa_id);
145 ike_sa_id->switch_initiator(ike_sa_id);
146 ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, ike_sa_id);
147 if (ike_sa == NULL)
148 {
149 this->logger->log(this->logger, ERROR,
150 "received packet with SPIs %llx:%llx, but no such IKE_SA",
151 ike_sa_id->get_initiator_spi(ike_sa_id),
152 ike_sa_id->get_responder_spi(ike_sa_id));
153 if (message->get_request(message))
154 {
155 /* TODO: send notify if we have NULL crypters,
156 * see todo in send_notify_response
157 send_notify_response(this, message, INVALID_IKE_SPI); */
158 }
159 ike_sa_id->destroy(ike_sa_id);
160 message->destroy(message);
161 return DESTROY_ME;
162 }
163
164 status = ike_sa->process_message(ike_sa, message);
165 if (status == DESTROY_ME)
166 {
167 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
168 }
169 else
170 {
171 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
172 }
173 ike_sa_id->destroy(ike_sa_id);
174 message->destroy(message);
175 return DESTROY_ME;
176 }
177
178 /**
179 * Implements incoming_packet_job_t.get_packet.
180 */
181 static packet_t* get_packet(private_incoming_packet_job_t *this)
182 {
183 return this->packet;
184 }
185
186 /**
187 * Implements job_t.destroy.
188 */
189 static void destroy(private_incoming_packet_job_t *this)
190 {
191 this->packet->destroy(this->packet);
192 free(this);
193 }
194
195 /*
196 * Described in header
197 */
198 incoming_packet_job_t *incoming_packet_job_create(packet_t *packet)
199 {
200 private_incoming_packet_job_t *this = malloc_thing(private_incoming_packet_job_t);
201
202 /* interface functions */
203 this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
204 this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
205 this->public.job_interface.destroy = (void(*)(job_t*))destroy;
206
207 this->public.get_packet = (packet_t*(*)(incoming_packet_job_t*)) get_packet;
208
209 /* private variables */
210 this->packet = packet;
211 this->logger = logger_manager->get_logger(logger_manager, WORKER);
212
213 return &(this->public);
214 }