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') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
41 | const char host_pair_magic[] = "host pair magic"; | |||
42 | ||||
43 | static 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 | ||||
52 | static 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 | ||||
64 | static 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 | ||||
71 | static 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 | ||||
78 | struct list_head host_pair_buckets[STATE_TABLE_SIZE499]; | |||
79 | ||||
80 | static 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 | ||||
91 | void 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 | ||||
120 | static struct connection *unoriented_connections = NULL((void*)0); | |||
121 | ||||
122 | void 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 | ||||
129 | struct 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 | ||||
143 | struct 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)); } } | |||
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) { | |||
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) && | |||
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)) { | |||
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) && | |||
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) && | |||
193 | !address_is_specified(hp->remote)) { | |||
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)); } } | |||
| ||||
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 | ||||
205 | static 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 | ||||
220 | static 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 | ||||
231 | struct 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 | ||||
253 | void connect_to_host_pair(struct connection *c) | |||
254 | { | |||
255 | if (oriented(c)) { | |||
256 | struct host_pair *hp = find_host_pair(c->spd.this.host_addr, | |||
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 | ||||
288 | void 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 | ||||
360 | void 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 | ||||
382 | void 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 */ | |||
397 | void 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. */ | |||
478 | void 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__ ); } }; | |||
| ||||
488 | struct connection *c = unoriented_connections; | |||
489 | unoriented_connections = NULL((void*)0); | |||
490 | while (c != NULL((void*)0)) { | |||
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); | |||
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 | } |