/* information about connections between hosts and clients * Copyright (C) 1998, 1999 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 . * * 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.38 2000/06/21 18:24:31 dhr 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. * "routed" indicates whether the routing has been done for * this connection. * - 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, or SOS_NOBODY if there is none. * * 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] * * When a connection is referenced by a state object, it must have * the IP addresses of the hosts filled in. Some connections are * missing one or the other IP addresses (essentially "wildcarded", * denoted by a value of 0.0.0.0). When one must be filled in (to allow * it to be used by a state object), a new connection is derived from * the old one. It is deleted when no longer in use. */ struct end { struct id id; struct in_addr /* network order */ host_addr, host_nexthop, client_net, client_mask; bool has_client; char *updown; u_int16_t host_port; /* host order */ }; /* test if IPv4 address a is inside end's client subnet * Warning: uses tricky bit twiddling. */ #define inside_client(a, end) \ (0 == (((a).s_addr ^ (end).client_net.s_addr) & (end).client_mask.s_addr)) /* test if client end matches subnet */ #define client_is(end, addr, mask) \ (same_subnet((end).client_net, (end).client_mask, (addr), (mask))) /* test if ends a and b have the same client subnets */ #define same_client(a, b) (client_is((a), (b).client_net, (b).client_mask)) /* test if end's client subnet is just its host */ #define self_client(end) (client_is((end), (end).host_addr, mask32.sin_addr)) 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; struct end this, that; /* internal fields: */ const struct iface *interface; /* filled in iff oriented */ bool routed; /* is routing in place for peer's client? */ so_serial_t /* state object serial number */ newest_isakmp_sa, newest_ipsec_sa, eroute_owner; enum rwcs { rwcs_permanent, /* normal connection */ rwcs_instance, /* instance created for a particular attempt */ rwcs_going_away /* being deleted -- don't delete again */ }; enum rwcs rw_state; #ifdef DEBUG unsigned int extra_debugging; #endif struct host_pair *host_pair; struct connection *hp_next; struct connection *next; }; #define oriented(c) ((c).interface != NULL) extern bool orient(struct connection *c, bool must); extern bool same_peer_ids(const struct connection *c , const struct connection *d, const struct id *his_id); extern size_t format_end(char *buf, size_t buf_len , struct end *this, struct end *that, bool is_left); 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 terminate_connection(const char *nm); extern void unorient_connection(struct connection *c); extern void delete_connection(struct connection *c); extern void delete_every_connection(void); extern void release_interface(struct iface *i); extern struct connection *route_owner(struct connection *c, bool eroute); #define HasWildcardIP(c) (is_NO_IP((c).that.host_addr)) extern struct connection *rw_connection(const struct connection *c, struct in_addr him); struct state; /* forward declaration of tag (defined in state.h) */ extern struct connection *con_by_name(const char *nm, bool strict), *find_host_connection(struct in_addr me, u_int16_t my_port , struct in_addr 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 , struct in_addr our_net, struct in_addr our_mask , struct in_addr peer_net, struct in_addr peer_mask); extern void show_connections_status(void);