Browse Source

sysctl: fix compatibility with procps sysctl

Busybox sysctl is incompatible with procps when '.' appears in
directory name, mostly happens with VLANs.

        busybox syntax (since 2008): net.ipv4.conf.eth0.100.mc_forwarding
         procps syntax (since 2002): net.ipv4.conf.eth0/100.mc_forwarding
                 (supported by both: net/ipv4/conf/eth0.100/mc_forwarding)

Use procps syntax for output; for input, allow both.

function                                             old     new   delta
sysctl_dots_to_slashes                                86     143     +57
sysctl_act_on_setting                                443     453     +10
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 67/0)               Total: 67 bytes

Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Aaro Koskinen 5 years ago
parent
commit
c89764c063
1 changed files with 26 additions and 2 deletions
  1. 26 2
      procps/sysctl.c

+ 26 - 2
procps/sysctl.c

@@ -56,9 +56,32 @@ enum {
 
 static void sysctl_dots_to_slashes(char *name)
 {
-	char *cptr, *last_good, *end;
+	char *cptr, *last_good, *end, *slash;
 	char end_ch;
 
+	end = strchrnul(name, '=');
+
+	slash = strchrnul(name, '/');
+	if (slash < end
+	 && strchrnul(name, '.') < slash
+	) {
+		/* There are both dots and slashes, and 1st dot is
+		 * before 1st slash.
+		 * (IOW: not raw, unmangled a/b/c.d format)
+		 *
+		 * procps supports this syntax for names with dots:
+		 *  net.ipv4.conf.eth0/100.mc_forwarding
+		 * (dots and slashes are simply swapped)
+		 */
+		while (end != name) {
+			end--;
+			if (*end == '.') *end = '/';
+			else if (*end == '/') *end = '.';
+		}
+		return;
+	}
+	/* else: use our old behavior: */
+
 	/* Convert minimum number of '.' to '/' so that
 	 * we end up with existing file's name.
 	 *
@@ -77,7 +100,6 @@ static void sysctl_dots_to_slashes(char *name)
 	 *
 	 * To set up testing: modprobe 8021q; vconfig add eth0 100
 	 */
-	end = strchrnul(name, '=');
 	end_ch = *end;
 	*end = '.'; /* trick the loop into trying full name too */
 
@@ -114,6 +136,8 @@ static int sysctl_act_on_setting(char *setting)
 	while (*cptr) {
 		if (*cptr == '/')
 			*cptr = '.';
+		else if (*cptr == '.')
+			*cptr = '/';
 		cptr++;
 	}