⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connections.c

📁 ipsec vpn
💻 C
📖 第 1 页 / 共 5 页
字号:
/* information about connections between hosts and clients * Copyright (C) 1998-2002  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.c,v 1.256.2.7 2005/11/17 01:44:12 mcr Exp $ */#include <string.h>#include <stdio.h>#include <stddef.h>#include <stdlib.h>#include <unistd.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/stat.h>#include <netinet/in.h>#include <arpa/inet.h>#include <resolv.h>#include <arpa/nameser.h>     /* missing from <resolv.h> on old systems */#include <sys/queue.h>#include <openswan.h>#include <openswan/ipsec_policy.h>#include "pfkeyv2.h"#include "kameipsec.h"#include "constants.h"#include "defs.h"#include "id.h"#include "x509.h"#include "pgp.h"#include "certs.h"#include "ac.h"#include "smartcard.h"#ifdef XAUTH_USEPAM#include <security/pam_appl.h>#endif#include "connections.h"	/* needs id.h */#include "pending.h"#include "foodgroups.h"#include "packet.h"#include "demux.h"	/* needs packet.h */#include "state.h"#include "timer.h"#include "ipsec_doi.h"	/* needs demux.h and state.h */#include "server.h"#include "kernel.h"	/* needs connections.h */#include "log.h"#include "keys.h"#include "secrets.h"#include "adns.h"	/* needs <resolv.h> */#include "dnskey.h"	/* needs keys.h and adns.h */#include "whack.h"#include "alg_info.h"#include "spdb.h"#include "ike_alg.h"#include "kernel_alg.h"#include "plutoalg.h"#include "xauth.h"#ifdef NAT_TRAVERSAL#include "nat_traversal.h"#endif#ifdef VIRTUAL_IP#include "virtual.h"#endif#ifndef ns_t_txt#define ns_t_txt T_TXT#endif#ifndef ns_t_key#define ns_t_key T_KEY#endifstatic struct connection *connections = NULL;/* struct host_pair: a nexus of information about a pair of hosts. * A host is an IP address, UDP port pair.  This is a debatable choice: * - should port be considered (no choice of port in standard)? * - should ID be considered (hard because not always known)? * - should IP address matter on our end (we don't know our end)? * Only oriented connections are registered. * Unoriented connections are kept on the unoriented_connections * linked list (using hp_next).  For them, host_pair is NULL. */struct host_pair {    struct {	ip_address addr;	u_int16_t  host_port;	        /* IKE port */	bool       host_port_specific;	/* if above is interesting */    } me, him;    bool initial_connection_sent;    struct connection *connections;	/* connections with this pair */    struct pending *pending;	/* awaiting Keying Channel */    struct host_pair *next;};static struct host_pair *host_pairs = NULL;static struct connection *unoriented_connections = NULL;void host_pair_enqueue_pending(const struct connection *c			       , struct pending *p			       , struct pending **pnext){    *pnext = c->host_pair->pending;    c->host_pair->pending = p;}struct pending **host_pair_first_pending(const struct connection *c){    if(c->host_pair == NULL) return NULL;    return &c->host_pair->pending;}    /* check to see that Ids of peers match */boolsame_peer_ids(const struct connection *c, const struct connection *d, const struct id *his_id){    return same_id(&c->spd.this.id, &d->spd.this.id)	&& same_id(his_id == NULL? &c->spd.that.id : his_id, &d->spd.that.id);}/** returns a host pair based upon addresses. *  * find_host_pair is given a pair of addresses, plus UDP ports, and * returns a host_pair entry that covers it. It also moves the relevant * pair description to the beginning of the list, so that it can be * found faster next time. *  */static struct host_pair *find_host_pair(const ip_address *myaddr	       , u_int16_t myport	       , const ip_address *hisaddr	       , u_int16_t hisport){    struct host_pair *p, *prev;    char b1[ADDRTOT_BUF],b2[ADDRTOT_BUF];    /* default hisaddr to an appropriate any */    if (hisaddr == NULL)	hisaddr = aftoinfo(addrtypeof(myaddr))->any;    /*     * look for a host-pair that has the right set of ports/address.     *     */        /*     * for the purposes of comparison, port 500 and 4500 are identical,     * but other ports are not.     * So if any port==4500, then set it to 500.     */    if(myport == 4500) myport=500;    if(hisport== 4500) hisport=500;    for (prev = NULL, p = host_pairs; p != NULL; prev = p, p = p->next)    {	DBG(DBG_CONTROLMORE	    , DBG_log("find_host_pair: comparing to %s:%d %s:%d\n"		      , (addrtot(&p->me.addr, 0, b1, sizeof(b1)), b1)		      , p->me.host_port		      , (addrtot(&p->him.addr, 0, b2, sizeof(b2)), b2)		      , p->him.host_port));		   	if (sameaddr(&p->me.addr, myaddr)	    && (!p->me.host_port_specific || p->me.host_port == myport)	    && sameaddr(&p->him.addr, hisaddr)	    && (!p->him.host_port_specific || p->him.host_port == hisport)	    )	{	    if (prev != NULL)	    {		prev->next = p->next;	/* remove p from list */		p->next = host_pairs;	/* and stick it on front */		host_pairs = p;	    }	    break;	}    }    return p;}/* find head of list of connections with this pair of hosts */static struct connection *find_host_pair_connections(const char *func			   , const ip_address *myaddr, u_int16_t myport			   			   , const ip_address *hisaddr, u_int16_t hisport){    char b1[ADDRTOT_BUF],b2[ADDRTOT_BUF];    struct host_pair *hp = find_host_pair(myaddr, myport, hisaddr, hisport);    DBG(DBG_CONTROLMORE	, DBG_log("find_host_pair_conn (%s): %s:%d %s:%d -> hp:%s\n"		  , func		  , (addrtot(myaddr,  0, b1, sizeof(b1)), b1)		  , myport		  , hisaddr ? (addrtot(hisaddr, 0, b2, sizeof(b2)), b2) : "%any"		  , hisport		  , (hp && hp->connections) ? hp->connections->name : "none"));		       return hp == NULL? NULL : hp->connections;}static voidconnect_to_host_pair(struct connection *c){    if (oriented(*c))    {	struct host_pair *hp = find_host_pair(&c->spd.this.host_addr					      , c->spd.this.host_port					      , &c->spd.that.host_addr					      , c->spd.that.host_port);	char b1[ADDRTOT_BUF],b2[ADDRTOT_BUF];	DBG(DBG_CONTROLMORE	    , DBG_log("connect_to_host_pair: %s:%d %s:%d -> hp:%s\n"		      , (addrtot(&c->spd.this.host_addr, 0, b1,sizeof(b1)), b1)		      , c->spd.this.host_port		      , (addrtot(&c->spd.that.host_addr, 0, b2,sizeof(b2)), b2)		      , c->spd.that.host_port		      , (hp && hp->connections) ? hp->connections->name : "none"));		   	if (hp == NULL)	{	    /* no suitable host_pair -- build one */	    hp = alloc_thing(struct host_pair, "host_pair");	    hp->me.addr = c->spd.this.host_addr;	    hp->him.addr = c->spd.that.host_addr;#ifdef NAT_TRAVERSAL	    hp->me.host_port = nat_traversal_enabled ? pluto_port : c->spd.this.host_port;	    hp->him.host_port = nat_traversal_enabled ? pluto_port : c->spd.that.host_port;#else	    hp->me.host_port = c->spd.this.host_port; 	    hp->him.host_port = c->spd.that.host_port;#endif	    hp->initial_connection_sent = FALSE;	    hp->connections = NULL;	    hp->pending = NULL;	    hp->next = host_pairs;	    host_pairs = hp;	}	c->host_pair = hp;	c->hp_next = hp->connections;	hp->connections = c;    }    else    {	/* since this connection isn't oriented, we place it	 * in the unoriented_connections list instead.	 */	c->host_pair = NULL;	c->hp_next = unoriented_connections;	unoriented_connections = c;    }}/* find a connection by name. * If strict, don't accept a CK_INSTANCE. * Move the winner (if any) to the front. * If none is found, and strict, a diagnostic is logged to whack. */struct connection *con_by_name(const char *nm, bool strict){    struct connection *p, *prev;    for (prev = NULL, p = connections; ; prev = p, p = p->ac_next)    {	if (p == NULL)	{	    if (strict)		whack_log(RC_UNKNOWN_NAME		    , "no connection named \"%s\"", nm);	    break;	}	if (streq(p->name, nm)	&& (!strict || p->kind != CK_INSTANCE))	{	    if (prev != NULL)	    {		prev->ac_next = p->ac_next;	/* remove p from list */		p->ac_next = connections;	/* and stick it on front */		connections = p;	    }	    break;	}    }    return p;}voidrelease_connection(struct connection *c, bool relations){    if (c->kind == CK_INSTANCE)    {	/* This does everything we need.	 * Note that we will be called recursively by delete_connection,	 * but kind will be CK_GOING_AWAY.	 */	delete_connection(c, relations);    }    else    {	flush_pending_by_connection(c);	delete_states_by_connection(c, relations);	unroute_connection(c);    }}/* Delete a connection */#define list_rm(etype, enext, e, ehead) { \	etype **ep; \	for (ep = &(ehead); *ep != (e); ep = &(*ep)->enext) \	    passert(*ep != NULL);    /* we must not come up empty-handed */ \	*ep = (e)->enext; \    }static voiddelete_end(struct connection *c UNUSED, struct spd_route *sr UNUSED, struct end *e){    free_id_content(&e->id);    pfreeany(e->updown);    freeanychunk(e->ca);#ifdef SMARTCARD    scx_release(e->sc);#endif    release_cert(e->cert);    free_ietfAttrList(e->groups);}static voiddelete_sr(struct connection *c, struct spd_route *sr){    delete_end(c, sr, &sr->this);    delete_end(c, sr, &sr->that);}voiddelete_connection(struct connection *c, bool relations){    struct spd_route *sr;    struct connection *old_cur_connection	= cur_connection == c? NULL : cur_connection;#ifdef DEBUG    lset_t old_cur_debugging = cur_debugging;#endif    set_cur_connection(c);    /* Must be careful to avoid circularity:     * we mark c as going away so it won't get deleted recursively.     */    passert(c->kind != CK_GOING_AWAY);    if (c->kind == CK_INSTANCE)    {	openswan_log("deleting connection \"%s\" instance with peer %s {isakmp=#%lu/ipsec=#%lu}"	     , c->name	     , ip_str(&c->spd.that.host_addr)	     , c->newest_isakmp_sa, c->newest_ipsec_sa);	c->kind = CK_GOING_AWAY;    }    else    {	openswan_log("deleting connection");    }    release_connection(c, relations);	/* won't delete c */    if (c->kind == CK_GROUP)	delete_group(c);    /* free up any logging resources */    perpeer_logfree(c);    /* find and delete c from connections list */    list_rm(struct connection, ac_next, c, connections);    cur_connection = old_cur_connection;    /* find and delete c from the host pair list */    if (c->host_pair == NULL)    {	list_rm(struct connection, hp_next, c, unoriented_connections);    }    else    {	struct host_pair *hp = c->host_pair;	list_rm(struct connection, hp_next, c, hp->connections);	c->host_pair = NULL;	/* redundant, but safe */	/* if there are no more connections with this host_pair	 * and we haven't even made an initial contact, let's delete	 * this guy in case we were created by an attempted DOS attack.	 */	if (hp->connections == NULL	&& !hp->initial_connection_sent)	{	    passert(hp->pending == NULL);	/* ??? must deal with this! */	    list_rm(struct host_pair, next, hp, host_pairs);	    pfree(hp);	}    }#ifdef VIRTUAL_IP    if (c->kind != CK_GOING_AWAY) pfreeany(c->spd.that.virt);#endif#ifdef DEBUG    set_debugging(old_cur_debugging);#endif    pfreeany(c->name);    sr = &c->spd;    while(sr) {	delete_sr(c, sr);	sr = sr->next;    }    free_generalNames(c->requested_ca, TRUE);    gw_delref(&c->gw_info);#ifdef KERNEL_ALG    alg_info_delref((struct alg_info **)&c->alg_info_esp);#endif#ifdef IKE_ALG    alg_info_delref((struct alg_info **)&c->alg_info_ike);#endif    pfree(c);}/* Delete connections with the specified name */voiddelete_connections_by_name(const char *name, bool strict){    struct connection *c = con_by_name(name, strict);    for (; c != NULL; c = con_by_name(name, FALSE))	delete_connection(c, FALSE);}voiddelete_every_connection(void){    while (connections != NULL)	delete_connection(connections, TRUE);}voidrelease_dead_interfaces(void){    struct host_pair *hp;    for (hp = host_pairs; hp != NULL; hp = hp->next)    {	struct connection **pp	    , *p;	for (pp = &hp->connections; (p = *pp) != NULL; )	{	    if (p->interface->change == IFN_DELETE)	    {		/* this connection's interface is going away */		enum connection_kind k = p->kind;		release_connection(p, TRUE);		if (k <= CK_PERMANENT)		{		    /* The connection should have survived release:		     * move it to the unoriented_connections list.		     */		    passert(p == *pp);		    p->interface = NULL;		    *pp = p->hp_next;	/* advance *pp */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -