| File: | programs/pluto/host_pair.c |
| Warning: | line 186, 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 | } |