• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/net/ieee802154/
1/*
2 * IEEE802154.4 socket interface
3 *
4 * Copyright 2007, 2008 Siemens AG
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Written by:
20 * Sergey Lapin <slapin@ossfans.org>
21 * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
22 */
23
24#include <linux/net.h>
25#include <linux/capability.h>
26#include <linux/module.h>
27#include <linux/if_arp.h>
28#include <linux/if.h>
29#include <linux/termios.h>	/* For TIOCOUTQ/INQ */
30#include <linux/list.h>
31#include <linux/slab.h>
32#include <net/datalink.h>
33#include <net/psnap.h>
34#include <net/sock.h>
35#include <net/tcp_states.h>
36#include <net/route.h>
37
38#include <net/af_ieee802154.h>
39#include <net/ieee802154_netdev.h>
40
41#include "af802154.h"
42
43/*
44 * Utility function for families
45 */
46struct net_device *ieee802154_get_dev(struct net *net,
47		struct ieee802154_addr *addr)
48{
49	struct net_device *dev = NULL;
50	struct net_device *tmp;
51	u16 pan_id, short_addr;
52
53	switch (addr->addr_type) {
54	case IEEE802154_ADDR_LONG:
55		rtnl_lock();
56		dev = dev_getbyhwaddr(net, ARPHRD_IEEE802154, addr->hwaddr);
57		if (dev)
58			dev_hold(dev);
59		rtnl_unlock();
60		break;
61	case IEEE802154_ADDR_SHORT:
62		if (addr->pan_id == 0xffff ||
63		    addr->short_addr == IEEE802154_ADDR_UNDEF ||
64		    addr->short_addr == 0xffff)
65			break;
66
67		rtnl_lock();
68
69		for_each_netdev(net, tmp) {
70			if (tmp->type != ARPHRD_IEEE802154)
71				continue;
72
73			pan_id = ieee802154_mlme_ops(tmp)->get_pan_id(tmp);
74			short_addr =
75				ieee802154_mlme_ops(tmp)->get_short_addr(tmp);
76
77			if (pan_id == addr->pan_id &&
78			    short_addr == addr->short_addr) {
79				dev = tmp;
80				dev_hold(dev);
81				break;
82			}
83		}
84
85		rtnl_unlock();
86		break;
87	default:
88		pr_warning("Unsupported ieee802154 address type: %d\n",
89				addr->addr_type);
90		break;
91	}
92
93	return dev;
94}
95
96static int ieee802154_sock_release(struct socket *sock)
97{
98	struct sock *sk = sock->sk;
99
100	if (sk) {
101		sock->sk = NULL;
102		sk->sk_prot->close(sk, 0);
103	}
104	return 0;
105}
106static int ieee802154_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
107		struct msghdr *msg, size_t len)
108{
109	struct sock *sk = sock->sk;
110
111	return sk->sk_prot->sendmsg(iocb, sk, msg, len);
112}
113
114static int ieee802154_sock_bind(struct socket *sock, struct sockaddr *uaddr,
115		int addr_len)
116{
117	struct sock *sk = sock->sk;
118
119	if (sk->sk_prot->bind)
120		return sk->sk_prot->bind(sk, uaddr, addr_len);
121
122	return sock_no_bind(sock, uaddr, addr_len);
123}
124
125static int ieee802154_sock_connect(struct socket *sock, struct sockaddr *uaddr,
126			int addr_len, int flags)
127{
128	struct sock *sk = sock->sk;
129
130	if (addr_len < sizeof(uaddr->sa_family))
131		return -EINVAL;
132
133	if (uaddr->sa_family == AF_UNSPEC)
134		return sk->sk_prot->disconnect(sk, flags);
135
136	return sk->sk_prot->connect(sk, uaddr, addr_len);
137}
138
139static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg,
140		unsigned int cmd)
141{
142	struct ifreq ifr;
143	int ret = -ENOIOCTLCMD;
144	struct net_device *dev;
145
146	if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
147		return -EFAULT;
148
149	ifr.ifr_name[IFNAMSIZ-1] = 0;
150
151	dev_load(sock_net(sk), ifr.ifr_name);
152	dev = dev_get_by_name(sock_net(sk), ifr.ifr_name);
153
154	if (!dev)
155		return -ENODEV;
156
157	if (dev->type == ARPHRD_IEEE802154 && dev->netdev_ops->ndo_do_ioctl)
158		ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd);
159
160	if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
161		ret = -EFAULT;
162	dev_put(dev);
163
164	return ret;
165}
166
167static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd,
168		unsigned long arg)
169{
170	struct sock *sk = sock->sk;
171
172	switch (cmd) {
173	case SIOCGSTAMP:
174		return sock_get_timestamp(sk, (struct timeval __user *)arg);
175	case SIOCGSTAMPNS:
176		return sock_get_timestampns(sk, (struct timespec __user *)arg);
177	case SIOCGIFADDR:
178	case SIOCSIFADDR:
179		return ieee802154_dev_ioctl(sk, (struct ifreq __user *)arg,
180				cmd);
181	default:
182		if (!sk->sk_prot->ioctl)
183			return -ENOIOCTLCMD;
184		return sk->sk_prot->ioctl(sk, cmd, arg);
185	}
186}
187
188static const struct proto_ops ieee802154_raw_ops = {
189	.family		   = PF_IEEE802154,
190	.owner		   = THIS_MODULE,
191	.release	   = ieee802154_sock_release,
192	.bind		   = ieee802154_sock_bind,
193	.connect	   = ieee802154_sock_connect,
194	.socketpair	   = sock_no_socketpair,
195	.accept		   = sock_no_accept,
196	.getname	   = sock_no_getname,
197	.poll		   = datagram_poll,
198	.ioctl		   = ieee802154_sock_ioctl,
199	.listen		   = sock_no_listen,
200	.shutdown	   = sock_no_shutdown,
201	.setsockopt	   = sock_common_setsockopt,
202	.getsockopt	   = sock_common_getsockopt,
203	.sendmsg	   = ieee802154_sock_sendmsg,
204	.recvmsg	   = sock_common_recvmsg,
205	.mmap		   = sock_no_mmap,
206	.sendpage	   = sock_no_sendpage,
207#ifdef CONFIG_COMPAT
208	.compat_setsockopt = compat_sock_common_setsockopt,
209	.compat_getsockopt = compat_sock_common_getsockopt,
210#endif
211};
212
213static const struct proto_ops ieee802154_dgram_ops = {
214	.family		   = PF_IEEE802154,
215	.owner		   = THIS_MODULE,
216	.release	   = ieee802154_sock_release,
217	.bind		   = ieee802154_sock_bind,
218	.connect	   = ieee802154_sock_connect,
219	.socketpair	   = sock_no_socketpair,
220	.accept		   = sock_no_accept,
221	.getname	   = sock_no_getname,
222	.poll		   = datagram_poll,
223	.ioctl		   = ieee802154_sock_ioctl,
224	.listen		   = sock_no_listen,
225	.shutdown	   = sock_no_shutdown,
226	.setsockopt	   = sock_common_setsockopt,
227	.getsockopt	   = sock_common_getsockopt,
228	.sendmsg	   = ieee802154_sock_sendmsg,
229	.recvmsg	   = sock_common_recvmsg,
230	.mmap		   = sock_no_mmap,
231	.sendpage	   = sock_no_sendpage,
232#ifdef CONFIG_COMPAT
233	.compat_setsockopt = compat_sock_common_setsockopt,
234	.compat_getsockopt = compat_sock_common_getsockopt,
235#endif
236};
237
238
239/*
240 * Create a socket. Initialise the socket, blank the addresses
241 * set the state.
242 */
243static int ieee802154_create(struct net *net, struct socket *sock,
244			     int protocol, int kern)
245{
246	struct sock *sk;
247	int rc;
248	struct proto *proto;
249	const struct proto_ops *ops;
250
251	if (!net_eq(net, &init_net))
252		return -EAFNOSUPPORT;
253
254	switch (sock->type) {
255	case SOCK_RAW:
256		proto = &ieee802154_raw_prot;
257		ops = &ieee802154_raw_ops;
258		break;
259	case SOCK_DGRAM:
260		proto = &ieee802154_dgram_prot;
261		ops = &ieee802154_dgram_ops;
262		break;
263	default:
264		rc = -ESOCKTNOSUPPORT;
265		goto out;
266	}
267
268	rc = -ENOMEM;
269	sk = sk_alloc(net, PF_IEEE802154, GFP_KERNEL, proto);
270	if (!sk)
271		goto out;
272	rc = 0;
273
274	sock->ops = ops;
275
276	sock_init_data(sock, sk);
277	sk->sk_family = PF_IEEE802154;
278
279	/* Checksums on by default */
280	sock_set_flag(sk, SOCK_ZAPPED);
281
282	if (sk->sk_prot->hash)
283		sk->sk_prot->hash(sk);
284
285	if (sk->sk_prot->init) {
286		rc = sk->sk_prot->init(sk);
287		if (rc)
288			sk_common_release(sk);
289	}
290out:
291	return rc;
292}
293
294static const struct net_proto_family ieee802154_family_ops = {
295	.family		= PF_IEEE802154,
296	.create		= ieee802154_create,
297	.owner		= THIS_MODULE,
298};
299
300static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev,
301	struct packet_type *pt, struct net_device *orig_dev)
302{
303	if (!netif_running(dev))
304		return -ENODEV;
305	pr_debug("got frame, type %d, dev %p\n", dev->type, dev);
306#ifdef DEBUG
307	print_hex_dump_bytes("ieee802154_rcv ", DUMP_PREFIX_NONE, skb->data, skb->len);
308#endif
309
310	if (!net_eq(dev_net(dev), &init_net))
311		goto drop;
312
313	ieee802154_raw_deliver(dev, skb);
314
315	if (dev->type != ARPHRD_IEEE802154)
316		goto drop;
317
318	if (skb->pkt_type != PACKET_OTHERHOST)
319		return ieee802154_dgram_deliver(dev, skb);
320
321drop:
322	kfree_skb(skb);
323	return NET_RX_DROP;
324}
325
326
327static struct packet_type ieee802154_packet_type = {
328	.type = __constant_htons(ETH_P_IEEE802154),
329	.func = ieee802154_rcv,
330};
331
332static int __init af_ieee802154_init(void)
333{
334	int rc = -EINVAL;
335
336	rc = proto_register(&ieee802154_raw_prot, 1);
337	if (rc)
338		goto out;
339
340	rc = proto_register(&ieee802154_dgram_prot, 1);
341	if (rc)
342		goto err_dgram;
343
344	/* Tell SOCKET that we are alive */
345	rc = sock_register(&ieee802154_family_ops);
346	if (rc)
347		goto err_sock;
348	dev_add_pack(&ieee802154_packet_type);
349
350	rc = 0;
351	goto out;
352
353err_sock:
354	proto_unregister(&ieee802154_dgram_prot);
355err_dgram:
356	proto_unregister(&ieee802154_raw_prot);
357out:
358	return rc;
359}
360static void __exit af_ieee802154_remove(void)
361{
362	dev_remove_pack(&ieee802154_packet_type);
363	sock_unregister(PF_IEEE802154);
364	proto_unregister(&ieee802154_dgram_prot);
365	proto_unregister(&ieee802154_raw_prot);
366}
367
368module_init(af_ieee802154_init);
369module_exit(af_ieee802154_remove);
370
371MODULE_LICENSE("GPL");
372MODULE_ALIAS_NETPROTO(PF_IEEE802154);
373