raw.c revision ae641949df01b85117845bec45328eab6d6fada1
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>
319ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
329ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin#include "af802154.h"
339ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
349ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic HLIST_HEAD(raw_head);
359ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic DEFINE_RWLOCK(raw_lock);
369ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
379ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic void raw_hash(struct sock *sk)
389ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
399ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	write_lock_bh(&raw_lock);
409ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	sk_add_node(sk, &raw_head);
419ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
429ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	write_unlock_bh(&raw_lock);
439ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
449ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
459ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic void raw_unhash(struct sock *sk)
469ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
479ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	write_lock_bh(&raw_lock);
489ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (sk_del_node_init(sk))
499ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
509ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	write_unlock_bh(&raw_lock);
519ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
529ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
539ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic void raw_close(struct sock *sk, long timeout)
549ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
559ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	sk_common_release(sk);
569ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
579ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
589ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic int raw_bind(struct sock *sk, struct sockaddr *uaddr, int len)
599ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
609ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr;
619ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	int err = 0;
629ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct net_device *dev = NULL;
639ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
649ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (len < sizeof(*addr))
659ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		return -EINVAL;
669ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
679ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (addr->family != AF_IEEE802154)
689ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		return -EINVAL;
699ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
709ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	lock_sock(sk);
719ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
729ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	dev = ieee802154_get_dev(sock_net(sk), &addr->addr);
739ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (!dev) {
749ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		err = -ENODEV;
759ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out;
769ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
779ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
78929122cdd5d4c344e59f9b55f870a8fcf7aa0d27Dmitry Eremin-Solenikov	if (dev->type != ARPHRD_IEEE802154) {
799ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		err = -ENODEV;
809ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out_put;
819ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
829ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
839ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	sk->sk_bound_dev_if = dev->ifindex;
849ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	sk_dst_reset(sk);
859ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
869ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout_put:
879ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	dev_put(dev);
889ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout:
899ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	release_sock(sk);
909ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
919ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return err;
929ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
939ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
949ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic int raw_connect(struct sock *sk, struct sockaddr *uaddr,
959ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin			int addr_len)
969ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
979ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return -ENOTSUPP;
989ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
999ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1009ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic int raw_disconnect(struct sock *sk, int flags)
1019ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
1029ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return 0;
1039ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
1049ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1059ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
1069ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		       size_t size)
1079ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
1089ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct net_device *dev;
1099ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	unsigned mtu;
1109ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct sk_buff *skb;
111ae641949df01b85117845bec45328eab6d6fada1Herbert Xu	int hlen, tlen;
1129ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	int err;
1139ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1149ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (msg->msg_flags & MSG_OOB) {
1159ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags);
1169ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		return -EOPNOTSUPP;
1179ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
1189ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1199ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	lock_sock(sk);
1209ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (!sk->sk_bound_dev_if)
1219ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154);
1229ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	else
1239ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if);
1249ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	release_sock(sk);
1259ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1269ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (!dev) {
1279ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		pr_debug("no dev\n");
1289ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		err = -ENXIO;
1299ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out;
1309ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
1319ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1329ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	mtu = dev->mtu;
1339ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	pr_debug("name = %s, mtu = %u\n", dev->name, mtu);
1349ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1359ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (size > mtu) {
136e5241c448f94feee40b2a285c8bf55d066420073David S. Miller		pr_debug("size = %Zu, mtu = %u\n", size, mtu);
1379ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		err = -EINVAL;
1389ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out_dev;
1399ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
1409ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
141ae641949df01b85117845bec45328eab6d6fada1Herbert Xu	hlen = LL_RESERVED_SPACE(dev);
142ae641949df01b85117845bec45328eab6d6fada1Herbert Xu	tlen = dev->needed_tailroom;
143ae641949df01b85117845bec45328eab6d6fada1Herbert Xu	skb = sock_alloc_send_skb(sk, hlen + tlen + size,
1449ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin			msg->msg_flags & MSG_DONTWAIT, &err);
1459ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (!skb)
1469ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out_dev;
1479ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
148ae641949df01b85117845bec45328eab6d6fada1Herbert Xu	skb_reserve(skb, hlen);
1499ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1509ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb_reset_mac_header(skb);
1519ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb_reset_network_header(skb);
1529ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1539ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
1549ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (err < 0)
1559ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out_skb;
1569ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1579ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb->dev = dev;
1589ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb->sk  = sk;
1599ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb->protocol = htons(ETH_P_IEEE802154);
1609ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1619ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	dev_put(dev);
1629ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1639ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	err = dev_queue_xmit(skb);
1649ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (err > 0)
1659ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		err = net_xmit_errno(err);
1669ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1679ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return err ?: size;
1689ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1699ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout_skb:
1709ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	kfree_skb(skb);
1719ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout_dev:
1729ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	dev_put(dev);
1739ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout:
1749ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return err;
1759ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
1769ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1779ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
1789ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		       size_t len, int noblock, int flags, int *addr_len)
1799ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
1809ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	size_t copied = 0;
1819ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	int err = -EOPNOTSUPP;
1829ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct sk_buff *skb;
1839ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1849ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb = skb_recv_datagram(sk, flags, noblock, &err);
1859ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (!skb)
1869ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto out;
1879ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1889ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	copied = skb->len;
1899ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (len < copied) {
1909ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		msg->msg_flags |= MSG_TRUNC;
1919ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		copied = len;
1929ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
1939ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1949ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
1959ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (err)
1969ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		goto done;
1979ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
1983b885787ea4112eaa80945999ea0901bf742707fNeil Horman	sock_recv_ts_and_drops(msg, sk, skb);
1999ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2009ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (flags & MSG_TRUNC)
2019ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		copied = skb->len;
2029ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapindone:
2039ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	skb_free_datagram(sk, skb);
2049ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinout:
2059ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (err)
2069ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		return err;
2079ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return copied;
2089ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
2099ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2109ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstatic int raw_rcv_skb(struct sock *sk, struct sk_buff *skb)
2119ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
2129ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	if (sock_queue_rcv_skb(sk, skb) < 0) {
2139ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		kfree_skb(skb);
2149ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		return NET_RX_DROP;
2159ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
2169ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2179ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	return NET_RX_SUCCESS;
2189ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
2199ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2209ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2219ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinvoid ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb)
2229ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin{
2239ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct sock *sk;
2249ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	struct hlist_node *node;
2259ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2269ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	read_lock(&raw_lock);
2279ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	sk_for_each(sk, node, &raw_head) {
2289ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		bh_lock_sock(sk);
2299ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		if (!sk->sk_bound_dev_if ||
2309ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		    sk->sk_bound_dev_if == dev->ifindex) {
2319ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2329ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin			struct sk_buff *clone;
2339ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
2349ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin			clone = skb_clone(skb, GFP_ATOMIC);
2359ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin			if (clone)
2369ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin				raw_rcv_skb(sk, clone);
2379ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		}
2389ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin		bh_unlock_sock(sk);
2399ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	}
2409ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	read_unlock(&raw_lock);
2419ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin}
2429ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
243a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikovstatic int raw_getsockopt(struct sock *sk, int level, int optname,
244a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov		    char __user *optval, int __user *optlen)
245a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov{
246a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov	return -EOPNOTSUPP;
247a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov}
248a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov
249a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikovstatic int raw_setsockopt(struct sock *sk, int level, int optname,
250b7058842c940ad2c08dd829b21e5c92ebe3b8758David S. Miller		    char __user *optval, unsigned int optlen)
251a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov{
252a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov	return -EOPNOTSUPP;
253a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov}
254a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov
2559ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapinstruct proto ieee802154_raw_prot = {
2569ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.name		= "IEEE-802.15.4-RAW",
2579ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.owner		= THIS_MODULE,
2589ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.obj_size	= sizeof(struct sock),
2599ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.close		= raw_close,
2609ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.bind		= raw_bind,
2619ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.sendmsg	= raw_sendmsg,
2629ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.recvmsg	= raw_recvmsg,
2639ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.hash		= raw_hash,
2649ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.unhash		= raw_unhash,
2659ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.connect	= raw_connect,
2669ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin	.disconnect	= raw_disconnect,
267a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov	.getsockopt	= raw_getsockopt,
268a9dfac3353b03432e3d46a0dde6795588c46256dDmitry Eremin-Solenikov	.setsockopt	= raw_setsockopt,
2699ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin};
2709ec7671603573ede31207eb5b0b3e1aa211b2854Sergey Lapin
271