1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
|
/* information about connections between hosts and clients
* Copyright (C) 1998-2001 D. Hugh Redelmeier
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id: connections.h,v 1.79 2003/09/02 01:14:00 mcr Exp $
*/
/* There are two kinds of connections:
* - ISAKMP connections, between hosts (for IKE communication)
* - IPsec connections, between clients (for secure IP communication)
*
* An ISAKMP connection looks like:
* host<--->host
*
* An IPsec connection looks like:
* client-subnet<-->host<->nexthop<--->nexthop<->host<-->client-subnet
*
* For the connection to be relevant to this instance of Pluto,
* exactly one of the hosts must be a public interface of our machine
* known to this instance.
*
* The client subnet might simply be the host -- this is a
* representation of "host mode".
*
* Each nexthop defaults to the neighbouring host's IP address.
* The nexthop is a property of the pair of hosts, not each
* individually. It is only needed for IPsec because of the
* way IPsec is mixed into the kernel routing logic. Furthermore,
* only this end's nexthop is actually used. Eventually, nexthop
* will be unnecessary.
*
* Other information represented:
* - each connection has a name: a chunk of uninterpreted text
* that is unique for each connection.
* - security requirements (currently just the "policy" flags from
* the whack command to initiate the connection, but eventually
* much more. Different for ISAKMP and IPsec connections.
* - rekeying parameters:
* + time an SA may live
* + time before SA death that a rekeying should be attempted
* (only by the initiator)
* + number of times to attempt rekeying
* - With the current KLIPS, we must route packets for a client
* subnet through the ipsec interface (ipsec0). Only one
* gateway can get traffic for a specific (client) subnet.
* Furthermore, if the routing isn't in place, packets will
* be sent in the clear.
* "routing" indicates whether the routing has been done for
* this connection. Note that several connections may claim
* the same routing, as long as they agree about where the
* packets are to be sent.
* - With the current KLIPS, only one outbound IPsec SA bundle can be
* used for a particular client. This is due to a limitation
* of using only routing for selection. So only one IPsec state (SA)
* may "own" the eroute. "eroute_owner" is the serial number of
* this state, SOS_NOBODY if there is none. "routing" indicates
* what kind of erouting has been done for this connection, if any.
*
* Details on routing is in constants.h
*
* Operations on Connections:
*
* - add a new connection (with all details) [whack command]
* - delete a connection (by name) [whack command]
* - initiate a connection (by name) [whack command]
* - find a connection (by IP addresses of hosts)
* [response to peer request; finding ISAKMP connection for IPsec connection]
*
* Some connections are templates, missing the address of the peer
* (represented by INADDR_ANY). These are always arranged so that the
* missing end is "that" (there can only be one missing end). These can
* be instantiated (turned into real connections) by Pluto in one of two
* different ways: Road Warrior Instantiation or Opportunistic
* Instantiation. A template connection is marked for Opportunistic
* Instantiation by specifying the peer client as 0.0.0.0/32 (or the IPV6
* equivalent). Otherwise, it is suitable for Road Warrior Instantiation.
*
* Instantiation creates a new temporary connection, with the missing
* details filled in. The resulting template lasts only as long as there
* is a state that uses it.
*/
/* connection policy priority: how important this policy is
* - used to implement eroute-like precedence (augmented by a small
* bonus for a routed connection).
* - a whole number
* - larger is more important
* - three subcomponents. In order of decreasing significance:
* + length of source subnet mask (8 bits)
* + length of destination subnet mask (8 bits)
* + bias (8 bit)
* - a bias of 1 is added to allow prio BOTTOM_PRIO to be less than all
* normal priorities
* - other bias values are created on the fly to give mild preference
* to certaion conditions (eg. routedness)
* - priority is inherited -- an instance of a policy has the same priority
* as the original policy, even though its subnets might be smaller.
* - display format: n,m
*/
typedef unsigned long policy_prio_t;
#define BOTTOM_PRIO ((policy_prio_t)0) /* smaller than any real prio */
#define set_policy_prio(c) { (c)->prio = \
((policy_prio_t)(c)->spd.this.client.maskbits << 16) \
| ((policy_prio_t)(c)->spd.that.client.maskbits << 8) \
| (policy_prio_t)1; }
#define POLICY_PRIO_BUF (3+1+3+1)
extern void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]);
struct end {
struct id id;
ip_address
host_addr,
host_nexthop;
ip_subnet client;
bool key_from_DNS_on_demand;
bool has_client;
char *updown;
u_int16_t host_port; /* host order */
};
struct spd_route {
struct spd_route *next;
struct end this;
struct end that;
so_serial_t eroute_owner;
enum routing_t routing; /* level of routing in place */
uint32_t reqid;
};
struct connection {
char *name;
lset_t policy;
time_t sa_ike_life_seconds;
time_t sa_ipsec_life_seconds;
time_t sa_rekey_margin;
unsigned long sa_rekey_fuzz;
unsigned long sa_keying_tries;
char *log_file_name; /* name of log file */
FILE *log_file; /* possibly open FILE */
CIRCLEQ_ENTRY(connection) log_link; /* linked list of open conns */
bool log_file_err; /* only bitch once */
struct spd_route spd;
/* internal fields: */
unsigned long instance_serial;
policy_prio_t prio;
bool instance_initiation_ok; /* this is an instance of a policy that mandates initiate */
enum connection_kind kind;
const struct iface *interface; /* filled in iff oriented */
so_serial_t /* state object serial number */
newest_isakmp_sa,
newest_ipsec_sa;
#ifdef DEBUG
lset_t extra_debugging;
#endif
/* note: if the client is the gateway, the following must be equal */
sa_family_t addr_family; /* between gateways */
sa_family_t tunnel_addr_family; /* between clients */
struct connection *policy_next; /* if multiple policies,
next one to apply */
struct gw_info *gw_info;
struct host_pair *host_pair;
struct connection *hp_next; /* host pair list link */
struct connection *ac_next; /* all connections list link */
};
#define oriented(c) ((c).interface != NULL)
extern bool orient(struct connection *c);
extern bool same_peer_ids(const struct connection *c
, const struct connection *d, const struct id *his_id);
/* Format the topology of a connection end, leaving out defaults.
* Largest left end looks like: client === host : port [ host_id ] --- hop
* Note: if that==NULL, skip nexthop
*/
#define END_BUF (SUBNETTOT_BUF + ADDRTOT_BUF + IDTOA_BUF + ADDRTOT_BUF + 10)
extern size_t format_end(char *buf, size_t buf_len
, const struct end *this, const struct end *that
, bool is_left, lset_t policy);
struct whack_message; /* forward declaration of tag whack_msg */
extern void add_connection(const struct whack_message *wm);
extern void initiate_connection(const char *name, int whackfd);
extern void initiate_opportunistic(const ip_address *our_client
, const ip_address *peer_client, bool held, int whackfd);
extern void terminate_connection(const char *nm);
extern void release_connection(struct connection *c);
extern void delete_connection(struct connection *c);
extern void delete_connections_by_name(const char *name, bool strict);
extern void delete_every_connection(void);
extern char *add_group_instance(struct connection *group, const ip_subnet *target);
extern void remove_group_instance(const struct connection *group, const char *name);
extern void release_dead_interfaces(void);
extern void check_orientations(void);
extern struct connection *route_owner(struct connection *c
, struct spd_route **srp
, struct connection **erop
, struct spd_route **esrp);
extern struct connection *shunt_owner(const ip_subnet *ours
, const ip_subnet *his);
extern bool uniqueIDs; /* --uniqueids? */
extern void ISAKMP_SA_established(struct connection *c, so_serial_t serial);
#define his_id_was_instantiated(c) ((c)->kind == CK_INSTANCE \
&& id_is_ipaddr(&(c)->spd.that.id) \
&& sameaddr(&(c)->spd.that.id.ip_addr, &(c)->spd.that.host_addr))
struct state; /* forward declaration of tag (defined in state.h) */
extern struct connection
*con_by_name(const char *nm, bool strict),
*find_host_connection(const ip_address *me, u_int16_t my_port
, const ip_address *him, u_int16_t his_port),
*refine_host_connection(const struct state *st, const struct id *id
, bool initiator),
*find_client_connection(struct connection *c
, const ip_subnet *our_net
, const ip_subnet *peer_net),
*find_connection_by_reqid(uint32_t reqid);
extern struct connection *
find_connection_for_clients(struct spd_route **srp
, const ip_address *our_client
, const ip_address *peer_client);
/* instantiating routines
* Note: connection_discard() is in state.h because all its work
* is looking through state objects.
*/
struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
extern struct connection *rw_instantiate(struct connection *c
, const ip_address *him
, const struct id *his_id);
extern struct connection *oppo_instantiate(struct connection *c
, const ip_address *him
, const struct id *his_id
, struct gw_info *gw
, const ip_address *our_client
, const ip_address *peer_client);
extern struct connection
*build_outgoing_opportunistic_connection(struct gw_info *gw
, const ip_address *our_client
, const ip_address *peer_client);
/* worst case: "[" serial "] " myclient "=== ..." peer "===" hisclient '\0' */
#define CONN_INST_BUF \
(2 + 10 + 1 + SUBNETTOT_BUF + 7 + ADDRTOT_BUF + 3 + SUBNETTOT_BUF + 1)
extern void fmt_conn_instance(const struct connection *c
, char buf[CONN_INST_BUF]);
/* operations on "pending", the structure representing Quick Mode
* negotiations delayed until a Keying Channel has been negotiated.
*/
struct pending; /* forward declaration (opaque outside connections.c) */
extern void add_pending(int whack_sock
, struct state *isakmp_sa
, struct connection *c
, lset_t policy
, unsigned long try
, so_serial_t replacing);
extern void release_pending_whacks(struct state *st, err_t story);
extern void unpend(struct state *st);
extern void update_pending(struct state *os, struct state *ns);
extern void flush_pending_by_state(struct state *st);
extern void show_pending_phase2(const struct host_pair *hp, const struct state *st);
extern void connection_discard(struct connection *c);
/* A template connection's eroute can be eclipsed by
* either a %hold or an eroute for an instance iff
* the template is a /32 -> /32. This requires some special casing.
*/
#define eclipsable(sr) (subnetishost(&(sr)->this.client) && subnetishost(&(sr)->that.client))
extern long eclipse_count;
extern struct connection *eclipsed(struct connection *c, struct spd_route **);
/* print connection status */
extern void show_connections_status(void);
extern int connection_compare(const struct connection *ca
, const struct connection *cb);
|