diff options
Diffstat (limited to 'net')
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 * |