lkml.org 
[lkml]   [1998]   [Feb]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH (masq)] 2.0.33 crashes
Hi!
I've attached a patch that *could* solve masquerading related
2.0.33 freezes.
It changes:
- use soft (instead of hard, cli() ) irq locking for
. control connection handling (eg. ftp)
. /proc/net/ip_masquerade
- [bonus:] cleanup ip_autofw timers when deleting/flushing.

It will be great if ppl reporting freezes could test this (greater if it
solves them :))

Regards...


-- Juanjo http://juanjox.home.ml.org


--- linux/include/net/ip_masq.h.dist Tue Dec 2 19:20:39 1997
+++ linux/include/net/ip_masq.h Mon Feb 23 09:57:43 1998
@@ -1,5 +1,7 @@
/*
* IP masquerading functionality definitions
+ *
+ * $Id: ip_masq.h,v 0.12 1998/02/23 11:41:19 jjo Exp jjo $
*/

#ifndef _IP_MASQ_H
@@ -32,6 +34,7 @@
#define MASQUERADE_EXPIRE_TCP 15*60*HZ
#define MASQUERADE_EXPIRE_TCP_FIN 2*60*HZ
#define MASQUERADE_EXPIRE_UDP 5*60*HZ
+#define MASQUERADE_EXPIRE_RETRY 1*60*HZ
/*
* ICMP can no longer be modified on the fly using an ioctl - this
* define is the only way to change the timeouts
@@ -51,7 +54,9 @@
#define IP_MASQ_F_SAW_FIN (IP_MASQ_F_SAW_FIN_IN | \
IP_MASQ_F_SAW_FIN_OUT)
/* tcp fin pkts seen */
+#if 0
#define IP_MASQ_F_CONTROL 0x100 /* this is a control channel */
+#endif
#define IP_MASQ_F_NO_SPORT 0x200 /* no sport set yet */
#define IP_MASQ_F_FTP_PASV 0x400 /* ftp PASV command just issued */
#define IP_MASQ_F_NO_REPLY 0x800 /* no reply yet from outside */
@@ -83,7 +88,8 @@
struct ip_masq_app *app; /* bound ip_masq_app object */
void *app_data; /* Application private data */
unsigned flags; /* status flags */
- struct ip_masq *control; /* Corresponding control connection */
+ struct ip_masq *control; /* Master control connection */
+ atomic_t n_control; /* Number of "controlled" masqs */
};

/*
@@ -124,6 +130,10 @@
extern struct ip_masq *ip_masq_new(struct device *dev, int proto, __u32 saddr, __u16 sport, __u32 daddr, __u16 dport, unsigned flags);
extern void ip_masq_set_expire(struct ip_masq *ms, unsigned long tout);

+extern void ip_masq_control_add(struct ip_masq *ms, struct ip_masq* ctl_ms);
+extern void ip_masq_control_del(struct ip_masq *ms);
+extern struct ip_masq * ip_masq_control_get(struct ip_masq *ms);
+
#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW
extern void ip_autofw_expire(unsigned long data);
#endif
@@ -199,6 +209,81 @@
#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW
extern struct ip_autofw * ip_autofw_hosts;
#endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
+
+/*
+ * atomic_t stuff
+ */
+#define ATOMIC_INIT(x) (x)
+#define atomic_read(px) (*(px))
+
+
+/*
+ * Locking stuff
+ */
+
+
+static __inline__ void ip_masq_lock(atomic_t *lock, int rw)
+{
+#if 0
+ if (rw)
+#endif
+ start_bh_atomic();
+ atomic_inc(lock);
+}
+
+static __inline__ void ip_masq_unlock(atomic_t *lock, int rw)
+{
+ atomic_dec(lock);
+#if 0
+ if (rw)
+#endif
+ end_bh_atomic();
+}
+
+/*
+ * Sleep-able lockzzz...
+ */
+static __inline__ void ip_masq_lockz(atomic_t *lock, struct wait_queue ** waitq, int rw)
+{
+ if (rw)
+ while(atomic_read(lock)) sleep_on(waitq);
+ ip_masq_lock(lock, rw);
+}
+
+static __inline__ void ip_masq_unlockz(atomic_t *lock, struct wait_queue ** waitq, int rw)
+{
+ ip_masq_unlock(lock, rw);
+ if (rw)
+ wake_up(waitq);
+}
+
+/*
+ * Perfect for winning races ... ;)
+ */
+static __inline__ int ip_masq_nlocks(atomic_t *lock)
+{
+ return atomic_read(lock);
+}
+
+extern atomic_t __ip_masq_lock;
+
+/*
+ * Debugging stuff
+ */
+
+
+#define IP_MASQ_INFO(msg...) \
+ printk(KERN_INFO "IP_MASQ:" ## msg)
+
+#define IP_MASQ_DEBUG(msg...) \
+ printk(KERN_DEBUG "IP_MASQ:" ## msg)
+
+#define IP_MASQ_ERR(msg...) \
+ printk(KERN_ERR "IP_MASQ:" ## msg)
+
+#define IP_MASQ_WARNING(msg...) \
+ printk(KERN_WARNING "IP_MASQ:" ## msg)
+

#endif /* __KERNEL__ */

--- linux/net/ipv4/ip_masq.c.dist Tue Aug 5 14:44:26 1997
+++ linux/net/ipv4/ip_masq.c Mon Feb 23 09:06:36 1998
@@ -4,6 +4,8 @@
*
* Copyright (c) 1994 Pauline Middelink
*
+ * $Id: ip_masq.c,v 0.12 1998/02/23 11:40:49 jjo Exp jjo $
+ *
* See ip_fw.c for original log
*
* Fixes:
@@ -20,6 +22,8 @@
* Delian Delchev : Added support for ICMP requests and replys
* Nigel Metheringham : ICMP in ICMP handling, tidy ups, bug fixes, made ICMP optional
* Juan Jose Ciarlante : re-assign maddr if no packet received from outside
+ * Juan Jose Ciarlante : softlocking.
+ * Juan Jose Ciarlante : littl autofw oops fix
*
*/

@@ -45,6 +49,14 @@

#define IP_MASQ_TAB_SIZE 256 /* must be power of 2 */

+
+/*
+ * deletion-procinfo mutex lock
+ */
+static struct wait_queue *masq_wait;
+atomic_t __ip_masq_lock = ATOMIC_INIT(0);
+
+
/*
* Implement IP packet masquerading
*/
@@ -130,6 +142,10 @@
X(ip_masq_free_ports),
X(ip_masq_expire),
X(ip_masq_out_get_2),
+ X(__ip_masq_lock),
+ X(ip_masq_control_add),
+ X(ip_masq_control_del),
+ X(ip_masq_control_get),
#include <linux/symtab_end.h>
};

@@ -519,54 +535,41 @@
return NULL;
}

+/*
+ * Lock-protect against /proc access (currently the only
+ * simultaneous possibility).
+ * Forget about cli() and friends.
+ */
static void masq_expire(unsigned long data)
{
- struct ip_masq *ms = (struct ip_masq *)data, *ms_data;
- unsigned long flags;
-
- if (ms->flags & IP_MASQ_F_CONTROL) {
- /* a control channel is about to expire */
- int idx = 0, reprieve = 0;
-#ifdef DEBUG_CONFIG_IP_MASQUERADE
- printk("Masquerade control %s %lX:%X about to expire\n",
- masq_proto_name(ms->protocol),
- ntohl(ms->saddr),ntohs(ms->sport));
-#endif
- save_flags(flags);
- cli();
+ struct ip_masq *ms = (struct ip_masq *)data;
+
+ ip_masq_lock(&__ip_masq_lock, 1);

- /*
- * If any other masquerade entry claims that the expiring entry
- * is its control channel then keep the control entry alive.
- * Useful for long running data channels with inactive control
- * links which we don't want to lose, e.g. ftp.
- * Assumption: loops such as a->b->a or a->a will never occur.
- */
- for (idx = 0; idx < IP_MASQ_TAB_SIZE && !reprieve; idx++) {
- for (ms_data = ip_masq_m_tab[idx]; ms_data ; ms_data = ms_data->m_link) {
- if (ms_data->control == ms) {
- reprieve = 1; /* this control connection can live a bit longer */
- ip_masq_set_expire(ms, ip_masq_expire->tcp_timeout);
-#ifdef DEBUG_CONFIG_IP_MASQUERADE
- printk("Masquerade control %s %lX:%X expiry reprieved\n",
- masq_proto_name(ms->protocol),
- ntohl(ms->saddr),ntohs(ms->sport));
-#endif
- break;
- }
- }
- }
- restore_flags(flags);
- if (reprieve)
- return;
+ /*
+ * Already locked, do bounce ...
+ */
+ if (ip_masq_nlocks(&__ip_masq_lock) != 1) {
+ goto masq_expire_later;
}

+ /*
+ * do I control anybody?
+ */
+ if (atomic_read(&ms->n_control))
+ goto masq_expire_later;
+
+ /*
+ * does anybody controls me?
+ */
+
+ if (ms->control)
+ ip_masq_control_del(ms);
+
#ifdef DEBUG_CONFIG_IP_MASQUERADE
printk("Masqueraded %s %lX:%X expired\n",masq_proto_name(ms->protocol),ntohl(ms->saddr),ntohs(ms->sport));
#endif

- save_flags(flags);
- cli();

if (ip_masq_unhash(ms)) {
ip_masq_free_ports[masq_proto_num(ms->protocol)]++;
@@ -575,7 +578,16 @@
kfree_s(ms,sizeof(*ms));
}

- restore_flags(flags);
+masq_expire_later:
+ IP_MASQ_DEBUG("masq_expire delayed: %s %08lX:%04X->%08lX:%04X nlocks-1=%d masq.n_control=%d\n",
+ masq_proto_name(ms->protocol),
+ ntohl(ms->saddr), ntohs(ms->sport),
+ ntohl(ms->daddr), ntohs(ms->dport),
+ ip_masq_nlocks(&__ip_masq_lock)-1,
+ atomic_read(&ms->n_control));
+
+ ip_masq_unlock(&__ip_masq_lock, 1);
+ ip_masq_set_expire(ms, MASQUERADE_EXPIRE_RETRY);
}

#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW
@@ -1547,6 +1559,49 @@
return 0;
}

+void ip_masq_control_add(struct ip_masq *ms, struct ip_masq* ctl_ms)
+{
+ if (ms->control) {
+ IP_MASQ_ERR( "request control ADD for already controlled: %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n",
+ NIPQUAD(ms->saddr),ntohs(ms->sport),
+ NIPQUAD(ms->daddr),ntohs(ms->dport));
+ ip_masq_control_del(ms);
+ }
+ IP_MASQ_DEBUG("ADDing control for: ms.dst=%d.%d.%d.%d:%d ctl_ms.dst=%d.%d.%d.%d:%d\n",
+ NIPQUAD(ms->daddr),ntohs(ms->dport),
+ NIPQUAD(ctl_ms->daddr),ntohs(ctl_ms->dport));
+ ms->control = ctl_ms;
+ atomic_inc(&ctl_ms->n_control);
+}
+
+void ip_masq_control_del(struct ip_masq *ms)
+{
+ struct ip_masq *ctl_ms = ms->control;
+ if (!ctl_ms) {
+ IP_MASQ_ERR( "request control DEL for uncontrolled: %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n",
+ NIPQUAD(ms->saddr),ntohs(ms->sport),
+ NIPQUAD(ms->daddr),ntohs(ms->dport));
+ return;
+ }
+ IP_MASQ_DEBUG("DELeting control for: ms.dst=%d.%d.%d.%d:%d ctl_ms.dst=%d.%d.%d.%d:%d\n",
+ NIPQUAD(ms->daddr),ntohs(ms->dport),
+ NIPQUAD(ctl_ms->daddr),ntohs(ctl_ms->dport));
+ ms->control = NULL;
+ if (atomic_read(&ctl_ms->n_control) == 0) {
+ IP_MASQ_ERR( "BUG control DEL with n=0 : %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n",
+ NIPQUAD(ms->saddr),ntohs(ms->sport),
+ NIPQUAD(ms->daddr),ntohs(ms->dport));
+ return;
+
+ }
+ atomic_dec(&ctl_ms->n_control);
+}
+
+struct ip_masq * ip_masq_control_get(struct ip_masq *ms)
+{
+ return ms->control;
+}
+
/*
* /proc/net entries
*/
@@ -1601,10 +1656,11 @@
{
off_t pos=0, begin;
struct ip_masq *ms;
- unsigned long flags;
char temp[129];
int idx = 0;
int len=0;
+
+ ip_masq_lockz(&__ip_masq_lock, &masq_wait, 0);

if (offset < 128)
{
@@ -1620,8 +1676,6 @@
len = sprintf(buffer, "%-127s\n", temp);
}
pos = 128;
- save_flags(flags);
- cli();

for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++)
for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link)
@@ -1651,7 +1705,8 @@
goto done;
}
done:
- restore_flags(flags);
+ ip_masq_unlockz(&__ip_masq_lock, &masq_wait, 0);
+
begin = len - (pos - offset);
*start = buffer + begin;
len -= begin;
--- linux/net/ipv4/ip_masq_ftp.c.dist Tue Apr 8 12:47:47 1997
+++ linux/net/ipv4/ip_masq_ftp.c Mon Feb 23 09:06:36 1998
@@ -1,17 +1,16 @@
/*
* IP_MASQ_FTP ftp masquerading module
*
- *
- * Version: @(#)ip_masq_ftp.c 0.01 02/05/96
- *
* Author: Wouter Gadeyne
*
+ * $Id: ip_masq_ftp.c,v 0.3 1998/02/23 11:46:36 jjo Exp jjo $
*
* Fixes:
* Wouter Gadeyne : Fixed masquerading support of ftp PORT commands
* Juan Jose Ciarlante : Code moved and adapted from ip_fw.c
* Keith Owens : Add keep alive for ftp control channel
* Nigel Metheringham : Added multiple port support
+ * Juan Jose Ciarlante : use ip_masq_control_xxx functions
*
*
*
@@ -146,8 +145,7 @@

if (n_ms==NULL)
return 0;
- n_ms->control = ms; /* keepalive from data to the control channel */
- ms->flags |= IP_MASQ_F_CONTROL; /* this is a control channel */
+ ip_masq_control_add(n_ms, ms);
}

/*
@@ -285,8 +283,8 @@

if (n_ms==NULL)
return 0;
- n_ms->control = ms; /* keepalive from data to the control channel */
- ms->flags |= IP_MASQ_F_CONTROL; /* this is a control channel */
+
+ ip_masq_control_add(n_ms, ms);
}

/*
--- linux/net/ipv4/ip_fw.c.dist Tue Aug 12 15:30:28 1997
+++ linux/net/ipv4/ip_fw.c Mon Feb 23 09:08:14 1998
@@ -933,11 +933,15 @@
if (prev)
{
prev->next=curr->next;
+ if (curr->flags&IP_AUTOFW_ACTIVE)
+ del_timer(&curr->timer);
kfree_s(curr,sizeof(struct ip_autofw));
return(0);
}
else
{
+ if (ip_autofw_hosts->flags&IP_AUTOFW_ACTIVE)
+ del_timer(&ip_autofw_hosts->timer);
kfree_s(ip_autofw_hosts,sizeof(struct ip_autofw));
ip_autofw_hosts=curr->next;
return(0);
@@ -956,6 +960,8 @@
{
af=ip_autofw_hosts;
ip_autofw_hosts=ip_autofw_hosts->next;
+ if (af->flags&IP_AUTOFW_ACTIVE)
+ del_timer(&af->timer);
kfree_s(af,sizeof(struct ip_autofw));
}
return(0);
\
 
 \ /
  Last update: 2005-03-22 13:41    [W:0.031 / U:0.292 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site