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