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

📄 ipsec_xmit.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 4 页
字号:
		ixs->headroom = ixs->tailroom = 0;		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,			    "klips_debug:ipsec_xmit_encap_bundle: "			    "calling room 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:			ixs->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;				ixs->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:				ixs->headroom += sizeof(struct esphdr);				break;#endif /* CONFIG_KLIPS_ENC_3DES */			default:				ixs->stats->tx_errors++;				bundle_stat = IPSEC_XMIT_ESP_BADALG;				goto cleanup;			}#ifdef CONFIG_KLIPS_ALG			if ((ixt_a=ixs->ipsp->ips_alg_auth)) {				ixs->tailroom += AHHMAC_HASHLEN;			} else#endif /* CONFIG_KLIPS_ALG */			switch(ixs->ipsp->ips_authalg) {#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5			case AH_MD5:				ixs->tailroom += AHHMAC_HASHLEN;				break;#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1			case AH_SHA:				ixs->tailroom += AHHMAC_HASHLEN;				break;#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */			case AH_NONE:				break;			default:				ixs->stats->tx_errors++;				bundle_stat = IPSEC_XMIT_AH_BADALG;				goto cleanup;			}			#ifdef CONFIG_KLIPS_ALG			ixs->tailroom += blocksize != 1 ?				((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 :				((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2;#else			ixs->tailroom += ((8 - ((ixs->pyldsz + 2 * sizeof(unsigned char)) % 8)) % 8) + 2;#endif /* CONFIG_KLIPS_ALG */#ifdef CONFIG_KLIPS_NAT_TRAVERSAL		if ((ixs->ipsp->ips_natt_type) && (!ixs->natt_type)) {			ixs->natt_type = ixs->ipsp->ips_natt_type;			ixs->natt_sport = ixs->ipsp->ips_natt_sport;			ixs->natt_dport = ixs->ipsp->ips_natt_dport;			switch (ixs->natt_type) {				case ESPINUDP_WITH_NON_IKE:					ixs->natt_head = sizeof(struct udphdr)+(2*sizeof(__u32));					break;									case ESPINUDP_WITH_NON_ESP:					ixs->natt_head = sizeof(struct udphdr);					break;									default:				  KLIPS_PRINT(debug_tunnel & DB_TN_CROUT					      , "klips_xmit: invalid nat-t type %d"					      , ixs->natt_type);				  bundle_stat = IPSEC_XMIT_ESPUDP_BADTYPE;				  goto cleanup;					      					break;			}			ixs->tailroom += ixs->natt_head;		}#endif			break;#endif /* !CONFIG_KLIPS_ESP */#ifdef CONFIG_KLIPS_IPIP		case IPPROTO_IPIP:			ixs->headroom += sizeof(struct iphdr);			break;#endif /* !CONFIG_KLIPS_IPIP */		case IPPROTO_COMP:#ifdef CONFIG_KLIPS_IPCOMP			/*			  We can't predict how much the packet will			  shrink without doing the actual compression.			  We could do it here, if we were the first			  encapsulation in the chain.  That might save			  us a skb_copy_expand, since we might fit			  into the existing skb then.  However, this			  would be a bit unclean (and this hack has			  bit us once), so we better not do it. After			  all, the skb_copy_expand is cheap in			  comparison to the actual compression.			  At least we know the packet will not grow.			*/			break;#endif /* CONFIG_KLIPS_IPCOMP */		default:			ixs->stats->tx_errors++;			bundle_stat = IPSEC_XMIT_BADPROTO;			goto cleanup;		}		ixs->ipsp = ixs->ipsp->ips_onext;		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,			    "klips_debug:ipsec_xmit_encap_bundle: "			    "Required head,tailroom: %d,%d\n", 			    ixs->headroom, ixs->tailroom);		ixs->max_headroom += ixs->headroom;		ixs->max_tailroom += ixs->tailroom;		ixs->pyldsz += (ixs->headroom + ixs->tailroom);	}	ixs->ipsp = ixs->ipsq;	/* restore the head of the ipsec_sa chain */			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,		    "klips_debug:ipsec_xmit_encap_bundle: "		    "existing head,tailroom: %d,%d before applying xforms with head,tailroom: %d,%d .\n",		    skb_headroom(ixs->skb), skb_tailroom(ixs->skb),		    ixs->max_headroom, ixs->max_tailroom);			ixs->tot_headroom += ixs->max_headroom;	ixs->tot_tailroom += ixs->max_tailroom;			ixs->mtudiff = ixs->prv->mtu + ixs->tot_headroom + ixs->tot_tailroom - ixs->physmtu;	KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,		    "klips_debug:ipsec_xmit_encap_bundle: "		    "mtu:%d physmtu:%d tothr:%d tottr:%d mtudiff:%d ippkttotlen:%d\n",		    ixs->prv->mtu, ixs->physmtu,		    ixs->tot_headroom, ixs->tot_tailroom, ixs->mtudiff, ntohs(ixs->iph->tot_len));	if(ixs->mtudiff > 0) {		int newmtu = ixs->physmtu - (ixs->tot_headroom + ((ixs->tot_tailroom + 2) & ~7) + 5);		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,			    "klips_info:ipsec_xmit_encap_bundle: "			    "dev %s mtu of %d decreased by %d to %d\n",			    ixs->dev->name,			    ixs->prv->mtu,			    ixs->prv->mtu - newmtu,			    newmtu);		ixs->prv->mtu = newmtu;#ifdef NET_21#if 0		ixs->skb->dst->pmtu = ixs->prv->mtu; /* RGB */#endif /* 0 */#else /* NET_21 */#if 0		ixs->dev->mtu = ixs->prv->mtu; /* RGB */#endif /* 0 */#endif /* NET_21 */	}	/* 	   If the sender is doing PMTU discovery, and the	   packet doesn't fit within ixs->prv->mtu, notify him	   (unless it was an ICMP packet, or it was not the	   zero-offset packet) and send it anyways.	   Note: buggy firewall configuration may prevent the	   ICMP packet from getting back.	*/	if(sysctl_ipsec_icmp	   && ixs->prv->mtu < ntohs(ixs->iph->tot_len)	   && (ixs->iph->frag_off & __constant_htons(IP_DF)) ) {		int notify = ixs->iph->protocol != IPPROTO_ICMP			&& (ixs->iph->frag_off & __constant_htons(IP_OFFSET)) == 0;			#ifdef IPSEC_obey_DF		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,			    "klips_debug:ipsec_xmit_encap_bundle: "			    "fragmentation needed and DF set; %sdropping packet\n",			    notify ? "sending ICMP and " : "");		if (notify)			ICMP_SEND(ixs->skb,				  ICMP_DEST_UNREACH,				  ICMP_FRAG_NEEDED,				  ixs->prv->mtu,				  ixs->physdev);		ixs->stats->tx_errors++;		bundle_stat = IPSEC_XMIT_CANNOTFRAG;		goto cleanup;#else /* IPSEC_obey_DF */		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,			    "klips_debug:ipsec_xmit_encap_bundle: "			    "fragmentation needed and DF set; %spassing packet\n",			    notify ? "sending ICMP and " : "");		if (notify)			ICMP_SEND(ixs->skb,				  ICMP_DEST_UNREACH,				  ICMP_FRAG_NEEDED,				  ixs->prv->mtu,				  ixs->physdev);#endif /* IPSEC_obey_DF */	}		#ifdef MSS_HACK	/*	 * If this is a transport mode TCP packet with	 * SYN set, determine an effective MSS based on 	 * AH/ESP overheads determined above.	 */	if (ixs->iph->protocol == IPPROTO_TCP 	    && ixs->outgoing_said.proto != IPPROTO_IPIP) {		struct tcphdr *tcph = ixs->skb->h.th;		if (tcph->syn && !tcph->ack) {			if(!ipsec_adjust_mss(ixs->skb, tcph, ixs->prv->mtu)) {				printk(KERN_WARNING				       "klips_warning:ipsec_xmit_encap_bundle: "				       "ipsec_adjust_mss() failed\n");				ixs->stats->tx_errors++;				bundle_stat = IPSEC_XMIT_MSSERR;				goto cleanup;			}		}	}#endif /* MSS_HACK */#ifdef CONFIG_KLIPS_NAT_TRAVERSAL      if ((ixs->natt_type) && (ixs->outgoing_said.proto != IPPROTO_IPIP)) {	      /**	       * NAT-Traversal and Transport Mode:	       *   we need to correct TCP/UDP checksum	       *	       * If we've got NAT-OA, we can fix checksum without recalculation.	       * If we don't we can zero udp checksum.	       */	      __u32 natt_oa = ixs->ipsp->ips_natt_oa ?		      ((struct sockaddr_in*)(ixs->ipsp->ips_natt_oa))->sin_addr.s_addr : 0;	      __u16 pkt_len = ixs->skb->tail - (unsigned char *)ixs->iph;	      __u16 data_len = pkt_len - (ixs->iph->ihl << 2);	      switch (ixs->iph->protocol) {		      case IPPROTO_TCP:			      if (data_len >= sizeof(struct tcphdr)) {				      struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ixs->iph+ixs->iph->ihl);				      if (natt_oa) {					      __u32 buff[2] = { ~ixs->iph->daddr, natt_oa };					      KLIPS_PRINT(debug_tunnel,						      "klips_debug:ipsec_tunnel_start_xmit: "						      "NAT-T & TRANSPORT: "						      "fix TCP checksum using NAT-OA\n");					      tcp->check = csum_fold(						      csum_partial((unsigned char *)buff, sizeof(buff),						      tcp->check^0xffff));				      }				      else {					      KLIPS_PRINT(debug_tunnel,						      "klips_debug:ipsec_tunnel_start_xmit: "						      "NAT-T & TRANSPORT: do not recalc TCP checksum\n");				      }			      }			      else {				      KLIPS_PRINT(debug_tunnel,					      "klips_debug:ipsec_tunnel_start_xmit: "					      "NAT-T & TRANSPORT: can't fix TCP checksum\n");			      }			      break;		      case IPPROTO_UDP:			      if (data_len >= sizeof(struct udphdr)) {				      struct udphdr *udp = (struct udphdr *)((__u32 *)ixs->iph+ixs->iph->ihl);				      if (udp->check == 0) {					      KLIPS_PRINT(debug_tunnel,						      "klips_debug:ipsec_tunnel_start_xmit: "						      "NAT-T & TRANSPORT: UDP checksum already 0\n");				      }				      else if (natt_oa) {					      __u32 buff[2] = { ~ixs->iph->daddr, natt_oa };					      KLIPS_PRINT(debug_tunnel,						      "klips_debug:ipsec_tunnel_start_xmit: "						      "NAT-T & TRANSPORT: "						      "fix UDP checksum using NAT-OA\n");					      udp->check = csum_fold(						      csum_partial((unsigned char *)buff, sizeof(buff),						      udp->check^0xffff));				      }				      else {					      KLIPS_PRINT(debug_tunnel,						      "klips_debug:ipsec_tunnel_start_xmit: "						      "NAT-T & TRANSPORT: zero UDP checksum\n");					      udp->check = 0;				      }			      }			      else {				      KLIPS_PRINT(debug_tunnel,					      "klips_debug:ipsec_tunnel_start_xmit: "					      "NAT-T & TRANSPORT: can't fix UDP checksum\n");			      }			      break;		      default:			      KLIPS_PRINT(debug_tunnel,				      "klips_debug:ipsec_tunnel_start_xmit: "				      "NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n");			      break;	      }      }#endif /* CONFIG_KLIPS_NAT_TRAVERSAL */	if(!ixs->hard_header_stripped) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_debug:ipsec_xmit_encap_bundle: "			    "allocating %d bytes for hardheader.\n",			    ixs->hard_header_len);		if((ixs->saved_header = kmalloc(ixs->hard_header_len, GFP_ATOMIC)) == NULL) {			printk(KERN_WARNING "klips_debug:ipsec_xmit_encap_bundle: "			       "Failed, tried to allocate %d bytes for temp hard_header.\n", 			       ixs->hard_header_len);			ixs->stats->tx_errors++;			bundle_stat = IPSEC_XMIT_ERRMEMALLOC;			goto cleanup;		}		{			int i;			for (i = 0; i < ixs->hard_header_len; i++) {				ixs->saved_header[i] = ixs->skb->data[i];			}		}		if(ixs->skb->len < ixs->hard_header_len) {			printk(KERN_WARNING "klips_error:ipsec_xmit_encap_bundle: "			       "tried to skb_pull hhlen=%d, %d available.  This should never happen, please report.\n",			       ixs->hard_header_len, (int)(ixs->skb->len));			ixs->stats->tx_errors++;			bundle_stat = IPSEC_XMIT_ESP_PUSHPULLERR;			goto cleanup;		}		skb_pull(ixs->skb, ixs->hard_header_len);		ixs->hard_header_stripped = 1;			/*			ixs->iph = (struct iphdr *) (ixs->skb->data); */		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,			    "klips_debug:ipsec_xmit_encap_bundle: "			    "head,tailroom: %d,%d after hard_header stripped.\n",			    skb_headroom(ixs->skb), skb_tailroom(ixs->skb));		KLIPS_IP_PRINT(debug_tunnel & DB_TN_CROUT, ixs->iph);	} else {		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,			    "klips_debug:ipsec_xmit_encap_bundle: "			    "hard header already stripped.\n");	}			ixs->ll_headroom = (ixs->hard_header_len + 15) & ~15;	if ((skb_headroom(ixs->skb) >= ixs->max_headroom + 2 * ixs->ll_headroom) && 	    (skb_tailroom(ixs->skb) >= ixs->max_tailroom)#ifndef NET_21	    && ixs->skb->free#endif /* !NET_21 */		) {		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,			    "klips_debug:ipsec_xmit_encap_bundle: "			    "data fits in existing skb\n");	} else {		struct sk_buff* tskb;		if(!ixs->oskb) {			ixs->oskb = ixs->skb;		}		tskb = skb_copy_expand(ixs->skb,				       /* The need for 2 * link layer length here remains unexplained...RGB */				       ixs->max_headroom + 2 * ixs->ll_headroom,				       ixs->max_tailroom,				       GFP_ATOMIC);#ifdef NET_21		if(tskb && ixs->skb->sk) {			skb_set_owner_w(tskb, ixs->skb->sk);		}#endif /* NET_21 */		if(ixs->skb != ixs->oskb) {			ipsec_kfree_skb(ixs->skb);		}		ixs->skb = tskb;		if (!ixs->skb) {			printk(KERN_WARNING			       "klips_debug:ipsec_xmit_encap_bundle: "			       "Failed, tried to allocate %d head and %d tailroom\n", 			       ixs->max_headroom, ixs->max_tailroom);			ixs->stats->tx_errors++;			bundle_stat = IPSEC_XMIT_ERRSKBALLOC;			goto cleanup;		}		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,			    "klips_debug:ipsec_xmit_encap_bundle: "			    "head,tailroom: %d,%d after allocation\n",			    skb_headroom(ixs->skb), skb_tailroom(ixs->skb));	}			/*	 * Apply grouped transforms to packet	 */	while (ixs->ipsp) {		enum ipsec_xmit_value encap_stat = IPSEC_XMIT_OK;		encap_stat = ipsec_xmit_encap_once(ixs);		if(encap_stat != IPSEC_XMIT_OK) {			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_encap_bundle: encap_once failed: %d\n",				    encap_stat);							bundle_stat = IPSEC_XMIT_ENCAPFAIL;			goto cleanup;		}	}	/* end encapsulation loop here XXX */ cleanup:	spin_unlock(&tdb_lock);	return bundle_stat;}/* * $Log: ipsec_xmit.c,v $ * Revision 1.10  2004/09/13 17:55:21  ken * MD5* -> osMD5* * * Revision 1.9  2004/07/10 19:11:18  mcr * 	CONFIG_IPSEC -> CONFIG_KLIPS. * * Revision 1.8  2004/04/06 02:49:26  mcr * 	pullup of algo code from alg-branch. * * Revision 1.7  2004/02/03 03:13:41  mcr * 	mark invalid encapsulation states. * * Revision 1.6.2.1  2003/12/22 15:25:52  jjo *      Merged algo-0.8.1-rc11-test1 into alg-branch * * Revision 1.6  2003/12/10 01:14:27  mcr * 	NAT-traversal patches to KLIPS. * * Revision 1.5  2003/10/31 02:27:55  mcr * 	pulled up port-selector patches and sa_id elimination. * * Revision 1.4.4.2  2003/10/29 01:37:39  mcr * 	when creating %hold from %trap, only make the %hold as * 	specific as the %trap was - so if the protocol and ports * 	were wildcards, then the %hold will be too. * * Revision 1.4.4.1  2003/09/21 13:59:56  mcr * 	pre-liminary X.509 patch - does not yet pass tests. * * Revision 1.4  2003/06/20 02:28:10  mcr * 	misstype of variable name, not detected by module build. * * Revision 1.3  2003/06/20 01:42:21  mcr * 	added counters to measure how many ACQUIREs we send to pluto, * 	and how many are successfully sent. * * Revision 1.2  2003/04/03 17:38:35  rgb * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. * Normalised coding style. * Simplified logic and reduced duplication of code. * * Revision 1.1  2003/02/12 19:31:23  rgb * Refactored from ipsec_tunnel.c * */

⌨️ 快捷键说明

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