summaryrefslogtreecommitdiff
path: root/src/charon/sa/ike_sa_manager.h
blob: 3f0752cc856f9f0a736ab6affee949631afd1543 (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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
 * Copyright (C) 2005-2006 Martin Willi
 * Copyright (C) 2005 Jan Hutter
 * 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.
 *
 * $Id: ike_sa_manager.h 4624 2008-11-11 13:11:44Z tobias $
 */

/**
 * @defgroup ike_sa_manager ike_sa_manager
 * @{ @ingroup sa
 */

#ifndef IKE_SA_MANAGER_H_
#define IKE_SA_MANAGER_H_

typedef struct ike_sa_manager_t ike_sa_manager_t;

#include <library.h>
#include <sa/ike_sa.h>
#include <encoding/message.h>
#include <config/peer_cfg.h>

/**
 * The IKE_SA-Manager is responsible for managing all initiated and responded IKE_SA's.
 *
 * To avoid access from multiple threads, IKE_SAs must be checked out from
 * the manager, and checked in after usage. 
 * The manager also handles deletion of SAs.
 *
 * @todo checking of double-checkouts from the same threads would be nice.
 * This could be done by comparing thread-ids via pthread_self()...
 * 
 * @todo Managing of ike_sa_t objects in a hash table instead of linked list.
 */
struct ike_sa_manager_t {
	
	/**
	 * Checkout an existing IKE_SA.
	 * 
	 * @param ike_sa_id			the SA identifier, will be updated
	 * @returns 					
	 * 							- checked out IKE_SA if found
	 * 							- NULL, if specified IKE_SA is not found.
	 */
	ike_sa_t* (*checkout) (ike_sa_manager_t* this, ike_sa_id_t *sa_id);
	
	/**
	 * Create and check out a new IKE_SA.
	 * 
	 * @param initiator			TRUE for initiator, FALSE otherwise
	 * @returns 				created and checked out IKE_SA
	 */
	ike_sa_t* (*checkout_new) (ike_sa_manager_t* this, bool initiator);
	
	/**
	 * Checkout an IKE_SA by a message.
	 * 
	 * In some situations, it is necessary that the manager knows the
	 * message to use for the checkout. This has the following reasons:
	 * 
	 * 1. If the targeted IKE_SA is already processing a message, we do not
	 *    check it out if the message ID is the same.
	 * 2. If it is an IKE_SA_INIT request, we have to check if it is a 
	 *    retransmission. If so, we have to drop the message, we would
	 *    create another unneeded IKE_SA for each retransmitted packet.
	 *
	 * A call to checkout_by_message() returns a (maybe new created) IKE_SA.
	 * If processing the message does not make sense (for the reasons above),
	 * NULL is returned.
	 * 
	 * @param ike_sa_id			the SA identifier, will be updated
	 * @returns 					
	 * 							- checked out/created IKE_SA
	 * 							- NULL to not process message further
	 */
	ike_sa_t* (*checkout_by_message) (ike_sa_manager_t* this, message_t *message);
	
	/**
	 * Checkout an IKE_SA for initiation by a peer_config.
	 *
	 * To initiate, a CHILD_SA may be established within an existing IKE_SA.
	 * This call checks for an existing IKE_SA by comparing the configuration.
	 * If the CHILD_SA can be created in an existing IKE_SA, the matching SA
	 * is returned.
	 * If no IKE_SA is found, a new one is created. This is also the case when
	 * the found IKE_SA is in the DELETING state.
	 *
	 * @param peer_cfg			configuration used to find an existing IKE_SA
	 * @return					checked out/created IKE_SA
	 */
	ike_sa_t* (*checkout_by_config) (ike_sa_manager_t* this,
								 	 peer_cfg_t *peer_cfg);
	
	/**
	 * Check out a duplicate if ike_sa to do uniqueness tests.
	 *
	 * @param ike_sa			ike_sa to get a duplicate from
	 * @return					checked out duplicate
	 */
	ike_sa_t* (*checkout_duplicate)(ike_sa_manager_t *this, ike_sa_t *ike_sa);
	
	/**
	 * Check out an IKE_SA a unique ID.
	 *
	 * Every IKE_SA and every CHILD_SA is uniquely identified by an ID. 
	 * These checkout function uses, depending
	 * on the child parameter, the unique ID of the IKE_SA or the reqid
	 * of one of a IKE_SAs CHILD_SA.
	 *
	 * @param id				unique ID of the object
	 * @param child				TRUE to use CHILD, FALSE to use IKE_SA
	 * @return
	 * 							- checked out IKE_SA, if found
	 * 							- NULL, if not found
	 */
	ike_sa_t* (*checkout_by_id) (ike_sa_manager_t* this, u_int32_t id,
								 bool child);
	
	/**
	 * Check out an IKE_SA by the policy/connection name.
	 *
	 * Check out the IKE_SA by the connections name or by a CHILD_SAs policy
	 * name.
	 *
	 * @param name				name of the connection/policy
	 * @param child				TRUE to use policy name, FALSE to use conn name
	 * @return
	 * 							- checked out IKE_SA, if found
	 * 							- NULL, if not found
	 */
	ike_sa_t* (*checkout_by_name) (ike_sa_manager_t* this, char *name,
								   bool child);
	
	/**
	 * Create an enumerator over all stored IKE_SAs.
	 *
	 * The avoid synchronization issues, the enumerator locks access
	 * to the manager exclusively, until it gets destroyed.
	 *
	 * @return					enumerator over all IKE_SAs.
	 */
	enumerator_t *(*create_enumerator) (ike_sa_manager_t* this);
	
	/**
	 * Checkin the SA after usage.
	 * 
	 * @warning the SA pointer MUST NOT be used after checkin! 
	 * The SA must be checked out again!
	 *  
	 * @param ike_sa_id			the SA identifier, will be updated
	 * @param ike_sa			checked out SA
	 * @returns 				
	 * 							- SUCCESS if checked in
	 * 							- NOT_FOUND when not found (shouldn't happen!)
	 */
	status_t (*checkin) (ike_sa_manager_t* this, ike_sa_t *ike_sa);
	
	/**
	 * Destroy a checked out SA.
	 *
	 * The IKE SA is destroyed without notification of the remote peer.
	 * Use this only if the other peer doesn't respond or behaves not
	 * as predicted.
	 * Checking in and destruction is an atomic operation (for the IKE_SA),
	 * so this can be called if the SA is in a "unclean" state, without the
	 * risk that another thread can get the SA.
	 *
	 * @param ike_sa			SA to delete
	 * @returns 				
	 * 							- SUCCESS if found
	 * 							- NOT_FOUND when no such SA is available
	 */
	status_t (*checkin_and_destroy) (ike_sa_manager_t* this, ike_sa_t *ike_sa);
	
	/**
	 * Get the number of IKE_SAs which are in the connecting state.
	 *
	 * To prevent the server from resource exhaustion, cookies and other
	 * mechanisms are used. The number of half open IKE_SAs is a good
	 * indicator to see if a peer is flooding the server.
	 * If a host is supplied, only the number of half open IKE_SAs initiated
	 * from this IP are counted.
	 * Only SAs for which we are the responder are counted.
	 * 
	 * @param ip				NULL for all, IP for half open IKE_SAs with IP
	 * @return					number of half open IKE_SAs
	 */
	int (*get_half_open_count) (ike_sa_manager_t *this, host_t *ip);
	
	/**
	 * Delete all existing IKE_SAs and destroy them immediately.
	 * 
	 * Threads will be driven out, so all SAs can be deleted cleanly.
	 */
	void (*flush)(ike_sa_manager_t *this);
	
	/**
	 * Destroys the manager with all associated SAs.
	 *
	 * A call to flush() is required before calling destroy.
	 */
	void (*destroy) (ike_sa_manager_t *this);
};

/**
 * Create a manager.
 * 
 * @returns 	ike_sa_manager_t object, NULL if initialization fails
 */
ike_sa_manager_t *ike_sa_manager_create(void);

#endif /*IKE_SA_MANAGER_H_ @} */