aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Baryshkov <dbaryshkov@gmail.com>2009-08-06 22:58:43 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-13 00:54:50 -0400
commit99eb8558642b988055d2b8b16a334475550f78d3 (patch)
treec139d938a9b3c43e8ce28201a995bf6973122daf
parent74eda55db4335383ccdd1fb51a7b014202f89366 (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>
-rw-r--r--include/net/af_ieee802154.h5
-rw-r--r--net/ieee802154/dgram.c58
2 files changed, 59 insertions, 4 deletions
diff --git a/include/net/af_ieee802154.h b/include/net/af_ieee802154.h
index e9c70ead23fc..75e64c7a2960 100644
--- a/include/net/af_ieee802154.h
+++ b/include/net/af_ieee802154.h
@@ -54,4 +54,9 @@ struct sockaddr_ieee802154 {
54 struct ieee802154_addr addr; 54 struct ieee802154_addr addr;
55}; 55};
56 56
57/* get/setsockopt */
58#define SOL_IEEE802154 0
59
60#define WPAN_WANTACK 0
61
57#endif 62#endif
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
49static inline struct dgram_sock *dgram_sk(const struct sock *sk) 50static 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
55static void dgram_hash(struct sock *sk) 55static 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)
382static int dgram_getsockopt(struct sock *sk, int level, int optname, 386static 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
388static int dgram_setsockopt(struct sock *sk, int level, int optname, 416static 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
394struct proto ieee802154_dgram_prot = { 444struct proto ieee802154_dgram_prot = {