• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /* Utility function for families */
44 struct net_device*
ieee802154_get_dev(struct net * net,const struct ieee802154_addr * addr)45 ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr)
46 {
47 	struct net_device *dev = NULL;
48 	struct net_device *tmp;
49 	__le16 pan_id, short_addr;
50 	u8 hwaddr[IEEE802154_ADDR_LEN];
51 
52 	switch (addr->mode) {
53 	case IEEE802154_ADDR_LONG:
54 		ieee802154_devaddr_to_raw(hwaddr, addr->extended_addr);
55 		rcu_read_lock();
56 		dev = dev_getbyhwaddr_rcu(net, ARPHRD_IEEE802154, hwaddr);
57 		if (dev)
58 			dev_hold(dev);
59 		rcu_read_unlock();
60 		break;
61 	case IEEE802154_ADDR_SHORT:
62 		if (addr->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST) ||
63 		    addr->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) ||
64 		    addr->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST))
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_warn("Unsupported ieee802154 address type: %d\n",
89 			addr->mode);
90 		break;
91 	}
92 
93 	return dev;
94 }
95 
ieee802154_sock_release(struct socket * sock)96 static 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 }
ieee802154_sock_sendmsg(struct kiocb * iocb,struct socket * sock,struct msghdr * msg,size_t len)106 static 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 
ieee802154_sock_bind(struct socket * sock,struct sockaddr * uaddr,int addr_len)114 static 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 
ieee802154_sock_connect(struct socket * sock,struct sockaddr * uaddr,int addr_len,int flags)125 static 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 
ieee802154_dev_ioctl(struct sock * sk,struct ifreq __user * arg,unsigned int cmd)139 static 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 
ieee802154_sock_ioctl(struct socket * sock,unsigned int cmd,unsigned long arg)167 static 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 
188 static 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 
213 static 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 /* Create a socket. Initialise the socket, blank the addresses
240  * set the state.
241  */
ieee802154_create(struct net * net,struct socket * sock,int protocol,int kern)242 static int ieee802154_create(struct net *net, struct socket *sock,
243 			     int protocol, int kern)
244 {
245 	struct sock *sk;
246 	int rc;
247 	struct proto *proto;
248 	const struct proto_ops *ops;
249 
250 	if (!net_eq(net, &init_net))
251 		return -EAFNOSUPPORT;
252 
253 	switch (sock->type) {
254 	case SOCK_RAW:
255 		proto = &ieee802154_raw_prot;
256 		ops = &ieee802154_raw_ops;
257 		break;
258 	case SOCK_DGRAM:
259 		proto = &ieee802154_dgram_prot;
260 		ops = &ieee802154_dgram_ops;
261 		break;
262 	default:
263 		rc = -ESOCKTNOSUPPORT;
264 		goto out;
265 	}
266 
267 	rc = -ENOMEM;
268 	sk = sk_alloc(net, PF_IEEE802154, GFP_KERNEL, proto);
269 	if (!sk)
270 		goto out;
271 	rc = 0;
272 
273 	sock->ops = ops;
274 
275 	sock_init_data(sock, sk);
276 	/* FIXME: sk->sk_destruct */
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 	}
290 out:
291 	return rc;
292 }
293 
294 static const struct net_proto_family ieee802154_family_ops = {
295 	.family		= PF_IEEE802154,
296 	.create		= ieee802154_create,
297 	.owner		= THIS_MODULE,
298 };
299 
ieee802154_rcv(struct sk_buff * skb,struct net_device * dev,struct packet_type * pt,struct net_device * orig_dev)300 static 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 		goto drop;
305 	pr_debug("got frame, type %d, dev %p\n", dev->type, dev);
306 #ifdef DEBUG
307 	print_hex_dump_bytes("ieee802154_rcv ",
308 			     DUMP_PREFIX_NONE, skb->data, skb->len);
309 #endif
310 
311 	if (!net_eq(dev_net(dev), &init_net))
312 		goto drop;
313 
314 	ieee802154_raw_deliver(dev, skb);
315 
316 	if (dev->type != ARPHRD_IEEE802154)
317 		goto drop;
318 
319 	if (skb->pkt_type != PACKET_OTHERHOST)
320 		return ieee802154_dgram_deliver(dev, skb);
321 
322 drop:
323 	kfree_skb(skb);
324 	return NET_RX_DROP;
325 }
326 
327 
328 static struct packet_type ieee802154_packet_type = {
329 	.type = htons(ETH_P_IEEE802154),
330 	.func = ieee802154_rcv,
331 };
332 
af_ieee802154_init(void)333 static int __init af_ieee802154_init(void)
334 {
335 	int rc = -EINVAL;
336 
337 	rc = proto_register(&ieee802154_raw_prot, 1);
338 	if (rc)
339 		goto out;
340 
341 	rc = proto_register(&ieee802154_dgram_prot, 1);
342 	if (rc)
343 		goto err_dgram;
344 
345 	/* Tell SOCKET that we are alive */
346 	rc = sock_register(&ieee802154_family_ops);
347 	if (rc)
348 		goto err_sock;
349 	dev_add_pack(&ieee802154_packet_type);
350 
351 	rc = 0;
352 	goto out;
353 
354 err_sock:
355 	proto_unregister(&ieee802154_dgram_prot);
356 err_dgram:
357 	proto_unregister(&ieee802154_raw_prot);
358 out:
359 	return rc;
360 }
af_ieee802154_remove(void)361 static void __exit af_ieee802154_remove(void)
362 {
363 	dev_remove_pack(&ieee802154_packet_type);
364 	sock_unregister(PF_IEEE802154);
365 	proto_unregister(&ieee802154_dgram_prot);
366 	proto_unregister(&ieee802154_raw_prot);
367 }
368 
369 module_init(af_ieee802154_init);
370 module_exit(af_ieee802154_remove);
371 
372 MODULE_LICENSE("GPL");
373 MODULE_ALIAS_NETPROTO(PF_IEEE802154);
374