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

📄 connections.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
    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#ifdef NAT_TRAVERSAL, u_int16_t his_port#endif#ifdef VIRTUAL_IP, const ip_subnet *his_net#endif, const struct id *his_id){#ifdef NAT_TRAVERSAL    struct connection *d = instantiate(c, him, his_port, his_id);#else    struct connection *d = instantiate(c, him, his_id);#endif#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){#ifdef NAT_TRAVERSAL    struct connection *d = instantiate(c, him, 0, his_id);#else    struct connection *d = instantiate(c, him, his_id);#endif    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);#ifdef NAT_TRAVERSAL	    if (c->spd.that.host_port != pluto_port) {		p += strlen(p);		sprintf(p, ":%d", c->spd.that.host_port);	    }#endif	}    }}/* 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));    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 *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(&p->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;		    }		    DBG(DBG_OPPO,			DBG_log("comparing best %s to %s"				, best->name, c->name));		    for (bestsr = &best->spd; best!=c && bestsr; bestsr=bestsr->next)		    {			if (!subnetinsubnet(&bestsr->this.client, &sr->this.client)			|| (samesubnet(&bestsr->this.client, &sr->this.client)			     && !subnetinsubnet(&bestsr->that.client						, &sr->that.client)))			{			    best = c;			}		    }		}	    }	}    }    if (best == NULL    || NEVER_NEGOTIATE(best->policy)    || (best->policy & POLICY_OPPO) == LEMPTY    || best->kind != CK_TEMPLATE)	return NULL;    else	return oppo_instantiate(best, &gw->gw_id.ip_addr, NULL, gw			      , our_client, peer_client);}boolorient(struct connection *c){    struct spd_route *sr;    if (!oriented(*c))    {	struct iface *p;	for (sr = &c->spd; sr; sr = sr->next)	{	    /* Note: this loop does not stop when it finds a match:	     * it continues checking to catch any ambiguity.	     */	    for (p = interfaces; p != NULL; p = p->next)	    {#ifdef NAT_TRAVERSAL		if (p->ike_float) continue;#endif		for (;;)		{		    /* check if this interface matches this end */		    if (sameaddr(&sr->this.host_addr, &p->addr)		    && (!no_klips || sr->this.host_port == pluto_port))		    {			if (oriented(*c))			{			    if (c->interface == p)				loglog(RC_LOG_SERIOUS				       , "both sides of \"%s\" are our interface %s!"				       , c->name, p->rname);			    else				loglog(RC_LOG_SERIOUS, "two interfaces match \"%s\" (%s, %s)"				       , c->name, c->interface->rname, p->rname);			    c->interface = NULL;	/* withdraw orientation */			    return FALSE;			}			c->interface = p;		    }		    /* done with this interface if it doesn't match that end */		    if (!(sameaddr(&sr->that.host_addr, &p->addr)		    && (!no_klips || sr->that.host_port == pluto_port)))			break;		    /* swap ends and try again.		     * It is a little tricky to see that this loop will stop.		     * Only continue if the far side matches.		     * If both sides match, there is an error-out.		     */		    {			struct end t = sr->this;

⌨️ 快捷键说明

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