diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-18 16:45:01 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-18 16:45:01 -0700 |
commit | 2e0c17d100c35e843dac1e99daf19b5e2b3fe168 (patch) | |
tree | 5bb58364fb453298819fe479cad95f5fcfeb8edf /net | |
parent | 7de4a9a73563e5f6f3c153015fadee433a443241 (diff) | |
parent | 22001a13d09d82772e831dcdac0553994a4bac5d (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (39 commits)
gigaset: fix build failure
bridge: Make first arg to deliver_clone const.
bridge br_multicast: Don't refer to BR_INPUT_SKB_CB(skb)->mrouters_only without IGMP snooping.
route: Fix caught BUG_ON during rt_secret_rebuild_oneshot()
bridge br_multicast: Fix skb leakage in error path.
bridge br_multicast: Fix handling of Max Response Code in IGMPv3 message.
NET: netpoll, fix potential NULL ptr dereference
tipc: fix lockdep warning on address assignment
l2tp: Fix UDP socket reference count bugs in the pppol2tp driver
smsc95xx: wait for PHY to complete reset during init
l2tp: Fix oops in pppol2tp_xmit
smsc75xx: SMSC LAN75xx USB gigabit ethernet adapter driver
ne: Do not use slashes in irq name string
NET: ksz884x, fix lock imbalance
gigaset: correct range checking off by one error
bridge: Fix br_forward crash in promiscuous mode
bridge: Move NULL mdb check into br_mdb_ip_get
ISDN: Add PCI ID for HFC-2S/4S Beronet Card PCIe
net-2.6 [Bug-Fix][dccp]: fix oops caused after failed initialisation
myri: remove dead code
...
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_device.c | 2 | ||||
-rw-r--r-- | net/bridge/br_forward.c | 18 | ||||
-rw-r--r-- | net/bridge/br_input.c | 4 | ||||
-rw-r--r-- | net/bridge/br_multicast.c | 18 | ||||
-rw-r--r-- | net/bridge/br_private.h | 10 | ||||
-rw-r--r-- | net/core/netpoll.c | 4 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 8 | ||||
-rw-r--r-- | net/dccp/ipv6.c | 8 | ||||
-rw-r--r-- | net/dccp/proto.c | 16 | ||||
-rw-r--r-- | net/ipv4/route.c | 16 | ||||
-rw-r--r-- | net/phonet/pn_dev.c | 3 | ||||
-rw-r--r-- | net/phonet/pn_netlink.c | 3 | ||||
-rw-r--r-- | net/tipc/ref.c | 26 |
13 files changed, 79 insertions, 57 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index eb7062d2e9e..90a9024e5c1 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -40,7 +40,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) goto out; mdst = br_mdb_get(br, skb); - if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) + if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) br_multicast_deliver(mdst, skb); else br_flood_deliver(br, skb); diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index d61e6f74112..8dbec83e50c 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -19,6 +19,11 @@ #include <linux/netfilter_bridge.h> #include "br_private.h" +static int deliver_clone(const struct net_bridge_port *prev, + struct sk_buff *skb, + void (*__packet_hook)(const struct net_bridge_port *p, + struct sk_buff *skb)); + /* Don't forward packets to originating port or forwarding diasabled */ static inline int should_deliver(const struct net_bridge_port *p, const struct sk_buff *skb) @@ -94,17 +99,22 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) } /* called with rcu_read_lock */ -void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) +void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0) { if (should_deliver(to, skb)) { - __br_forward(to, skb); + if (skb0) + deliver_clone(to, skb, __br_forward); + else + __br_forward(to, skb); return; } - kfree_skb(skb); + if (!skb0) + kfree_skb(skb); } -static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, +static int deliver_clone(const struct net_bridge_port *prev, + struct sk_buff *skb, void (*__packet_hook)(const struct net_bridge_port *p, struct sk_buff *skb)) { diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 53b39851d87..d74d570fc84 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -70,7 +70,7 @@ int br_handle_frame_finish(struct sk_buff *skb) if (is_multicast_ether_addr(dest)) { mdst = br_mdb_get(br, skb); - if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) { + if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) { if ((mdst && !hlist_unhashed(&mdst->mglist)) || br_multicast_is_router(br)) skb2 = skb; @@ -90,7 +90,7 @@ int br_handle_frame_finish(struct sk_buff *skb) if (skb) { if (dst) - br_forward(dst->dst, skb); + br_forward(dst->dst, skb, skb2); else br_flood_forward(br, skb, skb2); } diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index fd96a8dc97f..6980625537c 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -49,22 +49,23 @@ static struct net_bridge_mdb_entry *__br_mdb_ip_get( static struct net_bridge_mdb_entry *br_mdb_ip_get( struct net_bridge_mdb_htable *mdb, __be32 dst) { + if (!mdb) + return NULL; + return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst)); } struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, struct sk_buff *skb) { - struct net_bridge_mdb_htable *mdb = br->mdb; - - if (!mdb || br->multicast_disabled) + if (br->multicast_disabled) return NULL; switch (skb->protocol) { case htons(ETH_P_IP): if (BR_INPUT_SKB_CB(skb)->igmp) break; - return br_mdb_ip_get(mdb, ip_hdr(skb)->daddr); + return br_mdb_ip_get(br->mdb, ip_hdr(skb)->daddr); } return NULL; @@ -851,8 +852,8 @@ static int br_multicast_query(struct net_bridge *br, if (ih3->nsrcs) goto out; - max_delay = ih3->code ? 1 : - IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE); + max_delay = ih3->code ? + IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; } if (!group) @@ -990,7 +991,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, err = pskb_trim_rcsum(skb2, len); if (err) - return err; + goto err_out; } len -= ip_hdrlen(skb2); @@ -1012,7 +1013,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, case CHECKSUM_NONE: skb2->csum = 0; if (skb_checksum_complete(skb2)) - return -EINVAL; + goto out; } err = 0; @@ -1039,6 +1040,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, out: __skb_push(skb2, offset); +err_out: if (skb2 != skb) kfree_skb(skb2); return err; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index fef0384e3c0..846d7d1e207 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -206,12 +206,20 @@ struct net_bridge struct br_input_skb_cb { struct net_device *brdev; +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING int igmp; int mrouters_only; +#endif }; #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING +# define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb) (BR_INPUT_SKB_CB(__skb)->mrouters_only) +#else +# define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb) (0) +#endif + extern struct notifier_block br_device_notifier; extern const u8 br_group_address[ETH_ALEN]; @@ -252,7 +260,7 @@ extern void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb); extern int br_dev_queue_push_xmit(struct sk_buff *skb); extern void br_forward(const struct net_bridge_port *to, - struct sk_buff *skb); + struct sk_buff *skb, struct sk_buff *skb0); extern int br_forward_finish(struct sk_buff *skb); extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 7aa69725376..d4ec38fa64e 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -735,7 +735,7 @@ int netpoll_setup(struct netpoll *np) npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); if (!npinfo) { err = -ENOMEM; - goto release; + goto put; } npinfo->rx_flags = 0; @@ -845,7 +845,7 @@ int netpoll_setup(struct netpoll *np) kfree(npinfo); } - +put: dev_put(ndev); return err; } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index b195c4feaa0..4071eaf2b36 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -998,11 +998,11 @@ static struct inet_protosw dccp_v4_protosw = { static int __net_init dccp_v4_init_net(struct net *net) { - int err; + if (dccp_hashinfo.bhash == NULL) + return -ESOCKTNOSUPPORT; - err = inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET, - SOCK_DCCP, IPPROTO_DCCP, net); - return err; + return inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET, + SOCK_DCCP, IPPROTO_DCCP, net); } static void __net_exit dccp_v4_exit_net(struct net *net) diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 1aec6349e85..af3394df63b 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1191,11 +1191,11 @@ static struct inet_protosw dccp_v6_protosw = { static int __net_init dccp_v6_init_net(struct net *net) { - int err; + if (dccp_hashinfo.bhash == NULL) + return -ESOCKTNOSUPPORT; - err = inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6, - SOCK_DCCP, IPPROTO_DCCP, net); - return err; + return inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6, + SOCK_DCCP, IPPROTO_DCCP, net); } static void __net_exit dccp_v6_exit_net(struct net *net) diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 0ef7061920c..aa4cef374fd 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -1036,7 +1036,7 @@ static int __init dccp_init(void) FIELD_SIZEOF(struct sk_buff, cb)); rc = percpu_counter_init(&dccp_orphan_count, 0); if (rc) - goto out; + goto out_fail; rc = -ENOBUFS; inet_hashinfo_init(&dccp_hashinfo); dccp_hashinfo.bind_bucket_cachep = @@ -1125,8 +1125,9 @@ static int __init dccp_init(void) goto out_sysctl_exit; dccp_timestamping_init(); -out: - return rc; + + return 0; + out_sysctl_exit: dccp_sysctl_exit(); out_ackvec_exit: @@ -1135,18 +1136,19 @@ out_free_dccp_mib: dccp_mib_exit(); out_free_dccp_bhash: free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order); - dccp_hashinfo.bhash = NULL; out_free_dccp_locks: inet_ehash_locks_free(&dccp_hashinfo); out_free_dccp_ehash: free_pages((unsigned long)dccp_hashinfo.ehash, ehash_order); - dccp_hashinfo.ehash = NULL; out_free_bind_bucket_cachep: kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); - dccp_hashinfo.bind_bucket_cachep = NULL; out_free_percpu: percpu_counter_destroy(&dccp_orphan_count); - goto out; +out_fail: + dccp_hashinfo.bhash = NULL; + dccp_hashinfo.ehash = NULL; + dccp_hashinfo.bind_bucket_cachep = NULL; + return rc; } static void __exit dccp_fini(void) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d9b40248b97..a770df2493d 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -932,10 +932,8 @@ static void rt_secret_rebuild_oneshot(struct net *net) { del_timer_sync(&net->ipv4.rt_secret_timer); rt_cache_invalidate(net); - if (ip_rt_secret_interval) { - net->ipv4.rt_secret_timer.expires += ip_rt_secret_interval; - add_timer(&net->ipv4.rt_secret_timer); - } + if (ip_rt_secret_interval) + mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval); } static void rt_emergency_hash_rebuild(struct net *net) @@ -3103,22 +3101,20 @@ static void rt_secret_reschedule(int old) rtnl_lock(); for_each_net(net) { int deleted = del_timer_sync(&net->ipv4.rt_secret_timer); + long time; if (!new) continue; if (deleted) { - long time = net->ipv4.rt_secret_timer.expires - jiffies; + time = net->ipv4.rt_secret_timer.expires - jiffies; if (time <= 0 || (time += diff) <= 0) time = 0; - - net->ipv4.rt_secret_timer.expires = time; } else - net->ipv4.rt_secret_timer.expires = new; + time = new; - net->ipv4.rt_secret_timer.expires += jiffies; - add_timer(&net->ipv4.rt_secret_timer); + mod_timer(&net->ipv4.rt_secret_timer, jiffies + time); } rtnl_unlock(); } diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index c597cc53a6f..5c6ae0c701c 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -107,8 +107,7 @@ static void phonet_device_destroy(struct net_device *dev) if (pnd) { u8 addr; - for (addr = find_first_bit(pnd->addrs, 64); addr < 64; - addr = find_next_bit(pnd->addrs, 64, 1+addr)) + for_each_set_bit(addr, pnd->addrs, 64) phonet_address_notify(RTM_DELADDR, dev, addr); kfree(pnd); } diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index 2e6c7eb8e76..fe2e7088ee0 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c @@ -141,8 +141,7 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) continue; addr_idx = 0; - for (addr = find_first_bit(pnd->addrs, 64); addr < 64; - addr = find_next_bit(pnd->addrs, 64, 1+addr)) { + for_each_set_bit(addr, pnd->addrs, 64) { if (addr_idx++ < addr_start_idx) continue; diff --git a/net/tipc/ref.c b/net/tipc/ref.c index 414fc34b8be..8dea66500cf 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c @@ -153,11 +153,11 @@ void tipc_ref_table_stop(void) u32 tipc_ref_acquire(void *object, spinlock_t **lock) { - struct reference *entry; u32 index; u32 index_mask; u32 next_plus_upper; u32 ref; + struct reference *entry = NULL; if (!object) { err("Attempt to acquire reference to non-existent object\n"); @@ -175,30 +175,36 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock) index = tipc_ref_table.first_free; entry = &(tipc_ref_table.entries[index]); index_mask = tipc_ref_table.index_mask; - /* take lock in case a previous user of entry still holds it */ - spin_lock_bh(&entry->lock); next_plus_upper = entry->ref; tipc_ref_table.first_free = next_plus_upper & index_mask; ref = (next_plus_upper & ~index_mask) + index; - entry->ref = ref; - entry->object = object; - *lock = &entry->lock; } else if (tipc_ref_table.init_point < tipc_ref_table.capacity) { index = tipc_ref_table.init_point++; entry = &(tipc_ref_table.entries[index]); spin_lock_init(&entry->lock); - spin_lock_bh(&entry->lock); ref = tipc_ref_table.start_mask + index; - entry->ref = ref; - entry->object = object; - *lock = &entry->lock; } else { ref = 0; } write_unlock_bh(&ref_table_lock); + /* + * Grab the lock so no one else can modify this entry + * While we assign its ref value & object pointer + */ + if (entry) { + spin_lock_bh(&entry->lock); + entry->ref = ref; + entry->object = object; + *lock = &entry->lock; + /* + * keep it locked, the caller is responsible + * for unlocking this when they're done with it + */ + } + return ref; } |