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 = { |
