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

📄 ipsec_tunnel.c

📁 网上下到的一个很详细介绍VPN基础知识的资料
💻 C
📖 第 1 页 / 共 5 页
字号:
		  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 TDB instead.  This is not likely to happen		  in KLIPS1 unless a volunteer contributes it, but will be		  designed into KLIPS2.		*/		if(tdbprev == NULL) {			spin_lock(&tdb_lock);		}		tdbp = gettdb(&outgoing_said);		sa_len = satoa(outgoing_said, 0, sa, SATOA_BUF);		if (tdbp == NULL) {			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "no Tunnel Descriptor Block for SA%s: outgoing packet with no SA, dropped.\n",				    sa_len ? sa : " (error)");			stats->tx_dropped++;			goto cleanup;		}				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_debug:ipsec_tunnel_start_xmit: "			    "found Tunnel Descriptor Block -- SA:<%s%s%s> %s\n",			    TDB_XFORM_NAME(tdbp),			    sa_len ? sa : " (error)");				/*		 * How much headroom do we need to be able to apply		 * all the grouped transforms?		 */		tdbq = tdbp;	/* save the head of the tdb chain */		while (tdbp)	{			sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);			/* If it is in larval state, drop the packet, we cannot process yet. */			if(tdbp->tdb_state == SADB_SASTATE_LARVAL) {				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "TDB in larval state for SA:<%s%s%s> %s, cannot be used yet, dropping packet.\n",					    TDB_XFORM_NAME(tdbp),					    sa_len ? sa : " (error)");				spin_unlock(&tdb_lock);				stats->tx_errors++;				goto cleanup;			}			if(tdbp->tdb_state == SADB_SASTATE_DEAD) {				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "TDB in dead state for SA:<%s%s%s> %s, can no longer be used, dropping packet.\n",					    TDB_XFORM_NAME(tdbp),					    sa_len ? sa : " (error)");				spin_unlock(&tdb_lock);				stats->tx_errors++;				goto cleanup;			}			/* If the replay window counter == -1, expire SA, it will roll */			if(tdbp->tdb_replaywin && tdbp->tdb_replaywin_lastseq == -1) {				pfkey_expire(tdbp, 1);				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "replay window counter rolled for SA:<%s%s%s> %s, packet dropped, expiring SA.\n",					    TDB_XFORM_NAME(tdbp),					    sa_len ? sa : " (error)");				deltdbchain(tdbp);				spin_unlock(&tdb_lock);				stats->tx_errors++;				goto cleanup;			}			/* If any of the lifetime counters have overflowed, expire the SA(s). */			if(tdbp->tdb_lifetime_bytes_h &&			   (tdbp->tdb_lifetime_bytes_c > tdbp->tdb_lifetime_bytes_h)) {				pfkey_expire(tdbp, 1);				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "hard bytes lifetime of SA:<%s%s%s> %s has been reached, SA expired, outgoing packet dropped.\n",					    TDB_XFORM_NAME(tdbp),					    sa_len ? sa : " (error)");				deltdbchain(tdbp);				spin_unlock(&tdb_lock);				stats->tx_errors++;				goto cleanup;			}			if(tdbp->tdb_lifetime_bytes_s &&			   (tdbp->tdb_lifetime_bytes_c > tdbp->tdb_lifetime_bytes_s)) {				if(tdbp->tdb_state != SADB_SASTATE_DYING) {					pfkey_expire(tdbp, 0);				}				tdbp->tdb_state = SADB_SASTATE_DYING;				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "soft bytes lifetime of SA:<%s%s%s> %s has been reached, SA expiring, soft expire message sent up, outgoing packet still processed.\n",					    TDB_XFORM_NAME(tdbp),					    sa_len ? sa : " (error)");			}			if(tdbp->tdb_lifetime_addtime_h &&			   ((jiffies / HZ) - tdbp->tdb_lifetime_addtime_c >			    tdbp->tdb_lifetime_addtime_h)) {				pfkey_expire(tdbp, 1);				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "hard addtime lifetime of SA:<%s%s%s> %s has been reached, SA expired, outgoing packet dropped.\n",					    TDB_XFORM_NAME(tdbp),					    sa_len ? sa : " (error)");				deltdbchain(tdbp);				spin_unlock(&tdb_lock);				stats->tx_errors++;				goto cleanup;			}			if(tdbp->tdb_lifetime_addtime_s &&			   ((jiffies / HZ) - tdbp->tdb_lifetime_addtime_c >			    tdbp->tdb_lifetime_addtime_s)) {				if(tdbp->tdb_state != SADB_SASTATE_DYING) {					pfkey_expire(tdbp, 0);				}				tdbp->tdb_state = SADB_SASTATE_DYING;				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "soft addtime lifetime of SA:<%s%s%s> %s has been reached, SA expiring, soft expire message sent up, outgoing packet still processed.\n",					    TDB_XFORM_NAME(tdbp),					    sa_len ? sa : " (error)");			}			if(tdbp->tdb_lifetime_usetime_c) {				if(tdbp->tdb_lifetime_usetime_h &&				   ((jiffies / HZ) - tdbp->tdb_lifetime_usetime_c >				    tdbp->tdb_lifetime_usetime_h)) {					pfkey_expire(tdbp, 1);					KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,						    "klips_debug:ipsec_tunnel_start_xmit: "						    "hard usetime lifetime of SA:<%s%s%s> %s has been reached, SA expired, outgoing packet dropped.\n",						    TDB_XFORM_NAME(tdbp),						    sa_len ? sa : " (error)");					deltdbchain(tdbp);					spin_unlock(&tdb_lock);					stats->tx_errors++;					goto cleanup;				}				if(tdbp->tdb_lifetime_usetime_s &&				   ((jiffies / HZ) - tdbp->tdb_lifetime_usetime_c >				    tdbp->tdb_lifetime_usetime_s)) {					if(tdbp->tdb_state != SADB_SASTATE_DYING) {						pfkey_expire(tdbp, 0);					}					tdbp->tdb_state = SADB_SASTATE_DYING;					KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,						    "klips_debug:ipsec_tunnel_start_xmit: "						    "soft usetime lifetime of SA:<%s%s%s> %s has been reached, SA expiring, soft expire message sent up, outgoing packet still processed.\n",						    TDB_XFORM_NAME(tdbp),						    sa_len ? sa : " (error)");				}			}			if(tdbp->tdb_lifetime_packets_h &&			   (tdbp->tdb_lifetime_packets_c > tdbp->tdb_lifetime_packets_h)) {				pfkey_expire(tdbp, 1);				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "hard packets lifetime of SA:<%s%s%s> %s has been reached, SA expired, outgoing packet dropped.\n",					    TDB_XFORM_NAME(tdbp),					    sa_len ? sa : " (error)");				deltdbchain(tdbp);				spin_unlock(&tdb_lock);				stats->tx_errors++;				goto cleanup;			}			if(tdbp->tdb_lifetime_packets_s &&			   (tdbp->tdb_lifetime_packets_c > tdbp->tdb_lifetime_packets_s)) {				if(tdbp->tdb_state != SADB_SASTATE_DYING) {					pfkey_expire(tdbp, 0);				}				tdbp->tdb_state = SADB_SASTATE_DYING;				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "soft packets lifetime of SA:<%s%s%s> %s has been reached, SA expiring, soft expire message sent up, outgoing packet still processed.\n",					    TDB_XFORM_NAME(tdbp),					    sa_len ? sa : " (error)");			}			headroom = tailroom = 0;			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "calling room for <%s%s%s>, SA:%s\n", 				    TDB_XFORM_NAME(tdbp),				    sa_len ? sa : " (error)");			switch(tdbp->tdb_said.proto) {#ifdef CONFIG_IPSEC_AH			case IPPROTO_AH:				headroom += sizeof(struct ah);				break;#endif /* CONFIG_IPSEC_AH */#ifdef CONFIG_IPSEC_ESP			case IPPROTO_ESP:				switch(tdbp->tdb_encalg) {#ifdef CONFIG_IPSEC_ENC_3DES				case ESP_3DES:					headroom += sizeof(struct esp);					break;#endif /* CONFIG_IPSEC_ENC_3DES */				default:					spin_unlock(&tdb_lock);					stats->tx_errors++;					goto cleanup;				}				switch(tdbp->tdb_authalg) {#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5				case AH_MD5:					tailroom += AHHMAC_HASHLEN;					break;#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1				case AH_SHA:					tailroom += AHHMAC_HASHLEN;					break;#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */				case AH_NONE:					break;				default:					spin_unlock(&tdb_lock);					stats->tx_errors++;					goto cleanup;				}							tailroom += ((8 - ((pyldsz + 2 * sizeof(unsigned char)) % 8)) % 8) + 2;				break;#endif /* !CONFIG_IPSEC_ESP */#ifdef CONFIG_IPSEC_IPIP			case IPPROTO_IPIP:				headroom += sizeof(struct iphdr);				break;#endif /* !CONFIG_IPSEC_IPIP */			case IPPROTO_COMP:#ifdef CONFIG_IPSEC_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_IPSEC_IPCOMP */			default:				spin_unlock(&tdb_lock);				stats->tx_errors++;				goto cleanup;			}			tdbp = tdbp->tdb_onext;			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "Required head,tailroom: %d,%d\n", 				    headroom, tailroom);			max_headroom += headroom;			max_tailroom += tailroom;			pyldsz += (headroom + tailroom);		}		tdbp = tdbq;	/* restore the head of the tdb chain */				KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,			    "klips_debug:ipsec_tunnel_start_xmit: "			    "existing head,tailroom: %d,%d before applying xforms with head,tailroom: %d,%d .\n",			    skb_headroom(skb), skb_tailroom(skb),			    max_headroom, max_tailroom);				tot_headroom += max_headroom;		tot_tailroom += max_tailroom;				mtudiff = prv->mtu + tot_headroom + tot_tailroom - physmtu;		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,			    "klips_debug:ipsec_tunnel_start_xmit: "			    "mtu:%d physmtu:%d tothr:%d tottr:%d mtudiff:%d ippkttotlen:%d\n",			    prv->mtu, physmtu,			    tot_headroom, tot_tailroom, mtudiff, ntohs(iph->tot_len));		if(mtudiff > 0) {			int newmtu = physmtu - (tot_headroom + ((tot_tailroom + 2) & ~7) + 5);			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,				    "klips_info:ipsec_tunnel_start_xmit: "				    "dev %s mtu of %d decreased by %d to %d\n",				    dev->name,				    prv->mtu,				    prv->mtu - newmtu,				    newmtu);			prv->mtu = newmtu;#ifdef NET_21#if 0			skb->dst->pmtu = prv->mtu; /* RGB */#endif /* 0 */#else /* NET_21 */#if 0			dev->mtu = prv->mtu; /* RGB */#endif /* 0 */#endif /* NET_21 */		}		/* If the sender is doing PMTU discovery, and the packet doesn't fit within		 * prv->mtu, notify him (unless it was an ICMP packet) and drop it.		 * Note: buggy firewall configuration may prevent the ICMP packet from getting back.		 * Note2: Linux 2.4.x is trying to do PMTU discovery on ICMP packets, but this seems		 * bogus, and should be fixed in the kernel.		 */		if (iph->frag_off & __constant_htons(IP_DF)			&& prv->mtu < ntohs(iph->tot_len))		{			int notify = iph->protocol != IPPROTO_ICMP				     && (iph->frag_off & __constant_htons(IP_OFFSET)) == 0;			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "fragmentation needed and DF set; %sdropping packet\n",				    notify ? "sending ICMP and " : "");			if (notify)				ICMP_SEND(skb,					  ICMP_DEST_UNREACH,					  ICMP_FRAG_NEEDED,					  prv->mtu,					  physdev);			stats->tx_dropped++;			goto cleanup;		}		#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 (iph->protocol == IPPROTO_TCP 		    && outgoing_said.proto != IPPROTO_IPIP) {			struct tcphdr *tcph = skb->h.th;			if (tcph->syn && !tcph->ack) {				if(!ipsec_adjust_mss(skb, tcph, prv->mtu)) {					spin_unlock(&tdb_lock);					printk(KERN_WARNING					       "klips_warning:ipsec_tunnel_start_xmit: "					       "ipsec_adjust_mss() failed\n");					stats->tx_errors++;					goto cleanup;				}			}		}#endif /* MSS_HACK */		if(!hard_header_stripped) {			if((saved_header = kmalloc(hard_header_len, GFP_ATOMIC)) == NULL) {				spin_unlock(&tdb_lock);				printk(KERN_WARNING "klips_debug:ipsec_tunnel_start_xmit: "				       "Failed, tried to allocate %d bytes for temp hard_header.\n", 				       hard_header_len);				stats->tx_errors++;				goto cleanup;			}			for (i = 0; i < hard_header_len; i++) {				saved_header[i] = skb->data[i];			}			if(skb->len < hard_header_len) {				spin_unlock(&tdb_lock);				printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: "				       "tried to skb_pull hhlen=%d, %d available.  This should never happen, please report.\n",				       hard_header_len, (int)(skb->len));				stats->tx_errors++;				goto cleanup;			}			skb_pull(skb, hard_header_len);			hard_header_stripped = 1;			/*			iph = (struct iphdr *) (skb->data); */			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "head,tailroom: %d,%d after hard_header stripped.\n",				    skb_headroom(skb), skb_tailroom(skb));			KLIPS_IP_PRINT(debug_tunnel & DB_TN_CROUT, iph);		} else {			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "hard header already stripped.\n");		}				ll_headroom = (hard_header_len + 15) & ~15;		if ((skb_headroom(skb) >= max_headroom + 2 * ll_headroom) && 		    (skb_tailroom(skb) >= max_tailroom)#ifndef NET_21			&& skb->free#endif /* !NET_21 */			) {			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "data fits in existing skb\n");		} else {			struct sk_buff* tskb = skb;			if(!oskb) {				oskb = skb;			}			tskb = skb_copy_expand(skb,			/* The reason for 2 * link layer length here still baffles me...RGB */					       max_headroom + 2 * ll_headroom,					       max_tailroom,					       GFP_ATOMIC);#ifdef NET_21			if(tskb && skb->sk) {				skb_set_owner_w(tskb, skb->sk);			}#endif /* NET_21 */			if(!(skb == oskb) ) {				dev_kfree_skb(skb, FREE_WRITE);			}			skb = tskb;			if (!skb) {				spin_unlock(&tdb_lock);				printk(KERN_WARNING				       "klips_debug:ipsec_tunnel_start_xmit: "				       "Failed, tried to allocate %d head and %d tailroom\n", 				       max_headroom, max_tailroom);				stats->tx_errors++;				goto cleanup;

⌨️ 快捷键说明

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