Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 26fd76ca authored by Samuel Ortiz's avatar Samuel Ortiz
Browse files

NFC: llcp: Implement socket options



Some LLCP services (e.g. the validation ones) require some control over
the LLCP link parameters like the receive window (RW) or the MIU extension
(MIUX). This can only be done through socket options.

Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent e4306bec
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -298,6 +298,7 @@ struct ucred {
#define SOL_IUCV	277
#define SOL_IUCV	277
#define SOL_CAIF	278
#define SOL_CAIF	278
#define SOL_ALG		279
#define SOL_ALG		279
#define SOL_NFC		280


/* IPX options */
/* IPX options */
#define IPX_TYPE	1
#define IPX_TYPE	1
+4 −0
Original line number Original line Diff line number Diff line
@@ -220,4 +220,8 @@ struct sockaddr_nfc_llcp {
#define NFC_LLCP_DIRECTION_RX		0x00
#define NFC_LLCP_DIRECTION_RX		0x00
#define NFC_LLCP_DIRECTION_TX		0x01
#define NFC_LLCP_DIRECTION_TX		0x01


/* socket option names */
#define NFC_LLCP_RW   0
#define NFC_LLCP_MIUX 1

#endif /*__LINUX_NFC_H */
#endif /*__LINUX_NFC_H */
+3 −0
Original line number Original line Diff line number Diff line
@@ -104,6 +104,9 @@ struct nfc_llcp_sock {
	u8 dsap;
	u8 dsap;
	char *service_name;
	char *service_name;
	size_t service_name_len;
	size_t service_name_len;
	u8 rw;
	u16 miux;



	/* Remote link parameters */
	/* Remote link parameters */
	u8 remote_rw;
	u8 remote_rw;
+117 −2
Original line number Original line Diff line number Diff line
@@ -223,6 +223,121 @@ static int llcp_sock_listen(struct socket *sock, int backlog)
	return ret;
	return ret;
}
}


static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
			       char __user *optval, unsigned int optlen)
{
	struct sock *sk = sock->sk;
	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
	u32 opt;
	int err = 0;

	pr_debug("%p optname %d\n", sk, optname);

	if (level != SOL_NFC)
		return -ENOPROTOOPT;

	lock_sock(sk);

	switch (optname) {
	case NFC_LLCP_RW:
		if (sk->sk_state == LLCP_CONNECTED ||
		    sk->sk_state == LLCP_BOUND ||
		    sk->sk_state == LLCP_LISTEN) {
			err = -EINVAL;
			break;
		}

		if (get_user(opt, (u32 __user *) optval)) {
			err = -EFAULT;
			break;
		}

		if (opt > LLCP_MAX_RW) {
			err = -EINVAL;
			break;
		}

		llcp_sock->rw = (u8) opt;

		break;

	case NFC_LLCP_MIUX:
		if (sk->sk_state == LLCP_CONNECTED ||
		    sk->sk_state == LLCP_BOUND ||
		    sk->sk_state == LLCP_LISTEN) {
			err = -EINVAL;
			break;
		}

		if (get_user(opt, (u32 __user *) optval)) {
			err = -EFAULT;
			break;
		}

		if (opt > LLCP_MAX_MIUX) {
			err = -EINVAL;
			break;
		}

		llcp_sock->miux = (u16) opt;

		break;

	default:
		err = -ENOPROTOOPT;
		break;
	}

	release_sock(sk);

	return err;
}

static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
			       char __user *optval, int __user *optlen)
{
	struct sock *sk = sock->sk;
	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
	int len, err = 0;

	pr_debug("%p optname %d\n", sk, optname);

	if (level != SOL_NFC)
		return -ENOPROTOOPT;

	if (get_user(len, optlen))
		return -EFAULT;

	len = min_t(u32, len, sizeof(u32));

	lock_sock(sk);

	switch (optname) {
	case NFC_LLCP_RW:
		if (put_user(llcp_sock->rw, (u32 __user *) optval))
			err = -EFAULT;

		break;

	case NFC_LLCP_MIUX:
		if (put_user(llcp_sock->miux, (u32 __user *) optval))
			err = -EFAULT;

		break;

	default:
		err = -ENOPROTOOPT;
		break;
	}

	release_sock(sk);

	if (put_user(len, optlen))
		return -EFAULT;

	return err;
}

void nfc_llcp_accept_unlink(struct sock *sk)
void nfc_llcp_accept_unlink(struct sock *sk)
{
{
	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
@@ -735,8 +850,8 @@ static const struct proto_ops llcp_sock_ops = {
	.ioctl          = sock_no_ioctl,
	.ioctl          = sock_no_ioctl,
	.listen         = llcp_sock_listen,
	.listen         = llcp_sock_listen,
	.shutdown       = sock_no_shutdown,
	.shutdown       = sock_no_shutdown,
	.setsockopt     = sock_no_setsockopt,
	.setsockopt     = nfc_llcp_setsockopt,
	.getsockopt     = sock_no_getsockopt,
	.getsockopt     = nfc_llcp_getsockopt,
	.sendmsg        = llcp_sock_sendmsg,
	.sendmsg        = llcp_sock_sendmsg,
	.recvmsg        = llcp_sock_recvmsg,
	.recvmsg        = llcp_sock_recvmsg,
	.mmap           = sock_no_mmap,
	.mmap           = sock_no_mmap,