home *** CD-ROM | disk | FTP | other *** search
- From nik@netaxs.comTue Jul 18 09:26:08 1995
- Date: Mon, 17 Jul 1995 17:25:26 -0400 (EDT)
- From: Nik Weidenbacher <nik@netaxs.com>
- To: masq@eves.com
- Subject: The 1.2 patch.
-
- I have heard many requests for this, so here it is. I also posted it to
- c.o.l.networking.
-
- nik
-
- diff -rc linux/arch/i386/config.in linux+masq/arch/i386/config.in
- *** linux/arch/i386/config.in Tue Mar 7 15:25:26 1995
- --- linux+masq/arch/i386/config.in Thu Mar 9 10:00:25 1995
- ***************
- *** 46,51 ****
- --- 46,54 ----
- bool 'IP multicasting' CONFIG_IP_MULTICAST n
- bool 'IP firewalling' CONFIG_IP_FIREWALL n
- bool 'IP accounting' CONFIG_IP_ACCT n
- + if [ "$CONFIG_IP_FORWARD" = "y" -a "$CONFIG_IP_FIREWALL" = "y" ]; then
- + bool 'IP masquerading (ALPHA)' CONFIG_IP_MASQUERADE n
- + fi
- comment '(it is safe to leave these untouched)'
- bool 'PC/TCP compatibility mode' CONFIG_INET_PCTCP n
- bool 'Reverse ARP' CONFIG_INET_RARP n
- diff -rc linux/include/linux/ip_fw.h linux+masq/include/linux/ip_fw.h
- *** linux/include/linux/ip_fw.h Thu Mar 9 19:33:55 1995
- --- linux+masq/include/linux/ip_fw.h Sat Mar 18 10:46:39 1995
- ***************
- *** 15,20 ****
- --- 15,23 ----
- * Alan.
- *
- * All the real work was done by .....
- + *
- + * Fixes:
- + * Pauline Middelink : Added masquerading.
- */
-
- /*
- ***************
- *** 83,89 ****
- #define IP_FW_F_BIDIR 0x040 /* For bidirectional firewalls */
- #define IP_FW_F_TCPSYN 0x080 /* For tcp packets-check SYN only */
- #define IP_FW_F_ICMPRPL 0x100 /* Send back icmp unreachable packet */
- ! #define IP_FW_F_MASK 0x1FF /* All possible flag bits mask */
-
- /*
- * New IP firewall options for [gs]etsockopt at the RAW IP level.
- --- 86,93 ----
- #define IP_FW_F_BIDIR 0x040 /* For bidirectional firewalls */
- #define IP_FW_F_TCPSYN 0x080 /* For tcp packets-check SYN only */
- #define IP_FW_F_ICMPRPL 0x100 /* Send back icmp unreachable packet */
- ! #define IP_FW_F_MASQ 0x200 /* Masquerading */
- ! #define IP_FW_F_MASK 0x3FF /* All possible flag bits mask */
-
- /*
- * New IP firewall options for [gs]etsockopt at the RAW IP level.
- ***************
- *** 134,147 ****
- extern struct ip_fw *ip_fw_fwd_chain;
- extern int ip_fw_blk_policy;
- extern int ip_fw_fwd_policy;
- extern int ip_fw_ctl(int, void *, int);
- #endif
- #ifdef CONFIG_IP_ACCT
- extern struct ip_fw *ip_acct_chain;
- - extern void ip_acct_cnt(struct iphdr *, struct device *, struct ip_fw *);
- extern int ip_acct_ctl(int, void *, int);
- #endif
- ! extern int ip_fw_chk(struct iphdr *, struct device *rif,struct ip_fw *, int, int);
- #endif /* KERNEL */
-
- #endif /* _IP_FW_H */
- --- 138,166 ----
- extern struct ip_fw *ip_fw_fwd_chain;
- extern int ip_fw_blk_policy;
- extern int ip_fw_fwd_policy;
- + extern int ip_fw_chk(struct iphdr *, struct device *rif,struct ip_fw *, int, int);
- extern int ip_fw_ctl(int, void *, int);
- #endif
- #ifdef CONFIG_IP_ACCT
- extern struct ip_fw *ip_acct_chain;
- extern int ip_acct_ctl(int, void *, int);
- #endif
- ! #ifdef CONFIG_IP_MASQUERADE
- ! struct ip_masq {
- ! struct ip_masq *next; /* next member in list */
- ! struct timer_list timer; /* Expiration timer */
- ! __u16 protocol; /* Which protocol are we talking? */
- ! __u32 src, dst; /* Source and destination IP addresses */
- ! __u16 sport,dport; /* Source and destoination ports */
- ! __u16 mport; /* Masquaraded port */
- ! __u32 init_seq; /* Add delta from this seq. on */
- ! short delta; /* Delta in sequence numbers */
- ! char sawfin; /* Did we saw an FIN packet? */
- ! };
- ! extern struct ip_masq *ip_msq_hosts;
- ! extern void ip_fw_masquerade(struct sk_buff *, struct device *);
- ! extern int ip_fw_demasquerade(struct sk_buff *);
- ! #endif
- #endif /* KERNEL */
-
- #endif /* _IP_FW_H */
- diff -rc linux/include/linux/proc_fs.h linux+masq/include/linux/proc_fs.h
- *** linux/include/linux/proc_fs.h Sun Feb 12 20:11:02 1995
- --- linux+masq/include/linux/proc_fs.h Thu Mar 9 10:00:26 1995
- ***************
- *** 74,79 ****
- --- 74,82 ----
- #ifdef CONFIG_IP_ACCT
- PROC_NET_IPACCT,
- #endif
- + #ifdef CONFIG_IP_MASQUERADE
- + PROC_NET_IPMSQHST,
- + #endif
- #if defined(CONFIG_WAVELAN)
- PROC_NET_WAVELAN,
- #endif /* defined(CONFIG_WAVELAN) */
- diff -rc linux/net/inet/ip.c linux+masq/net/inet/ip.c
- *** linux/net/inet/ip.c Thu Mar 9 19:33:55 1995
- --- linux+masq/net/inet/ip.c Sat Mar 18 10:44:03 1995
- ***************
- *** 62,67 ****
- --- 62,69 ----
- * Alan Cox : RAW sockets demultiplex in the BSD style.
- * Gunther Mayer : Fix the SNMP reporting typo
- * Alan Cox : Always in group 224.0.0.1
- + * Pauline Middelink : Fast ip_checksum update when forwarding
- + * Masquerading support.
- * Alan Cox : Multicast loopback error for 224.0.0.1
- * Alan Cox : IP_MULTICAST_LOOP option.
- * Alan Cox : Use notifiers.
- ***************
- *** 1263,1280 ****
- struct rtable *rt; /* Route we use */
- unsigned char *ptr; /* Data pointer */
- unsigned long raddr; /* Router IP address */
- !
- /*
- * See if we are allowed to forward this.
- */
-
- ! #ifdef CONFIG_IP_FIREWALL
- ! int err;
- !
- ! if((err=ip_fw_chk(skb->h.iph, dev, ip_fw_fwd_chain, ip_fw_fwd_policy, 0))!=1)
- ! {
- ! if(err==-1)
- ! icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
- return;
- }
- #endif
- --- 1265,1282 ----
- struct rtable *rt; /* Route we use */
- unsigned char *ptr; /* Data pointer */
- unsigned long raddr; /* Router IP address */
- ! #ifdef CONFIG_IP_FIREWALL
- ! int fw_res = 0; /* Forwarding Result */
- !
- /*
- * See if we are allowed to forward this.
- + * Note: demasqueraded fragments are always 'back'warded.
- */
-
- ! if( !(is_frag&4) && (fw_res=ip_fw_chk(skb->h.iph, dev, ip_fw_fwd_chain, ip_fw_fwd_policy, 0))<1)
- ! {
- ! if(fw_res==-1)
- ! icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
- return;
- }
- #endif
- ***************
- *** 1291,1302 ****
-
- iph = skb->h.iph;
- iph->ttl--;
- - if (iph->ttl <= 0)
- - {
- - /* Tell the sender its packet died... */
- - icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev);
- - return;
- - }
-
- /*
- * Re-compute the IP header checksum.
- --- 1293,1298 ----
- ***************
- *** 1304,1310 ****
- --- 1300,1324 ----
- * and could thus adjust the checksum as Phil Karn does in KA9Q
- */
-
- + #if 0
- ip_send_check(iph);
- + #else
- + /*
- + * Like this?
- + * Notice we must do the additions in HOST format!
- + */
- + iph->check = ntohs(iph->check) + 0x0100;
- + if ((iph->check & 0xFF00) == 0)
- + iph->check++; /* carry overflow */
- + iph->check = htons(iph->check);
- + #endif
- +
- + if (iph->ttl <= 0)
- + {
- + /* Tell the sender its packet died... */
- + icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev);
- + return;
- + }
-
- /*
- * OK, the packet is still valid. Fetch its destination address,
- ***************
- *** 1380,1385 ****
- --- 1394,1407 ----
-
- if (dev2->flags & IFF_UP)
- {
- + #ifdef CONFIG_IP_MASQUERADE
- + /*
- + * If this fragment needs masquerading, make it so...
- + * (Dont masquerade de-masqueraded fragments)
- + */
- + if (!(is_frag&4) && fw_res==2)
- + ip_fw_masquerade(skb, dev2);
- + #endif
-
- /*
- * Current design decrees we copy the packet. For identical header
- ***************
- *** 1430,1436 ****
- * Count mapping we shortcut
- */
-
- ! ip_acct_cnt(iph,dev,ip_acct_chain);
- #endif
-
- /*
- --- 1452,1458 ----
- * Count mapping we shortcut
- */
-
- ! ip_fw_chk(iph,dev,ip_acct_chain,0,1);
- #endif
-
- /*
- ***************
- *** 1501,1507 ****
-
- #ifdef CONFIG_IP_FIREWALL
-
- ! if ((err=ip_fw_chk(iph,dev,ip_fw_blk_chain,ip_fw_blk_policy, 0))!=1)
- {
- if(err==-1)
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
- --- 1523,1529 ----
-
- #ifdef CONFIG_IP_FIREWALL
-
- ! if ((err=ip_fw_chk(iph,dev,ip_fw_blk_chain,ip_fw_blk_policy,0))<1)
- {
- if(err==-1)
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
- ***************
- *** 1613,1624 ****
- while(1);
- }
- #endif
- /*
- * Account for the packet
- */
- !
- #ifdef CONFIG_IP_ACCT
- ! ip_acct_cnt(iph,dev, ip_acct_chain);
- #endif
-
- /*
- --- 1635,1658 ----
- while(1);
- }
- #endif
- +
- + #ifdef CONFIG_IP_MASQUERADE
- + /*
- + * Do we need to de-masquerade this fragment?
- + */
- + if (ip_fw_demasquerade(skb)) {
- + ip_forward(skb, dev, is_frag|4);
- + kfree_skb(skb, FREE_WRITE);
- + return(0);
- + }
- + #endif
- +
- /*
- * Account for the packet
- */
- !
- #ifdef CONFIG_IP_ACCT
- ! ip_fw_chk(iph,dev,ip_acct_chain,0,1);
- #endif
-
- /*
- ***************
- *** 1634,1641 ****
- skb->dev = dev;
- iph=skb->h.iph;
- }
- -
- -
-
- /*
- * Point into the IP datagram, just past the header.
- --- 1668,1673 ----
- ***************
- *** 1643,1655 ****
-
- skb->ip_hdr = iph;
- skb->h.raw += iph->ihl*4;
- !
- /*
- * Deliver to raw sockets. This is fun as to avoid copies we want to make no surplus copies.
- */
- !
- hash = iph->protocol & (SOCK_ARRAY_SIZE-1);
- !
- /* If there maybe a raw socket we must check - if not we don't care less */
- if((raw_sk=raw_prot.sock_array[hash])!=NULL)
- {
- --- 1675,1687 ----
-
- skb->ip_hdr = iph;
- skb->h.raw += iph->ihl*4;
- !
- /*
- * Deliver to raw sockets. This is fun as to avoid copies we want to make no surplus copies.
- */
- !
- hash = iph->protocol & (SOCK_ARRAY_SIZE-1);
- !
- /* If there maybe a raw socket we must check - if not we don't care less */
- if((raw_sk=raw_prot.sock_array[hash])!=NULL)
- {
- ***************
- *** 1921,1927 ****
-
- ip_statistics.IpOutRequests++;
- #ifdef CONFIG_IP_ACCT
- ! ip_acct_cnt(iph,dev, ip_acct_chain);
- #endif
-
- #ifdef CONFIG_IP_MULTICAST
- --- 1953,1959 ----
-
- ip_statistics.IpOutRequests++;
- #ifdef CONFIG_IP_ACCT
- ! ip_fw_chk(iph,dev,ip_acct_chain,0,1);
- #endif
-
- #ifdef CONFIG_IP_MULTICAST
- diff -rc linux/net/inet/ip_fw.c linux+masq/net/inet/ip_fw.c
- *** linux/net/inet/ip_fw.c Fri Mar 10 09:07:14 1995
- --- linux+masq/net/inet/ip_fw.c Sat Mar 18 11:15:41 1995
- ***************
- *** 21,26 ****
- --- 21,41 ----
- * Jos Vos 5/Mar/1995.
- *
- * All the real work was done by .....
- + *
- + * Fixes:
- + * Pauline Middelink : Added masquerading.
- + */
- +
- + /*
- + * Masquerading functionality
- + *
- + * Copyright (c) 1994 Pauline Middelink
- + *
- + * The pieces which added masquerading functionality are totaly
- + * my responsibility and have nothing to with the original authors
- + * copyright or doing.
- + *
- + * Parts distributed under GPL.
- */
-
- /*
- ***************
- *** 58,63 ****
- --- 73,79 ----
- #include "protocol.h"
- #include "route.h"
- #include "tcp.h"
- + #include "udp.h"
- #include <linux/skbuff.h>
- #include "sock.h"
- #include "icmp.h"
- ***************
- *** 104,109 ****
- --- 120,148 ----
- #define IP_INFO_FWD 1
- #define IP_INFO_ACCT 2
-
- + /*
- + * Implement IP packet masquerading
- + */
- +
- + #ifdef CONFIG_IP_MASQUERADE
- +
- + #undef DEBUG_MASQ
- +
- + #define MASQUERADE_EXPIRE_TCP 15*60*HZ
- + #define MASQUERADE_EXPIRE_TCP_FIN 2*60*HZ
- + #define MASQUERADE_EXPIRE_UDP 5*60*HZ
- +
- + /*
- + * Linux ports don't get allocated above 32K. I used a extra 4K port-space
- + */
- + #define PORT_MASQ_BEGIN 32768
- + #define PORT_MASQ_END (PORT_MASQ_BEGIN+4096)
- +
- + static unsigned short masq_port = PORT_MASQ_BEGIN;
- + static char *strProt[] = {"UDP","TCP"};
- + struct ip_masq *ip_msq_hosts;
- +
- + #endif
-
- /*
- * Returns 1 if the port is matched by the vector, 0 otherwise
- ***************
- *** 136,143 ****
-
-
- /*
- ! * Returns 0 if packet should be dropped, 1 if it should be accepted,
- ! * and -1 if an ICMP host unreachable packet should be sent.
- * Also does accounting so you can feed it the accounting chain.
- * If opt is set to 1, it means that we do this for accounting
- * purposes (searches all entries and handles fragments different).
- --- 175,184 ----
-
-
- /*
- ! * Returns 0 if packet should be dropped, 1 if it should be
- ! * accepted and -1 if an ICMP host unreachable packet should
- ! * be sent. Returns 2 to indicate it as matched by a masquerading rule.
- ! *
- * Also does accounting so you can feed it the accounting chain.
- * If opt is set to 1, it means that we do this for accounting
- * purposes (searches all entries and handles fragments different).
- ***************
- *** 149,173 ****
- int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int policy, int opt)
- {
- struct ip_fw *f;
- ! struct tcphdr *tcp=(struct tcphdr *)((unsigned long *)ip+ip->ihl);
- ! struct udphdr *udp=(struct udphdr *)((unsigned long *)ip+ip->ihl);
- __u32 src, dst;
- __u16 src_port=0, dst_port=0;
- unsigned short f_prt=0, prt;
- char notcpsyn=1, frag1, match;
- unsigned short f_flag;
-
- - /*
- - * If the chain is empty follow policy. The BSD one
- - * accepts anything giving you a time window while
- - * flushing and rebuilding the tables.
- - */
- -
- - src = ip->saddr;
- - dst = ip->daddr;
- -
- /*
- ! * This way we handle fragmented packets.
- * we ignore all fragments but the first one
- * so the whole packet can't be reassembled.
- * This way we relay on the full info which
- --- 190,205 ----
- int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int policy, int opt)
- {
- struct ip_fw *f;
- ! struct tcphdr *tcp=(struct tcphdr *)((unsigned char *)ip+ip->ihl*4);
- ! struct udphdr *udp=(struct udphdr *)((unsigned char *)ip+ip->ihl*4);
- __u32 src, dst;
- __u16 src_port=0, dst_port=0;
- unsigned short f_prt=0, prt;
- char notcpsyn=1, frag1, match;
- unsigned short f_flag;
-
- /*
- ! * This way we handle fragmented packets:
- * we ignore all fragments but the first one
- * so the whole packet can't be reassembled.
- * This way we relay on the full info which
- ***************
- *** 195,201 ****
- * per device. We have a device per address with dummy
- * devices instead.
- */
- !
- dprintf1("Packet ");
- switch(ip->protocol)
- {
- --- 227,233 ----
- * per device. We have a device per address with dummy
- * devices instead.
- */
- !
- dprintf1("Packet ");
- switch(ip->protocol)
- {
- ***************
- *** 388,399 ****
- else
- f_flag=policy;
- if(f_flag&IP_FW_F_ACCEPT)
- ! return 1;
- if(f_flag&IP_FW_F_ICMPRPL)
- return -1;
- return 0;
- }
-
-
- static void zero_fw_chain(struct ip_fw *chainptr)
- {
- --- 420,811 ----
- else
- f_flag=policy;
- if(f_flag&IP_FW_F_ACCEPT)
- ! return (f_flag&IP_FW_F_MASQ) ? 2 : 1;
- if(f_flag&IP_FW_F_ICMPRPL)
- return -1;
- return 0;
- }
-
- + #ifdef CONFIG_IP_MASQUERADE
- +
- + static
- + void masq_expire(unsigned long data)
- + {
- + struct ip_masq *ms = (struct ip_masq *)data;
- + struct ip_masq *old,*cur;
- + unsigned long flags;
- +
- + #ifdef DEBUG_MASQ
- + printk("Masqueraded %s %lX:%X expired\n",
- + strProt[ms->protocol==IPPROTO_TCP],
- + ntohl(ms->src),ntohs(ms->sport));
- + #endif
- +
- + save_flags(flags);
- + cli();
- +
- + /* delete from list of hosts */
- + old = NULL;
- + cur = ip_msq_hosts;
- + while (cur!=NULL) {
- + if (cur==ms) {
- + if (old==NULL) ip_msq_hosts = ms->next;
- + else old->next = ms->next;
- + kfree_s(ms,sizeof(*ms));
- + break;
- + }
- + old = cur;
- + cur=cur->next;
- + }
- + restore_flags(flags);
- + }
- +
- + /*
- + * Create a new masquerade list entry, also allocate an
- + * unused mport, keeping the portnumber between the
- + * given boundaries MASQ_BEGIN and MASQ_END.
- + *
- + * FIXME: possible deadlock if all free ports are exhausted!
- + */
- + static
- + struct ip_masq *alloc_masq_entry(void)
- + {
- + struct ip_masq *ms, *mst;
- + unsigned long flags;
- +
- + ms = (struct ip_masq *) kmalloc(sizeof(struct ip_masq), GFP_ATOMIC);
- + if (ms==NULL)
- + return NULL;
- +
- + memset(ms,0,sizeof(*ms));
- + init_timer(&ms->timer);
- + ms->timer.data = (unsigned long)ms;
- + ms->timer.function = masq_expire;
- +
- + save_flags(flags);
- + cli();
- + do {
- + /* Try the next available port number */
- + ms->mport = htons(masq_port++);
- + if (masq_port==PORT_MASQ_END)
- + masq_port = PORT_MASQ_BEGIN;
- +
- + /* Now hunt through the used ports to see if
- + * this port is in use... */
- + mst = ip_msq_hosts;
- + while (mst && mst->mport!=ms->mport)
- + mst = mst->next;
- + }
- + while (mst!=NULL);
- +
- + /* add new entry in front of list to minimize lookup-time */
- + ms->next = ip_msq_hosts;
- + ip_msq_hosts = ms;
- + restore_flags(flags);
- +
- + return ms;
- + }
- +
- + #ifdef notdef
- +
- + /*
- + * When passing an FTP 'PORT' command, try to replace the IP
- + * address with an newly assigned (masquereded) port on this
- + * host, so the ftp-data connect FROM the site will succeed...
- + *
- + * Also, when the size of the packet changes, create an delta
- + * offset, which will be added to every th->seq (and subtracted for
- + * (th->acqseq) whose seq > init_seq.
- + *
- + * Not for the faint of heart!
- + */
- + static
- + struct sk_buff *revamp(struct sk_buff *skb, struct device *dev, struct ip_masq *ftp)
- + {
- + struct iphdr *iph = skb->h.iph;
- + struct tcphdr *th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
- + struct sk_buff *skb2;
- + char *p, *data = (char *)&th[1];
- + unsigned char p1,p2,p3,p4,p5,p6;
- + unsigned long from;
- + unsigned short port;
- + struct ip_masq *ms;
- + char buf[20]; /* xxx.xxx.xxx.xxx\r\n */
- +
- + /*
- + * Adjust seq and ack_seq with delta-offset for
- + * the packets AFTER this one...
- + */
- + if (ftp->delta && after(ftp->init_seq,th->seq)) {
- + th->seq += ftp->delta;
- + th->ack_seq += ftp->delta;
- + }
- +
- + while (skb->len - ((unsigned char *)data - skb->h.raw) > 18)
- + {
- + if (memcmp(data,"PORT ",5)!=0 && memcmp(data,"port ",5)!=0) {
- + data += 5;
- + continue;
- + }
- + p = data+5;
- + p1 = simple_strtoul(data+5,&data,10);
- + if (*data!=',')
- + continue;
- + p2 = simple_strtoul(data+1,&data,10);
- + if (*data!=',')
- + continue;
- + p3 = simple_strtoul(data+1,&data,10);
- + if (*data!=',')
- + continue;
- + p4 = simple_strtoul(data+1,&data,10);
- + if (*data!=',')
- + continue;
- + p5 = simple_strtoul(data+1,&data,10);
- + if (*data!=',')
- + continue;
- + p6 = simple_strtoul(data+1,&data,10);
- + if (*data!='\r' && *data!='\n')
- + continue;
- +
- + from = (p1<<24) | (p2<<16) | (p3<<8) | p4;
- + port = (p5<<8) | p6;
- + printk("PORT %lX:%X detected\n",from,port);
- +
- + /*
- + * Now create an masquerade entry for it
- + */
- + ms = alloc_masq_entry();
- + if (ms==NULL)
- + return skb;
- + ms->protocol = IPPROTO_TCP;
- + ms->src = htonl(from); /* derived from PORT cmd */
- + ms->sport = htons(port); /* derived from PORT cmd */
- + ms->dst = iph->daddr;
- + ms->dport = htons(20); /* ftp-data */
- + ms->timer.expires = MASQUERADE_EXPIRE_TCP_FIN;
- + add_timer(&ms->timer);
- +
- + /*
- + * Replace the old PORT with the new one
- + */
- + from = ntohl(dev->pa_addr);
- + port = ntohs(ms->mport);
- + sprintf(buf,"%ld,%ld,%ld,%ld,%d,%d",
- + from>>24&255,from>>16&255,from>>8&255,from&255,
- + port>>8&255,port&255);
- +
- + /*
- + * Calculate required delta-offset to keep TCP happy
- + */
- + ftp->delta += strlen(buf) - (data-p);
- + if (ftp->delta==0) {
- + /*
- + * simple case, just replace the old PORT cmd
- + */
- + ftp->init_seq = 0;
- + memcpy(p,buf,strlen(buf));
- + return skb;
- + }
- +
- + /*
- + * Sizes differ, make a copy
- + */
- + printk("MASQUERADE: resizing needed for %d bytes (%ld)\n",ftp->delta, skb->len);
- + if (!ftp->init_seq)
- + ftp->init_seq = th->seq;
- +
- + skb2 = alloc_skb(skb->mem_len-sizeof(struct sk_buff)+ftp->delta, GFP_ATOMIC);
- + if (skb2 == NULL) {
- + printk("MASQUERADE: No memory available\n");
- + return skb;
- + }
- + skb2->free = skb->free;
- + skb2->len = skb->len + ftp->delta;
- + skb2->h.raw = &skb2->data[skb->h.raw - skb->data];
- +
- + /*
- + * Copy the packet data into the new buffer.
- + * Thereby replacing the PORT cmd.
- + */
- + memcpy(skb2->data, skb->data, (p - (char *)skb->data));
- + memcpy(&skb2->data[(p - (char *)skb->data)], buf, strlen(buf));
- + memcpy(&skb2->data[(p - (char *)skb->data) + strlen(buf)], data,
- + skb->mem_len - sizeof(struct sk_buff) - ((char *)skb->h.raw - data));
- +
- + /*
- + * Problem, how to replace the new skb with old one,
- + * preferably inplace, so all the pointers in the
- + * calling tree keep ok :(
- + */
- + kfree_skb(skb, FREE_WRITE);
- + return skb2;
- + }
- + return skb;
- + }
- + #endif
- +
- + void ip_fw_masquerade(struct sk_buff *skb, struct device *dev)
- + {
- + struct iphdr *iph = skb->h.iph;
- + unsigned short *portptr;
- + struct ip_masq *ms;
- + int size;
- +
- + /*
- + * We can only masquerade protocols with ports...
- + */
- + if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
- + return;
- +
- + /*
- + * Now hunt the list to see if we have an old entry
- + */
- + portptr = (unsigned short *)&(((char *)iph)[iph->ihl*4]);
- + ms = ip_msq_hosts;
- +
- + #ifdef DEBUG_MASQ
- + printk("Outgoing %s %lX:%X -> %lX:%X\n",
- + strProt[iph->protocol==IPPROTO_TCP],
- + ntohl(iph->saddr), ntohs(portptr[0]),
- + ntohl(iph->daddr), ntohs(portptr[1]));
- + #endif
- + while (ms!=NULL) {
- + if (iph->protocol == ms->protocol &&
- + iph->saddr == ms->src && iph->daddr == ms->dst &&
- + portptr[0] == ms->sport && portptr[1] == ms->dport) {
- + del_timer(&ms->timer);
- + break;
- + }
- + ms = ms->next;
- + }
- +
- + /*
- + * Nope, not found, create a new entry for it
- + */
- + if (ms==NULL) {
- + ms = alloc_masq_entry();
- + if (ms==NULL) {
- + printk("MASQUERADE: no memory left !\n");
- + return;
- + }
- + ms->protocol = iph->protocol;
- + ms->src = iph->saddr;
- + ms->dst = iph->daddr;
- + ms->sport = portptr[0];
- + ms->dport = portptr[1];
- + }
- +
- + /*
- + * Change the fragments origin
- + */
- + size = skb->len - ((unsigned char *)portptr - skb->h.raw);
- + iph->saddr = dev->pa_addr; /* my own address */
- + portptr[0] = ms->mport;
- +
- + /*
- + * Adjust packet accordingly to protocol
- + */
- + if (iph->protocol==IPPROTO_UDP) {
- + ms->timer.expires = MASQUERADE_EXPIRE_UDP;
- + udp_send_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size,skb->sk);
- + }
- + else {
- + struct tcphdr *th;
- + #ifdef notdef
- + if (portptr[1]==htons(21)) {
- + skb = revamp(skb, dev, ms);
- + iph = skb->h.iph;
- + portptr = (unsigned short *)&(((char *)iph)[iph->ihl*4]);
- + }
- + #endif
- + th = (struct tcphdr *)portptr;
- +
- + /*
- + * Timeout depends if FIN packet was seen
- + */
- + if (ms->sawfin || th->fin) {
- + ms->timer.expires = MASQUERADE_EXPIRE_TCP_FIN;
- + ms->sawfin = 1;
- + }
- + else ms->timer.expires = MASQUERADE_EXPIRE_TCP;
- +
- + tcp_send_check(th,iph->saddr,iph->daddr,size,skb->sk);
- + }
- + add_timer(&ms->timer);
- + ip_send_check(iph);
- +
- + #ifdef DEBUG_MASQ
- + printk("O-routed from %lX:%X over %s\n",ntohl(dev->pa_addr),ntohs(ms->mport),dev->name);
- + #endif
- + }
- +
- + /*
- + * Check if it's an masqueraded port, look it up,
- + * and send it on it's way...
- + *
- + * Better not have many hosts using the designated portrange
- + * as 'normal' ports, or you'll be spending lots of time in
- + * this function.
- + */
- + int ip_fw_demasquerade(struct sk_buff *skb)
- + {
- + struct iphdr *iph = skb->h.iph;
- + unsigned short *portptr;
- + struct ip_masq *ms;
- + int size;
- +
- + if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
- + return 0;
- +
- + portptr = (unsigned short *)&(((char *)iph)[iph->ihl*4]);
- + if (ntohs(portptr[1]) < PORT_MASQ_BEGIN ||
- + ntohs(portptr[1]) > PORT_MASQ_END)
- + return 0;
- +
- + #ifdef DEBUG_MASQ
- + printk("Incoming %s %lX:%X -> %lX:%X\n",
- + strProt[iph->protocol==IPPROTO_TCP],
- + ntohl(iph->saddr), ntohs(portptr[0]),
- + ntohl(iph->daddr), ntohs(portptr[1]));
- + #endif
- + /*
- + * reroute to original host:port if found...
- + *
- + * NB. Cannot check destination address, just for the incoming port.
- + * reason: archie.doc.ac.uk has 6 interfaces, you send to
- + * phoenix and get a reply from any other interface(==dst)!
- + */
- + ms = ip_msq_hosts;
- + while (ms!=NULL) {
- + if (iph->protocol==ms->protocol &&
- + /* iph->saddr==ms->dst && */
- + portptr[0]==ms->dport &&
- + portptr[1]==ms->mport)
- + {
- + size = skb->len - ((unsigned char *)portptr - skb->h.raw);
- + iph->daddr = ms->src;
- + portptr[1] = ms->sport;
- +
- + /*
- + * Yug! adjust UDP/TCP and IP checksums
- + */
- + if (iph->protocol==IPPROTO_UDP)
- + udp_send_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size,skb->sk);
- + else
- + tcp_send_check((struct tcphdr *)portptr,iph->saddr,iph->daddr,size,skb->sk);
- + ip_send_check(iph);
- + #ifdef DEBUG_MASQ
- + printk("I-routed to %lX:%X\n",ntohl(iph->daddr),ntohs(portptr[1]));
- + #endif
- + return 1;
- + }
- + ms = ms->next;
- + }
- +
- + /* sorry, all this trouble for a no-hit :) */
- + return 0;
- + }
- + #endif
-
- static void zero_fw_chain(struct ip_fw *chainptr)
- {
- ***************
- *** 442,448 ****
- if ( ftmp == NULL )
- {
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printf("ip_fw_ctl: malloc said no\n");
- #endif
- return( ENOMEM );
- }
- --- 854,860 ----
- if ( ftmp == NULL )
- {
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printk("ip_fw_ctl: malloc said no\n");
- #endif
- return( ENOMEM );
- }
- ***************
- *** 511,518 ****
- addb4--;
- }
-
- ! if (((o_da & o_dm) == (n_da & n_dm))
- ! &&((o_sa & o_sm) == (n_sa & n_sm)))
- {
- if (newkind!=IP_FW_F_ALL &&
- oldkind==IP_FW_F_ALL)
- --- 923,930 ----
- addb4--;
- }
-
- ! if (((o_da & o_dm) == (n_da & n_dm)) &&
- ! ((o_sa & o_sm) == (n_sa & n_sm)))
- {
- if (newkind!=IP_FW_F_ALL &&
- oldkind==IP_FW_F_ALL)
- ***************
- *** 603,609 ****
- if (chtmp_prev)
- chtmp_prev->fw_next=ftmp;
- else
- ! *chainptr=ftmp;
- restore_flags(flags);
- return(0);
- }
- --- 1015,1021 ----
- if (chtmp_prev)
- chtmp_prev->fw_next=ftmp;
- else
- ! *chainptr=ftmp;
- restore_flags(flags);
- return(0);
- }
- ***************
- *** 635,647 ****
- while( ftmp != NULL )
- {
- matches=1;
- ! if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr
- || ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
- || ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
- || ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
- || ftmp->fw_via.s_addr!=frwl->fw_via.s_addr
- || ftmp->fw_flg!=frwl->fw_flg)
- ! matches=0;
-
- tport1=ftmp->fw_nsp+ftmp->fw_ndp;
- tport2=frwl->fw_nsp+frwl->fw_ndp;
- --- 1047,1059 ----
- while( ftmp != NULL )
- {
- matches=1;
- ! if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr
- || ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
- || ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
- || ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
- || ftmp->fw_via.s_addr!=frwl->fw_via.s_addr
- || ftmp->fw_flg!=frwl->fw_flg)
- ! matches=0;
-
- tport1=ftmp->fw_nsp+ftmp->fw_ndp;
- tport2=frwl->fw_nsp+frwl->fw_ndp;
- ***************
- *** 650,657 ****
- else if (tport1!=0)
- {
- for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
- ! if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
- ! matches=0;
- }
- if(matches)
- {
- --- 1062,1069 ----
- else if (tport1!=0)
- {
- for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
- ! if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
- ! matches=0;
- }
- if(matches)
- {
- ***************
- *** 661,671 ****
- ltmp->fw_next=ftmp->fw_next;
- kfree_s(ftmp,sizeof(*ftmp));
- ftmp=ltmp->fw_next;
- ! }
- ! else
- ! {
- ! *chainptr=ftmp->fw_next;
- ! kfree_s(ftmp,sizeof(*ftmp));
- ftmp=*chainptr;
- }
- }
- --- 1073,1083 ----
- ltmp->fw_next=ftmp->fw_next;
- kfree_s(ftmp,sizeof(*ftmp));
- ftmp=ltmp->fw_next;
- ! }
- ! else
- ! {
- ! *chainptr=ftmp->fw_next;
- ! kfree_s(ftmp,sizeof(*ftmp));
- ftmp=*chainptr;
- }
- }
- ***************
- *** 708,714 ****
- if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 )
- {
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printk("ip_fw_ctl: src range set but n_src_p=%d\n",
- frwl->fw_nsp);
- #endif
- return(NULL);
- --- 1120,1126 ----
- if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 )
- {
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printk("ip_fw_ctl: src range set but fw_nsp=%d\n",
- frwl->fw_nsp);
- #endif
- return(NULL);
- ***************
- *** 717,723 ****
- if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 )
- {
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printk("ip_fw_ctl: dst range set but n_dst_p=%d\n",
- frwl->fw_ndp);
- #endif
- return(NULL);
- --- 1129,1135 ----
- if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 )
- {
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printk("ip_fw_ctl: dst range set but fw_ndp=%d\n",
- frwl->fw_ndp);
- #endif
- return(NULL);
- ***************
- *** 740,751 ****
-
- #ifdef CONFIG_IP_ACCT
-
- - void ip_acct_cnt(struct iphdr *iph, struct device *dev, struct ip_fw *f)
- - {
- - (void) ip_fw_chk(iph, dev, f, 0, 1);
- - return;
- - }
- -
- int ip_acct_ctl(int stage, void *m, int len)
- {
- if ( stage == IP_ACCT_FLUSH )
- --- 1152,1157 ----
- ***************
- *** 775,790 ****
- return( del_from_chain(&ip_acct_chain,frwl));
- default:
- /*
- ! * Should be panic but... (Why ??? - AC)
- */
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printf("ip_acct_ctl: unknown request %d\n",stage);
- #endif
- return(EINVAL);
- }
- }
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printf("ip_acct_ctl: unknown request %d\n",stage);
- #endif
- return(EINVAL);
- }
- --- 1181,1196 ----
- return( del_from_chain(&ip_acct_chain,frwl));
- default:
- /*
- ! * Should be panic but... (Why ??? - AC)
- */
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printk("ip_acct_ctl: unknown request %d\n",stage);
- #endif
- return(EINVAL);
- }
- }
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printk("ip_acct_ctl: unknown request %d\n",stage);
- #endif
- return(EINVAL);
- }
- ***************
- *** 839,845 ****
- if ( len < sizeof(struct ip_fwpkt) )
- {
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printf("ip_fw_ctl: length=%d, expected %d\n",
- len, sizeof(struct ip_fwpkt));
- #endif
- return( EINVAL );
- --- 1245,1251 ----
- if ( len < sizeof(struct ip_fwpkt) )
- {
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printk("ip_fw_ctl: length=%d, expected %d\n",
- len, sizeof(struct ip_fwpkt));
- #endif
- return( EINVAL );
- ***************
- *** 851,857 ****
- if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
- {
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printf("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
- sizeof(struct ip)/sizeof(int));
- #endif
- return(EINVAL);
- --- 1257,1263 ----
- if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
- {
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printk("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
- sizeof(struct ip)/sizeof(int));
- #endif
- return(EINVAL);
- ***************
- *** 908,914 ****
- }
-
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printf("ip_fw_ctl: unknown request %d\n",stage);
- #endif
- return(EINVAL);
- }
- --- 1314,1320 ----
- }
-
- #ifdef DEBUG_CONFIG_IP_FIREWALL
- ! printk("ip_fw_ctl: unknown request %d\n",stage);
- #endif
- return(EINVAL);
- }
- ***************
- *** 1013,1016 ****
- --- 1419,1467 ----
- return ip_chain_procinfo(IP_INFO_FWD, buffer,start,offset,length,reset);
- }
-
- + #endif
- +
- + #ifdef CONFIG_IP_MASQUERADE
- +
- + int ip_msqhst_procinfo(char *buffer, char **start, off_t offset, int length)
- + {
- + off_t pos=0, begin=0;
- + struct ip_masq *ms;
- + unsigned long flags;
- + int len=0;
- +
- + len=sprintf(buffer,"Prc FromIP FPrt ToIP TPrt Masq Init-seq Delta Expires\n");
- + save_flags(flags);
- + cli();
- +
- + ms=ip_msq_hosts;
- + while (ms!=NULL) {
- + int timer_active = del_timer(&ms->timer);
- + if (!timer_active)
- + ms->timer.expires = 0;
- + len+=sprintf(buffer+len,"%s %08lX:%04X %08lX:%04X %04X %08lX %5d %lu\n",
- + strProt[ms->protocol==IPPROTO_TCP],
- + ntohl(ms->src),ntohs(ms->sport),
- + ntohl(ms->dst),ntohs(ms->dport),
- + ntohs(ms->mport),
- + ms->init_seq,ms->delta,ms->timer.expires);
- + if (timer_active)
- + add_timer(&ms->timer);
- +
- + pos=begin+len;
- + if(pos<offset) {
- + len=0;
- + begin=pos;
- + }
- + if(pos>offset+length)
- + break;
- + ms=ms->next;
- + }
- + restore_flags(flags);
- + *start=buffer+(offset-begin);
- + len-=(offset-begin);
- + if(len>length)
- + len=length;
- + return len;
- + }
- #endif
- diff -rc linux/net/inet/udp.c linux+masq/net/inet/udp.c
- *** linux/net/inet/udp.c Thu Jan 26 06:25:54 1995
- --- linux+masq/net/inet/udp.c Thu Mar 9 10:00:27 1995
- ***************
- *** 230,236 ****
- * doing or get burned...
- */
-
- ! static void udp_send_check(struct udphdr *uh, unsigned long saddr,
- unsigned long daddr, int len, struct sock *sk)
- {
- uh->check = 0;
- --- 230,236 ----
- * doing or get burned...
- */
-
- ! void udp_send_check(struct udphdr *uh, unsigned long saddr,
- unsigned long daddr, int len, struct sock *sk)
- {
- uh->check = 0;
- diff -rc linux/net/inet/udp.h linux+masq/net/inet/udp.h
- *** linux/net/inet/udp.h Wed Dec 1 13:44:15 1993
- --- linux+masq/net/inet/udp.h Thu Mar 9 10:00:27 1995
- ***************
- *** 33,38 ****
- --- 33,40 ----
-
- extern void udp_err(int err, unsigned char *header, unsigned long daddr,
- unsigned long saddr, struct inet_protocol *protocol);
- + extern void udp_send_check(struct udphdr *uh, unsigned long saddr,
- + unsigned long daddr, int len, struct sock *sk);
- extern int udp_recvfrom(struct sock *sk, unsigned char *to,
- int len, int noblock, unsigned flags,
- struct sockaddr_in *sin, int *addr_len);
-
-
-