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

📄 nat_traversal.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 2 页
字号:
		{			char ip_t[ADDRTOT_BUF];			addrtot(&ip, 0, ip_t, sizeof(ip_t));			DBG_log("received NAT-OA: %s", ip_t);		}	);	if (isanyaddr(&ip)) {		loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %%any NAT-OA...");	}	else {		st->nat_oa = ip;	}}bool nat_traversal_add_natoa(u_int8_t np, pb_stream *outs,	struct state *st){	struct isakmp_nat_oa natoa;	pb_stream pbs;	unsigned char ip_val[sizeof(struct in6_addr)];	size_t ip_len = 0;	ip_address *ip;	if ((!st) || (!st->st_connection)) {		loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",			__FILE__, __LINE__);		return FALSE;	}	ip = &(st->st_connection->spd.this.host_addr);	if (!out_modify_previous_np((st->nat_traversal & NAT_T_WITH_RFC_VALUES		? ISAKMP_NEXT_NATOA_RFC : ISAKMP_NEXT_NATOA_DRAFTS), 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_RFC):	    mth = natt_type_bitnames[2];	    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_log("ka_event: send NAT-KA to %s:%d",			ip_str(&st->st_connection->spd.that.host_addr),			st->st_connection->spd.that.host_port);	);	/** 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->nat_traversal & NAT_T_DETECTED) &&		((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->nat_traversal & NAT_T_DETECTED) &&				((st_newest->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(&c->spd.that.host_addr, &(nfo->addr)) &&		(c->spd.that.host_port == nfo->sport)) {		/**		 * Change host port		 */		c->spd.that.host_port = 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.				 */				c->spd.that.host_port = 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 connection *c = st ? st->st_connection : NULL;	struct iface *i = NULL;	if ((st == NULL) || (c == NULL)) {		return;	}	if (md) {		/**		 * If source port has changed, update (including other states and		 * established kernel SA)		 */		if (c->spd.that.host_port != md->sender_port) {			nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port,				&c->spd.that.host_addr, md->sender_port);		}		/**		 * If interface type has changed, update local port (500/4500)		 */		if (((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT) &&			 (md->iface->ike_float == FALSE)) ||			((c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT) &&			 (md->iface->ike_float == TRUE))) {			c->spd.this.host_port = (md->iface->ike_float == TRUE)				? NAT_T_IKE_FLOAT_PORT : pluto_port;			DBG(DBG_NATT,				DBG_log("NAT-T: updating local port to %d", c->spd.this.host_port);			);		}	}	/**	 * 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->nat_traversal & NAT_T_WITH_PORT_FLOATING) &&		(st->nat_traversal & NAT_T_DETECTED) &&		(c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT)) {		DBG(DBG_NATT,			DBG_log("NAT-T: floating to port %d", NAT_T_IKE_FLOAT_PORT);		);		c->spd.this.host_port = NAT_T_IKE_FLOAT_PORT;		c->spd.that.host_port = NAT_T_IKE_FLOAT_PORT;		/*		 * Also update pending connections or they will be deleted if uniqueids		 * option is set.		 */		update_pending(st, st);	}	/**	 * Find valid interface according to local port (500/4500)	 */	if (((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT) &&		 (c->interface->ike_float == FALSE)) ||		((c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT) &&		 (c->interface->ike_float == TRUE))) {		for (i = interfaces; i !=  NULL; i = i->next) {			if ((sameaddr(&c->interface->addr, &i->addr)) &&				(i->ike_float != c->interface->ike_float)) {				DBG(DBG_NATT,					DBG_log("NAT-T: using interface %s:%d", i->rname,						i->ike_float ? NAT_T_IKE_FLOAT_PORT : pluto_port);				);				c->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(&c->spd.that.host_addr, &(nfo->src)) &&		(st->st_esp.our_spi == nfo->sa->sadb_sa_spi)) {		nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port,			&(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.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.15 2004/11/30 02:31:14 mcr Exp $ * */

⌨️ 快捷键说明

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