aboutsummaryrefslogtreecommitdiffstats
path: root/net/phonet
diff options
context:
space:
mode:
Diffstat (limited to 'net/phonet')
-rw-r--r--net/phonet/af_phonet.c83
-rw-r--r--net/phonet/datagram.c6
-rw-r--r--net/phonet/pep.c35
-rw-r--r--net/phonet/pn_dev.c219
-rw-r--r--net/phonet/pn_netlink.c138
-rw-r--r--net/phonet/socket.c82
6 files changed, 463 insertions, 100 deletions
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index f60c0c2aacba..526d0273991a 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -35,7 +35,6 @@
35 35
36/* Transport protocol registration */ 36/* Transport protocol registration */
37static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly; 37static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly;
38static DEFINE_SPINLOCK(proto_tab_lock);
39 38
40static struct phonet_protocol *phonet_proto_get(int protocol) 39static struct phonet_protocol *phonet_proto_get(int protocol)
41{ 40{
@@ -44,11 +43,11 @@ static struct phonet_protocol *phonet_proto_get(int protocol)
44 if (protocol >= PHONET_NPROTO) 43 if (protocol >= PHONET_NPROTO)
45 return NULL; 44 return NULL;
46 45
47 spin_lock(&proto_tab_lock); 46 rcu_read_lock();
48 pp = proto_tab[protocol]; 47 pp = rcu_dereference(proto_tab[protocol]);
49 if (pp && !try_module_get(pp->prot->owner)) 48 if (pp && !try_module_get(pp->prot->owner))
50 pp = NULL; 49 pp = NULL;
51 spin_unlock(&proto_tab_lock); 50 rcu_read_unlock();
52 51
53 return pp; 52 return pp;
54} 53}
@@ -60,7 +59,8 @@ static inline void phonet_proto_put(struct phonet_protocol *pp)
60 59
61/* protocol family functions */ 60/* protocol family functions */
62 61
63static int pn_socket_create(struct net *net, struct socket *sock, int protocol) 62static int pn_socket_create(struct net *net, struct socket *sock, int protocol,
63 int kern)
64{ 64{
65 struct sock *sk; 65 struct sock *sk;
66 struct pn_sock *pn; 66 struct pn_sock *pn;
@@ -118,7 +118,7 @@ out:
118 return err; 118 return err;
119} 119}
120 120
121static struct net_proto_family phonet_proto_family = { 121static const struct net_proto_family phonet_proto_family = {
122 .family = PF_PHONET, 122 .family = PF_PHONET,
123 .create = pn_socket_create, 123 .create = pn_socket_create,
124 .owner = THIS_MODULE, 124 .owner = THIS_MODULE,
@@ -190,9 +190,8 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev,
190 skb->priority = 0; 190 skb->priority = 0;
191 skb->dev = dev; 191 skb->dev = dev;
192 192
193 if (pn_addr(src) == pn_addr(dst)) { 193 if (skb->pkt_type == PACKET_LOOPBACK) {
194 skb_reset_mac_header(skb); 194 skb_reset_mac_header(skb);
195 skb->pkt_type = PACKET_LOOPBACK;
196 skb_orphan(skb); 195 skb_orphan(skb);
197 if (irq) 196 if (irq)
198 netif_rx(skb); 197 netif_rx(skb);
@@ -222,6 +221,9 @@ static int pn_raw_send(const void *data, int len, struct net_device *dev,
222 if (skb == NULL) 221 if (skb == NULL)
223 return -ENOMEM; 222 return -ENOMEM;
224 223
224 if (phonet_address_lookup(dev_net(dev), pn_addr(dst)) == 0)
225 skb->pkt_type = PACKET_LOOPBACK;
226
225 skb_reserve(skb, MAX_PHONET_HEADER); 227 skb_reserve(skb, MAX_PHONET_HEADER);
226 __skb_put(skb, len); 228 __skb_put(skb, len);
227 skb_copy_to_linear_data(skb, data, len); 229 skb_copy_to_linear_data(skb, data, len);
@@ -235,6 +237,7 @@ static int pn_raw_send(const void *data, int len, struct net_device *dev,
235int pn_skb_send(struct sock *sk, struct sk_buff *skb, 237int pn_skb_send(struct sock *sk, struct sk_buff *skb,
236 const struct sockaddr_pn *target) 238 const struct sockaddr_pn *target)
237{ 239{
240 struct net *net = sock_net(sk);
238 struct net_device *dev; 241 struct net_device *dev;
239 struct pn_sock *pn = pn_sk(sk); 242 struct pn_sock *pn = pn_sk(sk);
240 int err; 243 int err;
@@ -243,9 +246,13 @@ int pn_skb_send(struct sock *sk, struct sk_buff *skb,
243 246
244 err = -EHOSTUNREACH; 247 err = -EHOSTUNREACH;
245 if (sk->sk_bound_dev_if) 248 if (sk->sk_bound_dev_if)
246 dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if); 249 dev = dev_get_by_index(net, sk->sk_bound_dev_if);
247 else 250 else if (phonet_address_lookup(net, daddr) == 0) {
248 dev = phonet_device_get(sock_net(sk)); 251 dev = phonet_device_get(net);
252 skb->pkt_type = PACKET_LOOPBACK;
253 } else
254 dev = phonet_route_output(net, daddr);
255
249 if (!dev || !(dev->flags & IFF_UP)) 256 if (!dev || !(dev->flags & IFF_UP))
250 goto drop; 257 goto drop;
251 258
@@ -369,6 +376,12 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,
369 376
370 pn_skb_get_dst_sockaddr(skb, &sa); 377 pn_skb_get_dst_sockaddr(skb, &sa);
371 378
379 /* check if this is broadcasted */
380 if (pn_sockaddr_get_addr(&sa) == PNADDR_BROADCAST) {
381 pn_deliver_sock_broadcast(net, skb);
382 goto out;
383 }
384
372 /* check if we are the destination */ 385 /* check if we are the destination */
373 if (phonet_address_lookup(net, pn_sockaddr_get_addr(&sa)) == 0) { 386 if (phonet_address_lookup(net, pn_sockaddr_get_addr(&sa)) == 0) {
374 /* Phonet packet input */ 387 /* Phonet packet input */
@@ -381,6 +394,38 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,
381 send_obj_unreachable(skb); 394 send_obj_unreachable(skb);
382 send_reset_indications(skb); 395 send_reset_indications(skb);
383 } 396 }
397 } else if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
398 goto out; /* Race between address deletion and loopback */
399 else {
400 /* Phonet packet routing */
401 struct net_device *out_dev;
402
403 out_dev = phonet_route_output(net, pn_sockaddr_get_addr(&sa));
404 if (!out_dev) {
405 LIMIT_NETDEBUG(KERN_WARNING"No Phonet route to %02X\n",
406 pn_sockaddr_get_addr(&sa));
407 goto out;
408 }
409
410 __skb_push(skb, sizeof(struct phonethdr));
411 skb->dev = out_dev;
412 if (out_dev == dev) {
413 LIMIT_NETDEBUG(KERN_ERR"Phonet loop to %02X on %s\n",
414 pn_sockaddr_get_addr(&sa), dev->name);
415 goto out_dev;
416 }
417 /* Some drivers (e.g. TUN) do not allocate HW header space */
418 if (skb_cow_head(skb, out_dev->hard_header_len))
419 goto out_dev;
420
421 if (dev_hard_header(skb, out_dev, ETH_P_PHONET, NULL, NULL,
422 skb->len) < 0)
423 goto out_dev;
424 dev_queue_xmit(skb);
425 dev_put(out_dev);
426 return NET_RX_SUCCESS;
427out_dev:
428 dev_put(out_dev);
384 } 429 }
385 430
386out: 431out:
@@ -393,6 +438,8 @@ static struct packet_type phonet_packet_type __read_mostly = {
393 .func = phonet_rcv, 438 .func = phonet_rcv,
394}; 439};
395 440
441static DEFINE_MUTEX(proto_tab_lock);
442
396int __init_or_module phonet_proto_register(int protocol, 443int __init_or_module phonet_proto_register(int protocol,
397 struct phonet_protocol *pp) 444 struct phonet_protocol *pp)
398{ 445{
@@ -405,12 +452,12 @@ int __init_or_module phonet_proto_register(int protocol,
405 if (err) 452 if (err)
406 return err; 453 return err;
407 454
408 spin_lock(&proto_tab_lock); 455 mutex_lock(&proto_tab_lock);
409 if (proto_tab[protocol]) 456 if (proto_tab[protocol])
410 err = -EBUSY; 457 err = -EBUSY;
411 else 458 else
412 proto_tab[protocol] = pp; 459 rcu_assign_pointer(proto_tab[protocol], pp);
413 spin_unlock(&proto_tab_lock); 460 mutex_unlock(&proto_tab_lock);
414 461
415 return err; 462 return err;
416} 463}
@@ -418,10 +465,11 @@ EXPORT_SYMBOL(phonet_proto_register);
418 465
419void phonet_proto_unregister(int protocol, struct phonet_protocol *pp) 466void phonet_proto_unregister(int protocol, struct phonet_protocol *pp)
420{ 467{
421 spin_lock(&proto_tab_lock); 468 mutex_lock(&proto_tab_lock);
422 BUG_ON(proto_tab[protocol] != pp); 469 BUG_ON(proto_tab[protocol] != pp);
423 proto_tab[protocol] = NULL; 470 rcu_assign_pointer(proto_tab[protocol], NULL);
424 spin_unlock(&proto_tab_lock); 471 mutex_unlock(&proto_tab_lock);
472 synchronize_rcu();
425 proto_unregister(pp->prot); 473 proto_unregister(pp->prot);
426} 474}
427EXPORT_SYMBOL(phonet_proto_unregister); 475EXPORT_SYMBOL(phonet_proto_unregister);
@@ -435,6 +483,7 @@ static int __init phonet_init(void)
435 if (err) 483 if (err)
436 return err; 484 return err;
437 485
486 pn_sock_init();
438 err = sock_register(&phonet_proto_family); 487 err = sock_register(&phonet_proto_family);
439 if (err) { 488 if (err) {
440 printk(KERN_ALERT 489 printk(KERN_ALERT
diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c
index ef5c75c372e4..67f072e94d00 100644
--- a/net/phonet/datagram.c
+++ b/net/phonet/datagram.c
@@ -159,11 +159,9 @@ out_nofree:
159static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb) 159static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb)
160{ 160{
161 int err = sock_queue_rcv_skb(sk, skb); 161 int err = sock_queue_rcv_skb(sk, skb);
162 if (err < 0) { 162
163 if (err < 0)
163 kfree_skb(skb); 164 kfree_skb(skb);
164 if (err == -ENOMEM)
165 atomic_inc(&sk->sk_drops);
166 }
167 return err ? NET_RX_DROP : NET_RX_SUCCESS; 165 return err ? NET_RX_DROP : NET_RX_SUCCESS;
168} 166}
169 167
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 5f32d217535b..b6356f3832f6 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -360,8 +360,6 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
360 err = sock_queue_rcv_skb(sk, skb); 360 err = sock_queue_rcv_skb(sk, skb);
361 if (!err) 361 if (!err)
362 return 0; 362 return 0;
363 if (err == -ENOMEM)
364 atomic_inc(&sk->sk_drops);
365 break; 363 break;
366 } 364 }
367 365
@@ -716,8 +714,8 @@ static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg)
716 return -EINVAL; 714 return -EINVAL;
717 715
718 lock_sock(sk); 716 lock_sock(sk);
719 if (sock_flag(sk, SOCK_URGINLINE) 717 if (sock_flag(sk, SOCK_URGINLINE) &&
720 && !skb_queue_empty(&pn->ctrlreq_queue)) 718 !skb_queue_empty(&pn->ctrlreq_queue))
721 answ = skb_peek(&pn->ctrlreq_queue)->len; 719 answ = skb_peek(&pn->ctrlreq_queue)->len;
722 else if (!skb_queue_empty(&sk->sk_receive_queue)) 720 else if (!skb_queue_empty(&sk->sk_receive_queue))
723 answ = skb_peek(&sk->sk_receive_queue)->len; 721 answ = skb_peek(&sk->sk_receive_queue)->len;
@@ -845,7 +843,7 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk,
845 struct msghdr *msg, size_t len) 843 struct msghdr *msg, size_t len)
846{ 844{
847 struct pep_sock *pn = pep_sk(sk); 845 struct pep_sock *pn = pep_sk(sk);
848 struct sk_buff *skb = NULL; 846 struct sk_buff *skb;
849 long timeo; 847 long timeo;
850 int flags = msg->msg_flags; 848 int flags = msg->msg_flags;
851 int err, done; 849 int err, done;
@@ -853,6 +851,16 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk,
853 if (msg->msg_flags & MSG_OOB || !(msg->msg_flags & MSG_EOR)) 851 if (msg->msg_flags & MSG_OOB || !(msg->msg_flags & MSG_EOR))
854 return -EOPNOTSUPP; 852 return -EOPNOTSUPP;
855 853
854 skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len,
855 flags & MSG_DONTWAIT, &err);
856 if (!skb)
857 return -ENOBUFS;
858
859 skb_reserve(skb, MAX_PHONET_HEADER + 3);
860 err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
861 if (err < 0)
862 goto outfree;
863
856 lock_sock(sk); 864 lock_sock(sk);
857 timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); 865 timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
858 if ((1 << sk->sk_state) & (TCPF_LISTEN|TCPF_CLOSE)) { 866 if ((1 << sk->sk_state) & (TCPF_LISTEN|TCPF_CLOSE)) {
@@ -896,28 +904,13 @@ disabled:
896 goto disabled; 904 goto disabled;
897 } 905 }
898 906
899 if (!skb) {
900 skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len,
901 flags & MSG_DONTWAIT, &err);
902 if (skb == NULL)
903 goto out;
904 skb_reserve(skb, MAX_PHONET_HEADER + 3);
905
906 if (sk->sk_state != TCP_ESTABLISHED ||
907 !atomic_read(&pn->tx_credits))
908 goto disabled; /* sock_alloc_send_skb might sleep */
909 }
910
911 err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
912 if (err < 0)
913 goto out;
914
915 err = pipe_skb_send(sk, skb); 907 err = pipe_skb_send(sk, skb);
916 if (err >= 0) 908 if (err >= 0)
917 err = len; /* success! */ 909 err = len; /* success! */
918 skb = NULL; 910 skb = NULL;
919out: 911out:
920 release_sock(sk); 912 release_sock(sk);
913outfree:
921 kfree_skb(skb); 914 kfree_skb(skb);
922 return err; 915 return err;
923} 916}
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
index 5f42f30dd168..bc4a33bf2d3d 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -33,11 +33,17 @@
33#include <net/netns/generic.h> 33#include <net/netns/generic.h>
34#include <net/phonet/pn_dev.h> 34#include <net/phonet/pn_dev.h>
35 35
36struct phonet_routes {
37 struct mutex lock;
38 struct net_device *table[64];
39};
40
36struct phonet_net { 41struct phonet_net {
37 struct phonet_device_list pndevs; 42 struct phonet_device_list pndevs;
43 struct phonet_routes routes;
38}; 44};
39 45
40int phonet_net_id; 46int phonet_net_id __read_mostly;
41 47
42struct phonet_device_list *phonet_device_list(struct net *net) 48struct phonet_device_list *phonet_device_list(struct net *net)
43{ 49{
@@ -55,7 +61,8 @@ static struct phonet_device *__phonet_device_alloc(struct net_device *dev)
55 pnd->netdev = dev; 61 pnd->netdev = dev;
56 bitmap_zero(pnd->addrs, 64); 62 bitmap_zero(pnd->addrs, 64);
57 63
58 list_add(&pnd->list, &pndevs->list); 64 BUG_ON(!mutex_is_locked(&pndevs->lock));
65 list_add_rcu(&pnd->list, &pndevs->list);
59 return pnd; 66 return pnd;
60} 67}
61 68
@@ -64,6 +71,7 @@ static struct phonet_device *__phonet_get(struct net_device *dev)
64 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); 71 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
65 struct phonet_device *pnd; 72 struct phonet_device *pnd;
66 73
74 BUG_ON(!mutex_is_locked(&pndevs->lock));
67 list_for_each_entry(pnd, &pndevs->list, list) { 75 list_for_each_entry(pnd, &pndevs->list, list) {
68 if (pnd->netdev == dev) 76 if (pnd->netdev == dev)
69 return pnd; 77 return pnd;
@@ -71,6 +79,18 @@ static struct phonet_device *__phonet_get(struct net_device *dev)
71 return NULL; 79 return NULL;
72} 80}
73 81
82static struct phonet_device *__phonet_get_rcu(struct net_device *dev)
83{
84 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
85 struct phonet_device *pnd;
86
87 list_for_each_entry_rcu(pnd, &pndevs->list, list) {
88 if (pnd->netdev == dev)
89 return pnd;
90 }
91 return NULL;
92}
93
74static void phonet_device_destroy(struct net_device *dev) 94static void phonet_device_destroy(struct net_device *dev)
75{ 95{
76 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); 96 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
@@ -78,11 +98,11 @@ static void phonet_device_destroy(struct net_device *dev)
78 98
79 ASSERT_RTNL(); 99 ASSERT_RTNL();
80 100
81 spin_lock_bh(&pndevs->lock); 101 mutex_lock(&pndevs->lock);
82 pnd = __phonet_get(dev); 102 pnd = __phonet_get(dev);
83 if (pnd) 103 if (pnd)
84 list_del(&pnd->list); 104 list_del_rcu(&pnd->list);
85 spin_unlock_bh(&pndevs->lock); 105 mutex_unlock(&pndevs->lock);
86 106
87 if (pnd) { 107 if (pnd) {
88 u8 addr; 108 u8 addr;
@@ -100,8 +120,8 @@ struct net_device *phonet_device_get(struct net *net)
100 struct phonet_device *pnd; 120 struct phonet_device *pnd;
101 struct net_device *dev = NULL; 121 struct net_device *dev = NULL;
102 122
103 spin_lock_bh(&pndevs->lock); 123 rcu_read_lock();
104 list_for_each_entry(pnd, &pndevs->list, list) { 124 list_for_each_entry_rcu(pnd, &pndevs->list, list) {
105 dev = pnd->netdev; 125 dev = pnd->netdev;
106 BUG_ON(!dev); 126 BUG_ON(!dev);
107 127
@@ -112,7 +132,7 @@ struct net_device *phonet_device_get(struct net *net)
112 } 132 }
113 if (dev) 133 if (dev)
114 dev_hold(dev); 134 dev_hold(dev);
115 spin_unlock_bh(&pndevs->lock); 135 rcu_read_unlock();
116 return dev; 136 return dev;
117} 137}
118 138
@@ -122,7 +142,7 @@ int phonet_address_add(struct net_device *dev, u8 addr)
122 struct phonet_device *pnd; 142 struct phonet_device *pnd;
123 int err = 0; 143 int err = 0;
124 144
125 spin_lock_bh(&pndevs->lock); 145 mutex_lock(&pndevs->lock);
126 /* Find or create Phonet-specific device data */ 146 /* Find or create Phonet-specific device data */
127 pnd = __phonet_get(dev); 147 pnd = __phonet_get(dev);
128 if (pnd == NULL) 148 if (pnd == NULL)
@@ -131,7 +151,7 @@ int phonet_address_add(struct net_device *dev, u8 addr)
131 err = -ENOMEM; 151 err = -ENOMEM;
132 else if (test_and_set_bit(addr >> 2, pnd->addrs)) 152 else if (test_and_set_bit(addr >> 2, pnd->addrs))
133 err = -EEXIST; 153 err = -EEXIST;
134 spin_unlock_bh(&pndevs->lock); 154 mutex_unlock(&pndevs->lock);
135 return err; 155 return err;
136} 156}
137 157
@@ -141,36 +161,56 @@ int phonet_address_del(struct net_device *dev, u8 addr)
141 struct phonet_device *pnd; 161 struct phonet_device *pnd;
142 int err = 0; 162 int err = 0;
143 163
144 spin_lock_bh(&pndevs->lock); 164 mutex_lock(&pndevs->lock);
145 pnd = __phonet_get(dev); 165 pnd = __phonet_get(dev);
146 if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) 166 if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) {
147 err = -EADDRNOTAVAIL; 167 err = -EADDRNOTAVAIL;
148 else if (bitmap_empty(pnd->addrs, 64)) { 168 pnd = NULL;
149 list_del(&pnd->list); 169 } else if (bitmap_empty(pnd->addrs, 64))
170 list_del_rcu(&pnd->list);
171 else
172 pnd = NULL;
173 mutex_unlock(&pndevs->lock);
174
175 if (pnd) {
176 synchronize_rcu();
150 kfree(pnd); 177 kfree(pnd);
151 } 178 }
152 spin_unlock_bh(&pndevs->lock);
153 return err; 179 return err;
154} 180}
155 181
156/* Gets a source address toward a destination, through a interface. */ 182/* Gets a source address toward a destination, through a interface. */
157u8 phonet_address_get(struct net_device *dev, u8 addr) 183u8 phonet_address_get(struct net_device *dev, u8 daddr)
158{ 184{
159 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
160 struct phonet_device *pnd; 185 struct phonet_device *pnd;
186 u8 saddr;
161 187
162 spin_lock_bh(&pndevs->lock); 188 rcu_read_lock();
163 pnd = __phonet_get(dev); 189 pnd = __phonet_get_rcu(dev);
164 if (pnd) { 190 if (pnd) {
165 BUG_ON(bitmap_empty(pnd->addrs, 64)); 191 BUG_ON(bitmap_empty(pnd->addrs, 64));
166 192
167 /* Use same source address as destination, if possible */ 193 /* Use same source address as destination, if possible */
168 if (!test_bit(addr >> 2, pnd->addrs)) 194 if (test_bit(daddr >> 2, pnd->addrs))
169 addr = find_first_bit(pnd->addrs, 64) << 2; 195 saddr = daddr;
196 else
197 saddr = find_first_bit(pnd->addrs, 64) << 2;
170 } else 198 } else
171 addr = PN_NO_ADDR; 199 saddr = PN_NO_ADDR;
172 spin_unlock_bh(&pndevs->lock); 200 rcu_read_unlock();
173 return addr; 201
202 if (saddr == PN_NO_ADDR) {
203 /* Fallback to another device */
204 struct net_device *def_dev;
205
206 def_dev = phonet_device_get(dev_net(dev));
207 if (def_dev) {
208 if (def_dev != dev)
209 saddr = phonet_address_get(def_dev, daddr);
210 dev_put(def_dev);
211 }
212 }
213 return saddr;
174} 214}
175 215
176int phonet_address_lookup(struct net *net, u8 addr) 216int phonet_address_lookup(struct net *net, u8 addr)
@@ -179,8 +219,8 @@ int phonet_address_lookup(struct net *net, u8 addr)
179 struct phonet_device *pnd; 219 struct phonet_device *pnd;
180 int err = -EADDRNOTAVAIL; 220 int err = -EADDRNOTAVAIL;
181 221
182 spin_lock_bh(&pndevs->lock); 222 rcu_read_lock();
183 list_for_each_entry(pnd, &pndevs->list, list) { 223 list_for_each_entry_rcu(pnd, &pndevs->list, list) {
184 /* Don't allow unregistering devices! */ 224 /* Don't allow unregistering devices! */
185 if ((pnd->netdev->reg_state != NETREG_REGISTERED) || 225 if ((pnd->netdev->reg_state != NETREG_REGISTERED) ||
186 ((pnd->netdev->flags & IFF_UP)) != IFF_UP) 226 ((pnd->netdev->flags & IFF_UP)) != IFF_UP)
@@ -192,7 +232,7 @@ int phonet_address_lookup(struct net *net, u8 addr)
192 } 232 }
193 } 233 }
194found: 234found:
195 spin_unlock_bh(&pndevs->lock); 235 rcu_read_unlock();
196 return err; 236 return err;
197} 237}
198 238
@@ -219,6 +259,32 @@ static int phonet_device_autoconf(struct net_device *dev)
219 return 0; 259 return 0;
220} 260}
221 261
262static void phonet_route_autodel(struct net_device *dev)
263{
264 struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id);
265 unsigned i;
266 DECLARE_BITMAP(deleted, 64);
267
268 /* Remove left-over Phonet routes */
269 bitmap_zero(deleted, 64);
270 mutex_lock(&pnn->routes.lock);
271 for (i = 0; i < 64; i++)
272 if (dev == pnn->routes.table[i]) {
273 rcu_assign_pointer(pnn->routes.table[i], NULL);
274 set_bit(i, deleted);
275 }
276 mutex_unlock(&pnn->routes.lock);
277
278 if (bitmap_empty(deleted, 64))
279 return; /* short-circuit RCU */
280 synchronize_rcu();
281 for (i = find_first_bit(deleted, 64); i < 64;
282 i = find_next_bit(deleted, 64, i + 1)) {
283 rtm_phonet_notify(RTM_DELROUTE, dev, i);
284 dev_put(dev);
285 }
286}
287
222/* notify Phonet of device events */ 288/* notify Phonet of device events */
223static int phonet_device_notify(struct notifier_block *me, unsigned long what, 289static int phonet_device_notify(struct notifier_block *me, unsigned long what,
224 void *arg) 290 void *arg)
@@ -232,6 +298,7 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what,
232 break; 298 break;
233 case NETDEV_UNREGISTER: 299 case NETDEV_UNREGISTER:
234 phonet_device_destroy(dev); 300 phonet_device_destroy(dev);
301 phonet_route_autodel(dev);
235 break; 302 break;
236 } 303 }
237 return 0; 304 return 0;
@@ -246,18 +313,14 @@ static struct notifier_block phonet_device_notifier = {
246/* Per-namespace Phonet devices handling */ 313/* Per-namespace Phonet devices handling */
247static int phonet_init_net(struct net *net) 314static int phonet_init_net(struct net *net)
248{ 315{
249 struct phonet_net *pnn = kmalloc(sizeof(*pnn), GFP_KERNEL); 316 struct phonet_net *pnn = net_generic(net, phonet_net_id);
250 if (!pnn)
251 return -ENOMEM;
252 317
253 if (!proc_net_fops_create(net, "phonet", 0, &pn_sock_seq_fops)) { 318 if (!proc_net_fops_create(net, "phonet", 0, &pn_sock_seq_fops))
254 kfree(pnn);
255 return -ENOMEM; 319 return -ENOMEM;
256 }
257 320
258 INIT_LIST_HEAD(&pnn->pndevs.list); 321 INIT_LIST_HEAD(&pnn->pndevs.list);
259 spin_lock_init(&pnn->pndevs.lock); 322 mutex_init(&pnn->pndevs.lock);
260 net_assign_generic(net, phonet_net_id, pnn); 323 mutex_init(&pnn->routes.lock);
261 return 0; 324 return 0;
262} 325}
263 326
@@ -265,25 +328,35 @@ static void phonet_exit_net(struct net *net)
265{ 328{
266 struct phonet_net *pnn = net_generic(net, phonet_net_id); 329 struct phonet_net *pnn = net_generic(net, phonet_net_id);
267 struct net_device *dev; 330 struct net_device *dev;
331 unsigned i;
268 332
269 rtnl_lock(); 333 rtnl_lock();
270 for_each_netdev(net, dev) 334 for_each_netdev(net, dev)
271 phonet_device_destroy(dev); 335 phonet_device_destroy(dev);
336
337 for (i = 0; i < 64; i++) {
338 dev = pnn->routes.table[i];
339 if (dev) {
340 rtm_phonet_notify(RTM_DELROUTE, dev, i);
341 dev_put(dev);
342 }
343 }
272 rtnl_unlock(); 344 rtnl_unlock();
273 345
274 proc_net_remove(net, "phonet"); 346 proc_net_remove(net, "phonet");
275 kfree(pnn);
276} 347}
277 348
278static struct pernet_operations phonet_net_ops = { 349static struct pernet_operations phonet_net_ops = {
279 .init = phonet_init_net, 350 .init = phonet_init_net,
280 .exit = phonet_exit_net, 351 .exit = phonet_exit_net,
352 .id = &phonet_net_id,
353 .size = sizeof(struct phonet_net),
281}; 354};
282 355
283/* Initialize Phonet devices list */ 356/* Initialize Phonet devices list */
284int __init phonet_device_init(void) 357int __init phonet_device_init(void)
285{ 358{
286 int err = register_pernet_gen_device(&phonet_net_id, &phonet_net_ops); 359 int err = register_pernet_device(&phonet_net_ops);
287 if (err) 360 if (err)
288 return err; 361 return err;
289 362
@@ -298,5 +371,75 @@ void phonet_device_exit(void)
298{ 371{
299 rtnl_unregister_all(PF_PHONET); 372 rtnl_unregister_all(PF_PHONET);
300 unregister_netdevice_notifier(&phonet_device_notifier); 373 unregister_netdevice_notifier(&phonet_device_notifier);
301 unregister_pernet_gen_device(phonet_net_id, &phonet_net_ops); 374 unregister_pernet_device(&phonet_net_ops);
375}
376
377int phonet_route_add(struct net_device *dev, u8 daddr)
378{
379 struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id);
380 struct phonet_routes *routes = &pnn->routes;
381 int err = -EEXIST;
382
383 daddr = daddr >> 2;
384 mutex_lock(&routes->lock);
385 if (routes->table[daddr] == NULL) {
386 rcu_assign_pointer(routes->table[daddr], dev);
387 dev_hold(dev);
388 err = 0;
389 }
390 mutex_unlock(&routes->lock);
391 return err;
392}
393
394int phonet_route_del(struct net_device *dev, u8 daddr)
395{
396 struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id);
397 struct phonet_routes *routes = &pnn->routes;
398
399 daddr = daddr >> 2;
400 mutex_lock(&routes->lock);
401 if (dev == routes->table[daddr])
402 rcu_assign_pointer(routes->table[daddr], NULL);
403 else
404 dev = NULL;
405 mutex_unlock(&routes->lock);
406
407 if (!dev)
408 return -ENOENT;
409 synchronize_rcu();
410 dev_put(dev);
411 return 0;
412}
413
414struct net_device *phonet_route_get(struct net *net, u8 daddr)
415{
416 struct phonet_net *pnn = net_generic(net, phonet_net_id);
417 struct phonet_routes *routes = &pnn->routes;
418 struct net_device *dev;
419
420 ASSERT_RTNL(); /* no need to hold the device */
421
422 daddr >>= 2;
423 rcu_read_lock();
424 dev = rcu_dereference(routes->table[daddr]);
425 rcu_read_unlock();
426 return dev;
427}
428
429struct net_device *phonet_route_output(struct net *net, u8 daddr)
430{
431 struct phonet_net *pnn = net_generic(net, phonet_net_id);
432 struct phonet_routes *routes = &pnn->routes;
433 struct net_device *dev;
434
435 daddr >>= 2;
436 rcu_read_lock();
437 dev = rcu_dereference(routes->table[daddr]);
438 if (dev)
439 dev_hold(dev);
440 rcu_read_unlock();
441
442 if (!dev)
443 dev = phonet_device_get(net); /* Default route */
444 return dev;
302} 445}
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index d21fd3576610..2e6c7eb8e76a 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -29,6 +29,8 @@
29#include <net/sock.h> 29#include <net/sock.h>
30#include <net/phonet/pn_dev.h> 30#include <net/phonet/pn_dev.h>
31 31
32/* Device address handling */
33
32static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, 34static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
33 u32 pid, u32 seq, int event); 35 u32 pid, u32 seq, int event);
34 36
@@ -51,8 +53,7 @@ void phonet_address_notify(int event, struct net_device *dev, u8 addr)
51 RTNLGRP_PHONET_IFADDR, NULL, GFP_KERNEL); 53 RTNLGRP_PHONET_IFADDR, NULL, GFP_KERNEL);
52 return; 54 return;
53errout: 55errout:
54 if (err < 0) 56 rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err);
55 rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err);
56} 57}
57 58
58static const struct nla_policy ifa_phonet_policy[IFA_MAX+1] = { 59static const struct nla_policy ifa_phonet_policy[IFA_MAX+1] = {
@@ -130,8 +131,8 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
130 int addr_idx = 0, addr_start_idx = cb->args[1]; 131 int addr_idx = 0, addr_start_idx = cb->args[1];
131 132
132 pndevs = phonet_device_list(sock_net(skb->sk)); 133 pndevs = phonet_device_list(sock_net(skb->sk));
133 spin_lock_bh(&pndevs->lock); 134 rcu_read_lock();
134 list_for_each_entry(pnd, &pndevs->list, list) { 135 list_for_each_entry_rcu(pnd, &pndevs->list, list) {
135 u8 addr; 136 u8 addr;
136 137
137 if (dev_idx > dev_start_idx) 138 if (dev_idx > dev_start_idx)
@@ -153,13 +154,137 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
153 } 154 }
154 155
155out: 156out:
156 spin_unlock_bh(&pndevs->lock); 157 rcu_read_unlock();
157 cb->args[0] = dev_idx; 158 cb->args[0] = dev_idx;
158 cb->args[1] = addr_idx; 159 cb->args[1] = addr_idx;
159 160
160 return skb->len; 161 return skb->len;
161} 162}
162 163
164/* Routes handling */
165
166static int fill_route(struct sk_buff *skb, struct net_device *dev, u8 dst,
167 u32 pid, u32 seq, int event)
168{
169 struct rtmsg *rtm;
170 struct nlmsghdr *nlh;
171
172 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), 0);
173 if (nlh == NULL)
174 return -EMSGSIZE;
175
176 rtm = nlmsg_data(nlh);
177 rtm->rtm_family = AF_PHONET;
178 rtm->rtm_dst_len = 6;
179 rtm->rtm_src_len = 0;
180 rtm->rtm_tos = 0;
181 rtm->rtm_table = RT_TABLE_MAIN;
182 rtm->rtm_protocol = RTPROT_STATIC;
183 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
184 rtm->rtm_type = RTN_UNICAST;
185 rtm->rtm_flags = 0;
186 NLA_PUT_U8(skb, RTA_DST, dst);
187 NLA_PUT_U32(skb, RTA_OIF, dev->ifindex);
188 return nlmsg_end(skb, nlh);
189
190nla_put_failure:
191 nlmsg_cancel(skb, nlh);
192 return -EMSGSIZE;
193}
194
195void rtm_phonet_notify(int event, struct net_device *dev, u8 dst)
196{
197 struct sk_buff *skb;
198 int err = -ENOBUFS;
199
200 skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
201 nla_total_size(1) + nla_total_size(4), GFP_KERNEL);
202 if (skb == NULL)
203 goto errout;
204 err = fill_route(skb, dev, dst, 0, 0, event);
205 if (err < 0) {
206 WARN_ON(err == -EMSGSIZE);
207 kfree_skb(skb);
208 goto errout;
209 }
210 rtnl_notify(skb, dev_net(dev), 0,
211 RTNLGRP_PHONET_ROUTE, NULL, GFP_KERNEL);
212 return;
213errout:
214 rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_ROUTE, err);
215}
216
217static const struct nla_policy rtm_phonet_policy[RTA_MAX+1] = {
218 [RTA_DST] = { .type = NLA_U8 },
219 [RTA_OIF] = { .type = NLA_U32 },
220};
221
222static int route_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
223{
224 struct net *net = sock_net(skb->sk);
225 struct nlattr *tb[RTA_MAX+1];
226 struct net_device *dev;
227 struct rtmsg *rtm;
228 int err;
229 u8 dst;
230
231 if (!capable(CAP_SYS_ADMIN))
232 return -EPERM;
233
234 ASSERT_RTNL();
235
236 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_phonet_policy);
237 if (err < 0)
238 return err;
239
240 rtm = nlmsg_data(nlh);
241 if (rtm->rtm_table != RT_TABLE_MAIN || rtm->rtm_type != RTN_UNICAST)
242 return -EINVAL;
243 if (tb[RTA_DST] == NULL || tb[RTA_OIF] == NULL)
244 return -EINVAL;
245 dst = nla_get_u8(tb[RTA_DST]);
246 if (dst & 3) /* Phonet addresses only have 6 high-order bits */
247 return -EINVAL;
248
249 dev = __dev_get_by_index(net, nla_get_u32(tb[RTA_OIF]));
250 if (dev == NULL)
251 return -ENODEV;
252
253 if (nlh->nlmsg_type == RTM_NEWROUTE)
254 err = phonet_route_add(dev, dst);
255 else
256 err = phonet_route_del(dev, dst);
257 if (!err)
258 rtm_phonet_notify(nlh->nlmsg_type, dev, dst);
259 return err;
260}
261
262static int route_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
263{
264 struct net *net = sock_net(skb->sk);
265 u8 addr, addr_idx = 0, addr_start_idx = cb->args[0];
266
267 for (addr = 0; addr < 64; addr++) {
268 struct net_device *dev;
269
270 dev = phonet_route_get(net, addr << 2);
271 if (!dev)
272 continue;
273
274 if (addr_idx++ < addr_start_idx)
275 continue;
276 if (fill_route(skb, dev, addr << 2, NETLINK_CB(cb->skb).pid,
277 cb->nlh->nlmsg_seq, RTM_NEWROUTE))
278 goto out;
279 }
280
281out:
282 cb->args[0] = addr_idx;
283 cb->args[1] = 0;
284
285 return skb->len;
286}
287
163int __init phonet_netlink_register(void) 288int __init phonet_netlink_register(void)
164{ 289{
165 int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL); 290 int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL);
@@ -169,5 +294,8 @@ int __init phonet_netlink_register(void)
169 /* Further __rtnl_register() cannot fail */ 294 /* Further __rtnl_register() cannot fail */
170 __rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL); 295 __rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL);
171 __rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit); 296 __rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit);
297 __rtnl_register(PF_PHONET, RTM_NEWROUTE, route_doit, NULL);
298 __rtnl_register(PF_PHONET, RTM_DELROUTE, route_doit, NULL);
299 __rtnl_register(PF_PHONET, RTM_GETROUTE, NULL, route_dumpit);
172 return 0; 300 return 0;
173} 301}
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index aa5b5a972bff..69c8b826a0ce 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -45,13 +45,28 @@ static int pn_socket_release(struct socket *sock)
45 return 0; 45 return 0;
46} 46}
47 47
48#define PN_HASHSIZE 16
49#define PN_HASHMASK (PN_HASHSIZE-1)
50
51
48static struct { 52static struct {
49 struct hlist_head hlist; 53 struct hlist_head hlist[PN_HASHSIZE];
50 spinlock_t lock; 54 spinlock_t lock;
51} pnsocks = { 55} pnsocks;
52 .hlist = HLIST_HEAD_INIT, 56
53 .lock = __SPIN_LOCK_UNLOCKED(pnsocks.lock), 57void __init pn_sock_init(void)
54}; 58{
59 unsigned i;
60
61 for (i = 0; i < PN_HASHSIZE; i++)
62 INIT_HLIST_HEAD(pnsocks.hlist + i);
63 spin_lock_init(&pnsocks.lock);
64}
65
66static struct hlist_head *pn_hash_list(u16 obj)
67{
68 return pnsocks.hlist + (obj & PN_HASHMASK);
69}
55 70
56/* 71/*
57 * Find address based on socket address, match only certain fields. 72 * Find address based on socket address, match only certain fields.
@@ -64,10 +79,11 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
64 struct sock *rval = NULL; 79 struct sock *rval = NULL;
65 u16 obj = pn_sockaddr_get_object(spn); 80 u16 obj = pn_sockaddr_get_object(spn);
66 u8 res = spn->spn_resource; 81 u8 res = spn->spn_resource;
82 struct hlist_head *hlist = pn_hash_list(obj);
67 83
68 spin_lock_bh(&pnsocks.lock); 84 spin_lock_bh(&pnsocks.lock);
69 85
70 sk_for_each(sknode, node, &pnsocks.hlist) { 86 sk_for_each(sknode, node, hlist) {
71 struct pn_sock *pn = pn_sk(sknode); 87 struct pn_sock *pn = pn_sk(sknode);
72 BUG_ON(!pn->sobject); /* unbound socket */ 88 BUG_ON(!pn->sobject); /* unbound socket */
73 89
@@ -82,8 +98,8 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
82 if (pn->resource != res) 98 if (pn->resource != res)
83 continue; 99 continue;
84 } 100 }
85 if (pn_addr(pn->sobject) 101 if (pn_addr(pn->sobject) &&
86 && pn_addr(pn->sobject) != pn_addr(obj)) 102 pn_addr(pn->sobject) != pn_addr(obj))
87 continue; 103 continue;
88 104
89 rval = sknode; 105 rval = sknode;
@@ -94,13 +110,44 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
94 spin_unlock_bh(&pnsocks.lock); 110 spin_unlock_bh(&pnsocks.lock);
95 111
96 return rval; 112 return rval;
113}
114
115/* Deliver a broadcast packet (only in bottom-half) */
116void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb)
117{
118 struct hlist_head *hlist = pnsocks.hlist;
119 unsigned h;
120
121 spin_lock(&pnsocks.lock);
122 for (h = 0; h < PN_HASHSIZE; h++) {
123 struct hlist_node *node;
124 struct sock *sknode;
125
126 sk_for_each(sknode, node, hlist) {
127 struct sk_buff *clone;
128
129 if (!net_eq(sock_net(sknode), net))
130 continue;
131 if (!sock_flag(sknode, SOCK_BROADCAST))
132 continue;
97 133
134 clone = skb_clone(skb, GFP_ATOMIC);
135 if (clone) {
136 sock_hold(sknode);
137 sk_receive_skb(sknode, clone, 0);
138 }
139 }
140 hlist++;
141 }
142 spin_unlock(&pnsocks.lock);
98} 143}
99 144
100void pn_sock_hash(struct sock *sk) 145void pn_sock_hash(struct sock *sk)
101{ 146{
147 struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject);
148
102 spin_lock_bh(&pnsocks.lock); 149 spin_lock_bh(&pnsocks.lock);
103 sk_add_node(sk, &pnsocks.hlist); 150 sk_add_node(sk, hlist);
104 spin_unlock_bh(&pnsocks.lock); 151 spin_unlock_bh(&pnsocks.lock);
105} 152}
106EXPORT_SYMBOL(pn_sock_hash); 153EXPORT_SYMBOL(pn_sock_hash);
@@ -416,15 +463,20 @@ EXPORT_SYMBOL(pn_sock_get_port);
416static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos) 463static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos)
417{ 464{
418 struct net *net = seq_file_net(seq); 465 struct net *net = seq_file_net(seq);
466 struct hlist_head *hlist = pnsocks.hlist;
419 struct hlist_node *node; 467 struct hlist_node *node;
420 struct sock *sknode; 468 struct sock *sknode;
469 unsigned h;
421 470
422 sk_for_each(sknode, node, &pnsocks.hlist) { 471 for (h = 0; h < PN_HASHSIZE; h++) {
423 if (!net_eq(net, sock_net(sknode))) 472 sk_for_each(sknode, node, hlist) {
424 continue; 473 if (!net_eq(net, sock_net(sknode)))
425 if (!pos) 474 continue;
426 return sknode; 475 if (!pos)
427 pos--; 476 return sknode;
477 pos--;
478 }
479 hlist++;
428 } 480 }
429 return NULL; 481 return NULL;
430} 482}