aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/socket.h1
-rw-r--r--include/uapi/linux/nfc.h4
-rw-r--r--net/nfc/llcp/llcp.h3
-rw-r--r--net/nfc/llcp/sock.c119
4 files changed, 125 insertions, 2 deletions
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 2b9f74b0ffea..428c37a1f95c 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -298,6 +298,7 @@ struct ucred {
298#define SOL_IUCV 277 298#define SOL_IUCV 277
299#define SOL_CAIF 278 299#define SOL_CAIF 278
300#define SOL_ALG 279 300#define SOL_ALG 279
301#define SOL_NFC 280
301 302
302/* IPX options */ 303/* IPX options */
303#define IPX_TYPE 1 304#define IPX_TYPE 1
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h
index 7969f46f1bb3..855630fe731d 100644
--- a/include/uapi/linux/nfc.h
+++ b/include/uapi/linux/nfc.h
@@ -220,4 +220,8 @@ struct sockaddr_nfc_llcp {
220#define NFC_LLCP_DIRECTION_RX 0x00 220#define NFC_LLCP_DIRECTION_RX 0x00
221#define NFC_LLCP_DIRECTION_TX 0x01 221#define NFC_LLCP_DIRECTION_TX 0x01
222 222
223/* socket option names */
224#define NFC_LLCP_RW 0
225#define NFC_LLCP_MIUX 1
226
223#endif /*__LINUX_NFC_H */ 227#endif /*__LINUX_NFC_H */
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 32cec81939e6..5f117adac2e5 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -104,6 +104,9 @@ struct nfc_llcp_sock {
104 u8 dsap; 104 u8 dsap;
105 char *service_name; 105 char *service_name;
106 size_t service_name_len; 106 size_t service_name_len;
107 u8 rw;
108 u16 miux;
109
107 110
108 /* Remote link parameters */ 111 /* Remote link parameters */
109 u8 remote_rw; 112 u8 remote_rw;
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index cc564992ba95..9357a756f7a9 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -223,6 +223,121 @@ error:
223 return ret; 223 return ret;
224} 224}
225 225
226static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
227 char __user *optval, unsigned int optlen)
228{
229 struct sock *sk = sock->sk;
230 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
231 u32 opt;
232 int err = 0;
233
234 pr_debug("%p optname %d\n", sk, optname);
235
236 if (level != SOL_NFC)
237 return -ENOPROTOOPT;
238
239 lock_sock(sk);
240
241 switch (optname) {
242 case NFC_LLCP_RW:
243 if (sk->sk_state == LLCP_CONNECTED ||
244 sk->sk_state == LLCP_BOUND ||
245 sk->sk_state == LLCP_LISTEN) {
246 err = -EINVAL;
247 break;
248 }
249
250 if (get_user(opt, (u32 __user *) optval)) {
251 err = -EFAULT;
252 break;
253 }
254
255 if (opt > LLCP_MAX_RW) {
256 err = -EINVAL;
257 break;
258 }
259
260 llcp_sock->rw = (u8) opt;
261
262 break;
263
264 case NFC_LLCP_MIUX:
265 if (sk->sk_state == LLCP_CONNECTED ||
266 sk->sk_state == LLCP_BOUND ||
267 sk->sk_state == LLCP_LISTEN) {
268 err = -EINVAL;
269 break;
270 }
271
272 if (get_user(opt, (u32 __user *) optval)) {
273 err = -EFAULT;
274 break;
275 }
276
277 if (opt > LLCP_MAX_MIUX) {
278 err = -EINVAL;
279 break;
280 }
281
282 llcp_sock->miux = (u16) opt;
283
284 break;
285
286 default:
287 err = -ENOPROTOOPT;
288 break;
289 }
290
291 release_sock(sk);
292
293 return err;
294}
295
296static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
297 char __user *optval, int __user *optlen)
298{
299 struct sock *sk = sock->sk;
300 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
301 int len, err = 0;
302
303 pr_debug("%p optname %d\n", sk, optname);
304
305 if (level != SOL_NFC)
306 return -ENOPROTOOPT;
307
308 if (get_user(len, optlen))
309 return -EFAULT;
310
311 len = min_t(u32, len, sizeof(u32));
312
313 lock_sock(sk);
314
315 switch (optname) {
316 case NFC_LLCP_RW:
317 if (put_user(llcp_sock->rw, (u32 __user *) optval))
318 err = -EFAULT;
319
320 break;
321
322 case NFC_LLCP_MIUX:
323 if (put_user(llcp_sock->miux, (u32 __user *) optval))
324 err = -EFAULT;
325
326 break;
327
328 default:
329 err = -ENOPROTOOPT;
330 break;
331 }
332
333 release_sock(sk);
334
335 if (put_user(len, optlen))
336 return -EFAULT;
337
338 return err;
339}
340
226void nfc_llcp_accept_unlink(struct sock *sk) 341void nfc_llcp_accept_unlink(struct sock *sk)
227{ 342{
228 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); 343 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
@@ -735,8 +850,8 @@ static const struct proto_ops llcp_sock_ops = {
735 .ioctl = sock_no_ioctl, 850 .ioctl = sock_no_ioctl,
736 .listen = llcp_sock_listen, 851 .listen = llcp_sock_listen,
737 .shutdown = sock_no_shutdown, 852 .shutdown = sock_no_shutdown,
738 .setsockopt = sock_no_setsockopt, 853 .setsockopt = nfc_llcp_setsockopt,
739 .getsockopt = sock_no_getsockopt, 854 .getsockopt = nfc_llcp_getsockopt,
740 .sendmsg = llcp_sock_sendmsg, 855 .sendmsg = llcp_sock_sendmsg,
741 .recvmsg = llcp_sock_recvmsg, 856 .recvmsg = llcp_sock_recvmsg,
742 .mmap = sock_no_mmap, 857 .mmap = sock_no_mmap,