Example #1
0
/* 
 *	Delete existing entry
 */
static int ip_masq_user_del(struct ip_masq_user *ums)
{
	struct ip_masq *ms=NULL;

	if (masq_proto_num (ums->protocol) == -1) {
		return EPROTONOSUPPORT;
	}
	start_bh_atomic();
	if (ums->mport && ums->maddr) {
		ms = ip_masq_in_get(ums->protocol, 
				ums->daddr, ums->dport, 
				ums->maddr, ums->mport);
		end_bh_atomic();
	} else if (ums->sport && ums->saddr) {
		ms = ip_masq_out_get(ums->protocol,
				ums->saddr, ums->sport,
				ums->daddr, ums->dport);
		end_bh_atomic();
	} else
		return EINVAL;	
	
	if (ms == NULL) {
		return ESRCH;
	}

	/*
	 *	got (locked) entry, setup almost tiny timeout :) and  
	 *	give away
	 *
	 *	FIXME: should use something better than S_CLOSE
	 */
	ms->timeout = IP_MASQ_S_CLOSE;

	masq_user_k2u(ms, ums);
	ip_masq_put(ms);
	return 0;
}
Example #2
0
static struct ip_masq * ip_masq_user_locked_get (struct ip_masq_user *ums, int *err)
{
	struct ip_masq *ms=NULL;
	if (masq_proto_num (ums->protocol) == -1) {
		*err = EPROTONOSUPPORT;
	}

	start_bh_atomic();
	if (ums->mport && ums->maddr) {
		ms = ip_masq_in_get(ums->protocol, 
				ums->daddr, ums->dport, 
				ums->maddr, ums->mport);
		end_bh_atomic();
	} else if (ums->sport && ums->saddr) {
		ms = ip_masq_out_get(ums->protocol,
				ums->saddr, ums->sport,
				ums->daddr, ums->dport);
		end_bh_atomic();
	} else
		*err = EINVAL;	
	
	if (ms == NULL) *err = ESRCH;
	return ms;
}
Example #3
0
int ip_fw_demasquerade(struct sk_buff **skb_p, struct device *dev)
{
        struct sk_buff 	*skb = *skb_p;
 	struct iphdr	*iph = skb->h.iph;
 	__u16	*portptr;
 	struct ip_masq	*ms;
	unsigned short len;
	unsigned long 	timeout;
#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW 
 	struct ip_autofw *af;
#endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */

	switch (iph->protocol) {
	case IPPROTO_ICMP:
		return(ip_fw_demasq_icmp(skb_p, dev));
	case IPPROTO_TCP:
	case IPPROTO_UDP:
		/* Make sure packet is in the masq range */
		portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
		if ((ntohs(portptr[1]) < PORT_MASQ_BEGIN ||
		     ntohs(portptr[1]) > PORT_MASQ_END)
#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW 
		    && !ip_autofw_check_range(iph->saddr, portptr[1], 
					      iph->protocol, 0)
		    && !ip_autofw_check_direct(portptr[1], iph->protocol)
		    && !ip_autofw_check_port(portptr[1], iph->protocol)
#endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
			)
			return 0;

		/* Check that the checksum is OK */
		len = ntohs(iph->tot_len) - (iph->ihl * 4);
		if ((iph->protocol == IPPROTO_UDP) && (portptr[3] == 0))
			/* No UDP checksum */
			break;

		switch (skb->ip_summed) 
		{
			case CHECKSUM_NONE:
				skb->csum = csum_partial((char *)portptr, len, 0);
			case CHECKSUM_HW:
				if (csum_tcpudp_magic(iph->saddr, iph->daddr, len,
						      iph->protocol, skb->csum))
				{
					printk(KERN_DEBUG "MASQ: failed TCP/UDP checksum from %s!\n", 
					       in_ntoa(iph->saddr));
					return -1;
				}
			default:
				/* CHECKSUM_UNNECESSARY */
		}
		break;
	default:
		return 0;
	}


#ifdef DEBUG_CONFIG_IP_MASQUERADE
 	printk("Incoming %s %lX:%X -> %lX:%X\n",
 		masq_proto_name(iph->protocol),
 		ntohl(iph->saddr), ntohs(portptr[0]),
 		ntohl(iph->daddr), ntohs(portptr[1]));
#endif
 	/*
 	 * reroute to original host:port if found...
         */

        ms = ip_masq_in_get(iph);

#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW 

        if (ms == NULL && (af=ip_autofw_check_range(iph->saddr, portptr[1], iph->protocol, 0))) 
	{
#ifdef DEBUG_CONFIG_IP_MASQUERADE
		printk("ip_autofw_check_range\n");
#endif
        	ms = ip_masq_new_enh(dev, iph->protocol,
        			     af->where, portptr[1],
        			     iph->saddr, portptr[0],
        			     0,
        			     portptr[1]);
        }
        if ( ms == NULL && (af=ip_autofw_check_port(portptr[1], iph->protocol)) ) 
	{
#ifdef DEBUG_CONFIG_IP_MASQUERADE
		printk("ip_autofw_check_port\n");
#endif
        	ms = ip_masq_new_enh(dev, iph->protocol,
        			     af->where, htons(af->hidden),
        			     iph->saddr, portptr[0],
        			     IP_MASQ_F_AFW_PORT,
        			     htons(af->visible));
        }
#endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */

        if (ms != NULL)
        {
#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW 
        	ip_autofw_update_in(iph->saddr, portptr[1], iph->protocol);
#endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
        	
		/* Stop the timer ticking.... */
		ip_masq_set_expire(ms,0);

                /*
                 *	got reply, so clear flag
                 */
                ms->flags &= ~IP_MASQ_F_NO_REPLY;
                
                /*
                 *	Set dport if not defined yet.
                 */

                if ( ms->flags & IP_MASQ_F_NO_DPORT && ms->protocol == IPPROTO_TCP ) {
                        ms->flags &= ~IP_MASQ_F_NO_DPORT;
                        ms->dport = portptr[0];
#ifdef DEBUG_CONFIG_IP_MASQUERADE
                        printk("ip_fw_demasquerade(): filled dport=%d\n",
                               ntohs(ms->dport));
#endif
                }
                if (ms->flags & IP_MASQ_F_NO_DADDR && ms->protocol == IPPROTO_TCP)  {
                        ms->flags &= ~IP_MASQ_F_NO_DADDR;
                        ms->daddr = iph->saddr;
#ifdef DEBUG_CONFIG_IP_MASQUERADE
                        printk("ip_fw_demasquerade(): filled daddr=%X\n",
                               ntohs(ms->daddr));
#endif
                }
                iph->daddr = ms->saddr;
                portptr[1] = ms->sport;

                /*
                 *	Attempt ip_masq_app call.
                 *	will fix ip_masq and iph ack_seq stuff
                 */

                if (ip_masq_app_pkt_in(ms, skb_p, dev) != 0)
                {
                        /*
                         *	skb has changed, update pointers.
                         */

                        skb = *skb_p;
                        iph = skb->h.iph;
                        portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
                        len = ntohs(iph->tot_len) - (iph->ihl * 4);
                }

                /*
                 * Yug! adjust UDP/TCP and IP checksums, also update
		 * timeouts.
		 * If a TCP RST is seen collapse the tunnel (by using short timeout)!
                 */
                if (masq_proto_num(iph->protocol)==0)
		{
                        recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,len);
			timeout = ip_masq_expire->udp_timeout;
		}
                else
                {
			struct tcphdr *th;
                        skb->csum = csum_partial((void *)(((struct tcphdr *)portptr) + 1),
                                                 len - sizeof(struct tcphdr), 0);
                        tcp_send_check((struct tcphdr *)portptr,iph->saddr,iph->daddr,len,skb);

			/* Check if TCP FIN or RST */
			th = (struct tcphdr *)portptr;
			if (th->fin)
			{
				ms->flags |= IP_MASQ_F_SAW_FIN_IN;
			}
			if (th->rst)
			{
				ms->flags |= IP_MASQ_F_SAW_RST;
			}
			
			/* Now set the timeouts */
			if (ms->flags & IP_MASQ_F_SAW_RST)
			{
				timeout = 1;
			}
			else if ((ms->flags & IP_MASQ_F_SAW_FIN) == IP_MASQ_F_SAW_FIN)
			{
				timeout = ip_masq_expire->tcp_fin_timeout;
			}
			else timeout = ip_masq_expire->tcp_timeout;
                }
		ip_masq_set_expire(ms, timeout);
                ip_send_check(iph);
#ifdef DEBUG_CONFIG_IP_MASQUERADE
                printk("I-routed to %lX:%X\n",ntohl(iph->daddr),ntohs(portptr[1]));
#endif
                return 1;
 	}

 	/* sorry, all this trouble for a no-hit :) */
 	return 0;
}

/*
 *	/proc/net entries
 */


#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW

static int ip_autofw_procinfo(char *buffer, char **start, off_t offset,
			      int length, int unused)
{
	off_t pos=0, begin=0;
	struct ip_autofw * af;
	int len=0;
	
	len=sprintf(buffer,"Type Prot Low  High Vis  Hid  Where    Last     CPto CPrt Timer Flags\n"); 
        
        for(af = ip_autofw_hosts; af ; af = af->next)
	{
		len+=sprintf(buffer+len,"%4X %4X %04X-%04X/%04X %04X %08lX %08lX %04X %04X %6lu %4X\n",
					af->type,
					af->protocol,
					af->low,
					af->high,
					af->visible,
					af->hidden,
					ntohl(af->where),
					ntohl(af->lastcontact),
					af->ctlproto,
					af->ctlport,
					(af->timer.expires<jiffies ? 0 : af->timer.expires-jiffies), 
					af->flags);

		pos=begin+len;
		if(pos<offset) 
		{
 			len=0;
			begin=pos;
		}
		if(pos>offset+length)
			break;
        }
	*start=buffer+(offset-begin);
	len-=(offset-begin);
	if(len>length)
		len=length;
	return len;
}