summaryrefslogtreecommitdiff
path: root/src/libcharon/kernel/kernel_handler.c
blob: 9c0e2602b44cde6068c7bd08e70d8928254dd563 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
 * Copyright (C) 2010 Tobias Brunner
 * Hochschule fuer Technik Rapperswil
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

#include "kernel_handler.h"

#include <hydra.h>
#include <daemon.h>
#include <processing/jobs/acquire_job.h>
#include <processing/jobs/delete_child_sa_job.h>
#include <processing/jobs/migrate_job.h>
#include <processing/jobs/rekey_child_sa_job.h>
#include <processing/jobs/roam_job.h>
#include <processing/jobs/update_sa_job.h>

typedef struct private_kernel_handler_t private_kernel_handler_t;

/**
 * Private data of a kernel_handler_t object.
 */
struct private_kernel_handler_t {

	/**
	 * Public part of kernel_handler_t object.
	 */
	kernel_handler_t public;
};

/**
 * convert an IP protocol identifier to the IKEv2 specific protocol identifier.
 */
static inline protocol_id_t proto_ip2ike(u_int8_t protocol)
{
	switch (protocol)
	{
		case IPPROTO_ESP:
			return PROTO_ESP;
		case IPPROTO_AH:
			return PROTO_AH;
		default:
			return protocol;
	}
}

METHOD(kernel_listener_t, acquire, bool,
	private_kernel_handler_t *this, u_int32_t reqid,
	traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
{
	if (src_ts && dst_ts)
	{
		DBG1(DBG_KNL, "creating acquire job for policy %R === %R with "
			 "reqid {%u}", src_ts, dst_ts, reqid);
	}
	else
	{
		DBG1(DBG_KNL, "creating acquire job for policy with reqid {%u}", reqid);
	}
	lib->processor->queue_job(lib->processor,
							(job_t*)acquire_job_create(reqid, src_ts, dst_ts));
	return TRUE;
}

METHOD(kernel_listener_t, expire, bool,
	private_kernel_handler_t *this, u_int8_t protocol, u_int32_t spi,
	host_t *dst, bool hard)
{
	protocol_id_t proto = proto_ip2ike(protocol);

	DBG1(DBG_KNL, "creating %s job for CHILD_SA %N/0x%08x/%H",
		 hard ? "delete" : "rekey", protocol_id_names, proto, ntohl(spi), dst);

	if (hard)
	{
		lib->processor->queue_job(lib->processor,
				(job_t*)delete_child_sa_job_create(proto, spi, dst, hard));
	}
	else
	{
		lib->processor->queue_job(lib->processor,
				(job_t*)rekey_child_sa_job_create(proto, spi, dst));
	}
	return TRUE;
}

METHOD(kernel_listener_t, mapping, bool,
	private_kernel_handler_t *this, u_int8_t protocol, u_int32_t spi,
	host_t *dst, host_t *remote)
{
	protocol_id_t proto = proto_ip2ike(protocol);

	DBG1(DBG_KNL, "NAT mappings of CHILD_SA %N/0x%08x/%H changed to %#H, "
		 "queuing update job", protocol_id_names, proto, ntohl(spi), dst,
		 remote);

	lib->processor->queue_job(lib->processor,
						(job_t*)update_sa_job_create(proto, spi, dst, remote));
	return TRUE;
}

METHOD(kernel_listener_t, migrate, bool,
	private_kernel_handler_t *this, u_int32_t reqid,
	traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
	policy_dir_t direction, host_t *local, host_t *remote)
{
	DBG1(DBG_KNL, "creating migrate job for policy %R === %R %N with reqid {%u}",
		 src_ts, dst_ts, policy_dir_names, direction, reqid, local);

	lib->processor->queue_job(lib->processor,
						(job_t*)migrate_job_create(reqid, src_ts, dst_ts,
												   direction, local, remote));
	return TRUE;
}

METHOD(kernel_listener_t, roam, bool,
	private_kernel_handler_t *this, bool address)
{
	DBG2(DBG_KNL, "creating roam job %s",
		 address ? "due to address/link change" : "due to route change");

	lib->processor->queue_job(lib->processor, (job_t*)roam_job_create(address));
	return TRUE;
}

METHOD(kernel_handler_t, destroy, void,
	private_kernel_handler_t *this)
{
	hydra->kernel_interface->remove_listener(hydra->kernel_interface,
											 &this->public.listener);
	free(this);
}

kernel_handler_t *kernel_handler_create()
{
	private_kernel_handler_t *this;

	INIT(this,
		.public = {
			.listener = {
				.acquire = _acquire,
				.expire = _expire,
				.mapping = _mapping,
				.migrate = _migrate,
				.roam = _roam,
			},
			.destroy = _destroy,
		},
	);

	hydra->kernel_interface->add_listener(hydra->kernel_interface,
										  &this->public.listener);

	return &this->public;
}