diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 134 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 135 |
2 files changed, 135 insertions, 134 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 5765a82cf380..6af38722d5cb 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -722,17 +722,6 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, stru | |||
722 | } | 722 | } |
723 | 723 | ||
724 | /* ---- Socket interface ---- */ | 724 | /* ---- Socket interface ---- */ |
725 | static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) | ||
726 | { | ||
727 | struct sock *sk; | ||
728 | struct hlist_node *node; | ||
729 | sk_for_each(sk, node, &l2cap_sk_list.head) | ||
730 | if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src)) | ||
731 | goto found; | ||
732 | sk = NULL; | ||
733 | found: | ||
734 | return sk; | ||
735 | } | ||
736 | 725 | ||
737 | /* Find socket with psm and source bdaddr. | 726 | /* Find socket with psm and source bdaddr. |
738 | * Returns closest match. | 727 | * Returns closest match. |
@@ -859,70 +848,6 @@ static void l2cap_sock_close(struct sock *sk) | |||
859 | l2cap_sock_kill(sk); | 848 | l2cap_sock_kill(sk); |
860 | } | 849 | } |
861 | 850 | ||
862 | int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | ||
863 | { | ||
864 | struct sock *sk = sock->sk; | ||
865 | struct sockaddr_l2 la; | ||
866 | int len, err = 0; | ||
867 | |||
868 | BT_DBG("sk %p", sk); | ||
869 | |||
870 | if (!addr || addr->sa_family != AF_BLUETOOTH) | ||
871 | return -EINVAL; | ||
872 | |||
873 | memset(&la, 0, sizeof(la)); | ||
874 | len = min_t(unsigned int, sizeof(la), alen); | ||
875 | memcpy(&la, addr, len); | ||
876 | |||
877 | if (la.l2_cid) | ||
878 | return -EINVAL; | ||
879 | |||
880 | lock_sock(sk); | ||
881 | |||
882 | if (sk->sk_state != BT_OPEN) { | ||
883 | err = -EBADFD; | ||
884 | goto done; | ||
885 | } | ||
886 | |||
887 | if (la.l2_psm) { | ||
888 | __u16 psm = __le16_to_cpu(la.l2_psm); | ||
889 | |||
890 | /* PSM must be odd and lsb of upper byte must be 0 */ | ||
891 | if ((psm & 0x0101) != 0x0001) { | ||
892 | err = -EINVAL; | ||
893 | goto done; | ||
894 | } | ||
895 | |||
896 | /* Restrict usage of well-known PSMs */ | ||
897 | if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) { | ||
898 | err = -EACCES; | ||
899 | goto done; | ||
900 | } | ||
901 | } | ||
902 | |||
903 | write_lock_bh(&l2cap_sk_list.lock); | ||
904 | |||
905 | if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) { | ||
906 | err = -EADDRINUSE; | ||
907 | } else { | ||
908 | /* Save source address */ | ||
909 | bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); | ||
910 | l2cap_pi(sk)->psm = la.l2_psm; | ||
911 | l2cap_pi(sk)->sport = la.l2_psm; | ||
912 | sk->sk_state = BT_BOUND; | ||
913 | |||
914 | if (__le16_to_cpu(la.l2_psm) == 0x0001 || | ||
915 | __le16_to_cpu(la.l2_psm) == 0x0003) | ||
916 | l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; | ||
917 | } | ||
918 | |||
919 | write_unlock_bh(&l2cap_sk_list.lock); | ||
920 | |||
921 | done: | ||
922 | release_sock(sk); | ||
923 | return err; | ||
924 | } | ||
925 | |||
926 | static int l2cap_do_connect(struct sock *sk) | 851 | static int l2cap_do_connect(struct sock *sk) |
927 | { | 852 | { |
928 | bdaddr_t *src = &bt_sk(sk)->src; | 853 | bdaddr_t *src = &bt_sk(sk)->src; |
@@ -1068,65 +993,6 @@ done: | |||
1068 | return err; | 993 | return err; |
1069 | } | 994 | } |
1070 | 995 | ||
1071 | int l2cap_sock_listen(struct socket *sock, int backlog) | ||
1072 | { | ||
1073 | struct sock *sk = sock->sk; | ||
1074 | int err = 0; | ||
1075 | |||
1076 | BT_DBG("sk %p backlog %d", sk, backlog); | ||
1077 | |||
1078 | lock_sock(sk); | ||
1079 | |||
1080 | if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) | ||
1081 | || sk->sk_state != BT_BOUND) { | ||
1082 | err = -EBADFD; | ||
1083 | goto done; | ||
1084 | } | ||
1085 | |||
1086 | switch (l2cap_pi(sk)->mode) { | ||
1087 | case L2CAP_MODE_BASIC: | ||
1088 | break; | ||
1089 | case L2CAP_MODE_ERTM: | ||
1090 | case L2CAP_MODE_STREAMING: | ||
1091 | if (!disable_ertm) | ||
1092 | break; | ||
1093 | /* fall through */ | ||
1094 | default: | ||
1095 | err = -ENOTSUPP; | ||
1096 | goto done; | ||
1097 | } | ||
1098 | |||
1099 | if (!l2cap_pi(sk)->psm) { | ||
1100 | bdaddr_t *src = &bt_sk(sk)->src; | ||
1101 | u16 psm; | ||
1102 | |||
1103 | err = -EINVAL; | ||
1104 | |||
1105 | write_lock_bh(&l2cap_sk_list.lock); | ||
1106 | |||
1107 | for (psm = 0x1001; psm < 0x1100; psm += 2) | ||
1108 | if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { | ||
1109 | l2cap_pi(sk)->psm = cpu_to_le16(psm); | ||
1110 | l2cap_pi(sk)->sport = cpu_to_le16(psm); | ||
1111 | err = 0; | ||
1112 | break; | ||
1113 | } | ||
1114 | |||
1115 | write_unlock_bh(&l2cap_sk_list.lock); | ||
1116 | |||
1117 | if (err < 0) | ||
1118 | goto done; | ||
1119 | } | ||
1120 | |||
1121 | sk->sk_max_ack_backlog = backlog; | ||
1122 | sk->sk_ack_backlog = 0; | ||
1123 | sk->sk_state = BT_LISTEN; | ||
1124 | |||
1125 | done: | ||
1126 | release_sock(sk); | ||
1127 | return err; | ||
1128 | } | ||
1129 | |||
1130 | int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags) | 996 | int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags) |
1131 | { | 997 | { |
1132 | DECLARE_WAITQUEUE(wait, current); | 998 | DECLARE_WAITQUEUE(wait, current); |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 20efd240a786..ef9a60fda495 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -62,6 +62,141 @@ static void l2cap_sock_timeout(unsigned long arg) | |||
62 | sock_put(sk); | 62 | sock_put(sk); |
63 | } | 63 | } |
64 | 64 | ||
65 | static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) | ||
66 | { | ||
67 | struct sock *sk; | ||
68 | struct hlist_node *node; | ||
69 | sk_for_each(sk, node, &l2cap_sk_list.head) | ||
70 | if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src)) | ||
71 | goto found; | ||
72 | sk = NULL; | ||
73 | found: | ||
74 | return sk; | ||
75 | } | ||
76 | |||
77 | static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | ||
78 | { | ||
79 | struct sock *sk = sock->sk; | ||
80 | struct sockaddr_l2 la; | ||
81 | int len, err = 0; | ||
82 | |||
83 | BT_DBG("sk %p", sk); | ||
84 | |||
85 | if (!addr || addr->sa_family != AF_BLUETOOTH) | ||
86 | return -EINVAL; | ||
87 | |||
88 | memset(&la, 0, sizeof(la)); | ||
89 | len = min_t(unsigned int, sizeof(la), alen); | ||
90 | memcpy(&la, addr, len); | ||
91 | |||
92 | if (la.l2_cid) | ||
93 | return -EINVAL; | ||
94 | |||
95 | lock_sock(sk); | ||
96 | |||
97 | if (sk->sk_state != BT_OPEN) { | ||
98 | err = -EBADFD; | ||
99 | goto done; | ||
100 | } | ||
101 | |||
102 | if (la.l2_psm) { | ||
103 | __u16 psm = __le16_to_cpu(la.l2_psm); | ||
104 | |||
105 | /* PSM must be odd and lsb of upper byte must be 0 */ | ||
106 | if ((psm & 0x0101) != 0x0001) { | ||
107 | err = -EINVAL; | ||
108 | goto done; | ||
109 | } | ||
110 | |||
111 | /* Restrict usage of well-known PSMs */ | ||
112 | if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) { | ||
113 | err = -EACCES; | ||
114 | goto done; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | write_lock_bh(&l2cap_sk_list.lock); | ||
119 | |||
120 | if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) { | ||
121 | err = -EADDRINUSE; | ||
122 | } else { | ||
123 | /* Save source address */ | ||
124 | bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); | ||
125 | l2cap_pi(sk)->psm = la.l2_psm; | ||
126 | l2cap_pi(sk)->sport = la.l2_psm; | ||
127 | sk->sk_state = BT_BOUND; | ||
128 | |||
129 | if (__le16_to_cpu(la.l2_psm) == 0x0001 || | ||
130 | __le16_to_cpu(la.l2_psm) == 0x0003) | ||
131 | l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; | ||
132 | } | ||
133 | |||
134 | write_unlock_bh(&l2cap_sk_list.lock); | ||
135 | |||
136 | done: | ||
137 | release_sock(sk); | ||
138 | return err; | ||
139 | } | ||
140 | |||
141 | static int l2cap_sock_listen(struct socket *sock, int backlog) | ||
142 | { | ||
143 | struct sock *sk = sock->sk; | ||
144 | int err = 0; | ||
145 | |||
146 | BT_DBG("sk %p backlog %d", sk, backlog); | ||
147 | |||
148 | lock_sock(sk); | ||
149 | |||
150 | if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) | ||
151 | || sk->sk_state != BT_BOUND) { | ||
152 | err = -EBADFD; | ||
153 | goto done; | ||
154 | } | ||
155 | |||
156 | switch (l2cap_pi(sk)->mode) { | ||
157 | case L2CAP_MODE_BASIC: | ||
158 | break; | ||
159 | case L2CAP_MODE_ERTM: | ||
160 | case L2CAP_MODE_STREAMING: | ||
161 | if (!disable_ertm) | ||
162 | break; | ||
163 | /* fall through */ | ||
164 | default: | ||
165 | err = -ENOTSUPP; | ||
166 | goto done; | ||
167 | } | ||
168 | |||
169 | if (!l2cap_pi(sk)->psm) { | ||
170 | bdaddr_t *src = &bt_sk(sk)->src; | ||
171 | u16 psm; | ||
172 | |||
173 | err = -EINVAL; | ||
174 | |||
175 | write_lock_bh(&l2cap_sk_list.lock); | ||
176 | |||
177 | for (psm = 0x1001; psm < 0x1100; psm += 2) | ||
178 | if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { | ||
179 | l2cap_pi(sk)->psm = cpu_to_le16(psm); | ||
180 | l2cap_pi(sk)->sport = cpu_to_le16(psm); | ||
181 | err = 0; | ||
182 | break; | ||
183 | } | ||
184 | |||
185 | write_unlock_bh(&l2cap_sk_list.lock); | ||
186 | |||
187 | if (err < 0) | ||
188 | goto done; | ||
189 | } | ||
190 | |||
191 | sk->sk_max_ack_backlog = backlog; | ||
192 | sk->sk_ack_backlog = 0; | ||
193 | sk->sk_state = BT_LISTEN; | ||
194 | |||
195 | done: | ||
196 | release_sock(sk); | ||
197 | return err; | ||
198 | } | ||
199 | |||
65 | static int l2cap_sock_release(struct socket *sock) | 200 | static int l2cap_sock_release(struct socket *sock) |
66 | { | 201 | { |
67 | struct sock *sk = sock->sk; | 202 | struct sock *sk = sock->sk; |