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

📄 ipsec_xmit.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (ixs->iph->version != 4) {		KLIPS_PRINT(debug_tunnel,			    "klips_debug:ipsec_xmit_sanity_check_skb: "			    "found IP Version %d but cannot process other IP versions than v4.\n",			    ixs->iph->version); /* XXX */		ixs->stats->tx_dropped++;		return IPSEC_XMIT_NOIPV6;	}	#if IPSEC_DISALLOW_IPOPTIONS	if ((ixs->iph->ihl << 2) != sizeof (struct iphdr)) {		KLIPS_PRINT(debug_tunnel,			    "klips_debug:ipsec_xmit_sanity_check_skb: "			    "cannot process IP header options yet.  May be mal-formed packet.\n"); /* XXX */		ixs->stats->tx_dropped++;		return IPSEC_XMIT_NOIPOPTIONS;	}#endif /* IPSEC_DISALLOW_IPOPTIONS */	#ifndef NET_21	if (ixs->iph->ttl <= 0) {		/* Tell the sender its packet died... */		ICMP_SEND(ixs->skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, ixs->physdev);		KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_xmit_sanity_check_skb: "			    "TTL=0, too many hops!\n");		ixs->stats->tx_dropped++;		return IPSEC_XMIT_TTLEXPIRED;	}#endif /* !NET_21 */		return IPSEC_XMIT_OK;}enum ipsec_xmit_valueipsec_xmit_encap_once(struct ipsec_xmit_state *ixs){#ifdef CONFIG_KLIPS_ESP	struct esphdr *espp;#ifdef CONFIG_KLIPS_ENC_3DES	__u32 iv[ESP_IV_MAXSZ_INT];#endif /* !CONFIG_KLIPS_ENC_3DES */	unsigned char *idat, *pad;	int authlen = 0, padlen = 0, i;#endif /* !CONFIG_KLIPS_ESP */#ifdef CONFIG_KLIPS_AH	struct iphdr ipo;	struct ahhdr *ahp;#endif /* CONFIG_KLIPS_AH */#if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1)	union {#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5		MD5_CTX md5;#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1		SHA1_CTX sha1;#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */	} tctx;	__u8 hash[AH_AMAX];#endif /* defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) */	int headroom = 0, tailroom = 0, ilen = 0, len = 0;	unsigned char *dat;	int blocksize = 8; /* XXX: should be inside ixs --jjo */#ifdef CONFIG_KLIPS_ALG	struct ipsec_alg_enc *ixt_e = NULL;	struct ipsec_alg_auth *ixt_a = NULL;#endif /* CONFIG_KLIPS_ALG */		ixs->iphlen = ixs->iph->ihl << 2;	ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen;	ixs->sa_len = satot(&ixs->ipsp->ips_said, 0, ixs->sa_txt, SATOT_BUF);	KLIPS_PRINT(debug_tunnel & DB_TN_OXFS,		    "klips_debug:ipsec_xmit_encap_once: "		    "calling output for <%s%s%s>, SA:%s\n", 		    IPS_XFORM_NAME(ixs->ipsp),		    ixs->sa_len ? ixs->sa_txt : " (error)");		switch(ixs->ipsp->ips_said.proto) {#ifdef CONFIG_KLIPS_AH	case IPPROTO_AH:		headroom += sizeof(struct ahhdr);		break;#endif /* CONFIG_KLIPS_AH */#ifdef CONFIG_KLIPS_ESP	case IPPROTO_ESP:#ifdef CONFIG_KLIPS_ALG		if ((ixt_e=ixs->ipsp->ips_alg_enc)) {			blocksize = ixt_e->ixt_blocksize;			headroom += ESP_HEADER_LEN + ixt_e->ixt_ivlen/8;		} else#endif /* CONFIG_KLIPS_ALG */		switch(ixs->ipsp->ips_encalg) {#ifdef CONFIG_KLIPS_ENC_3DES		case ESP_3DES:			headroom += sizeof(struct esphdr);			break;#endif /* CONFIG_KLIPS_ENC_3DES */		default:			ixs->stats->tx_errors++;			return IPSEC_XMIT_ESP_BADALG;		}#ifdef CONFIG_KLIPS_ALG		if ((ixt_a=ixs->ipsp->ips_alg_auth)) {			tailroom += AHHMAC_HASHLEN;		} else#endif /* CONFIG_KLIPS_ALG */		switch(ixs->ipsp->ips_authalg) {#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5		case AH_MD5:			authlen = AHHMAC_HASHLEN;			break;#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1		case AH_SHA:			authlen = AHHMAC_HASHLEN;			break;#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */		case AH_NONE:			break;		default:			ixs->stats->tx_errors++;			return IPSEC_XMIT_ESP_BADALG;		}		#ifdef CONFIG_KLIPS_ALG		tailroom += blocksize != 1 ?			((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 :			((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2;#else		tailroom += ((8 - ((ixs->pyldsz + 2 * sizeof(unsigned char)) % 8)) % 8) + 2;#endif /* CONFIG_KLIPS_ALG */		tailroom += authlen;		break;#endif /* !CONFIG_KLIPS_ESP */#ifdef CONFIG_KLIPS_IPIP	case IPPROTO_IPIP:		headroom += sizeof(struct iphdr);		ixs->iphlen = sizeof(struct iphdr);		break;#endif /* !CONFIG_KLIPS_IPIP */#ifdef CONFIG_KLIPS_IPCOMP	case IPPROTO_COMP:		break;#endif /* CONFIG_KLIPS_IPCOMP */	default:		ixs->stats->tx_errors++;		return IPSEC_XMIT_BADPROTO;	}		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,		    "klips_debug:ipsec_xmit_encap_once: "		    "pushing %d bytes, putting %d, proto %d.\n", 		    headroom, tailroom, ixs->ipsp->ips_said.proto);	if(skb_headroom(ixs->skb) < headroom) {		printk(KERN_WARNING		       "klips_error:ipsec_xmit_encap_once: "		       "tried to skb_push headroom=%d, %d available.  This should never happen, please report.\n",		       headroom, skb_headroom(ixs->skb));		ixs->stats->tx_errors++;		return IPSEC_XMIT_ESP_PUSHPULLERR;	}	dat = skb_push(ixs->skb, headroom);	ilen = ixs->skb->len - tailroom;	if(skb_tailroom(ixs->skb) < tailroom) {		printk(KERN_WARNING		       "klips_error:ipsec_xmit_encap_once: "		       "tried to skb_put %d, %d available.  This should never happen, please report.\n",		       tailroom, skb_tailroom(ixs->skb));		ixs->stats->tx_errors++;		return IPSEC_XMIT_ESP_PUSHPULLERR;	}	skb_put(ixs->skb, tailroom);	KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,		    "klips_debug:ipsec_xmit_encap_once: "		    "head,tailroom: %d,%d before xform.\n",		    skb_headroom(ixs->skb), skb_tailroom(ixs->skb));	len = ixs->skb->len;	if(len > 0xfff0) {		printk(KERN_WARNING "klips_error:ipsec_xmit_encap_once: "		       "tot_len (%d) > 65520.  This should never happen, please report.\n",		       len);		ixs->stats->tx_errors++;		return IPSEC_XMIT_BADLEN;	}	memmove((void *)dat, (void *)(dat + headroom), ixs->iphlen);	ixs->iph = (struct iphdr *)dat;	ixs->iph->tot_len = htons(ixs->skb->len);		switch(ixs->ipsp->ips_said.proto) {#ifdef CONFIG_KLIPS_ESP	case IPPROTO_ESP:		espp = (struct esphdr *)(dat + ixs->iphlen);		espp->esp_spi = ixs->ipsp->ips_said.spi;		espp->esp_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq));		#ifdef CONFIG_KLIPS_ALG		if (!ixt_e)#endif /* CONFIG_KLIPS_ALG */		switch(ixs->ipsp->ips_encalg) {#if defined(CONFIG_KLIPS_ENC_3DES)#ifdef CONFIG_KLIPS_ENC_3DES		case ESP_3DES:#endif /* CONFIG_KLIPS_ENC_3DES */			iv[0] = *((__u32*)&(espp->esp_iv)    ) =				((__u32*)(ixs->ipsp->ips_iv))[0];			iv[1] = *((__u32*)&(espp->esp_iv) + 1) =				((__u32*)(ixs->ipsp->ips_iv))[1];			break;#endif /* defined(CONFIG_KLIPS_ENC_3DES) */		default:			ixs->stats->tx_errors++;			return IPSEC_XMIT_ESP_BADALG;		}				idat = dat + ixs->iphlen + headroom;		ilen = len - (ixs->iphlen + headroom + authlen);				/* Self-describing padding */		pad = &dat[len - tailroom];		padlen = tailroom - 2 - authlen;		for (i = 0; i < padlen; i++) {			pad[i] = i + 1; 		}		dat[len - authlen - 2] = padlen;				dat[len - authlen - 1] = ixs->iph->protocol;		ixs->iph->protocol = IPPROTO_ESP;		#ifdef CONFIG_KLIPS_ALG		/* Do all operations here:		 * copy IV->ESP, encrypt, update ips IV		 */		if (ixt_e) {			int ret;			memcpy(espp->esp_iv, 					ixs->ipsp->ips_iv, 					ixt_e->ixt_ivlen/8);			ret=ipsec_alg_esp_encrypt(ixs->ipsp, 					idat, ilen, espp->esp_iv,					IPSEC_ALG_ENCRYPT);			memcpy(ixs->ipsp->ips_iv,					idat + ilen - ixt_e->ixt_ivlen/8,					ixt_e->ixt_ivlen/8);		} else#endif /* CONFIG_KLIPS_ALG */		switch(ixs->ipsp->ips_encalg) {#ifdef CONFIG_KLIPS_ENC_3DES		case ESP_3DES:			des_ede3_cbc_encrypt((des_cblock *)idat,					     (des_cblock *)idat,					     ilen,					     ((struct des_eks *)(ixs->ipsp->ips_key_e))[0].ks,					     ((struct des_eks *)(ixs->ipsp->ips_key_e))[1].ks,					     ((struct des_eks *)(ixs->ipsp->ips_key_e))[2].ks,					     (des_cblock *)iv, 1);			break;#endif /* CONFIG_KLIPS_ENC_3DES */		default:			ixs->stats->tx_errors++;			return IPSEC_XMIT_ESP_BADALG;		}		#ifdef CONFIG_KLIPS_ALG		if (!ixt_e)#endif /* CONFIG_KLIPS_ALG */		switch(ixs->ipsp->ips_encalg) {#if defined(CONFIG_KLIPS_ENC_3DES)#ifdef CONFIG_KLIPS_ENC_3DES		case ESP_3DES:#endif /* CONFIG_KLIPS_ENC_3DES */			/* XXX update IV with the last 8 octets of the encryption */#if KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK			((__u32*)(ixs->ipsp->ips_iv))[0] =				((__u32 *)(idat))[(ilen >> 2) - 2];			((__u32*)(ixs->ipsp->ips_iv))[1] =				((__u32 *)(idat))[(ilen >> 2) - 1];#else /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */			prng_bytes(&ipsec_prng, (char *)ixs->ipsp->ips_iv, EMT_ESPDES_IV_SZ); #endif /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */			break;#endif /* defined(CONFIG_KLIPS_ENC_3DES) */		default:			ixs->stats->tx_errors++;			return IPSEC_XMIT_ESP_BADALG;		}		#ifdef CONFIG_KLIPS_ALG		if (ixt_a) {			ipsec_alg_sa_esp_hash(ixs->ipsp,					(caddr_t)espp, len - ixs->iphlen - authlen,					&(dat[len - authlen]), authlen);		} else#endif /* CONFIG_KLIPS_ALG */		switch(ixs->ipsp->ips_authalg) {#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5		case AH_MD5:			dmp("espp", (char*)espp, len - ixs->iphlen - authlen);			tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx;			dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5));			osMD5Update(&tctx.md5, (caddr_t)espp, len - ixs->iphlen - authlen);			dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5));			osMD5Final(hash, &tctx.md5);			dmp("ictx hash", (char*)&hash, sizeof(hash));			tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx;			dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5));			osMD5Update(&tctx.md5, hash, AHMD596_ALEN);			dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5));			osMD5Final(hash, &tctx.md5);			dmp("octx hash", (char*)&hash, sizeof(hash));			memcpy(&(dat[len - authlen]), hash, authlen);						/* paranoid */			memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5));			memset((caddr_t)hash, 0, sizeof(*hash));			break;#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1		case AH_SHA:			tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx;			SHA1Update(&tctx.sha1, (caddr_t)espp, len - ixs->iphlen - authlen);			SHA1Final(hash, &tctx.sha1);			tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx;			SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN);			SHA1Final(hash, &tctx.sha1);			memcpy(&(dat[len - authlen]), hash, authlen);						/* paranoid */			memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1));			memset((caddr_t)hash, 0, sizeof(*hash));			break;#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */		case AH_NONE:			break;		default:			ixs->stats->tx_errors++;			return IPSEC_XMIT_AH_BADALG;		}#ifdef NET_21		ixs->skb->h.raw = (unsigned char*)espp;#endif /* NET_21 */		break;#endif /* !CONFIG_KLIPS_ESP */#ifdef CONFIG_KLIPS_AH	case IPPROTO_AH:		ahp = (struct ahhdr *)(dat + ixs->iphlen);		ahp->ah_spi = ixs->ipsp->ips_said.spi;		ahp->ah_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq));		ahp->ah_rv = 0;		ahp->ah_nh = ixs->iph->protocol;		ahp->ah_hl = (headroom >> 2) - sizeof(__u64)/sizeof(__u32);		ixs->iph->protocol = IPPROTO_AH;		dmp("ahp", (char*)ahp, sizeof(*ahp));				ipo = *ixs->iph;		ipo.tos = 0;		ipo.frag_off = 0;		ipo.ttl = 0;		ipo.check = 0;		dmp("ipo", (char*)&ipo, sizeof(ipo));				switch(ixs->ipsp->ips_authalg) {#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5		case AH_MD5:			tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx;			dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5));			osMD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr));			dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5));			osMD5Update(&tctx.md5, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data));			dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5));			osMD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN);			dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5));			osMD5Update(&tctx.md5,  dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom);			dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5));			osMD5Final(hash, &tctx.md5);			dmp("ictx hash", (char*)&hash, sizeof(hash));			tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx;			dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5));			osMD5Update(&tctx.md5, hash, AHMD596_ALEN);			dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5));			osMD5Final(hash, &tctx.md5);			dmp("octx hash", (char*)&hash, sizeof(hash));								memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN);								/* paranoid */			memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5));			memset((caddr_t)hash, 0, sizeof(*hash));			break;#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1		case AH_SHA:			tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx;			SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr));			SHA1Update(&tctx.sha1, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data));			SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN);			SHA1Update(&tctx.sha1,  dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom);			SHA1Final(hash, &tctx.sha1);			tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx;			SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN);			SHA1Final(hash, &tctx.sha1);								memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN);								/* paranoid */			memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1));			memset((caddr_t)hash, 0, sizeof(*hash));			break;#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */		default:			ixs->stats->tx_errors++;			return IPSEC_XMIT_AH_BADALG;		}#ifdef NET_21		ixs->skb->h.raw = (unsigned char*)ahp;#endif /* NET_21 */		break;#endif /* CONFIG_KLIPS_AH */#ifdef CONFIG_KLIPS_IPIP	case IPPROTO_IPIP:		ixs->iph->version  = 4;		switch(sysctl_ipsec_tos) {		case 0:#ifdef NET_21			ixs->iph->tos = ixs->skb->nh.iph->tos;#else /* NET_21 */			ixs->iph->tos = ixs->skb->ip_hdr->tos;#endif /* NET_21 */			break;		case 1:			ixs->iph->tos = 0;			break;		default:			break;		}#ifdef NET_21#ifdef NETDEV_23		ixs->iph->ttl      = sysctl_ip_default_ttl;#else /* NETDEV_23 */		ixs->iph->ttl      = ip_statistics.IpDefaultTTL;#endif /* NETDEV_23 */#else /* NET_21 */		ixs->iph->ttl      = 64; /* ip_statistics.IpDefaultTTL; */#endif /* NET_21 */		ixs->iph->frag_off = 0;		ixs->iph->saddr    = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_s))->sin_addr.s_addr;		ixs->iph->daddr    = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_d))->sin_addr.s_addr;		ixs->iph->protocol = IPPROTO_IPIP;		ixs->iph->ihl      = sizeof(struct iphdr) >> 2;		KLIPS_IP_SELECT_IDENT(ixs->iph, ixs->skb);		ixs->newdst = (__u32)ixs->iph->daddr;		ixs->newsrc = (__u32)ixs->iph->saddr;		#ifdef NET_21		ixs->skb->h.ipiph = ixs->skb->nh.iph;#endif /* NET_21 */		break;#endif /* !CONFIG_KLIPS_IPIP */#ifdef CONFIG_KLIPS_IPCOMP	case IPPROTO_COMP:	{		unsigned int flags = 0;#ifdef CONFIG_KLIPS_DEBUG		unsigned int old_tot_len = ntohs(ixs->iph->tot_len);#endif /* CONFIG_KLIPS_DEBUG */		ixs->ipsp->ips_comp_ratio_dbytes += ntohs(ixs->iph->tot_len);		ixs->skb = skb_compress(ixs->skb, ixs->ipsp, &flags);

⌨️ 快捷键说明

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