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

📄 nat_traversal.c

📁 ipsec vpn
💻 C
📖 第 1 页 / 共 2 页
字号:
			__FILE__, __LINE__);		return FALSE;	}	ip = &(st->st_localaddr);	nat_np = (st->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES		  ? ISAKMP_NEXT_NATOA_RFC : ISAKMP_NEXT_NATOA_DRAFTS);	if (!out_modify_previous_np(nat_np, outs)) {		return FALSE;	}	memset(&natoa, 0, sizeof(natoa));	natoa.isanoa_np = np;	switch (addrtypeof(ip)) {		case AF_INET:			ip_len = sizeof(ip->u.v4.sin_addr.s_addr);			memcpy(ip_val, &ip->u.v4.sin_addr.s_addr, ip_len);			natoa.isanoa_idtype = ID_IPV4_ADDR;			break;		case AF_INET6:			ip_len = sizeof(ip->u.v6.sin6_addr.s6_addr);			memcpy(ip_val, &ip->u.v6.sin6_addr.s6_addr, ip_len);			natoa.isanoa_idtype = ID_IPV6_ADDR;			break;		default:			loglog(RC_LOG_SERIOUS, "NAT-Traversal: "				"invalid addrtypeof()=%d", addrtypeof(ip));			return FALSE;	}	if (!out_struct(&natoa, &isakmp_nat_oa, outs, &pbs))		return FALSE;	if (!out_raw(ip_val, ip_len, &pbs, "NAT-OA"))		return FALSE;	DBG(DBG_NATT,		DBG_dump("NAT-OA (S):", ip_val, ip_len);	);	close_output_pbs(&pbs);	return TRUE;}void nat_traversal_show_result (u_int32_t nt, u_int16_t sport){	const char *mth = NULL, *rslt = NULL;	switch (nt & NAT_TRAVERSAL_METHOD) {	case LELEM(NAT_TRAVERSAL_IETF_00_01):	    mth = natt_type_bitnames[0];	    break;	case LELEM(NAT_TRAVERSAL_IETF_02_03):	    mth = natt_type_bitnames[1];	    break;	case LELEM(NAT_TRAVERSAL_OSX):	    mth = natt_type_bitnames[2];	    break;	case LELEM(NAT_TRAVERSAL_RFC):	    mth = natt_type_bitnames[3];	    break;	}	switch (nt & NAT_T_DETECTED) {		case 0:			rslt = "no NAT detected";			break;		case LELEM(NAT_TRAVERSAL_NAT_BHND_ME):			rslt = "i am NATed";			break;		case LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):			rslt = "peer is NATed";			break;		case LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):			rslt = "both are NATed";			break;	}	loglog(RC_LOG_SERIOUS,		"NAT-Traversal: Result using %s: %s",		mth ? mth : "unknown method",		rslt ? rslt : "unknown result"		);	if ((nt & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER)) &&		(sport == IKE_UDP_PORT) &&		((nt & NAT_T_WITH_PORT_FLOATING)==0)) {		loglog(RC_LOG_SERIOUS,			"Warning: peer is NATed but source port is still udp/%d. "			"IPsec-passthrough NAT device suspected -- NAT-T may not work.",			IKE_UDP_PORT		);	}}int nat_traversal_espinudp_socket (int sk, const char *fam, u_int32_t type){	int r;	r = setsockopt(sk, SOL_UDP, UDP_ESPINUDP, &type, sizeof(type));	if ((r<0) && (errno == ENOPROTOOPT)) {		loglog(RC_LOG_SERIOUS,		       "NAT-Traversal: ESPINUDP(%d) not supported by kernel for family %s"		       , type, fam);		disable_nat_traversal(type);	}	return r;}void nat_traversal_new_ka_event (void){	if (_ka_evt) return;  /* Event already schedule */	event_schedule(EVENT_NAT_T_KEEPALIVE, _kap, NULL);	_ka_evt = 1;}static void nat_traversal_send_ka (struct state *st){	static unsigned char ka_payload = 0xff;	chunk_t sav;	DBG(DBG_NATT|DBG_DPD,		DBG_log("ka_event: send NAT-KA to %s:%d (state=#%lu)"			, ip_str(&st->st_remoteaddr)			, st->st_remoteport			, st->st_serialno);	);	/** save state chunk */	setchunk(sav, st->st_tpacket.ptr, st->st_tpacket.len);	/** send keep alive */	setchunk(st->st_tpacket, &ka_payload, 1);	send_packet(st, "NAT-T Keep Alive", FALSE);	/** restore state chunk */	setchunk(st->st_tpacket, sav.ptr, sav.len);}/** * Find ISAKMP States with NAT-T and send keep-alive */static void nat_traversal_ka_event_state (struct state *st, void *data){	unsigned int *_kap_st = (unsigned int *)data;	const struct connection *c = st->st_connection;	if (!c) return;	if ( ((st->st_state == STATE_MAIN_R3)	      || (st->st_state == STATE_MAIN_I4)	      || (st->st_state == STATE_AGGR_R2)	      || (st->st_state == STATE_AGGR_I2))	     &&	(st->hidden_variables.st_nat_traversal & NAT_T_DETECTED)	     &&	((st->hidden_variables.st_nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME))		 || (_force_ka)))	{	    /**	     * - ISAKMP established	     * - NAT-Traversal detected	     * - NAT-KeepAlive needed (we are NATed)	     */	    if (c->newest_isakmp_sa != st->st_serialno) {		/** 		 * if newest is also valid, ignore this one, we will only use		 * newest. 		 */		struct state *st_newest;		st_newest = state_with_serialno(c->newest_isakmp_sa);		if ((st_newest)		    && ((st_newest->st_state==STATE_MAIN_R3)			|| (st_newest->st_state==STATE_MAIN_I4))		    && (st_newest->hidden_variables.st_nat_traversal & NAT_T_DETECTED)		    && ((st_newest->hidden_variables.st_nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME))			|| (_force_ka)))		{		    return;		}	    }	    set_cur_state(st);	    nat_traversal_send_ka(st);	    reset_cur_state();	    (*_kap_st)++;	}}void nat_traversal_ka_event (void){	unsigned int _kap_st = 0;	_ka_evt = 0;  /* ready to be reschedule */	for_each_state((void *)nat_traversal_ka_event_state, &_kap_st);	if (_kap_st) {	    /**	     * If there are still states who needs Keep-Alive, schedule new event	     */	    nat_traversal_new_ka_event();	}}struct _new_mapp_nfo {	ip_address addr;	u_int16_t sport, dport;};static void nat_traversal_find_new_mapp_state (struct state *st, void *data){	struct connection *c = st->st_connection;	struct _new_mapp_nfo *nfo = (struct _new_mapp_nfo *)data;	if ((c)	    && sameaddr(&st->st_remoteaddr, &(nfo->addr)) &&	    (st->st_remoteport == nfo->sport))	{	    /**	     * Change host port	     */	    st->st_remoteport = nfo->dport;	    if (IS_IPSEC_SA_ESTABLISHED(st->st_state) ||		IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state)) {		if (!update_ipsec_sa(st)) {		    /**		     * If ipsec update failed, restore old port or we'll		     * not be able to update anymore.		     */		    st->st_remoteport = nfo->sport;		}	    }	}}static int nat_traversal_new_mapping(const ip_address *src, u_int16_t sport,	const ip_address *dst, u_int16_t dport){	char srca[ADDRTOT_BUF], dsta[ADDRTOT_BUF];	struct _new_mapp_nfo nfo;	addrtot(src, 0, srca, ADDRTOT_BUF);	addrtot(dst, 0, dsta, ADDRTOT_BUF);	if (!sameaddr(src, dst)) {		loglog(RC_LOG_SERIOUS, "nat_traversal_new_mapping: "			"address change currently not supported [%s:%d,%s:%d]",			srca, sport, dsta, dport);		return -1;	}	if (sport == dport) {		/* no change */		return 0;	}	DBG_log("NAT-T: new mapping %s:%d/%d)", srca, sport, dport);	nfo.addr = *src;	nfo.sport = sport;	nfo.dport = dport;	for_each_state((void *)nat_traversal_find_new_mapp_state, &nfo);	return 0;}void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st){	struct iface_port *i = NULL;	if (st == NULL) {		return;	}	if (md) {		/**		 * If source port has changed, update (including other		 * states and established kernel SA)		 */		if (st->st_remoteport != md->sender_port) {		    nat_traversal_new_mapping(&st->st_remoteaddr					      , st->st_remoteport					      , &st->st_remoteaddr					      , md->sender_port);		}		/**		 * If interface type has changed, update local port (500/4500)		 */		if (md->iface->port != st->st_localport)		{		    st->st_localport = md->iface->port;		    DBG(DBG_NATT,			DBG_log("NAT-T: updating local port to %d"				, st->st_localport));		}	}	/**	 * If we're initiator and NAT-T (with port floating) is detected, we	 * need to change port (MAIN_I3 or QUICK_I1)	 */	if (((st->st_state == STATE_MAIN_I3)	     || (st->st_state == STATE_QUICK_I1))	    && (st->hidden_variables.st_nat_traversal & NAT_T_WITH_PORT_FLOATING)	    && (st->hidden_variables.st_nat_traversal & NAT_T_DETECTED)	    && (st->st_localport != NAT_T_IKE_FLOAT_PORT))	{	    DBG(DBG_NATT		, DBG_log("NAT-T: floating to port %d", NAT_T_IKE_FLOAT_PORT));	    	    st->st_localport  = NAT_T_IKE_FLOAT_PORT;	    st->st_remoteport = NAT_T_IKE_FLOAT_PORT;	    	    /*	     * Also update pending connections or they will be deleted if	     * uniqueids option is set.	     * THIS does NOTHING as, both arguments are "st"!	     */	    update_pending(st, st);	}	/**	 * Find valid interface according to local port (500/4500)	 */	if (!(sameaddr(&st->st_localaddr, &st->st_interface->ip_addr)	      && st->st_localport == st->st_interface->port))	    	{	    char b1[ADDRTOT_BUF], b2[ADDRTOT_BUF];	    DBG(DBG_NATT,		DBG_log("NAT-T connection has wrong interface definition %s:%u vs %s:%u"			, (addrtot(&st->st_localaddr, 0, b1, sizeof(b1)),b1)			, st->st_localport			, (addrtot(&st->st_interface->ip_addr, 0, b2, sizeof(b2)),b2)			, st->st_interface->port));	    for (i = interfaces; i !=  NULL; i = i->next) {		if ((sameaddr(&st->st_localaddr, &i->ip_addr))		    && (st->st_localport == i->port))		{		    DBG(DBG_NATT,			DBG_log("NAT-T: using interface %s:%d"				, i->ip_dev->id_rname				, i->port));		    st->st_interface = i;		    break;		}	    }	}}struct _new_klips_mapp_nfo {	struct sadb_sa *sa;	ip_address src, dst;	u_int16_t sport, dport;};static void nat_t_new_klips_mapp (struct state *st, void *data){	struct connection *c = st->st_connection;	struct _new_klips_mapp_nfo *nfo = (struct _new_klips_mapp_nfo *)data;	if ((c)	    && (st->st_esp.present)	    && sameaddr(&st->st_remoteaddr, &(nfo->src))	    && (st->st_esp.our_spi == nfo->sa->sadb_sa_spi))	{	    nat_traversal_new_mapping(&st->st_remoteaddr				      , st->st_remoteport				      , &(nfo->dst), nfo->dport);	}}void process_pfkey_nat_t_new_mapping(	struct sadb_msg *msg __attribute__ ((unused)),	struct sadb_ext *extensions[SADB_EXT_MAX + 1]){	struct _new_klips_mapp_nfo nfo;	struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC];	struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST];	struct sockaddr *srca, *dsta;	err_t ugh = NULL;	nfo.sa = (void *) extensions[SADB_EXT_SA];	if ((!nfo.sa) || (!srcx) || (!dstx)) {		openswan_log("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: "			"got NULL params");		return;	}	srca = ((struct sockaddr *)(void *)&srcx[1]);	dsta = ((struct sockaddr *)(void *)&dstx[1]);	if ((srca->sa_family != AF_INET) || (dsta->sa_family != AF_INET)) {		ugh = "only AF_INET supported";	}	else {		char text_said[SATOT_BUF];		char _srca[ADDRTOT_BUF], _dsta[ADDRTOT_BUF];		ip_said said;		initaddr((const void *) &((const struct sockaddr_in *)srca)->sin_addr,			sizeof(((const struct sockaddr_in *)srca)->sin_addr),			srca->sa_family, &(nfo.src));		nfo.sport = ntohs(((const struct sockaddr_in *)srca)->sin_port);		initaddr((const void *) &((const struct sockaddr_in *)dsta)->sin_addr,			sizeof(((const struct sockaddr_in *)dsta)->sin_addr),			dsta->sa_family, &(nfo.dst));		nfo.dport = ntohs(((const struct sockaddr_in *)dsta)->sin_port);		DBG(DBG_NATT,			initsaid(&nfo.src, nfo.sa->sadb_sa_spi, SA_ESP, &said);			satot(&said, 0, text_said, SATOT_BUF);			addrtot(&nfo.src, 0, _srca, ADDRTOT_BUF);			addrtot(&nfo.dst, 0, _dsta, ADDRTOT_BUF);			DBG_log("new klips mapping %s %s:%d %s:%d",				text_said, _srca, nfo.sport, _dsta, nfo.dport);		);		for_each_state((void *)nat_t_new_klips_mapp, &nfo);	}	if (ugh != NULL)		openswan_log("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: %s", ugh);}#endif/* * $Log: nat_traversal.c,v $ * Revision 1.26.2.6  2006/01/04 18:57:52  ken * Send 02_N too * * Revision 1.26.2.5  2005/11/24 05:30:37  ken * MCR's refactored natd_lookup function for multi-NAT-D Hash * * Revision 1.26.2.4  2005/09/27 04:30:20  paul * Backport of HEAD's patch, adopted from Peter Van der Beken's * (peterv@propagandism.org) MacOSX interop patch. * * Reported to Apple Developer Center (ADC) by Paul Wouters (paul@xelerance.com): * Problem ID: 4274347 * Title: IPsec NAT-T implementation is broken, breaking L2TP VPN's to non-apple servers * Created Date: 26-Sep-2005 06:36 PM * * Revision 1.26.2.3  2005/09/07 00:41:12  paul * Pull up mcr's nat-t detection for klips. * * Revision 1.26.2.2  2005/07/26 02:11:23  ken * Pullin from HEAD: * Split Aggressive mode into ikev1_aggr.c * Fix NAT-T that we broke in dr7 * Move dpd/pgp vendor id's to vendor.[ch] * * Revision 1.26.2.1  2005/07/26 01:20:14  ken * Pull in st -> c changes from HEAD * * Revision 1.27  2005/07/26 01:14:58  mcr * 	switch from i->interface to st->st_interface. * 	cleaned up some diagnostic, and canonicalized to "NAT-Traversal" * * Revision 1.26  2005/06/14 22:38:06  mcr * 	changed definition of interface such that we can now compare if * 	a NAT vs non-NAT interface are considered the "same" * * Revision 1.25  2005/05/08 13:25:48  paul * fixed typo * * Revision 1.24  2005/04/21 21:58:06  mcr * 	log correct address/port for NAT-KA. * * Revision 1.23  2005/04/20 15:30:28  mcr * 	additional debugging of NAT-KA and DPD messages. * * Revision 1.22  2005/04/08 18:29:52  mcr * 	use natt_defines.h to get definitions. * * Revision 1.21  2005/04/06 17:56:04  mcr * 	log where/who the DPD R_U_THERE sent to. * * Revision 1.20  2005/03/20 23:16:16  mcr * 	fixed typo in case. * * Revision 1.19  2005/02/14 18:27:27  mcr * 	additional debugging of when NAT-T is enabled, and when the * 	VID is actually being sent. * * Revision 1.18  2005/01/28 06:22:52  mcr * 	additional debugging of whether or not NAT-T vendor * 	IDs are inserted. * * Revision 1.17  2005/01/24 03:35:22  mcr * 	fixed selection of interface for various states * 	of NAT "floating" * * Revision 1.16  2005/01/23 19:16:15  mcr * 	moved nat varibales to "hidden_variables" * 	added for RFC3947 NAT code. * * Revision 1.15  2004/11/30 02:31:14  mcr * 	oops, function didn't match prototype. * * Revision 1.14  2004/11/30 02:26:59  mcr * 	additional debugging of port-floating enabling/disabling. * * Revision 1.13  2004/11/05 00:14:50  mcr * 	added log info. * * * $Id: nat_traversal.c,v 1.26.2.6 2006/01/04 18:57:52 ken Exp $ * */

⌨️ 快捷键说明

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