aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee802154
diff options
context:
space:
mode:
authorPhoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>2014-05-16 11:46:41 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-16 17:23:41 -0400
commitaf9eed5bbf0fb4e398081e79a707545dcca5ebda (patch)
tree9692f6122fa3b281cc89410bad98d796bfa1eace /net/ieee802154
parentf30be4d53cada48598dab0983866ae4b16af46dc (diff)
ieee802154: add dgram sockopts for security control
Allow datagram sockets to override the security settings of the device they send from on a per-socket basis. Requires CAP_NET_ADMIN or CAP_NET_RAW, since raw sockets can send arbitrary packets anyway. Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ieee802154')
-rw-r--r--net/ieee802154/dgram.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
index 76c77256a56e..4f0ed8780194 100644
--- a/net/ieee802154/dgram.c
+++ b/net/ieee802154/dgram.c
@@ -21,6 +21,7 @@
21 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> 21 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
22 */ 22 */
23 23
24#include <linux/capability.h>
24#include <linux/net.h> 25#include <linux/net.h>
25#include <linux/module.h> 26#include <linux/module.h>
26#include <linux/if_arp.h> 27#include <linux/if_arp.h>
@@ -47,6 +48,10 @@ struct dgram_sock {
47 unsigned int bound:1; 48 unsigned int bound:1;
48 unsigned int connected:1; 49 unsigned int connected:1;
49 unsigned int want_ack:1; 50 unsigned int want_ack:1;
51 unsigned int secen:1;
52 unsigned int secen_override:1;
53 unsigned int seclevel:3;
54 unsigned int seclevel_override:1;
50}; 55};
51 56
52static inline struct dgram_sock *dgram_sk(const struct sock *sk) 57static inline struct dgram_sock *dgram_sk(const struct sock *sk)
@@ -264,6 +269,11 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk,
264 dst_addr = ro->dst_addr; 269 dst_addr = ro->dst_addr;
265 } 270 }
266 271
272 cb->secen = ro->secen;
273 cb->secen_override = ro->secen_override;
274 cb->seclevel = ro->seclevel;
275 cb->seclevel_override = ro->seclevel_override;
276
267 err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &dst_addr, 277 err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &dst_addr,
268 ro->bound ? &ro->src_addr : NULL, size); 278 ro->bound ? &ro->src_addr : NULL, size);
269 if (err < 0) 279 if (err < 0)
@@ -427,6 +437,20 @@ static int dgram_getsockopt(struct sock *sk, int level, int optname,
427 case WPAN_WANTACK: 437 case WPAN_WANTACK:
428 val = ro->want_ack; 438 val = ro->want_ack;
429 break; 439 break;
440 case WPAN_SECURITY:
441 if (!ro->secen_override)
442 val = WPAN_SECURITY_DEFAULT;
443 else if (ro->secen)
444 val = WPAN_SECURITY_ON;
445 else
446 val = WPAN_SECURITY_OFF;
447 break;
448 case WPAN_SECURITY_LEVEL:
449 if (!ro->seclevel_override)
450 val = WPAN_SECURITY_LEVEL_DEFAULT;
451 else
452 val = ro->seclevel;
453 break;
430 default: 454 default:
431 return -ENOPROTOOPT; 455 return -ENOPROTOOPT;
432 } 456 }
@@ -442,6 +466,7 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname,
442 char __user *optval, unsigned int optlen) 466 char __user *optval, unsigned int optlen)
443{ 467{
444 struct dgram_sock *ro = dgram_sk(sk); 468 struct dgram_sock *ro = dgram_sk(sk);
469 struct net *net = sock_net(sk);
445 int val; 470 int val;
446 int err = 0; 471 int err = 0;
447 472
@@ -457,6 +482,47 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname,
457 case WPAN_WANTACK: 482 case WPAN_WANTACK:
458 ro->want_ack = !!val; 483 ro->want_ack = !!val;
459 break; 484 break;
485 case WPAN_SECURITY:
486 if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
487 !ns_capable(net->user_ns, CAP_NET_RAW)) {
488 err = -EPERM;
489 break;
490 }
491
492 switch (val) {
493 case WPAN_SECURITY_DEFAULT:
494 ro->secen_override = 0;
495 break;
496 case WPAN_SECURITY_ON:
497 ro->secen_override = 1;
498 ro->secen = 1;
499 break;
500 case WPAN_SECURITY_OFF:
501 ro->secen_override = 1;
502 ro->secen = 0;
503 break;
504 default:
505 err = -EINVAL;
506 break;
507 }
508 break;
509 case WPAN_SECURITY_LEVEL:
510 if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
511 !ns_capable(net->user_ns, CAP_NET_RAW)) {
512 err = -EPERM;
513 break;
514 }
515
516 if (val < WPAN_SECURITY_LEVEL_DEFAULT ||
517 val > IEEE802154_SCF_SECLEVEL_ENC_MIC128) {
518 err = -EINVAL;
519 } else if (val == WPAN_SECURITY_LEVEL_DEFAULT) {
520 ro->seclevel_override = 0;
521 } else {
522 ro->seclevel_override = 1;
523 ro->seclevel = val;
524 }
525 break;
460 default: 526 default:
461 err = -ENOPROTOOPT; 527 err = -ENOPROTOOPT;
462 break; 528 break;