summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/Config.in2
-rw-r--r--net/atm/Makefile12
-rw-r--r--net/atm/lec.c4
-rw-r--r--net/atm/proc.c1
-rw-r--r--net/core/dev.c4
-rw-r--r--net/core/dv.c2
-rw-r--r--net/decnet/af_decnet.c7
-rw-r--r--net/ethernet/eth.c27
-rw-r--r--net/ipv4/devinet.c8
-rw-r--r--net/ipv4/ip_fragment.c13
-rw-r--r--net/ipv4/netfilter/Config.in4
-rw-r--r--net/ipv4/netfilter/Makefile2
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c245
-rw-r--r--net/ipv4/netfilter/ipt_tcpmss.c108
-rw-r--r--net/ipv4/sysctl_net_ipv4.c5
-rw-r--r--net/ipv6/ip6_fib.c31
-rw-r--r--net/ipv6/ipv6_sockglue.c9
-rw-r--r--net/ipv6/reassembly.c13
-rw-r--r--net/ipv6/tcp_ipv6.c2
-rw-r--r--net/ipx/af_ipx.c474
-rw-r--r--net/ipx/sysctl_net_ipx.c42
-rw-r--r--net/irda/af_irda.c11
-rw-r--r--net/irda/ircomm/Makefile2
-rw-r--r--net/irda/ircomm/ircomm_core.c2
-rw-r--r--net/irda/ircomm/ircomm_event.c2
-rw-r--r--net/irda/ircomm/ircomm_lmp.c2
-rw-r--r--net/irda/ircomm/ircomm_ttp.c2
-rw-r--r--net/irda/ircomm/ircomm_tty.c4
-rw-r--r--net/irda/irias_object.c2
-rw-r--r--net/irda/irlan/irlan_provider.c4
-rw-r--r--net/irda/irlap.c3
-rw-r--r--net/irda/irlap_comp.c2
-rw-r--r--net/irda/irlap_event.c2
-rw-r--r--net/irda/irlmp.c2
-rw-r--r--net/irda/irlmp_frame.c2
-rw-r--r--net/irda/irnet/Config.in5
-rw-r--r--net/irda/irnet/irnet.h16
-rw-r--r--net/irda/irnet/irnet_irda.c8
-rw-r--r--net/khttpd/main.c2
-rw-r--r--net/khttpd/rfc.c2
-rw-r--r--net/netsyms.c24
-rw-r--r--net/sched/Makefile194
-rw-r--r--net/sched/cls_tcindex.c73
-rw-r--r--net/sched/sch_cbq.c8
-rw-r--r--net/sched/sch_dsmark.c8
-rw-r--r--net/sched/sch_tbf.c21
-rw-r--r--net/sunrpc/svcsock.c11
-rw-r--r--net/sysctl_net.c7
-rw-r--r--net/unix/af_unix.c4
-rw-r--r--net/wanrouter/wanmain.c2
50 files changed, 901 insertions, 541 deletions
diff --git a/net/Config.in b/net/Config.in
index 96b8ee502..0adfaa4cf 100644
--- a/net/Config.in
+++ b/net/Config.in
@@ -81,7 +81,7 @@ fi
mainmenu_option next_comment
comment 'QoS and/or fair queueing'
-bool 'QoS and/or fair queueing (EXPERIMENTAL)' CONFIG_NET_SCHED
+bool 'QoS and/or fair queueing' CONFIG_NET_SCHED
if [ "$CONFIG_NET_SCHED" = "y" ]; then
source net/sched/Config.in
fi
diff --git a/net/atm/Makefile b/net/atm/Makefile
index f122d1a62..76e60e92e 100644
--- a/net/atm/Makefile
+++ b/net/atm/Makefile
@@ -7,16 +7,14 @@
#
# Note 2! The CFLAGS definition is now in the main makefile...
-include ../../.config
+O_TARGET := atm.o
-O_TARGET= atm.o
+export-objs := common.o atm_misc.o raw.o resources.o ipcommon.o proc.o
-export-objs = common.o atm_misc.o raw.o resources.o ipcommon.o proc.o
+list-multi := mpoa.o
+mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o
-multi-list = mpoa.o
-mpoa-objs = mpc.o mpoa_caches.o mpoa_proc.o
-
-obj-$(CONFIG_ATM) = addr.o pvc.o signaling.o svc.o common.o atm_misc.o raw.o resources.o
+obj-$(CONFIG_ATM) := addr.o pvc.o signaling.o svc.o common.o atm_misc.o raw.o resources.o
ifeq ($(CONFIG_ATM_CLIP),y)
obj-y += clip.o
diff --git a/net/atm/lec.c b/net/atm/lec.c
index ec0dc2671..2e0f697bb 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -51,9 +51,9 @@ static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
#define DPRINTK(format,args...)
#endif
-struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
+extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
unsigned char *addr);
-void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
+extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
#define DUMP_PACKETS 0 /* 0 = None,
diff --git a/net/atm/proc.c b/net/atm/proc.c
index ef0091735..8c3dc562f 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -561,7 +561,6 @@ int atm_proc_dev_register(struct atm_dev *dev)
dev->proc_entry->proc_fops = &proc_dev_atm_operations;
dev->proc_entry->owner = THIS_MODULE;
return 0;
- kfree(dev->proc_entry);
fail0:
kfree(dev->proc_name);
fail1:
diff --git a/net/core/dev.c b/net/core/dev.c
index cf4dcf8cd..3276ee10e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -349,7 +349,7 @@ int netdev_boot_setup_check(struct net_device *dev)
/*
* Saves at boot time configured settings for any netdevice.
*/
-static int __init netdev_boot_setup(char *str)
+int __init netdev_boot_setup(char *str)
{
int ints[5];
struct ifmap map;
@@ -359,7 +359,7 @@ static int __init netdev_boot_setup(char *str)
return 0;
/* Save settings */
- memset(&map, -1, sizeof(map));
+ memset(&map, 0, sizeof(map));
if (ints[0] > 0)
map.irq = ints[1];
if (ints[0] > 1)
diff --git a/net/core/dv.c b/net/core/dv.c
index 0e5b3e671..1a31310ca 100644
--- a/net/core/dv.c
+++ b/net/core/dv.c
@@ -172,7 +172,7 @@ int check_args(struct divert_cf *div_cf, struct net_device **dev)
return -EINVAL;
/* user issuing the ioctl must be a super one :) */
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
/* Device must have a divert_blk member NOT null */
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 6cca075c0..f5e94de8f 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -1431,10 +1431,13 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char *opt
struct sock *sk = sock->sk;
struct dn_scp *scp = DN_SK(sk);
struct linkinfo_dn link;
- int r_len = *optlen;
+ int r_len;
void *r_data = NULL;
- int val;
+ unsigned int val;
+ if(get_user(r_len , optlen))
+ return -EFAULT;
+
switch(optname) {
case DSO_CONDATA:
if (r_len > sizeof(struct optdata_dn))
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index b26c97e4e..81735d961 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -30,6 +30,7 @@
* Alan Cox : Protect against forwarding explosions with
* older network drivers and IFF_ALLMULTI.
* Christer Weinigel : Better rebuild header message.
+ * Andrew Morton : 26Feb01: kill ether_setup() - use netdev_boot_setup().
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -60,31 +61,9 @@
#include <asm/system.h>
#include <asm/checksum.h>
-static int __init eth_setup(char *str)
-{
- int ints[5];
- struct ifmap map;
-
- str = get_options(str, ARRAY_SIZE(ints), ints);
- if (!str || !*str)
- return 0;
-
- /* Save settings */
- memset(&map, -1, sizeof(map));
- if (ints[0] > 0)
- map.irq = ints[1];
- if (ints[0] > 1)
- map.base_addr = ints[2];
- if (ints[0] > 2)
- map.mem_start = ints[3];
- if (ints[0] > 3)
- map.mem_end = ints[4];
-
- /* Add new entry to the list */
- return netdev_boot_setup_add(str, &map);
-}
+extern int __init netdev_boot_setup(char *str);
-__setup("ether=", eth_setup);
+__setup("ether=", netdev_boot_setup);
/*
* Create the Ethernet MAC header for an arbitrary protocol layer
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 8d668ff41..e35e0d6cb 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1,7 +1,7 @@
/*
* NET3 IP device support routines.
*
- * Version: $Id: devinet.c,v 1.40 2001/02/05 06:03:47 davem Exp $
+ * Version: $Id: devinet.c,v 1.41 2001/02/18 09:26:26 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -827,10 +827,8 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, void
return NOTIFY_DONE;
}
-struct notifier_block ip_netdev_notifier={
- inetdev_event,
- NULL,
- 0
+struct notifier_block ip_netdev_notifier = {
+ notifier_call: inetdev_event,
};
#ifdef CONFIG_RTNETLINK
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index afed5862e..5cd316a26 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -213,18 +213,17 @@ static void ip_evictor(void)
if (ipq_hash[i] == NULL)
continue;
- write_lock(&ipfrag_lock);
+ read_lock(&ipfrag_lock);
if ((qp = ipq_hash[i]) != NULL) {
/* find the oldest queue for this hash bucket */
while (qp->next)
qp = qp->next;
- __ipq_unlink(qp);
- write_unlock(&ipfrag_lock);
+ atomic_inc(&qp->refcnt);
+ read_unlock(&ipfrag_lock);
spin_lock(&qp->lock);
- if (del_timer(&qp->timer))
- atomic_dec(&qp->refcnt);
- qp->last_in |= COMPLETE;
+ if (!(qp->last_in&COMPLETE))
+ ipq_kill(qp);
spin_unlock(&qp->lock);
ipq_put(qp);
@@ -232,7 +231,7 @@ static void ip_evictor(void)
progress = 1;
continue;
}
- write_unlock(&ipfrag_lock);
+ read_unlock(&ipfrag_lock);
}
} while (progress);
}
diff --git a/net/ipv4/netfilter/Config.in b/net/ipv4/netfilter/Config.in
index 5887658fb..cb4789fb3 100644
--- a/net/ipv4/netfilter/Config.in
+++ b/net/ipv4/netfilter/Config.in
@@ -20,6 +20,7 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
dep_tristate ' netfilter MARK match support' CONFIG_IP_NF_MATCH_MARK $CONFIG_IP_NF_IPTABLES
dep_tristate ' Multiple port match support' CONFIG_IP_NF_MATCH_MULTIPORT $CONFIG_IP_NF_IPTABLES
dep_tristate ' TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' tcpmss match support' CONFIG_IP_NF_MATCH_TCPMSS $CONFIG_IP_NF_IPTABLES
if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
dep_tristate ' Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
fi
@@ -45,7 +46,7 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
# If they want FTP, set to $CONFIG_IP_NF_NAT (m or y),
# or $CONFIG_IP_NF_FTP (m or y), whichever is weaker. Argh.
if [ "$CONFIG_IP_NF_FTP" = "m" ]; then
- define_tristate CONFIG_IP_NF_NAT_FTP m
+ define_tristate CONFIG_IP_NF_NAT_FTP m
else
if [ "$CONFIG_IP_NF_FTP" = "y" ]; then
define_tristate CONFIG_IP_NF_NAT_FTP $CONFIG_IP_NF_NAT
@@ -60,6 +61,7 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
dep_tristate ' MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
fi
dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' TCPMSS target support' CONFIG_IP_NF_TARGET_TCPMSS $CONFIG_IP_NF_IPTABLES
fi
# Backwards compatibility modules: only if you don't build in the others.
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index c40caa75e..5833a87c7 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
+obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
# targets
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
@@ -63,6 +64,7 @@ obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
+obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
# backwards compatibility
obj-$(CONFIG_IP_NF_COMPAT_IPCHAINS) += ipchains.o
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
new file mode 100644
index 000000000..9dd50740a
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -0,0 +1,245 @@
+/*
+ * This is a module which is used for setting the MSS option in TCP packets.
+ *
+ * Copyright (c) 2000 Marc Boucher
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/ip.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_TCPMSS.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+static u_int16_t
+cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
+{
+ u_int32_t diffs[] = { oldvalinv, newval };
+ return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
+ oldcheck^0xFFFF));
+}
+
+static inline unsigned int
+optlen(const u_int8_t *opt, unsigned int offset)
+{
+ /* Beware zero-length options: make finite progress */
+ if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0) return 1;
+ else return opt[offset+1];
+}
+
+static unsigned int
+ipt_tcpmss_target(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
+ struct tcphdr *tcph;
+ struct iphdr *iph = (*pskb)->nh.iph;
+ u_int16_t tcplen, newtotlen, oldval, newmss;
+ unsigned int i;
+ u_int8_t *opt;
+
+ tcplen = (*pskb)->len - iph->ihl*4;
+
+ tcph = (void *)iph + iph->ihl*4;
+
+ /* Since it passed flags test in tcp match, we know it is is
+ not a fragment, and has data >= tcp header length. SYN
+ packets should not contain data: if they did, then we risk
+ running over MTU, sending Frag Needed and breaking things
+ badly. --RR */
+ if (tcplen != tcph->doff*4) {
+ if (net_ratelimit())
+ printk(KERN_ERR
+ "ipt_tcpmss_target: bad length (%d bytes)\n",
+ (*pskb)->len);
+ return NF_DROP;
+ }
+
+ if(tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) {
+ if(!(*pskb)->dst) {
+ if (net_ratelimit())
+ printk(KERN_ERR
+ "ipt_tcpmss_target: no dst?! can't determine path-MTU\n");
+ return NF_DROP; /* or IPT_CONTINUE ?? */
+ }
+
+ if((*pskb)->dst->pmtu <= (sizeof(struct iphdr) + sizeof(struct tcphdr))) {
+ if (net_ratelimit())
+ printk(KERN_ERR
+ "ipt_tcpmss_target: unknown or invalid path-MTU (%d)\n", (*pskb)->dst->pmtu);
+ return NF_DROP; /* or IPT_CONTINUE ?? */
+ }
+
+ newmss = (*pskb)->dst->pmtu - sizeof(struct iphdr) - sizeof(struct tcphdr);
+ } else
+ newmss = tcpmssinfo->mss;
+
+ opt = (u_int8_t *)tcph;
+ for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)){
+ if ((opt[i] == TCPOPT_MSS) &&
+ ((tcph->doff*4 - i) >= TCPOLEN_MSS) &&
+ (opt[i+1] == TCPOLEN_MSS)) {
+ u_int16_t oldmss;
+
+ oldmss = (opt[i+2] << 8) | opt[i+3];
+
+ if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) &&
+ (oldmss <= newmss))
+ return IPT_CONTINUE;
+
+ opt[i+2] = (newmss & 0xff00) >> 8;
+ opt[i+3] = (newmss & 0x00ff);
+
+ tcph->check = cheat_check(htons(oldmss)^0xFFFF,
+ htons(newmss),
+ tcph->check);
+
+ DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu"
+ "->%u.%u.%u.%u:%hu changed TCP MSS option"
+ " (from %u to %u)\n",
+ NIPQUAD((*pskb)->nh.iph->saddr),
+ ntohs(tcph->source),
+ NIPQUAD((*pskb)->nh.iph->daddr),
+ ntohs(tcph->dest),
+ oldmss, newmss);
+ goto retmodified;
+ }
+ }
+
+ /*
+ * MSS Option not found ?! add it..
+ */
+ if (skb_tailroom((*pskb)) < TCPOLEN_MSS) {
+ struct sk_buff *newskb;
+
+ newskb = skb_copy_expand(*pskb, skb_headroom(*pskb),
+ TCPOLEN_MSS, GFP_ATOMIC);
+ if (!newskb) {
+ if (net_ratelimit())
+ printk(KERN_ERR "ipt_tcpmss_target:"
+ " unable to allocate larger skb\n");
+ return NF_DROP;
+ }
+
+ kfree_skb(*pskb);
+ *pskb = newskb;
+ iph = (*pskb)->nh.iph;
+ tcph = (void *)iph + iph->ihl*4;
+ }
+
+ skb_put((*pskb), TCPOLEN_MSS);
+
+ opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
+ memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
+
+ tcph->check = cheat_check(htons(tcplen) ^ 0xFFFF,
+ htons(tcplen + TCPOLEN_MSS), tcph->check);
+ tcplen += TCPOLEN_MSS;
+
+ opt[0] = TCPOPT_MSS;
+ opt[1] = TCPOLEN_MSS;
+ opt[2] = (newmss & 0xff00) >> 8;
+ opt[3] = (newmss & 0x00ff);
+
+ tcph->check = cheat_check(~0, *((u_int32_t *)opt), tcph->check);
+
+ oldval = ((u_int16_t *)tcph)[6];
+ tcph->doff += TCPOLEN_MSS/4;
+ tcph->check = cheat_check(oldval ^ 0xFFFF,
+ ((u_int16_t *)tcph)[6], tcph->check);
+
+ newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS);
+ iph->check = cheat_check(iph->tot_len ^ 0xFFFF,
+ newtotlen, iph->check);
+ iph->tot_len = newtotlen;
+
+ DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu"
+ "->%u.%u.%u.%u:%hu added TCP MSS option (%u)\n",
+ NIPQUAD((*pskb)->nh.iph->saddr),
+ ntohs(tcph->source),
+ NIPQUAD((*pskb)->nh.iph->daddr),
+ ntohs(tcph->dest),
+ newmss);
+
+ retmodified:
+ /* If we had a hardware checksum before, it's now invalid */
+ (*pskb)->ip_summed = CHECKSUM_NONE;
+ (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;
+ return IPT_CONTINUE;
+}
+
+#define TH_SYN 0x02
+
+static inline int find_syn_match(const struct ipt_entry_match *m)
+{
+ const struct ipt_tcp *tcpinfo = (const struct ipt_tcp *)m->data;
+
+ if (strcmp(m->u.kernel.match->name, "tcp") == 0
+ && (tcpinfo->flg_cmp & TH_SYN)
+ && !(tcpinfo->invflags & IPT_TCP_INV_FLAGS))
+ return 1;
+
+ return 0;
+}
+
+/* Must specify -p tcp --syn/--tcp-flags SYN */
+static int
+ipt_tcpmss_checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
+
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) {
+ DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n",
+ targinfosize, IPT_ALIGN(sizeof(struct ipt_tcpmss_info)));
+ return 0;
+ }
+
+
+ if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) &&
+ ((hook_mask & ~((1 << NF_IP_FORWARD)
+ | (1 << NF_IP_LOCAL_OUT)
+ | (1 << NF_IP_POST_ROUTING))) != 0)) {
+ printk("TCPMSS: path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n");
+ return 0;
+ }
+
+ if (e->ip.proto == IPPROTO_TCP
+ && !(e->ip.invflags & IPT_INV_PROTO)
+ && IPT_MATCH_ITERATE(e, find_syn_match))
+ return 1;
+
+ printk("TCPMSS: Only works on TCP SYN packets\n");
+ return 0;
+}
+
+static struct ipt_target ipt_tcpmss_reg
+= { { NULL, NULL }, "TCPMSS",
+ ipt_tcpmss_target, ipt_tcpmss_checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ return ipt_register_target(&ipt_tcpmss_reg);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&ipt_tcpmss_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_tcpmss.c b/net/ipv4/netfilter/ipt_tcpmss.c
new file mode 100644
index 000000000..7dae37a33
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_tcpmss.c
@@ -0,0 +1,108 @@
+/* Kernel module to match TCP MSS values. */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ipt_tcpmss.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+#define TH_SYN 0x02
+
+/* Returns 1 if the mss option is set and matched by the range, 0 otherwise */
+static inline int
+mssoption_match(u_int16_t min, u_int16_t max,
+ const struct tcphdr *tcp,
+ u_int16_t datalen,
+ int invert,
+ int *hotdrop)
+{
+ unsigned int i;
+ const u_int8_t *opt = (u_int8_t *)tcp;
+
+ /* If we don't have the whole header, drop packet. */
+ if (tcp->doff * 4 > datalen) {
+ *hotdrop = 1;
+ return 0;
+ }
+
+ for (i = sizeof(struct tcphdr); i < tcp->doff * 4; ) {
+ if ((opt[i] == TCPOPT_MSS)
+ && ((tcp->doff * 4 - i) >= TCPOLEN_MSS)
+ && (opt[i+1] == TCPOLEN_MSS)) {
+ u_int16_t mssval;
+
+ mssval = (opt[i+2] << 8) | opt[i+3];
+
+ return (mssval >= min && mssval <= max) ^ invert;
+ }
+ if (opt[i] < 2) i++;
+ else i += opt[i+1]?:1;
+ }
+
+ return invert;
+}
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ const struct ipt_tcpmss_match_info *info = matchinfo;
+ const struct tcphdr *tcph = (void *)skb->nh.iph + skb->nh.iph->ihl*4;
+
+ return mssoption_match(info->mss_min, info->mss_max, tcph,
+ skb->len - skb->nh.iph->ihl*4,
+ info->invert, hotdrop);
+}
+
+static inline int find_syn_match(const struct ipt_entry_match *m)
+{
+ const struct ipt_tcp *tcpinfo = (const struct ipt_tcp *)m->data;
+
+ if (strcmp(m->u.kernel.match->name, "tcp") == 0
+ && (tcpinfo->flg_cmp & TH_SYN)
+ && !(tcpinfo->invflags & IPT_TCP_INV_FLAGS))
+ return 1;
+
+ return 0;
+}
+
+static int
+checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_tcpmss_match_info)))
+ return 0;
+
+ /* Must specify -p tcp */
+ if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
+ printk("tcpmss: Only works on TCP packets\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ipt_match tcpmss_match
+= { { NULL, NULL }, "tcpmss", &match, &checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ return ipt_register_match(&tcpmss_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&tcpmss_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 68d536e10..25f0b0c1e 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -1,7 +1,7 @@
/*
* sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem.
*
- * $Id: sysctl_net_ipv4.c,v 1.47 2000/10/19 15:51:02 davem Exp $
+ * $Id: sysctl_net_ipv4.c,v 1.48 2001/02/23 01:39:05 davem Exp $
*
* Begun April 1, 1996, Mike Shaver.
* Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS]
@@ -47,10 +47,11 @@ extern int inet_peer_maxttl;
extern int inet_peer_gc_mintime;
extern int inet_peer_gc_maxtime;
+#ifdef CONFIG_SYSCTL
static int tcp_retr1_max = 255;
-
static int ip_local_port_range_min[] = { 1, 1 };
static int ip_local_port_range_max[] = { 65535, 65535 };
+#endif
struct ipv4_config ipv4_config;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 49fc32f59..28180240b 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: ip6_fib.c,v 1.22 2000/09/12 00:38:34 davem Exp $
+ * $Id: ip6_fib.c,v 1.23 2001/03/19 20:31:17 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -76,7 +76,7 @@ rwlock_t fib6_walker_lock = RW_LOCK_UNLOCKED;
#endif
static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt);
-static void fib6_repair_tree(struct fib6_node *fn);
+static struct fib6_node * fib6_repair_tree(struct fib6_node *fn);
/*
* A routing update causes an increase of the serial number on the
@@ -774,7 +774,7 @@ static struct rt6_info * fib6_find_prefix(struct fib6_node *fn)
* is the node we want to try and remove.
*/
-static void fib6_repair_tree(struct fib6_node *fn)
+static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
{
int children;
int nstate;
@@ -809,7 +809,7 @@ static void fib6_repair_tree(struct fib6_node *fn)
}
#endif
atomic_inc(&fn->leaf->rt6i_ref);
- return;
+ return fn->parent;
}
pn = fn->parent;
@@ -865,7 +865,7 @@ static void fib6_repair_tree(struct fib6_node *fn)
node_free(fn);
if (pn->fn_flags&RTN_RTINFO || SUBTREE(pn))
- return;
+ return pn;
rt6_release(pn->leaf);
pn->leaf = NULL;
@@ -903,7 +903,26 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp)
if (fn->leaf == NULL) {
fn->fn_flags &= ~RTN_RTINFO;
rt6_stats.fib_route_nodes--;
- fib6_repair_tree(fn);
+ fn = fib6_repair_tree(fn);
+ }
+
+ if (atomic_read(&rt->rt6i_ref) != 1) {
+ /* This route is used as dummy address holder in some split
+ * nodes. It is not leaked, but it still holds other resources,
+ * which must be released in time. So, scan ascendant nodes
+ * and replace dummy references to this route with references
+ * to still alive ones.
+ */
+ while (fn) {
+ if (!(fn->fn_flags&RTN_RTINFO) && fn->leaf == rt) {
+ fn->leaf = fib6_find_prefix(fn);
+ atomic_inc(&fn->leaf->rt6i_ref);
+ rt6_release(rt);
+ }
+ fn = fn->parent;
+ }
+ /* No more references are possiible at this point. */
+ if (atomic_read(&rt->rt6i_ref) != 1) BUG();
}
#ifdef CONFIG_RTNETLINK
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index e93799a37..2332f7549 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -7,7 +7,7 @@
*
* Based on linux/net/ipv4/ip_sockglue.c
*
- * $Id: ipv6_sockglue.c,v 1.34 2000/11/28 13:44:28 davem Exp $
+ * $Id: ipv6_sockglue.c,v 1.36 2001/02/26 05:59:07 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -253,6 +253,13 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
if (optlen == 0)
goto update;
+ /* 1K is probably excessive
+ * 1K is surely not enough, 2K per standard header is 16K.
+ */
+ retv = -EINVAL;
+ if (optlen > 64*1024)
+ break;
+
opt = sock_kmalloc(sk, sizeof(*opt) + optlen, GFP_KERNEL);
retv = -ENOBUFS;
if (opt == NULL)
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 0529aa480..10ab39e04 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -203,18 +203,17 @@ static void ip6_evictor(void)
if (ip6_frag_hash[i] == NULL)
continue;
- write_lock(&ip6_frag_lock);
+ read_lock(&ip6_frag_lock);
if ((fq = ip6_frag_hash[i]) != NULL) {
/* find the oldest queue for this hash bucket */
while (fq->next)
fq = fq->next;
- __fq_unlink(fq);
- write_unlock(&ip6_frag_lock);
+ atomic_inc(&fq->refcnt);
+ read_unlock(&ip6_frag_lock);
spin_lock(&fq->lock);
- if (del_timer(&fq->timer))
- atomic_dec(&fq->refcnt);
- fq->last_in |= COMPLETE;
+ if (!(fq->last_in&COMPLETE))
+ fq_kill(fq);
spin_unlock(&fq->lock);
fq_put(fq);
@@ -222,7 +221,7 @@ static void ip6_evictor(void)
progress = 1;
continue;
}
- write_unlock(&ip6_frag_lock);
+ read_unlock(&ip6_frag_lock);
}
} while (progress);
}
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 8f452acc1..3bbfcca17 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -421,7 +421,7 @@ static int tcp_v6_check_established(struct sock *sk)
struct sock *sk2, **skp;
struct tcp_tw_bucket *tw;
- write_lock(&head->lock);
+ write_lock_bh(&head->lock);
for(skp = &(head + tcp_ehash_size)->chain; (sk2=*skp)!=NULL; skp = &sk2->next) {
tw = (struct tcp_tw_bucket*)sk2;
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 0d0e6e00f..83406e85c 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -65,6 +65,12 @@
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>,
* December, 2000
* Revision 044: Call ipxitf_hold on NETDEV_UP (acme)
+ * Revision 045: fix PPROP routing bug (acme)
+ * Revision 046: Further fixes to PPROP, ipxitf_create_internal was
+ * doing an unneeded MOD_INC_USE_COUNT, implement
+ * sysctl for ipx_pprop_broacasting, fix the ipx sysctl
+ * handling, making it dynamic, some cleanups, thanks to
+ * Petr Vandrovec for review and good suggestions. (acme)
*
* Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT
* pair. Also, now usage count is managed this way
@@ -81,7 +87,6 @@
*/
#include <linux/config.h>
-#if defined (CONFIG_IPX) || defined (CONFIG_IPX_MODULE)
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
@@ -111,14 +116,14 @@
#include <linux/init.h>
#include <linux/if_arp.h>
-#ifdef MODULE
-static void ipx_proto_finito(void);
-#endif /* def MODULE */
+extern void ipx_register_sysctl(void);
+extern void ipx_unregister_sysctl(void);
/* Configuration Variables */
static unsigned char ipxcfg_max_hops = 16;
static char ipxcfg_auto_select_primary;
static char ipxcfg_auto_create_interfaces;
+static int sysctl_ipx_pprop_broadcasting = 1;
/* Global Variables */
static struct datalink_proto *p8022_datalink;
@@ -139,6 +144,8 @@ static spinlock_t ipx_interfaces_lock = SPIN_LOCK_UNLOCKED;
static ipx_interface *ipx_primary_net;
static ipx_interface *ipx_internal_net;
+#define IPX_SKB_CB(__skb) ((struct ipx_cb *)&((__skb)->cb[0]))
+
#undef IPX_REFCNT_DEBUG
#ifdef IPX_REFCNT_DEBUG
atomic_t ipx_sock_nr;
@@ -450,11 +457,12 @@ static int ipxitf_device_event(struct notifier_block *notifier,
spin_lock_bh(&ipx_interfaces_lock);
for (i = ipx_interfaces; i;) {
tmp = i->if_next;
- if (i->if_dev == dev)
+ if (i->if_dev == dev) {
if (event == NETDEV_UP)
ipxitf_hold(i);
else
__ipxitf_put(i);
+ }
i = tmp;
}
spin_unlock_bh(&ipx_interfaces_lock);
@@ -674,17 +682,30 @@ static struct sk_buff *ipxitf_adjust_skbuff(ipx_interface *intrfc,
return skb2;
}
-/* caller must hold a reference to intrfc */
+/* caller must hold a reference to intrfc and the skb has to be unshared */
static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
{
struct ipxhdr *ipx = skb->nh.ipxh;
- struct ipx_cb *cb = (struct ipx_cb *) skb->cb;
struct net_device *dev = intrfc->if_dev;
struct datalink_proto *dl = intrfc->if_dlink;
char dest_node[IPX_NODE_LEN];
int send_to_wire = 1;
int addr_len;
+
+ ipx->ipx_tctrl = IPX_SKB_CB(skb)->ipx_tctrl;
+ ipx->ipx_dest.net = IPX_SKB_CB(skb)->ipx_dest_net;
+ ipx->ipx_source.net = IPX_SKB_CB(skb)->ipx_source_net;
+
+ /* see if we need to include the netnum in the route list */
+ if (IPX_SKB_CB(skb)->last_hop.index >= 0) {
+ u32 *last_hop = (u32 *)(((u8 *) skb->data) +
+ sizeof(struct ipxhdr) +
+ IPX_SKB_CB(skb)->last_hop.index *
+ sizeof(u32));
+ *last_hop = IPX_SKB_CB(skb)->last_hop.netnum;
+ IPX_SKB_CB(skb)->last_hop.index = -1;
+ }
/*
* We need to know how many skbuffs it will take to send out this
@@ -701,7 +722,7 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
* up clones.
*/
- if (cb->ipx_dest_net == intrfc->if_netnum) {
+ if (ipx->ipx_dest.net == intrfc->if_netnum) {
/*
* To our own node, loop and free the original.
* The internal net will receive on all node address.
@@ -730,7 +751,7 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
* We are still charging the sender. Which is right - the driver
* free will handle this fairly.
*/
- if (cb->ipx_source_net != intrfc->if_netnum) {
+ if (ipx->ipx_source.net != intrfc->if_netnum) {
/*
* Unshare the buffer before modifying the count in
* case its a flood or tcpdump
@@ -738,7 +759,7 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
skb = skb_unshare(skb, GFP_ATOMIC);
if (!skb)
return 0;
- if (++(cb->ipx_tctrl) > ipxcfg_max_hops)
+ if (++ipx->ipx_tctrl > ipxcfg_max_hops)
send_to_wire = 0;
}
@@ -759,17 +780,6 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
if (!skb)
return 0;
- ipx->ipx_tctrl = cb->ipx_tctrl;
- ipx->ipx_dest.net = cb->ipx_dest_net;
- ipx->ipx_source.net = cb->ipx_source_net;
- /* see if we need to include the netnum in the route list */
- if (cb->last_hop_index >= 0) {
- u32 *last_hop = (u32 *)(((u8 *) skb->data) +
- sizeof(struct ipxhdr) + cb->last_hop_index *
- sizeof(u32));
- *last_hop = intrfc->if_netnum;
- }
-
/* set up data link and physical headers */
skb->dev = dev;
skb->protocol = htons(ETH_P_IPX);
@@ -789,93 +799,40 @@ static int ipxitf_add_local_route(ipx_interface *intrfc)
static const char * ipx_frame_name(unsigned short);
static const char * ipx_device_name(ipx_interface *);
+static void ipxitf_discover_netnum(ipx_interface *intrfc, struct sk_buff *skb);
+static int ipxitf_pprop(ipx_interface *intrfc, struct sk_buff *skb);
static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
{
struct ipxhdr *ipx = skb->nh.ipxh;
- struct ipx_cb *cb = (struct ipx_cb *) skb->cb;
int ret = 0;
ipxitf_hold(intrfc);
/* See if we should update our network number */
- if (!intrfc->if_netnum && /* net number of intrfc not known yet */
- cb->ipx_source_net == cb->ipx_dest_net && /* intra packet */
- cb->ipx_source_net) {
- ipx_interface *i = ipxitf_find_using_net(cb->ipx_source_net);
- /* NB: NetWare servers lie about their hop count so we
- * dropped the test based on it. This is the best way
- * to determine this is a 0 hop count packet.
- */
- if (!i) {
- intrfc->if_netnum = cb->ipx_source_net;
- ipxitf_add_local_route(intrfc);
- } else {
- printk(KERN_WARNING "IPX: Network number collision %lx\n %s %s and %s %s\n",
- (long unsigned int) htonl(cb->ipx_source_net),
- ipx_device_name(i),
- ipx_frame_name(i->if_dlink_type),
- ipx_device_name(intrfc),
- ipx_frame_name(intrfc->if_dlink_type));
- ipxitf_put(i);
- }
- }
+ if (!intrfc->if_netnum) /* net number of intrfc not known yet */
+ ipxitf_discover_netnum(intrfc, skb);
- cb->last_hop_index = -1;
-
- if (ipx->ipx_type == IPX_TYPE_PPROP && cb->ipx_tctrl < 8 &&
- skb->pkt_type != PACKET_OTHERHOST &&
- /* header + 8 network numbers */
- ntohs(ipx->ipx_pktsize) >= sizeof(struct ipxhdr) + 8 * 4) {
- int i;
- ipx_interface *ifcs;
- struct sk_buff *skb2;
- char *c = ((char *) skb->data) + sizeof(struct ipxhdr);
- u32 *l = (u32 *) c;
-
- /* Dump packet if already seen this net */
- for (i = 0; i < cb->ipx_tctrl; i++)
- if (*l++ == intrfc->if_netnum)
- break;
-
- if (i == cb->ipx_tctrl) {
- /* < 8 hops && input itfc not in list */
- /* insert recvd netnum into list */
- cb->last_hop_index = i;
- cb->ipx_tctrl++;
- /* xmit on all other interfaces... */
- spin_lock_bh(&ipx_interfaces_lock);
- for (ifcs = ipx_interfaces; ifcs;
- ifcs = ifcs->if_next) {
- /* Except unconfigured interfaces */
- if (!ifcs->if_netnum)
- continue;
-
- /* That aren't in the list */
- l = (__u32 *) c;
- for (i = 0; i <= cb->ipx_tctrl; i++)
- if (ifcs->if_netnum == *l++)
- break;
- if (i - 1 == cb->ipx_tctrl) {
- cb->ipx_dest_net = ifcs->if_netnum;
- skb2=skb_clone(skb, GFP_ATOMIC);
- if (skb2)
- ipxrtr_route_skb(skb2);
- }
- }
- spin_unlock_bh(&ipx_interfaces_lock);
- }
+ IPX_SKB_CB(skb)->last_hop.index = -1;
+ if (ipx->ipx_type == IPX_TYPE_PPROP) {
+ ret = ipxitf_pprop(intrfc, skb);
+ if (ret)
+ goto out_free_skb;
}
- if (!cb->ipx_dest_net)
- cb->ipx_dest_net = intrfc->if_netnum;
- if (!cb->ipx_source_net)
- cb->ipx_source_net = intrfc->if_netnum;
+ /* local processing follows */
+ if (!IPX_SKB_CB(skb)->ipx_dest_net)
+ IPX_SKB_CB(skb)->ipx_dest_net = intrfc->if_netnum;
+ if (!IPX_SKB_CB(skb)->ipx_source_net)
+ IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum;
- if (intrfc->if_netnum != cb->ipx_dest_net) {
+ /* it doesn't make sense to route a pprop packet, there's no meaning
+ * in the ipx_dest_net for such packets */
+ if (ipx->ipx_type != IPX_TYPE_PPROP &&
+ intrfc->if_netnum != IPX_SKB_CB(skb)->ipx_dest_net) {
/* We only route point-to-point packets. */
if (skb->pkt_type == PACKET_HOST) {
- skb=skb_unshare(skb, GFP_ATOMIC);
+ skb = skb_unshare(skb, GFP_ATOMIC);
if (skb)
ret = ipxrtr_route_skb(skb);
goto out_intrfc;
@@ -899,6 +856,124 @@ out_intrfc:
return ret;
}
+static void ipxitf_discover_netnum(ipx_interface *intrfc, struct sk_buff *skb)
+{
+ const struct ipx_cb *cb = IPX_SKB_CB(skb);
+
+ /* see if this is an intra packet: source_net == dest_net */
+ if (cb->ipx_source_net == cb->ipx_dest_net && cb->ipx_source_net) {
+ ipx_interface *i = ipxitf_find_using_net(cb->ipx_source_net);
+ /* NB: NetWare servers lie about their hop count so we
+ * dropped the test based on it. This is the best way
+ * to determine this is a 0 hop count packet. */
+ if (!i) {
+ intrfc->if_netnum = cb->ipx_source_net;
+ ipxitf_add_local_route(intrfc);
+ } else {
+ printk(KERN_WARNING "IPX: Network number collision "
+ "%lx\n %s %s and %s %s\n",
+ (unsigned long) htonl(cb->ipx_source_net),
+ ipx_device_name(i),
+ ipx_frame_name(i->if_dlink_type),
+ ipx_device_name(intrfc),
+ ipx_frame_name(intrfc->if_dlink_type));
+ ipxitf_put(i);
+ }
+ }
+}
+
+/**
+ * ipxitf_pprop - Process packet propagation IPX packet type 0x14, used for
+ * NetBIOS broadcasts
+ * @intrfc: IPX interface receiving this packet
+ * @skb: Received packet
+ *
+ * Checks if packet is valid: if its more than %IPX_MAX_PPROP_HOPS hops or if it
+ * is smaller than a IPX header + the room for %IPX_MAX_PPROP_HOPS hops we drop
+ * it, not even processing it locally, if it has exact %IPX_MAX_PPROP_HOPS we
+ * don't broadcast it, but process it locally. See chapter 5 of Novell's "IPX
+ * RIP and SAP Router Specification", Part Number 107-000029-001.
+ *
+ * If it is valid, check if we have pprop broadcasting enabled by the user,
+ * if not, just return zero for local processing.
+ *
+ * If it is enabled check the packet and don't broadcast it if we have already
+ * seen this packet.
+ *
+ * Broadcast: send it to the interfaces that aren't on the packet visited nets
+ * array, just after the IPX header.
+ *
+ * Returns -EINVAL for invalid packets, so that the calling function drops
+ * the packet without local processing. 0 if packet is to be locally processed.
+ */
+static int ipxitf_pprop(ipx_interface *intrfc, struct sk_buff *skb)
+{
+ struct ipxhdr *ipx = skb->nh.ipxh;
+ int i, ret = -EINVAL;
+ ipx_interface *ifcs;
+ char *c;
+ u32 *l;
+
+ /* Illegal packet - too many hops or too short */
+ /* We decide to throw it away: no broadcasting, no local processing.
+ * NetBIOS unaware implementations route them as normal packets -
+ * tctrl <= 15, any data payload... */
+ if (IPX_SKB_CB(skb)->ipx_tctrl > IPX_MAX_PPROP_HOPS ||
+ ntohs(ipx->ipx_pktsize) < sizeof(struct ipxhdr) +
+ IPX_MAX_PPROP_HOPS * sizeof(u32))
+ goto out;
+ /* are we broadcasting this damn thing? */
+ ret = 0;
+ if (!sysctl_ipx_pprop_broadcasting)
+ goto out;
+ /* We do broadcast packet on the IPX_MAX_PPROP_HOPS hop, but we
+ * process it locally. All previous hops broadcasted it, and process it
+ * locally. */
+ if (IPX_SKB_CB(skb)->ipx_tctrl == IPX_MAX_PPROP_HOPS)
+ goto out;
+
+ c = ((u8 *) ipx) + sizeof(struct ipxhdr);
+ l = (u32 *) c;
+
+ /* Don't broadcast packet if already seen this net */
+ for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++)
+ if (*l++ == intrfc->if_netnum)
+ goto out;
+
+ /* < IPX_MAX_PPROP_HOPS hops && input interface not in list. Save the
+ * position where we will insert recvd netnum into list, later on,
+ * in ipxitf_send */
+ IPX_SKB_CB(skb)->last_hop.index = i;
+ IPX_SKB_CB(skb)->last_hop.netnum = intrfc->if_netnum;
+ /* xmit on all other interfaces... */
+ spin_lock_bh(&ipx_interfaces_lock);
+ for (ifcs = ipx_interfaces; ifcs; ifcs = ifcs->if_next) {
+ /* Except unconfigured interfaces */
+ if (!ifcs->if_netnum)
+ continue;
+
+ /* That aren't in the list */
+ if (ifcs == intrfc)
+ continue;
+ l = (__u32 *) c;
+ /* don't consider the last entry in the packet list,
+ * it is our netnum, and it is not there yet */
+ for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++)
+ if (ifcs->if_netnum == *l++)
+ break;
+ if (i == IPX_SKB_CB(skb)->ipx_tctrl) {
+ struct sk_buff *s = skb_copy(skb, GFP_ATOMIC);
+
+ if (s) {
+ IPX_SKB_CB(s)->ipx_dest_net = ifcs->if_netnum;
+ ipxrtr_route_skb(s);
+ }
+ }
+ }
+ spin_unlock_bh(&ipx_interfaces_lock);
+out: return ret;
+}
+
static void ipxitf_insert(ipx_interface *intrfc)
{
ipx_interface *i;
@@ -918,6 +993,30 @@ static void ipxitf_insert(ipx_interface *intrfc)
ipx_primary_net = intrfc;
}
+static ipx_interface *ipxitf_alloc(struct net_device *dev, __u32 netnum,
+ unsigned short dlink_type,
+ struct datalink_proto *dlink,
+ unsigned char internal, int ipx_offset)
+{
+ ipx_interface *intrfc = kmalloc(sizeof(ipx_interface), GFP_ATOMIC);
+
+ if (intrfc) {
+ intrfc->if_dev = dev;
+ intrfc->if_netnum = netnum;
+ intrfc->if_dlink_type = dlink_type;
+ intrfc->if_dlink = dlink;
+ intrfc->if_internal = internal;
+ intrfc->if_ipx_offset = ipx_offset;
+ intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET;
+ intrfc->if_sklist = NULL;
+ atomic_set(&intrfc->refcnt, 1);
+ spin_lock_init(&intrfc->if_sklist_lock);
+ MOD_INC_USE_COUNT;
+ }
+
+ return intrfc;
+}
+
static int ipxitf_create_internal(ipx_interface_definition *idef)
{
ipx_interface *intrfc;
@@ -935,23 +1034,11 @@ static int ipxitf_create_internal(ipx_interface_definition *idef)
ipxitf_put(intrfc);
return -EADDRINUSE;
}
-
- intrfc = kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
+ intrfc = ipxitf_alloc(NULL, idef->ipx_network, 0, NULL, 1, 0);
if (!intrfc)
return -EAGAIN;
- intrfc->if_dev = NULL;
- intrfc->if_netnum = idef->ipx_network;
- intrfc->if_dlink_type = 0;
- intrfc->if_dlink = NULL;
- intrfc->if_sklist = NULL;
- intrfc->if_internal = 1;
- intrfc->if_ipx_offset = 0;
- intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET;
memcpy((char *)&(intrfc->if_node), idef->ipx_node, IPX_NODE_LEN);
ipx_internal_net = ipx_primary_net = intrfc;
- spin_lock_init(&intrfc->if_sklist_lock);
- atomic_set(&intrfc->refcnt, 1);
- MOD_INC_USE_COUNT;
ipxitf_hold(intrfc);
ipxitf_insert(intrfc);
@@ -1040,7 +1127,8 @@ static int ipxitf_create(ipx_interface_definition *idef)
case IPX_FRAME_NONE:
default:
- break;
+ err = -EPROTONOSUPPORT;
+ goto out_dev;
}
err = -ENETDOWN;
@@ -1052,28 +1140,18 @@ static int ipxitf_create(ipx_interface_definition *idef)
if (dev->addr_len > IPX_NODE_LEN)
goto out_dev;
- err = -EPROTONOSUPPORT;
- if (!datalink)
- goto out_dev;
-
intrfc = ipxitf_find_using_phys(dev, dlink_type);
if (!intrfc) {
/* Ok now create */
- intrfc = kmalloc(sizeof(ipx_interface), GFP_ATOMIC);
+ intrfc = ipxitf_alloc(dev, idef->ipx_network, dlink_type,
+ datalink, 0, dev->hard_header_len +
+ datalink->header_length);
err = -EAGAIN;
if (!intrfc)
goto out_dev;
- intrfc->if_dev = dev;
- intrfc->if_netnum = idef->ipx_network;
- intrfc->if_dlink_type = dlink_type;
- intrfc->if_dlink = datalink;
- intrfc->if_sklist = NULL;
- intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET;
/* Setup primary if necessary */
if (idef->ipx_special == IPX_PRIMARY)
ipx_primary_net = intrfc;
- intrfc->if_internal = 0;
- intrfc->if_ipx_offset = dev->hard_header_len + datalink->header_length;
if (!memcmp(idef->ipx_node, "\000\000\000\000\000\000",
IPX_NODE_LEN)) {
memset(intrfc->if_node, 0, IPX_NODE_LEN);
@@ -1081,9 +1159,6 @@ static int ipxitf_create(ipx_interface_definition *idef)
dev->dev_addr, dev->addr_len);
} else
memcpy(intrfc->if_node, idef->ipx_node, IPX_NODE_LEN);
- spin_lock_init(&intrfc->if_sklist_lock);
- atomic_set(&intrfc->refcnt, 1);
- MOD_INC_USE_COUNT;
ipxitf_hold(intrfc);
ipxitf_insert(intrfc);
}
@@ -1145,8 +1220,15 @@ out: spin_unlock_bh(&ipx_interfaces_lock);
static ipx_interface *ipxitf_auto_create(struct net_device *dev,
unsigned short dlink_type)
{
- struct datalink_proto *datalink = NULL;
- ipx_interface *intrfc;
+ ipx_interface *intrfc = NULL;
+ struct datalink_proto *datalink;
+
+ if (!dev)
+ goto out;
+
+ /* Check addresses are suitable */
+ if (dev->addr_len > IPX_NODE_LEN)
+ goto out;
switch (htons(dlink_type)) {
case ETH_P_IPX:
@@ -1166,38 +1248,23 @@ static ipx_interface *ipxitf_auto_create(struct net_device *dev,
break;
default:
- return NULL;
+ goto out;
}
- if (!dev)
- return NULL;
-
- /* Check addresses are suitable */
- if (dev->addr_len > IPX_NODE_LEN)
- return NULL;
+ intrfc = ipxitf_alloc(dev, 0, dlink_type, datalink, 0,
+ dev->hard_header_len + datalink->header_length);
- intrfc = kmalloc(sizeof(ipx_interface), GFP_ATOMIC);
if (intrfc) {
- intrfc->if_dev = dev;
- intrfc->if_netnum = 0;
- intrfc->if_dlink_type = dlink_type;
- intrfc->if_dlink = datalink;
- intrfc->if_sklist = NULL;
- intrfc->if_internal = 0;
- intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET;
- intrfc->if_ipx_offset = dev->hard_header_len +
- datalink->header_length;
memset(intrfc->if_node, 0, IPX_NODE_LEN);
memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
dev->dev_addr, dev->addr_len);
spin_lock_init(&intrfc->if_sklist_lock);
atomic_set(&intrfc->refcnt, 1);
- MOD_INC_USE_COUNT;
ipxitf_insert(intrfc);
dev_hold(dev);
}
- return intrfc;
+out: return intrfc;
}
static int ipxitf_ioctl(unsigned int cmd, void *arg)
@@ -1283,6 +1350,17 @@ static int ipxitf_ioctl(unsigned int cmd, void *arg)
* *
\**************************************************************************/
+static inline void ipxrtr_hold(ipx_route *rt)
+{
+ atomic_inc(&rt->refcnt);
+}
+
+static inline void ipxrtr_put(ipx_route *rt)
+{
+ if (atomic_dec_and_test(&rt->refcnt))
+ kfree(rt);
+}
+
static ipx_route *ipxrtr_lookup(__u32 net)
{
ipx_route *r;
@@ -1290,6 +1368,8 @@ static ipx_route *ipxrtr_lookup(__u32 net)
read_lock_bh(&ipx_routes_lock);
for (r = ipx_routes; r && r->ir_net != net; r = r->ir_next)
;
+ if (r)
+ ipxrtr_hold(r);
read_unlock_bh(&ipx_routes_lock);
return r;
@@ -1300,21 +1380,27 @@ static ipx_route *ipxrtr_lookup(__u32 net)
static int ipxrtr_add_route(__u32 network, ipx_interface *intrfc, unsigned char *node)
{
ipx_route *rt;
+ int ret;
/* Get a route structure; either existing or create */
rt = ipxrtr_lookup(network);
if (!rt) {
rt = kmalloc(sizeof(ipx_route),GFP_ATOMIC);
+ ret = -EAGAIN;
if (!rt)
- return -EAGAIN;
+ goto out;
+ atomic_set(&rt->refcnt, 1);
+ ipxrtr_hold(rt);
write_lock_bh(&ipx_routes_lock);
rt->ir_next = ipx_routes;
ipx_routes = rt;
write_unlock_bh(&ipx_routes_lock);
+ } else {
+ ret = -EEXIST;
+ if (intrfc == ipx_internal_net)
+ goto out_put;
}
- else if (intrfc == ipx_internal_net)
- return -EEXIST;
rt->ir_net = network;
rt->ir_intrfc = intrfc;
@@ -1326,7 +1412,10 @@ static int ipxrtr_add_route(__u32 network, ipx_interface *intrfc, unsigned char
rt->ir_routed = 1;
}
- return 0;
+ ret = 0;
+out_put:
+ ipxrtr_put(rt);
+out: return ret;
}
static void ipxrtr_del_routes(ipx_interface *intrfc)
@@ -1337,7 +1426,7 @@ static void ipxrtr_del_routes(ipx_interface *intrfc)
for (r = &ipx_routes; (tmp = *r) != NULL;) {
if (tmp->ir_intrfc == intrfc) {
*r = tmp->ir_next;
- kfree(tmp);
+ ipxrtr_put(tmp);
} else
r = &(tmp->ir_next);
}
@@ -1373,7 +1462,7 @@ static int ipxrtr_delete(long net)
goto out;
*r = tmp->ir_next;
- kfree(tmp);
+ ipxrtr_put(tmp);
err = 0;
goto out;
}
@@ -1432,7 +1521,6 @@ static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, stru
struct sk_buff *skb;
ipx_interface *intrfc;
struct ipxhdr *ipx;
- struct ipx_cb *cb;
int size;
int ipx_offset;
ipx_route *rt = NULL;
@@ -1444,9 +1532,9 @@ static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, stru
intrfc = ipx_primary_net;
} else {
rt = ipxrtr_lookup(usipx->sipx_network);
+ err = -ENETUNREACH;
if (!rt)
- return -ENETUNREACH;
-
+ goto out;
intrfc = rt->ir_intrfc;
}
@@ -1456,45 +1544,44 @@ static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, stru
skb = sock_alloc_send_skb(sk, size, 0, noblock, &err);
if (!skb)
- goto out;
+ goto out_put;
skb_reserve(skb,ipx_offset);
skb->sk = sk;
- cb = (struct ipx_cb *) skb->cb;
/* Fill in IPX header */
ipx = (struct ipxhdr *)skb_put(skb, sizeof(struct ipxhdr));
ipx->ipx_pktsize= htons(len + sizeof(struct ipxhdr));
- cb->ipx_tctrl = 0;
+ IPX_SKB_CB(skb)->ipx_tctrl = 0;
ipx->ipx_type = usipx->sipx_type;
skb->h.raw = (void *)skb->nh.ipxh = ipx;
- cb->last_hop_index = -1;
-
+ IPX_SKB_CB(skb)->last_hop.index = -1;
#ifdef CONFIG_IPX_INTERN
- cb->ipx_source_net = sk->protinfo.af_ipx.intrfc->if_netnum;
+ IPX_SKB_CB(skb)->ipx_source_net = sk->protinfo.af_ipx.intrfc->if_netnum;
memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.node, IPX_NODE_LEN);
#else
err = ntohs(sk->protinfo.af_ipx.port);
if (err == 0x453 || err == 0x452) {
/* RIP/SAP special handling for mars_nwe */
- cb->ipx_source_net = intrfc->if_netnum;
+ IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum;
memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN);
} else {
- cb->ipx_source_net = sk->protinfo.af_ipx.intrfc->if_netnum;
+ IPX_SKB_CB(skb)->ipx_source_net =
+ sk->protinfo.af_ipx.intrfc->if_netnum;
memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);
}
#endif /* CONFIG_IPX_INTERN */
ipx->ipx_source.sock = sk->protinfo.af_ipx.port;
- cb->ipx_dest_net = usipx->sipx_network;
+ IPX_SKB_CB(skb)->ipx_dest_net = usipx->sipx_network;
memcpy(ipx->ipx_dest.node,usipx->sipx_node,IPX_NODE_LEN);
ipx->ipx_dest.sock = usipx->sipx_port;
err = memcpy_fromiovec(skb_put(skb,len),iov,len);
if (err) {
kfree_skb(skb);
- goto out;
+ goto out_put;
}
/* Apply checksum. Not allowed on 802.3 links. */
@@ -1505,15 +1592,19 @@ static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, stru
err = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ?
rt->ir_router_node : ipx->ipx_dest.node);
-out: ipxitf_put(intrfc);
- return err;
+out_put:
+ ipxitf_put(intrfc);
+ if (rt)
+ ipxrtr_put(rt);
+out: return err;
}
-
+
+/* the skb has to be unshared, we'll end up calling ipxitf_send, that'll
+ * modify the packet */
int ipxrtr_route_skb(struct sk_buff *skb)
{
struct ipxhdr *ipx = skb->nh.ipxh;
- struct ipx_cb *cb = (struct ipx_cb *) skb->cb;
- ipx_route *r = ipxrtr_lookup(cb->ipx_dest_net);
+ ipx_route *r = ipxrtr_lookup(IPX_SKB_CB(skb)->ipx_dest_net);
if (!r) { /* no known route */
kfree_skb(skb);
@@ -1524,6 +1615,7 @@ int ipxrtr_route_skb(struct sk_buff *skb)
ipxitf_send(r->ir_intrfc, skb, (r->ir_routed) ?
r->ir_router_node : ipx->ipx_dest.node);
ipxitf_put(r->ir_intrfc);
+ ipxrtr_put(r);
return 0;
}
@@ -2033,6 +2125,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
{
struct sock *sk = sock->sk;
struct sockaddr_ipx *addr;
+ ipx_route *rt;
sk->state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
@@ -2064,8 +2157,8 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
/* We can either connect to primary network or somewhere
* we can route to */
- if (!(!addr->sipx_network && ipx_primary_net) &&
- !ipxrtr_lookup(addr->sipx_network))
+ rt = ipxrtr_lookup(addr->sipx_network);
+ if (!rt && !(!addr->sipx_network && ipx_primary_net))
return -ENETUNREACH;
sk->protinfo.af_ipx.dest_addr.net = addr->sipx_network;
@@ -2079,6 +2172,8 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
sk->state = TCP_ESTABLISHED;
}
+ if (rt)
+ ipxrtr_put(rt);
return 0;
}
@@ -2129,7 +2224,6 @@ int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
/* NULL here for pt means the packet was looped back */
ipx_interface *intrfc;
struct ipxhdr *ipx;
- struct ipx_cb *cb;
u16 ipx_pktsize;
int ret;
@@ -2151,21 +2245,22 @@ int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize))
goto drop;
- cb = (struct ipx_cb *) skb->cb;
- cb->ipx_tctrl = ipx->ipx_tctrl;
- cb->ipx_dest_net = ipx->ipx_dest.net;
- cb->ipx_source_net = ipx->ipx_source.net;
+ IPX_SKB_CB(skb)->ipx_tctrl = ipx->ipx_tctrl;
+ IPX_SKB_CB(skb)->ipx_dest_net = ipx->ipx_dest.net;
+ IPX_SKB_CB(skb)->ipx_source_net = ipx->ipx_source.net;
/* Determine what local ipx endpoint this is */
intrfc = ipxitf_find_using_phys(dev, pt->type);
if (!intrfc) {
if (ipxcfg_auto_create_interfaces &&
- ntohl(cb->ipx_dest_net)) {
+ ntohl(IPX_SKB_CB(skb)->ipx_dest_net)) {
intrfc = ipxitf_auto_create(dev, pt->type);
- ipxitf_hold(intrfc);
+ if (intrfc)
+ ipxitf_hold(intrfc);
}
if (!intrfc) /* Not one of ours */
+ /* or invalid packet for auto creation */
goto drop;
}
@@ -2290,11 +2385,10 @@ static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size,
msg->msg_namelen = sizeof(*sipx);
if (sipx) {
- struct ipx_cb *cb = (struct ipx_cb *) skb->cb;
sipx->sipx_family = AF_IPX;
sipx->sipx_port = ipx->ipx_source.sock;
memcpy(sipx->sipx_node,ipx->ipx_source.node,IPX_NODE_LEN);
- sipx->sipx_network = cb->ipx_source_net;
+ sipx->sipx_network = IPX_SKB_CB(skb)->ipx_source_net;
sipx->sipx_type = ipx->ipx_type;
}
err = copied;
@@ -2469,6 +2563,10 @@ extern void destroy_8023_client(struct datalink_proto *);
static unsigned char ipx_8022_type = 0xE0;
static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
+static const char banner[] __initdata =
+ KERN_INFO "NET4: Linux IPX 0.46 for NET4.0\n"
+ KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n" \
+ KERN_INFO "IPX Portions Copyright (c) 2000, 2001 Conectiva, Inc.\n";
static int __init ipx_init(void)
{
@@ -2489,14 +2587,13 @@ static int __init ipx_init(void)
printk(KERN_CRIT "IPX: Unable to register with SNAP\n");
register_netdevice_notifier(&ipx_dev_notifier);
+ ipx_register_sysctl();
#ifdef CONFIG_PROC_FS
proc_net_create("ipx", 0, ipx_get_info);
proc_net_create("ipx_interface", 0, ipx_interface_get_info);
proc_net_create("ipx_route", 0, ipx_rt_get_info);
#endif
- printk(KERN_INFO "NET4: Linux IPX 0.44 for NET4.0\n");
- printk(KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
- printk(KERN_INFO "IPX Portions Copyright (c) 2000 Conectiva, Inc.\n");
+ printk(banner);
return 0;
}
@@ -2506,8 +2603,13 @@ module_init(ipx_init);
int ipx_if_offset(unsigned long ipx_net_number)
{
ipx_route *rt = ipxrtr_lookup(ipx_net_number);
+ int ret = -ENETUNREACH;
- return rt ? rt->ir_intrfc->if_ipx_offset : -ENETUNREACH;
+ if (!rt)
+ goto out;
+ ret = rt->ir_intrfc->if_ipx_offset;
+ ipxrtr_put(rt);
+out: return ret;
}
/* Export symbols for higher layers */
@@ -2530,8 +2632,7 @@ EXPORT_SYMBOL(ipx_unregister_spx);
* sockets be closed from user space.
*/
-#ifdef MODULE
-static void ipx_proto_finito(void)
+static void __exit ipx_proto_finito(void)
{
/* no need to worry about having anything on the ipx_interfaces
* list, when a interface is created we increment the module
@@ -2541,6 +2642,7 @@ static void ipx_proto_finito(void)
proc_net_remove("ipx_route");
proc_net_remove("ipx_interface");
proc_net_remove("ipx");
+ ipx_unregister_sysctl();
unregister_netdevice_notifier(&ipx_dev_notifier);
@@ -2562,5 +2664,3 @@ static void ipx_proto_finito(void)
}
module_exit(ipx_proto_finito);
-#endif /* MODULE */
-#endif /* CONFIG_IPX || CONFIG_IPX_MODULE */
diff --git a/net/ipx/sysctl_net_ipx.c b/net/ipx/sysctl_net_ipx.c
index c699d6ff0..f28943f0e 100644
--- a/net/ipx/sysctl_net_ipx.c
+++ b/net/ipx/sysctl_net_ipx.c
@@ -3,11 +3,51 @@
*
* Begun April 1, 1996, Mike Shaver.
* Added /proc/sys/net/ipx directory entry (empty =) ). [MS]
+ * Added /proc/sys/net/ipx/ipx_pprop_broadcasting - acme March 4, 2001
*/
#include <linux/mm.h>
#include <linux/sysctl.h>
+/* From af_ipx.c */
+extern int sysctl_ipx_pprop_broadcasting;
+
+#ifdef CONFIG_SYSCTL
ctl_table ipx_table[] = {
- {0}
+ { NET_IPX_PPROP_BROADCASTING, "ipx_pprop_broadcasting",
+ &sysctl_ipx_pprop_broadcasting, sizeof(int), 0644, NULL,
+ &proc_dointvec },
+ { 0 }
+};
+
+static ctl_table ipx_dir_table[] = {
+ { NET_IPX, "ipx", NULL, 0, 0555, ipx_table },
+ { 0 }
+};
+
+static ctl_table ipx_root_table[] = {
+ { CTL_NET, "net", NULL, 0, 0555, ipx_dir_table },
+ { 0 }
};
+
+static struct ctl_table_header *ipx_table_header;
+
+void ipx_register_sysctl(void)
+{
+ ipx_table_header = register_sysctl_table(ipx_root_table, 1);
+}
+
+void ipx_unregister_sysctl(void)
+{
+ unregister_sysctl_table(ipx_table_header);
+}
+
+#else
+void ipx_register_sysctl(void)
+{
+}
+
+void ipx_unregister_sysctl(void)
+{
+}
+#endif
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 250b22ae9..cad22b277 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -146,7 +146,7 @@ static void irda_disconnect_indication(void *instance, void *sap,
/* Close our TSAP.
* If we leave it open, IrLMP put it back into the list of
- * unconnected LSAPs. The problem is that any incomming request
+ * unconnected LSAPs. The problem is that any incoming request
* can then be matched to this socket (and it will be, because
* it is at the head of the list). This would prevent any
* listening socket waiting on the same TSAP to get those requests.
@@ -229,7 +229,7 @@ static void irda_connect_confirm(void *instance, void *sap,
/*
* Function irda_connect_indication(instance, sap, qos, max_sdu_size, userdata)
*
- * Incomming connection
+ * Incoming connection
*
*/
static void irda_connect_indication(void *instance, void *sap,
@@ -285,7 +285,7 @@ static void irda_connect_indication(void *instance, void *sap,
/*
* Function irda_connect_response (handle)
*
- * Accept incomming connection
+ * Accept incoming connection
*
*/
void irda_connect_response(struct irda_sock *self)
@@ -836,7 +836,7 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
/*
* Function irda_accept (sock, newsock, flags)
*
- * Wait for incomming connection
+ * Wait for incoming connection
*
*/
static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
@@ -1995,6 +1995,9 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
if (get_user(len, optlen))
return -EFAULT;
+ if(optlen < 0)
+ return -EINVAL;
+
switch (optname) {
case IRLMP_ENUMDEVICES:
/* Ask lmp for the current discovery log */
diff --git a/net/irda/ircomm/Makefile b/net/irda/ircomm/Makefile
index fe0a6a830..12c52cf24 100644
--- a/net/irda/ircomm/Makefile
+++ b/net/irda/ircomm/Makefile
@@ -9,7 +9,7 @@
O_TARGET := ircomm_and_tty.o
-multi-objs := ircomm.o ircomm-tty.o
+list-multi := ircomm.o ircomm-tty.o
ircomm-objs := ircomm_core.o ircomm_event.o ircomm_lmp.o ircomm_ttp.o
ircomm-tty-objs := ircomm_tty.o ircomm_tty_attach.o ircomm_tty_ioctl.o ircomm_param.o
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
index 7ae03b0a6..bc791de5f 100644
--- a/net/irda/ircomm/ircomm_core.c
+++ b/net/irda/ircomm/ircomm_core.c
@@ -220,7 +220,7 @@ int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel,
/*
* Function ircomm_connect_indication (self, qos, skb)
*
- * Notify user layer about the incomming connection
+ * Notify user layer about the incoming connection
*
*/
void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
diff --git a/net/irda/ircomm/ircomm_event.c b/net/irda/ircomm/ircomm_event.c
index 5b43be858..ea80c7874 100644
--- a/net/irda/ircomm/ircomm_event.c
+++ b/net/irda/ircomm/ircomm_event.c
@@ -151,7 +151,7 @@ static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event,
/*
* Function ircomm_state_waitr (self, event, skb)
*
- * IrCOMM has received an incomming connection request and is awaiting
+ * IrCOMM has received an incoming connection request and is awaiting
* response from the user
*/
static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
diff --git a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c
index ca4526260..5ddd3e1de 100644
--- a/net/irda/ircomm/ircomm_lmp.c
+++ b/net/irda/ircomm/ircomm_lmp.c
@@ -219,7 +219,7 @@ int ircomm_lmp_data_request(struct ircomm_cb *self, struct sk_buff *skb,
/*
* Function ircomm_lmp_data_indication (instance, sap, skb)
*
- * Incomming data which we must deliver to the state machine, to check
+ * Incoming data which we must deliver to the state machine, to check
* we are still connected.
*/
int ircomm_lmp_data_indication(void *instance, void *sap,
diff --git a/net/irda/ircomm/ircomm_ttp.c b/net/irda/ircomm/ircomm_ttp.c
index 642b8416a..d17a5b544 100644
--- a/net/irda/ircomm/ircomm_ttp.c
+++ b/net/irda/ircomm/ircomm_ttp.c
@@ -156,7 +156,7 @@ int ircomm_ttp_data_request(struct ircomm_cb *self, struct sk_buff *skb,
/*
* Function ircomm_ttp_data_indication (instance, sap, skb)
*
- * Incomming data
+ * Incoming data
*
*/
int ircomm_ttp_data_indication(void *instance, void *sap,
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index b88cc3d53..c7d931b98 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -1106,7 +1106,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
/*
* Function ircomm_tty_data_indication (instance, sap, skb)
*
- * Handle incomming data, and deliver it to the line discipline
+ * Handle incoming data, and deliver it to the line discipline
*
*/
static int ircomm_tty_data_indication(void *instance, void *sap,
@@ -1155,7 +1155,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
/*
* Function ircomm_tty_control_indication (instance, sap, skb)
*
- * Parse all incomming parameters (easy!)
+ * Parse all incoming parameters (easy!)
*
*/
static int ircomm_tty_control_indication(void *instance, void *sap,
diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
index 65d1e4409..f6a4c1c8d 100644
--- a/net/irda/irias_object.c
+++ b/net/irda/irias_object.c
@@ -162,7 +162,7 @@ int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib)
ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;);
ASSERT(attrib != NULL, return -1;);
- /* Remove atribute from object */
+ /* Remove attribute from object */
node = hashbin_remove(obj->attribs, 0, attrib->name);
if (!node)
return 0; /* Already removed or non-existent */
diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c
index e06807bd9..6df8e97f5 100644
--- a/net/irda/irlan/irlan_provider.c
+++ b/net/irda/irlan/irlan_provider.c
@@ -162,7 +162,7 @@ static void irlan_provider_connect_indication(void *instance, void *sap,
/*
* Function irlan_provider_connect_response (handle)
*
- * Accept incomming connection
+ * Accept incoming connection
*
*/
void irlan_provider_connect_response(struct irlan_cb *self,
@@ -371,7 +371,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
/*
* Function irlan_provider_register(void)
*
- * Register provider support so we can accept incomming connections.
+ * Register provider support so we can accept incoming connections.
*
*/
int irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
diff --git a/net/irda/irlap.c b/net/irda/irlap.c
index b815f9f3a..c8bbecb8c 100644
--- a/net/irda/irlap.c
+++ b/net/irda/irlap.c
@@ -51,6 +51,7 @@
hashbin_t *irlap = NULL;
int sysctl_slot_timeout = SLOT_TIMEOUT * 1000 / HZ;
+extern void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb);
static void __irlap_close(struct irlap_cb *self);
static char *lap_reasons[] = {
@@ -241,7 +242,7 @@ void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb)
/*
* Function irlap_connect_response (self, skb)
*
- * Service user has accepted incomming connection
+ * Service user has accepted incoming connection
*
*/
void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb)
diff --git a/net/irda/irlap_comp.c b/net/irda/irlap_comp.c
index e81fc7e4a..37d6a6fbf 100644
--- a/net/irda/irlap_comp.c
+++ b/net/irda/irlap_comp.c
@@ -92,7 +92,7 @@ void irda_unregister_compressor ( struct compressor *cp)
/*
* Function irda_set_compression (self, proto)
*
- * The the compression protocol to be used by this session
+ * The compression protocol to be used by this session
*
*/
int irda_set_compression( struct irlap_cb *self, int proto)
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
index 10a942584..6a2d34f61 100644
--- a/net/irda/irlap_event.c
+++ b/net/irda/irlap_event.c
@@ -546,7 +546,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
break;
case SLOT_TIMER_EXPIRED:
/*
- * Wait a little longer if we detect an incomming frame. This
+ * Wait a little longer if we detect an incoming frame. This
* is not mentioned in the spec, but is a good thing to do,
* since we want to work even with devices that violate the
* timing requirements.
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 29debb1bd..19b41e788 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -450,7 +450,7 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
/*
* Function irlmp_connect_indication (self)
*
- * Incomming connection
+ * Incoming connection
*
*/
void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb)
diff --git a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c
index 56287afbb..803e598ff 100644
--- a/net/irda/irlmp_frame.c
+++ b/net/irda/irlmp_frame.c
@@ -470,7 +470,7 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel,
lsap = (struct lsap_cb *) hashbin_get_first(queue);
while (lsap != NULL) {
/*
- * If this is an incomming connection, then the destination
+ * If this is an incoming connection, then the destination
* LSAP selector may have been specified as LM_ANY so that
* any client can connect. In that case we only need to check
* if the source LSAP (in our view!) match!
diff --git a/net/irda/irnet/Config.in b/net/irda/irnet/Config.in
index d578593f1..ac6f9c433 100644
--- a/net/irda/irnet/Config.in
+++ b/net/irda/irnet/Config.in
@@ -1 +1,4 @@
-dep_tristate ' IrNET protocol' CONFIG_IRNET $CONFIG_IRDA
+if [ "$CONFIG_NETDEVICES" != "n" ]; then
+ dep_tristate ' IrNET protocol' CONFIG_IRNET $CONFIG_IRDA $CONFIG_PPP
+fi
+
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h
index 6c9df66b3..e9f936737 100644
--- a/net/irda/irnet/irnet.h
+++ b/net/irda/irnet/irnet.h
@@ -9,7 +9,7 @@
* what's in there...
*
* Note : as most part of the Linux kernel, this module is available
- * under the GNU Public License (GPL).
+ * under the GNU General Public License (GPL).
*/
#ifndef IRNET_H
@@ -52,14 +52,14 @@
* o multipoint operation (limited by IrLAP specification)
* o information in /proc/net/irda/irnet
* o IrNET events on /dev/irnet (for user space daemon)
- * o IrNET deamon (irnetd) to automatically handle incomming requests
+ * o IrNET deamon (irnetd) to automatically handle incoming requests
* o Windows 2000 compatibility (tested, but need more work)
* Currently missing :
* o Lot's of testing (that's your job)
* o Connection retries (may be too hard to do)
* o Check pppd persist mode
- * o User space deamon (to automatically handle incomming requests)
- * o A registered device number (comming, waiting from an answer)
+ * o User space deamon (to automatically handle incoming requests)
+ * o A registered device number (coming, waiting from an answer)
* o Final integration in Linux-IrDA (up to Dag)
*
* The setup is not currently the most easy, but this should get much
@@ -109,16 +109,16 @@
* and allow to offer the event channel, useful for other stuff like debug.
*
* On the other hand, this require a loose coordination between the
- * present module and irnetd. One critical area is how incomming request
+ * present module and irnetd. One critical area is how incoming request
* are handled.
- * When irnet receive an incomming request, it send an event to irnetd and
- * drop the incomming IrNET socket.
+ * When irnet receive an incoming request, it send an event to irnetd and
+ * drop the incoming IrNET socket.
* irnetd start a pppd instance, which create a new IrNET socket. This new
* socket is then connected in the originating node to the pppd instance.
* At this point, in the originating node, the first socket is closed.
*
* I admit, this is a bit messy and waste some ressources. The alternative
- * is caching incomming socket, and that's also quite messy and waste
+ * is caching incoming socket, and that's also quite messy and waste
* ressources.
* We also make connection time slower. For example, on a 115 kb/s link it
* adds 60ms to the connection time (770 ms). However, this is slower than
diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
index ead7ef678..0a1200484 100644
--- a/net/irda/irnet/irnet_irda.c
+++ b/net/irda/irnet/irnet_irda.c
@@ -523,7 +523,7 @@ irda_irnet_destroy(irnet_socket * self)
/*
* The IrNET service is composed of one server socket and a variable
* number of regular IrNET sockets. The server socket is supposed to
- * handle incomming connections and redirect them to one IrNET sockets.
+ * handle incoming connections and redirect them to one IrNET sockets.
* It's a superset of the regular IrNET socket, but has a very distinct
* behaviour...
*/
@@ -662,7 +662,7 @@ irnet_find_socket(irnet_socket * self)
/*
* Function irda_connect_socket (self)
*
- * Connect an incomming connection to the socket
+ * Connect an incoming connection to the socket
*
*/
static inline int
@@ -721,7 +721,7 @@ irnet_connect_socket(irnet_socket * self,
/*
* Function irda_disconnect_server (self)
*
- * Cleanup the server socket when the incomming connection abort
+ * Cleanup the server socket when the incoming connection abort
*
*/
static inline void
@@ -1097,7 +1097,7 @@ irnet_status_indication(void * instance,
/*
* Function irnet_connect_indication(instance, sap, qos, max_sdu_size, userdata)
*
- * Incomming connection
+ * Incoming connection
*
* In theory, this function is called only on the server socket.
* Some other node is attempting to connect to the IrNET service, and has
diff --git a/net/khttpd/main.c b/net/khttpd/main.c
index 2ade82be2..c0b4da163 100644
--- a/net/khttpd/main.c
+++ b/net/khttpd/main.c
@@ -138,7 +138,7 @@ static int MainDaemon(void *cpu_pointer)
changes +=DataSending(CPUNR);
changes +=Userspace(CPUNR);
changes +=Logging(CPUNR);
- /* Test for incomming connections _again_, because it is possible
+ /* Test for incoming connections _again_, because it is possible
one came in during the other steps, and the wakeup doesn't happen
then.
*/
diff --git a/net/khttpd/rfc.c b/net/khttpd/rfc.c
index c2629682a..a9f249178 100644
--- a/net/khttpd/rfc.c
+++ b/net/khttpd/rfc.c
@@ -101,7 +101,7 @@ char *ResolveMimeType(const char *File,__kernel_size_t *Len)
/*
The returned string is for READ ONLY, ownership of the memory is NOT
- transfered.
+ transferred.
*/
{
diff --git a/net/netsyms.c b/net/netsyms.c
index 52b98f4e1..8adcef849 100644
--- a/net/netsyms.c
+++ b/net/netsyms.c
@@ -432,17 +432,7 @@ EXPORT_SYMBOL(arp_find);
#endif /* CONFIG_INET */
#ifdef CONFIG_TR
-EXPORT_SYMBOL(tr_setup);
EXPORT_SYMBOL(tr_type_trans);
-EXPORT_SYMBOL(register_trdev);
-EXPORT_SYMBOL(unregister_trdev);
-EXPORT_SYMBOL(init_trdev);
-#endif
-
-#ifdef CONFIG_NET_FC
-EXPORT_SYMBOL(register_fcdev);
-EXPORT_SYMBOL(unregister_fcdev);
-EXPORT_SYMBOL(init_fcdev);
#endif
/* Device callback registration */
@@ -451,14 +441,10 @@ EXPORT_SYMBOL(unregister_netdevice_notifier);
/* support for loadable net drivers */
#ifdef CONFIG_NET
-EXPORT_SYMBOL(init_etherdev);
EXPORT_SYMBOL(loopback_dev);
EXPORT_SYMBOL(register_netdevice);
EXPORT_SYMBOL(unregister_netdevice);
-EXPORT_SYMBOL(register_netdev);
-EXPORT_SYMBOL(unregister_netdev);
EXPORT_SYMBOL(netdev_state_change);
-EXPORT_SYMBOL(ether_setup);
EXPORT_SYMBOL(dev_new_index);
EXPORT_SYMBOL(dev_get_by_index);
EXPORT_SYMBOL(__dev_get_by_index);
@@ -469,8 +455,6 @@ EXPORT_SYMBOL(netdev_set_master);
EXPORT_SYMBOL(eth_type_trans);
#ifdef CONFIG_FDDI
EXPORT_SYMBOL(fddi_type_trans);
-EXPORT_SYMBOL(fddi_setup);
-EXPORT_SYMBOL(init_fddidev);
#endif /* CONFIG_FDDI */
#if 0
EXPORT_SYMBOL(eth_copy_and_sum);
@@ -511,8 +495,6 @@ EXPORT_SYMBOL(if_port_text);
#ifdef CONFIG_HIPPI
EXPORT_SYMBOL(hippi_type_trans);
-EXPORT_SYMBOL(init_hippi_dev);
-EXPORT_SYMBOL(unregister_hipdev);
#endif
#ifdef CONFIG_SYSCTL
@@ -523,12 +505,6 @@ EXPORT_SYMBOL(sysctl_ip_default_ttl);
#endif
#endif
-#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
-#include<linux/if_ltalk.h>
-EXPORT_SYMBOL(ltalk_setup);
-#endif
-
-
/* Packet scheduler modules want these. */
EXPORT_SYMBOL(qdisc_destroy);
EXPORT_SYMBOL(qdisc_reset);
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 95707af00..164a97fe7 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -1,182 +1,34 @@
#
# Makefile for the Linux Traffic Control Unit.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := sched.o
obj-y := sch_generic.o
-ifeq ($(CONFIG_NET_SCHED), y)
-
-obj-y += sch_api.o sch_fifo.o
-
-ifeq ($(CONFIG_NET_ESTIMATOR), y)
-obj-y += estimator.o
-endif
-
-ifeq ($(CONFIG_NET_CLS), y)
-obj-y += cls_api.o
-
-ifeq ($(CONFIG_NET_CLS_POLICE), y)
-obj-y += police.o
-endif
-
-endif
-
-ifeq ($(CONFIG_NET_SCH_INGRESS), y)
-obj-y += sch_ingress.o
-else
- ifeq ($(CONFIG_NET_SCH_INGRESS), m)
- obj-m += sch_ingress.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_SCH_CBQ), y)
-obj-y += sch_cbq.o
-else
- ifeq ($(CONFIG_NET_SCH_CBQ), m)
- obj-m += sch_cbq.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_SCH_CSZ), y)
-obj-y += sch_csz.o
-else
- ifeq ($(CONFIG_NET_SCH_CSZ), m)
- obj-m += sch_csz.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_SCH_HPFQ), y)
-obj-y += sch_hpfq.o
-else
- ifeq ($(CONFIG_NET_SCH_HPFQ), m)
- obj-m += sch_hpfq.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_SCH_HFSC), y)
-obj-y += sch_hfsc.o
-else
- ifeq ($(CONFIG_NET_SCH_HFSC), m)
- obj-m += sch_hfsc.o
- endif
-endif
-
-
-ifeq ($(CONFIG_NET_SCH_SFQ), y)
-obj-y += sch_sfq.o
-else
- ifeq ($(CONFIG_NET_SCH_SFQ), m)
- obj-m += sch_sfq.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_SCH_RED), y)
-obj-y += sch_red.o
-else
- ifeq ($(CONFIG_NET_SCH_RED), m)
- obj-m += sch_red.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_SCH_TBF), y)
-obj-y += sch_tbf.o
-else
- ifeq ($(CONFIG_NET_SCH_TBF), m)
- obj-m += sch_tbf.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_SCH_PRIO), y)
-obj-y += sch_prio.o
-else
- ifeq ($(CONFIG_NET_SCH_PRIO), m)
- obj-m += sch_prio.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_SCH_TEQL), y)
-obj-y += sch_teql.o
-else
- ifeq ($(CONFIG_NET_SCH_TEQL), m)
- obj-m += sch_teql.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_SCH_GRED), y)
-obj-y += sch_gred.o
-else
- ifeq ($(CONFIG_NET_SCH_GRED), m)
- obj-m += sch_gred.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_SCH_DSMARK), y)
-obj-y += sch_dsmark.o
-else
- ifeq ($(CONFIG_NET_SCH_DSMARK), m)
- obj-m += sch_dsmark.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_CLS_TCINDEX), y)
-obj-y += cls_tcindex.o
-else
- ifeq ($(CONFIG_NET_CLS_TCINDEX), m)
- obj-m += cls_tcindex.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_SCH_ATM), y)
-obj-y += sch_atm.o
-endif
-
-ifeq ($(CONFIG_NET_CLS_U32), y)
-obj-y += cls_u32.o
-else
- ifeq ($(CONFIG_NET_CLS_U32), m)
- obj-m += cls_u32.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_CLS_RSVP), y)
-obj-y += cls_rsvp.o
-else
- ifeq ($(CONFIG_NET_CLS_RSVP), m)
- obj-m += cls_rsvp.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_CLS_RSVP6), y)
-obj-y += cls_rsvp6.o
-else
- ifeq ($(CONFIG_NET_CLS_RSVP6), m)
- obj-m += cls_rsvp6.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_CLS_ROUTE4), y)
-obj-y += cls_route.o
-else
- ifeq ($(CONFIG_NET_CLS_ROUTE4), m)
- obj-m += cls_route.o
- endif
-endif
-
-ifeq ($(CONFIG_NET_CLS_FW), y)
-obj-y += cls_fw.o
-else
- ifeq ($(CONFIG_NET_CLS_FW), m)
- obj-m += cls_fw.o
- endif
-endif
-endif
+obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o
+obj-$(CONFIG_NET_ESTIMATOR) += estimator.o
+obj-$(CONFIG_NET_CLS) += cls_api.o
+obj-$(CONFIG_NET_CLS_POLICE) += police.o
+obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o
+obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
+obj-$(CONFIG_NET_SCH_CSZ) += sch_csz.o
+obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o
+obj-$(CONFIG_NET_SCH_HFSC) += sch_hfsc.o
+obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
+obj-$(CONFIG_NET_SCH_RED) += sch_red.o
+obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
+obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
+obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
+obj-$(CONFIG_NET_SCH_GRED) += sch_gred.o
+obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
+obj-$(CONFIG_NET_CLS_TCINDEX) += cls_tcindex.o
+obj-$(CONFIG_NET_SCH_ATM) += sch_atm.o
+obj-$(CONFIG_NET_CLS_U32) += cls_u32.o
+obj-$(CONFIG_NET_CLS_RSVP) += cls_rsvp.o
+obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o
+obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o
+obj-$(CONFIG_NET_CLS_FW) += cls_fw.o
include $(TOPDIR)/Rules.make
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 8ab839f8a..750eb4672 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -76,7 +76,7 @@ static struct tcindex_filter_result *lookup(struct tcindex_data *p,__u16 key)
struct tcindex_filter *f;
if (p->perfect)
- return p->perfect[key].res.classid ? p->perfect+key : NULL;
+ return p->perfect[key].res.class ? p->perfect+key : NULL;
if (!p->h)
return NULL;
for (f = p->h[key % p->hash]; f; f = f->next) {
@@ -122,8 +122,14 @@ static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp,
static unsigned long tcindex_get(struct tcf_proto *tp, u32 handle)
{
+ struct tcindex_data *p = PRIV(tp);
+ struct tcindex_filter_result *r;
+
DPRINTK("tcindex_get(tp %p,handle 0x%08x)\n",tp,handle);
- return (unsigned long) lookup(PRIV(tp),handle);
+ if (p->perfect && handle >= p->alloc_hash)
+ return 0;
+ r = lookup(PRIV(tp),handle);
+ return r && r->res.class ? (unsigned long) r : 0;
}
@@ -164,7 +170,7 @@ static int tcindex_delete(struct tcf_proto *tp, unsigned long arg)
DPRINTK("tcindex_delete(tp %p,arg 0x%lx),p %p,f %p\n",tp,arg,p,f);
if (p->perfect) {
- if (!r->res.classid)
+ if (!r->res.class)
return -ENOENT;
} else {
int i;
@@ -212,7 +218,7 @@ static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle,
struct tcindex_filter *f;
struct tcindex_filter_result *r = (struct tcindex_filter_result *) *arg;
struct tcindex_filter **walk;
- int hash;
+ int hash,shift;
__u16 mask;
DPRINTK("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
@@ -237,17 +243,22 @@ static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle,
return -EINVAL;
mask = *(__u16 *) RTA_DATA(tb[TCA_TCINDEX_MASK-1]);
}
- if (p->perfect && hash <= mask)
+ if (!tb[TCA_TCINDEX_SHIFT-1])
+ shift = p->shift;
+ else {
+ if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(__u16))
+ return -EINVAL;
+ shift = *(int *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]);
+ }
+ if (p->perfect && hash <= (mask >> shift))
return -EBUSY;
- if ((p->perfect || p->h) && hash > p->alloc_hash)
+ if (p->perfect && hash > p->alloc_hash)
+ return -EBUSY;
+ if (p->h && hash != p->alloc_hash)
return -EBUSY;
p->hash = hash;
p->mask = mask;
- if (tb[TCA_TCINDEX_SHIFT-1]) {
- if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(__u16))
- return -EINVAL;
- p->shift = *(int *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]);
- }
+ p->shift = shift;
if (tb[TCA_TCINDEX_FALL_THROUGH-1]) {
if (RTA_PAYLOAD(tb[TCA_TCINDEX_FALL_THROUGH-1]) < sizeof(int))
return -EINVAL;
@@ -258,9 +269,9 @@ static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle,
tb[TCA_TCINDEX_POLICE-1]);
if (!tb[TCA_TCINDEX_CLASSID-1] && !tb[TCA_TCINDEX_POLICE-1])
return 0;
- if (!p->hash) {
- if (p->mask < PERFECT_HASH_THRESHOLD) {
- p->hash = p->mask+1;
+ if (!hash) {
+ if ((mask >> shift) < PERFECT_HASH_THRESHOLD) {
+ p->hash = (mask >> shift)+1;
} else {
p->hash = DEFAULT_HASH_SIZE;
}
@@ -268,7 +279,7 @@ static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle,
if (!p->perfect && !p->h) {
p->alloc_hash = p->hash;
DPRINTK("hash %d mask %d\n",p->hash,p->mask);
- if (p->hash > p->mask) {
+ if (p->hash > (mask >> shift)) {
p->perfect = kmalloc(p->hash*
sizeof(struct tcindex_filter_result),GFP_KERNEL);
if (!p->perfect)
@@ -283,7 +294,15 @@ static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle,
memset(p->h, 0, p->hash*sizeof(struct tcindex_filter *));
}
}
- if (handle > p->mask)
+ /*
+ * Note: this could be as restrictive as
+ * if (handle & ~(mask >> shift))
+ * but then, we'd fail handles that may become valid after some
+ * future mask change. While this is extremely unlikely to ever
+ * matter, the check below is safer (and also more
+ * backwards-compatible).
+ */
+ if (p->perfect && handle >= p->alloc_hash)
return -EINVAL;
if (p->perfect) {
r = p->perfect+handle;
@@ -308,17 +327,16 @@ static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle,
}
}
#ifdef CONFIG_NET_CLS_POLICE
- if (!tb[TCA_TCINDEX_POLICE-1]) {
- r->police = NULL;
- } else {
- struct tcf_police *police =
- tcf_police_locate(tb[TCA_TCINDEX_POLICE-1],NULL);
+ {
+ struct tcf_police *police;
- tcf_tree_lock(tp);
+ police = tb[TCA_TCINDEX_POLICE-1] ?
+ tcf_police_locate(tb[TCA_TCINDEX_POLICE-1],NULL) : NULL;
+ tcf_tree_lock(tp);
police = xchg(&r->police,police);
- tcf_tree_unlock(tp);
+ tcf_tree_unlock(tp);
tcf_police_release(police);
- }
+ }
#endif
if (r != &new_filter_result)
return 0;
@@ -339,13 +357,13 @@ static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle,
static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
{
struct tcindex_data *p = PRIV(tp);
- struct tcindex_filter *f;
+ struct tcindex_filter *f,*next;
int i;
DPRINTK("tcindex_walk(tp %p,walker %p),p %p\n",tp,walker,p);
if (p->perfect) {
for (i = 0; i < p->hash; i++) {
- if (!p->perfect[i].res.classid)
+ if (!p->perfect[i].res.class)
continue;
if (walker->count >= walker->skip) {
if (walker->fn(tp,
@@ -361,7 +379,8 @@ static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
if (!p->h)
return;
for (i = 0; i < p->hash; i++) {
- for (f = p->h[i]; f; f = f->next) {
+ for (f = p->h[i]; f; f = next) {
+ next = f->next;
if (walker->count >= walker->skip) {
if (walker->fn(tp,(unsigned long) &f->result,
walker) < 0) {
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index dc9f11aa7..a0c2d7585 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -506,7 +506,7 @@ static void cbq_ovl_classic(struct cbq_class *cl)
}
}
- q->wd_expires = delay;
+ q->wd_expires = base_delay;
}
}
@@ -1740,9 +1740,13 @@ cbq_destroy(struct Qdisc* sch)
}
for (h = 0; h < 16; h++) {
- for (cl = q->classes[h]; cl; cl = cl->next)
+ struct cbq_class *next;
+
+ for (cl = q->classes[h]; cl; cl = next) {
+ next = cl->next;
if (cl != &q->link)
cbq_destroy_class(cl);
+ }
}
qdisc_put_rtab(q->link.R_tab);
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index d30d08896..184ca0ac8 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -84,7 +84,9 @@ static int dsmark_graft(struct Qdisc *sch,unsigned long arg,
static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
{
- return NULL;
+ struct dsmark_qdisc_data *p = PRIV(sch);
+
+ return p->q;
}
@@ -187,7 +189,7 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
struct dsmark_qdisc_data *p = PRIV(sch);
struct tcf_result res;
int result;
- int ret;
+ int ret = NET_XMIT_POLICED;
D2PRINTK("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
if (p->set_tc_index) {
@@ -237,7 +239,7 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
((ret = p->q->enqueue(skb,p->q)) != 0)) {
sch->stats.drops++;
- return 0;
+ return ret;
}
sch->stats.bytes += skb->len;
sch->stats.packets++;
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 061ef312a..7b5248e74 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -66,7 +66,7 @@
N(t+delta) = min{B/R, N(t) + delta}
If the first packet in queue has length S, it may be
- transmited only at the time t_* when S/R <= N(t_*),
+ transmitted only at the time t_* when S/R <= N(t_*),
and in this case N(t) jumps:
N(t_* + 0) = N(t_* - 0) - S/R.
@@ -276,7 +276,7 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
struct tc_tbf_qopt *qopt;
struct qdisc_rate_table *rtab = NULL;
struct qdisc_rate_table *ptab = NULL;
- int max_size;
+ int max_size,n;
if (rtattr_parse(tb, TCA_TBF_PTAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
tb[TCA_TBF_PARMS-1] == NULL ||
@@ -295,15 +295,18 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
goto done;
}
- max_size = psched_mtu(sch->dev);
+ for (n = 0; n < 256; n++)
+ if (rtab->data[n] > qopt->buffer) break;
+ max_size = (n << qopt->rate.cell_log)-1;
if (ptab) {
- int n = max_size>>qopt->peakrate.cell_log;
- while (n>0 && ptab->data[n-1] > qopt->mtu) {
- max_size -= (1<<qopt->peakrate.cell_log);
- n--;
- }
+ int size;
+
+ for (n = 0; n < 256; n++)
+ if (ptab->data[n] > qopt->mtu) break;
+ size = (n << qopt->peakrate.cell_log)-1;
+ if (size < max_size) max_size = size;
}
- if (rtab->data[max_size>>qopt->rate.cell_log] > qopt->buffer)
+ if (max_size < 0)
goto done;
sch_tree_lock(sch);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 53d0ed236..bd85f3516 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -212,16 +212,20 @@ static inline void
svc_sock_release(struct svc_rqst *rqstp)
{
struct svc_sock *svsk = rqstp->rq_sock;
+ struct svc_serv *serv = svsk->sk_server;
- if (!svsk)
- return;
svc_release_skb(rqstp);
rqstp->rq_sock = NULL;
+
+ spin_lock_bh(&serv->sv_lock);
if (!--(svsk->sk_inuse) && svsk->sk_dead) {
+ spin_unlock_bh(&serv->sv_lock);
dprintk("svc: releasing dead socket\n");
sock_release(svsk->sk_sock);
kfree(svsk);
}
+ else
+ spin_unlock_bh(&serv->sv_lock);
}
/*
@@ -1034,14 +1038,15 @@ svc_delete_socket(struct svc_sock *svsk)
if (svsk->sk_qued)
rpc_remove_list(&serv->sv_sockets, svsk);
- spin_unlock_bh(&serv->sv_lock);
svsk->sk_dead = 1;
if (!svsk->sk_inuse) {
+ spin_unlock_bh(&serv->sv_lock);
sock_release(svsk->sk_sock);
kfree(svsk);
} else {
+ spin_unlock_bh(&serv->sv_lock);
printk(KERN_NOTICE "svc: server socket destroy delayed\n");
/* svsk->sk_server = NULL; */
}
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index 61f948390..23d157c61 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -20,10 +20,6 @@
extern ctl_table ipv4_table[];
#endif
-#ifdef CONFIG_IPX
-extern ctl_table ipx_table[];
-#endif
-
extern ctl_table core_table[];
#ifdef CONFIG_NET
@@ -51,9 +47,6 @@ ctl_table net_table[] = {
#ifdef CONFIG_INET
{NET_IPV4, "ipv4", NULL, 0, 0555, ipv4_table},
#endif
-#ifdef CONFIG_IPX
- {NET_IPX, "ipx", NULL, 0, 0555, ipx_table},
-#endif
#ifdef CONFIG_IPV6
{NET_IPV6, "ipv6", NULL, 0, 0555, ipv6_table},
#endif
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index a2e28fef2..cab183730 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1852,8 +1852,8 @@ struct net_proto_family unix_family_ops = {
extern void unix_sysctl_register(void);
extern void unix_sysctl_unregister(void);
#else
-static inline unix_sysctl_register() {};
-static inline unix_sysctl_unregister() {};
+static inline void unix_sysctl_register(void) {}
+static inline void unix_sysctl_unregister(void) {}
#endif
static const char banner[] __initdata = KERN_INFO "NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.\n";
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index 26e3f9130..cdb2c210e 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -5,7 +5,7 @@
* the following common services for the WAN Link Drivers:
* o WAN device managenment (registering, unregistering)
* o Network interface management
-* o Physical connection management (dial-up, incomming calls)
+* o Physical connection management (dial-up, incoming calls)
* o Logical connection management (switched virtual circuits)
* o Protocol encapsulation/decapsulation
*