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

📄 ipsec_rcv.c

📁 网上下到的一个很详细介绍VPN基础知识的资料
💻 C
📖 第 1 页 / 共 4 页
字号:
				break;			default:				tdbp->tdb_alg_errs += 1;				spin_unlock(&tdb_lock);				if(stats) {					stats->rx_errors++;				}				goto rcvleave;			}			idat += esphlen;			ilen -= esphlen;						switch(tdbp->tdb_encalg) {			case ESP_3DES:				if ((ilen) % 8) {					tdbp->tdb_encsize_errs += 1;					spin_unlock(&tdb_lock);					printk("klips_error:ipsec_rcv: "					       "got packet with esplen = %d from %s -- should be on 8 octet boundary, packet dropped\n",					       ilen,					       ipaddr_txt);					if(stats) {						stats->rx_errors++;					}					goto rcvleave;				}				des_ede3_cbc_encrypt(idat, idat, ilen,						     tdbp->tdb_key_e,						     tdbp->tdb_key_e + sizeof(struct des_eks),						     tdbp->tdb_key_e + 2 * sizeof(struct des_eks),						     (caddr_t)iv, 0);				break;			}			next_header = idat[ilen - 1];			padlen = idat[ilen - 2];			pad = padlen + 2 + authlen;			{			        int badpad = 0;								KLIPS_PRINT(debug_rcv & DB_RX_IPAD,					    "klips_debug:ipsec_rcv: "					    "padlen=%d, contents: 0x<offset>: 0x<value> 0x<value> ...\n",					    padlen);								for (i = 1; i <= padlen; i++) {					if((i % 16) == 1) {						KLIPS_PRINT(debug_rcv & DB_RX_IPAD,							    "klips_debug:           %02x:",							    i - 1);					}					KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD,						    " %02x",						    idat[ilen - 2 - padlen + i - 1]);					if(i != idat[ilen - 2 - padlen + i - 1]) {					        badpad = 1;					} 					if((i % 16) == 0) {						KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD,							    "\n");					}				}				if((i % 16) != 1) {					KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD,							"\n");				}				if(badpad) {					KLIPS_PRINT(debug_rcv & DB_RX_IPAD,						    "klips_debug:ipsec_rcv: "						    "warning, decrypted packet from %s has bad padding\n",						    ipaddr_txt);					KLIPS_PRINT(debug_rcv & DB_RX_IPAD,						    "klips_debug:ipsec_rcv: "						    "...may be bad decryption -- not dropped\n");					tdbp->tdb_encpad_errs += 1;				}								KLIPS_PRINT(debug_rcv & DB_RX_IPAD,					    "klips_debug:ipsec_rcv: "					    "packet decrypted from %s: next_header = %d, padding = %d\n",					    ipaddr_txt,					    next_header,					    pad - 2 - authlen);			}#endif /* !CONFIG_IPSEC_ESP */#ifdef CONFIG_IPSEC_AH		case IPPROTO_AH:			break;#endif /* CONFIG_IPSEC_AH */		}	       		/*		 *	Discard the original IP header		 */				ipp->protocol = next_header;				switch(proto) {#ifdef CONFIG_IPSEC_ESP		case IPPROTO_ESP:			ipp->tot_len = htons(ntohs(ipp->tot_len) - (esphlen + pad));			memmove((void *)(skb->data + esphlen),				(void *)(skb->data), iphlen);			if(skb->len < esphlen) {				spin_unlock(&tdb_lock);				printk(KERN_WARNING				       "klips_error:ipsec_rcv: "				       "tried to skb_pull esphlen=%d, %d available.  This should never happen, please report.\n",				       esphlen, (int)(skb->len));				goto rcvleave;			}			skb_pull(skb, esphlen);			KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,				    "klips_debug:ipsec_rcv: "				    "trimming to %d.\n",				    len - esphlen - pad);			if(pad + esphlen <= len) {			        skb_trim(skb, len - esphlen - pad);			} else {				spin_unlock(&tdb_lock);			        KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,				            "klips_debug:ipsec_rcv: "					    "bogus packet, size is zero or negative, dropping.\n");				goto rcvleave;			}		break;#endif /* !CONFIG_IPSEC_ESP */#ifdef CONFIG_IPSEC_AH		case IPPROTO_AH:			ipp->tot_len = htons(ntohs(ipp->tot_len) - ahhlen);			memmove((void *)(skb->data + ahhlen),				(void *)(skb->data), iphlen);			if(skb->len < ahhlen) {				spin_unlock(&tdb_lock);				printk(KERN_WARNING				       "klips_error:ipsec_rcv: "				       "tried to skb_pull ahhlen=%d, %d available.  This should never happen, please report.\n",				       ahhlen,				       (int)(skb->len));				goto rcvleave;			}			skb_pull(skb, ahhlen);			break;#endif /* CONFIG_IPSEC_AH */		}		/*		 *	Adjust pointers		 */				len = skb->len;		dat = skb->data;		#ifdef NET_21/*		skb->h.ipiph=(struct iphdr *)skb->data; */		skb->nh.raw = skb->data;		skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2);				memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));#else /* NET_21 */		skb->h.iph=(struct iphdr *)skb->data;		skb->ip_hdr=(struct iphdr *)skb->data;		memset(skb->proto_priv, 0, sizeof(struct options));#endif /* NET_21 */				ipp = (struct iphdr *)dat;		ipp->check = 0;		ipp->check = ip_fast_csum((unsigned char *)dat, iphlen >> 2);				KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,			    "klips_debug:ipsec_rcv: "			    "after <%s%s%s>, SA:%s:\n",			    TDB_XFORM_NAME(tdbp),			    sa_len ? sa : " (error)");		KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp);				skb->protocol = htons(ETH_P_IP);		skb->ip_summed = 0;		tdbprev = tdbp;		tdbnext = tdbp->tdb_inext;		if(sysctl_ipsec_inbound_policy_check) {			if(tdbnext) {				if(tdbnext->tdb_onext != tdbp) {					spin_unlock(&tdb_lock);					KLIPS_PRINT(debug_rcv,						    "klips_debug:ipsec_rcv: "						    "SA:%s, backpolicy does not agree with fwdpolicy.\n",						    sa_len ? sa : " (error)");					if(stats) {						stats->rx_dropped++;					}					goto rcvleave;				}				KLIPS_PRINT(debug_rcv,					    "klips_debug:ipsec_rcv: "					    "SA:%s, backpolicy agrees with fwdpolicy.\n",					    sa_len ? sa : " (error)");				if(!(   (ipp->protocol == IPPROTO_AH  )					|| (ipp->protocol == IPPROTO_ESP )					|| (ipp->protocol == IPPROTO_IPIP)#ifdef CONFIG_IPSEC_IPCOMP					|| (ipp->protocol == IPPROTO_COMP)#endif /* CONFIG_IPSEC_IPCOMP */					)) {					spin_unlock(&tdb_lock);					KLIPS_PRINT(debug_rcv,						    "klips_debug:ipsec_rcv: "						    "packet with incomplete policy dropped, last successful SA:%s.\n",						    sa_len ? sa : " (error)");					if(stats) {						stats->rx_dropped++;					}					goto rcvleave;				}				KLIPS_PRINT(debug_rcv,					    "klips_debug:ipsec_rcv: "					    "SA:%s, Another IPSEC header to process.\n",					    sa_len ? sa : " (error)");			} else {				KLIPS_PRINT(debug_rcv,					    "klips_debug:ipsec_rcv: "					    "No tdb_inext from this SA:%s.\n",					    sa_len ? sa : " (error)");			}		}#ifdef CONFIG_IPSEC_IPCOMP		/* update ipcomp ratio counters, even if no ipcomp packet is present */		if (tdbnext		  && tdbnext->tdb_said.proto == IPPROTO_COMP		  && ipp->protocol != IPPROTO_COMP) {			tdbnext->tdb_comp_ratio_cbytes += ntohs(ipp->tot_len);			tdbnext->tdb_comp_ratio_dbytes += ntohs(ipp->tot_len);		}#endif /* CONFIG_IPSEC_IPCOMP */		tdbp->tdb_lifetime_bytes_c += len;		if(!tdbp->tdb_lifetime_usetime_c) {			tdbp->tdb_lifetime_usetime_c = jiffies / HZ;		}		tdbp->tdb_lifetime_usetime_l = jiffies / HZ;		tdbp->tdb_lifetime_packets_c += 1;			/* end decapsulation loop here */	} while(   (ipp->protocol == IPPROTO_ESP )		|| (ipp->protocol == IPPROTO_AH  )#ifdef CONFIG_IPSEC_IPCOMP		|| (ipp->protocol == IPPROTO_COMP)#endif /* CONFIG_IPSEC_IPCOMP */		);	#ifdef CONFIG_IPSEC_IPCOMP	if(tdbnext && tdbnext->tdb_said.proto == IPPROTO_COMP) {		tdbprev = tdbp;		tdbp = tdbnext;		tdbnext = tdbp->tdb_inext;	}#endif /* CONFIG_IPSEC_IPCOMP */	/*	 * XXX this needs to be locked from when it was first looked	 * up in the decapsulation loop.  Perhaps it is better to put	 * the IPIP decap inside the loop.	 */	if(tdbnext) {		tdbp = tdbnext;		sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);		if(ipp->protocol != IPPROTO_IPIP) {			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "SA:%s, Hey!  How did this get through?  Dropped.\n",				    sa_len ? sa : " (error)");			if(stats) {				stats->rx_dropped++;			}			goto rcvleave;		}		if(sysctl_ipsec_inbound_policy_check) {			if((tdbnext = tdbp->tdb_inext)) {				char sa2[SATOA_BUF];				size_t sa_len2;				sa_len2 = satoa(tdbnext->tdb_said, 0, sa2, SATOA_BUF);				spin_unlock(&tdb_lock);				KLIPS_PRINT(debug_rcv,					    "klips_debug:ipsec_rcv: "					    "unexpected SA:%s after IPIP SA:%s\n",					    sa_len2 ? sa2 : " (error)",					    sa_len ? sa : " (error)");				if(stats) {					stats->rx_dropped++;				}				goto rcvleave;			}			if(ipp->saddr != ((struct sockaddr_in*)(tdbp->tdb_addr_s))->sin_addr.s_addr) {				spin_unlock(&tdb_lock);				ipaddr.s_addr = ipp->saddr;				addrtoa(ipaddr, 0, ipaddr_txt, sizeof(ipaddr_txt));				KLIPS_PRINT(debug_rcv,					    "klips_debug:ipsec_rcv: "					    "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n",					    sa_len ? sa : " (error)",					    ipaddr_txt);				if(stats) {					stats->rx_dropped++;				}				goto rcvleave;			}		}		/*		 * XXX this needs to be locked from when it was first looked		 * up in the decapsulation loop.  Perhaps it is better to put		 * the IPIP decap inside the loop.		 */		tdbp->tdb_lifetime_bytes_c += len;		if(!tdbp->tdb_lifetime_usetime_c) {			tdbp->tdb_lifetime_usetime_c = jiffies / HZ;		}		tdbp->tdb_lifetime_usetime_l = jiffies / HZ;		tdbp->tdb_lifetime_packets_c += 1;				if(skb->len < iphlen) {			spin_unlock(&tdb_lock);			printk(KERN_WARNING "klips_debug:ipsec_rcv: "			       "tried to skb_pull iphlen=%d, %d available.  This should never happen, please report.\n",			       iphlen,			       (int)(skb->len));			goto rcvleave;		}		skb_pull(skb, iphlen);#ifdef NET_21		ipp = (struct iphdr *)skb->nh.raw = skb->data;		skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2);				memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));#else /* NET_21 */		ipp = skb->ip_hdr = skb->h.iph = (struct iphdr *)skb->data;		memset(skb->proto_priv, 0, sizeof(struct options));#endif /* NET_21 */		skb->protocol = htons(ETH_P_IP);		skb->ip_summed = 0;		KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,			    "klips_debug:ipsec_rcv: "			    "IPIP tunnel stripped.\n");		KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp);	}#ifdef INBOUND_POLICY_CHECK_eroute	/*	  Do *not* enable this without thoroughly checking spinlock issues	  first.  In particular, nesting an eroute spinlock within a tdb	  spinlock could result in a deadlock.  (Well, only on a SMP machine	  under 2.4?)	*/	/*	 * First things first -- look us up in the erouting tables.	 */	matcher.sen_len = sizeof (struct sockaddr_encap);	matcher.sen_family = AF_ENCAP;	matcher.sen_type = SENT_IP4;	if(ipp->protocol == IPPROTO_IPIP) {		struct iphdr *ipp2;		ipp2 = (struct iphdr*) (((char*)ipp) + (ipp->ihl << 2));		matcher.sen_ip_src.s_addr = ipp2->saddr;		matcher.sen_ip_dst.s_addr = ipp2->daddr;	} else {		matcher.sen_ip_src.s_addr = ipp->saddr;		matcher.sen_ip_dst.s_addr = ipp->daddr;	}		/*	 * 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);		er = ipsec_findroute(&matcher);	if(er) {		policy_said = er->er_said;		policy_eaddr = er->er_eaddr;		policy_emask = er->er_emask;		er->er_count++;		er->er_lasttime = jiffies/HZ;	}		spin_unlock(&eroute_lock);	if(er) {		/*		 * The spinlock is to prevent any other process from		 * accessing or deleting the tdb while we are using and		 * updating it.		 */		spin_lock(&tdb_lock);		policy_tdb = gettdb(&policy_said);		if (policy_tdb == NULL) {			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "no Tunnel Descriptor Block for SA%s: incoming packet with no policy SA, dropped.\n",				    sa_len ? sa : " (error)");			goto rcvleave;		}				sa_len = satoa(policy_said, 0, sa, SATOA_BUF);		KLIPS_PRINT(debug_rcv,			    "klips_debug:ipsec_rcv: "			    "found policy Tunnel Descriptor Block -- SA:%s\n",			    sa_len ? sa : " (error)");		while(1) {			if(policy_tdb->tdb_inext) {				policy_tdb = policy_tdb->tdb_inext;			} else {				break;			}		}		if(policy_tdb != tdbp) {			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "Tunnel Descriptor Block for SA%s: incoming packet with different policy SA, dropped.\n",				    sa_len ? sa : " (error)");			goto rcvleave;		}		/* spin_unlock(&tdb_lock); */	}#endif /* INBOUND_POLICY_CHECK_eroute */	spin_unlock(&tdb_lock);#ifdef NET_21	if(stats) {		stats->rx_bytes += skb->len;	}	if(skb->dst) {		dst_release(skb->dst);		skb->dst = NULL;	}	skb->pkt_type = PACKET_HOST;	if(hard_header_len &&	   (skb->mac.raw != (skb->data - hard_header_len)) &&	   (hard_header_len <= skb_headroom(skb))) {		/* copy back original MAC header */		memmove(skb->data - hard_header_len, skb->mac.raw, hard_header_len);		skb->mac.raw = skb->data - hard_header_len;	}#endif /* NET_21 */#ifdef CONFIG_IPSEC_IPCOMP	if(ipp->protocol == IPPROTO_COMP) {		unsigned int flags = 0;		if(sysctl_ipsec_inbound_policy_check) {			KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,				"klips_debug:ipsec_rcv: "				"inbound policy checking enabled, IPCOMP follows IPIP, dropped.\n");			if (stats) {				stats->rx_errors++;			}			goto rcvleave;		}		/*		  XXX need a TDB for updating ratio counters but it is not		  following policy anyways so it is not a priority		*/		skb = skb_decompress(skb, NULL, &flags);		if (!skb || flags) {			KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,				"klips_debug:ipsec_rcv: "				"skb_decompress() returned error flags: %d, dropped.\n",			       flags);			if (stats) {				stats->rx_errors++;			}			goto rcvleave;		}	}#endif /* CONFIG_IPSEC_IPCOMP */#ifdef SKB_RESET_NFCT        nf_conntrack_put(skb->nfct);        skb->nfct = NULL;#ifdef CONFIG_NETFILTER_DEBUG	skb->nf_debug = 0;#endif /* CONFIG_NETFILTER_DEBUG */#endif /* SKB_RESET_NFCT */	KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,		    "klips_debug:ipsec_rcv: "		    "netif_rx() called.\n");	netif_rx(skb);	MOD_DEC_USE_COUNT;	return(0);	 rcvleave: 	if(skb) {#ifdef NET_21                kfree_skb(skb);#else /* NET_21 */                kfree_skb(skb, FREE_WRITE);#endif /* NET_21 */	}	MOD_DEC_USE_COUNT;

⌨️ 快捷键说明

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