patch-2.1.124 linux/net/ipv4/ip_masq_portfw.c
Next file: linux/net/ipv4/ip_masq_raudio.c
Previous file: linux/net/ipv4/ip_masq_mod.c
Back to the patch index
Back to the overall index
- Lines: 345
- Date:
Sun Oct 4 10:21:45 1998
- Orig file:
v2.1.123/linux/net/ipv4/ip_masq_portfw.c
- Orig date:
Wed Dec 10 09:45:16 1997
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq_portfw.c linux/net/ipv4/ip_masq_portfw.c
@@ -2,7 +2,7 @@
* IP_MASQ_PORTFW masquerading module
*
*
- * Version: @(#)ip_masq_portfw.c 0.02 97/10/30
+ * $Id: ip_masq_portfw.c,v 1.2 1998/08/29 23:51:11 davem Exp $
*
* Author: Steven Clarke <steven.clarke@monmouth.demon.co.uk>
*
@@ -10,9 +10,8 @@
* Juan Jose Ciarlante : created this new file from ip_masq.c and ip_fw.c
* Juan Jose Ciarlante : modularized
* Juan Jose Ciarlante : use GFP_KERNEL
+ * Juan Jose Ciarlante : locking
*
- * FIXME
- * - after creating /proc/net/ip_masq/ direct, put portfw underneath
*/
#include <linux/config.h>
@@ -23,19 +22,38 @@
#include <linux/list.h>
#include <net/ip.h>
#include <linux/ip_fw.h>
+#include <linux/ip_masq.h>
#include <net/ip_masq.h>
#include <net/ip_masq_mod.h>
-#include <net/ip_portfw.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
+#define IP_PORTFW_PORT_MIN 1
+#define IP_PORTFW_PORT_MAX 60999
+
+struct ip_portfw {
+ struct list_head list;
+ __u32 laddr, raddr;
+ __u16 lport, rport;
+ atomic_t pref_cnt; /* pref "counter" down to 0 */
+ int pref; /* user set pref */
+};
+
static struct ip_masq_mod *mmod_self = NULL;
+/*
+ * Debug level
+ */
+#ifdef CONFIG_IP_MASQ_DEBUG
+static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
/*
* Lock
*/
-static atomic_t portfw_lock = ATOMIC_INIT(0);
-static struct wait_queue *portfw_wait;
+#ifdef __SMP__
+static spinlock_t portfw_lock = SPIN_LOCK_UNLOCKED;
+#endif
static struct list_head portfw_list[2];
static __inline__ int portfw_idx(int protocol)
@@ -61,7 +79,7 @@
nent = atomic_read(&mmod_self->mmod_nent);
- ip_masq_lockz(&portfw_lock, &portfw_wait, 1);
+ write_lock_bh(&portfw_lock);
for (entry=list->next;entry != list;entry = entry->next) {
n = list_entry(entry, struct ip_portfw, list);
@@ -75,7 +93,7 @@
MOD_DEC_USE_COUNT;
}
}
- ip_masq_unlockz(&portfw_lock, &portfw_wait, 1);
+ write_unlock_bh(&portfw_lock);
return nent==atomic_read(&mmod_self->mmod_nent)? ESRCH : 0;
}
@@ -91,7 +109,7 @@
struct list_head *e;
struct ip_portfw *n;
- ip_masq_lockz(&portfw_lock, &portfw_wait, 1);
+ write_lock_bh(&portfw_lock);
for (prot = 0; prot < 2;prot++) {
l = &portfw_list[prot];
@@ -104,12 +122,12 @@
}
}
- ip_masq_unlockz(&portfw_lock, &portfw_wait, 1);
+ write_unlock_bh(&portfw_lock);
}
/*
* Lookup routine for lport,laddr match
- * called from ip_masq module (via registered obj)
+ * must be called with locked tables
*/
static __inline__ struct ip_portfw *ip_portfw_lookup(__u16 protocol, __u16 lport, __u32 laddr, __u32 *daddr_p, __u16 *dport_p)
{
@@ -118,8 +136,6 @@
struct ip_portfw *n = NULL;
struct list_head *l, *e;
- ip_masq_lock(&portfw_lock, 0);
-
l = &portfw_list[prot];
for (e=l->next;e!=l;e=e->next) {
@@ -136,7 +152,6 @@
}
n = NULL;
out:
- ip_masq_unlock(&portfw_lock, 0);
return n;
}
@@ -153,7 +168,7 @@
int count = 0;
- ip_masq_lockz(&portfw_lock, &portfw_wait, 0);
+ read_lock_bh(&portfw_lock);
l = &portfw_list[prot];
@@ -169,7 +184,7 @@
}
}
- ip_masq_unlockz(&portfw_lock, &portfw_wait, 0);
+ read_unlock_bh(&portfw_lock);
return count;
}
@@ -212,14 +227,14 @@
atomic_set(&npf->pref_cnt, npf->pref);
INIT_LIST_HEAD(&npf->list);
- ip_masq_lockz(&portfw_lock, &portfw_wait, 1);
+ write_lock_bh(&portfw_lock);
/*
* Add at head
*/
list_add(&npf->list, &portfw_list[prot]);
- ip_masq_unlockz(&portfw_lock, &portfw_wait, 1);
+ write_unlock_bh(&portfw_lock);
ip_masq_mod_inc_nent(mmod_self);
return 0;
@@ -227,18 +242,34 @@
-static __inline__ int portfw_ctl(int cmd, struct ip_fw_masqctl *mctl, int optlen)
+static __inline__ int portfw_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
{
- struct ip_portfw_edits *mm = (struct ip_portfw_edits *) mctl->u.mod.data;
+ struct ip_portfw_user *mm = &mctl->u.portfw_user;
int ret = EINVAL;
+ int arglen = optlen - IP_MASQ_CTL_BSIZE;
+ int cmd;
- /*
- * Don't trust the lusers - plenty of error checking!
+
+ IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(len=%d/%d|%d/%d)\n",
+ arglen,
+ sizeof (*mm),
+ optlen,
+ sizeof (*mctl));
+
+ /*
+ * Yes, I'm a bad guy ...
*/
- if (optlen<sizeof(*mm))
+ if (arglen != sizeof(*mm) && optlen != sizeof(*mctl))
return EINVAL;
- if (cmd != IP_FW_MASQ_FLUSH) {
+ /*
+ * Don't trust the lusers - plenty of error checking!
+ */
+ cmd = mctl->m_cmd;
+ IP_MASQ_DEBUG(1-debug, "ip_masq_portfw_ctl(cmd=%d)\n", cmd);
+
+
+ if (cmd != IP_MASQ_CMD_FLUSH) {
if (htons(mm->lport) < IP_PORTFW_PORT_MIN
|| htons(mm->lport) > IP_PORTFW_PORT_MAX)
return EINVAL;
@@ -249,19 +280,19 @@
switch(cmd) {
- case IP_FW_MASQ_ADD:
+ case IP_MASQ_CMD_ADD:
ret = ip_portfw_add(mm->protocol,
mm->lport, mm->laddr,
mm->rport, mm->raddr,
mm->pref);
break;
- case IP_FW_MASQ_DEL:
+ case IP_MASQ_CMD_DEL:
ret = ip_portfw_del(mm->protocol,
mm->lport, mm->laddr,
mm->rport, mm->raddr);
break;
- case IP_FW_MASQ_FLUSH:
+ case IP_MASQ_CMD_FLUSH:
ip_portfw_flush();
ret = 0;
break;
@@ -286,7 +317,6 @@
int ind;
int len=0;
- ip_masq_lockz(&portfw_lock, &portfw_wait, 0);
if (offset < 64)
{
@@ -295,6 +325,8 @@
}
pos = 64;
+ read_lock_bh(&portfw_lock);
+
for(ind = 0; ind < 2; ind++)
{
l = &portfw_list[ind];
@@ -302,8 +334,10 @@
{
pf = list_entry(e, struct ip_portfw, list);
pos += 64;
- if (pos <= offset)
+ if (pos <= offset) {
+ len = 0;
continue;
+ }
sprintf(temp,"%s %08lX %5u > %08lX %5u %5d %5d",
ind ? "TCP" : "UDP",
@@ -317,7 +351,7 @@
}
}
done:
- ip_masq_unlockz(&portfw_lock, &portfw_wait, 0);
+ read_unlock_bh(&portfw_lock);
begin = len - (pos - offset);
*start = buffer + begin;
@@ -329,7 +363,7 @@
static struct proc_dir_entry portfw_proc_entry = {
/* 0, 0, NULL", */
- 0, 9, "ip_portfw", /* Just for compatibility, for now ... */
+ 0, 6, "portfw", /* Just for compatibility, for now ... */
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
portfw_procinfo
@@ -341,13 +375,26 @@
#define proc_ent NULL
#endif
-static int portfw_in_rule(struct iphdr *iph, __u16 *portp)
+static int portfw_in_rule(const struct sk_buff *skb, const struct iphdr *iph)
{
+ const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+#ifdef CONFIG_IP_MASQ_DEBUG
+ struct rtable *rt = (struct rtable *)skb->dst;
+#endif
+ struct ip_portfw *pfw;
- return (ip_portfw_lookup(iph->protocol, portp[1], iph->daddr, NULL, NULL)!=0);
+ IP_MASQ_DEBUG(2, "portfw_in_rule(): skb:= dev=%s (index=%d), rt_iif=%d, rt_flags=0x%x rt_dev___=%s daddr=%d.%d.%d.%d dport=%d\n",
+ skb->dev->name, skb->dev->ifindex, rt->rt_iif, rt->rt_flags,
+ rt->u.dst.dev->name,
+ NIPQUAD(iph->daddr), ntohs(portp[1]));
+
+ read_lock(&portfw_lock);
+ pfw = ip_portfw_lookup(iph->protocol, portp[1], iph->daddr, NULL, NULL);
+ read_unlock(&portfw_lock);
+ return (pfw!=0);
}
-static struct ip_masq * portfw_in_create(struct iphdr *iph, __u16 *portp, __u32 maddr)
+static struct ip_masq * portfw_in_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
{
/*
* If no entry exists in the masquerading table
@@ -357,13 +404,14 @@
__u32 raddr;
__u16 rport;
+ const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
struct ip_masq *ms = NULL;
struct ip_portfw *pf;
/*
- * Lock for reading only, by now...
+ * Lock for writing.
*/
- ip_masq_lock(&portfw_lock, 0);
+ write_lock(&portfw_lock);
if ((pf=ip_portfw_lookup(iph->protocol,
portp[1], iph->daddr,
@@ -375,8 +423,8 @@
0);
ip_masq_listen(ms);
- if (!ms || atomic_read(&mmod_self->mmod_nent) <= 1 ||
- ip_masq_nlocks(&portfw_lock) != 1)
+ if (!ms || atomic_read(&mmod_self->mmod_nent) <= 1
+ /* || ip_masq_nlocks(&portfw_lock) != 1 */ )
/*
* Maybe later...
*/
@@ -390,18 +438,16 @@
*/
if (atomic_dec_and_test(&pf->pref_cnt)) {
- start_bh_atomic();
atomic_set(&pf->pref_cnt, pf->pref);
list_del(&pf->list);
list_add(&pf->list,
portfw_list[portfw_idx(iph->protocol)].prev);
- end_bh_atomic();
}
}
out:
- ip_masq_unlock(&portfw_lock, 0);
+ write_unlock(&portfw_lock);
return ms;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov