aboutsummaryrefslogtreecommitdiffstats
path: root/net/phonet/af_phonet.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/phonet/af_phonet.c')
-rw-r--r--net/phonet/af_phonet.c83
1 files changed, 66 insertions, 17 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