updated some inline docs
[strongswan.git] / src / charon / sa / transactions / transaction.c
1 /**
2 * @file transaction.c
3 *
4 * @brief Generic contstructor for the different transaction types.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
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 #include "transaction.h"
24
25 #include <sa/child_sa.h>
26 #include <sa/transactions/ike_sa_init.h>
27 #include <sa/transactions/ike_auth.h>
28 #include <sa/transactions/delete_ike_sa.h>
29 #include <sa/transactions/create_child_sa.h>
30 #include <sa/transactions/delete_child_sa.h>
31 #include <sa/transactions/dead_peer_detection.h>
32 #include <encoding/payloads/ts_payload.h>
33 #include <encoding/payloads/sa_payload.h>
34 #include <encoding/payloads/nonce_payload.h>
35 #include <encoding/payloads/notify_payload.h>
36 #include <encoding/payloads/delete_payload.h>
37 #include <utils/logger_manager.h>
38
39
40 /*
41 * see header file
42 */
43 transaction_t *transaction_create(ike_sa_t *ike_sa, message_t *request)
44 {
45 iterator_t *iterator;
46 payload_t *current;
47 notify_payload_t *notify;
48 transaction_t *transaction = NULL;
49 u_int32_t message_id;
50
51 if (!request->get_request(request))
52 {
53 return NULL;
54 }
55 message_id = request->get_message_id(request);
56
57 switch (request->get_exchange_type(request))
58 {
59 case IKE_SA_INIT:
60 {
61 if (ike_sa->get_state(ike_sa) == SA_CREATED)
62 {
63 transaction = (transaction_t*)ike_sa_init_create(ike_sa, message_id);
64 }
65 break;
66 }
67 case IKE_AUTH:
68 {
69 /* IKE_AUTH is always created in IKE_SA_INIT, it never should
70 * appear alone */
71 break;
72 }
73 case CREATE_CHILD_SA:
74 {
75 if (ike_sa->get_state(ike_sa) != SA_ESTABLISHED)
76 {
77 break;
78 }
79 /* look for a REKEY_SA notify */
80 iterator = request->get_payload_iterator(request);
81 while (iterator->has_next(iterator))
82 {
83 iterator->current(iterator, (void**)&current);
84 if (current->get_type(current) != NOTIFY)
85 {
86 continue;
87 }
88 notify = (notify_payload_t*)current;
89 if (notify->get_notify_type(notify) != REKEY_SA)
90 {
91 continue;
92 }
93 switch (notify->get_protocol_id(notify))
94 {
95 case PROTO_IKE:
96 /* TODO: transaction = rekey_ike_sa_create(ike_sa, message_id); */
97 break;
98 case PROTO_AH:
99 case PROTO_ESP:
100 /* we do not handle rekeying of CHILD_SAs in a special
101 * transaction, as the procedure is nearly equal
102 * to create a new CHILD_SA. */
103 transaction = (transaction_t*)create_child_sa_create(ike_sa, message_id);
104 break;
105 default:
106 break;
107 }
108 if (transaction)
109 {
110 break;
111 }
112 }
113 iterator->destroy(iterator);
114 if (!transaction)
115 {
116 /* we have not found a REKEY_SA notify for IKE. This means
117 * we create a new CHILD_SA, or rekey an existing one.
118 * Both cases are handled with the create_child_sa transaction. */
119 transaction = (transaction_t*)create_child_sa_create(ike_sa, message_id);
120 }
121 break;
122 }
123 case INFORMATIONAL:
124 {
125 if (ike_sa->get_state(ike_sa) == SA_CREATED)
126 {
127 break;
128 }
129 u_int payload_count = 0;
130 iterator = request->get_payload_iterator(request);
131 while (iterator->has_next(iterator))
132 {
133 payload_count++;
134 iterator->current(iterator, (void**)&current);
135 switch (current->get_type(current))
136 {
137 case DELETE:
138 {
139 delete_payload_t *delete_payload;
140 delete_payload = (delete_payload_t*)current;
141 switch (delete_payload->get_protocol_id(delete_payload))
142 {
143 case PROTO_IKE:
144 transaction = (transaction_t*)
145 delete_ike_sa_create(ike_sa, message_id);
146 break;
147 case PROTO_AH:
148 case PROTO_ESP:
149 transaction = (transaction_t*)
150 delete_child_sa_create(ike_sa, message_id);
151 break;
152 default:
153 break;
154 }
155 break;
156 }
157 default:
158 break;
159 }
160 if (transaction)
161 {
162 break;
163 }
164 }
165 iterator->destroy(iterator);
166 /* empty informationals are used for dead peer detection in
167 * IKEv2. We use a special transaction for it. */
168 if (payload_count == 0)
169 {
170 transaction = (transaction_t*)
171 dead_peer_detection_create(ike_sa, message_id);
172 }
173 break;
174 }
175 default:
176 break;
177 }
178 return transaction;
179 }