Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name host_pair.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 -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -resource-dir /usr/lib64/clang/13.0.0 -D TimeZoneOffset=timezone -D PIE -D NSS_IPSEC_PROFILE -D XFRM_LIFETIME_DEFAULT=30 -D USE_IKEv1 -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 HAVE_NM -D USE_PAM_AUTH -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 USE_NSS_KDF -D DEFAULT_RUNDIR="/run/pluto" -D IPSEC_CONF="/etc/ipsec.conf" -D IPSEC_CONFDDIR="/etc/ipsec.d" -D IPSEC_NSSDIR="/var/lib/ipsec/nss" -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/quick-libreswan-2/programs/pluto/linux-copy -D HERE_FILENAME="programs/pluto/host_pair.c" -internal-isystem /usr/lib64/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/11/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu99 -fdebug-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -ferror-limit 19 -stack-protector 3 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-01-01-205714-1273399-1 -x c /home/build/quick-libreswan-2/programs/pluto/host_pair.c
1/* information about connections between hosts
2 *
3 * Copyright (C) 1998-2002,2013 D. Hugh Redelmeier <hugh@mimosa.com>
4 * Copyright (C) 2007 Michael Richardson <mcr@xelerance.com>
5 * Copyright (C) 2007 Ken Bantoft <ken@xelerance.com>
6 * Copyright (C) 2008-2010 Paul Wouters <paul@xelerance.com>
7 * Copyright (C) 2010 Tuomo Soini <tis@foobar.fi>
8 * Copyright (C) 2011 Avesh Agarwal <avagarwa@redhat.com>
9 * Copyright (C) 2012 Paul Wouters <paul@libreswan.org>
10 * Copyright (C) 2013-2019 Paul Wouters <pwouters@redhat.com>
11 * Copyright (C) 2019 Andrew Cagney <cagney@gnu.org>
12 * Copyright (C) 2021 Paul Wouters <paul.wouters@aiven.io>
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 *
24 */
25
26#include "defs.h"
27#include "connections.h"
28#include "pending.h"
29#include "kernel.h" /* for unroute_connection(c) */
30#include "log.h"
31#include "ip_info.h"
32#include "hash_table.h"
33#include "iface.h"
34#include "orient.h"
35#include "host_pair.h"
36
37/*
38 * Table of host_pairs (local->remote endpoints/addresses).
39 */
40
41const char host_pair_magic[] = "host pair magic";
42
43static void jam_host_pair(struct jambuf *buf, const void *data)
44{
45 const struct host_pair *hp = data;
46 passert(hp->magic == host_pair_magic)({ _Bool assertion__ = hp->magic == host_pair_magic; if (!
assertion__) { where_t here = ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/host_pair.c", .
line = 46, }; &here; }); const struct logger *logger_ = &
failsafe_logger; llog_passert(logger_, here, "%s", "hp->magic == host_pair_magic"
); } (void) 1; })
;
47 jam_address(buf, &hp->local);
48 jam(buf, "->");
49 jam_address(buf, &hp->remote);
50}
51
52static hash_t hp_hasher(const ip_address local, const ip_address remote)
53{
54 hash_t hash = zero_hash;
55 if (pexpect(address_is_specified(local))({ _Bool assertion__ = address_is_specified(local); if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/host_pair.c", .line = 55
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "address_is_specified(local)"
); } assertion__; })
) {
56 hash = hash_table_hasher(address_as_shunk(&local), hash);
57 }
58 if (address_is_specified(remote)) {
59 hash = hash_table_hasher(address_as_shunk(&remote), hash);
60 }
61 return hash;
62}
63
64static hash_t host_pair_hasher(const void *data)
65{
66 const struct host_pair *hp = data;
67 passert(hp->magic == host_pair_magic)({ _Bool assertion__ = hp->magic == host_pair_magic; if (!
assertion__) { where_t here = ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/host_pair.c", .
line = 67, }; &here; }); const struct logger *logger_ = &
failsafe_logger; llog_passert(logger_, here, "%s", "hp->magic == host_pair_magic"
); } (void) 1; })
;
68 return hp_hasher(hp->local, hp->remote);
69}
70
71static struct list_entry *host_pair_list_entry(void *data)
72{
73 struct host_pair *hp = data;
74 passert(hp->magic == host_pair_magic)({ _Bool assertion__ = hp->magic == host_pair_magic; if (!
assertion__) { where_t here = ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/host_pair.c", .
line = 74, }; &here; }); const struct logger *logger_ = &
failsafe_logger; llog_passert(logger_, here, "%s", "hp->magic == host_pair_magic"
); } (void) 1; })
;
75 return &hp->host_pair_entry;
76}
77
78struct list_head host_pair_buckets[STATE_TABLE_SIZE499];
79
80static struct hash_table host_pairs = {
81 .info = {
82 .name = "host_pair table",
83 .jam = jam_host_pair,
84 },
85 .hasher = host_pair_hasher,
86 .entry = host_pair_list_entry,
87 .nr_slots = elemsof(host_pair_buckets)(sizeof(host_pair_buckets) / sizeof(*(host_pair_buckets))),
88 .slots = host_pair_buckets,
89};
90
91void init_host_pair(void)
92{
93 init_hash_table(&host_pairs);
94}
95
96#define LIST_RM(ENEXT, E, EHEAD, EXPECTED){ _Bool found_ = 0; for (typeof(*(EHEAD)) **ep_ = &(EHEAD
); *ep_ != ((void*)0); ep_ = &(*ep_)->ENEXT) { if (*ep_
== (E)) { *ep_ = (E)->ENEXT; found_ = 1; break; } } ({ _Bool
assertion__ = found_ || !(EXPECTED); if (!assertion__) { where_t
here_ = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/host_pair.c", .line = 96, }; &here
; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect
(logger_, here_, "%s", "found_ || !(EXPECTED)"); } assertion__
; }); }
\
97 { \
98 bool_Bool found_ = false0; \
99 for (typeof(*(EHEAD)) **ep_ = &(EHEAD); *ep_ != NULL((void*)0); ep_ = &(*ep_)->ENEXT) { \
100 if (*ep_ == (E)) { \
101 *ep_ = (E)->ENEXT; \
102 found_ = true1; \
103 break; \
104 } \
105 } \
106 /* we must not come up empty-handed? */ \
107 pexpect(found_ || !(EXPECTED))({ _Bool assertion__ = found_ || !(EXPECTED); if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/host_pair.c", .line = 107
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "found_ || !(EXPECTED)")
; } assertion__; })
; \
108 }
109
110/* struct host_pair: a nexus of information about a pair of hosts.
111 * A host is an IP address, UDP port pair. This is a debatable choice:
112 * - should port be considered (no choice of port in standard)?
113 * - should ID be considered (hard because not always known)?
114 * - should IP address matter on our end (we don't know our end)?
115 * Only oriented connections are registered.
116 * Unoriented connections are kept on the unoriented_connections
117 * linked list (using hp_next). For them, host_pair is NULL.
118 */
119
120static struct connection *unoriented_connections = NULL((void*)0);
121
122void host_pair_enqueue_pending(const struct connection *c,
123 struct pending *p)
124{
125 p->next = c->host_pair->pending;
126 c->host_pair->pending = p;
127}
128
129struct pending **host_pair_first_pending(const struct connection *c)
130{
131 if (c->host_pair == NULL((void*)0))
132 return NULL((void*)0);
133
134 return &c->host_pair->pending;
135}
136
137/*
138 * Returns a host-pair based upon addresses.
139 *
140 * REMOTE can either be a valid address or UNSET_ADDRESS.
141 */
142
143struct host_pair *find_host_pair(const ip_address local,
144 const ip_address remote)
145{
146 address_buf lb, rb;
147 dbg("looking for host pair matching %s->%s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("looking for host pair matching %s->%s", str_address
(&local, &lb), str_address(&remote, &rb)); } }
9
Assuming the condition is false
10
Taking false branch
148 str_address(&local, &lb), str_address(&remote, &rb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("looking for host pair matching %s->%s", str_address
(&local, &lb), str_address(&remote, &rb)); } }
;
149 hash_t hash = hp_hasher(local, remote);
150 struct host_pair *hp = NULL((void*)0);
151 struct list_head *bucket = hash_table_bucket(&host_pairs, hash);
152 FOR_EACH_LIST_ENTRY_NEW2OLD(bucket, hp)for (struct list_entry *entry_ = (bucket)->head.older; entry_
!= ((void*)0); entry_ = ((void*)0)) for (hp = (typeof(hp))entry_
->data, entry_ = entry_->older; hp != ((void*)0); hp = (
typeof(hp))entry_->data, entry_ = entry_->older)
{
11
Assuming 'entry_' is not equal to null
12
Loop condition is true. Entering loop body
13
Assuming 'hp' is not equal to null
14
Loop condition is true. Entering loop body
153 /*
154 * Skip when the first connection is an instance;
155 * why????
156 */
157 if (hp->connections != NULL((void*)0) && (hp->connections->kind == CK_INSTANCE) &&
15
Assuming field 'connections' is equal to NULL
158 (hp->connections->spd.that.id.kind == ID_NULL)) {
159 connection_buf ci;
160 dbg("find_host_pair: ignore CK_INSTANCE with ID_NULL hp:"PRI_CONNECTION,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("find_host_pair: ignore CK_INSTANCE with ID_NULL hp:"
"\"%s\"%s", (hp->connections)->name, str_connection_instance
(hp->connections, &ci)); } }
161 pri_connection(hp->connections, &ci)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("find_host_pair: ignore CK_INSTANCE with ID_NULL hp:"
"\"%s\"%s", (hp->connections)->name, str_connection_instance
(hp->connections, &ci)); } }
;
162 continue;
163 }
164
165 if (!address_eq_address(hp->local, local)) {
16
Assuming the condition is false
17
Taking false branch
166 address_buf lb;
167 connection_buf cb;
168 if (hp->connections == NULL((void*)0)) {
169 /* ??? what should we report? */
170 dbg("host_pair: local %s does not match connection=<NULL>",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("host_pair: local %s does not match connection=<NULL>"
, str_address(&local, &lb)); } }
171 str_address(&local, &lb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("host_pair: local %s does not match connection=<NULL>"
, str_address(&local, &lb)); } }
;
172 } else {
173 dbg("host_pair: local %s does not match connection="PRI_CONNECTION,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("host_pair: local %s does not match connection="
"\"%s\"%s", str_address(&local, &lb), (hp->connections
)->name, str_connection_instance(hp->connections, &
cb)); } }
174 str_address(&local, &lb),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("host_pair: local %s does not match connection="
"\"%s\"%s", str_address(&local, &lb), (hp->connections
)->name, str_connection_instance(hp->connections, &
cb)); } }
175 pri_connection(hp->connections, &cb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("host_pair: local %s does not match connection="
"\"%s\"%s", str_address(&local, &lb), (hp->connections
)->name, str_connection_instance(hp->connections, &
cb)); } }
;
176 }
177 continue;
178 }
179
180 /* now try to match */
181
182 if (address_is_specified(remote) &&
18
Assuming the condition is false
183 address_eq_address(remote, hp->remote)) {
184 connection_buf cb;
185 address_buf lb, rb;
186 dbg("host_pair: %s->%s exactly matches connection "PRI_CONNECTION,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("host_pair: %s->%s exactly matches connection "
"\"%s\"%s", str_address(&local, &lb), str_address(&
remote, &rb), (hp->connections)->name, str_connection_instance
(hp->connections, &cb)); } }
187 str_address(&local, &lb), str_address(&remote, &rb),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("host_pair: %s->%s exactly matches connection "
"\"%s\"%s", str_address(&local, &lb), str_address(&
remote, &rb), (hp->connections)->name, str_connection_instance
(hp->connections, &cb)); } }
188 pri_connection(hp->connections, &cb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("host_pair: %s->%s exactly matches connection "
"\"%s\"%s", str_address(&local, &lb), str_address(&
remote, &rb), (hp->connections)->name, str_connection_instance
(hp->connections, &cb)); } }
;
189 return hp;
190 }
191
192 if (!address_is_specified(remote) &&
19
Assuming the condition is true
21
Taking true branch
193 !address_is_specified(hp->remote)) {
20
Assuming the condition is true
194 connection_buf cb;
195 address_buf lb, rb;
196 dbg("host_pair: %s->%s any matched connection="PRI_CONNECTION,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("host_pair: %s->%s any matched connection="
"\"%s\"%s", str_address(&local, &lb), str_address(&
remote, &rb), (hp->connections)->name, str_connection_instance
(hp->connections, &cb)); } }
22
Assuming the condition is true
23
Taking true branch
24
Access to field 'name' results in a dereference of a null pointer (loaded from field 'connections')
197 str_address(&local, &lb), str_address(&remote, &rb),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("host_pair: %s->%s any matched connection="
"\"%s\"%s", str_address(&local, &lb), str_address(&
remote, &rb), (hp->connections)->name, str_connection_instance
(hp->connections, &cb)); } }
198 pri_connection(hp->connections, &cb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("host_pair: %s->%s any matched connection="
"\"%s\"%s", str_address(&local, &lb), str_address(&
remote, &rb), (hp->connections)->name, str_connection_instance
(hp->connections, &cb)); } }
;
199 return hp;
200 }
201 }
202 return NULL((void*)0);
203}
204
205static struct host_pair *alloc_host_pair(ip_address local, ip_address remote, where_t where)
206{
207 struct host_pair *hp = alloc_thing(struct host_pair, "host pair")((struct host_pair*) alloc_bytes(sizeof(struct host_pair), ("host pair"
)))
;
208 hp->magic = host_pair_magic;
209 hp->local = local;
210 /*
211 * Force unset/NULL to 'any' a.k.a. zero; so hash is
212 * consistent and comparisons work.
213 */
214 hp->remote = (address_is_unset(&remote) ? address_type(&local)->address.any : remote);
215 add_hash_table_entry(&host_pairs, hp);
216 dbg_alloc("hp", hp, where);
217 return hp;
218}
219
220static void free_host_pair(struct host_pair **hp, where_t where)
221{
222 /* ??? must deal with this! */
223 passert((*hp)->pending == NULL)({ _Bool assertion__ = (*hp)->pending == ((void*)0); if (!
assertion__) { where_t here = ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/host_pair.c", .
line = 223, }; &here; }); const struct logger *logger_ = &
failsafe_logger; llog_passert(logger_, here, "%s", "(*hp)->pending == ((void*)0)"
); } (void) 1; })
;
224 pexpect((*hp)->connections == NULL)({ _Bool assertion__ = (*hp)->connections == ((void*)0); if
(!assertion__) { where_t here_ = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/host_pair.c"
, .line = 224, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "(*hp)->connections == ((void*)0)"
); } assertion__; })
;
225 del_hash_table_entry(&host_pairs, *hp);
226 dbg_free("hp", *hp, where);
227 pfree(*hp);
228 *hp = NULL((void*)0);
229}
230
231struct connection *next_host_pair_connection(const ip_address local,
232 const ip_address remote,
233 struct connection **next,
234 bool_Bool first,
235 where_t where)
236{
237 /* for moment just wrap above; should merge */
238 struct connection *c;
239 if (first) {
240 address_buf lb, rb;
241 dbg("FOR_EACH_HOST_PAIR_CONNECTION(%s->%s) in "PRI_WHERE,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("FOR_EACH_HOST_PAIR_CONNECTION(%s->%s) in "
"(%s() +%lu %s)", str_address(&local, &lb), str_address
(&remote, &rb), (where)->func, (where)->line, (
where)->file); } }
242 str_address(&local, &lb), str_address(&remote, &rb),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("FOR_EACH_HOST_PAIR_CONNECTION(%s->%s) in "
"(%s() +%lu %s)", str_address(&local, &lb), str_address
(&remote, &rb), (where)->func, (where)->line, (
where)->file); } }
243 pri_where(where)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("FOR_EACH_HOST_PAIR_CONNECTION(%s->%s) in "
"(%s() +%lu %s)", str_address(&local, &lb), str_address
(&remote, &rb), (where)->func, (where)->line, (
where)->file); } }
;
244 struct host_pair *hp = find_host_pair(local, remote);
245 c = (hp != NULL((void*)0)) ? hp->connections : NULL((void*)0);
246 } else {
247 c = *next;
248 }
249 *next = (c != NULL((void*)0)) ? c->hp_next : NULL((void*)0);
250 return c;
251}
252
253void connect_to_host_pair(struct connection *c)
254{
255 if (oriented(c)) {
6
Assuming the condition is true
7
Taking true branch
256 struct host_pair *hp = find_host_pair(c->spd.this.host_addr,
8
Calling 'find_host_pair'
257 /* remote could be unset OR any */
258 c->spd.that.host_addr);
259
260 address_buf b1, b2;
261 dbg("connect_to_host_pair: %s->%s -> hp@%p: %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connect_to_host_pair: %s->%s -> hp@%p: %s"
, str_address(&c->spd.this.host_addr, &b1), str_address
(&c->spd.that.host_addr, &b2), hp, (hp != ((void*)
0) && hp->connections != ((void*)0)) ? hp->connections
->name : "none"); } }
262 str_address(&c->spd.this.host_addr, &b1),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connect_to_host_pair: %s->%s -> hp@%p: %s"
, str_address(&c->spd.this.host_addr, &b1), str_address
(&c->spd.that.host_addr, &b2), hp, (hp != ((void*)
0) && hp->connections != ((void*)0)) ? hp->connections
->name : "none"); } }
263 str_address(&c->spd.that.host_addr, &b2),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connect_to_host_pair: %s->%s -> hp@%p: %s"
, str_address(&c->spd.this.host_addr, &b1), str_address
(&c->spd.that.host_addr, &b2), hp, (hp != ((void*)
0) && hp->connections != ((void*)0)) ? hp->connections
->name : "none"); } }
264 hp, (hp != NULL && hp->connections != NULL) ? hp->connections->name : "none"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connect_to_host_pair: %s->%s -> hp@%p: %s"
, str_address(&c->spd.this.host_addr, &b1), str_address
(&c->spd.that.host_addr, &b2), hp, (hp != ((void*)
0) && hp->connections != ((void*)0)) ? hp->connections
->name : "none"); } }
;
265
266 if (hp == NULL((void*)0)) {
267 /* no suitable host_pair -- build one */
268 ip_address local = c->spd.this.host_addr;
269 /* remote could be unset OR any */
270 ip_address remote = c->spd.that.host_addr;
271 hp = alloc_host_pair(local, remote, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/host_pair.c", .line = 271, }; &here; }
)
);
272 }
273 c->host_pair = hp;
274 c->hp_next = hp->connections;
275 hp->connections = c;
276 } else {
277 /* since this connection isn't oriented, we place it
278 * in the unoriented_connections list instead.
279 */
280 pexpect(c->host_pair == NULL)({ _Bool assertion__ = c->host_pair == ((void*)0); if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/host_pair.c", .line = 280
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "c->host_pair == ((void*)0)"
); } assertion__; })
;
281 pexpect(c->interface == NULL)({ _Bool assertion__ = c->interface == ((void*)0); if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/host_pair.c", .line = 281
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "c->interface == ((void*)0)"
); } assertion__; })
;
282 c->host_pair = NULL((void*)0);
283 c->hp_next = unoriented_connections;
284 unoriented_connections = c;
285 }
286}
287
288void release_dead_interfaces(struct logger *logger)
289{
290 /*
291 * Delete any connections with a dead interface. Deleting the
292 * connection could (?) trigger deleting other connections,
293 * but presumably they are further down in the list?
294 */
295 struct connection_query cq = { .where = HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/host_pair.c", .line = 295, }; &here; }
)
, .c = NULL((void*)0), };
296 while (new2old_connection(&cq)) {
297 struct connection *c = cq.c;
298
299 if (!oriented(c)) {
300 connection_buf cb;
301 dbg("connection interface un-oriented: "PRI_CONNECTION,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection interface un-oriented: ""\"%s\"%s"
, (c)->name, str_connection_instance(c, &cb)); } }
302 pri_connection(c, &cb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection interface un-oriented: ""\"%s\"%s"
, (c)->name, str_connection_instance(c, &cb)); } }
;
303 continue;
304 }
305
306 passert(c->interface != NULL)({ _Bool assertion__ = c->interface != ((void*)0); if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/host_pair.c", .line = 306
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "c->interface != ((void*)0)"
); } (void) 1; })
; /* aka oriented() */
307 if (c->interface->ip_dev->ifd_change != IFD_DELETE) {
308 connection_buf cb;
309 dbg("connection interface safe: "PRI_CONNECTION,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection interface safe: ""\"%s\"%s", (c)->
name, str_connection_instance(c, &cb)); } }
310 pri_connection(c, &cb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection interface safe: ""\"%s\"%s", (c)->
name, str_connection_instance(c, &cb)); } }
;
311 continue;
312 }
313
314 connection_buf cb;
315 dbg("connection interface deleted: "PRI_CONNECTION,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection interface deleted: ""\"%s\"%s", (c
)->name, str_connection_instance(c, &cb)); } }
316 pri_connection(c, &cb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("connection interface deleted: ""\"%s\"%s", (c
)->name, str_connection_instance(c, &cb)); } }
;
317
318 /* XXX: something better? */
319 close_any(&c->logger->global_whackfd)close_any_fd((&c->logger->global_whackfd), ({ static
const struct where here = { .func = __func__, .file = "programs/pluto/host_pair.c"
, .line = 319, }; &here; }))
;
320 c->logger->global_whackfd = fd_dup(logger->global_whackfd, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/host_pair.c", .line = 320, }; &here; }
)
);
321
322 /*
323 * This connection instance interface is going away.
324 * Note: this used to pass relations as true, to cleanup
325 * everything but that did not take into account a site to
326 * site conn on right=%any also being an instance.
327 *
328 * If there's a template then it is earlier so not
329 * affected by this.
330 */
331 if (c->kind == CK_INSTANCE) {
332 delete_connection(&c, /*relations?*/false0);
333 pexpect(c == NULL)({ _Bool assertion__ = c == ((void*)0); if (!assertion__) { where_t
here_ = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/host_pair.c", .line = 333, }; &
here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "c == ((void*)0)"); } assertion__
; })
;
334 continue;
335 }
336
337 /*
338 * The connection is somewhat permenant; release it
339 * and move it to the unoriented_connections list.
340 */
341 release_connection(c, /*relations?*/true1);
342 terminate_connections_by_name(c->name, /*quiet?*/false0, logger);
343
344 /*
345 * disorient connection and then put on the unoriented
346 * list.
347 */
348 pexpect(c->host_pair != NULL)({ _Bool assertion__ = c->host_pair != ((void*)0); if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/host_pair.c", .line = 348
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "c->host_pair != ((void*)0)"
); } assertion__; })
;
349 delete_oriented_hp(c);
350 c->interface = NULL((void*)0);
351 c->hp_next = unoriented_connections;
352 unoriented_connections = c;
353 pexpect(c->host_pair == NULL)({ _Bool assertion__ = c->host_pair == ((void*)0); if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/host_pair.c", .line = 353
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "c->host_pair == ((void*)0)"
); } assertion__; })
;
354
355 /* XXX: something better? */
356 close_any(&c->logger->global_whackfd)close_any_fd((&c->logger->global_whackfd), ({ static
const struct where here = { .func = __func__, .file = "programs/pluto/host_pair.c"
, .line = 356, }; &here; }))
;
357 }
358}
359
360void delete_oriented_hp(struct connection *c)
361{
362 struct host_pair *hp = c->host_pair;
363
364 pexpect(c->host_pair != NULL)({ _Bool assertion__ = c->host_pair != ((void*)0); if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/host_pair.c", .line = 364
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "c->host_pair != ((void*)0)"
); } assertion__; })
;
365 pexpect(c->interface != NULL)({ _Bool assertion__ = c->interface != ((void*)0); if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/host_pair.c", .line = 365
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "c->interface != ((void*)0)"
); } assertion__; })
;
366
367 LIST_RM(hp_next, c, hp->connections, true/*expected*/){ _Bool found_ = 0; for (typeof(*(hp->connections)) **ep_ =
&(hp->connections); *ep_ != ((void*)0); ep_ = &(*
ep_)->hp_next) { if (*ep_ == (c)) { *ep_ = (c)->hp_next
; found_ = 1; break; } } ({ _Bool assertion__ = found_ || !(1
); if (!assertion__) { where_t here_ = ({ static const struct
where here = { .func = __func__, .file = "programs/pluto/host_pair.c"
, .line = 367, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "found_ || !(1)"
); } assertion__; }); }
;
368
369 pexpect(c->host_pair != NULL)({ _Bool assertion__ = c->host_pair != ((void*)0); if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/host_pair.c", .line = 369
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "c->host_pair != ((void*)0)"
); } assertion__; })
;
370 c->host_pair = NULL((void*)0);
371
372 /*
373 * If there are no more connections with this host_pair and we
374 * haven't even made an initial contact, let's delete this guy
375 * in case we were created by an attempted DOS attack.
376 */
377 if (hp->connections == NULL((void*)0)) {
378 free_host_pair(&hp, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/host_pair.c", .line = 378, }; &here; }
)
);
379 }
380}
381
382void host_pair_remove_connection(struct connection *c, bool_Bool connection_valid)
383{
384 if (c->host_pair == NULL((void*)0)) {
385 /*
386 * When CONNECTION_VALID expect to find/remove C from
387 * the unoriented list.
388 */
389 LIST_RM(hp_next, c, unoriented_connections,{ _Bool found_ = 0; for (typeof(*(unoriented_connections)) **
ep_ = &(unoriented_connections); *ep_ != ((void*)0); ep_ =
&(*ep_)->hp_next) { if (*ep_ == (c)) { *ep_ = (c)->
hp_next; found_ = 1; break; } } ({ _Bool assertion__ = found_
|| !(connection_valid); if (!assertion__) { where_t here_ = (
{ static const struct where here = { .func = __func__, .file =
"programs/pluto/host_pair.c", .line = 390, }; &here; });
const struct logger *logger_ = &failsafe_logger; llog_pexpect
(logger_, here_, "%s", "found_ || !(connection_valid)"); } assertion__
; }); }
390 connection_valid){ _Bool found_ = 0; for (typeof(*(unoriented_connections)) **
ep_ = &(unoriented_connections); *ep_ != ((void*)0); ep_ =
&(*ep_)->hp_next) { if (*ep_ == (c)) { *ep_ = (c)->
hp_next; found_ = 1; break; } } ({ _Bool assertion__ = found_
|| !(connection_valid); if (!assertion__) { where_t here_ = (
{ static const struct where here = { .func = __func__, .file =
"programs/pluto/host_pair.c", .line = 390, }; &here; });
const struct logger *logger_ = &failsafe_logger; llog_pexpect
(logger_, here_, "%s", "found_ || !(connection_valid)"); } assertion__
; }); }
;
391 } else {
392 delete_oriented_hp(c);
393 }
394}
395
396/* update the host pairs with the latest DNS ip address */
397void update_host_pairs(struct connection *c)
398{
399 struct host_pair *hp = c->host_pair;
400 const char *dnshostname = c->dnshostname;
401
402 /* ??? perhaps we should return early if dnshostname == NULL */
403
404 if (hp == NULL((void*)0))
405 return;
406
407 struct connection *d = hp->connections;
408
409 /* ??? looks as if addr_family is not allowed to change. Bug? */
410 /* ??? why are we using d->dnshostname instead of (c->)dnshostname? */
411 /* ??? code used to test for d == NULL, but that seems impossible. */
412
413 pexpect(dnshostname == d->dnshostname || streq(dnshostname, d->dnshostname))({ _Bool assertion__ = dnshostname == d->dnshostname || (strcmp
((dnshostname), (d->dnshostname)) == 0); if (!assertion__)
{ where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/host_pair.c", .line = 413
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "dnshostname == d->dnshostname || (strcmp((dnshostname), (d->dnshostname)) == 0)"
); } assertion__; })
;
414
415 ip_address new_addr;
416
417 if (d->dnshostname == NULL((void*)0) ||
418 ttoaddress_dns(shunk1(d->dnshostname),
419 address_type(&d->spd.that.host_addr), &new_addr) != NULL((void*)0) ||
420 sameaddr(&new_addr, &hp->remote))
421 return;
422
423 struct connection *conn_list = NULL((void*)0);
424
425 while (d != NULL((void*)0)) {
426 struct connection *nxt = d->hp_next;
427
428 /*
429 * ??? this test used to assume that dnshostname != NULL
430 * if d->dnshostname != NULL. Is that true?
431 */
432 if (d->dnshostname != NULL((void*)0) && dnshostname != NULL((void*)0) &&
433 streq(d->dnshostname, dnshostname)(strcmp((d->dnshostname), (dnshostname)) == 0)) {
434 /*
435 * If there is a dnshostname and it is the same as
436 * the one that has changed, then change
437 * the connection's remote host address and remove
438 * the connection from the host pair.
439 */
440
441 /*
442 * Unroute the old connection before changing the ip
443 * address.
444 */
445 unroute_connection(d);
446
447 /*
448 * If the client is the peer, also update the
449 * client info
450 */
451 if (!d->spd.that.has_client) {
452 d->spd.that.client = selector_from_address(new_addr);
453 }
454
455 d->spd.that.host_addr = new_addr;
456 LIST_RM(hp_next, d, d->host_pair->connections, true){ _Bool found_ = 0; for (typeof(*(d->host_pair->connections
)) **ep_ = &(d->host_pair->connections); *ep_ != ((
void*)0); ep_ = &(*ep_)->hp_next) { if (*ep_ == (d)) {
*ep_ = (d)->hp_next; found_ = 1; break; } } ({ _Bool assertion__
= found_ || !(1); if (!assertion__) { where_t here_ = ({ static
const struct where here = { .func = __func__, .file = "programs/pluto/host_pair.c"
, .line = 456, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "found_ || !(1)"
); } assertion__; }); }
;
457
458 d->hp_next = conn_list;
459 conn_list = d;
460 }
461 d = nxt;
462 }
463
464 while (conn_list != NULL((void*)0)) {
465 struct connection *nxt = conn_list->hp_next;
466
467 /* assumption: orientation is the same as before */
468 connect_to_host_pair(conn_list);
469 conn_list = nxt;
470 }
471
472 if (hp->connections == NULL((void*)0)) {
473 free_host_pair(&hp, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/host_pair.c", .line = 473, }; &here; }
)
);
474 }
475}
476
477/* Adjust orientations of connections to reflect newly added interfaces. */
478void check_orientations(struct logger *logger)
479{
480 /*
481 * Try to orient unoriented connections by re-building the
482 * unoriented connections list.
483 *
484 * The list is emptied, then as each connection fails to
485 * orient it goes back on the list.
486 */
487 dbg("FOR_EACH_UNORIENTED_CONNECTION_... in %s", __func__){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("FOR_EACH_UNORIENTED_CONNECTION_... in %s", __func__
); } }
;
1
Assuming the condition is false
2
Taking false branch
488 struct connection *c = unoriented_connections;
489 unoriented_connections = NULL((void*)0);
490 while (c != NULL((void*)0)) {
3
Assuming 'c' is not equal to NULL
4
Loop condition is true. Entering loop body
491 /* step off */
492 struct connection *nxt = c->hp_next;
493 orient(c, logger);
494 /*
495 * Either put C back on unoriented, or add to a host
496 * pair.
497 */
498 connect_to_host_pair(c);
5
Calling 'connect_to_host_pair'
499 c = nxt;
500 }
501
502 /*
503 * Check that no oriented connection has become double-oriented.
504 * In other words, the far side must not match one of our new
505 * interfaces.
506 */
507 for (struct iface_endpoint *i = interfaces; i != NULL((void*)0); i = i->next) {
508 if (i->ip_dev->ifd_change != IFD_ADD) {
509 continue;
510 }
511 for (unsigned u = 0; u < host_pairs.nr_slots; u++) {
512 struct list_head *bucket = &host_pairs.slots[u];
513 struct host_pair *hp = NULL((void*)0);
514 FOR_EACH_LIST_ENTRY_NEW2OLD(bucket, hp)for (struct list_entry *entry_ = (bucket)->head.older; entry_
!= ((void*)0); entry_ = ((void*)0)) for (hp = (typeof(hp))entry_
->data, entry_ = entry_->older; hp != ((void*)0); hp = (
typeof(hp))entry_->data, entry_ = entry_->older)
{
515 /*
516 * XXX: what's with the maybe compare
517 * the port logic?
518 */
519 if (sameaddr(&hp->remote,
520 &i->ip_dev->id_address)) {
521 /*
522 * bad news: the whole chain
523 * of connections hanging off
524 * this host pair has both
525 * sides matching an
526 * interface. We'll get rid
527 * of them, using orient and
528 * connect_to_host_pair.
529 */
530 struct connection *c =
531 hp->connections;
532 hp->connections = NULL((void*)0);
533 while (c != NULL((void*)0)) {
534 struct connection *nxt =
535 c->hp_next;
536 c->interface = NULL((void*)0);
537 c->host_pair = NULL((void*)0);
538 c->hp_next = NULL((void*)0);
539 orient(c, logger);
540 connect_to_host_pair(c);
541 c = nxt;
542 }
543 /*
544 * XXX: is this ever not the
545 * case?
546 */
547 if (hp->connections == NULL((void*)0)) {
548 free_host_pair(&hp, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/host_pair.c", .line = 548, }; &here; }
)
);
549 }
550 }
551 }
552 }
553 }
554}