diff options
author | Dmitry Baryshkov <dbaryshkov@gmail.com> | 2009-08-06 22:58:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-13 00:54:50 -0400 |
commit | 99eb8558642b988055d2b8b16a334475550f78d3 (patch) | |
tree | c139d938a9b3c43e8ce28201a995bf6973122daf /net/ieee802154 | |
parent | 74eda55db4335383ccdd1fb51a7b014202f89366 (diff) |
af_ieee802154: add support for WANT_ACK socket option
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ieee802154')
-rw-r--r-- | net/ieee802154/dgram.c | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 25018a9a53aa..77ae6852b93d 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c | |||
@@ -44,6 +44,7 @@ struct dgram_sock { | |||
44 | struct ieee802154_addr dst_addr; | 44 | struct ieee802154_addr dst_addr; |
45 | 45 | ||
46 | unsigned bound:1; | 46 | unsigned bound:1; |
47 | unsigned want_ack:1; | ||
47 | }; | 48 | }; |
48 | 49 | ||
49 | static inline struct dgram_sock *dgram_sk(const struct sock *sk) | 50 | static inline struct dgram_sock *dgram_sk(const struct sock *sk) |
@@ -51,7 +52,6 @@ static inline struct dgram_sock *dgram_sk(const struct sock *sk) | |||
51 | return container_of(sk, struct dgram_sock, sk); | 52 | return container_of(sk, struct dgram_sock, sk); |
52 | } | 53 | } |
53 | 54 | ||
54 | |||
55 | static void dgram_hash(struct sock *sk) | 55 | static void dgram_hash(struct sock *sk) |
56 | { | 56 | { |
57 | write_lock_bh(&dgram_lock); | 57 | write_lock_bh(&dgram_lock); |
@@ -74,6 +74,7 @@ static int dgram_init(struct sock *sk) | |||
74 | 74 | ||
75 | ro->dst_addr.addr_type = IEEE802154_ADDR_LONG; | 75 | ro->dst_addr.addr_type = IEEE802154_ADDR_LONG; |
76 | ro->dst_addr.pan_id = 0xffff; | 76 | ro->dst_addr.pan_id = 0xffff; |
77 | ro->want_ack = 1; | ||
77 | memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr)); | 78 | memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr)); |
78 | return 0; | 79 | return 0; |
79 | } | 80 | } |
@@ -237,7 +238,10 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
237 | 238 | ||
238 | skb_reset_network_header(skb); | 239 | skb_reset_network_header(skb); |
239 | 240 | ||
240 | mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA | MAC_CB_FLAG_ACKREQ; | 241 | mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA; |
242 | if (ro->want_ack) | ||
243 | mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ; | ||
244 | |||
241 | mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev); | 245 | mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev); |
242 | err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &ro->dst_addr, | 246 | err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &ro->dst_addr, |
243 | ro->bound ? &ro->src_addr : NULL, size); | 247 | ro->bound ? &ro->src_addr : NULL, size); |
@@ -382,13 +386,59 @@ int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) | |||
382 | static int dgram_getsockopt(struct sock *sk, int level, int optname, | 386 | static int dgram_getsockopt(struct sock *sk, int level, int optname, |
383 | char __user *optval, int __user *optlen) | 387 | char __user *optval, int __user *optlen) |
384 | { | 388 | { |
385 | return -EOPNOTSUPP; | 389 | struct dgram_sock *ro = dgram_sk(sk); |
390 | |||
391 | int val, len; | ||
392 | |||
393 | if (level != SOL_IEEE802154) | ||
394 | return -EOPNOTSUPP; | ||
395 | |||
396 | if (get_user(len, optlen)) | ||
397 | return -EFAULT; | ||
398 | |||
399 | len = min_t(unsigned int, len, sizeof(int)); | ||
400 | |||
401 | switch (optname) { | ||
402 | case WPAN_WANTACK: | ||
403 | val = ro->want_ack; | ||
404 | break; | ||
405 | default: | ||
406 | return -ENOPROTOOPT; | ||
407 | } | ||
408 | |||
409 | if (put_user(len, optlen)) | ||
410 | return -EFAULT; | ||
411 | if (copy_to_user(optval, &val, len)) | ||
412 | return -EFAULT; | ||
413 | return 0; | ||
386 | } | 414 | } |
387 | 415 | ||
388 | static int dgram_setsockopt(struct sock *sk, int level, int optname, | 416 | static int dgram_setsockopt(struct sock *sk, int level, int optname, |
389 | char __user *optval, int __user optlen) | 417 | char __user *optval, int __user optlen) |
390 | { | 418 | { |
391 | return -EOPNOTSUPP; | 419 | struct dgram_sock *ro = dgram_sk(sk); |
420 | int val; | ||
421 | int err = 0; | ||
422 | |||
423 | if (optlen < sizeof(int)) | ||
424 | return -EINVAL; | ||
425 | |||
426 | if (get_user(val, (int __user *)optval)) | ||
427 | return -EFAULT; | ||
428 | |||
429 | lock_sock(sk); | ||
430 | |||
431 | switch (optname) { | ||
432 | case WPAN_WANTACK: | ||
433 | ro->want_ack = !!val; | ||
434 | break; | ||
435 | default: | ||
436 | err = -ENOPROTOOPT; | ||
437 | break; | ||
438 | } | ||
439 | |||
440 | release_sock(sk); | ||
441 | return err; | ||
392 | } | 442 | } |
393 | 443 | ||
394 | struct proto ieee802154_dgram_prot = { | 444 | struct proto ieee802154_dgram_prot = { |