19ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin/*
29ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * Raw IEEE 802.15.4 sockets
39ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin *
49ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * Copyright 2007, 2008 Siemens AG
59ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin *
69ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * This program is free software; you can redistribute it and/or modify
79ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * it under the terms of the GNU General Public License version 2
89ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * as published by the Free Software Foundation.
99ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin *
109ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * This program is distributed in the hope that it will be useful,
119ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * but WITHOUT ANY WARRANTY; without even the implied warranty of
129ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
139ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * GNU General Public License for more details.
149ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin *
159ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * You should have received a copy of the GNU General Public License along
169ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * with this program; if not, write to the Free Software Foundation, Inc.,
179ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
189ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin *
199ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * Written by:
209ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * Sergey Lapin <slapin@ossfans.org>
219ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
229ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin */
239ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
249ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin#include <linux/net.h>
259ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin#include <linux/module.h>
269ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin#include <linux/if_arp.h>
279ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin#include <linux/list.h>
285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
299ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin#include <net/sock.h>
30f0166e5e3cdab66d5a31f796ce18e21fd3ce99dcDmitry Eremin-Solenikov#include <net/af_ieee802154.h>
31e6278d92005e9d6e374f269b4ce39c908a68ad5dPhoebe Buckheister#include <net/ieee802154_netdev.h>
329ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
339ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin#include "af802154.h"
349ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
359ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic HLIST_HEAD(raw_head);
369ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic DEFINE_RWLOCK(raw_lock);
379ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
389ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic void raw_hash(struct sock *sk)
399ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
409ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	write_lock_bh(&raw_lock);
419ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	sk_add_node(sk, &raw_head);
429ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
439ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	write_unlock_bh(&raw_lock);
449ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
459ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
469ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic void raw_unhash(struct sock *sk)
479ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
489ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	write_lock_bh(&raw_lock);
499ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (sk_del_node_init(sk))
509ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
519ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	write_unlock_bh(&raw_lock);
529ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
539ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
549ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic void raw_close(struct sock *sk, long timeout)
559ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
569ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	sk_common_release(sk);
579ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
589ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
59e6278d92005e9d6e374f269b4ce39c908a68ad5dPhoebe Buckheisterstatic int raw_bind(struct sock *sk, struct sockaddr *_uaddr, int len)
609ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
61e6278d92005e9d6e374f269b4ce39c908a68ad5dPhoebe Buckheister	struct ieee802154_addr addr;
62e6278d92005e9d6e374f269b4ce39c908a68ad5dPhoebe Buckheister	struct sockaddr_ieee802154 *uaddr = (struct sockaddr_ieee802154 *)_uaddr;
639ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	int err = 0;
649ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct net_device *dev = NULL;
659ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
66e6278d92005e9d6e374f269b4ce39c908a68ad5dPhoebe Buckheister	if (len < sizeof(*uaddr))
679ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		return -EINVAL;
689ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
69e6278d92005e9d6e374f269b4ce39c908a68ad5dPhoebe Buckheister	uaddr = (struct sockaddr_ieee802154 *)_uaddr;
70e6278d92005e9d6e374f269b4ce39c908a68ad5dPhoebe Buckheister	if (uaddr->family != AF_IEEE802154)
719ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		return -EINVAL;
729ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
739ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	lock_sock(sk);
749ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
75e6278d92005e9d6e374f269b4ce39c908a68ad5dPhoebe Buckheister	ieee802154_addr_from_sa(&addr, &uaddr->addr);
76e6278d92005e9d6e374f269b4ce39c908a68ad5dPhoebe Buckheister	dev = ieee802154_get_dev(sock_net(sk), &addr);
779ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (!dev) {
789ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		err = -ENODEV;
799ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out;
809ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
819ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
82929122cdd5d4c344e59f9b55f870a8fcf7aa0d27Dmitry Eremin-Solenikov	if (dev->type != ARPHRD_IEEE802154) {
839ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		err = -ENODEV;
849ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out_put;
859ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
869ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
879ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	sk->sk_bound_dev_if = dev->ifindex;
889ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	sk_dst_reset(sk);
899ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
909ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout_put:
919ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	dev_put(dev);
929ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout:
939ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	release_sock(sk);
949ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
959ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return err;
969ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
979ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
989ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic int raw_connect(struct sock *sk, struct sockaddr *uaddr,
994710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram		       int addr_len)
1009ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
1019ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return -ENOTSUPP;
1029ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
1039ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1049ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic int raw_disconnect(struct sock *sk, int flags)
1059ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
1069ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return 0;
1079ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
1089ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1094710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadramstatic int raw_sendmsg(struct kiocb *iocb, struct sock *sk,
1104710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram		       struct msghdr *msg, size_t size)
1119ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
1129ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct net_device *dev;
11395c961747284a6b83a5e2d81240e214b0fa3464dEric Dumazet	unsigned int mtu;
1149ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct sk_buff *skb;
115ae641949df01b85117845bec45328eab6d6fada1Herbert Xu	int hlen, tlen;
1169ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	int err;
1179ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1189ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (msg->msg_flags & MSG_OOB) {
1199ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags);
1209ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		return -EOPNOTSUPP;
1219ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
1229ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1239ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	lock_sock(sk);
1249ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (!sk->sk_bound_dev_if)
1259ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154);
1269ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	else
1279ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if);
1289ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	release_sock(sk);
1299ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1309ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (!dev) {
1319ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		pr_debug("no dev\n");
1329ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		err = -ENXIO;
1339ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out;
1349ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
1359ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1369ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	mtu = dev->mtu;
1379ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	pr_debug("name = %s, mtu = %u\n", dev->name, mtu);
1389ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1399ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (size > mtu) {
140e5241c448f94feee40b2a285c8bf55d066420073David S. Miller		pr_debug("size = %Zu, mtu = %u\n", size, mtu);
1419ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		err = -EINVAL;
1429ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out_dev;
1439ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
1449ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
145ae641949df01b85117845bec45328eab6d6fada1Herbert Xu	hlen = LL_RESERVED_SPACE(dev);
146ae641949df01b85117845bec45328eab6d6fada1Herbert Xu	tlen = dev->needed_tailroom;
147ae641949df01b85117845bec45328eab6d6fada1Herbert Xu	skb = sock_alloc_send_skb(sk, hlen + tlen + size,
1484710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram				  msg->msg_flags & MSG_DONTWAIT, &err);
1499ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (!skb)
1509ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out_dev;
1519ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
152ae641949df01b85117845bec45328eab6d6fada1Herbert Xu	skb_reserve(skb, hlen);
1539ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1549ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb_reset_mac_header(skb);
1559ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb_reset_network_header(skb);
1569ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1579ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
1589ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (err < 0)
1599ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out_skb;
1609ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1619ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb->dev = dev;
1629ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb->sk  = sk;
1639ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb->protocol = htons(ETH_P_IEEE802154);
1649ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1659ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	dev_put(dev);
1669ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1679ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	err = dev_queue_xmit(skb);
1689ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (err > 0)
1699ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		err = net_xmit_errno(err);
1709ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1719ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return err ?: size;
1729ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1739ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout_skb:
1749ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	kfree_skb(skb);
1759ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout_dev:
1769ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	dev_put(dev);
1779ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout:
1789ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return err;
1799ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
1809ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1819ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
1829ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		       size_t len, int noblock, int flags, int *addr_len)
1839ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
1849ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	size_t copied = 0;
1859ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	int err = -EOPNOTSUPP;
1869ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct sk_buff *skb;
1879ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1889ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb = skb_recv_datagram(sk, flags, noblock, &err);
1899ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (!skb)
1909ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out;
1919ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1929ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	copied = skb->len;
1939ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (len < copied) {
1949ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		msg->msg_flags |= MSG_TRUNC;
1959ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		copied = len;
1969ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
1979ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1989ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
1999ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (err)
2009ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto done;
2019ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2023b885787ea4112eaa80945999ea0901bf742707fNeil Horman	sock_recv_ts_and_drops(msg, sk, skb);
2039ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2049ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (flags & MSG_TRUNC)
2059ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		copied = skb->len;
2069ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapindone:
2079ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb_free_datagram(sk, skb);
2089ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout:
2099ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (err)
2109ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		return err;
2119ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return copied;
2129ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
2139ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2149ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic int raw_rcv_skb(struct sock *sk, struct sk_buff *skb)
2159ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
2168cfad496c4257441710735ccef622f3829870164Phoebe Buckheister	skb = skb_share_check(skb, GFP_ATOMIC);
2178cfad496c4257441710735ccef622f3829870164Phoebe Buckheister	if (!skb)
2188cfad496c4257441710735ccef622f3829870164Phoebe Buckheister		return NET_RX_DROP;
2198cfad496c4257441710735ccef622f3829870164Phoebe Buckheister
2209ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (sock_queue_rcv_skb(sk, skb) < 0) {
2219ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		kfree_skb(skb);
2229ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		return NET_RX_DROP;
2239ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
2249ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2259ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return NET_RX_SUCCESS;
2269ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
2279ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2289ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2299ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinvoid ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb)
2309ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
2319ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct sock *sk;
2329ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2339ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	read_lock(&raw_lock);
234b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin	sk_for_each(sk, &raw_head) {
2359ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		bh_lock_sock(sk);
2369ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		if (!sk->sk_bound_dev_if ||
2379ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		    sk->sk_bound_dev_if == dev->ifindex) {
2389ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin			struct sk_buff *clone;
2399ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2409ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin			clone = skb_clone(skb, GFP_ATOMIC);
2419ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin			if (clone)
2429ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin				raw_rcv_skb(sk, clone);
2439ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		}
2449ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		bh_unlock_sock(sk);
2459ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
2469ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	read_unlock(&raw_lock);
2479ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
2489ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
249a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikovstatic int raw_getsockopt(struct sock *sk, int level, int optname,
2504710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram			  char __user *optval, int __user *optlen)
251a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov{
252a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov	return -EOPNOTSUPP;
253a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov}
254a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov
255a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikovstatic int raw_setsockopt(struct sock *sk, int level, int optname,
2564710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram			  char __user *optval, unsigned int optlen)
257a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov{
258a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov	return -EOPNOTSUPP;
259a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov}
260a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov
2619ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstruct proto ieee802154_raw_prot = {
2629ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.name		= "IEEE-802.15.4-RAW",
2639ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.owner		= THIS_MODULE,
2649ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.obj_size	= sizeof(struct sock),
2659ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.close		= raw_close,
2669ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.bind		= raw_bind,
2679ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.sendmsg	= raw_sendmsg,
2689ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.recvmsg	= raw_recvmsg,
2699ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.hash		= raw_hash,
2709ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.unhash		= raw_unhash,
2719ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.connect	= raw_connect,
2729ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.disconnect	= raw_disconnect,
273a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov	.getsockopt	= raw_getsockopt,
274a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov	.setsockopt	= raw_setsockopt,
2759ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin};
276