9c0e2602b44cde6068c7bd08e70d8928254dd563
[strongswan.git] / src / libcharon / kernel / kernel_handler.c
1 /*
2 * Copyright (C) 2010 Tobias Brunner
3 * 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
16 #include "kernel_handler.h"
17
18 #include <hydra.h>
19 #include <daemon.h>
20 #include <processing/jobs/acquire_job.h>
21 #include <processing/jobs/delete_child_sa_job.h>
22 #include <processing/jobs/migrate_job.h>
23 #include <processing/jobs/rekey_child_sa_job.h>
24 #include <processing/jobs/roam_job.h>
25 #include <processing/jobs/update_sa_job.h>
26
27 typedef struct private_kernel_handler_t private_kernel_handler_t;
28
29 /**
30 * Private data of a kernel_handler_t object.
31 */
32 struct private_kernel_handler_t {
33
34 /**
35 * Public part of kernel_handler_t object.
36 */
37 kernel_handler_t public;
38 };
39
40 /**
41 * convert an IP protocol identifier to the IKEv2 specific protocol identifier.
42 */
43 static inline protocol_id_t proto_ip2ike(u_int8_t protocol)
44 {
45 switch (protocol)
46 {
47 case IPPROTO_ESP:
48 return PROTO_ESP;
49 case IPPROTO_AH:
50 return PROTO_AH;
51 default:
52 return protocol;
53 }
54 }
55
56 METHOD(kernel_listener_t, acquire, bool,
57 private_kernel_handler_t *this, u_int32_t reqid,
58 traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
59 {
60 if (src_ts && dst_ts)
61 {
62 DBG1(DBG_KNL, "creating acquire job for policy %R === %R with "
63 "reqid {%u}", src_ts, dst_ts, reqid);
64 }
65 else
66 {
67 DBG1(DBG_KNL, "creating acquire job for policy with reqid {%u}", reqid);
68 }
69 lib->processor->queue_job(lib->processor,
70 (job_t*)acquire_job_create(reqid, src_ts, dst_ts));
71 return TRUE;
72 }
73
74 METHOD(kernel_listener_t, expire, bool,
75 private_kernel_handler_t *this, u_int8_t protocol, u_int32_t spi,
76 host_t *dst, bool hard)
77 {
78 protocol_id_t proto = proto_ip2ike(protocol);
79
80 DBG1(DBG_KNL, "creating %s job for CHILD_SA %N/0x%08x/%H",
81 hard ? "delete" : "rekey", protocol_id_names, proto, ntohl(spi), dst);
82
83 if (hard)
84 {
85 lib->processor->queue_job(lib->processor,
86 (job_t*)delete_child_sa_job_create(proto, spi, dst, hard));
87 }
88 else
89 {
90 lib->processor->queue_job(lib->processor,
91 (job_t*)rekey_child_sa_job_create(proto, spi, dst));
92 }
93 return TRUE;
94 }
95
96 METHOD(kernel_listener_t, mapping, bool,
97 private_kernel_handler_t *this, u_int8_t protocol, u_int32_t spi,
98 host_t *dst, host_t *remote)
99 {
100 protocol_id_t proto = proto_ip2ike(protocol);
101
102 DBG1(DBG_KNL, "NAT mappings of CHILD_SA %N/0x%08x/%H changed to %#H, "
103 "queuing update job", protocol_id_names, proto, ntohl(spi), dst,
104 remote);
105
106 lib->processor->queue_job(lib->processor,
107 (job_t*)update_sa_job_create(proto, spi, dst, remote));
108 return TRUE;
109 }
110
111 METHOD(kernel_listener_t, migrate, bool,
112 private_kernel_handler_t *this, u_int32_t reqid,
113 traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
114 policy_dir_t direction, host_t *local, host_t *remote)
115 {
116 DBG1(DBG_KNL, "creating migrate job for policy %R === %R %N with reqid {%u}",
117 src_ts, dst_ts, policy_dir_names, direction, reqid, local);
118
119 lib->processor->queue_job(lib->processor,
120 (job_t*)migrate_job_create(reqid, src_ts, dst_ts,
121 direction, local, remote));
122 return TRUE;
123 }
124
125 METHOD(kernel_listener_t, roam, bool,
126 private_kernel_handler_t *this, bool address)
127 {
128 DBG2(DBG_KNL, "creating roam job %s",
129 address ? "due to address/link change" : "due to route change");
130
131 lib->processor->queue_job(lib->processor, (job_t*)roam_job_create(address));
132 return TRUE;
133 }
134
135 METHOD(kernel_handler_t, destroy, void,
136 private_kernel_handler_t *this)
137 {
138 hydra->kernel_interface->remove_listener(hydra->kernel_interface,
139 &this->public.listener);
140 free(this);
141 }
142
143 kernel_handler_t *kernel_handler_create()
144 {
145 private_kernel_handler_t *this;
146
147 INIT(this,
148 .public = {
149 .listener = {
150 .acquire = _acquire,
151 .expire = _expire,
152 .mapping = _mapping,
153 .migrate = _migrate,
154 .roam = _roam,
155 },
156 .destroy = _destroy,
157 },
158 );
159
160 hydra->kernel_interface->add_listener(hydra->kernel_interface,
161 &this->public.listener);
162
163 return &this->public;
164 }