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

📄 connections.c

📁 ipsec vpn
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif	/* add to connections list */	t->ac_next = connections;	connections = t;	/* same host_pair as parent: stick after parent on list */	group->hp_next = t;	/* route if group is routed */	if (group->policy & POLICY_GROUTED)	{	    if (!trap_connection(t))		whack_log(RC_ROUTE, "could not route");	}    }    return name;}/* an old target has disappeared for a group: delete instance */voidremove_group_instance(const struct connection *group USED_BY_DEBUG, const char *name){    passert(group->kind == CK_GROUP);    passert(oriented(*group));    delete_connections_by_name(name, FALSE);}/* Common part of instantiating a Road Warrior or Opportunistic connection. * his_id can be used to carry over an ID discovered in Phase 1. * It must not disagree with the one in c, but if that is unspecified, * the new connection will use his_id. * If his_id is NULL, and c.that.id is uninstantiated (ID_NONE), the * new connection will continue to have an uninstantiated that.id. * Note: instantiation does not affect port numbers. * * Note that instantiate can only deal with a single SPD/eroute. */static struct connection *instantiate(struct connection *c, const ip_address *him	    , const struct id *his_id){    struct connection *d;    int wildcards;    passert(c->kind == CK_TEMPLATE);    passert(c->spd.next == NULL);    c->instance_serial++;    d = clone_thing(*c, "temporary connection");    if (his_id != NULL)    {	passert(match_id(his_id, &d->spd.that.id, &wildcards));	d->spd.that.id = *his_id;	d->spd.that.has_id_wildcards = FALSE;    }    unshare_connection_strings(d);    unshare_ietfAttrList(&d->spd.this.groups);    unshare_ietfAttrList(&d->spd.that.groups);#ifdef KERNEL_ALG    alg_info_addref((struct alg_info *)d->alg_info_esp);#endif#ifdef IKE_ALG    alg_info_addref((struct alg_info *)d->alg_info_ike);#endif    d->kind = CK_INSTANCE;    passert(oriented(*d));    d->spd.that.host_addr = *him;    setportof(htons(c->spd.that.port), &d->spd.that.host_addr);    default_end(&d->spd.that, &d->spd.this.host_addr);    /* We cannot guess what our next_hop should be, but if it was     * explicitly specified as 0.0.0.0, we set it to be him.     * (whack will not allow nexthop to be elided in RW case.)     */    default_end(&d->spd.this, &d->spd.that.host_addr);    d->spd.next = NULL;    d->spd.reqid = gen_reqid();    /* set internal fields */    d->ac_next = connections;    connections = d;    d->spd.routing = RT_UNROUTED;    d->newest_isakmp_sa = SOS_NOBODY;    d->newest_ipsec_sa = SOS_NOBODY;    d->spd.eroute_owner = SOS_NOBODY;    /* reset log file info */    d->log_file_name = NULL;    d->log_file = NULL;    d->log_file_err = FALSE;    connect_to_host_pair(d);    return d;}struct connection *rw_instantiate(struct connection *c, const ip_address *him, const ip_subnet *his_net, const struct id *his_id){    struct connection *d = instantiate(c, him, his_id);#ifdef VIRTUAL_IP    if (d && his_net && is_virtual_connection(c)) {	d->spd.that.client = *his_net;	d->spd.that.virt = NULL;	if (subnetishost(his_net) && addrinsubnet(him, his_net))	    d->spd.that.has_client = FALSE;    }#endif    if (d->policy & POLICY_OPPO)    {	/* This must be before we know the client addresses.	 * Fill in one that is impossible.  This prevents anyone else from	 * trying to use this connection to get to a particular client	 */	d->spd.that.client = *aftoinfo(subnettypeof(&d->spd.that.client))->none;    }    DBG(DBG_CONTROL	, DBG_log("instantiated \"%s\" for %s" , d->name, ip_str(him)));    return d;}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 USED_BY_DEBUG		 , const ip_address *peer_client){    struct connection *d = instantiate(c, him, his_id);    DBG(DBG_CONTROL,	DBG_log("oppo instantiate d=%s from c=%s with c->routing %s, d->routing %s"		, d->name, c->name		, enum_name(&routing_story, c->spd.routing)		, enum_name(&routing_story, d->spd.routing)));    passert(d->spd.next == NULL);    /* fill in our client side */    if (d->spd.this.has_client)    {	/* there was a client in the abstract connection	 * so we demand that the required client is within that subnet.	 */	passert(addrinsubnet(our_client, &d->spd.this.client));	happy(addrtosubnet(our_client, &d->spd.this.client));	/* opportunistic connections do not use port selectors */	setportof(0, &d->spd.this.client.addr);    }    else    {	/* there was no client in the abstract connection	 * so we demand that the required client be the host	 */	passert(sameaddr(our_client, &d->spd.this.host_addr));    }    /*     * fill in peer's client side.     * If the client is the peer, excise the client from the connection.     */    passert((d->policy & POLICY_OPPO)	&& addrinsubnet(peer_client, &d->spd.that.client));    happy(addrtosubnet(peer_client, &d->spd.that.client));    /* opportunistic connections do not use port selectors */    setportof(0, &d->spd.that.client.addr);    if (sameaddr(peer_client, &d->spd.that.host_addr))	d->spd.that.has_client = FALSE;    passert(d->gw_info == NULL);    gw_addref(gw);    d->gw_info = gw;    /* Adjust routing if something is eclipsing c.     * It must be a %hold for us (hard to passert this).     * If there was another instance eclipsing, we'd be using it.     */    if (c->spd.routing == RT_ROUTED_ECLIPSED)	d->spd.routing = RT_ROUTED_PROSPECTIVE;    /* Remember if the template is routed:     * if so, this instance applies for initiation     * even if it is created for responding.     */    if (routed(c->spd.routing))	d->instance_initiation_ok = TRUE;    DBG(DBG_CONTROL,	char topo[CONNECTION_BUF];	(void) format_connection(topo, sizeof(topo), d, &d->spd);	DBG_log("instantiated \"%s\": %s", d->name, topo);    );    return d;}/* priority formatting */voidfmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]){    if (pp == BOTTOM_PRIO)	snprintf(buf, POLICY_PRIO_BUF, "0");    else	snprintf(buf, POLICY_PRIO_BUF, "%lu,%lu"	    , pp>>16, (pp & ~(~(policy_prio_t)0 << 16)) >> 8);}/* Format any information needed to identify an instance of a connection. * Fills any needed information into buf which MUST be big enough. * Road Warrior: peer's IP address * Opportunistic: [" " myclient "==="] " ..." peer ["===" hisclient] '\0' */static size_tfmt_client(const ip_subnet *client, const ip_address *gw, const char *prefix, char buf[ADDRTOT_BUF]){    if (subnetisaddr(client, gw))    {	buf[0] = '\0';	/* compact denotation for "self" */    }    else    {	char *ap;	strcpy(buf, prefix);	ap = buf + strlen(prefix);	if (subnetisnone(client))	    strcpy(ap, "?");	/* unknown */	else	    subnettot(client, 0, ap, SUBNETTOT_BUF);    }    return strlen(buf);}voidfmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF]){    char *p = buf;    *p = '\0';    if (c->kind == CK_INSTANCE)    {	if (c->instance_serial != 0)	{	    snprintf(p, CONN_INST_BUF, "[%lu]", c->instance_serial);	    p += strlen(p);	}	if (c->policy & POLICY_OPPO)	{	    size_t w = fmt_client(&c->spd.this.client, &c->spd.this.host_addr, " ", p);	    p += w;	    strcpy(p, w == 0? " ..." : "=== ...");	    p += strlen(p);	    addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);	    p += strlen(p);	    (void) fmt_client(&c->spd.that.client, &c->spd.that.host_addr, "===", p);	}	else	{	    *p++ = ' ';	    addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);	}    }}/* Find an existing connection for a trapped outbound packet. * This is attempted before we bother with gateway discovery. *   + this connection is routed or instance_of_routed_template *     (i.e. approved for on-demand) *   + this subnet contains our_client (or we are our_client) *   + that subnet contains peer_client (or peer is peer_client) *   + don't care about Phase 1 IDs (we don't know) * Note: result may still need to be instantiated. * The winner has the highest policy priority. * * If there are several with that priority, we give preference to * the first one that is an instance. * * See also build_outgoing_opportunistic_connection. */struct connection *find_connection_for_clients(struct spd_route **srp,			    const ip_address *our_client,			    const ip_address *peer_client,			    int transport_proto){    struct connection *c = connections, *best = NULL;    policy_prio_t best_prio = BOTTOM_PRIO;    struct spd_route *sr;    struct spd_route *best_sr;    int our_port  = ntohs(portof(our_client));    int peer_port = ntohs(portof(peer_client));    best_sr = NULL;    passert(!isanyaddr(our_client) && !isanyaddr(peer_client));#ifdef DEBUG    if (DBGP(DBG_CONTROL))    {	char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];	addrtot(our_client, 0, ocb, sizeof(ocb));	addrtot(peer_client, 0, pcb, sizeof(pcb));	DBG_log("find_connection: "		"looking for policy for connection: %s:%d/%d -> %s:%d/%d"		, ocb, transport_proto, our_port, pcb, transport_proto, peer_port);    }#endif /* DEBUG */    for (c = connections; c != NULL; c = c->ac_next)    {	if (c->kind == CK_GROUP)	    continue;	for (sr = &c->spd; best!=c && sr; sr = sr->next)	{	    if ((routed(sr->routing) || c->instance_initiation_ok)	    && addrinsubnet(our_client, &sr->this.client) 	    && addrinsubnet(peer_client, &sr->that.client) 	    && (!sr->this.protocol || transport_proto == sr->this.protocol) 	    && (!sr->this.port || our_port == sr->this.port) 	    && (!sr->that.port || peer_port == sr->that.port))	    {		char cib[CONN_INST_BUF];		char cib2[CONN_INST_BUF]; 		policy_prio_t prio = 8 * (c->prio + (c->kind == CK_INSTANCE)) 				   + 2 * (sr->this.port == our_port) 				   + 2 * (sr->that.port == peer_port) 				   +     (sr->this.protocol == transport_proto);#ifdef DEBUG		if (DBGP(DBG_CONTROL|DBG_CONTROLMORE))		{		    char c_ocb[SUBNETTOT_BUF], c_pcb[SUBNETTOT_BUF];		    subnettot(&c->spd.this.client, 0, c_ocb, sizeof(c_ocb));		    subnettot(&c->spd.that.client, 0, c_pcb, sizeof(c_pcb)); 		    DBG_log("find_connection: " 			    "conn \"%s\"%s has compatible peers: %s -> %s [pri: %ld]"			    , c->name			    , (fmt_conn_instance(c, cib), cib)			    , c_ocb, c_pcb, prio);		}#endif /* DEBUG */		if (best == NULL)		{		    best = c;		    best_sr = sr;		    best_prio = prio;		}		DBG(DBG_CONTROLMORE,		    DBG_log("find_connection: comparing best \"%s\"%s [pri:%ld]{%p} (child %s) to \"%s\"%s [pri:%ld]{%p} (child %s)"			    , best->name			    , (fmt_conn_instance(best, cib), cib)			    , best_prio			    , best			    , (best->policy_next ? best->policy_next->name : "none")			    , c->name			    , (fmt_conn_instance(c, cib2), cib2)			    , prio			    , c			    , (c->policy_next ? c->policy_next->name : "none")));		if (prio > best_prio)		{		    best = c;		    best_sr = sr;		    best_prio = prio;		}	    }	}    }    if (best!= NULL && NEVER_NEGOTIATE(best->policy))	best = NULL;    if (srp != NULL && best != NULL)	*srp = best_sr;#ifdef DEBUG    if (DBGP(DBG_CONTROL))    {	if (best)	{	    char cib[CONN_INST_BUF];	    DBG_log("find_connection: concluding with \"%s\"%s [pri:%ld]{%p} kind=%s"		    , best->name		    , (fmt_conn_instance(best, cib), cib)		    , best_prio		    , best		    , enum_name(&connection_kind_names, best->kind));	} else {	    DBG_log("find_connection: concluding with empty");	}    }#endif /* DEBUG */    return best;}/* Find and instantiate a connection for an outgoing Opportunistic connection. * We've already discovered its gateway. * We look for a the connection such that: *   + this is one of our interfaces *   + this subnet contains our_client (or we are our_client) *     (we will specialize the client).  We prefer the smallest such subnet. *   + that subnet contains peer_clent (we will specialize the client). *     We prefer the smallest such subnet. *   + is opportunistic *   + that peer is NO_IP *   + don't care about Phase 1 IDs (probably should be default) * We could look for a connection that already had the desired peer * (rather than NO_IP) specified, but it doesn't seem worth the * bother. * * We look for the routed policy applying to the narrowest subnets. * We only succeed if we find such a policy AND it is satisfactory. * * The body of the inner loop is a lot like that in * find_connection_for_clients.  In this case, we know the gateways * that we need to instantiate an opportunistic connection. */struct connection *build_outgoing_opportunistic_connection(struct gw_info *gw					,const ip_address *our_client					,const ip_address *peer_client){    struct iface_port *p;    struct connection *best = NULL;    struct spd_route *sr, *bestsr;    char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];    addrtot(our_client, 0, ocb, sizeof(ocb));    addrtot(peer_client, 0, pcb, sizeof(pcb));    passert(!isanyaddr(our_client) && !isanyaddr(peer_client));    /* We don't know his ID yet, so gw id must be an ipaddr */    passert(gw->key != NULL);    passert(id_is_ipaddr(&gw->gw_id));    /* for each of our addresses... */    for (p = interfaces; p != NULL; p = p->next)    {	/* go through those connections with our address and NO_IP as hosts	 * We cannot know what port the peer would use, so we assume	 * that it is pluto_port (makes debugging easier).	 */	struct connection *c = find_host_pair_connections(__FUNCTION__, &p->ip_addr							  , pluto_port							  , (ip_address *)NULL							  , pluto_port);	for (; c != NULL; c = c->hp_next)	{	    DBG(DBG_OPPO,		DBG_log("checking %s", c->name));	    if (c->kind == CK_GROUP)	    {		continue;	    }	    for (sr = &c->spd; best!=c && sr; sr = sr->next)	    {		if (routed(sr->routing)		&& addrinsubnet(our_client, &sr->this.client)		&& addrinsubnet(peer_client, &sr->that.client))		{		    if (best == NULL)		    {			best = c;			break;

⌨️ 快捷键说明

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