home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hacks & Cracks
/
Hacks_and_Cracks.iso
/
hackersclub
/
km
/
downloads
/
c_scripts
/
ip_masq.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-03-25
|
33KB
|
1,271 lines
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);