aboutsummaryrefslogtreecommitdiffstats
path: root/net/phonet/socket.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /net/phonet/socket.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/phonet/socket.c')
-rw-r--r--net/phonet/socket.c83
1 files changed, 68 insertions, 15 deletions
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index aa5b5a972bff..c785bfd0744f 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -23,6 +23,7 @@
23 * 02110-1301 USA 23 * 02110-1301 USA
24 */ 24 */
25 25
26#include <linux/gfp.h>
26#include <linux/kernel.h> 27#include <linux/kernel.h>
27#include <linux/net.h> 28#include <linux/net.h>
28#include <linux/poll.h> 29#include <linux/poll.h>
@@ -45,13 +46,28 @@ static int pn_socket_release(struct socket *sock)
45 return 0; 46 return 0;
46} 47}
47 48
49#define PN_HASHSIZE 16
50#define PN_HASHMASK (PN_HASHSIZE-1)
51
52
48static struct { 53static struct {
49 struct hlist_head hlist; 54 struct hlist_head hlist[PN_HASHSIZE];
50 spinlock_t lock; 55 spinlock_t lock;
51} pnsocks = { 56} pnsocks;
52 .hlist = HLIST_HEAD_INIT, 57
53 .lock = __SPIN_LOCK_UNLOCKED(pnsocks.lock), 58void __init pn_sock_init(void)
54}; 59{
60 unsigned i;
61
62 for (i = 0; i < PN_HASHSIZE; i++)
63 INIT_HLIST_HEAD(pnsocks.hlist + i);
64 spin_lock_init(&pnsocks.lock);
65}
66
67static struct hlist_head *pn_hash_list(u16 obj)
68{
69 return pnsocks.hlist + (obj & PN_HASHMASK);
70}
55 71
56/* 72/*
57 * Find address based on socket address, match only certain fields. 73 * Find address based on socket address, match only certain fields.
@@ -64,10 +80,11 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
64 struct sock *rval = NULL; 80 struct sock *rval = NULL;
65 u16 obj = pn_sockaddr_get_object(spn); 81 u16 obj = pn_sockaddr_get_object(spn);
66 u8 res = spn->spn_resource; 82 u8 res = spn->spn_resource;
83 struct hlist_head *hlist = pn_hash_list(obj);
67 84
68 spin_lock_bh(&pnsocks.lock); 85 spin_lock_bh(&pnsocks.lock);
69 86
70 sk_for_each(sknode, node, &pnsocks.hlist) { 87 sk_for_each(sknode, node, hlist) {
71 struct pn_sock *pn = pn_sk(sknode); 88 struct pn_sock *pn = pn_sk(sknode);
72 BUG_ON(!pn->sobject); /* unbound socket */ 89 BUG_ON(!pn->sobject); /* unbound socket */
73 90
@@ -82,8 +99,8 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
82 if (pn->resource != res) 99 if (pn->resource != res)
83 continue; 100 continue;
84 } 101 }
85 if (pn_addr(pn->sobject) 102 if (pn_addr(pn->sobject) &&
86 && pn_addr(pn->sobject) != pn_addr(obj)) 103 pn_addr(pn->sobject) != pn_addr(obj))
87 continue; 104 continue;
88 105
89 rval = sknode; 106 rval = sknode;
@@ -94,13 +111,44 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
94 spin_unlock_bh(&pnsocks.lock); 111 spin_unlock_bh(&pnsocks.lock);
95 112
96 return rval; 113 return rval;
114}
115
116/* Deliver a broadcast packet (only in bottom-half) */
117void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb)
118{
119 struct hlist_head *hlist = pnsocks.hlist;
120 unsigned h;
121
122 spin_lock(&pnsocks.lock);
123 for (h = 0; h < PN_HASHSIZE; h++) {
124 struct hlist_node *node;
125 struct sock *sknode;
126
127 sk_for_each(sknode, node, hlist) {
128 struct sk_buff *clone;
129
130 if (!net_eq(sock_net(sknode), net))
131 continue;
132 if (!sock_flag(sknode, SOCK_BROADCAST))
133 continue;
97 134
135 clone = skb_clone(skb, GFP_ATOMIC);
136 if (clone) {
137 sock_hold(sknode);
138 sk_receive_skb(sknode, clone, 0);
139 }
140 }
141 hlist++;
142 }
143 spin_unlock(&pnsocks.lock);
98} 144}
99 145
100void pn_sock_hash(struct sock *sk) 146void pn_sock_hash(struct sock *sk)
101{ 147{
148 struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject);
149
102 spin_lock_bh(&pnsocks.lock); 150 spin_lock_bh(&pnsocks.lock);
103 sk_add_node(sk, &pnsocks.hlist); 151 sk_add_node(sk, hlist);
104 spin_unlock_bh(&pnsocks.lock); 152 spin_unlock_bh(&pnsocks.lock);
105} 153}
106EXPORT_SYMBOL(pn_sock_hash); 154EXPORT_SYMBOL(pn_sock_hash);
@@ -416,15 +464,20 @@ EXPORT_SYMBOL(pn_sock_get_port);
416static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos) 464static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos)
417{ 465{
418 struct net *net = seq_file_net(seq); 466 struct net *net = seq_file_net(seq);
467 struct hlist_head *hlist = pnsocks.hlist;
419 struct hlist_node *node; 468 struct hlist_node *node;
420 struct sock *sknode; 469 struct sock *sknode;
470 unsigned h;
421 471
422 sk_for_each(sknode, node, &pnsocks.hlist) { 472 for (h = 0; h < PN_HASHSIZE; h++) {
423 if (!net_eq(net, sock_net(sknode))) 473 sk_for_each(sknode, node, hlist) {
424 continue; 474 if (!net_eq(net, sock_net(sknode)))
425 if (!pos) 475 continue;
426 return sknode; 476 if (!pos)
427 pos--; 477 return sknode;
478 pos--;
479 }
480 hlist++;
428 } 481 }
429 return NULL; 482 return NULL;
430} 483}