diff options
Diffstat (limited to 'net/bluetooth/l2cap.c')
| -rw-r--r-- | net/bluetooth/l2cap.c | 84 | 
1 files changed, 32 insertions, 52 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index c791fcda7b2..7550abb0c96 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -305,33 +305,44 @@ static void l2cap_chan_del(struct sock *sk, int err)  	}  } -/* Service level security */ -static inline int l2cap_check_security(struct sock *sk) +static inline u8 l2cap_get_auth_type(struct sock *sk)  { -	struct l2cap_conn *conn = l2cap_pi(sk)->conn; -	__u8 auth_type; +	if (sk->sk_type == SOCK_RAW) { +		switch (l2cap_pi(sk)->sec_level) { +		case BT_SECURITY_HIGH: +			return HCI_AT_DEDICATED_BONDING_MITM; +		case BT_SECURITY_MEDIUM: +			return HCI_AT_DEDICATED_BONDING; +		default: +			return HCI_AT_NO_BONDING; +		} +	} else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) { +		if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW) +			l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; -	if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {  		if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) -			auth_type = HCI_AT_NO_BONDING_MITM; +			return HCI_AT_NO_BONDING_MITM;  		else -			auth_type = HCI_AT_NO_BONDING; - -		if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW) -			l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; +			return HCI_AT_NO_BONDING;  	} else {  		switch (l2cap_pi(sk)->sec_level) {  		case BT_SECURITY_HIGH: -			auth_type = HCI_AT_GENERAL_BONDING_MITM; -			break; +			return HCI_AT_GENERAL_BONDING_MITM;  		case BT_SECURITY_MEDIUM: -			auth_type = HCI_AT_GENERAL_BONDING; -			break; +			return HCI_AT_GENERAL_BONDING;  		default: -			auth_type = HCI_AT_NO_BONDING; -			break; +			return HCI_AT_NO_BONDING;  		}  	} +} + +/* Service level security */ +static inline int l2cap_check_security(struct sock *sk) +{ +	struct l2cap_conn *conn = l2cap_pi(sk)->conn; +	__u8 auth_type; + +	auth_type = l2cap_get_auth_type(sk);  	return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,  								auth_type); @@ -1068,39 +1079,7 @@ static int l2cap_do_connect(struct sock *sk)  	err = -ENOMEM; -	if (sk->sk_type == SOCK_RAW) { -		switch (l2cap_pi(sk)->sec_level) { -		case BT_SECURITY_HIGH: -			auth_type = HCI_AT_DEDICATED_BONDING_MITM; -			break; -		case BT_SECURITY_MEDIUM: -			auth_type = HCI_AT_DEDICATED_BONDING; -			break; -		default: -			auth_type = HCI_AT_NO_BONDING; -			break; -		} -	} else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) { -		if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) -			auth_type = HCI_AT_NO_BONDING_MITM; -		else -			auth_type = HCI_AT_NO_BONDING; - -		if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW) -			l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; -	} else { -		switch (l2cap_pi(sk)->sec_level) { -		case BT_SECURITY_HIGH: -			auth_type = HCI_AT_GENERAL_BONDING_MITM; -			break; -		case BT_SECURITY_MEDIUM: -			auth_type = HCI_AT_GENERAL_BONDING; -			break; -		default: -			auth_type = HCI_AT_NO_BONDING; -			break; -		} -	} +	auth_type = l2cap_get_auth_type(sk);  	hcon = hci_connect(hdev, ACL_LINK, dst,  					l2cap_pi(sk)->sec_level, auth_type); @@ -1127,7 +1106,8 @@ static int l2cap_do_connect(struct sock *sk)  		if (sk->sk_type != SOCK_SEQPACKET &&  				sk->sk_type != SOCK_STREAM) {  			l2cap_sock_clear_timer(sk); -			sk->sk_state = BT_CONNECTED; +			if (l2cap_check_security(sk)) +				sk->sk_state = BT_CONNECTED;  		} else  			l2cap_do_start(sk);  	} @@ -1893,8 +1873,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms  		if (pi->mode == L2CAP_MODE_STREAMING) {  			l2cap_streaming_send(sk);  		} else { -			if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && -					pi->conn_state && L2CAP_CONN_WAIT_F) { +			if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && +					(pi->conn_state & L2CAP_CONN_WAIT_F)) {  				err = len;  				break;  			}  |