diff options
Diffstat (limited to 'net/bluetooth/l2cap_sock.c')
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 90 |
1 files changed, 68 insertions, 22 deletions
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 5c406d3136f..e2e785c7463 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -334,7 +334,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us | |||
334 | opts.mode = chan->mode; | 334 | opts.mode = chan->mode; |
335 | opts.fcs = chan->fcs; | 335 | opts.fcs = chan->fcs; |
336 | opts.max_tx = chan->max_tx; | 336 | opts.max_tx = chan->max_tx; |
337 | opts.txwin_size = (__u16)chan->tx_win; | 337 | opts.txwin_size = chan->tx_win; |
338 | 338 | ||
339 | len = min_t(unsigned int, len, sizeof(opts)); | 339 | len = min_t(unsigned int, len, sizeof(opts)); |
340 | if (copy_to_user(optval, (char *) &opts, len)) | 340 | if (copy_to_user(optval, (char *) &opts, len)) |
@@ -359,10 +359,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us | |||
359 | break; | 359 | break; |
360 | } | 360 | } |
361 | 361 | ||
362 | if (chan->role_switch) | 362 | if (test_bit(FLAG_ROLE_SWITCH, &chan->flags)) |
363 | opt |= L2CAP_LM_MASTER; | 363 | opt |= L2CAP_LM_MASTER; |
364 | 364 | ||
365 | if (chan->force_reliable) | 365 | if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) |
366 | opt |= L2CAP_LM_RELIABLE; | 366 | opt |= L2CAP_LM_RELIABLE; |
367 | 367 | ||
368 | if (put_user(opt, (u32 __user *) optval)) | 368 | if (put_user(opt, (u32 __user *) optval)) |
@@ -449,7 +449,8 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch | |||
449 | break; | 449 | break; |
450 | 450 | ||
451 | case BT_FLUSHABLE: | 451 | case BT_FLUSHABLE: |
452 | if (put_user(chan->flushable, (u32 __user *) optval)) | 452 | if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags), |
453 | (u32 __user *) optval)) | ||
453 | err = -EFAULT; | 454 | err = -EFAULT; |
454 | 455 | ||
455 | break; | 456 | break; |
@@ -461,7 +462,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch | |||
461 | break; | 462 | break; |
462 | } | 463 | } |
463 | 464 | ||
464 | pwr.force_active = chan->force_active; | 465 | pwr.force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); |
465 | 466 | ||
466 | len = min_t(unsigned int, len, sizeof(pwr)); | 467 | len = min_t(unsigned int, len, sizeof(pwr)); |
467 | if (copy_to_user(optval, (char *) &pwr, len)) | 468 | if (copy_to_user(optval, (char *) &pwr, len)) |
@@ -469,6 +470,16 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch | |||
469 | 470 | ||
470 | break; | 471 | break; |
471 | 472 | ||
473 | case BT_CHANNEL_POLICY: | ||
474 | if (!enable_hs) { | ||
475 | err = -ENOPROTOOPT; | ||
476 | break; | ||
477 | } | ||
478 | |||
479 | if (put_user(chan->chan_policy, (u32 __user *) optval)) | ||
480 | err = -EFAULT; | ||
481 | break; | ||
482 | |||
472 | default: | 483 | default: |
473 | err = -ENOPROTOOPT; | 484 | err = -ENOPROTOOPT; |
474 | break; | 485 | break; |
@@ -503,7 +514,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us | |||
503 | opts.mode = chan->mode; | 514 | opts.mode = chan->mode; |
504 | opts.fcs = chan->fcs; | 515 | opts.fcs = chan->fcs; |
505 | opts.max_tx = chan->max_tx; | 516 | opts.max_tx = chan->max_tx; |
506 | opts.txwin_size = (__u16)chan->tx_win; | 517 | opts.txwin_size = chan->tx_win; |
507 | 518 | ||
508 | len = min_t(unsigned int, sizeof(opts), optlen); | 519 | len = min_t(unsigned int, sizeof(opts), optlen); |
509 | if (copy_from_user((char *) &opts, optval, len)) { | 520 | if (copy_from_user((char *) &opts, optval, len)) { |
@@ -511,7 +522,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us | |||
511 | break; | 522 | break; |
512 | } | 523 | } |
513 | 524 | ||
514 | if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) { | 525 | if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) { |
515 | err = -EINVAL; | 526 | err = -EINVAL; |
516 | break; | 527 | break; |
517 | } | 528 | } |
@@ -535,7 +546,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us | |||
535 | chan->omtu = opts.omtu; | 546 | chan->omtu = opts.omtu; |
536 | chan->fcs = opts.fcs; | 547 | chan->fcs = opts.fcs; |
537 | chan->max_tx = opts.max_tx; | 548 | chan->max_tx = opts.max_tx; |
538 | chan->tx_win = (__u8)opts.txwin_size; | 549 | chan->tx_win = opts.txwin_size; |
539 | break; | 550 | break; |
540 | 551 | ||
541 | case L2CAP_LM: | 552 | case L2CAP_LM: |
@@ -551,8 +562,15 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us | |||
551 | if (opt & L2CAP_LM_SECURE) | 562 | if (opt & L2CAP_LM_SECURE) |
552 | chan->sec_level = BT_SECURITY_HIGH; | 563 | chan->sec_level = BT_SECURITY_HIGH; |
553 | 564 | ||
554 | chan->role_switch = (opt & L2CAP_LM_MASTER); | 565 | if (opt & L2CAP_LM_MASTER) |
555 | chan->force_reliable = (opt & L2CAP_LM_RELIABLE); | 566 | set_bit(FLAG_ROLE_SWITCH, &chan->flags); |
567 | else | ||
568 | clear_bit(FLAG_ROLE_SWITCH, &chan->flags); | ||
569 | |||
570 | if (opt & L2CAP_LM_RELIABLE) | ||
571 | set_bit(FLAG_FORCE_RELIABLE, &chan->flags); | ||
572 | else | ||
573 | clear_bit(FLAG_FORCE_RELIABLE, &chan->flags); | ||
556 | break; | 574 | break; |
557 | 575 | ||
558 | default: | 576 | default: |
@@ -658,7 +676,10 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
658 | } | 676 | } |
659 | } | 677 | } |
660 | 678 | ||
661 | chan->flushable = opt; | 679 | if (opt) |
680 | set_bit(FLAG_FLUSHABLE, &chan->flags); | ||
681 | else | ||
682 | clear_bit(FLAG_FLUSHABLE, &chan->flags); | ||
662 | break; | 683 | break; |
663 | 684 | ||
664 | case BT_POWER: | 685 | case BT_POWER: |
@@ -675,7 +696,36 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
675 | err = -EFAULT; | 696 | err = -EFAULT; |
676 | break; | 697 | break; |
677 | } | 698 | } |
678 | chan->force_active = pwr.force_active; | 699 | |
700 | if (pwr.force_active) | ||
701 | set_bit(FLAG_FORCE_ACTIVE, &chan->flags); | ||
702 | else | ||
703 | clear_bit(FLAG_FORCE_ACTIVE, &chan->flags); | ||
704 | break; | ||
705 | |||
706 | case BT_CHANNEL_POLICY: | ||
707 | if (!enable_hs) { | ||
708 | err = -ENOPROTOOPT; | ||
709 | break; | ||
710 | } | ||
711 | |||
712 | if (get_user(opt, (u32 __user *) optval)) { | ||
713 | err = -EFAULT; | ||
714 | break; | ||
715 | } | ||
716 | |||
717 | if (opt > BT_CHANNEL_POLICY_AMP_PREFERRED) { | ||
718 | err = -EINVAL; | ||
719 | break; | ||
720 | } | ||
721 | |||
722 | if (chan->mode != L2CAP_MODE_ERTM && | ||
723 | chan->mode != L2CAP_MODE_STREAMING) { | ||
724 | err = -EOPNOTSUPP; | ||
725 | break; | ||
726 | } | ||
727 | |||
728 | chan->chan_policy = (u8) opt; | ||
679 | break; | 729 | break; |
680 | 730 | ||
681 | default: | 731 | default: |
@@ -709,7 +759,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
709 | return -ENOTCONN; | 759 | return -ENOTCONN; |
710 | } | 760 | } |
711 | 761 | ||
712 | err = l2cap_chan_send(chan, msg, len); | 762 | err = l2cap_chan_send(chan, msg, len, sk->sk_priority); |
713 | 763 | ||
714 | release_sock(sk); | 764 | release_sock(sk); |
715 | return err; | 765 | return err; |
@@ -931,11 +981,9 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
931 | chan->fcs = pchan->fcs; | 981 | chan->fcs = pchan->fcs; |
932 | chan->max_tx = pchan->max_tx; | 982 | chan->max_tx = pchan->max_tx; |
933 | chan->tx_win = pchan->tx_win; | 983 | chan->tx_win = pchan->tx_win; |
984 | chan->tx_win_max = pchan->tx_win_max; | ||
934 | chan->sec_level = pchan->sec_level; | 985 | chan->sec_level = pchan->sec_level; |
935 | chan->role_switch = pchan->role_switch; | 986 | chan->flags = pchan->flags; |
936 | chan->force_reliable = pchan->force_reliable; | ||
937 | chan->flushable = pchan->flushable; | ||
938 | chan->force_active = pchan->force_active; | ||
939 | 987 | ||
940 | security_sk_clone(parent, sk); | 988 | security_sk_clone(parent, sk); |
941 | } else { | 989 | } else { |
@@ -964,12 +1012,10 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
964 | chan->max_tx = L2CAP_DEFAULT_MAX_TX; | 1012 | chan->max_tx = L2CAP_DEFAULT_MAX_TX; |
965 | chan->fcs = L2CAP_FCS_CRC16; | 1013 | chan->fcs = L2CAP_FCS_CRC16; |
966 | chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; | 1014 | chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; |
1015 | chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; | ||
967 | chan->sec_level = BT_SECURITY_LOW; | 1016 | chan->sec_level = BT_SECURITY_LOW; |
968 | chan->role_switch = 0; | 1017 | chan->flags = 0; |
969 | chan->force_reliable = 0; | 1018 | set_bit(FLAG_FORCE_ACTIVE, &chan->flags); |
970 | chan->flushable = BT_FLUSHABLE_OFF; | ||
971 | chan->force_active = BT_POWER_FORCE_ACTIVE_ON; | ||
972 | |||
973 | } | 1019 | } |
974 | 1020 | ||
975 | /* Default config options */ | 1021 | /* Default config options */ |