Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dgram.c
Go to the documentation of this file.
1 /*
2  * IEEE 802.15.4 dgram 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 <[email protected]>
21  * Dmitry Eremin-Solenikov <[email protected]>
22  */
23 
24 #include <linux/net.h>
25 #include <linux/module.h>
26 #include <linux/if_arp.h>
27 #include <linux/list.h>
28 #include <linux/slab.h>
29 #include <net/sock.h>
30 #include <net/af_ieee802154.h>
31 #include <net/ieee802154.h>
32 #include <net/ieee802154_netdev.h>
33 
34 #include <asm/ioctls.h>
35 
36 #include "af802154.h"
37 
38 static HLIST_HEAD(dgram_head);
39 static DEFINE_RWLOCK(dgram_lock);
40 
41 struct dgram_sock {
42  struct sock sk;
43 
46 
47  unsigned int bound:1;
48  unsigned int want_ack:1;
49 };
50 
51 static inline struct dgram_sock *dgram_sk(const struct sock *sk)
52 {
53  return container_of(sk, struct dgram_sock, sk);
54 }
55 
56 static void dgram_hash(struct sock *sk)
57 {
58  write_lock_bh(&dgram_lock);
59  sk_add_node(sk, &dgram_head);
60  sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
61  write_unlock_bh(&dgram_lock);
62 }
63 
64 static void dgram_unhash(struct sock *sk)
65 {
66  write_lock_bh(&dgram_lock);
67  if (sk_del_node_init(sk))
68  sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
69  write_unlock_bh(&dgram_lock);
70 }
71 
72 static int dgram_init(struct sock *sk)
73 {
74  struct dgram_sock *ro = dgram_sk(sk);
75 
76  ro->dst_addr.addr_type = IEEE802154_ADDR_LONG;
77  ro->dst_addr.pan_id = 0xffff;
78  ro->want_ack = 1;
79  memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr));
80  return 0;
81 }
82 
83 static void dgram_close(struct sock *sk, long timeout)
84 {
86 }
87 
88 static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
89 {
90  struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr;
91  struct dgram_sock *ro = dgram_sk(sk);
92  int err = -EINVAL;
93  struct net_device *dev;
94 
95  lock_sock(sk);
96 
97  ro->bound = 0;
98 
99  if (len < sizeof(*addr))
100  goto out;
101 
102  if (addr->family != AF_IEEE802154)
103  goto out;
104 
105  dev = ieee802154_get_dev(sock_net(sk), &addr->addr);
106  if (!dev) {
107  err = -ENODEV;
108  goto out;
109  }
110 
111  if (dev->type != ARPHRD_IEEE802154) {
112  err = -ENODEV;
113  goto out_put;
114  }
115 
116  memcpy(&ro->src_addr, &addr->addr, sizeof(struct ieee802154_addr));
117 
118  ro->bound = 1;
119  err = 0;
120 out_put:
121  dev_put(dev);
122 out:
123  release_sock(sk);
124 
125  return err;
126 }
127 
128 static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg)
129 {
130  switch (cmd) {
131  case SIOCOUTQ:
132  {
133  int amount = sk_wmem_alloc_get(sk);
134 
135  return put_user(amount, (int __user *)arg);
136  }
137 
138  case SIOCINQ:
139  {
140  struct sk_buff *skb;
141  unsigned long amount;
142 
143  amount = 0;
144  spin_lock_bh(&sk->sk_receive_queue.lock);
145  skb = skb_peek(&sk->sk_receive_queue);
146  if (skb != NULL) {
147  /*
148  * We will only return the amount
149  * of this packet since that is all
150  * that will be read.
151  */
152  /* FIXME: parse the header for more correct value */
153  amount = skb->len - (3+8+8);
154  }
155  spin_unlock_bh(&sk->sk_receive_queue.lock);
156  return put_user(amount, (int __user *)arg);
157  }
158 
159  }
160  return -ENOIOCTLCMD;
161 }
162 
163 /* FIXME: autobind */
164 static int dgram_connect(struct sock *sk, struct sockaddr *uaddr,
165  int len)
166 {
167  struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr;
168  struct dgram_sock *ro = dgram_sk(sk);
169  int err = 0;
170 
171  if (len < sizeof(*addr))
172  return -EINVAL;
173 
174  if (addr->family != AF_IEEE802154)
175  return -EINVAL;
176 
177  lock_sock(sk);
178 
179  if (!ro->bound) {
180  err = -ENETUNREACH;
181  goto out;
182  }
183 
184  memcpy(&ro->dst_addr, &addr->addr, sizeof(struct ieee802154_addr));
185 
186 out:
187  release_sock(sk);
188  return err;
189 }
190 
191 static int dgram_disconnect(struct sock *sk, int flags)
192 {
193  struct dgram_sock *ro = dgram_sk(sk);
194 
195  lock_sock(sk);
196 
197  ro->dst_addr.addr_type = IEEE802154_ADDR_LONG;
198  memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr));
199 
200  release_sock(sk);
201 
202  return 0;
203 }
204 
205 static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk,
206  struct msghdr *msg, size_t size)
207 {
208  struct net_device *dev;
209  unsigned int mtu;
210  struct sk_buff *skb;
211  struct dgram_sock *ro = dgram_sk(sk);
212  int hlen, tlen;
213  int err;
214 
215  if (msg->msg_flags & MSG_OOB) {
216  pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags);
217  return -EOPNOTSUPP;
218  }
219 
220  if (!ro->bound)
221  dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154);
222  else
223  dev = ieee802154_get_dev(sock_net(sk), &ro->src_addr);
224 
225  if (!dev) {
226  pr_debug("no dev\n");
227  err = -ENXIO;
228  goto out;
229  }
230  mtu = dev->mtu;
231  pr_debug("name = %s, mtu = %u\n", dev->name, mtu);
232 
233  if (size > mtu) {
234  pr_debug("size = %Zu, mtu = %u\n", size, mtu);
235  err = -EINVAL;
236  goto out_dev;
237  }
238 
239  hlen = LL_RESERVED_SPACE(dev);
240  tlen = dev->needed_tailroom;
241  skb = sock_alloc_send_skb(sk, hlen + tlen + size,
242  msg->msg_flags & MSG_DONTWAIT,
243  &err);
244  if (!skb)
245  goto out_dev;
246 
247  skb_reserve(skb, hlen);
248 
249  skb_reset_network_header(skb);
250 
251  mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
252  if (ro->want_ack)
253  mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
254 
255  mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
256  err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &ro->dst_addr,
257  ro->bound ? &ro->src_addr : NULL, size);
258  if (err < 0)
259  goto out_skb;
260 
261  skb_reset_mac_header(skb);
262 
263  err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
264  if (err < 0)
265  goto out_skb;
266 
267  skb->dev = dev;
268  skb->sk = sk;
270 
271  dev_put(dev);
272 
273  err = dev_queue_xmit(skb);
274  if (err > 0)
275  err = net_xmit_errno(err);
276 
277  return err ?: size;
278 
279 out_skb:
280  kfree_skb(skb);
281 out_dev:
282  dev_put(dev);
283 out:
284  return err;
285 }
286 
287 static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk,
288  struct msghdr *msg, size_t len, int noblock, int flags,
289  int *addr_len)
290 {
291  size_t copied = 0;
292  int err = -EOPNOTSUPP;
293  struct sk_buff *skb;
294 
295  skb = skb_recv_datagram(sk, flags, noblock, &err);
296  if (!skb)
297  goto out;
298 
299  copied = skb->len;
300  if (len < copied) {
301  msg->msg_flags |= MSG_TRUNC;
302  copied = len;
303  }
304 
305  /* FIXME: skip headers if necessary ?! */
306  err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
307  if (err)
308  goto done;
309 
310  sock_recv_ts_and_drops(msg, sk, skb);
311 
312  if (flags & MSG_TRUNC)
313  copied = skb->len;
314 done:
315  skb_free_datagram(sk, skb);
316 out:
317  if (err)
318  return err;
319  return copied;
320 }
321 
322 static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb)
323 {
324  if (sock_queue_rcv_skb(sk, skb) < 0) {
325  kfree_skb(skb);
326  return NET_RX_DROP;
327  }
328 
329  return NET_RX_SUCCESS;
330 }
331 
332 static inline int ieee802154_match_sock(u8 *hw_addr, u16 pan_id,
333  u16 short_addr, struct dgram_sock *ro)
334 {
335  if (!ro->bound)
336  return 1;
337 
338  if (ro->src_addr.addr_type == IEEE802154_ADDR_LONG &&
339  !memcmp(ro->src_addr.hwaddr, hw_addr, IEEE802154_ADDR_LEN))
340  return 1;
341 
342  if (ro->src_addr.addr_type == IEEE802154_ADDR_SHORT &&
343  pan_id == ro->src_addr.pan_id &&
344  short_addr == ro->src_addr.short_addr)
345  return 1;
346 
347  return 0;
348 }
349 
350 int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
351 {
352  struct sock *sk, *prev = NULL;
353  struct hlist_node *node;
354  int ret = NET_RX_SUCCESS;
355  u16 pan_id, short_addr;
356 
357  /* Data frame processing */
358  BUG_ON(dev->type != ARPHRD_IEEE802154);
359 
360  pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
361  short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev);
362 
363  read_lock(&dgram_lock);
364  sk_for_each(sk, node, &dgram_head) {
365  if (ieee802154_match_sock(dev->dev_addr, pan_id, short_addr,
366  dgram_sk(sk))) {
367  if (prev) {
368  struct sk_buff *clone;
369  clone = skb_clone(skb, GFP_ATOMIC);
370  if (clone)
371  dgram_rcv_skb(prev, clone);
372  }
373 
374  prev = sk;
375  }
376  }
377 
378  if (prev)
379  dgram_rcv_skb(prev, skb);
380  else {
381  kfree_skb(skb);
382  ret = NET_RX_DROP;
383  }
384  read_unlock(&dgram_lock);
385 
386  return ret;
387 }
388 
389 static int dgram_getsockopt(struct sock *sk, int level, int optname,
390  char __user *optval, int __user *optlen)
391 {
392  struct dgram_sock *ro = dgram_sk(sk);
393 
394  int val, len;
395 
396  if (level != SOL_IEEE802154)
397  return -EOPNOTSUPP;
398 
399  if (get_user(len, optlen))
400  return -EFAULT;
401 
402  len = min_t(unsigned int, len, sizeof(int));
403 
404  switch (optname) {
405  case WPAN_WANTACK:
406  val = ro->want_ack;
407  break;
408  default:
409  return -ENOPROTOOPT;
410  }
411 
412  if (put_user(len, optlen))
413  return -EFAULT;
414  if (copy_to_user(optval, &val, len))
415  return -EFAULT;
416  return 0;
417 }
418 
419 static int dgram_setsockopt(struct sock *sk, int level, int optname,
420  char __user *optval, unsigned int optlen)
421 {
422  struct dgram_sock *ro = dgram_sk(sk);
423  int val;
424  int err = 0;
425 
426  if (optlen < sizeof(int))
427  return -EINVAL;
428 
429  if (get_user(val, (int __user *)optval))
430  return -EFAULT;
431 
432  lock_sock(sk);
433 
434  switch (optname) {
435  case WPAN_WANTACK:
436  ro->want_ack = !!val;
437  break;
438  default:
439  err = -ENOPROTOOPT;
440  break;
441  }
442 
443  release_sock(sk);
444  return err;
445 }
446 
448  .name = "IEEE-802.15.4-MAC",
449  .owner = THIS_MODULE,
450  .obj_size = sizeof(struct dgram_sock),
451  .init = dgram_init,
452  .close = dgram_close,
453  .bind = dgram_bind,
454  .sendmsg = dgram_sendmsg,
455  .recvmsg = dgram_recvmsg,
456  .hash = dgram_hash,
457  .unhash = dgram_unhash,
458  .connect = dgram_connect,
459  .disconnect = dgram_disconnect,
460  .ioctl = dgram_ioctl,
461  .getsockopt = dgram_getsockopt,
462  .setsockopt = dgram_setsockopt,
463 };
464