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>
This commit is contained in:
Aaro Koskinen 2019-02-08 16:30:24 +01:00 committed by Denys Vlasenko
parent 78301861ef
commit c89764c063

View File

@ -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++;
}