File: | programs/pluto/pending.c |
Warning: | line 344, column 4 Access to field 'name' results in a dereference of a null pointer (loaded from field 'connection') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* information about connections between hosts and clients | |||
2 | * | |||
3 | * Copyright (C) 1998-2002,2013,2015 D. Hugh Redelmeier <hugh@mimosa.com> | |||
4 | * Copyright (C) 2003-2007 Michael Richardson <mcr@xelerance.com> | |||
5 | * Copyright (C) 2009 Paul Wouters <paul@xelerance.com> | |||
6 | * Copyright (C) 2012 Paul Wouters <paul@libreswan.org> | |||
7 | * Copyright (C) 2012-2018 Paul Wouters <pwouters@redhat.com> | |||
8 | * Copyright (C) 2011 Anthony Tong <atong@TrustedCS.com> | |||
9 | * Copyright (C) 2017-2018 Antony Antony <antony@phenome.org> | |||
10 | * Copyright (C) 2019 Andrew Cagney <cagney@gnu.org> | |||
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 <https://www.gnu.org/licenses/gpl2.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 <string.h> | |||
24 | #include <stdio.h> | |||
25 | #include <stddef.h> | |||
26 | #include <stdlib.h> | |||
27 | #include <unistd.h> | |||
28 | #include <netinet/in.h> | |||
29 | #include <sys/socket.h> | |||
30 | #include <sys/stat.h> | |||
31 | #include <netinet/in.h> | |||
32 | #include <arpa/inet.h> | |||
33 | #include <arpa/nameser.h> /* missing from <resolv.h> on old systems */ | |||
34 | #include <errno(*__errno_location ()).h> | |||
35 | ||||
36 | ||||
37 | #include "sysdep.h" | |||
38 | #include "constants.h" | |||
39 | #include "defs.h" | |||
40 | #include "id.h" | |||
41 | #include "x509.h" | |||
42 | #include "certs.h" | |||
43 | #include "connections.h" /* needs id.h */ | |||
44 | #include "pending.h" | |||
45 | #include "log.h" | |||
46 | #include "state.h" | |||
47 | #include "packet.h" | |||
48 | #include "demux.h" | |||
49 | #include "ikev1_quick.h" | |||
50 | #include "timer.h" | |||
51 | #include "ikev2.h" | |||
52 | #include "ip_address.h" | |||
53 | #include "host_pair.h" | |||
54 | #include "ikev2_create_child_sa.h" /* for initiate_v2_CREATE_CHILD_SA_create_child() */ | |||
55 | ||||
56 | /* | |||
57 | * queue an IPsec SA negotiation pending completion of a | |||
58 | * suitable phase 1 (IKE SA) | |||
59 | */ | |||
60 | ||||
61 | static void add_pending(struct fd *whack_sock, | |||
62 | struct ike_sa *ike, | |||
63 | struct connection *c, | |||
64 | lset_t policy, | |||
65 | unsigned long try, | |||
66 | so_serial_t replacing, | |||
67 | const shunk_t sec_label, | |||
68 | bool_Bool part_of_initiate) | |||
69 | { | |||
70 | /* look for duplicate pending IPsec SA's, skip add operation */ | |||
71 | struct pending **pp = host_pair_first_pending(c); | |||
72 | for (struct pending *p = pp ? *pp : NULL((void*)0); p != NULL((void*)0); p = p->next) { | |||
73 | if (p->connection == c) { | |||
74 | address_buf b; | |||
75 | connection_buf cib; | |||
76 | bool_Bool duplicate = (p->ike == ike); | |||
77 | dbg("connection "PRI_CONNECTION" is already pending: waiting on IKE SA #%lu connecting to %s; %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("connection ""\"%s\"%s"" is already pending: waiting on IKE SA #%lu connecting to %s; %s" , (c)->name, str_connection_instance(c, &cib), p->ike ->sa.st_serialno, str_address(&c->spd.that.host_addr , &b), duplicate ? "ignoring duplicate" : "this IKE SA is different" ); } } | |||
78 | pri_connection(c, &cib),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("connection ""\"%s\"%s"" is already pending: waiting on IKE SA #%lu connecting to %s; %s" , (c)->name, str_connection_instance(c, &cib), p->ike ->sa.st_serialno, str_address(&c->spd.that.host_addr , &b), duplicate ? "ignoring duplicate" : "this IKE SA is different" ); } } | |||
79 | p->ike->sa.st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("connection ""\"%s\"%s"" is already pending: waiting on IKE SA #%lu connecting to %s; %s" , (c)->name, str_connection_instance(c, &cib), p->ike ->sa.st_serialno, str_address(&c->spd.that.host_addr , &b), duplicate ? "ignoring duplicate" : "this IKE SA is different" ); } } | |||
80 | str_address(&c->spd.that.host_addr, &b),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("connection ""\"%s\"%s"" is already pending: waiting on IKE SA #%lu connecting to %s; %s" , (c)->name, str_connection_instance(c, &cib), p->ike ->sa.st_serialno, str_address(&c->spd.that.host_addr , &b), duplicate ? "ignoring duplicate" : "this IKE SA is different" ); } } | |||
81 | duplicate ? "ignoring duplicate" : "this IKE SA is different"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("connection ""\"%s\"%s"" is already pending: waiting on IKE SA #%lu connecting to %s; %s" , (c)->name, str_connection_instance(c, &cib), p->ike ->sa.st_serialno, str_address(&c->spd.that.host_addr , &b), duplicate ? "ignoring duplicate" : "this IKE SA is different" ); } }; | |||
82 | if (duplicate) { | |||
83 | return; | |||
84 | } | |||
85 | } | |||
86 | } | |||
87 | ||||
88 | struct pending *p = alloc_thing(struct pending, "struct pending")((struct pending*) alloc_bytes(sizeof(struct pending), ("struct pending" ))); | |||
89 | p->whack_sock = fd_dup(whack_sock, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 89, }; &here; })); /*on heap*/ | |||
90 | p->ike = ike; | |||
91 | p->connection = c; | |||
92 | p->policy = policy; | |||
93 | p->try = try; | |||
94 | p->replacing = replacing; | |||
95 | p->pend_time = mononow(); | |||
96 | p->part_of_initiate = part_of_initiate; /* useful */ | |||
97 | p->sec_label = sec_label; | |||
98 | ||||
99 | /* | |||
100 | * If this is part of an initiate then there's already enough | |||
101 | * going on; no need to log this action. | |||
102 | */ | |||
103 | enum stream only = part_of_initiate ? (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX)))) ? DEBUG_STREAM : NO_STREAM) : ALL_STREAMS; | |||
104 | if (only != NO_STREAM) { | |||
105 | address_buf b; | |||
106 | state_bufconnection_buf sab; | |||
107 | log_pending(only | RC_COMMENT, p, | |||
108 | "queue %s; waiting on %s "PRI_STATE"\"%s\"%s"" ""#%lu"" negotiating with %s", | |||
109 | /* "Child SA" or "IPsec SA" */ | |||
110 | enum_enum_name(&sa_type_names, p->connection->ike_version, IPSEC_SA), | |||
111 | /* "IKE SA" or "ISAKMP SA" */ | |||
112 | enum_enum_name(&sa_type_names, p->connection->ike_version, IKE_SA), | |||
113 | pri_state(&ike->sa, &sab)((&ike->sa)->st_connection)->name, str_connection_instance ((&ike->sa)->st_connection, &sab), ((&ike-> sa)->st_serialno), | |||
114 | ipstr(&c->spd.that.host_addr, &b)); | |||
115 | } | |||
116 | host_pair_enqueue_pending(c, p); | |||
117 | } | |||
118 | ||||
119 | void add_v1_pending(struct fd *whackfd, | |||
120 | struct ike_sa *ike, | |||
121 | struct connection *c, | |||
122 | lset_t policy, | |||
123 | unsigned long try, | |||
124 | so_serial_t replacing, | |||
125 | const shunk_t sec_label, | |||
126 | bool_Bool part_of_initiate) | |||
127 | { | |||
128 | passert(ike->sa.st_ike_version == IKEv1)({ _Bool assertion__ = ike->sa.st_connection->ike_version == IKEv1; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c" , .line = 128, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "ike->sa.st_connection->ike_version == IKEv1" ); } (void) 1; }); | |||
129 | add_pending(whackfd, ike, c, policy, try, replacing, sec_label, part_of_initiate); | |||
130 | } | |||
131 | ||||
132 | void add_v2_pending(struct fd *whackfd, | |||
133 | struct ike_sa *ike, | |||
134 | struct connection *c, | |||
135 | lset_t policy, | |||
136 | unsigned long try, | |||
137 | so_serial_t replacing, | |||
138 | const shunk_t sec_label, | |||
139 | bool_Bool part_of_initiate) | |||
140 | { | |||
141 | passert(ike->sa.st_ike_version == IKEv2)({ _Bool assertion__ = ike->sa.st_connection->ike_version == IKEv2; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c" , .line = 141, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "ike->sa.st_connection->ike_version == IKEv2" ); } (void) 1; }); | |||
142 | if (c->config->sec_label.len > 0 || sec_label.len > 0) { | |||
143 | /* | |||
144 | * Convert the template connection into a connection | |||
145 | * instance that contains the sec_label, and toss that | |||
146 | * onto the pending queue. | |||
147 | */ | |||
148 | if (!pexpect(c->kind == CK_TEMPLATE)({ _Bool assertion__ = c->kind == CK_TEMPLATE; if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 148, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "c->kind == CK_TEMPLATE" ); } assertion__; }) || | |||
149 | !pexpect(c->config->sec_label.len > 0)({ _Bool assertion__ = c->config->sec_label.len > 0; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c" , .line = 149, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "c->config->sec_label.len > 0" ); } assertion__; }) || | |||
150 | !pexpect(sec_label.len > 0)({ _Bool assertion__ = sec_label.len > 0; if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 150, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "sec_label.len > 0"); } assertion__; })) { | |||
151 | return; | |||
152 | } | |||
153 | ip_address remote_address = endpoint_address(ike->sa.st_remote_endpoint); | |||
154 | struct connection *d = instantiate(c, &remote_address, /*peer_id*/NULL((void*)0), sec_label); | |||
155 | connection_buf db; | |||
156 | dbg("generating and then tossing child connection "PRI_CONNECTION" with sec_label="PRI_SHUNK" into the pending queue",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("generating and then tossing child connection " "\"%s\"%s"" with sec_label=""%.*s"" into the pending queue", ( d)->name, str_connection_instance(d, &db), ((int) (sec_label ).len), (const char *) ((sec_label).ptr)); } } | |||
157 | pri_connection(d, &db), pri_shunk(sec_label)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("generating and then tossing child connection " "\"%s\"%s"" with sec_label=""%.*s"" into the pending queue", ( d)->name, str_connection_instance(d, &db), ((int) (sec_label ).len), (const char *) ((sec_label).ptr)); } }; | |||
158 | c = d; | |||
159 | } | |||
160 | add_pending(whackfd, ike, c, policy, try, replacing, sec_label, part_of_initiate); | |||
161 | } | |||
162 | ||||
163 | /* | |||
164 | * Release all the whacks awaiting the completion of this state. This | |||
165 | * is accomplished by closing all the whack socket file descriptors. | |||
166 | * We go to some trouble to tell each whack, but to not tell it twice. | |||
167 | */ | |||
168 | ||||
169 | void release_pending_whacks(struct state *st, err_t story) | |||
170 | { | |||
171 | /* | |||
172 | * Use fstat() to uniquely identify the whack connection - | |||
173 | * multiple sockets to the same whack will have similar | |||
174 | * 'struct stat' values. | |||
175 | * | |||
176 | * If the socket is valid, close it. | |||
177 | */ | |||
178 | if (!fd_p(st->st_logger->object_whackfd)) { | |||
179 | dbg("%s: state #%lu has no whack fd",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: state #%lu has no whack fd", __func__, st ->st_serialno); } } | |||
180 | __func__, st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: state #%lu has no whack fd", __func__, st ->st_serialno); } }; | |||
181 | return; | |||
182 | } | |||
183 | ||||
184 | /* | |||
185 | * Check for the SA's parent and if that needs to disconnect. | |||
186 | * | |||
187 | * For instance, when the IKE_SA establishes but the first | |||
188 | * CHILD_SA fails with a timeout then this code will be called | |||
189 | * with the CHILD_SA. | |||
190 | * | |||
191 | * XXX: Since this is meant to release pending whacks, should | |||
192 | * this check for, and release the whacks for any pending | |||
193 | * CHILD_SA attached to this ST's IKE SA? | |||
194 | */ | |||
195 | struct ike_sa *ike_with_same_whack = NULL((void*)0); | |||
196 | if (IS_CHILD_SA(st)((st)->st_clonedfrom != 0)) { | |||
197 | struct ike_sa *ike = ike_sa(st, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 197, }; &here; })); | |||
198 | if (same_fd(st->st_logger->object_whackfd, ike->sa.st_logger->object_whackfd)) { | |||
199 | ike_with_same_whack = ike; | |||
200 | release_any_whack(&ike->sa, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 200, }; &here; }), "release pending whacks state's IKE SA"); | |||
201 | } else { | |||
202 | release_any_whack(st, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 202, }; &here; }), "releasing isolated child"); | |||
203 | return; | |||
204 | } | |||
205 | } else { | |||
206 | ike_with_same_whack = pexpect_ike_sa(st); | |||
207 | } | |||
208 | pexpect(ike_with_same_whack != NULL)({ _Bool assertion__ = ike_with_same_whack != ((void*)0); if ( !assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 208, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_pexpect(logger_, here_, "%s", "ike_with_same_whack != ((void*)0)" ); } assertion__; }); | |||
209 | ||||
210 | /* | |||
211 | * Now go through pending children and close the whack socket | |||
212 | * of any that are going to be assigned this ST as the parent. | |||
213 | * XXX: Is this because the parent is dying so anything | |||
214 | * waiting on it should be deleted. | |||
215 | * | |||
216 | * SAME_FD() is used to identify whack sockets that are | |||
217 | * different to ST - when found a further release message is | |||
218 | * printed. | |||
219 | */ | |||
220 | ||||
221 | struct pending **pp = host_pair_first_pending(st->st_connection); | |||
222 | if (pp == NULL((void*)0)) | |||
223 | return; | |||
224 | for (struct pending *p = *pp; p != NULL((void*)0); p = p->next) { | |||
225 | dbg("%s: IKE SA #%lu "PRI_FD" has pending CHILD SA with socket "PRI_FD,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: IKE SA #%lu ""fd@%p"" has pending CHILD SA with socket " "fd@%p", __func__, p->ike->sa.st_serialno, (p->ike-> sa.st_logger->object_whackfd), (p->whack_sock)); } } | |||
226 | __func__, p->ike->sa.st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: IKE SA #%lu ""fd@%p"" has pending CHILD SA with socket " "fd@%p", __func__, p->ike->sa.st_serialno, (p->ike-> sa.st_logger->object_whackfd), (p->whack_sock)); } } | |||
227 | pri_fd(p->ike->sa.st_logger->object_whackfd),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: IKE SA #%lu ""fd@%p"" has pending CHILD SA with socket " "fd@%p", __func__, p->ike->sa.st_serialno, (p->ike-> sa.st_logger->object_whackfd), (p->whack_sock)); } } | |||
228 | pri_fd(p->whack_sock)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s: IKE SA #%lu ""fd@%p"" has pending CHILD SA with socket " "fd@%p", __func__, p->ike->sa.st_serialno, (p->ike-> sa.st_logger->object_whackfd), (p->whack_sock)); } }; | |||
229 | if (p->ike == ike_with_same_whack && fd_p(p->whack_sock)) { | |||
230 | if (!same_fd(st->st_logger->object_whackfd, p->whack_sock)) { | |||
231 | /* XXX: why not the log file? */ | |||
232 | log_pending(WHACK_STREAM|RC_COMMENT, p, | |||
233 | "%s for IKE SA, but releasing whack for pending %s", | |||
234 | story, | |||
235 | /* "IPsec SA" or "CHILD SA" */ | |||
236 | enum_enum_name(&sa_type_names, p->connection->ike_version, IPSEC_SA)); | |||
237 | } | |||
238 | close_any(&p->whack_sock)close_any_fd((&p->whack_sock), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c" , .line = 238, }; &here; }));/*on-heap*/ | |||
239 | } | |||
240 | } | |||
241 | release_any_whack(st, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 241, }; &here; }), "releasing child"); | |||
242 | } | |||
243 | ||||
244 | /* | |||
245 | * remove a pending from a linked list. | |||
246 | * | |||
247 | * pp points to the link to the entry. | |||
248 | * *pp will be updated to point to the successor to the original *pp. | |||
249 | * In effect, we advance *pp. | |||
250 | * Note: If you are traversing a linked list and deleting some entries, | |||
251 | * you should not advance pp after calling delete_pending. | |||
252 | */ | |||
253 | static void delete_pending(struct pending **pp) | |||
254 | { | |||
255 | /* remove from list */ | |||
256 | struct pending *p = *pp; | |||
257 | *pp = p->next; | |||
258 | ||||
259 | if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) { | |||
260 | if (p->connection == NULL((void*)0)) { | |||
261 | /* | |||
262 | * ??? when does this happen? | |||
263 | * | |||
264 | * Look for p->connection=NULL below. When | |||
265 | * unpend()ing, the pending connection's | |||
266 | * ownership is transfered to the state. | |||
267 | */ | |||
268 | DBG_log("removing pending policy {%p}; connection ownership transfered", p); | |||
269 | } else { | |||
270 | connection_buf cib; | |||
271 | DBG_log("removing pending policy {%p} with connection "PRI_CONNECTION"\"%s\"%s""", | |||
272 | p, pri_connection(p->connection, &cib)(p->connection)->name, str_connection_instance(p->connection , &cib)); | |||
273 | } | |||
274 | } | |||
275 | ||||
276 | if (p->connection != NULL((void*)0)) { | |||
277 | /* above unlink means C is no longer pending */ | |||
278 | pexpect(!connection_is_pending(p->connection))({ _Bool assertion__ = !connection_is_pending(p->connection ); if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c" , .line = 278, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "!connection_is_pending(p->connection)" ); } assertion__; }); | |||
279 | connection_delete_unused_instance(&p->connection, | |||
280 | /*old-state*/NULL((void*)0), | |||
281 | null_fd((struct fd *) ((void*)0))/*XXX: p->whack_sock?*/); | |||
282 | } | |||
283 | close_any(&p->whack_sock)close_any_fd((&p->whack_sock), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c" , .line = 283, }; &here; })); /*on-heap*/ | |||
284 | ||||
285 | pfree(p); | |||
286 | } | |||
287 | ||||
288 | /* | |||
289 | * Look for phase2s that were waiting for a phase 1. | |||
290 | * | |||
291 | * XXX instead of doing this work NOW, we should simply create an event | |||
292 | * in zero future time to unpend the state. | |||
293 | * YYY but, in fact, quick_mode will enqueue a cryptographic operation | |||
294 | * anyway, which will get done "later" anyway, so make it is just fine | |||
295 | * as it is. | |||
296 | * In IKEv2 it called when AUTH is complete, child is established. | |||
297 | * Established child get removed not unpend. | |||
298 | */ | |||
299 | ||||
300 | void unpend(struct ike_sa *ike, struct connection *cc) | |||
301 | { | |||
302 | if (cc == NULL((void*)0)) { | |||
| ||||
303 | dbg("unpending state #%lu", ike->sa.st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("unpending state #%lu", ike->sa.st_serialno ); } }; | |||
304 | } else { | |||
305 | connection_buf cib; | |||
306 | dbg("unpending state #%lu connection "PRI_CONNECTION"",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("unpending state #%lu connection ""\"%s\"%s""" , ike->sa.st_serialno, (cc)->name, str_connection_instance (cc, &cib)); } } | |||
307 | ike->sa.st_serialno, pri_connection(cc, &cib)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("unpending state #%lu connection ""\"%s\"%s""" , ike->sa.st_serialno, (cc)->name, str_connection_instance (cc, &cib)); } }; | |||
308 | } | |||
309 | ||||
310 | for (struct pending *p, **pp = host_pair_first_pending(ike->sa.st_connection); | |||
311 | (p = *pp) != NULL((void*)0); ) { | |||
312 | if (p->ike == ike) { | |||
313 | p->pend_time = mononow(); | |||
314 | char *what ="unqueuing"; | |||
315 | switch (ike->sa.st_ike_versionst_connection->ike_version) { | |||
316 | case IKEv2: | |||
317 | if (cc == p->connection) { | |||
318 | /* | |||
319 | * IKEv2 AUTH negotiation | |||
320 | * include child. nothing to | |||
321 | * upend, like in IKEv1, | |||
322 | * delete it | |||
323 | */ | |||
324 | what = "delete from"; | |||
325 | } else if (!already_has_larval_v2_child(ike, p->connection)) { | |||
326 | submit_v2_CREATE_CHILD_SA_new_child(ike, p->connection, | |||
327 | p->policy, p->try, | |||
328 | p->whack_sock); | |||
329 | } | |||
330 | break; | |||
331 | case IKEv1: | |||
332 | #ifdef USE_IKEv11 | |||
333 | quick_outI1(p->whack_sock, &ike->sa, p->connection, | |||
334 | p->policy, | |||
335 | p->try, p->replacing, | |||
336 | null_shunk); | |||
337 | #endif | |||
338 | break; | |||
339 | default: | |||
340 | bad_case(ike->sa.st_ike_version)libreswan_bad_case("ike->sa.st_ike_version", (ike->sa.st_connection ->ike_version), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 340, }; &here; })); | |||
341 | } | |||
342 | address_buf b; | |||
343 | connection_buf cib; | |||
344 | dbg("%s pending %s with %s "PRI_CONNECTION"",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s pending %s with %s ""\"%s\"%s""", what, (ike ->sa.st_connection->ike_version == IKEv2) ? "Child SA" : "Quick Mode", str_address(&p->connection->spd.that .host_addr, &b), (p->connection)->name, str_connection_instance (p->connection, &cib)); } } | |||
| ||||
345 | what,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s pending %s with %s ""\"%s\"%s""", what, (ike ->sa.st_connection->ike_version == IKEv2) ? "Child SA" : "Quick Mode", str_address(&p->connection->spd.that .host_addr, &b), (p->connection)->name, str_connection_instance (p->connection, &cib)); } } | |||
346 | (ike->sa.st_ike_version == IKEv2) ? "Child SA" : "Quick Mode",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s pending %s with %s ""\"%s\"%s""", what, (ike ->sa.st_connection->ike_version == IKEv2) ? "Child SA" : "Quick Mode", str_address(&p->connection->spd.that .host_addr, &b), (p->connection)->name, str_connection_instance (p->connection, &cib)); } } | |||
347 | str_address(&p->connection->spd.that.host_addr, &b),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s pending %s with %s ""\"%s\"%s""", what, (ike ->sa.st_connection->ike_version == IKEv2) ? "Child SA" : "Quick Mode", str_address(&p->connection->spd.that .host_addr, &b), (p->connection)->name, str_connection_instance (p->connection, &cib)); } } | |||
348 | pri_connection(p->connection, &cib)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("%s pending %s with %s ""\"%s\"%s""", what, (ike ->sa.st_connection->ike_version == IKEv2) ? "Child SA" : "Quick Mode", str_address(&p->connection->spd.that .host_addr, &b), (p->connection)->name, str_connection_instance (p->connection, &cib)); } }; | |||
349 | ||||
350 | p->connection = NULL((void*)0); /* ownership transferred */ | |||
351 | delete_pending(pp); /* in effect, advances pp */ | |||
352 | } else { | |||
353 | pp = &p->next; | |||
354 | } | |||
355 | } | |||
356 | } | |||
357 | ||||
358 | struct connection *first_pending(const struct ike_sa *ike, | |||
359 | lset_t *policy, | |||
360 | struct fd **p_whack_sock) | |||
361 | { | |||
362 | struct pending **pp, *p; | |||
363 | ||||
364 | dbg("getting first pending from state #%lu", ike->sa.st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("getting first pending from state #%lu", ike-> sa.st_serialno); } }; | |||
365 | ||||
366 | for (pp = host_pair_first_pending(ike->sa.st_connection); | |||
367 | (p = *pp) != NULL((void*)0); pp = &p->next) | |||
368 | { | |||
369 | if (p->ike == ike) { | |||
370 | close_any(p_whack_sock)close_any_fd((p_whack_sock), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 370, }; &here; })); /*on-heap*/ | |||
371 | *p_whack_sock = fd_dup(p->whack_sock, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 371, }; &here; })); /*on-heap*/ | |||
372 | *policy = p->policy; | |||
373 | return p->connection; | |||
374 | } | |||
375 | } | |||
376 | return NULL((void*)0); | |||
377 | } | |||
378 | ||||
379 | /* | |||
380 | * Look for phase2s that were waiting for a phase 1. If the time that we | |||
381 | * have been pending exceeds a DPD timeout that was set, then we call the | |||
382 | * dpd_timeout() on this state. We hope this kills the pending state. | |||
383 | */ | |||
384 | bool_Bool pending_check_timeout(const struct connection *c) | |||
385 | { | |||
386 | struct pending **pp, *p; | |||
387 | ||||
388 | for (pp = host_pair_first_pending(c); (p = *pp) != NULL((void*)0); ) { | |||
389 | deltatime_t waited = monotimediff(mononow(), p->pend_time); | |||
390 | connection_buf cib; | |||
391 | dbg("checking connection "PRI_CONNECTION" for stuck phase 2s (waited %jd, patience 3*%jd)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("checking connection ""\"%s\"%s"" for stuck phase 2s (waited %jd, patience 3*%jd)" , (c)->name, str_connection_instance(c, &cib), deltasecs (waited), deltasecs(c->dpd_timeout)); } } | |||
392 | pri_connection(c, &cib), deltasecs(waited),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("checking connection ""\"%s\"%s"" for stuck phase 2s (waited %jd, patience 3*%jd)" , (c)->name, str_connection_instance(c, &cib), deltasecs (waited), deltasecs(c->dpd_timeout)); } } | |||
393 | deltasecs(c->dpd_timeout)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("checking connection ""\"%s\"%s"" for stuck phase 2s (waited %jd, patience 3*%jd)" , (c)->name, str_connection_instance(c, &cib), deltasecs (waited), deltasecs(c->dpd_timeout)); } }; | |||
394 | if (deltasecs(c->dpd_timeout) > 0) { | |||
395 | if (!monobefore(mononow(), | |||
396 | monotime_add(p->pend_time, | |||
397 | deltatimescale(3, 1, c->dpd_timeout)))) { | |||
398 | connection_buf cib; | |||
399 | dbg("connection "PRI_CONNECTION" stuck, restarting",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("connection ""\"%s\"%s"" stuck, restarting", ( c)->name, str_connection_instance(c, &cib)); } } | |||
400 | pri_connection(c, &cib)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("connection ""\"%s\"%s"" stuck, restarting", ( c)->name, str_connection_instance(c, &cib)); } }; | |||
401 | return true1; | |||
402 | } | |||
403 | } | |||
404 | pp = &p->next; | |||
405 | } | |||
406 | return false0; | |||
407 | } | |||
408 | ||||
409 | /* a IKE SA negotiation has been replaced; update any pending */ | |||
410 | void update_pending(struct ike_sa *old_ike, struct ike_sa *new_ike) | |||
411 | { | |||
412 | struct pending *p, **pp; | |||
413 | ||||
414 | pexpect(old_ike != NULL)({ _Bool assertion__ = old_ike != ((void*)0); if (!assertion__ ) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/pending.c", .line = 414, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_pexpect(logger_, here_, "%s", "old_ike != ((void*)0)") ; } assertion__; }); | |||
415 | if (old_ike == NULL((void*)0)) | |||
416 | return; | |||
417 | ||||
418 | pp = host_pair_first_pending(old_ike->sa.st_connection); | |||
419 | if (pp == NULL((void*)0)) | |||
420 | return; | |||
421 | ||||
422 | for (p = *pp; p != NULL((void*)0); p = p->next) | |||
423 | if (p->ike == old_ike) | |||
424 | p->ike = new_ike; | |||
425 | } | |||
426 | ||||
427 | /* a IKE SA negotiation has failed; discard any pending */ | |||
428 | void flush_pending_by_state(struct ike_sa *ike) | |||
429 | { | |||
430 | struct pending **pp, *p; | |||
431 | ||||
432 | pp = host_pair_first_pending(ike->sa.st_connection); | |||
433 | if (pp == NULL((void*)0)) | |||
434 | return; | |||
435 | ||||
436 | while ((p = *pp) != NULL((void*)0)) { | |||
437 | if (p->ike == ike) { | |||
438 | /* we don't have to worry about deref to free'ed | |||
439 | * *pp, because delete_pending updates pp to | |||
440 | * point to the next element before it frees *pp | |||
441 | */ | |||
442 | delete_pending(pp); /* in effect, advances pp */ | |||
443 | } else { | |||
444 | pp = &p->next; | |||
445 | } | |||
446 | } | |||
447 | } | |||
448 | ||||
449 | /* a connection has been deleted; discard any related pending */ | |||
450 | void flush_pending_by_connection(const struct connection *c) | |||
451 | { | |||
452 | struct pending **pp, *p; | |||
453 | ||||
454 | pp = host_pair_first_pending(c); | |||
455 | if (pp == NULL((void*)0)) | |||
456 | return; | |||
457 | ||||
458 | while ((p = *pp) != NULL((void*)0)) { | |||
459 | if (p->connection == c) { | |||
460 | p->connection = NULL((void*)0); /* prevent delete_pending from releasing */ | |||
461 | delete_pending(pp); /* in effect, advances pp */ | |||
462 | } else { | |||
463 | pp = &p->next; | |||
464 | } | |||
465 | } | |||
466 | } | |||
467 | ||||
468 | void show_pending_child_details(struct show *s, | |||
469 | const struct connection *c, | |||
470 | const struct ike_sa *ike) | |||
471 | { | |||
472 | struct pending **pp, *p; | |||
473 | ||||
474 | pp = host_pair_first_pending(c); | |||
475 | if (pp == NULL((void*)0)) | |||
476 | return; | |||
477 | ||||
478 | for (p = *pp; p != NULL((void*)0); p = p->next) { | |||
479 | if (p->ike == ike) { | |||
480 | /* connection-name state-number [replacing state-number] */ | |||
481 | SHOW_JAMBUF(RC_COMMENT, s, buf)for (struct jambuf *buf = show_jambuf(s); buf != ((void*)0); jambuf_to_show (buf, s, RC_COMMENT), buf = ((void*)0)) { | |||
482 | jam(buf, "#%lu: pending ", p->ike->sa.st_serialno); | |||
483 | jam_string(buf, (ike->sa.st_ike_versionst_connection->ike_version == IKEv2) ? "CHILD SA" : "Phase 2"); | |||
484 | jam(buf, " for "); | |||
485 | jam_connection(buf, c); | |||
486 | if (p->replacing != SOS_NOBODY0) { | |||
487 | jam(buf, " replacing #%lu", p->replacing); | |||
488 | } | |||
489 | } | |||
490 | } | |||
491 | } | |||
492 | } | |||
493 | ||||
494 | bool_Bool connection_is_pending(const struct connection *c) | |||
495 | { | |||
496 | /* see if it is being used by a pending */ | |||
497 | struct pending **pp, *p; | |||
498 | ||||
499 | pp = host_pair_first_pending(c); | |||
500 | if (pp == NULL((void*)0)) | |||
501 | return false0; | |||
502 | ||||
503 | for (p = *pp; p != NULL((void*)0); p = p->next) | |||
504 | if (p->connection == c) | |||
505 | return true1; /* in use, so we're done */ | |||
506 | ||||
507 | return false0; | |||
508 | } |