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

📄 ipsec_xmit.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef NET_21		ixs->iph = ixs->skb->nh.iph;#else /* NET_21 */		ixs->iph = ixs->skb->ip_hdr;#endif /* NET_21 */		ixs->ipsp->ips_comp_ratio_cbytes += ntohs(ixs->iph->tot_len);#ifdef CONFIG_KLIPS_DEBUG		if (debug_tunnel & DB_TN_CROUT)		{			if (old_tot_len > ntohs(ixs->iph->tot_len))				KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,					    "klips_debug:ipsec_xmit_encap_once: "					    "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n",					    old_tot_len, ntohs(ixs->iph->tot_len),					    ntohs(((struct ipcomphdr*)(((char*)ixs->iph) + ((ixs->iph->ihl) << 2)))->ipcomp_cpi),					    ntohl(ixs->ipsp->ips_said.spi),					    (__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff));			else				KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,					    "klips_debug:ipsec_xmit_encap_once: "					    "packet did not compress (flags = %d).\n",					    flags);		}#endif /* CONFIG_KLIPS_DEBUG */	}	break;#endif /* CONFIG_KLIPS_IPCOMP */	default:		ixs->stats->tx_errors++;		return IPSEC_XMIT_BADPROTO;	}			#ifdef NET_21	ixs->skb->nh.raw = ixs->skb->data;#else /* NET_21 */	ixs->skb->ip_hdr = ixs->skb->h.iph = (struct iphdr *) ixs->skb->data;#endif /* NET_21 */	ixs->iph->check = 0;	ixs->iph->check = ip_fast_csum((unsigned char *)ixs->iph, ixs->iph->ihl);				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,		    "klips_debug:ipsec_xmit_encap_once: "		    "after <%s%s%s>, SA:%s:\n",		    IPS_XFORM_NAME(ixs->ipsp),		    ixs->sa_len ? ixs->sa_txt : " (error)");	KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); 				ixs->ipsp->ips_life.ipl_bytes.ipl_count += len;	ixs->ipsp->ips_life.ipl_bytes.ipl_last = len;	if(!ixs->ipsp->ips_life.ipl_usetime.ipl_count) {		ixs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ;	}	ixs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ;	ixs->ipsp->ips_life.ipl_packets.ipl_count++; 	ixs->ipsp = ixs->ipsp->ips_onext;				return IPSEC_XMIT_OK;}/* * If the IP packet (iph) is a carrying TCP/UDP, then set the encaps * source and destination ports to those from the TCP/UDP header. */void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er){	struct udphdr *udp;	switch (iph->protocol) {	case IPPROTO_UDP:	case IPPROTO_TCP:		/*		 * The ports are at the same offsets in a TCP and UDP		 * header so hack it ...		 */		udp = (struct udphdr*)(((char*)iph)+(iph->ihl<<2));		er->sen_sport = udp->source;		er->sen_dport = udp->dest;		break;	default:		er->sen_sport = 0;		er->sen_dport = 0;		break;	}}/* * A TRAP eroute is installed and we want to replace it with a HOLD * eroute. */static int create_hold_eroute(struct eroute *origtrap,			      struct sk_buff * skb, struct iphdr * iph,			      uint32_t eroute_pid){	struct eroute hold_eroute;	ip_said hold_said;	struct sk_buff *first, *last;	int error;	first = last = NULL;	memset((caddr_t)&hold_eroute, 0, sizeof(hold_eroute));	memset((caddr_t)&hold_said, 0, sizeof(hold_said));		hold_said.proto = IPPROTO_INT;	hold_said.spi = htonl(SPI_HOLD);	hold_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY;		hold_eroute.er_eaddr.sen_len = sizeof(struct sockaddr_encap);	hold_eroute.er_emask.sen_len = sizeof(struct sockaddr_encap);	hold_eroute.er_eaddr.sen_family = AF_ENCAP;	hold_eroute.er_emask.sen_family = AF_ENCAP;	hold_eroute.er_eaddr.sen_type = SENT_IP4;	hold_eroute.er_emask.sen_type = 255;		hold_eroute.er_eaddr.sen_ip_src.s_addr = iph->saddr;	hold_eroute.er_eaddr.sen_ip_dst.s_addr = iph->daddr;	hold_eroute.er_emask.sen_ip_src.s_addr = INADDR_BROADCAST;	hold_eroute.er_emask.sen_ip_dst.s_addr = INADDR_BROADCAST;	hold_eroute.er_emask.sen_sport = 0;	hold_eroute.er_emask.sen_dport = 0;	hold_eroute.er_pid = eroute_pid;	hold_eroute.er_count = 0;	hold_eroute.er_lasttime = jiffies/HZ;	/*	 * if it wasn't captured by a wildcard, then don't record it as	 * a wildcard.	 */	if(origtrap->er_eaddr.sen_proto != 0) {	  hold_eroute.er_eaddr.sen_proto = iph->protocol;	  if((iph->protocol == IPPROTO_TCP ||	      iph->protocol == IPPROTO_UDP) &&	     (origtrap->er_eaddr.sen_sport != 0 ||	      origtrap->er_eaddr.sen_dport != 0)) {	    if(origtrap->er_eaddr.sen_sport != 0)	      hold_eroute.er_emask.sen_sport = ~0;	    if(origtrap->er_eaddr.sen_dport != 0) 	      hold_eroute.er_emask.sen_dport = ~0;	    ipsec_extract_ports(iph, &hold_eroute.er_eaddr);	  }	}#ifdef CONFIG_KLIPS_DEBUG	if (debug_pfkey) {		char buf1[64], buf2[64];		subnettoa(hold_eroute.er_eaddr.sen_ip_src,			  hold_eroute.er_emask.sen_ip_src, 0, buf1, sizeof(buf1));		subnettoa(hold_eroute.er_eaddr.sen_ip_dst,			  hold_eroute.er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));		KLIPS_PRINT(debug_pfkey,			    "klips_debug:ipsec_tunnel_start_xmit: "			    "calling breakeroute and makeroute for %s:%d->%s:%d %d HOLD eroute.\n",			    buf1, ntohs(hold_eroute.er_eaddr.sen_sport),			    buf2, ntohs(hold_eroute.er_eaddr.sen_dport),			    hold_eroute.er_eaddr.sen_proto);	}#endif /* CONFIG_KLIPS_DEBUG */	if (ipsec_breakroute(&(hold_eroute.er_eaddr), &(hold_eroute.er_emask),			     &first, &last)) {		KLIPS_PRINT(debug_pfkey,			    "klips_debug:ipsec_tunnel_start_xmit: "			    "HOLD breakeroute found nothing.\n");	} else {		KLIPS_PRINT(debug_pfkey,			    "klips_debug:ipsec_tunnel_start_xmit: "			    "HOLD breakroute deleted %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u %u\n",			    NIPQUAD(hold_eroute.er_eaddr.sen_ip_src),			    ntohs(hold_eroute.er_eaddr.sen_sport),			    NIPQUAD(hold_eroute.er_eaddr.sen_ip_dst),			    ntohs(hold_eroute.er_eaddr.sen_dport),			    hold_eroute.er_eaddr.sen_proto);	}	if (first != NULL)		kfree_skb(first);	if (last != NULL)		kfree_skb(last);	error = ipsec_makeroute(&(hold_eroute.er_eaddr),				&(hold_eroute.er_emask),				hold_said, eroute_pid, skb, NULL, NULL);	if (error) {		KLIPS_PRINT(debug_pfkey,			    "klips_debug:ipsec_tunnel_start_xmit: "			    "HOLD makeroute returned %d, failed.\n", error);	} else {		KLIPS_PRINT(debug_pfkey,			    "klips_debug:ipsec_tunnel_start_xmit: "			    "HOLD makeroute call successful.\n");	}	return (error == 0);}enum ipsec_xmit_valueipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs){#ifdef CONFIG_KLIPS_ALG	struct ipsec_alg_enc *ixt_e = NULL;	struct ipsec_alg_auth *ixt_a = NULL;	int blocksize = 8;#endif /* CONFIG_KLIPS_ALG */	enum ipsec_xmit_value bundle_stat = IPSEC_XMIT_OK; 	ixs->newdst = ixs->orgdst = ixs->iph->daddr;	ixs->newsrc = ixs->orgsrc = ixs->iph->saddr;	ixs->orgedst = ixs->outgoing_said.dst.u.v4.sin_addr.s_addr;	ixs->iphlen = ixs->iph->ihl << 2;	ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen;	ixs->max_headroom = ixs->max_tailroom = 0;			if (ixs->outgoing_said.proto == IPPROTO_INT) {		switch (ntohl(ixs->outgoing_said.spi)) {		case SPI_DROP:			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_encap_bundle: "				    "shunt SA of DROP or no eroute: dropping.\n");			ixs->stats->tx_dropped++;			break;						case SPI_REJECT:			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_encap_bundle: "				    "shunt SA of REJECT: notifying and dropping.\n");			ICMP_SEND(ixs->skb,				  ICMP_DEST_UNREACH,				  ICMP_PKT_FILTERED,				  0,				  ixs->physdev);			ixs->stats->tx_dropped++;			break;						case SPI_PASS:#ifdef NET_21			ixs->pass = 1;#endif /* NET_21 */			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_encap_bundle: "				    "PASS: calling dev_queue_xmit\n");			return IPSEC_XMIT_PASS;			goto cleanup;						case SPI_HOLD:			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_encap_bundle: "				    "shunt SA of HOLD: this does not make sense here, dropping.\n");			ixs->stats->tx_dropped++;			break;		case SPI_TRAP:		case SPI_TRAPSUBNET:		{			struct sockaddr_in src, dst;#ifdef CONFIG_KLIPS_DEBUG			char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF];#endif /* CONFIG_KLIPS_DEBUG */			/* Signal all listening KMds with a PF_KEY ACQUIRE */			src.sin_family = AF_INET;			dst.sin_family = AF_INET;			src.sin_addr.s_addr = ixs->iph->saddr;			dst.sin_addr.s_addr = ixs->iph->daddr;			ixs->ips.ips_transport_protocol = 0;			src.sin_port = 0;			dst.sin_port = 0;			{			  int i;			  for(i = 0;			      i < sizeof(struct sockaddr_in)				- offsetof(struct sockaddr_in, sin_zero);			      i++) {			    src.sin_zero[i] = 0;			    dst.sin_zero[i] = 0;			  }			}						if(ixs->eroute->er_eaddr.sen_proto != 0) {			  ixs->ips.ips_transport_protocol = ixs->iph->protocol;			  			  if(ixs->eroute->er_eaddr.sen_sport != 0) {			    src.sin_port = 			      (ixs->iph->protocol == IPPROTO_UDP			       ? ((struct udphdr*) (((caddr_t)ixs->iph) + (ixs->iph->ihl << 2)))->source			       : (ixs->iph->protocol == IPPROTO_TCP				  ? ((struct tcphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl << 2)))->source				  : 0));			  }			  if(ixs->eroute->er_eaddr.sen_dport != 0) {			    dst.sin_port = 			      (ixs->iph->protocol == IPPROTO_UDP			       ? ((struct udphdr*) (((caddr_t)ixs->iph) + (ixs->iph->ihl << 2)))->dest			       : (ixs->iph->protocol == IPPROTO_TCP				  ? ((struct tcphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl << 2)))->dest				  : 0));			  }			}							ixs->ips.ips_addr_s = (struct sockaddr*)(&src);			ixs->ips.ips_addr_d = (struct sockaddr*)(&dst);			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_encap_bundle: "				    "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n",				    addrtoa(((struct sockaddr_in*)(ixs->ips.ips_addr_s))->sin_addr, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR",				    ntohs(((struct sockaddr_in*)(ixs->ips.ips_addr_s))->sin_port),				    addrtoa(((struct sockaddr_in*)(ixs->ips.ips_addr_d))->sin_addr, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR",				    ntohs(((struct sockaddr_in*)(ixs->ips.ips_addr_d))->sin_port),				    ixs->ips.ips_said.proto);							/* increment count of total traps needed */			ipsec_xmit_trap_count++;			if (pfkey_acquire(&ixs->ips) == 0) {				/* note that we succeeded */			        ipsec_xmit_trap_sendcount++;									if (ixs->outgoing_said.spi==htonl(SPI_TRAPSUBNET)) {					/*					 * The spinlock is to prevent any other					 * process from accessing or deleting					 * the eroute while we are using and					 * updating it.					 */					spin_lock(&eroute_lock);					ixs->eroute = ipsec_findroute(&ixs->matcher);					if(ixs->eroute) {						ixs->eroute->er_said.spi = htonl(SPI_HOLD);						ixs->eroute->er_first = ixs->skb;						ixs->skb = NULL;					}					spin_unlock(&eroute_lock);				} else if (create_hold_eroute(ixs->eroute,							      ixs->skb,							      ixs->iph,							      ixs->eroute_pid)) {					ixs->skb = NULL;				} 				/* whether or not the above succeeded, we continue */							}			ixs->stats->tx_dropped++;		}		default:			/* XXX what do we do with an unknown shunt spi? */			break;		} /* switch (ntohl(ixs->outgoing_said.spi)) */		return IPSEC_XMIT_STOLEN;	} /* if (ixs->outgoing_said.proto == IPPROTO_INT) */		/*	  The spinlock is to prevent any other process from	  accessing or deleting the ipsec_sa hash table or any of the	  ipsec_sa s while we are using and updating them.		  	  This is not optimal, but was relatively straightforward	  at the time.  A better way to do it has been planned for	  more than a year, to lock the hash table and put reference	  counts on each ipsec_sa instead.  This is not likely to happen	  in KLIPS1 unless a volunteer contributes it, but will be	  designed into KLIPS2.	*/	spin_lock(&tdb_lock);	ixs->ipsp = ipsec_sa_getbyid(&ixs->outgoing_said);	ixs->sa_len = satot(&ixs->outgoing_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt));	if (ixs->ipsp == NULL) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_debug:ipsec_xmit_encap_bundle: "			    "no ipsec_sa for SA%s: outgoing packet with no SA, dropped.\n",			    ixs->sa_len ? ixs->sa_txt : " (error)");		ixs->stats->tx_dropped++;		bundle_stat = IPSEC_XMIT_SAIDNOTFOUND;		goto cleanup;	}			ipsec_sa_put(ixs->ipsp); /* incomplete */	KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,		    "klips_debug:ipsec_xmit_encap_bundle: "		    "found ipsec_sa -- SA:<%s%s%s> %s\n",		    IPS_XFORM_NAME(ixs->ipsp),		    ixs->sa_len ? ixs->sa_txt : " (error)");			/*	 * How much headroom do we need to be able to apply	 * all the grouped transforms?	 */	ixs->ipsq = ixs->ipsp;	/* save the head of the ipsec_sa chain */	while (ixs->ipsp) {		ixs->sa_len = satot(&ixs->ipsp->ips_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt));		if(ixs->sa_len == 0) {			strcpy(ixs->sa_txt, "(error)");		}		/* If it is in larval state, drop the packet, we cannot process yet. */		if(ixs->ipsp->ips_state == SADB_SASTATE_LARVAL) {			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_encap_bundle: "				    "ipsec_sa in larval state for SA:<%s%s%s> %s, cannot be used yet, dropping packet.\n",				    IPS_XFORM_NAME(ixs->ipsp),				    ixs->sa_len ? ixs->sa_txt : " (error)");			ixs->stats->tx_errors++;			bundle_stat = IPSEC_XMIT_SAIDNOTLIVE;			goto cleanup;		}		if(ixs->ipsp->ips_state == SADB_SASTATE_DEAD) {			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_encap_bundle: "				    "ipsec_sa in dead state for SA:<%s%s%s> %s, can no longer be used, dropping packet.\n",				    IPS_XFORM_NAME(ixs->ipsp),				    ixs->sa_len ? ixs->sa_txt : " (error)");			ixs->stats->tx_errors++;			bundle_stat = IPSEC_XMIT_SAIDNOTLIVE;			goto cleanup;		}		/* If the replay window counter == -1, expire SA, it will roll */		if(ixs->ipsp->ips_replaywin && ixs->ipsp->ips_replaywin_lastseq == -1) {			pfkey_expire(ixs->ipsp, 1);			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_encap_bundle: "				    "replay window counter rolled for SA:<%s%s%s> %s, packet dropped, expiring SA.\n",				    IPS_XFORM_NAME(ixs->ipsp),				    ixs->sa_len ? ixs->sa_txt : " (error)");			ipsec_sa_delchain(ixs->ipsp);			ixs->stats->tx_errors++;			bundle_stat = IPSEC_XMIT_REPLAYROLLED;			goto cleanup;		}		/*		 * if this is the first time we are using this SA, mark start time,		 * and offset hard/soft counters by "now" for later checking.		 */#if 0		if(ixs->ipsp->ips_life.ipl_usetime.count == 0) {			ixs->ipsp->ips_life.ipl_usetime.count = jiffies;			ixs->ipsp->ips_life.ipl_usetime.hard += jiffies;			ixs->ipsp->ips_life.ipl_usetime.soft += jiffies;		}#endif			  		if(ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_bytes, "bytes", ixs->sa_txt, 					ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied ||		   ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_addtime, "addtime",ixs->sa_txt,					ipsec_life_timebased,  ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied ||		   ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_usetime, "usetime",ixs->sa_txt,					ipsec_life_timebased,  ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied ||		   ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_packets, "packets",ixs->sa_txt,					ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied) {							ipsec_sa_delchain(ixs->ipsp);			ixs->stats->tx_errors++;			bundle_stat = IPSEC_XMIT_LIFETIMEFAILED;			goto cleanup;		}			

⌨️ 快捷键说明

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