Bug Summary

File:programs/pluto/pending.c
Warning:line 290, column 4
Access to field 'name' results in a dereference of a null pointer (loaded from field 'connection')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pending.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -pic-is-pie -mthread-model posix -mdisable-fp-elim -relaxed-aliasing -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -resource-dir /usr/lib64/clang/8.0.0 -D TimeZoneOffset=timezone -D linux -D PIE -D NSS_IPSEC_PROFILE -D XFRM_SUPPORT -D USE_XFRM_INTERFACE -D USE_DNSSEC -D DEFAULT_DNSSEC_ROOTKEY_FILE="/var/lib/unbound/root.key" -D HAVE_LABELED_IPSEC -D HAVE_SECCOMP -D LIBCURL -D USE_LINUX_AUDIT -D USE_SYSTEMD_WATCHDOG -D HAVE_NM -D XAUTH_HAVE_PAM -D USE_3DES -D USE_AES -D USE_CAMELLIA -D USE_CHACHA -D USE_DH31 -D USE_MD5 -D USE_SHA1 -D USE_SHA2 -D USE_PRF_AES_XCBC -D DEFAULT_RUNDIR="/run/pluto" -D IPSEC_CONF="/etc/ipsec.conf" -D IPSEC_CONFDDIR="/etc/ipsec.d" -D IPSEC_NSSDIR="/etc/ipsec.d" -D IPSEC_CONFDIR="/etc" -D IPSEC_EXECDIR="/usr/local/libexec/ipsec" -D IPSEC_SBINDIR="/usr/local/sbin" -D IPSEC_VARDIR="/var" -D POLICYGROUPSDIR="/etc/ipsec.d/policies" -D IPSEC_SECRETS_FILE="/etc/ipsec.secrets" -D FORCE_PR_ASSERT -D USE_FORK=1 -D USE_VFORK=0 -D USE_DAEMON=0 -D USE_PTHREAD_SETSCHEDPRIO=1 -D GCC_LINT -D HAVE_LIBCAP_NG -I . -I ../../OBJ.linux.x86_64/programs/pluto -I ../../include -I /usr/include/nss3 -I /usr/include/nspr4 -I /home/build/libreswan/programs/pluto/linux-copy -D HERE_BASENAME="pending.c" -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/8.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-missing-field-initializers -std=gnu99 -fdebug-compilation-dir /home/build/libreswan/programs/pluto -ferror-limit 19 -fmessage-length 0 -stack-protector 3 -fobjc-runtime=gcc -fdiagnostics-show-option -analyzer-output=html -o /tmp/scan-build-2020-09-09-193337-25440-1 -x c /home/build/libreswan/programs/pluto/pending.c -faddrsig
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 "pluto_crypt.h" /* for pluto_crypto_req & pluto_crypto_req_cont */
52#include "ikev2.h"
53#include "ip_address.h"
54#include "hostpair.h"
55
56/*
57 * queue an IPsec SA negotiation pending completion of a
58 * suitable phase 1 (IKE SA)
59 */
60void add_pending(struct fd *whack_sock,
61 struct ike_sa *ike,
62 struct connection *c,
63 lset_t policy,
64 unsigned long try,
65 so_serial_t replacing,
66 struct xfrm_user_sec_ctx_ike *uctx,
67 bool_Bool part_of_initiate)
68{
69 struct pending *p, **pp;
70
71 /* look for duplicate pending IPsec SA's, skip add operation */
72 pp = host_pair_first_pending(c);
73
74 for (p = pp ? *pp : NULL((void*)0); p != NULL((void*)0); p = p->next) {
75 if (p->connection == c && p->ike == ike) {
76 address_buf b;
77 connection_buf cib;
78 dbg("Ignored already queued up pending IPsec SA negotiation with %s "PRI_CONNECTION"",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("Ignored already queued up pending IPsec SA negotiation with %s "
"\"%s\"%s""", str_address(&c->spd.that.host_addr, &
b), (c)->name, str_connection_instance(c, &cib)); } }
79 str_address(&c->spd.that.host_addr, &b),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("Ignored already queued up pending IPsec SA negotiation with %s "
"\"%s\"%s""", str_address(&c->spd.that.host_addr, &
b), (c)->name, str_connection_instance(c, &cib)); } }
80 pri_connection(c, &cib)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("Ignored already queued up pending IPsec SA negotiation with %s "
"\"%s\"%s""", str_address(&c->spd.that.host_addr, &
b), (c)->name, str_connection_instance(c, &cib)); } }
;
81 return;
82 }
83 }
84
85 p = alloc_thing(struct pending, "struct pending")((struct pending*) alloc_bytes(sizeof(struct pending), ("struct pending"
)))
;
86 p->whack_sock = dup_any(whack_sock)dup_any_fd((whack_sock), (where_t) { .func = __func__, .basename
= "pending.c" , .line = 86})
; /*on heap*/
87 p->ike = ike;
88 p->connection = c;
89 p->policy = policy;
90 p->try = try;
91 p->replacing = replacing;
92 p->pend_time = mononow();
93 p->part_of_initiate = part_of_initiate; /* useful */
94 p->uctx = NULL((void*)0);
95 if (uctx != NULL((void*)0)) {
96 p->uctx = clone_thing(*uctx, "pending security context")((__typeof__(&(*uctx))) clone_bytes((const void *)&(*
uctx), sizeof(*uctx), ("pending security context")))
;
97 dbg("pending IPsec SA negotiation with security context %s, %d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("pending IPsec SA negotiation with security context %s, %d"
, p->uctx->sec_ctx_value, p->uctx->ctx.ctx_len); }
}
98 p->uctx->sec_ctx_value,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("pending IPsec SA negotiation with security context %s, %d"
, p->uctx->sec_ctx_value, p->uctx->ctx.ctx_len); }
}
99 p->uctx->ctx.ctx_len){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("pending IPsec SA negotiation with security context %s, %d"
, p->uctx->sec_ctx_value, p->uctx->ctx.ctx_len); }
}
;
100 }
101
102 /*
103 * If this is part of an initiate then there's already enough
104 * going on; no need to log this action.
105 */
106 enum stream only = part_of_initiate ? (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX)))) ? DEBUG_STREAM : NO_STREAM) : ALL_STREAMS;
107 if (only != NO_STREAM) {
108 address_buf b;
109 connection_buf cibb;
110 struct connection *cb = ike->sa.st_connection;
111 log_pending(only | RC_COMMENT, p,
112 "queuing pending IPsec SA negotiating with %s IKE SA #%lu "PRI_CONNECTION"\"%s\"%s""",
113 ipstr(&c->spd.that.host_addr, &b),
114 ike->sa.st_serialno, pri_connection(cb, &cibb)(cb)->name, str_connection_instance(cb, &cibb));
115 }
116 host_pair_enqueue_pending(c, p, &p->next);
117}
118
119/*
120 * Release all the whacks awaiting the completion of this state. This
121 * is accomplished by closing all the whack socket file descriptors.
122 * We go to some trouble to tell each whack, but to not tell it twice.
123 */
124
125void release_pending_whacks(struct state *st, err_t story)
126{
127 /*
128 * Use fstat() to uniquely identify the whack connection -
129 * multiple sockets to the same whack will have similar
130 * 'struct stat' values.
131 *
132 * If the socket is valid, close it.
133 */
134 if (!fd_p(st->st_whack_sockst_logger->object_whackfd)) {
135 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); } }
136 __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); } }
;
137 return;
138 }
139
140 /*
141 * Check for the SA's parent and if that needs to disconnect.
142 *
143 * For instance, when the IKE_SA establishes but the first
144 * CHILD_SA fails with a timeout then this code will be called
145 * with the CHILD_SA.
146 *
147 * XXX: Since this is meant to release pending whacks, should
148 * this check for, and release the whacks for any pending
149 * CHILD_SA attached to this ST's IKE SA?
150 */
151 struct ike_sa *ike_with_same_whack = NULL((void*)0);
152 if (IS_CHILD_SA(st)((st)->st_clonedfrom != 0)) {
153 struct ike_sa *ike = ike_sa(st, HERE(where_t) { .func = __func__, .basename = "pending.c" , .line
= 153}
);
154 if (same_fd(st->st_whack_sockst_logger->object_whackfd, ike->sa.st_whack_sockst_logger->object_whackfd)) {
155 ike_with_same_whack = ike;
156 release_any_whack(&ike->sa, HERE(where_t) { .func = __func__, .basename = "pending.c" , .line
= 156}
, "release pending whacks state's IKE SA");
157 } else {
158 release_any_whack(st, HERE(where_t) { .func = __func__, .basename = "pending.c" , .line
= 158}
, "releasing isolated child");
159 return;
160 }
161 } else {
162 ike_with_same_whack = pexpect_ike_sa(st);
163 }
164 pexpect(ike_with_same_whack != NULL)({ _Bool assertion__ = ike_with_same_whack != ((void*)0); if (
!assertion__) { log_pexpect((where_t) { .func = __func__, .basename
= "pending.c" , .line = 164}, "%s", "ike_with_same_whack != NULL"
); } assertion__; })
;
165
166 /*
167 * Now go through pending children and close the whack socket
168 * of any that are going to be assigned this ST as the parent.
169 * XXX: Is this because the parent is dying so anything
170 * waiting on it should be deleted.
171 *
172 * SAME_FD() is used to identify whack sockets that are
173 * different to ST - when found a further release message is
174 * printed.
175 */
176
177 struct pending **pp = host_pair_first_pending(st->st_connection);
178 if (pp == NULL((void*)0))
179 return;
180 for (struct pending *p = *pp; p != NULL((void*)0); p = p->next) {
181 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-fd@%p"" has pending CHILD SA with socket "
"fd-fd@%p", __func__, p->ike->sa.st_serialno, (p->ike
->sa.st_logger->object_whackfd), (p->whack_sock)); }
}
182 __func__, p->ike->sa.st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: IKE SA #%lu ""fd-fd@%p"" has pending CHILD SA with socket "
"fd-fd@%p", __func__, p->ike->sa.st_serialno, (p->ike
->sa.st_logger->object_whackfd), (p->whack_sock)); }
}
183 pri_fd(p->ike->sa.st_whack_sock),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: IKE SA #%lu ""fd-fd@%p"" has pending CHILD SA with socket "
"fd-fd@%p", __func__, p->ike->sa.st_serialno, (p->ike
->sa.st_logger->object_whackfd), (p->whack_sock)); }
}
184 pri_fd(p->whack_sock)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: IKE SA #%lu ""fd-fd@%p"" has pending CHILD SA with socket "
"fd-fd@%p", __func__, p->ike->sa.st_serialno, (p->ike
->sa.st_logger->object_whackfd), (p->whack_sock)); }
}
;
185 if (p->ike == ike_with_same_whack && fd_p(p->whack_sock)) {
186 if (!same_fd(st->st_whack_sockst_logger->object_whackfd, p->whack_sock)) {
187 /* XXX: why not the log file? */
188 log_pending(WHACK_STREAM|RC_COMMENT, p,
189 "%s for IKE SA, but releasing whack for pending %s",
190 story,
191 /* IPsec SA or CHILD SA */
192 enum_enum_name(&sa_type_names,
193 p->connection->ike_version,
194 IPSEC_SA));
195 }
196 close_any(&p->whack_sock)close_any_fd((&p->whack_sock), (where_t) { .func = __func__
, .basename = "pending.c" , .line = 196})
;/*on-heap*/
197 }
198 }
199 release_any_whack(st, HERE(where_t) { .func = __func__, .basename = "pending.c" , .line
= 199}
, "releasing child");
200}
201
202/*
203 * remove a pending from a linked list.
204 *
205 * pp points to the link to the entry.
206 * *pp will be updated to point to the successor to the original *pp.
207 * In effect, we advance *pp.
208 * Note: If you are traversing a linked list and deleting some entries,
209 * you should not advance pp after calling delete_pending.
210 */
211static void delete_pending(struct pending **pp)
212{
213 struct pending *p = *pp;
214
215 *pp = p->next;
216 if (p->connection != NULL((void*)0))
217 connection_discard(p->connection);
218 close_any(&p->whack_sock)close_any_fd((&p->whack_sock), (where_t) { .func = __func__
, .basename = "pending.c" , .line = 218})
; /*on-heap*/
219
220 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
221 if (p->connection == NULL((void*)0)) {
222 /* ??? when does this happen? */
223 DBG_log("removing pending policy for no connection {%p}", p);
224 } else {
225 connection_buf cib;
226 DBG_log("removing pending policy for "PRI_CONNECTION"\"%s\"%s"" {%p}",
227 pri_connection(p->connection, &cib)(p->connection)->name, str_connection_instance(p->connection
, &cib)
, p);
228 }
229 }
230
231 pfreeany(p->uctx){ typeof(p->uctx) *pp_ = &(p->uctx); if (*pp_ != ((
void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }
;
232 pfree(p);
233}
234
235/*
236 * Look for phase2s that were waiting for a phase 1.
237 *
238 * XXX instead of doing this work NOW, we should simply create an event
239 * in zero future time to unpend the state.
240 * YYY but, in fact, quick_mode will enqueue a cryptographic operation
241 * anyway, which will get done "later" anyway, so make it is just fine
242 * as it is.
243 * In IKEv2 it called when AUTH is complete, child is established.
244 * Established child get removed not unpend.
245 */
246void unpend(struct ike_sa *ike, struct connection *cc)
247{
248 struct pending **pp, *p;
249 char *what ="unqueuing";
250
251 if (cc == NULL((void*)0)) {
1
Assuming 'cc' is equal to NULL
2
Taking true branch
252 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
); } }
;
3
Assuming the condition is false
4
Taking false branch
253 } else {
254 connection_buf cib;
255 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)); } }
256 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)); } }
;
257 }
258
259 for (pp = host_pair_first_pending(ike->sa.st_connection);
6
Loop condition is true. Entering loop body
260 (p = *pp) != NULL((void*)0); )
5
Assuming the condition is true
261 {
262 if (p->ike == ike) {
7
Assuming the condition is true
8
Taking true branch
263 p->pend_time = mononow();
264 switch (ike->sa.st_ike_version) {
9
Control jumps to 'case IKEv2:' at line 265
265 case IKEv2:
266 if (cc != p->connection) {
10
Assuming pointer value is null
11
Taking false branch
267 ikev2_initiate_child_sa(p);
268 } else {
269 /*
270 * IKEv2 AUTH negotiation
271 * include child. nothing to
272 * upend, like in IKEv1,
273 * delete it
274 */
275 what = "delete from";
276 }
277 break;
12
Execution continues on line 288
278 case IKEv1:
279 quick_outI1(p->whack_sock, &ike->sa, p->connection,
280 p->policy,
281 p->try, p->replacing
282 , p->uctx
283 );
284 break;
285 default:
286 bad_case(ike->sa.st_ike_version)libreswan_bad_case("ike->sa.st_ike_version", (ike->sa.st_ike_version
), (where_t) { .func = __func__, .basename = "pending.c" , .line
= 286})
;
287 }
288 address_buf b;
289 connection_buf cib;
290 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_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)); } }
13
Assuming the condition is true
14
Taking true branch
15
'?' condition is true
16
Access to field 'name' results in a dereference of a null pointer (loaded from field 'connection')
291 what,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s pending %s with %s ""\"%s\"%s""", what, (ike
->sa.st_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)); } }
292 (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_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)); } }
293 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_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)); } }
294 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_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)); } }
;
295
296 p->connection = NULL((void*)0); /* ownership transferred */
297 delete_pending(pp); /* in effect, advances pp */
298 } else {
299 pp = &p->next;
300 }
301 }
302}
303
304struct connection *first_pending(const struct ike_sa *ike,
305 lset_t *policy,
306 struct fd **p_whack_sock)
307{
308 struct pending **pp, *p;
309
310 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); } }
;
311
312 for (pp = host_pair_first_pending(ike->sa.st_connection);
313 (p = *pp) != NULL((void*)0); pp = &p->next)
314 {
315 if (p->ike == ike) {
316 close_any(p_whack_sock)close_any_fd((p_whack_sock), (where_t) { .func = __func__, .basename
= "pending.c" , .line = 316})
; /*on-heap*/
317 *p_whack_sock = dup_any(p->whack_sock)dup_any_fd((p->whack_sock), (where_t) { .func = __func__, .
basename = "pending.c" , .line = 317})
; /*on-heap*/
318 *policy = p->policy;
319 return p->connection;
320 }
321 }
322 return NULL((void*)0);
323}
324
325/*
326 * Look for phase2s that were waiting for a phase 1. If the time that we
327 * have been pending exceeds a DPD timeout that was set, then we call the
328 * dpd_timeout() on this state. We hope this kills the pending state.
329 */
330bool_Bool pending_check_timeout(const struct connection *c)
331{
332 struct pending **pp, *p;
333
334 for (pp = host_pair_first_pending(c); (p = *pp) != NULL((void*)0); ) {
335 deltatime_t waited = monotimediff(mononow(), p->pend_time);
336 connection_buf cib;
337 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)); } }
338 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)); } }
339 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)); } }
;
340 if (deltasecs(c->dpd_timeout) > 0) {
341 if (!monobefore(mononow(),
342 monotime_add(p->pend_time,
343 deltatimescale(3, 1, c->dpd_timeout)))) {
344 connection_buf cib;
345 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)); } }
346 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)); } }
;
347 return TRUE1;
348 }
349 }
350 pp = &p->next;
351 }
352 return FALSE0;
353}
354
355/* a IKE SA negotiation has been replaced; update any pending */
356void update_pending(struct ike_sa *old_ike, struct ike_sa *new_ike)
357{
358 struct pending *p, **pp;
359
360 pp = host_pair_first_pending(old_ike->sa.st_connection);
361 if (pp == NULL((void*)0))
362 return;
363
364 for (p = *pp; p != NULL((void*)0); p = p->next)
365 if (p->ike == old_ike)
366 p->ike = new_ike;
367}
368
369/* a IKE SA negotiation has failed; discard any pending */
370void flush_pending_by_state(struct ike_sa *ike)
371{
372 struct pending **pp, *p;
373
374 pp = host_pair_first_pending(ike->sa.st_connection);
375 if (pp == NULL((void*)0))
376 return;
377
378 while ((p = *pp) != NULL((void*)0)) {
379 if (p->ike == ike) {
380 /* we don't have to worry about deref to free'ed
381 * *pp, because delete_pending updates pp to
382 * point to the next element before it frees *pp
383 */
384 delete_pending(pp); /* in effect, advances pp */
385 } else {
386 pp = &p->next;
387 }
388 }
389}
390
391/* a connection has been deleted; discard any related pending */
392void flush_pending_by_connection(const struct connection *c)
393{
394 struct pending **pp, *p;
395
396 pp = host_pair_first_pending(c);
397 if (pp == NULL((void*)0))
398 return;
399
400 while ((p = *pp) != NULL((void*)0)) {
401 if (p->connection == c) {
402 p->connection = NULL((void*)0); /* prevent delete_pending from releasing */
403 delete_pending(pp); /* in effect, advances pp */
404 } else {
405 pp = &p->next;
406 }
407 }
408}
409
410void show_pending_phase2(struct show *s,
411 const struct connection *c,
412 const struct ike_sa *ike)
413{
414 struct pending **pp, *p;
415
416 pp = host_pair_first_pending(c);
417 if (pp == NULL((void*)0))
418 return;
419
420 for (p = *pp; p != NULL((void*)0); p = p->next) {
421 if (p->ike == ike) {
422 /* connection-name state-number [replacing state-number] */
423 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))
{
424 jam(buf, "#%lu: pending ", p->ike->sa.st_serialno);
425 jam_string(buf, (ike->sa.st_ike_version == IKEv2) ? "CHILD SA" : "Phase 2");
426 jam(buf, " for ");
427 jam_connection(buf, c);
428 if (p->replacing != SOS_NOBODY0) {
429 jam(buf, " replacing #%lu", p->replacing);
430 }
431 }
432 }
433 }
434}
435
436bool_Bool in_pending_use(const struct connection *c)
437{
438 /* see if it is being used by a pending */
439 struct pending **pp, *p;
440
441 pp = host_pair_first_pending(c);
442 if (pp == NULL((void*)0))
443 return FALSE0;
444
445 for (p = *pp; p != NULL((void*)0); p = p->next)
446 if (p->connection == c)
447 return TRUE1; /* in use, so we're done */
448
449 return FALSE0;
450}