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

📄 ip_masq.c

📁 GNU Hurd 源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			write_unlock(&__ip_masq_lock);                }                		iph->saddr = ms->maddr;		ip_send_check(iph);		/* Rewrite port (id) */		(icmph->un).echo.id = ms->mport;		icmph->checksum = 0;		icmph->checksum = ip_compute_csum((unsigned char *)icmph, len);		IP_MASQ_DEBUG(2, "icmp request rwt %lX->%lX id %d type %d\n",		       ntohl(iph->saddr),		       ntohl(iph->daddr),		       ntohs(icmp_id(icmph)),		       icmph->type);		masq_set_state(ms, 1, iph, icmph);		ip_masq_put(ms);		return 1;	}#endif	/*	 * Work through seeing if this is for us.	 * These checks are supposed to be in an order that	 * means easy things are checked first to speed up	 * processing.... however this means that some	 * packets will manage to get a long way down this	 * stack and then be rejected, but thats life	 */	if ((icmph->type != ICMP_DEST_UNREACH) &&	    (icmph->type != ICMP_SOURCE_QUENCH) &&	    (icmph->type != ICMP_TIME_EXCEEDED))		return 0;	/* Now find the contained IP header */	ciph = (struct iphdr *) (icmph + 1);#ifdef CONFIG_IP_MASQUERADE_ICMP	if (ciph->protocol == IPPROTO_ICMP) {		/*		 * This section handles ICMP errors for ICMP packets		 */		struct icmphdr  *cicmph = (struct icmphdr *)((char *)ciph + 							     (ciph->ihl<<2));		IP_MASQ_DEBUG(2, "fw icmp/icmp rcv %lX->%lX id %d type %d\n",		       ntohl(ciph->saddr),		       ntohl(ciph->daddr),		       ntohs(icmp_id(cicmph)),		       cicmph->type);		read_lock(&__ip_masq_lock);		ms = __ip_masq_out_get(ciph->protocol, 				      ciph->daddr,				      icmp_id(cicmph),				      ciph->saddr,				      icmp_hv_rep(cicmph));		read_unlock(&__ip_masq_lock);		if (ms == NULL)			return 0;		/* Now we do real damage to this packet...! */		/* First change the source IP address, and recalc checksum */		iph->saddr = ms->maddr;		ip_send_check(iph);			/* Now change the *dest* address in the contained IP */		ciph->daddr = ms->maddr;		__ip_masq_put(ms);		ip_send_check(ciph);		/* Change the ID to the masqed one! */		(cicmph->un).echo.id = ms->mport;			/* And finally the ICMP checksum */		icmph->checksum = 0;		icmph->checksum = ip_compute_csum((unsigned char *) icmph, len);		IP_MASQ_DEBUG(2, "fw icmp/icmp rwt %lX->%lX id %d type %d\n",		       ntohl(ciph->saddr),		       ntohl(ciph->daddr),		       ntohs(icmp_id(cicmph)),		       cicmph->type);		return 1;	}#endif /* CONFIG_IP_MASQUERADE_ICMP */	/* We are only interested ICMPs generated from TCP or UDP packets */	if ((ciph->protocol != IPPROTO_UDP) && (ciph->protocol != IPPROTO_TCP))		return 0;	/*	 * Find the ports involved - this packet was	 * incoming so the ports are right way round	 * (but reversed relative to outer IP header!)	 */	pptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]);#if 0	if (ntohs(pptr[1]) < PORT_MASQ_BEGIN || 	    ntohs(pptr[1]) > PORT_MASQ_END) 		return 0;#endif	/* Ensure the checksum is correct */	if (ip_compute_csum((unsigned char *) icmph, len))	{		/* Failed checksum! */		IP_MASQ_DEBUG(0, "forward ICMP: failed checksum from %d.%d.%d.%d!\n",			      NIPQUAD(iph->saddr));		return(-1);	} 	IP_MASQ_DEBUG(2, "Handling forward ICMP for %08lX:%04X -> %08lX:%04X\n",	       ntohl(ciph->saddr), ntohs(pptr[0]),	       ntohl(ciph->daddr), ntohs(pptr[1]));#if 0	/* This is pretty much what __ip_masq_in_get_iph() does */	ms = __ip_masq_in_get(ciph->protocol, ciph->saddr, pptr[0], ciph->daddr, pptr[1]);#endif	read_lock(&__ip_masq_lock);	ms = __ip_masq_out_get(ciph->protocol,			       ciph->daddr,			       pptr[1],			       ciph->saddr,			       pptr[0]);	read_unlock(&__ip_masq_lock);	if (ms == NULL)		return 0;	/* Now we do real damage to this packet...! */	/* First change the source IP address, and recalc checksum */	iph->saddr = ms->maddr;	ip_send_check(iph);	/* Now change the *dest* address in the contained IP */	ciph->daddr = ms->maddr;	ip_send_check(ciph);	/* the TCP/UDP dest port - cannot redo check */	pptr[1] = ms->mport;	__ip_masq_put(ms);	/* And finally the ICMP checksum */	icmph->checksum = 0;	icmph->checksum = ip_compute_csum((unsigned char *) icmph, len); 	IP_MASQ_DEBUG(2, "Rewrote forward ICMP to %08lX:%04X -> %08lX:%04X\n",	       ntohl(ciph->saddr), ntohs(pptr[0]),	       ntohl(ciph->daddr), ntohs(pptr[1]));	return 1;}/* *	Own skb_cow() beast, tweaked for rewriting commonly *	used pointers in masq code */static struct sk_buff * masq_skb_cow(struct sk_buff **skb_p, 			struct iphdr **iph_p, unsigned char **t_p) {	struct sk_buff *skb=(*skb_p);	if (skb_cloned(skb)) {		skb = skb_copy(skb, GFP_ATOMIC);		if (skb) {			/*			 *	skb changed, update other pointers			 */			struct iphdr *iph = skb->nh.iph;			kfree_skb(*skb_p);			*skb_p = skb;			*iph_p = iph;			*t_p = (char*) iph + iph->ihl * 4;		}	}	return skb;}/* *	Handle ICMP messages in reverse (demasquerade) direction. *	Find any that might be relevant, check against existing connections, *	forward to masqueraded host if relevant. *	Currently handles error types - unreachable, quench, ttl exceeded */int ip_fw_demasq_icmp(struct sk_buff **skb_p){        struct sk_buff 	*skb   = *skb_p; 	struct iphdr	*iph   = skb->nh.iph;	struct icmphdr  *icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2));	struct iphdr    *ciph;	/* The ip header contained within the ICMP */	__u16	        *pptr;	/* port numbers from TCP/UDP contained header */	struct ip_masq	*ms;	unsigned short   len   = ntohs(iph->tot_len) - (iph->ihl * 4); 	IP_MASQ_DEBUG(2, "icmp in/rev (%d,%d) %lX -> %lX\n",	        icmph->type, ntohs(icmp_id(icmph)), 		ntohl(iph->saddr), ntohl(iph->daddr));#ifdef CONFIG_IP_MASQUERADE_ICMP			if ((icmph->type == ICMP_ECHOREPLY) ||	    (icmph->type == ICMP_TIMESTAMPREPLY) ||	    (icmph->type == ICMP_INFO_REPLY) ||	    (icmph->type == ICMP_ADDRESSREPLY))	{		IP_MASQ_DEBUG(2, "icmp reply rcv %lX->%lX id %d type %d, req %d\n",		       ntohl(iph->saddr),		       ntohl(iph->daddr),		       ntohs(icmp_id(icmph)),		       icmph->type,		       icmp_type_request(icmph->type));		ms = ip_masq_in_get(iph->protocol,				      iph->saddr,				      icmp_hv_rep(icmph),				      iph->daddr,				      icmp_id(icmph));		if (ms == NULL)			return 0;                /*                 *	got reply, so clear flag                 */                ms->flags &= ~IP_MASQ_F_NO_REPLY;		if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) {			ip_masq_put(ms);			return -1;		}		/* Reset source address */		iph->daddr = ms->saddr;		/* Redo IP header checksum */		ip_send_check(iph);		/* Set ID to fake port number */		(icmph->un).echo.id = ms->sport;		/* Reset ICMP checksum and set expiry */		icmph->checksum=0;		icmph->checksum=ip_compute_csum((unsigned char *)icmph,len);		IP_MASQ_DEBUG(2, "icmp reply rwt %lX->%lX id %d type %d\n",		       ntohl(iph->saddr),		       ntohl(iph->daddr),		       ntohs(icmp_id(icmph)),		       icmph->type);		masq_set_state(ms, 0, iph, icmph);		ip_masq_put(ms);		return 1;	} else {#endif		if ((icmph->type != ICMP_DEST_UNREACH) &&		    (icmph->type != ICMP_SOURCE_QUENCH) &&		    (icmph->type != ICMP_TIME_EXCEEDED))			return 0;#ifdef CONFIG_IP_MASQUERADE_ICMP	}#endif	/*	 * If we get here we have an ICMP error of one of the above 3 types	 * Now find the contained IP header	 */	ciph = (struct iphdr *) (icmph + 1);#ifdef CONFIG_IP_MASQUERADE_ICMP	if (ciph->protocol == IPPROTO_ICMP) {		/*		 * This section handles ICMP errors for ICMP packets		 *		 * First get a new ICMP header structure out of the IP packet		 */		struct icmphdr  *cicmph = (struct icmphdr *)((char *)ciph + 							     (ciph->ihl<<2));		IP_MASQ_DEBUG(2, "rv icmp/icmp rcv %lX->%lX id %d type %d\n",		       ntohl(ciph->saddr),		       ntohl(ciph->daddr),		       ntohs(icmp_id(cicmph)),		       cicmph->type);		read_lock(&__ip_masq_lock);		ms = __ip_masq_in_get(ciph->protocol, 				      ciph->daddr, 				      icmp_hv_req(cicmph),				      ciph->saddr, 				      icmp_id(cicmph));		read_unlock(&__ip_masq_lock);		if (ms == NULL)			return 0;		if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) {			__ip_masq_put(ms);			return -1;		}		ciph = (struct iphdr *) (icmph + 1);		cicmph = (struct icmphdr *)((char *)ciph + 					    (ciph->ihl<<2));		/* Now we do real damage to this packet...! */		/* First change the dest IP address, and recalc checksum */		iph->daddr = ms->saddr;		ip_send_check(iph);			/* Now change the *source* address in the contained IP */		ciph->saddr = ms->saddr;		ip_send_check(ciph);		/* Change the ID to the original one! */		(cicmph->un).echo.id = ms->sport;		__ip_masq_put(ms);		/* And finally the ICMP checksum */		icmph->checksum = 0;		icmph->checksum = ip_compute_csum((unsigned char *) icmph, len);		IP_MASQ_DEBUG(2, "rv icmp/icmp rwt %lX->%lX id %d type %d\n",		       ntohl(ciph->saddr),		       ntohl(ciph->daddr),		       ntohs(icmp_id(cicmph)),		       cicmph->type);		return 1;	}#endif /* CONFIG_IP_MASQUERADE_ICMP */	/* We are only interested ICMPs generated from TCP or UDP packets */	if ((ciph->protocol != IPPROTO_UDP) && 	    (ciph->protocol != IPPROTO_TCP))		return 0;	/*	 * Find the ports involved - remember this packet was	 * *outgoing* so the ports are reversed (and addresses)	 */	pptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]);	if (ntohs(pptr[0]) < PORT_MASQ_BEGIN || 	    ntohs(pptr[0]) > PORT_MASQ_END) 		return 0;	/* Ensure the checksum is correct */	if (ip_compute_csum((unsigned char *) icmph, len))	{		/* Failed checksum! */		IP_MASQ_ERR( "reverse ICMP: failed checksum from %d.%d.%d.%d!\n",		       NIPQUAD(iph->saddr));		return(-1);	} 	IP_MASQ_DEBUG(2, "Handling reverse ICMP for %08lX:%04X -> %08lX:%04X\n",	       ntohl(ciph->saddr), ntohs(pptr[0]),	       ntohl(ciph->daddr), ntohs(pptr[1]));	/* This is pretty much what __ip_masq_in_get_iph() does, except params are wrong way round */	read_lock(&__ip_masq_lock);	ms = __ip_masq_in_get(ciph->protocol,			      ciph->daddr,			      pptr[1],			      ciph->saddr,			      pptr[0]);	read_unlock(&__ip_masq_lock);	if (ms == NULL)		return 0;	if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) {		__ip_masq_put(ms);		return -1;	}	ciph = (struct iphdr *) (icmph + 1);	pptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]);	/* Now we do real damage to this packet...! */	/* First change the dest IP address, and recalc checksum */	iph->daddr = ms->saddr;	ip_send_check(iph);	/* Now change the *source* address in the contained IP */	ciph->saddr = ms->saddr;	ip_send_check(ciph);	/* the TCP/UDP source port - cannot redo check */	pptr[0] = ms->sport;	__ip_masq_put(ms);	/* And finally the ICMP checksum */	icmph->checksum = 0;	icmph->checksum = ip_compute_csum((unsigned char *) icmph, len); 	IP_MASQ_DEBUG(2, "Rewrote reverse ICMP to %08lX:%04X -> %08lX:%04X\n",	       ntohl(ciph->saddr), ntohs(pptr[0]),	       ntohl(ciph->daddr), ntohs(pptr[1]));	return 1;} /*  *	Check if it's an masqueraded port, look it up,  *	and send it on its way...  *  *	Better not have many hosts using the designated portrange  *	as 'normal' ports, or you'll be spending many time in  *	this function.  */int ip_fw_demasquerade(struct sk_buff **skb_p){	struct sk_buff 	*skb = *skb_p;	struct iphdr	*iph = skb->nh.iph;	union ip_masq_tphdr h;	struct ip_masq	*ms;	unsigned short size;	int doff = 0;	int csum = 0;	int csum_ok = 0;	__u32 maddr;	/*	 *	Big tappo: only PACKET_HOST (nor loopback neither mcasts)	 *	... don't know why 1st test DOES NOT include 2nd (?)	 */	if (skb->pkt_type != PACKET_HOST || skb->dev == &loopback_dev) {		IP_MASQ_DEBUG(2, "ip_fw_demasquerade(): packet type=%d proto=%d daddr=%d.%d.%d.%d ignored\n",			skb->pkt_type,			iph->protocol,			NIPQUAD(iph->daddr));		return 0;	}	h.raw = (char*) iph + iph->ihl * 4;	/*	 *	IP payload size	 */	size = ntohs(iph->tot_len) - (iph->ihl * 4);	doff = proto_doff(iph->protocol, h.raw, size);	switch (doff) {		case 0:			/*			 *	Input path: other IP protos Ok, will			 *	reach local sockets path.			 */			return 0;		case -1:			IP_MASQ_DEBUG(0, "I-pkt invalid packet data size\n");			return -1;	}	maddr = iph->daddr;	switch (iph->protocol) {	case IPPROTO_ICMP:		return(ip_fw_demasq_icmp(skb_p));	case IPPROTO_TCP:	case IPPROTO_UDP:		/* 		 *	Make sure packet is in the masq range 		 *	... or some mod-ule relaxes input range		 *	... or there is still some `special' mport opened		 */		if ((ntohs(h.portp[1]) < PORT_MASQ_BEGIN				|| ntohs(h.portp[1]) > PORT_MASQ_END)#ifdef CONFIG_IP_MASQUERADE_MOD				&& (ip_masq_mod_in_rule(skb, iph) != 1) #endif				&& atomic_read(&mport_count) == 0 )			return 0;		/* Check that the checksum is OK */		if ((iph->protocol == IPPROTO_UDP) && (h.uh->check == 0))			/* No UDP checksum */			break;#ifdef CONFIG_IP_MASQ_DEBUG		if (ip_masq_get_debug_level() > 3) {			skb->ip_summed = CHECKSUM_NONE;		}#endif		switch (skb->ip_summed)		{			case CHECKSUM_NONE:				csum = csum_partial(h.raw + doff, size - doff, 0);				csum_ok++;				skb->csum = csum_partial(h.raw , doff, csum);

⌨️ 快捷键说明

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