[net-next,4/8] l2tp: handle PPPIOC[GS]MRU and PPPIOC[GS]FLAGS in pppol2tp_ioctl()

Message ID cafaae7de607cd27ec4935997834f8e860fc6c69.1533895306.git.g.nault@alphalink.fr
State Accepted
Delegated to: David Miller
Headers show
Series
  • l2tp: rework pppol2tp ioctl handling
Related show

Commit Message

Guillaume Nault Aug. 10, 2018, 11:21 a.m.
Let pppol2tp_ioctl() handle ioctl commands directly. It still relies on
pppol2tp_{session,tunnel}_ioctl() for PPPIOCGL2TPSTATS.

Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
---
Checkpatch does not like the -ENOSYS return value, which should only be
used for non-existing syscalls. I have kept them so that userspace gets
the same errors before and after this patch.

However I am feeling that I may be too conservative and that, maybe
the *MRU and *FLAGS commands should be dropped entirely, like *IFMTU
was. That would drop two of the three -ENOSYS errors (the last one is
dropped by the last patch anyway).

David, James, do you have any preference? After all, the MRU/FLAGS
ioctls never had any effect on pppol2tp sockets. So I do not expect
code to use them or expect them to succeed. I you are ok, I will send
a followup patch for dropping those commands.

 net/l2tp/l2tp_ppp.c | 73 +++++++++++++++++++++++++++------------------
 1 file changed, 44 insertions(+), 29 deletions(-)

Patch

diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index e3ed8d473d91..f4ec6b2a093e 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -1045,7 +1045,6 @@  static int pppol2tp_session_ioctl(struct l2tp_session *session,
 {
 	int err = 0;
 	struct sock *sk;
-	int val = (int) arg;
 	struct l2tp_tunnel *tunnel = session->tunnel;
 	struct pppol2tp_ioc_stats stats;
 
@@ -1058,22 +1057,6 @@  static int pppol2tp_session_ioctl(struct l2tp_session *session,
 		return -EBADR;
 
 	switch (cmd) {
-	case PPPIOCGMRU:
-	case PPPIOCGFLAGS:
-		err = -EFAULT;
-		if (put_user(0, (int __user *)arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCSMRU:
-	case PPPIOCSFLAGS:
-		err = -EFAULT;
-		if (get_user(val, (int __user *)arg))
-			break;
-		err = 0;
-		break;
-
 	case PPPIOCGL2TPSTATS:
 		err = -ENXIO;
 		if (!(sk->sk_state & PPPOX_CONNECTED))
@@ -1180,23 +1163,55 @@  static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd,
 			  unsigned long arg)
 {
 	struct l2tp_session *session;
-	struct l2tp_tunnel *tunnel;
+	int val;
+
+	switch (cmd) {
+	case PPPIOCGMRU:
+	case PPPIOCGFLAGS:
+		session = sock->sk->sk_user_data;
+		if (!session)
+			return -ENOTCONN;
 
-	session = sock->sk->sk_user_data;
-	if (!session)
-		return -ENOTCONN;
+		/* Not defined for tunnels */
+		if (!session->session_id && !session->peer_session_id)
+			return -ENOSYS;
 
-	/* Special case: if session's session_id is zero, treat ioctl as a
-	 * tunnel ioctl
-	 */
-	if ((session->session_id == 0) &&
-	    (session->peer_session_id == 0)) {
-		tunnel = session->tunnel;
+		if (put_user(0, (int __user *)arg))
+			return -EFAULT;
+		break;
+
+	case PPPIOCSMRU:
+	case PPPIOCSFLAGS:
+		session = sock->sk->sk_user_data;
+		if (!session)
+			return -ENOTCONN;
 
-		return pppol2tp_tunnel_ioctl(tunnel, cmd, arg);
+		/* Not defined for tunnels */
+		if (!session->session_id && !session->peer_session_id)
+			return -ENOSYS;
+
+		if (get_user(val, (int __user *)arg))
+			return -EFAULT;
+		break;
+
+	case PPPIOCGL2TPSTATS:
+		session = sock->sk->sk_user_data;
+		if (!session)
+			return -ENOTCONN;
+
+		/* Session 0 represents the parent tunnel */
+		if (!session->session_id && !session->peer_session_id)
+			return pppol2tp_tunnel_ioctl(session->tunnel, cmd,
+						     arg);
+		else
+			return pppol2tp_session_ioctl(session, cmd, arg);
+		break;
+
+	default:
+		return -ENOSYS;
 	}
 
-	return pppol2tp_session_ioctl(session, cmd, arg);
+	return 0;
 }
 
 /*****************************************************************************