]> err.no Git - linux-2.6/blobdiff - net/core/neighbour.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux...
[linux-2.6] / net / core / neighbour.c
index a16cf1ec5e5ebe9fc100cb027c740c9387184472..19b8e003f15084821aee62374a74038514800d80 100644 (file)
@@ -358,11 +358,12 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
 {
        struct neighbour *n;
        int key_len = tbl->key_len;
-       u32 hash_val = tbl->hash(pkey, dev);
+       u32 hash_val;
 
        NEIGH_CACHE_STAT_INC(tbl, lookups);
 
        read_lock_bh(&tbl->lock);
+       hash_val = tbl->hash(pkey, dev);
        for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
                if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
                        neigh_hold(n);
@@ -379,11 +380,12 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
 {
        struct neighbour *n;
        int key_len = tbl->key_len;
-       u32 hash_val = tbl->hash(pkey, NULL);
+       u32 hash_val;
 
        NEIGH_CACHE_STAT_INC(tbl, lookups);
 
        read_lock_bh(&tbl->lock);
+       hash_val = tbl->hash(pkey, NULL);
        for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
                if (!memcmp(n->primary_key, pkey, key_len) &&
                    (net == n->dev->nd_net)) {
@@ -464,6 +466,28 @@ out_neigh_release:
        goto out;
 }
 
+struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
+               struct net *net, const void *pkey, struct net_device *dev)
+{
+       struct pneigh_entry *n;
+       int key_len = tbl->key_len;
+       u32 hash_val = *(u32 *)(pkey + key_len - 4);
+
+       hash_val ^= (hash_val >> 16);
+       hash_val ^= hash_val >> 8;
+       hash_val ^= hash_val >> 4;
+       hash_val &= PNEIGH_HASHMASK;
+
+       for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
+               if (!memcmp(n->key, pkey, key_len) &&
+                   (n->net == net) &&
+                   (n->dev == dev || !n->dev))
+                       break;
+       }
+
+       return n;
+}
+
 struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
                                    struct net *net, const void *pkey,
                                    struct net_device *dev, int creat)
@@ -507,6 +531,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
        if (tbl->pconstructor && tbl->pconstructor(n)) {
                if (dev)
                        dev_put(dev);
+               release_net(net);
                kfree(n);
                n = NULL;
                goto out;
@@ -836,7 +861,7 @@ static void neigh_timer_handler(unsigned long arg)
                struct sk_buff *skb = skb_peek(&neigh->arp_queue);
                /* keep skb alive even if arp_queue overflows */
                if (skb)
-                       skb_get(skb);
+                       skb = skb_copy(skb, GFP_ATOMIC);
                write_unlock(&neigh->lock);
                neigh->ops->solicit(neigh, skb);
                atomic_inc(&neigh->probes);
@@ -1386,10 +1411,10 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
                panic("cannot create neighbour cache statistics");
 
 #ifdef CONFIG_PROC_FS
-       tbl->pde = create_proc_entry(tbl->id, 0, init_net.proc_net_stat);
+       tbl->pde = proc_create(tbl->id, 0, init_net.proc_net_stat,
+                              &neigh_stat_seq_fops);
        if (!tbl->pde)
                panic("cannot create neighbour proc dir entry");
-       tbl->pde->proc_fops = &neigh_stat_seq_fops;
        tbl->pde->data = tbl;
 #endif
 
@@ -2800,6 +2825,7 @@ EXPORT_SYMBOL(neigh_table_init_no_netlink);
 EXPORT_SYMBOL(neigh_update);
 EXPORT_SYMBOL(pneigh_enqueue);
 EXPORT_SYMBOL(pneigh_lookup);
+EXPORT_SYMBOL_GPL(__pneigh_lookup);
 
 #ifdef CONFIG_ARPD
 EXPORT_SYMBOL(neigh_app_ns);