From mjt at tls.msk.ru Sat Apr 1 07:28:42 2023 From: mjt at tls.msk.ru (Michael Tokarev) Date: Sat, 1 Apr 2023 10:28:42 +0300 Subject: [PATCH] buildsys: resurrect PLATFORM_LINUX and depend on it for linux-specific applets In-Reply-To: <20221104164927.95804-1-mjt@msgid.tls.msk.ru> References: <20221104164927.95804-1-mjt@msgid.tls.msk.ru> Message-ID: Friendly ping #2. Is something like this not welcomed at all, or is okay generally but done in a wrong way, or maybe something else entirely? The change is relatively large and the code is bit-rotting slowly.. Thanks, /mjt 04.11.2022 19:49, Michael Tokarev wrote: > This effectively reverts the following two commits: > > commit e3b1a1fd28558f7a1b3c0ec33313bedb675be8a1 > Author: Denys Vlasenko > Date: Sat Feb 26 22:24:08 2011 +0100 > > Replace "depends on PLATFORM_LINUX" with "select PLATFORM_LINUX" > > and > > commit 5c69ad0ecdc18cf51b312c7c82848f4438fe1c8d > Author: Ron Yorston > Date: Tue Aug 4 08:24:19 2020 +0100 > > build system: drop PLATFORM_LINUX > > but does, hopefully, the right thing. > > Original complain was that the allnoconfig turns off PLATFORM_LINUX > on which all linux-specific applets depends. Instead of setting this > config option right for linux and non-linux (initially it was just a > regular kconfig symbol, not set depending on the platform), it were > turned into something which made little sense (in the first commit), > and later dropped completely. > > So introduce a dynamic kconfig symbol PLATFORM_LINUX with the value > actually depending on the target platform, so that it is not affected > by all{yes|no|whatever}config. This way, it is possible to depend on > it for linux-specific applets without breaking *config anymore. > > It is done by creating a small kconfig fragment, .platform.in, to > define just PLATFORM_LINUX symbol. It is created in Makefile if > ${CPP} has __linux__ #defined. And include it in the top-level Config.in. > > Regenerate default config files with the new symbol. > > And mark all the applets which were marked as "select PLATFORM_LINUX" > before the "build system: drop PLATFORM_LINUX" commit, as > "depends on PLATFORM_LINUX". > > Also mark 2 other applets, tc and dhcprelay, as linux-only too. > > This way, it is finally possible to build busybox on other platforms > without really huge efforts to maintain list of "incompatible" applets > externally, and does not put any pressure on the main development, - > the only thing needed is to keep the existing "depends on PLATFORM_LINUX" > lines. From rmy at pobox.com Mon Apr 3 20:33:34 2023 From: rmy at pobox.com (Ron Yorston) Date: Mon, 03 Apr 2023 21:33:34 +0100 Subject: sleep as an ash builtin Message-ID: <642b381e.RGMiXYMi3rqdOrsZ%rmy@pobox.com> Another thing about sleep as an ash builtin: $ trap 'echo yo' INT $ echo $EPOCHSECONDS; sleep 10; echo $EPOCHSECONDS 1680553805 ^C^C^C^C^Cyo 1680553815 $ No matter how urgently I press Ctrl-C the sleep runs its full course. Ron From akos.somfai at gmail.com Mon Apr 3 20:52:06 2023 From: akos.somfai at gmail.com (Akos Somfai) Date: Mon, 3 Apr 2023 22:52:06 +0200 Subject: [PATCH] lineedit: fix crash when icanon set with -echo Message-ID: <20230403205206.2902-1-akos.somfai@gmail.com> When icanon is set with -echo (e.g. ssh from an emacs shell) then S.state will remain null but later it will be deferenced causing ash to crash. Fix: additional check on state. --- libbb/lineedit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 625884adf..bdae10914 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -254,7 +254,7 @@ static NOINLINE const char *get_homedir_or_NULL(void) const char *home; # if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH - home = state->sh_get_var ? state->sh_get_var("HOME") : getenv("HOME"); + home = state && state->sh_get_var ? state->sh_get_var("HOME") : getenv("HOME"); # else home = getenv("HOME"); # endif @@ -2038,7 +2038,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) if (!cwd_buf) { const char *home; # if EDITING_HAS_sh_get_var - cwd_buf = state->sh_get_var + cwd_buf = state && state->sh_get_var ? xstrdup(state->sh_get_var("PWD")) : xrealloc_getcwd_or_warn(NULL); # else -- 2.40.0 From Keith.S.Thompson at gmail.com Tue Apr 4 05:15:40 2023 From: Keith.S.Thompson at gmail.com (Keith Thompson) Date: Mon, 3 Apr 2023 22:15:40 -0700 Subject: busybox seq doesn't handle negative numbers Message-ID: The GNU coreutils seq command recognizes and handles negative arguments. The busybox seq command does not. Any argument starting with a '-' character is assumed to be an option name. There is a (rather inconvenient) workaround: you can add a leading space, which is ignored. Busybox 1.36.0 (built from source), Ubuntu 22.04.2, GNU coreutils 8.32. ``` $ seq -s : -5 5 -5:-4:-3:-2:-1:0:1:2:3:4:5 $ busybox seq -s : -5 5 seq: invalid option -- '5' BusyBox v1.36.0 (2023-04-03 21:54:22 PDT) multi-call binary. Usage: seq [-w] [-s SEP] [FIRST [INC]] LAST Print numbers from FIRST to LAST, in steps of INC. FIRST, INC default to 1. -w Pad to last with leading zeros -s SEP String separator Exit 1 $ busybox seq -s : ' -5' 5 -5:-4:-3:-2:-1:0:1:2:3:4:5 ``` From asmadeus at codewreck.org Tue Apr 4 05:59:28 2023 From: asmadeus at codewreck.org (Dominique Martinet) Date: Tue, 4 Apr 2023 14:59:28 +0900 Subject: busybox seq doesn't handle negative numbers In-Reply-To: References: Message-ID: Keith Thompson wrote on Mon, Apr 03, 2023 at 10:15:40PM -0700: > The GNU coreutils seq command recognizes and handles negative > arguments. > > The busybox seq command does not. Any argument starting with a '-' > character is assumed to be an option name. > > There is a (rather inconvenient) workaround: you can add a leading > space, which is ignored. You can also use '--' to stop parsing options and feels a bit more standard than leading spaces. $ busybox seq -- -2 2 -2 -1 0 1 2 Commands like busybox tail handle ?digit, so I assume something similar can be done but that will be a bit convoluted to make it work the same way when there are other arguments first... -- Dominique Martinet | Asmadeus From steffen at sdaoden.eu Tue Apr 4 16:29:32 2023 From: steffen at sdaoden.eu (Steffen Nurpmeso) Date: Tue, 04 Apr 2023 18:29:32 +0200 Subject: busybox seq doesn't handle negative numbers In-Reply-To: References: Message-ID: <20230404162932.K_bQ8%steffen@sdaoden.eu> Dominique Martinet wrote in : |Keith Thompson wrote on Mon, Apr 03, 2023 at 10:15:40PM -0700: |> The GNU coreutils seq command recognizes and handles negative |> arguments. |> |> The busybox seq command does not. Any argument starting with a '-' |> character is assumed to be an option name. |> |> There is a (rather inconvenient) workaround: you can add a leading |> space, which is ignored. | |You can also use '--' to stop parsing options and feels a bit more |standard than leading spaces. Yeah, the thing rather is that GNU getopt parses the command line and performs reorders. I never really looked, but since the (entire family of the) mailer i maintain earned a security advisory for possible option injection attacks i always wondered how secure that can be. Despite that one of SuSE's blocks against my mailer (to replace its hm predecessor) is that they want me to support a different argument order (as in "[:opts:] [:receiver:] [:opts:] instead of "[:opts:] [:receiver:]"), but i do not, 'having added -. to explicitly stop option processing (we do also support --, but that then separates arguments to be passed to the MTA, further on down the command line) in order to prevent such option injection attacks. --steffen | |Der Kragenbaer, The moon bear, |der holt sich munter he cheerfully and one by one |einen nach dem anderen runter wa.ks himself off |(By Robert Gernhardt) From Keith.S.Thompson at gmail.com Tue Apr 4 21:12:10 2023 From: Keith.S.Thompson at gmail.com (Keith Thompson) Date: Tue, 4 Apr 2023 14:12:10 -0700 Subject: busybox seq doesn't handle negative numbers In-Reply-To: References: Message-ID: On Mon, Apr 3, 2023 at 10:59?PM Dominique Martinet wrote: > > Keith Thompson wrote on Mon, Apr 03, 2023 at 10:15:40PM -0700: > > The GNU coreutils seq command recognizes and handles negative > > arguments. > > > > The busybox seq command does not. Any argument starting with a '-' > > character is assumed to be an option name. > > > > There is a (rather inconvenient) workaround: you can add a leading > > space, which is ignored. > > You can also use '--' to stop parsing options and feels a bit more > standard than leading spaces. [...] Yes, using "--" is a better workaround than a quoted leading space. Another minor issue: The usage message for the -w option is unclear and not entirely accurate: -w Pad to last with leading zeros It took me a while to figure out that it means that it pads to the width of the LAST argument. And in fact it also (correctly) takes into account the width of the FIRST argument: $ busybox seq -s : -w -- -9 1 -9:-8:-7:-6:-5:-4:-3:-2:-1:00:01 $ busybox seq -s : -w -- -10 1 -10:-09:-08:-07:-06:-05:-04:-03:-02:-01:000:001 The GNU coreutils seq command has a clearer usage message for this: -w, --equal-width equalize width by padding with leading zeroes (I'm not suggesting busybox should support the long option.) From David.Laight at ACULAB.COM Wed Apr 5 08:19:25 2023 From: David.Laight at ACULAB.COM (David Laight) Date: Wed, 5 Apr 2023 08:19:25 +0000 Subject: busybox seq doesn't handle negative numbers In-Reply-To: <20230404162932.K_bQ8%steffen@sdaoden.eu> References: <20230404162932.K_bQ8%steffen@sdaoden.eu> Message-ID: <431dc1a049e445c6aaf57b8995f465d1@AcuMS.aculab.com> ... > Yeah, the thing rather is that GNU getopt parses the command line > and performs reorders. I never really looked, but since the > (entire family of the) mailer i maintain earned a security > advisory for possible option injection attacks i always wondered > how secure that can be... Yes, that is entirely broken and should never have been committed. I have to remember to add the 'magic character' to disable it. Historically a few programs use nonstandard argument ordering. Most notably 'rlogin hostname -l username' but that really doesn't justify how gnu getopt() works. Programs like tail, seq and sort are old and have argument parsing that (probably) predates the standard. (Although 'sort +4' seems to have been disabled even though it worked fine for over 30 years.) I wonder if there is an easy way to 'escape' from busybox getopt's 'unknown option' error path without printing a message (and them being able to print the message) so that programs like seq can decide that -12 isn't actually invalid. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) From steffen at sdaoden.eu Wed Apr 5 16:15:14 2023 From: steffen at sdaoden.eu (Steffen Nurpmeso) Date: Wed, 05 Apr 2023 18:15:14 +0200 Subject: busybox seq doesn't handle negative numbers In-Reply-To: <431dc1a049e445c6aaf57b8995f465d1@AcuMS.aculab.com> References: <20230404162932.K_bQ8%steffen@sdaoden.eu> <431dc1a049e445c6aaf57b8995f465d1@AcuMS.aculab.com> Message-ID: <20230405161514.nNYUl%steffen@sdaoden.eu> David Laight wrote in <431dc1a049e445c6aaf57b8995f465d1 at AcuMS.aculab.com>: |... |> Yeah, the thing rather is that GNU getopt parses the command line |> and performs reorders. I never really looked, but since the |> (entire family of the) mailer i maintain earned a security |> advisory for possible option injection attacks i always wondered |> how secure that can be... | |Yes, that is entirely broken and should never have been committed. |I have to remember to add the 'magic character' to disable it. Well ok as you say it, GNU coreutils seq uses an initial "+" to avoid this "permutation". I did not really look. GNU coreutils: #?0|kent:src$ grep -r getopt *.c|grep ' "[^+]'|wc -l 58 #?0|kent:src$ grep -r getopt *.c|grep ' "[+]'|wc -l 10 #?0|kent:src$ grep -r getopt *.c|grep ' "[+]'|cut -f1 -d' ' basename.c: chroot.c: nice.c: pathchk.c: printenv.c: runcon.c: seq.c: stdbuf.c: timeout.c: tr.c: In my opinion permutation is nonetheless a really expensive and terrible thing, and once you are used to have to terminate option processing to be on the safe side, you got it. Some things just need treatment, so it is. |Historically a few programs use nonstandard argument ordering. |Most notably 'rlogin hostname -l username' but that really |doesn't justify how gnu getopt() works. | |Programs like tail, seq and sort are old and have argument |parsing that (probably) predates the standard. |(Although 'sort +4' seems to have been disabled even though |it worked fine for over 30 years.) | |I wonder if there is an easy way to 'escape' from busybox |getopt's 'unknown option' error path without printing a |message (and them being able to print the message) so that |programs like seq can decide that -12 isn't actually invalid. --steffen | |Der Kragenbaer, The moon bear, |der holt sich munter he cheerfully and one by one |einen nach dem anderen runter wa.ks himself off |(By Robert Gernhardt) From pp01415943 at gmail.com Fri Apr 7 12:11:59 2023 From: pp01415943 at gmail.com (Petja Patjas) Date: Fri, 7 Apr 2023 15:11:59 +0300 Subject: [PATCH] vi: Fix 'o' and 'A' for files without an EOL. Message-ID: The problem can be reproduced by creating a file with some text that does not end in a newline: $ printf test > test $ vi test The last character will be placed on the next line as well. Problems can be seen with the 'A' command too. This patch should fix the problems. --- editors/vi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/editors/vi.c b/editors/vi.c index 2645afe87..ca8130722 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -556,6 +556,7 @@ static int crashme = 0; static void show_status_line(void); // put a message on the bottom line static void status_line_bold(const char *, ...); +static char *char_insert(char *p, char c, int undo); static void show_help(void) { @@ -1830,6 +1831,10 @@ static void dot_end(void) { undo_queue_commit(); dot = end_line(dot); // return pointer to last char cur line + if (*dot != '\n') { + /* There was no EOL, so create one. */ + dot = char_insert(dot + 1, '\n', NO_UNDO) - 1; + } } static char *move_to_col(char *p, int l) From pp01415943 at gmail.com Fri Apr 7 21:13:04 2023 From: pp01415943 at gmail.com (Petja Patjas) Date: Sat, 8 Apr 2023 00:13:04 +0300 Subject: [PATCH] vi: Fix 'o' and 'A' for files without an EOL. In-Reply-To: References: Message-ID: <8f744744-9f76-9e61-b26e-d33f5335a6f8@gmail.com> > The problem can be reproduced by creating a file with some text that > does not end in a newline: > > $ printf test > test > $ vi test > > > The last character will be placed on the next line as well. Problems can > be seen with the 'A' command too. > > This patch should fix the problems. > --- > editors/vi.c | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/editors/vi.c b/editors/vi.c > index 2645afe87..ca8130722 100644 > --- a/editors/vi.c > +++ b/editors/vi.c > @@ -556,6 +556,7 @@ static int crashme = 0; > > static void show_status_line(void); // put a message on the bottom line > static void status_line_bold(const char *, ...); > +static char *char_insert(char *p, char c, int undo); > > static void show_help(void) > { > @@ -1830,6 +1831,10 @@ static void dot_end(void) > { > undo_queue_commit(); > dot = end_line(dot); // return pointer to last char cur line > + if (*dot != '\n') { > + /* There was no EOL, so create one. */ > + dot = char_insert(dot + 1, '\n', NO_UNDO) - 1; > + } > } > > static char *move_to_col(char *p, int l) Ignore that patch, it breaks empty files. Here is another try. This makes init_text_buffer() add a terminating newline if the file is empty or the last character is not a newline. --- editors/vi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/editors/vi.c b/editors/vi.c index 2645afe87..d6c6e068e 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -2318,6 +2318,9 @@ static int init_text_buffer(char *fn) if (rc < 0) { // file doesnt exist. Start empty buf with dummy line char_insert(text, '\n', NO_UNDO); + } else if (end == text || *(end - 1) != '\n') { + // Make the last character of the buffer a newline. + char_insert(end, '\n', NO_UNDO); } flush_undo_data(); From tomaspaukrt at email.cz Sun Apr 9 08:18:51 2023 From: tomaspaukrt at email.cz (Tomas Paukrt) Date: Sun, 09 Apr 2023 10:18:51 +0200 (CEST) Subject: [PATCH] appletlib: fix "warning: unused variable applet_no" Message-ID: <3pR.ZYjX.2kbabLEuvV2.1aCdJh@seznam.cz> >From 0d02a593c1ddeb7c4bb49b26524498a388ce0a0f Mon Sep 17 00:00:00 2001 From: Tomas Paukrt Date: Sun, 9 Apr 2023 08:57:46 +0200 Subject: [PATCH] appletlib: fix "warning: unused variable applet_no" Signed-off-by: Tomas Paukrt --- libbb/appletlib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index d5335d3..d9cc484 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -918,7 +918,7 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) # endif # if NUM_APPLETS > 0 -void FAST_FUNC show_usage_if_dash_dash_help(int applet_no, char **argv) +void FAST_FUNC show_usage_if_dash_dash_help(int applet_no UNUSED_PARAM, char **argv) { /* Special case. POSIX says "test --help" * should be no different from e.g. "test --foo". -- 2.7.4 From tomaspaukrt at email.cz Sun Apr 9 08:19:29 2023 From: tomaspaukrt at email.cz (Tomas Paukrt) Date: Sun, 09 Apr 2023 10:19:29 +0200 (CEST) Subject: [PATCH] build system: clean more files on make clean Message-ID: <3pS.ZYjZ.5JrccbtTndk.1aCdKH@seznam.cz> >From 57bf559403d89133197d33a2a181815d1f057b2b Mon Sep 17 00:00:00 2001 From: Tomas Paukrt Date: Sun, 9 Apr 2023 09:06:43 +0200 Subject: [PATCH] build system: clean more files on make clean Signed-off-by: Tomas Paukrt --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7b4686f..4dcd592 100644 --- a/Makefile +++ b/Makefile @@ -966,7 +966,7 @@ endif # CONFIG_MODULES # Directories & files removed with 'make clean' CLEAN_DIRS += $(MODVERDIR) _install 0_lib -CLEAN_FILES += busybox busybox_unstripped* busybox.links \ +CLEAN_FILES += busybox busybox_unstripped* busybox.links busybox*.suid busybox*.nosuid \ System.map .kernelrelease \ .tmp_kallsyms* .tmp_version .tmp_busybox* .tmp_System.map -- 2.7.4 From vda.linux at googlemail.com Mon Apr 10 12:35:27 2023 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Mon, 10 Apr 2023 14:35:27 +0200 Subject: busybox seq doesn't handle negative numbers In-Reply-To: References: Message-ID: On Tue, Apr 4, 2023 at 7:16?AM Keith Thompson wrote: > The GNU coreutils seq command recognizes and handles negative > arguments. > > The busybox seq command does not. Any argument starting with a '-' > character is assumed to be an option name. Fixed, please try current git. From eblake at redhat.com Mon Apr 10 14:00:24 2023 From: eblake at redhat.com (Eric Blake) Date: Mon, 10 Apr 2023 09:00:24 -0500 Subject: [PATCH] readlink: Support --, -n always In-Reply-To: <20230324145814.1113627-1-eblake@redhat.com> References: <20230324145814.1113627-1-eblake@redhat.com> Message-ID: Ping On Fri, Mar 24, 2023 at 09:58:14AM -0500, Eric Blake wrote: > POSIX will be standardizing readlink (just the -n option) and realpath > (just -E and -e options): > https://www.austingroupbugs.net/view.php?id=1457 > > Change things for readlink so that the POSIX-mandated -n and -- work > even when disabling the non-standard (and partially non-working) -f > when FEATURE_READLINK_FOLLOW is clear. > > POSIX also wants readlink to be verbose by default (if the argument is > not a symlink, readlink must output a diagnostic); I did NOT address > that one, because I'm waiting to see what the GNU Coreutils folks do: > https://lists.gnu.org/archive/html/bug-coreutils/2023-03/msg00035.html > > Partial fix for https://bugs.busybox.net/show_bug.cgi?id=15466 > > Signed-off-by: Eric Blake > --- > coreutils/readlink.c | 29 ++++++++++++----------------- > 1 file changed, 12 insertions(+), 17 deletions(-) > > diff --git a/coreutils/readlink.c b/coreutils/readlink.c > index b2e867883..0a9aa957e 100644 > --- a/coreutils/readlink.c > +++ b/coreutils/readlink.c > @@ -25,12 +25,14 @@ > //kbuild:lib-$(CONFIG_READLINK) += readlink.o > > //usage:#define readlink_trivial_usage > -//usage: IF_FEATURE_READLINK_FOLLOW("[-fnv] ") "FILE" > +//usage: IF_FEATURE_READLINK_FOLLOW("[-fnv] ") > +//usage: IF_NOT_FEATURE_READLINK_FOLLOW("[-n] ") > +//usage: "FILE" > //usage:#define readlink_full_usage "\n\n" > -//usage: "Display the value of a symlink" > -//usage: IF_FEATURE_READLINK_FOLLOW( "\n" > -//usage: "\n -f Canonicalize by following all symlinks" > +//usage: "Display the value of a symlink" "\n" > //usage: "\n -n Don't add newline" > +//usage: IF_FEATURE_READLINK_FOLLOW( > +//usage: "\n -f Canonicalize by following all symlinks" > //usage: "\n -v Verbose" > //usage: ) > > @@ -67,25 +69,18 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) > { > char *buf; > char *fname; > + unsigned opt; > > - IF_FEATURE_READLINK_FOLLOW( > - unsigned opt; > - /* We need exactly one non-option argument. */ > - opt = getopt32(argv, "^" "fnvsq" "\0" "=1"); > - fname = argv[optind]; > - ) > - IF_NOT_FEATURE_READLINK_FOLLOW( > - const unsigned opt = 0; > - if (argc != 2) bb_show_usage(); > - fname = argv[1]; > - ) > + opt = getopt32(argv, "^" "n" IF_FEATURE_READLINK_FOLLOW("fvsq") > + "\0" "=1"); > + fname = argv[optind]; > > /* compat: coreutils readlink reports errors silently via exit code */ > if (!(opt & 4)) /* not -v */ > logmode = LOGMODE_NONE; > > /* NOFORK: only one alloc is allowed; must free */ > - if (opt & 1) { /* -f */ > + if (opt & 2) { /* -f */ > buf = xmalloc_realpath_coreutils(fname); > } else { > buf = xmalloc_readlink_or_warn(fname); > @@ -93,7 +88,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) > > if (!buf) > return EXIT_FAILURE; > - printf((opt & 2) ? "%s" : "%s\n", buf); > + printf((opt & 1) ? "%s" : "%s\n", buf); > free(buf); > > fflush_stdout_and_exit_SUCCESS(); > -- > 2.39.2 > > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox > -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org From vda.linux at googlemail.com Mon Apr 10 14:31:22 2023 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Mon, 10 Apr 2023 16:31:22 +0200 Subject: sleep as an ash builtin In-Reply-To: <642b381e.RGMiXYMi3rqdOrsZ%rmy@pobox.com> References: <642b381e.RGMiXYMi3rqdOrsZ%rmy@pobox.com> Message-ID: Thank you for the report. Fixed. Please try current git. On Mon, Apr 3, 2023 at 10:34?PM Ron Yorston wrote: > > Another thing about sleep as an ash builtin: > > $ trap 'echo yo' INT > $ echo $EPOCHSECONDS; sleep 10; echo $EPOCHSECONDS > 1680553805 > ^C^C^C^C^Cyo > 1680553815 > $ > > No matter how urgently I press Ctrl-C the sleep runs its full course. > > Ron > > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox From vda.linux at googlemail.com Mon Apr 10 15:00:42 2023 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Mon, 10 Apr 2023 17:00:42 +0200 Subject: [PATCH] appletlib: fix "warning: unused variable applet_no" In-Reply-To: <3pR.ZYjX.2kbabLEuvV2.1aCdJh@seznam.cz> References: <3pR.ZYjX.2kbabLEuvV2.1aCdJh@seznam.cz> Message-ID: Applied, thank you. On Sun, Apr 9, 2023 at 10:19?AM Tomas Paukrt wrote: > > From 0d02a593c1ddeb7c4bb49b26524498a388ce0a0f Mon Sep 17 00:00:00 2001 > From: Tomas Paukrt > Date: Sun, 9 Apr 2023 08:57:46 +0200 > Subject: [PATCH] appletlib: fix "warning: unused variable applet_no" > > Signed-off-by: Tomas Paukrt > --- > libbb/appletlib.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/libbb/appletlib.c b/libbb/appletlib.c > index d5335d3..d9cc484 100644 > --- a/libbb/appletlib.c > +++ b/libbb/appletlib.c > @@ -918,7 +918,7 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) > # endif > > # if NUM_APPLETS > 0 > -void FAST_FUNC show_usage_if_dash_dash_help(int applet_no, char **argv) > +void FAST_FUNC show_usage_if_dash_dash_help(int applet_no UNUSED_PARAM, char **argv) > { > /* Special case. POSIX says "test --help" > * should be no different from e.g. "test --foo". > -- > 2.7.4 > > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox From vda.linux at googlemail.com Mon Apr 10 15:27:45 2023 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Mon, 10 Apr 2023 17:27:45 +0200 Subject: [PATCH] miscutil: provide getrandom() userland implementation if needed In-Reply-To: <20230224225142.2555427-1-mmayer@broadcom.com> References: <20230224225142.2555427-1-mmayer@broadcom.com> Message-ID: I put the fix in seedrng.c Let's avoid adding two source files just for this. On Fri, Feb 24, 2023 at 11:52?PM Markus Mayer wrote: > > Glibc 2.24 and older do not provide an interface for the getrandom() > system call. Linux kernels have been implementing this sytem call since > kernel 3.17. > > Let's address the situation where glibc <= 2.24 and Linux >= 3.17 by > providing the system call interface ourselves when needed. This allows > users to take advantage of getrandom() as long as the kernel supports > it, even if glibc doesn't provide access to it. > > Signed-off-by: Markus Mayer > --- > miscutils/getrandom.c | 22 ++++++++++++++++++++++ > miscutils/random.h | 19 +++++++++++++++++++ > miscutils/seedrng.c | 6 +++++- > 3 files changed, 46 insertions(+), 1 deletion(-) > create mode 100644 miscutils/getrandom.c > create mode 100644 miscutils/random.h > > diff --git a/miscutils/getrandom.c b/miscutils/getrandom.c > new file mode 100644 > index 000000000000..ab6a57f8042e > --- /dev/null > +++ b/miscutils/getrandom.c > @@ -0,0 +1,22 @@ > +#include > + > +#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 24 > + > +#ifndef __NR_getrandom > +#include > +#endif > +#include > +#include "random.h" > + > +ssize_t getrandom(void *buffer, size_t length, unsigned int flags) > +{ > +#ifdef __NR_getrandom > + return syscall(__NR_getrandom, buffer, length, flags); > +#else > + /* For kernels that don't support getrandom() (< 3.17). */ > + errno = ENOSYS; > + return -1; > +#endif > +} > + > +#endif /* __GLIBC__ ... */ > diff --git a/miscutils/random.h b/miscutils/random.h > new file mode 100644 > index 000000000000..3131df5e8a5d > --- /dev/null > +++ b/miscutils/random.h > @@ -0,0 +1,19 @@ > +#ifndef _RANDOM_H > +#define _RANDOM_H 1 > + > +#include > +#include > + > +#ifndef GRND_NONBLOCK > +#define GRND_NONBLOCK 0x01 > +#endif > +#ifndef GRND_RANDOM > +#define GRND_RANDOM 0x02 > +#endif > +#ifndef GRND_INSECURE > +#define GRND_INSECURE 0x04 > +#endif > + > +ssize_t getrandom(void *buffer, size_t length, unsigned int flags); > + > +#endif /* _RANDOM_H */ > diff --git a/miscutils/seedrng.c b/miscutils/seedrng.c > index 967741dc72ea..8ce553e460b1 100644 > --- a/miscutils/seedrng.c > +++ b/miscutils/seedrng.c > @@ -29,7 +29,7 @@ > > //applet:IF_SEEDRNG(APPLET(seedrng, BB_DIR_USR_SBIN, BB_SUID_DROP)) > > -//kbuild:lib-$(CONFIG_SEEDRNG) += seedrng.o > +//kbuild:lib-$(CONFIG_SEEDRNG) += getrandom.o seedrng.o > > //usage:#define seedrng_trivial_usage > //usage: "[-d DIR] [-n]" > @@ -42,7 +42,11 @@ > #include "libbb.h" > > #include > +#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 24 > +#include "random.h" > +#else > #include > +#endif > #include > > #ifndef GRND_INSECURE > -- > 2.34.1 > > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox From rmy at pobox.com Mon Apr 10 16:11:52 2023 From: rmy at pobox.com (Ron Yorston) Date: Mon, 10 Apr 2023 17:11:52 +0100 Subject: sleep as an ash builtin In-Reply-To: References: <642b381e.RGMiXYMi3rqdOrsZ%rmy@pobox.com> Message-ID: <64343548.sGKZRYA86Phkmn79%rmy@pobox.com> Denys Vlasenko wrote: >Fixed. Please try current git. Thanks, Denys. Works now. But... /* Without this, bare "sleep" in ash shows _ash_ --help */ if (ENABLE_ASH_SLEEP && applet_name[0] != 's') { bb_simple_error_msg("sleep: missing operand"); return EXIT_FAILURE; } 'ash' can be configured to run as 'sh'. Which begins with 's'. Ron From Keith.S.Thompson at gmail.com Mon Apr 10 16:33:54 2023 From: Keith.S.Thompson at gmail.com (Keith Thompson) Date: Mon, 10 Apr 2023 09:33:54 -0700 Subject: busybox seq doesn't handle negative numbers In-Reply-To: References: Message-ID: On Mon, Apr 10, 2023 at 5:35?AM Denys Vlasenko wrote: > > On Tue, Apr 4, 2023 at 7:16?AM Keith Thompson > wrote: > > The GNU coreutils seq command recognizes and handles negative > > arguments. > > > > The busybox seq command does not. Any argument starting with a '-' > > character is assumed to be an option name. > > > Fixed, please try current git. I just tried it (commit 200a9669f), and there's still a bug. If you use "-s" with an argument *and* a negative number, it prints a usage message. As a workaround, you can use, for example, "-s:" as a single argument. ``` $ busybox seq -1 1 -1 0 1 $ busybox seq -w -1 1 -1 00 01 $ busybox seq -s: -1 1 -1:0:1 $ busybox seq -s : -1 1 seq: invalid option -- '1' BusyBox v1.37.0.git (2023-04-10 09:16:21 PDT) multi-call binary. Usage: seq [-w] [-s SEP] [FIRST [INC]] LAST Print numbers from FIRST to LAST, in steps of INC. FIRST, INC default to 1. -w Pad with leading zeros -s SEP String separator $ busybox seq -s : 0 1 0:1 ``` From thomas at devoogdt.com Mon Apr 10 17:58:15 2023 From: thomas at devoogdt.com (Thomas Devoogdt) Date: Mon, 10 Apr 2023 19:58:15 +0200 Subject: [PATCH] seedrng: fix for glibc <= 2.24 not providing random header In-Reply-To: References: Message-ID: <20230410175815.795159-1-thomas.devoogdt@barco.com> From: Thomas Devoogdt - dropped the wrong define (not sure why it was there) - not available if glibc <= 2.24 - GRND_NONBLOCK not defined if not included - ret < 0 && errno == ENOSYS has to be true to get creditable set Signed-off-by: Thomas Devoogdt --- miscutils/seedrng.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/miscutils/seedrng.c b/miscutils/seedrng.c index 7cc855141..3bf6e2ea7 100644 --- a/miscutils/seedrng.c +++ b/miscutils/seedrng.c @@ -42,25 +42,31 @@ #include "libbb.h" #include -#include #include /* Fix up glibc <= 2.24 not having getrandom() */ #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 24 #include -# define getrandom(...) bb_getrandom(__VA_ARGS__) static ssize_t getrandom(void *buffer, size_t length, unsigned flags) { # if defined(__NR_getrandom) return syscall(__NR_getrandom, buffer, length, flags); # else - return ENOSYS; + errno = ENOSYS; + return -1; # endif } +#else +#include +#endif + +/* Apparently some headers don't ship with this yet. */ +#ifndef GRND_NONBLOCK +#define GRND_NONBLOCK 0x0001 #endif #ifndef GRND_INSECURE -#define GRND_INSECURE 0x0004 /* Apparently some headers don't ship with this yet. */ +#define GRND_INSECURE 0x0004 #endif #define DEFAULT_SEED_DIR "/var/lib/seedrng" -- 2.40.0 From dzfkct.busyboxml at pacien.net Mon Apr 10 21:41:57 2023 From: dzfkct.busyboxml at pacien.net (dzfkct.busyboxml at pacien.net) Date: Mon, 10 Apr 2023 23:41:57 +0200 Subject: [PATCH] udhcpc(6): add -K option to set SKB priority Message-ID: <20230410214157.1017054-1-dzfkct.busyboxml@pacien.net> From: pacien This adds a command line option (-K) to set the SKB priority on outgoing packets. The option is part of "FEATURE_UDHCPC_SKB_PRIO". This makes it straightforward to set some VLAN priority for DHCP requests through an egress QoS map. Packet matching for firewall or scheduler marking is otherwise broken due to the use of raw packets. (Such priority tag is a hard requirement for some ISPs, such as Orange in France). Signed-off-by: Pacien TRAN-GIRARD --- networking/udhcp/Config.src | 10 ++++++++++ networking/udhcp/common.h | 6 ++++-- networking/udhcp/d6_common.h | 2 ++ networking/udhcp/d6_dhcpc.c | 26 +++++++++++++++++++------- networking/udhcp/d6_packet.c | 21 +++++++++++++++++++-- networking/udhcp/dhcpc.c | 29 ++++++++++++++++++++--------- networking/udhcp/dhcpc.h | 1 + networking/udhcp/dhcpd.c | 6 ++++-- networking/udhcp/packet.c | 21 +++++++++++++++++++-- 9 files changed, 98 insertions(+), 24 deletions(-) diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 7ba7f48fc..6d8a9876a 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -176,3 +176,13 @@ config FEATURE_UDHCP_8021Q help If selected, both client and server will support passing of VLAN ID and priority via options 132 and 133 as per 802.1Q. + +config FEATURE_UDHCPC_SKB_PRIO + bool "Enable '-K' option for udhcpc" + default y + depends on UDHCPC || UDHCPC6 + help + If selected, enables -K option to set the SKB priority of DHCP + packets. Useful together with some egress QoS mapping to send + requests with a specific VLAN priority tag, as required by some + ISPs. diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 49a0b593d..4cd7581e3 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -359,12 +359,14 @@ int udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) FAST_FUNC; int udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, uint32_t dest_nip, int dest_port, const uint8_t *dest_arp, - int ifindex) FAST_FUNC; + int ifindex + IF_FEATURE_UDHCPC_SKB_PRIO(, int skb_prio)) FAST_FUNC; int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, uint32_t dest_nip, int dest_port, - const char *ifname) FAST_FUNC; + const char *ifname + IF_FEATURE_UDHCPC_SKB_PRIO(, int skb_prio)) FAST_FUNC; void udhcp_sp_setup(void) FAST_FUNC; void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h index 3cbfbb89e..a8f22bef2 100644 --- a/networking/udhcp/d6_common.h +++ b/networking/udhcp/d6_common.h @@ -180,12 +180,14 @@ int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp + IF_FEATURE_UDHCPC_SKB_PRIO(, int skb_prio) ); int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, struct in6_addr *dst_ipv6, int dest_port + IF_FEATURE_UDHCPC_SKB_PRIO(, int skb_prio) ); #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index cdd06188e..2b192c2cb 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -127,6 +127,7 @@ static const char udhcpc6_longopts[] ALIGN1 = USE_FOR_MMU( "background\0" No_argument "b" ) + IF_FEATURE_UDHCPC_SKB_PRIO("skb-priority\0" Required_argument "K") /// IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a") IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") ; @@ -152,12 +153,14 @@ enum { OPT_d = 1 << 16, /* The rest has variable bit positions, need to be clever */ OPTBIT_d = 16, - USE_FOR_MMU( OPTBIT_b,) - ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) - IF_FEATURE_UDHCP_PORT( OPTBIT_P,) - USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) - ///IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,) - IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) + USE_FOR_MMU( OPTBIT_b,) + IF_FEATURE_UDHCPC_SKB_PRIO(OPTBIT_K,) + ///IF_FEATURE_UDHCPC_ARPING( OPTBIT_a,) + IF_FEATURE_UDHCP_PORT( OPTBIT_P,) + USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) + IF_FEATURE_UDHCPC_SKB_PRIO(OPT_K = 1 << OPTBIT_K,) + ///IF_FEATURE_UDHCPC_ARPING( OPT_a = 1 << OPTBIT_a,) + IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) }; #if ENABLE_FEATURE_UDHCPC6_RFC4704 @@ -561,6 +564,7 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t * packet, (end - (uint8_t*) packet), /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR + IF_FEATURE_UDHCPC_SKB_PRIO(, client_data.skb_prio) ); } @@ -866,6 +870,7 @@ static NOINLINE int send_d6_renew(struct in6_addr *server_ipv6, struct in6_addr &packet, (opt_ptr - (uint8_t*) &packet), our_cur_ipv6, CLIENT_PORT6, server_ipv6, SERVER_PORT6 + IF_FEATURE_UDHCPC_SKB_PRIO(, client_data.skb_prio) ); return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); } @@ -899,6 +904,7 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) &packet, (opt_ptr - (uint8_t*) &packet), our_cur_ipv6, CLIENT_PORT6, server_ipv6, SERVER_PORT6 + IF_FEATURE_UDHCPC_SKB_PRIO(, client_data.skb_prio) ); } @@ -1129,7 +1135,7 @@ static void client_background(void) //usage:# define IF_UDHCP_VERBOSE(...) //usage:#endif //usage:#define udhcpc6_trivial_usage -//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"R] [-t N] [-T SEC] [-A SEC|-n] [-i IFACE] [-s PROG]\n" +//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"R]"IF_FEATURE_UDHCPC_SKB_PRIO(" [-K PRIO]")" [-t N] [-T SEC] [-A SEC|-n] [-i IFACE] [-s PROG]\n" //usage: " [-p PIDFILE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-ldo] [-r IPv6] [-x OPT:VAL]... [-O OPT]..." //usage:#define udhcpc6_full_usage "\n" //usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")" @@ -1150,6 +1156,9 @@ static void client_background(void) //usage: IF_FEATURE_UDHCP_PORT( //usage: "\n -P PORT Use PORT (default 546)" //usage: ) +//usage: IF_FEATURE_UDHCPC_SKB_PRIO( +//usage: "\n -K PRIO Set packets SKB priority (default 0) [0-63]" +//usage: ) ////usage: IF_FEATURE_UDHCPC_ARPING( ////usage: "\n -a Use arping to validate offered address" ////usage: ) @@ -1199,6 +1208,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) /* Default options */ IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;) + IF_FEATURE_UDHCPC_SKB_PRIO(client_data.skb_prio = 0;) client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; client_data.script = CONFIG_UDHCPC6_DEFAULT_SCRIPT; client_data.sockfd = -1; @@ -1212,6 +1222,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) /* O,x: list; -T,-t,-A take numeric param */ "i:np:qRr:s:T:+t:+SA:+O:*ox:*fld" USE_FOR_MMU("b") + IF_FEATURE_UDHCPC_SKB_PRIO("K:+") ///IF_FEATURE_UDHCPC_ARPING("a") IF_FEATURE_UDHCP_PORT("P:") "v" @@ -1222,6 +1233,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ , &list_O , &list_x + IF_FEATURE_UDHCPC_SKB_PRIO(, &client_data.skb_prio) IF_FEATURE_UDHCP_PORT(, &str_P) IF_UDHCP_VERBOSE(, &dhcp_verbose) ); diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c index 142de9b43..0dc62f1ee 100644 --- a/networking/udhcp/d6_packet.c +++ b/networking/udhcp/d6_packet.c @@ -54,7 +54,8 @@ int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 UNUSED_PARAM, int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, - struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp) + struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp + IF_FEATURE_UDHCPC_SKB_PRIO(, int skb_prio)) { struct sockaddr_ll dest_sll; struct ip6_udp_d6_packet packet; @@ -68,6 +69,13 @@ int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( goto ret_msg; } +#if ENABLE_FEATURE_UDHCPC_SKB_PRIO + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, skb_prio) < 0) { + msg = "setsockopt(%s)"; + goto ret_close; + } +#endif + memset(&dest_sll, 0, sizeof(dest_sll)); memset(&packet, 0, offsetof(struct ip6_udp_d6_packet, data)); packet.data = *d6_pkt; /* struct copy */ @@ -139,7 +147,8 @@ int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, - struct in6_addr *dst_ipv6, int dest_port) + struct in6_addr *dst_ipv6, int dest_port + IF_FEATURE_UDHCPC_SKB_PRIO(, int skb_prio)) { struct sockaddr_in6 sa; int fd; @@ -151,6 +160,14 @@ int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( msg = "socket(%s)"; goto ret_msg; } + +#if ENABLE_FEATURE_UDHCPC_SKB_PRIO + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, skb_prio) < 0) { + msg = "setsockopt(%s)"; + goto ret_close; + } +#endif + setsockopt_reuseaddr(fd); memset(&sa, 0, sizeof(sa)); diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index c757fb37c..85db8d6fa 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -75,6 +75,7 @@ static const char udhcpc_longopts[] ALIGN1 = "background\0" No_argument "b" ) "broadcast\0" No_argument "B" + IF_FEATURE_UDHCPC_SKB_PRIO("skb-priority\0" Required_argument "K") IF_FEATURE_UDHCPC_ARPING("arping\0" Optional_argument "a") IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") ; @@ -102,12 +103,14 @@ enum { OPT_B = 1 << 18, /* The rest has variable bit positions, need to be clever */ OPTBIT_B = 18, - USE_FOR_MMU( OPTBIT_b,) - IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) - IF_FEATURE_UDHCP_PORT( OPTBIT_P,) - USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) - IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,) - IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) + USE_FOR_MMU( OPTBIT_b,) + IF_FEATURE_UDHCPC_SKB_PRIO(OPTBIT_K,) + IF_FEATURE_UDHCPC_ARPING( OPTBIT_a,) + IF_FEATURE_UDHCP_PORT( OPTBIT_P,) + USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) + IF_FEATURE_UDHCPC_SKB_PRIO(OPT_K = 1 << OPTBIT_K,) + IF_FEATURE_UDHCPC_ARPING( OPT_a = 1 << OPTBIT_a,) + IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) }; @@ -704,7 +707,8 @@ static int raw_bcast_from_client_data_ifindex(struct dhcp_packet *packet, uint32 return udhcp_send_raw_packet(packet, /*src*/ src_nip, CLIENT_PORT, /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, - client_data.ifindex); + client_data.ifindex + IF_FEATURE_UDHCPC_SKB_PRIO(, client_data.skb_prio)); } static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) @@ -713,7 +717,8 @@ static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t return udhcp_send_kernel_packet(packet, ciaddr, CLIENT_PORT, server, SERVER_PORT, - client_data.interface); + client_data.interface + IF_FEATURE_UDHCPC_SKB_PRIO(, client_data.skb_prio)); return raw_bcast_from_client_data_ifindex(packet, ciaddr); } @@ -1161,7 +1166,7 @@ static void client_background(void) //usage:# define IF_UDHCP_VERBOSE(...) //usage:#endif //usage:#define udhcpc_trivial_usage -//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC|-n]\n" +//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_SKB_PRIO(" [-K PRIO]")IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC|-n]\n" //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." //usage:#define udhcpc_full_usage "\n" @@ -1183,6 +1188,9 @@ static void client_background(void) //usage: "\n -R Release IP on exit" //usage: "\n -f Run in foreground" //usage: "\n -S Log to syslog too" +//usage: IF_FEATURE_UDHCPC_SKB_PRIO( +//usage: "\n -K PRIO Set packets SKB priority (default 0) [0-63]" +//usage: ) //usage: IF_FEATURE_UDHCPC_ARPING( //usage: "\n -a[MSEC] Validate offered address with ARP ping" //usage: ) @@ -1232,6 +1240,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) /* Default options */ IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) + IF_FEATURE_UDHCPC_SKB_PRIO(client_data.skb_prio = 0;) client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; client_data.sockfd = -1; @@ -1246,6 +1255,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) /* O,x: list; -T,-t,-A take numeric param */ "CV:F:i:np:qRr:s:T:+t:+SA:+O:*ox:*fB" USE_FOR_MMU("b") + IF_FEATURE_UDHCPC_SKB_PRIO("K:+") IF_FEATURE_UDHCPC_ARPING("a::") IF_FEATURE_UDHCP_PORT("P:") "v" @@ -1258,6 +1268,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ , &list_O , &list_x + IF_FEATURE_UDHCPC_SKB_PRIO(, &client_data.skb_prio) IF_FEATURE_UDHCPC_ARPING(, &str_a) IF_FEATURE_UDHCP_PORT(, &str_P) IF_UDHCP_VERBOSE(, &dhcp_verbose) diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h index 19b054b32..9cb050e91 100644 --- a/networking/udhcp/dhcpc.h +++ b/networking/udhcp/dhcpc.h @@ -9,6 +9,7 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN struct client_data_t { uint8_t client_mac[6]; /* Our mac address */ + IF_FEATURE_UDHCPC_SKB_PRIO(int skb_prio;) IF_FEATURE_UDHCP_PORT(uint16_t port;) int ifindex; /* Index number of the interface to use */ uint32_t xid; diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 66750e2e6..c149be194 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -603,7 +603,8 @@ static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadc udhcp_send_raw_packet(dhcp_pkt, /*src*/ server_data.server_nip, SERVER_PORT, /*dst*/ ciaddr, CLIENT_PORT, chaddr, - server_data.ifindex); + server_data.ifindex + IF_FEATURE_UDHCPC_SKB_PRIO(, 0)); } /* Send a packet to gateway_nip using the kernel ip stack */ @@ -618,7 +619,8 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) * even those which are clients' requests and would normally * (i.e. without relay) use CLIENT_PORT. See RFC 1542. */ - server_data.interface); + server_data.interface + IF_FEATURE_UDHCPC_SKB_PRIO(, 0)); } static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 529978189..049618422 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c @@ -106,7 +106,8 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, uint32_t dest_nip, int dest_port, const uint8_t *dest_arp, - int ifindex) + int ifindex + IF_FEATURE_UDHCPC_SKB_PRIO(, int skb_prio)) { struct sockaddr_ll dest_sll; struct ip_udp_dhcp_packet packet; @@ -121,6 +122,13 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, goto ret_msg; } +#if ENABLE_FEATURE_UDHCPC_SKB_PRIO + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, skb_prio) < 0) { + msg = "setsockopt(%s)"; + goto ret_close; + } +#endif + memset(&dest_sll, 0, sizeof(dest_sll)); memset(&packet, 0, offsetof(struct ip_udp_dhcp_packet, data)); packet.data = *dhcp_pkt; /* struct copy */ @@ -192,7 +200,8 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, uint32_t dest_nip, int dest_port, - const char *ifname) + const char *ifname + IF_FEATURE_UDHCPC_SKB_PRIO(, int skb_prio)) { struct sockaddr_in sa; unsigned padding; @@ -205,6 +214,14 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, msg = "socket(%s)"; goto ret_msg; } + +#if ENABLE_FEATURE_UDHCPC_SKB_PRIO + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, skb_prio) < 0) { + msg = "setsockopt(%s)"; + goto ret_close; + } +#endif + setsockopt_reuseaddr(fd); /* If interface carrier goes down, unless we -- 2.38.4 From dzfkct.busyboxml at pacien.net Mon Apr 10 22:54:10 2023 From: dzfkct.busyboxml at pacien.net (pacien) Date: Tue, 11 Apr 2023 00:54:10 +0200 Subject: [PATCH v2] udhcp: add option to set CoS priority In-Reply-To: <20230116101114.52097-1-peron.clem@gmail.com> Message-ID: <168116725009.1013566.3224554891847847588@mail.pacien.net> I worked on my own version of this, before seeing that this one was already posted to the list. Sorry for the collision. Message-Id: <20230410214157.1017054-1-dzfkct.busyboxml at pacien.net> It differs mainly in the terminology: it talks about the SKB priority instead of the CoS. Though it should perhaps be the "socket priority" instead? The VLAN CoS mapping isn't automatic. It also differs a bit in the way errors are handled, and puts the priority in the client_data struct with the rest of the settings. : > I'm still testing this patch and I'm unsure if we need to set the > priority for all the sockets. > [...] > udhcp_send_raw_packet() set the priority and not > udhcp_send_kernel_packet(). It seems that the former is used for multicast, the latter for unicast, used in particular for renew and release. So things should probably be kept consistent here. : > > > +//usage: "\n -y PRIORITY CoS value 0 .. 7, default 0" > > I don't see that you would cap the value to 7 anywhere, do you? > The manpage seems to imply that 0..6 can be used by unprivileged users, > higher values require CAP_NET_ADMIN which is fine per se; I assume the > kernel does enough sanity-checking so we can attempt to pass whatever > the user said. I believe 0 to 7 would correspond to VLAN CoS (PCP)? Though that should not be limited here for the socket priority. -- Pacien TRAN-GIRARD From vda.linux at googlemail.com Tue Apr 11 18:31:46 2023 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Tue, 11 Apr 2023 20:31:46 +0200 Subject: busybox seq doesn't handle negative numbers In-Reply-To: References: Message-ID: On Mon, Apr 10, 2023 at 6:34?PM Keith Thompson wrote: > On Mon, Apr 10, 2023 at 5:35?AM Denys Vlasenko wrote: > > On Tue, Apr 4, 2023 at 7:16?AM Keith Thompson > > wrote: > > > The GNU coreutils seq command recognizes and handles negative > > > arguments. > > > > > > The busybox seq command does not. Any argument starting with a '-' > > > character is assumed to be an option name. > > > > > > Fixed, please try current git. > > I just tried it (commit 200a9669f), and there's still a bug. > > If you use "-s" with an argument *and* a negative number, it prints a > usage message. > $ busybox seq -s : -1 1 > seq: invalid option -- '1' Fixed this too, please try current git. From Keith.S.Thompson at gmail.com Tue Apr 11 20:11:57 2023 From: Keith.S.Thompson at gmail.com (Keith Thompson) Date: Tue, 11 Apr 2023 13:11:57 -0700 Subject: busybox seq doesn't handle negative numbers In-Reply-To: References: Message-ID: On Tue, Apr 11, 2023 at 11:31?AM Denys Vlasenko wrote: > > On Mon, Apr 10, 2023 at 6:34?PM Keith Thompson > wrote: > > On Mon, Apr 10, 2023 at 5:35?AM Denys Vlasenko wrote: > > > On Tue, Apr 4, 2023 at 7:16?AM Keith Thompson > > > wrote: > > > > The GNU coreutils seq command recognizes and handles negative > > > > arguments. > > > > > > > > The busybox seq command does not. Any argument starting with a '-' > > > > character is assumed to be an option name. > > > > > > > > > Fixed, please try current git. > > > > I just tried it (commit 200a9669f), and there's still a bug. > > > > If you use "-s" with an argument *and* a negative number, it prints a > > usage message. > > $ busybox seq -s : -1 1 > > seq: invalid option -- '1' > > Fixed this too, please try current git. The current version (commit 478b5ac2b, 2023-04-11) correctly handles all the test cases from my previous email. I see from the comments that it can still break on "-s -1" (it hadn't even occurred to me that the separator can be more than one character), but that's probably not worth worrying about. Other separators starting with "-" do work, including "-s --". $ busybox seq -s - -1 1 -1-0-1 $ busybox seq -s -- -1 1 -1--0--1 $ seq -s -1 -1 1 seq: option requires an argument -- 's' [snip] I have some vague thoughts about ways to handle the arguments that correctly handle a few more corner cases, but I'm not going to worry about it too much. From peron.clem at gmail.com Tue Apr 11 20:58:00 2023 From: peron.clem at gmail.com (=?UTF-8?B?Q2zDqW1lbnQgUMOpcm9u?=) Date: Tue, 11 Apr 2023 22:58:00 +0200 Subject: [PATCH v2] udhcp: add option to set CoS priority In-Reply-To: <168116725009.1013566.3224554891847847588@mail.pacien.net> References: <20230116101114.52097-1-peron.clem@gmail.com> <168116725009.1013566.3224554891847847588@mail.pacien.net> Message-ID: Hi Pacien, On Tue, 11 Apr 2023 at 00:54, pacien wrote: > > I worked on my own version of this, before seeing that this one was > already posted to the list. Sorry for the collision. > > Message-Id: <20230410214157.1017054-1-dzfkct.busyboxml at pacien.net> > > It differs mainly in the terminology: it talks about the SKB priority > instead of the CoS. Though it should perhaps be the "socket priority" > instead? The VLAN CoS mapping isn't automatic. > > It also differs a bit in the way errors are handled, and puts the > priority in the client_data struct with the rest of the settings. > > : > > I'm still testing this patch and I'm unsure if we need to set the > > priority for all the sockets. > > [...] > > udhcp_send_raw_packet() set the priority and not > > udhcp_send_kernel_packet(). > > It seems that the former is used for multicast, the latter for unicast, > used in particular for renew and release. So things should probably be > kept consistent here. > > : > > > > +//usage: "\n -y PRIORITY CoS value 0 .. 7, default 0" > > > > I don't see that you would cap the value to 7 anywhere, do you? > > The manpage seems to imply that 0..6 can be used by unprivileged users, > > higher values require CAP_NET_ADMIN which is fine per se; I assume the > > kernel does enough sanity-checking so we can attempt to pass whatever > > the user said. > > I believe 0 to 7 would correspond to VLAN CoS (PCP)? > Though that should not be limited here for the socket priority. I agree with you for both. We should avoid using CoS terminology and not limit the value. I didn't get any response from maintainers and I'm not sure they are interested in this feature so I will not work on it. If you want to update and rework this, feel free to send a v3 on top of this series, but I doubt it will be merged... Thanks, Clement > > -- > Pacien TRAN-GIRARD From vda.linux at googlemail.com Wed Apr 12 10:24:30 2023 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Wed, 12 Apr 2023 12:24:30 +0200 Subject: sleep as an ash builtin In-Reply-To: <64343548.sGKZRYA86Phkmn79%rmy@pobox.com> References: <642b381e.RGMiXYMi3rqdOrsZ%rmy@pobox.com> <64343548.sGKZRYA86Phkmn79%rmy@pobox.com> Message-ID: Indeed. Fixed. On Mon, Apr 10, 2023 at 6:11?PM Ron Yorston wrote: > > Denys Vlasenko wrote: > >Fixed. Please try current git. > > Thanks, Denys. Works now. > > But... > > /* Without this, bare "sleep" in ash shows _ash_ --help */ > if (ENABLE_ASH_SLEEP && applet_name[0] != 's') { > bb_simple_error_msg("sleep: missing operand"); > return EXIT_FAILURE; > } > > 'ash' can be configured to run as 'sh'. Which begins with 's'. > > Ron From vda.linux at googlemail.com Wed Apr 12 11:45:21 2023 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Wed, 12 Apr 2023 13:45:21 +0200 Subject: [PATCH] lineedit: fix crash when icanon set with -echo In-Reply-To: <20230403205206.2902-1-akos.somfai@gmail.com> References: <20230403205206.2902-1-akos.somfai@gmail.com> Message-ID: Applied, thank you. On Mon, Apr 3, 2023 at 10:53?PM Akos Somfai wrote: > > When icanon is set with -echo (e.g. ssh from an emacs shell) then > S.state will remain null but later it will be deferenced causing ash to > crash. Fix: additional check on state. > --- > libbb/lineedit.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/libbb/lineedit.c b/libbb/lineedit.c > index 625884adf..bdae10914 100644 > --- a/libbb/lineedit.c > +++ b/libbb/lineedit.c > @@ -254,7 +254,7 @@ static NOINLINE const char *get_homedir_or_NULL(void) > const char *home; > > # if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH > - home = state->sh_get_var ? state->sh_get_var("HOME") : getenv("HOME"); > + home = state && state->sh_get_var ? state->sh_get_var("HOME") : getenv("HOME"); > # else > home = getenv("HOME"); > # endif > @@ -2038,7 +2038,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) > if (!cwd_buf) { > const char *home; > # if EDITING_HAS_sh_get_var > - cwd_buf = state->sh_get_var > + cwd_buf = state && state->sh_get_var > ? xstrdup(state->sh_get_var("PWD")) > : xrealloc_getcwd_or_warn(NULL); > # else > -- > 2.40.0 > > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox From rep.dot.nop at gmail.com Wed Apr 12 18:33:05 2023 From: rep.dot.nop at gmail.com (Bernhard Reutner-Fischer) Date: Wed, 12 Apr 2023 20:33:05 +0200 Subject: [PATCH] build system: clean more files on make clean In-Reply-To: <3pS.ZYjZ.5JrccbtTndk.1aCdKH@seznam.cz> References: <3pS.ZYjZ.5JrccbtTndk.1aCdKH@seznam.cz> Message-ID: <20230412203305.1d2f0c60@nbbrfq> Hi Tomas! Applied, thanks! On Sun, 09 Apr 2023 10:19:29 +0200 (CEST) "Tomas Paukrt" wrote: > From 57bf559403d89133197d33a2a181815d1f057b2b Mon Sep 17 00:00:00 2001 > From: Tomas Paukrt > Date: Sun, 9 Apr 2023 09:06:43 +0200 > Subject: [PATCH] build system: clean more files on make clean > > Signed-off-by: Tomas Paukrt > --- > Makefile | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/Makefile b/Makefile > index 7b4686f..4dcd592 100644 > --- a/Makefile > +++ b/Makefile > @@ -966,7 +966,7 @@ endif # CONFIG_MODULES > > # Directories & files removed with 'make clean' > CLEAN_DIRS += $(MODVERDIR) _install 0_lib > -CLEAN_FILES += busybox busybox_unstripped* busybox.links \ > +CLEAN_FILES += busybox busybox_unstripped* busybox.links busybox*.suid busybox*.nosuid \ > System.map .kernelrelease \ > .tmp_kallsyms* .tmp_version .tmp_busybox* .tmp_System.map > From rep.dot.nop at gmail.com Wed Apr 12 18:51:16 2023 From: rep.dot.nop at gmail.com (Bernhard Reutner-Fischer) Date: Wed, 12 Apr 2023 20:51:16 +0200 Subject: [PATCH v2] udhcp: add option to set CoS priority In-Reply-To: References: <20230116101114.52097-1-peron.clem@gmail.com> <168116725009.1013566.3224554891847847588@mail.pacien.net> Message-ID: <20230412205116.2148357e@nbbrfq> On Tue, 11 Apr 2023 22:58:00 +0200 Cl?ment P?ron wrote: > Hi Pacien, > > On Tue, 11 Apr 2023 at 00:54, pacien wrote: > > > > I worked on my own version of this, before seeing that this one was > > already posted to the list. Sorry for the collision. > > > > Message-Id: <20230410214157.1017054-1-dzfkct.busyboxml at pacien.net> > > > > It differs mainly in the terminology: it talks about the SKB priority > > instead of the CoS. Though it should perhaps be the "socket priority" > > instead? The VLAN CoS mapping isn't automatic. > > > > It also differs a bit in the way errors are handled, and puts the > > priority in the client_data struct with the rest of the settings. > > > > : > > > I'm still testing this patch and I'm unsure if we need to set the > > > priority for all the sockets. > > > [...] > > > udhcp_send_raw_packet() set the priority and not > > > udhcp_send_kernel_packet(). > > > > It seems that the former is used for multicast, the latter for unicast, > > used in particular for renew and release. So things should probably be > > kept consistent here. > > > > : > > > > > +//usage: "\n -y PRIORITY CoS value 0 .. 7, default 0" > > > > > > I don't see that you would cap the value to 7 anywhere, do you? > > > The manpage seems to imply that 0..6 can be used by unprivileged users, > > > higher values require CAP_NET_ADMIN which is fine per se; I assume the > > > kernel does enough sanity-checking so we can attempt to pass whatever > > > the user said. > > > > I believe 0 to 7 would correspond to VLAN CoS (PCP)? > > Though that should not be limited here for the socket priority. > > I agree with you for both. We should avoid using CoS terminology and > not limit the value. > > I didn't get any response from maintainers and I'm not sure they are > interested in this feature so I will not work on it. Well, at least i did reply, so "didn't get any response from maintainers" is not really fair, isn't it. Denys devotes alot of spare time and yes, sometimes patches fall throught the cracks, which is unfortunate. The usual thing to do is to ping once in a while. That said, anybody is free to comment on patches sent to the list, improve them, or question their validity or usefulness. That's what this list is for :) > > If you want to update and rework this, feel free to send a v3 on top > of this series, but I doubt it will be merged... I can see that it has it's use, so if anybody is willing to apply some tiny bit more TLC then i believe there is no big problem accepting it, maybe under a knob if really needed. Would be nice if you would include bloat-o-meter stats. See 'make baseline; apply the patch; make bloatcheck' and include the output in the commit message so folks are aware of the costs of that functionality, please. If it's not too excessive, we may not need a config knob, or we may, if it's not considered generally useful. cheers, From dzfkct.busyboxml at pacien.net Wed Apr 12 19:20:16 2023 From: dzfkct.busyboxml at pacien.net (Pacien TRAN-GIRARD) Date: Wed, 12 Apr 2023 21:20:16 +0200 Subject: [PATCH v2] udhcp: add option to set CoS priority In-Reply-To: <20230412205116.2148357e@nbbrfq> References: <20230116101114.52097-1-peron.clem@gmail.com> <168116725009.1013566.3224554891847847588@mail.pacien.net> <20230412205116.2148357e@nbbrfq> Message-ID: <168132721608.1393047.3139574052520067878@mail.pacien.net> Quoting Bernhard Reutner-Fischer (2023-04-12 20:51:16) > bloat-o-meter stats. > See 'make baseline; apply the patch; make bloatcheck' > and include the output in the commit message so folks are aware of the > costs of that functionality, please. If it's not too excessive, we may > not need a config knob, or we may, if it's not considered generally > useful. bloatcheck says 264 bytes (for a reworked version of the patch). Is there a threshold for whether or not to have a feature flag? (I couldn't find one in the FAQ). -- Pacien TRAN-GIRARD From dzfkct.busyboxml at pacien.net Thu Apr 13 10:48:14 2023 From: dzfkct.busyboxml at pacien.net (pacien) Date: Thu, 13 Apr 2023 12:48:14 +0200 Subject: [PATCH v3] udhcpc(6): add -K option to set kernel packet priority Message-ID: <20230413104812.1648285-1-dzfkct.busyboxml@pacien.net> From: pacien This adds a command line option (-K) to set the (kernel) packet priority. The option is part of "FEATURE_UDHCPC_SK_PRIO". This makes it straightforward to set some VLAN priority for DHCP requests through an egress QoS map. Packet matching for firewall or scheduler marking is otherwise broken due to the use of raw packets. (Such priority tag is a hard requirement for some ISPs, such as Orange in France). Enabling this feature costs 264 octets according to bloatcheck. Co-authored-by: Cl?ment P?ron Signed-off-by: Pacien TRAN-GIRARD --- Differences from Pacien's v1 and Cl?ment's v2: * made it clear that we're only talking about the kernel packet priority (CoS or SKB were ambiguous or unclear) Differences from Cl?ment's v2: * renamed the flag to -K to match the new terminology * moved sk_prio to client_data, passed as params instead of a global * used the same error handling as in the send_packet functions networking/udhcp/Config.src | 10 ++++++++++ networking/udhcp/common.h | 6 ++++-- networking/udhcp/d6_common.h | 2 ++ networking/udhcp/d6_dhcpc.c | 26 +++++++++++++++++++------- networking/udhcp/d6_packet.c | 21 +++++++++++++++++++-- networking/udhcp/dhcpc.c | 29 ++++++++++++++++++++--------- networking/udhcp/dhcpc.h | 1 + networking/udhcp/dhcpd.c | 6 ++++-- networking/udhcp/packet.c | 21 +++++++++++++++++++-- 9 files changed, 98 insertions(+), 24 deletions(-) diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 7ba7f48fc..731cf12fa 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -176,3 +176,13 @@ config FEATURE_UDHCP_8021Q help If selected, both client and server will support passing of VLAN ID and priority via options 132 and 133 as per 802.1Q. + +config FEATURE_UDHCPC_SK_PRIO + bool "Enable '-K' option for udhcpc" + default y + depends on UDHCPC || UDHCPC6 + help + If selected, enables -K option to set the kernel priority of DHCP + packets. Useful together with some egress QoS mapping to send + requests with a specific VLAN priority tag, as required by some + ISPs. diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 49a0b593d..30ee68375 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -359,12 +359,14 @@ int udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) FAST_FUNC; int udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, uint32_t dest_nip, int dest_port, const uint8_t *dest_arp, - int ifindex) FAST_FUNC; + int ifindex + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) FAST_FUNC; int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, uint32_t dest_nip, int dest_port, - const char *ifname) FAST_FUNC; + const char *ifname + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) FAST_FUNC; void udhcp_sp_setup(void) FAST_FUNC; void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h index 3cbfbb89e..05a5dc2b4 100644 --- a/networking/udhcp/d6_common.h +++ b/networking/udhcp/d6_common.h @@ -180,12 +180,14 @@ int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio) ); int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, struct in6_addr *dst_ipv6, int dest_port + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio) ); #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index cdd06188e..173aa2914 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -127,6 +127,7 @@ static const char udhcpc6_longopts[] ALIGN1 = USE_FOR_MMU( "background\0" No_argument "b" ) + IF_FEATURE_UDHCPC_SK_PRIO("sk-priority\0" Required_argument "K") /// IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a") IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") ; @@ -152,12 +153,14 @@ enum { OPT_d = 1 << 16, /* The rest has variable bit positions, need to be clever */ OPTBIT_d = 16, - USE_FOR_MMU( OPTBIT_b,) - ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) - IF_FEATURE_UDHCP_PORT( OPTBIT_P,) - USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) - ///IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,) - IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) + USE_FOR_MMU( OPTBIT_b,) + IF_FEATURE_UDHCPC_SK_PRIO(OPTBIT_K,) + ///IF_FEATURE_UDHCPC_ARPING( OPTBIT_a,) + IF_FEATURE_UDHCP_PORT( OPTBIT_P,) + USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) + IF_FEATURE_UDHCPC_SK_PRIO(OPT_K = 1 << OPTBIT_K,) + ///IF_FEATURE_UDHCPC_ARPING( OPT_a = 1 << OPTBIT_a,) + IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) }; #if ENABLE_FEATURE_UDHCPC6_RFC4704 @@ -561,6 +564,7 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t * packet, (end - (uint8_t*) packet), /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR + IF_FEATURE_UDHCPC_SK_PRIO(, client_data.sk_prio) ); } @@ -866,6 +870,7 @@ static NOINLINE int send_d6_renew(struct in6_addr *server_ipv6, struct in6_addr &packet, (opt_ptr - (uint8_t*) &packet), our_cur_ipv6, CLIENT_PORT6, server_ipv6, SERVER_PORT6 + IF_FEATURE_UDHCPC_SK_PRIO(, client_data.sk_prio) ); return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); } @@ -899,6 +904,7 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) &packet, (opt_ptr - (uint8_t*) &packet), our_cur_ipv6, CLIENT_PORT6, server_ipv6, SERVER_PORT6 + IF_FEATURE_UDHCPC_SK_PRIO(, client_data.sk_prio) ); } @@ -1129,7 +1135,7 @@ static void client_background(void) //usage:# define IF_UDHCP_VERBOSE(...) //usage:#endif //usage:#define udhcpc6_trivial_usage -//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"R] [-t N] [-T SEC] [-A SEC|-n] [-i IFACE] [-s PROG]\n" +//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"R]"IF_FEATURE_UDHCPC_SK_PRIO(" [-K PRIO]")" [-t N] [-T SEC] [-A SEC|-n] [-i IFACE] [-s PROG]\n" //usage: " [-p PIDFILE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-ldo] [-r IPv6] [-x OPT:VAL]... [-O OPT]..." //usage:#define udhcpc6_full_usage "\n" //usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")" @@ -1150,6 +1156,9 @@ static void client_background(void) //usage: IF_FEATURE_UDHCP_PORT( //usage: "\n -P PORT Use PORT (default 546)" //usage: ) +//usage: IF_FEATURE_UDHCPC_SK_PRIO( +//usage: "\n -K PRIO Set kernel packet priority (default 0)" +//usage: ) ////usage: IF_FEATURE_UDHCPC_ARPING( ////usage: "\n -a Use arping to validate offered address" ////usage: ) @@ -1199,6 +1208,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) /* Default options */ IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;) + IF_FEATURE_UDHCPC_SK_PRIO(client_data.sk_prio = 0;) client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; client_data.script = CONFIG_UDHCPC6_DEFAULT_SCRIPT; client_data.sockfd = -1; @@ -1212,6 +1222,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) /* O,x: list; -T,-t,-A take numeric param */ "i:np:qRr:s:T:+t:+SA:+O:*ox:*fld" USE_FOR_MMU("b") + IF_FEATURE_UDHCPC_SK_PRIO("K:+") ///IF_FEATURE_UDHCPC_ARPING("a") IF_FEATURE_UDHCP_PORT("P:") "v" @@ -1222,6 +1233,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ , &list_O , &list_x + IF_FEATURE_UDHCPC_SK_PRIO(, &client_data.sk_prio) IF_FEATURE_UDHCP_PORT(, &str_P) IF_UDHCP_VERBOSE(, &dhcp_verbose) ); diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c index 142de9b43..501497154 100644 --- a/networking/udhcp/d6_packet.c +++ b/networking/udhcp/d6_packet.c @@ -54,7 +54,8 @@ int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 UNUSED_PARAM, int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, - struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp) + struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) { struct sockaddr_ll dest_sll; struct ip6_udp_d6_packet packet; @@ -68,6 +69,13 @@ int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( goto ret_msg; } +#if ENABLE_FEATURE_UDHCPC_SK_PRIO + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, sk_prio) < 0) { + msg = "setsockopt(%s)"; + goto ret_close; + } +#endif + memset(&dest_sll, 0, sizeof(dest_sll)); memset(&packet, 0, offsetof(struct ip6_udp_d6_packet, data)); packet.data = *d6_pkt; /* struct copy */ @@ -139,7 +147,8 @@ int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, - struct in6_addr *dst_ipv6, int dest_port) + struct in6_addr *dst_ipv6, int dest_port + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) { struct sockaddr_in6 sa; int fd; @@ -151,6 +160,14 @@ int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( msg = "socket(%s)"; goto ret_msg; } + +#if ENABLE_FEATURE_UDHCPC_SK_PRIO + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, sk_prio) < 0) { + msg = "setsockopt(%s)"; + goto ret_close; + } +#endif + setsockopt_reuseaddr(fd); memset(&sa, 0, sizeof(sa)); diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index c757fb37c..8108f6856 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -75,6 +75,7 @@ static const char udhcpc_longopts[] ALIGN1 = "background\0" No_argument "b" ) "broadcast\0" No_argument "B" + IF_FEATURE_UDHCPC_SK_PRIO("sk-priority\0" Required_argument "K") IF_FEATURE_UDHCPC_ARPING("arping\0" Optional_argument "a") IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") ; @@ -102,12 +103,14 @@ enum { OPT_B = 1 << 18, /* The rest has variable bit positions, need to be clever */ OPTBIT_B = 18, - USE_FOR_MMU( OPTBIT_b,) - IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) - IF_FEATURE_UDHCP_PORT( OPTBIT_P,) - USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) - IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,) - IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) + USE_FOR_MMU( OPTBIT_b,) + IF_FEATURE_UDHCPC_SK_PRIO(OPTBIT_K,) + IF_FEATURE_UDHCPC_ARPING( OPTBIT_a,) + IF_FEATURE_UDHCP_PORT( OPTBIT_P,) + USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) + IF_FEATURE_UDHCPC_SK_PRIO(OPT_K = 1 << OPTBIT_K,) + IF_FEATURE_UDHCPC_ARPING( OPT_a = 1 << OPTBIT_a,) + IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) }; @@ -704,7 +707,8 @@ static int raw_bcast_from_client_data_ifindex(struct dhcp_packet *packet, uint32 return udhcp_send_raw_packet(packet, /*src*/ src_nip, CLIENT_PORT, /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, - client_data.ifindex); + client_data.ifindex + IF_FEATURE_UDHCPC_SK_PRIO(, client_data.sk_prio)); } static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) @@ -713,7 +717,8 @@ static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t return udhcp_send_kernel_packet(packet, ciaddr, CLIENT_PORT, server, SERVER_PORT, - client_data.interface); + client_data.interface + IF_FEATURE_UDHCPC_SK_PRIO(, client_data.sk_prio)); return raw_bcast_from_client_data_ifindex(packet, ciaddr); } @@ -1161,7 +1166,7 @@ static void client_background(void) //usage:# define IF_UDHCP_VERBOSE(...) //usage:#endif //usage:#define udhcpc_trivial_usage -//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC|-n]\n" +//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_SK_PRIO(" [-K PRIO]")IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC|-n]\n" //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." //usage:#define udhcpc_full_usage "\n" @@ -1183,6 +1188,9 @@ static void client_background(void) //usage: "\n -R Release IP on exit" //usage: "\n -f Run in foreground" //usage: "\n -S Log to syslog too" +//usage: IF_FEATURE_UDHCPC_SK_PRIO( +//usage: "\n -K PRIO Set kernel packet priority (default 0)" +//usage: ) //usage: IF_FEATURE_UDHCPC_ARPING( //usage: "\n -a[MSEC] Validate offered address with ARP ping" //usage: ) @@ -1232,6 +1240,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) /* Default options */ IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) + IF_FEATURE_UDHCPC_SK_PRIO(client_data.sk_prio = 0;) client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; client_data.sockfd = -1; @@ -1246,6 +1255,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) /* O,x: list; -T,-t,-A take numeric param */ "CV:F:i:np:qRr:s:T:+t:+SA:+O:*ox:*fB" USE_FOR_MMU("b") + IF_FEATURE_UDHCPC_SK_PRIO("K:+") IF_FEATURE_UDHCPC_ARPING("a::") IF_FEATURE_UDHCP_PORT("P:") "v" @@ -1258,6 +1268,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ , &list_O , &list_x + IF_FEATURE_UDHCPC_SK_PRIO(, &client_data.sk_prio) IF_FEATURE_UDHCPC_ARPING(, &str_a) IF_FEATURE_UDHCP_PORT(, &str_P) IF_UDHCP_VERBOSE(, &dhcp_verbose) diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h index 19b054b32..733491953 100644 --- a/networking/udhcp/dhcpc.h +++ b/networking/udhcp/dhcpc.h @@ -9,6 +9,7 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN struct client_data_t { uint8_t client_mac[6]; /* Our mac address */ + IF_FEATURE_UDHCPC_SK_PRIO(int sk_prio;) IF_FEATURE_UDHCP_PORT(uint16_t port;) int ifindex; /* Index number of the interface to use */ uint32_t xid; diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 66750e2e6..814b791b0 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -603,7 +603,8 @@ static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadc udhcp_send_raw_packet(dhcp_pkt, /*src*/ server_data.server_nip, SERVER_PORT, /*dst*/ ciaddr, CLIENT_PORT, chaddr, - server_data.ifindex); + server_data.ifindex + IF_FEATURE_UDHCPC_SK_PRIO(, 0)); } /* Send a packet to gateway_nip using the kernel ip stack */ @@ -618,7 +619,8 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) * even those which are clients' requests and would normally * (i.e. without relay) use CLIENT_PORT. See RFC 1542. */ - server_data.interface); + server_data.interface + IF_FEATURE_UDHCPC_SK_PRIO(, 0)); } static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 529978189..9cd2beafe 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c @@ -106,7 +106,8 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, uint32_t dest_nip, int dest_port, const uint8_t *dest_arp, - int ifindex) + int ifindex + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) { struct sockaddr_ll dest_sll; struct ip_udp_dhcp_packet packet; @@ -121,6 +122,13 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, goto ret_msg; } +#if ENABLE_FEATURE_UDHCPC_SK_PRIO + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, sk_prio) < 0) { + msg = "setsockopt(%s)"; + goto ret_close; + } +#endif + memset(&dest_sll, 0, sizeof(dest_sll)); memset(&packet, 0, offsetof(struct ip_udp_dhcp_packet, data)); packet.data = *dhcp_pkt; /* struct copy */ @@ -192,7 +200,8 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, uint32_t dest_nip, int dest_port, - const char *ifname) + const char *ifname + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) { struct sockaddr_in sa; unsigned padding; @@ -205,6 +214,14 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, msg = "socket(%s)"; goto ret_msg; } + +#if ENABLE_FEATURE_UDHCPC_SK_PRIO + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, sk_prio) < 0) { + msg = "setsockopt(%s)"; + goto ret_close; + } +#endif + setsockopt_reuseaddr(fd); /* If interface carrier goes down, unless we -- 2.38.4 From peron.clem at gmail.com Thu Apr 13 11:09:41 2023 From: peron.clem at gmail.com (=?UTF-8?B?Q2zDqW1lbnQgUMOpcm9u?=) Date: Thu, 13 Apr 2023 13:09:41 +0200 Subject: [PATCH v2] udhcp: add option to set CoS priority In-Reply-To: <20230412205116.2148357e@nbbrfq> References: <20230116101114.52097-1-peron.clem@gmail.com> <168116725009.1013566.3224554891847847588@mail.pacien.net> <20230412205116.2148357e@nbbrfq> Message-ID: Hi Bernhard, On Wed, 12 Apr 2023 at 20:51, Bernhard Reutner-Fischer wrote: > > On Tue, 11 Apr 2023 22:58:00 +0200 > Cl?ment P?ron wrote: > > > Hi Pacien, > > > > On Tue, 11 Apr 2023 at 00:54, pacien wrote: > > > > > > I worked on my own version of this, before seeing that this one was > > > already posted to the list. Sorry for the collision. > > > > > > Message-Id: <20230410214157.1017054-1-dzfkct.busyboxml at pacien.net> > > > > > > It differs mainly in the terminology: it talks about the SKB priority > > > instead of the CoS. Though it should perhaps be the "socket priority" > > > instead? The VLAN CoS mapping isn't automatic. > > > > > > It also differs a bit in the way errors are handled, and puts the > > > priority in the client_data struct with the rest of the settings. > > > > > > : > > > > I'm still testing this patch and I'm unsure if we need to set the > > > > priority for all the sockets. > > > > [...] > > > > udhcp_send_raw_packet() set the priority and not > > > > udhcp_send_kernel_packet(). > > > > > > It seems that the former is used for multicast, the latter for unicast, > > > used in particular for renew and release. So things should probably be > > > kept consistent here. > > > > > > : > > > > > > +//usage: "\n -y PRIORITY CoS value 0 .. 7, default 0" > > > > > > > > I don't see that you would cap the value to 7 anywhere, do you? > > > > The manpage seems to imply that 0..6 can be used by unprivileged users, > > > > higher values require CAP_NET_ADMIN which is fine per se; I assume the > > > > kernel does enough sanity-checking so we can attempt to pass whatever > > > > the user said. > > > > > > I believe 0 to 7 would correspond to VLAN CoS (PCP)? > > > Though that should not be limited here for the socket priority. > > > > I agree with you for both. We should avoid using CoS terminology and > > not limit the value. > > > > I didn't get any response from maintainers and I'm not sure they are > > interested in this feature so I will not work on it. > > Well, at least i did reply, so "didn't get any response from > maintainers" is not really fair, isn't it. Denys devotes alot of > spare time and yes, sometimes patches fall throught the cracks, which > is unfortunate. The usual thing to do is to ping once in a while. > > That said, anybody is free to comment on patches sent to the list, > improve them, or question their validity or usefulness. That's what > this list is for :) Apologize, not sure why but I thought it was a comment from someone else. My bad :( > > > > > If you want to update and rework this, feel free to send a v3 on top > > of this series, but I doubt it will be merged... > > I can see that it has it's use, so if anybody is willing to apply some > tiny bit more TLC then i believe there is no big problem accepting it, > maybe under a knob if really needed. Would be nice if you would include > bloat-o-meter stats. > See 'make baseline; apply the patch; make bloatcheck' > and include the output in the commit message so folks are aware of the > costs of that functionality, please. If it's not too excessive, we may > not need a config knob, or we may, if it's not considered generally > useful. > > cheers, From peron.clem at gmail.com Thu Apr 13 11:13:41 2023 From: peron.clem at gmail.com (=?UTF-8?B?Q2zDqW1lbnQgUMOpcm9u?=) Date: Thu, 13 Apr 2023 13:13:41 +0200 Subject: [PATCH v3] udhcpc(6): add -K option to set kernel packet priority In-Reply-To: <20230413104812.1648285-1-dzfkct.busyboxml@pacien.net> References: <20230413104812.1648285-1-dzfkct.busyboxml@pacien.net> Message-ID: Hi Pacien, On Thu, 13 Apr 2023 at 12:57, pacien wrote: > > From: pacien > > This adds a command line option (-K) to set the (kernel) packet > priority. The option is part of "FEATURE_UDHCPC_SK_PRIO". > > This makes it straightforward to set some VLAN priority for DHCP > requests through an egress QoS map. Packet matching for firewall > or scheduler marking is otherwise broken due to the use of raw > packets. > > (Such priority tag is a hard requirement for some ISPs, such as Orange > in France). > > Enabling this feature costs 264 octets according to bloatcheck. > > Co-authored-by: Cl?ment P?ron > Signed-off-by: Pacien TRAN-GIRARD > --- > Differences from Pacien's v1 and Cl?ment's v2: > * made it clear that we're only talking about the kernel packet priority > (CoS or SKB were ambiguous or unclear) > > Differences from Cl?ment's v2: > * renamed the flag to -K to match the new terminology > * moved sk_prio to client_data, passed as params instead of a global > * used the same error handling as in the send_packet functions > > networking/udhcp/Config.src | 10 ++++++++++ > networking/udhcp/common.h | 6 ++++-- > networking/udhcp/d6_common.h | 2 ++ > networking/udhcp/d6_dhcpc.c | 26 +++++++++++++++++++------- > networking/udhcp/d6_packet.c | 21 +++++++++++++++++++-- > networking/udhcp/dhcpc.c | 29 ++++++++++++++++++++--------- > networking/udhcp/dhcpc.h | 1 + > networking/udhcp/dhcpd.c | 6 ++++-- > networking/udhcp/packet.c | 21 +++++++++++++++++++-- > 9 files changed, 98 insertions(+), 24 deletions(-) > > diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src > index 7ba7f48fc..731cf12fa 100644 > --- a/networking/udhcp/Config.src > +++ b/networking/udhcp/Config.src > @@ -176,3 +176,13 @@ config FEATURE_UDHCP_8021Q > help > If selected, both client and server will support passing of VLAN > ID and priority via options 132 and 133 as per 802.1Q. > + > +config FEATURE_UDHCPC_SK_PRIO > + bool "Enable '-K' option for udhcpc" > + default y > + depends on UDHCPC || UDHCPC6 > + help > + If selected, enables -K option to set the kernel priority of DHCP > + packets. Useful together with some egress QoS mapping to send > + requests with a specific VLAN priority tag, as required by some > + ISPs. > diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h > index 49a0b593d..30ee68375 100644 > --- a/networking/udhcp/common.h > +++ b/networking/udhcp/common.h > @@ -359,12 +359,14 @@ int udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) FAST_FUNC; > int udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, > uint32_t source_nip, int source_port, > uint32_t dest_nip, int dest_port, const uint8_t *dest_arp, > - int ifindex) FAST_FUNC; > + int ifindex > + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) FAST_FUNC; > > int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, > uint32_t source_nip, int source_port, > uint32_t dest_nip, int dest_port, > - const char *ifname) FAST_FUNC; > + const char *ifname > + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) FAST_FUNC; > > void udhcp_sp_setup(void) FAST_FUNC; > void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; > diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h > index 3cbfbb89e..05a5dc2b4 100644 > --- a/networking/udhcp/d6_common.h > +++ b/networking/udhcp/d6_common.h > @@ -180,12 +180,14 @@ int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( > struct d6_packet *d6_pkt, unsigned d6_pkt_size, > struct in6_addr *src_ipv6, int source_port, > struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp > + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio) > ); > > int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( > struct d6_packet *d6_pkt, unsigned d6_pkt_size, > struct in6_addr *src_ipv6, int source_port, > struct in6_addr *dst_ipv6, int dest_port > + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio) > ); > > #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 > diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c > index cdd06188e..173aa2914 100644 > --- a/networking/udhcp/d6_dhcpc.c > +++ b/networking/udhcp/d6_dhcpc.c > @@ -127,6 +127,7 @@ static const char udhcpc6_longopts[] ALIGN1 = > USE_FOR_MMU( > "background\0" No_argument "b" > ) > + IF_FEATURE_UDHCPC_SK_PRIO("sk-priority\0" Required_argument "K") > /// IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a") > IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") > ; > @@ -152,12 +153,14 @@ enum { > OPT_d = 1 << 16, > /* The rest has variable bit positions, need to be clever */ > OPTBIT_d = 16, > - USE_FOR_MMU( OPTBIT_b,) > - ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) > - IF_FEATURE_UDHCP_PORT( OPTBIT_P,) > - USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) > - ///IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,) > - IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) > + USE_FOR_MMU( OPTBIT_b,) > + IF_FEATURE_UDHCPC_SK_PRIO(OPTBIT_K,) > + ///IF_FEATURE_UDHCPC_ARPING( OPTBIT_a,) > + IF_FEATURE_UDHCP_PORT( OPTBIT_P,) > + USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) > + IF_FEATURE_UDHCPC_SK_PRIO(OPT_K = 1 << OPTBIT_K,) > + ///IF_FEATURE_UDHCPC_ARPING( OPT_a = 1 << OPTBIT_a,) > + IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) > }; > > #if ENABLE_FEATURE_UDHCPC6_RFC4704 > @@ -561,6 +564,7 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t * > packet, (end - (uint8_t*) packet), > /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, > /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR > + IF_FEATURE_UDHCPC_SK_PRIO(, client_data.sk_prio) > ); > } > > @@ -866,6 +870,7 @@ static NOINLINE int send_d6_renew(struct in6_addr *server_ipv6, struct in6_addr > &packet, (opt_ptr - (uint8_t*) &packet), > our_cur_ipv6, CLIENT_PORT6, > server_ipv6, SERVER_PORT6 > + IF_FEATURE_UDHCPC_SK_PRIO(, client_data.sk_prio) > ); > return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); > } > @@ -899,6 +904,7 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) > &packet, (opt_ptr - (uint8_t*) &packet), > our_cur_ipv6, CLIENT_PORT6, > server_ipv6, SERVER_PORT6 > + IF_FEATURE_UDHCPC_SK_PRIO(, client_data.sk_prio) > ); > } > > @@ -1129,7 +1135,7 @@ static void client_background(void) > //usage:# define IF_UDHCP_VERBOSE(...) > //usage:#endif > //usage:#define udhcpc6_trivial_usage > -//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"R] [-t N] [-T SEC] [-A SEC|-n] [-i IFACE] [-s PROG]\n" > +//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"R]"IF_FEATURE_UDHCPC_SK_PRIO(" [-K PRIO]")" [-t N] [-T SEC] [-A SEC|-n] [-i IFACE] [-s PROG]\n" > //usage: " [-p PIDFILE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-ldo] [-r IPv6] [-x OPT:VAL]... [-O OPT]..." > //usage:#define udhcpc6_full_usage "\n" > //usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")" > @@ -1150,6 +1156,9 @@ static void client_background(void) > //usage: IF_FEATURE_UDHCP_PORT( > //usage: "\n -P PORT Use PORT (default 546)" > //usage: ) > +//usage: IF_FEATURE_UDHCPC_SK_PRIO( > +//usage: "\n -K PRIO Set kernel packet priority (default 0)" > +//usage: ) > ////usage: IF_FEATURE_UDHCPC_ARPING( > ////usage: "\n -a Use arping to validate offered address" > ////usage: ) > @@ -1199,6 +1208,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) > /* Default options */ > IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) > IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;) > + IF_FEATURE_UDHCPC_SK_PRIO(client_data.sk_prio = 0;) > client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; > client_data.script = CONFIG_UDHCPC6_DEFAULT_SCRIPT; > client_data.sockfd = -1; > @@ -1212,6 +1222,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) > /* O,x: list; -T,-t,-A take numeric param */ > "i:np:qRr:s:T:+t:+SA:+O:*ox:*fld" > USE_FOR_MMU("b") > + IF_FEATURE_UDHCPC_SK_PRIO("K:+") > ///IF_FEATURE_UDHCPC_ARPING("a") > IF_FEATURE_UDHCP_PORT("P:") > "v" > @@ -1222,6 +1233,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) > , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ > , &list_O > , &list_x > + IF_FEATURE_UDHCPC_SK_PRIO(, &client_data.sk_prio) > IF_FEATURE_UDHCP_PORT(, &str_P) > IF_UDHCP_VERBOSE(, &dhcp_verbose) > ); > diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c > index 142de9b43..501497154 100644 > --- a/networking/udhcp/d6_packet.c > +++ b/networking/udhcp/d6_packet.c > @@ -54,7 +54,8 @@ int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 UNUSED_PARAM, > int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( > struct d6_packet *d6_pkt, unsigned d6_pkt_size, > struct in6_addr *src_ipv6, int source_port, > - struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp) > + struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp > + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) > { > struct sockaddr_ll dest_sll; > struct ip6_udp_d6_packet packet; > @@ -68,6 +69,13 @@ int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( > goto ret_msg; > } > > +#if ENABLE_FEATURE_UDHCPC_SK_PRIO > + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, sk_prio) < 0) { One difference is that it will call setsockopt even when sk_prio is not set and default to '0'. I don't know if this can have an impact, or maybe we should default sk_prio to -1 and only call setsockopt_SOL_SOCKET_int() when it's >= 0 Regards, Clement > + msg = "setsockopt(%s)"; > + goto ret_close; > + } > +#endif > + > memset(&dest_sll, 0, sizeof(dest_sll)); > memset(&packet, 0, offsetof(struct ip6_udp_d6_packet, data)); > packet.data = *d6_pkt; /* struct copy */ > @@ -139,7 +147,8 @@ int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( > int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( > struct d6_packet *d6_pkt, unsigned d6_pkt_size, > struct in6_addr *src_ipv6, int source_port, > - struct in6_addr *dst_ipv6, int dest_port) > + struct in6_addr *dst_ipv6, int dest_port > + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) > { > struct sockaddr_in6 sa; > int fd; > @@ -151,6 +160,14 @@ int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( > msg = "socket(%s)"; > goto ret_msg; > } > + > +#if ENABLE_FEATURE_UDHCPC_SK_PRIO > + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, sk_prio) < 0) { > + msg = "setsockopt(%s)"; > + goto ret_close; > + } > +#endif > + > setsockopt_reuseaddr(fd); > > memset(&sa, 0, sizeof(sa)); > diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c > index c757fb37c..8108f6856 100644 > --- a/networking/udhcp/dhcpc.c > +++ b/networking/udhcp/dhcpc.c > @@ -75,6 +75,7 @@ static const char udhcpc_longopts[] ALIGN1 = > "background\0" No_argument "b" > ) > "broadcast\0" No_argument "B" > + IF_FEATURE_UDHCPC_SK_PRIO("sk-priority\0" Required_argument "K") > IF_FEATURE_UDHCPC_ARPING("arping\0" Optional_argument "a") > IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") > ; > @@ -102,12 +103,14 @@ enum { > OPT_B = 1 << 18, > /* The rest has variable bit positions, need to be clever */ > OPTBIT_B = 18, > - USE_FOR_MMU( OPTBIT_b,) > - IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) > - IF_FEATURE_UDHCP_PORT( OPTBIT_P,) > - USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) > - IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,) > - IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) > + USE_FOR_MMU( OPTBIT_b,) > + IF_FEATURE_UDHCPC_SK_PRIO(OPTBIT_K,) > + IF_FEATURE_UDHCPC_ARPING( OPTBIT_a,) > + IF_FEATURE_UDHCP_PORT( OPTBIT_P,) > + USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) > + IF_FEATURE_UDHCPC_SK_PRIO(OPT_K = 1 << OPTBIT_K,) > + IF_FEATURE_UDHCPC_ARPING( OPT_a = 1 << OPTBIT_a,) > + IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) > }; > > > @@ -704,7 +707,8 @@ static int raw_bcast_from_client_data_ifindex(struct dhcp_packet *packet, uint32 > return udhcp_send_raw_packet(packet, > /*src*/ src_nip, CLIENT_PORT, > /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, > - client_data.ifindex); > + client_data.ifindex > + IF_FEATURE_UDHCPC_SK_PRIO(, client_data.sk_prio)); > } > > static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) > @@ -713,7 +717,8 @@ static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t > return udhcp_send_kernel_packet(packet, > ciaddr, CLIENT_PORT, > server, SERVER_PORT, > - client_data.interface); > + client_data.interface > + IF_FEATURE_UDHCPC_SK_PRIO(, client_data.sk_prio)); > return raw_bcast_from_client_data_ifindex(packet, ciaddr); > } > > @@ -1161,7 +1166,7 @@ static void client_background(void) > //usage:# define IF_UDHCP_VERBOSE(...) > //usage:#endif > //usage:#define udhcpc_trivial_usage > -//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC|-n]\n" > +//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_SK_PRIO(" [-K PRIO]")IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC|-n]\n" > //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" > //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." > //usage:#define udhcpc_full_usage "\n" > @@ -1183,6 +1188,9 @@ static void client_background(void) > //usage: "\n -R Release IP on exit" > //usage: "\n -f Run in foreground" > //usage: "\n -S Log to syslog too" > +//usage: IF_FEATURE_UDHCPC_SK_PRIO( > +//usage: "\n -K PRIO Set kernel packet priority (default 0)" > +//usage: ) > //usage: IF_FEATURE_UDHCPC_ARPING( > //usage: "\n -a[MSEC] Validate offered address with ARP ping" > //usage: ) > @@ -1232,6 +1240,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) > /* Default options */ > IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) > IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) > + IF_FEATURE_UDHCPC_SK_PRIO(client_data.sk_prio = 0;) > client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; > client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; > client_data.sockfd = -1; > @@ -1246,6 +1255,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) > /* O,x: list; -T,-t,-A take numeric param */ > "CV:F:i:np:qRr:s:T:+t:+SA:+O:*ox:*fB" > USE_FOR_MMU("b") > + IF_FEATURE_UDHCPC_SK_PRIO("K:+") > IF_FEATURE_UDHCPC_ARPING("a::") > IF_FEATURE_UDHCP_PORT("P:") > "v" > @@ -1258,6 +1268,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) > , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ > , &list_O > , &list_x > + IF_FEATURE_UDHCPC_SK_PRIO(, &client_data.sk_prio) > IF_FEATURE_UDHCPC_ARPING(, &str_a) > IF_FEATURE_UDHCP_PORT(, &str_P) > IF_UDHCP_VERBOSE(, &dhcp_verbose) > diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h > index 19b054b32..733491953 100644 > --- a/networking/udhcp/dhcpc.h > +++ b/networking/udhcp/dhcpc.h > @@ -9,6 +9,7 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN > > struct client_data_t { > uint8_t client_mac[6]; /* Our mac address */ > + IF_FEATURE_UDHCPC_SK_PRIO(int sk_prio;) > IF_FEATURE_UDHCP_PORT(uint16_t port;) > int ifindex; /* Index number of the interface to use */ > uint32_t xid; > diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c > index 66750e2e6..814b791b0 100644 > --- a/networking/udhcp/dhcpd.c > +++ b/networking/udhcp/dhcpd.c > @@ -603,7 +603,8 @@ static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadc > udhcp_send_raw_packet(dhcp_pkt, > /*src*/ server_data.server_nip, SERVER_PORT, > /*dst*/ ciaddr, CLIENT_PORT, chaddr, > - server_data.ifindex); > + server_data.ifindex > + IF_FEATURE_UDHCPC_SK_PRIO(, 0)); > } > > /* Send a packet to gateway_nip using the kernel ip stack */ > @@ -618,7 +619,8 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) > * even those which are clients' requests and would normally > * (i.e. without relay) use CLIENT_PORT. See RFC 1542. > */ > - server_data.interface); > + server_data.interface > + IF_FEATURE_UDHCPC_SK_PRIO(, 0)); > } > > static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) > diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c > index 529978189..9cd2beafe 100644 > --- a/networking/udhcp/packet.c > +++ b/networking/udhcp/packet.c > @@ -106,7 +106,8 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) > int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, > uint32_t source_nip, int source_port, > uint32_t dest_nip, int dest_port, const uint8_t *dest_arp, > - int ifindex) > + int ifindex > + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) > { > struct sockaddr_ll dest_sll; > struct ip_udp_dhcp_packet packet; > @@ -121,6 +122,13 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, > goto ret_msg; > } > > +#if ENABLE_FEATURE_UDHCPC_SK_PRIO > + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, sk_prio) < 0) { > + msg = "setsockopt(%s)"; > + goto ret_close; > + } > +#endif > + > memset(&dest_sll, 0, sizeof(dest_sll)); > memset(&packet, 0, offsetof(struct ip_udp_dhcp_packet, data)); > packet.data = *dhcp_pkt; /* struct copy */ > @@ -192,7 +200,8 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, > int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, > uint32_t source_nip, int source_port, > uint32_t dest_nip, int dest_port, > - const char *ifname) > + const char *ifname > + IF_FEATURE_UDHCPC_SK_PRIO(, int sk_prio)) > { > struct sockaddr_in sa; > unsigned padding; > @@ -205,6 +214,14 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, > msg = "socket(%s)"; > goto ret_msg; > } > + > +#if ENABLE_FEATURE_UDHCPC_SK_PRIO > + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, sk_prio) < 0) { > + msg = "setsockopt(%s)"; > + goto ret_close; > + } > +#endif > + > setsockopt_reuseaddr(fd); > > /* If interface carrier goes down, unless we > -- > 2.38.4 > From rmy at pobox.com Thu Apr 13 11:55:20 2023 From: rmy at pobox.com (Ron Yorston) Date: Thu, 13 Apr 2023 12:55:20 +0100 Subject: [PATCH 0/1] ash,hush: tab completion of functions and aliases Message-ID: <6437eda8.7xmOSNErXOVqhWmq%rmy@pobox.com> There follows a patch to add tab completion of functions and aliases to ash and hush. (hush doesn't support aliases, but that's a different issue.) A couple of things: - The code makes repeated passes over the command and alias tables. We don't think this will be a problem in most cases. We do have an alternative patch which only requires a single pass but it's more intrusive and bigger (200 vs 114 bytes). It can be made available if there's interest. - bloatcheck doesn't give an accurate result for this patch. It was confused by there being two functions called get_builtin_name. The report in the patch was generated by splitting the change into two parts: one to change the names and a second to add the new code. Cheers, Ron From rmy at pobox.com Thu Apr 13 11:56:14 2023 From: rmy at pobox.com (Ron Yorston) Date: Thu, 13 Apr 2023 12:56:14 +0100 Subject: [PATCH 1/1] ash,hush: tab completion of functions and aliases In-Reply-To: <6437eda8.7xmOSNErXOVqhWmq%rmy@pobox.com> References: <6437eda8.7xmOSNErXOVqhWmq%rmy@pobox.com> Message-ID: <6437edde.hvw2JkLSCWRgS6Jt%rmy@pobox.com> Since commit 9e2a5668f (ash,hush: allow builtins to be tab-completed, closes 7532) ash and hush have supported tab completion of builtins. Other shells, bash and ksh for example, also support tab completion of functions and aliases. Add such support to ash and hush. function old new delta ash_command_name - 98 +98 hush_command_name - 71 +71 ash_builtin_name 17 - -17 hush_builtin_name 38 - -38 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 0/0 up/down: 169/-55) Total: 114 bytes Signed-off-by: Ron Yorston Signed-off-by: Avi Halachmi --- shell/ash.c | 30 ++++++++++++++++++++++++++---- shell/hush.c | 11 +++++++++-- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index d4ee4c93e..055f5ff73 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9732,7 +9732,7 @@ evalpipe(union node *n, int flags) /* setinteractive needs this forward reference */ #if ENABLE_FEATURE_TAB_COMPLETION -static const char *get_builtin_name(int i) FAST_FUNC; +static const char *ash_command_name(int i) FAST_FUNC; #endif /* @@ -9769,7 +9769,7 @@ setinteractive(int on) if (!line_input_state) { line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); # if ENABLE_FEATURE_TAB_COMPLETION - line_input_state->get_exe_name = get_builtin_name; + line_input_state->get_exe_name = ash_command_name; # endif # if EDITING_HAS_sh_get_var line_input_state->sh_get_var = lookupvar; @@ -10284,9 +10284,31 @@ find_builtin(const char *name) #if ENABLE_FEATURE_TAB_COMPLETION static const char * FAST_FUNC -get_builtin_name(int i) +ash_command_name(int i) { - return /*i >= 0 &&*/ i < ARRAY_SIZE(builtintab) ? builtintab[i].name + 1 : NULL; + int n; + + if (/*i >= 0 &&*/ i < ARRAY_SIZE(builtintab)) + return builtintab[i].name + 1; + i -= ARRAY_SIZE(builtintab); + + for (n = 0; n < CMDTABLESIZE; n++) { + for (struct tblentry *cmdp = cmdtable[n]; cmdp; cmdp = cmdp->next) { + if (cmdp->cmdtype == CMDFUNCTION && i-- <= 0) + return cmdp->cmdname; + } + } + +# if ENABLE_ASH_ALIAS + for (n = 0; n < ATABSIZE; n++) { + for(struct alias *ap = atab[n]; ap; ap = ap->next) { + if (i-- <= 0) + return ap->name; + } + } +#endif + + return NULL; } #endif diff --git a/shell/hush.c b/shell/hush.c index 202c0993a..9439c2cca 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -8220,7 +8220,7 @@ static const struct built_in_command *find_builtin(const char *name) } #if ENABLE_HUSH_JOB && ENABLE_FEATURE_TAB_COMPLETION -static const char * FAST_FUNC get_builtin_name(int i) +static const char * FAST_FUNC hush_command_name(int i) { if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) { return bltins1[i].b_cmd; @@ -8229,6 +8229,13 @@ static const char * FAST_FUNC get_builtin_name(int i) if (i < ARRAY_SIZE(bltins2)) { return bltins2[i].b_cmd; } +# if ENABLE_HUSH_FUNCTIONS + i -= ARRAY_SIZE(bltins2); + for (struct function *funcp = G.top_func; funcp; funcp = funcp->next) { + if (i-- <= 0) + return funcp->name; + } +# endif return NULL; } #endif @@ -10716,7 +10723,7 @@ int hush_main(int argc, char **argv) # if ENABLE_FEATURE_EDITING G.line_input_state = new_line_input_t(FOR_SHELL); # if ENABLE_FEATURE_TAB_COMPLETION - G.line_input_state->get_exe_name = get_builtin_name; + G.line_input_state->get_exe_name = hush_command_name; # endif # if EDITING_HAS_sh_get_var G.line_input_state->sh_get_var = get_local_var_value; -- 2.39.2 From dzfkct.busyboxml at pacien.net Thu Apr 13 12:07:07 2023 From: dzfkct.busyboxml at pacien.net (Pacien TRAN-GIRARD) Date: Thu, 13 Apr 2023 14:07:07 +0200 Subject: [PATCH v3] udhcpc(6): add -K option to set kernel packet priority In-Reply-To: References: <20230413104812.1648285-1-dzfkct.busyboxml@pacien.net> Message-ID: <168138762754.1656295.12624125235575222643@mail.pacien.net> Quoting Cl?ment P?ron (2023-04-13 13:13:41) > > +#if ENABLE_FEATURE_UDHCPC_SK_PRIO > > + if (setsockopt_SOL_SOCKET_int(fd, SO_PRIORITY, sk_prio) < 0) { > > One difference is that it will call setsockopt even when sk_prio is > not set and default to '0'. > > I don't know if this can have an impact, or maybe we should default > sk_prio to -1 and only call setsockopt_SOL_SOCKET_int() when it's >= 0 I omitted the check here since the default kernel packet priority is 0, so setting it again to 0 by default should not do any harm. From rmy at pobox.com Sun Apr 16 07:23:58 2023 From: rmy at pobox.com (Ron Yorston) Date: Sun, 16 Apr 2023 08:23:58 +0100 Subject: [PATCH] tr: display usage for incorrect arguments Message-ID: <643ba28e.HahgYCNaUCeBaFof%rmy@pobox.com> tr must have one or two non-option arguments. Display the usage message if any other number is present. function old new delta .rodata 108389 108392 +3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 3/0) Total: 3 bytes Signed-off-by: Ron Yorston --- coreutils/tr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/tr.c b/coreutils/tr.c index 1e402dfdb..7fe7f89d5 100644 --- a/coreutils/tr.c +++ b/coreutils/tr.c @@ -299,7 +299,7 @@ int tr_main(int argc UNUSED_PARAM, char **argv) */ /* '+': stop at first non-option */ - opts = getopt32(argv, "^+" "Ccds" "\0" "-1"); + opts = getopt32(argv, "^+" "Ccds" "\0" "-1:?2"); argv += optind; str1_length = expand(*argv++, &str1); -- 2.39.2 From vda.linux at googlemail.com Sun Apr 16 15:52:18 2023 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Sun, 16 Apr 2023 17:52:18 +0200 Subject: [PATCH 1/1] ash,hush: tab completion of functions and aliases In-Reply-To: <6437edde.hvw2JkLSCWRgS6Jt%rmy@pobox.com> References: <6437eda8.7xmOSNErXOVqhWmq%rmy@pobox.com> <6437edde.hvw2JkLSCWRgS6Jt%rmy@pobox.com> Message-ID: Applied, thank you. On Thu, Apr 13, 2023 at 1:56?PM Ron Yorston wrote: > > Since commit 9e2a5668f (ash,hush: allow builtins to be tab-completed, > closes 7532) ash and hush have supported tab completion of builtins. > > Other shells, bash and ksh for example, also support tab completion > of functions and aliases. > > Add such support to ash and hush. > > function old new delta > ash_command_name - 98 +98 > hush_command_name - 71 +71 > ash_builtin_name 17 - -17 > hush_builtin_name 38 - -38 > ------------------------------------------------------------------------------ > (add/remove: 2/2 grow/shrink: 0/0 up/down: 169/-55) Total: 114 bytes > > Signed-off-by: Ron Yorston > Signed-off-by: Avi Halachmi > --- > shell/ash.c | 30 ++++++++++++++++++++++++++---- > shell/hush.c | 11 +++++++++-- > 2 files changed, 35 insertions(+), 6 deletions(-) > > diff --git a/shell/ash.c b/shell/ash.c > index d4ee4c93e..055f5ff73 100644 > --- a/shell/ash.c > +++ b/shell/ash.c > @@ -9732,7 +9732,7 @@ evalpipe(union node *n, int flags) > > /* setinteractive needs this forward reference */ > #if ENABLE_FEATURE_TAB_COMPLETION > -static const char *get_builtin_name(int i) FAST_FUNC; > +static const char *ash_command_name(int i) FAST_FUNC; > #endif > > /* > @@ -9769,7 +9769,7 @@ setinteractive(int on) > if (!line_input_state) { > line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); > # if ENABLE_FEATURE_TAB_COMPLETION > - line_input_state->get_exe_name = get_builtin_name; > + line_input_state->get_exe_name = ash_command_name; > # endif > # if EDITING_HAS_sh_get_var > line_input_state->sh_get_var = lookupvar; > @@ -10284,9 +10284,31 @@ find_builtin(const char *name) > > #if ENABLE_FEATURE_TAB_COMPLETION > static const char * FAST_FUNC > -get_builtin_name(int i) > +ash_command_name(int i) > { > - return /*i >= 0 &&*/ i < ARRAY_SIZE(builtintab) ? builtintab[i].name + 1 : NULL; > + int n; > + > + if (/*i >= 0 &&*/ i < ARRAY_SIZE(builtintab)) > + return builtintab[i].name + 1; > + i -= ARRAY_SIZE(builtintab); > + > + for (n = 0; n < CMDTABLESIZE; n++) { > + for (struct tblentry *cmdp = cmdtable[n]; cmdp; cmdp = cmdp->next) { > + if (cmdp->cmdtype == CMDFUNCTION && i-- <= 0) > + return cmdp->cmdname; > + } > + } > + > +# if ENABLE_ASH_ALIAS > + for (n = 0; n < ATABSIZE; n++) { > + for(struct alias *ap = atab[n]; ap; ap = ap->next) { > + if (i-- <= 0) > + return ap->name; > + } > + } > +#endif > + > + return NULL; > } > #endif > > diff --git a/shell/hush.c b/shell/hush.c > index 202c0993a..9439c2cca 100644 > --- a/shell/hush.c > +++ b/shell/hush.c > @@ -8220,7 +8220,7 @@ static const struct built_in_command *find_builtin(const char *name) > } > > #if ENABLE_HUSH_JOB && ENABLE_FEATURE_TAB_COMPLETION > -static const char * FAST_FUNC get_builtin_name(int i) > +static const char * FAST_FUNC hush_command_name(int i) > { > if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) { > return bltins1[i].b_cmd; > @@ -8229,6 +8229,13 @@ static const char * FAST_FUNC get_builtin_name(int i) > if (i < ARRAY_SIZE(bltins2)) { > return bltins2[i].b_cmd; > } > +# if ENABLE_HUSH_FUNCTIONS > + i -= ARRAY_SIZE(bltins2); > + for (struct function *funcp = G.top_func; funcp; funcp = funcp->next) { > + if (i-- <= 0) > + return funcp->name; > + } > +# endif > return NULL; > } > #endif > @@ -10716,7 +10723,7 @@ int hush_main(int argc, char **argv) > # if ENABLE_FEATURE_EDITING > G.line_input_state = new_line_input_t(FOR_SHELL); > # if ENABLE_FEATURE_TAB_COMPLETION > - G.line_input_state->get_exe_name = get_builtin_name; > + G.line_input_state->get_exe_name = hush_command_name; > # endif > # if EDITING_HAS_sh_get_var > G.line_input_state->sh_get_var = get_local_var_value; > -- > 2.39.2 > > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox From vda.linux at googlemail.com Sun Apr 16 15:55:03 2023 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Sun, 16 Apr 2023 17:55:03 +0200 Subject: [PATCH] tr: display usage for incorrect arguments In-Reply-To: <643ba28e.HahgYCNaUCeBaFof%rmy@pobox.com> References: <643ba28e.HahgYCNaUCeBaFof%rmy@pobox.com> Message-ID: Applied, thank you. On Sun, Apr 16, 2023 at 9:24?AM Ron Yorston wrote: > > tr must have one or two non-option arguments. Display the usage > message if any other number is present. > > function old new delta > .rodata 108389 108392 +3 > ------------------------------------------------------------------------------ > (add/remove: 0/0 grow/shrink: 1/0 up/down: 3/0) Total: 3 bytes > > Signed-off-by: Ron Yorston > --- > coreutils/tr.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/coreutils/tr.c b/coreutils/tr.c > index 1e402dfdb..7fe7f89d5 100644 > --- a/coreutils/tr.c > +++ b/coreutils/tr.c > @@ -299,7 +299,7 @@ int tr_main(int argc UNUSED_PARAM, char **argv) > */ > > /* '+': stop at first non-option */ > - opts = getopt32(argv, "^+" "Ccds" "\0" "-1"); > + opts = getopt32(argv, "^+" "Ccds" "\0" "-1:?2"); > argv += optind; > > str1_length = expand(*argv++, &str1); > -- > 2.39.2 > > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox From vda.linux at googlemail.com Sun Apr 16 16:02:17 2023 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Sun, 16 Apr 2023 18:02:17 +0200 Subject: [PATCH] readlink: Support --, -n always In-Reply-To: References: <20230324145814.1113627-1-eblake@redhat.com> Message-ID: Applied, thank you On Mon, Apr 10, 2023 at 4:00?PM Eric Blake wrote: > > Ping > > On Fri, Mar 24, 2023 at 09:58:14AM -0500, Eric Blake wrote: > > POSIX will be standardizing readlink (just the -n option) and realpath > > (just -E and -e options): > > https://www.austingroupbugs.net/view.php?id=1457 > > > > Change things for readlink so that the POSIX-mandated -n and -- work > > even when disabling the non-standard (and partially non-working) -f > > when FEATURE_READLINK_FOLLOW is clear. > > > > POSIX also wants readlink to be verbose by default (if the argument is > > not a symlink, readlink must output a diagnostic); I did NOT address > > that one, because I'm waiting to see what the GNU Coreutils folks do: > > https://lists.gnu.org/archive/html/bug-coreutils/2023-03/msg00035.html > > > > Partial fix for https://bugs.busybox.net/show_bug.cgi?id=15466 > > > > Signed-off-by: Eric Blake > > --- > > coreutils/readlink.c | 29 ++++++++++++----------------- > > 1 file changed, 12 insertions(+), 17 deletions(-) > > > > diff --git a/coreutils/readlink.c b/coreutils/readlink.c > > index b2e867883..0a9aa957e 100644 > > --- a/coreutils/readlink.c > > +++ b/coreutils/readlink.c > > @@ -25,12 +25,14 @@ > > //kbuild:lib-$(CONFIG_READLINK) += readlink.o > > > > //usage:#define readlink_trivial_usage > > -//usage: IF_FEATURE_READLINK_FOLLOW("[-fnv] ") "FILE" > > +//usage: IF_FEATURE_READLINK_FOLLOW("[-fnv] ") > > +//usage: IF_NOT_FEATURE_READLINK_FOLLOW("[-n] ") > > +//usage: "FILE" > > //usage:#define readlink_full_usage "\n\n" > > -//usage: "Display the value of a symlink" > > -//usage: IF_FEATURE_READLINK_FOLLOW( "\n" > > -//usage: "\n -f Canonicalize by following all symlinks" > > +//usage: "Display the value of a symlink" "\n" > > //usage: "\n -n Don't add newline" > > +//usage: IF_FEATURE_READLINK_FOLLOW( > > +//usage: "\n -f Canonicalize by following all symlinks" > > //usage: "\n -v Verbose" > > //usage: ) > > > > @@ -67,25 +69,18 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) > > { > > char *buf; > > char *fname; > > + unsigned opt; > > > > - IF_FEATURE_READLINK_FOLLOW( > > - unsigned opt; > > - /* We need exactly one non-option argument. */ > > - opt = getopt32(argv, "^" "fnvsq" "\0" "=1"); > > - fname = argv[optind]; > > - ) > > - IF_NOT_FEATURE_READLINK_FOLLOW( > > - const unsigned opt = 0; > > - if (argc != 2) bb_show_usage(); > > - fname = argv[1]; > > - ) > > + opt = getopt32(argv, "^" "n" IF_FEATURE_READLINK_FOLLOW("fvsq") > > + "\0" "=1"); > > + fname = argv[optind]; > > > > /* compat: coreutils readlink reports errors silently via exit code */ > > if (!(opt & 4)) /* not -v */ > > logmode = LOGMODE_NONE; > > > > /* NOFORK: only one alloc is allowed; must free */ > > - if (opt & 1) { /* -f */ > > + if (opt & 2) { /* -f */ > > buf = xmalloc_realpath_coreutils(fname); > > } else { > > buf = xmalloc_readlink_or_warn(fname); > > @@ -93,7 +88,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) > > > > if (!buf) > > return EXIT_FAILURE; > > - printf((opt & 2) ? "%s" : "%s\n", buf); > > + printf((opt & 1) ? "%s" : "%s\n", buf); > > free(buf); > > > > fflush_stdout_and_exit_SUCCESS(); > > -- > > 2.39.2 > > > > _______________________________________________ > > busybox mailing list > > busybox at busybox.net > > http://lists.busybox.net/mailman/listinfo/busybox > > > > -- > Eric Blake, Principal Software Engineer > Red Hat, Inc. +1-919-301-3266 > Virtualization: qemu.org | libvirt.org > > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox From pp01415943 at gmail.com Mon Apr 17 13:28:53 2023 From: pp01415943 at gmail.com (Petja Patjas) Date: Mon, 17 Apr 2023 16:28:53 +0300 Subject: [PATCH v2] vi: Ensure that the edit buffer ends in a newline Message-ID: <20230417132853.46391-1-pp01415943@gmail.com> Currently vi assumes that the edit buffer ends in a newline. This may not be the case. For example: $ printf test > test $ vi test We fix this by inserting a newline to the end during initialization. Signed-off-by: Petja Patjas --- The first patch didn't apply, sorry about that. I also took this chance to simplify the logic a bit. editors/vi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/editors/vi.c b/editors/vi.c index 2645afe87..2947c5c1b 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -2315,9 +2315,10 @@ static int init_text_buffer(char *fn) update_filename(fn); rc = file_insert(fn, text, 1); - if (rc < 0) { - // file doesnt exist. Start empty buf with dummy line - char_insert(text, '\n', NO_UNDO); + if (rc <= 0 || *(end - 1) != '\n') { + // file doesn't exist or doesn't end in a newline. + // insert a newline to the end + char_insert(end, '\n', NO_UNDO); } flush_undo_data(); -- 2.40.0 From eblake at redhat.com Mon Apr 17 19:15:40 2023 From: eblake at redhat.com (Eric Blake) Date: Mon, 17 Apr 2023 14:15:40 -0500 Subject: [PATCH v2] readlink: slight size optimization Message-ID: <20230417191540.1773858-1-eblake@redhat.com> Exploit the value of the flag for -n to reduce the size of readlink_main() (shown here with CONFIG_FEATURE_READLINK_FOLLOW off) on x86_64. function old new delta readlink_main 121 118 -3 Signed-off-by: Eric Blake --- v2: Add 'make bloatcheck' details --- coreutils/readlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/readlink.c b/coreutils/readlink.c index 0a9aa957e..83c417e66 100644 --- a/coreutils/readlink.c +++ b/coreutils/readlink.c @@ -88,7 +88,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) if (!buf) return EXIT_FAILURE; - printf((opt & 1) ? "%s" : "%s\n", buf); + printf("%s%s", buf, "\n"[opt & 1]); free(buf); fflush_stdout_and_exit_SUCCESS(); base-commit: d2b81b3dc2b31d32e1060d3ea8bd998d30a37d8a -- 2.39.2 From farmatito at tiscali.it Mon Apr 17 21:21:21 2023 From: farmatito at tiscali.it (tito) Date: Mon, 17 Apr 2023 23:21:21 +0200 Subject: [PATCH v2] readlink: slight size optimization In-Reply-To: <20230417191540.1773858-1-eblake@redhat.com> References: <20230417191540.1773858-1-eblake@redhat.com> Message-ID: <20230417232121.2faaff1c@devuan> On Mon, 17 Apr 2023 14:15:40 -0500 Eric Blake wrote: > Exploit the value of the flag for -n to reduce the size of > readlink_main() (shown here with CONFIG_FEATURE_READLINK_FOLLOW off) > on x86_64. > > function old new delta > readlink_main 121 118 -3 > > Signed-off-by: Eric Blake > > --- > > v2: Add 'make bloatcheck' details > --- > coreutils/readlink.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/coreutils/readlink.c b/coreutils/readlink.c > index 0a9aa957e..83c417e66 100644 > --- a/coreutils/readlink.c > +++ b/coreutils/readlink.c > @@ -88,7 +88,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) > > if (!buf) > return EXIT_FAILURE; > - printf((opt & 1) ? "%s" : "%s\n", buf); > + printf("%s%s", buf, "\n"[opt & 1]); > free(buf); > > fflush_stdout_and_exit_SUCCESS(); > > base-commit: d2b81b3dc2b31d32e1060d3ea8bd998d30a37d8a Hi, I was just curious as with my limited C skills I didn't understand how "\n"[opt & 1] works, so I applied your patch and compiled it, but it seems to me that something is wrong: Prepare a link for testing: tito at devuan:~/Desktop/SourceCode/busybox_new$ ln -s busybox prova Busybox with your patch applied: $ ./busybox readlink prova Segmentation fault $ ./busybox readlink -n prova busybox(null)$ Real readlink; readlink prova busybox $ readlink -n prova busybox$ Did you intend something like: printf("%s%c", buf, '\n'*!(opt & 1)); I did not test if this reduces size. Ciao, Tito From harald at gigawatt.nl Mon Apr 17 21:43:36 2023 From: harald at gigawatt.nl (Harald van Dijk) Date: Mon, 17 Apr 2023 22:43:36 +0100 Subject: [PATCH v2] readlink: slight size optimization In-Reply-To: <20230417232121.2faaff1c@devuan> References: <20230417191540.1773858-1-eblake@redhat.com> <20230417232121.2faaff1c@devuan> Message-ID: On 17/04/2023 22:21, tito wrote: > On Mon, 17 Apr 2023 14:15:40 -0500 > Eric Blake wrote: > >> Exploit the value of the flag for -n to reduce the size of >> readlink_main() (shown here with CONFIG_FEATURE_READLINK_FOLLOW off) >> on x86_64. >> >> function old new delta >> readlink_main 121 118 -3 >> >> Signed-off-by: Eric Blake >> >> --- >> >> v2: Add 'make bloatcheck' details >> --- >> coreutils/readlink.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/coreutils/readlink.c b/coreutils/readlink.c >> index 0a9aa957e..83c417e66 100644 >> --- a/coreutils/readlink.c >> +++ b/coreutils/readlink.c >> @@ -88,7 +88,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) >> >> if (!buf) >> return EXIT_FAILURE; >> - printf((opt & 1) ? "%s" : "%s\n", buf); >> + printf("%s%s", buf, "\n"[opt & 1]); >> free(buf); >> >> fflush_stdout_and_exit_SUCCESS(); >> >> base-commit: d2b81b3dc2b31d32e1060d3ea8bd998d30a37d8a > > Hi, > I was just curious as with my limited C skills I didn't understand how "\n"[opt & 1] works, > so I applied your patch and compiled it, > but it seems to me that something is wrong: > > Prepare a link for testing: > tito at devuan:~/Desktop/SourceCode/busybox_new$ ln -s busybox prova > > Busybox with your patch applied: > $ ./busybox readlink prova > Segmentation fault > $ ./busybox readlink -n prova > busybox(null)$ Your testing is correct: the patch is wrong and cannot work. > Real readlink; > readlink prova > busybox > $ readlink -n prova > busybox$ > > Did you intend something like: > > printf("%s%c", buf, '\n'*!(opt & 1)); I am assuming it was intended to be printf("%s%s", buf, &"\n"[opt & 1]); As you are trying to understand how this works: the string "\n" is a character array consisting of the characters '\n' and '\0', where '\0' acts as the string terminator. &"\n"[0] is a pointer to the first element of this array and will be printed as the character '\n'. &"\n"[1] is a pointer to the second element of this array, the null character, meaning it is a null string and printing it has no effect. This is different from the approach you were taking: printing '\0' with %c results in the output of a null byte. You would not see this null byte if you visually inspect the output, but you would if you e.g. view the output with the 'od' utility. Cheers, Harald van Dijk > I did not test if this reduces size. > > Ciao, > Tito From eblake at redhat.com Mon Apr 17 22:23:04 2023 From: eblake at redhat.com (Eric Blake) Date: Mon, 17 Apr 2023 17:23:04 -0500 Subject: [PATCH v2] readlink: slight size optimization In-Reply-To: <20230417232121.2faaff1c@devuan> References: <20230417191540.1773858-1-eblake@redhat.com> <20230417232121.2faaff1c@devuan> Message-ID: On Mon, Apr 17, 2023 at 11:21:21PM +0200, tito wrote: > On Mon, 17 Apr 2023 14:15:40 -0500 > Eric Blake wrote: > > > Exploit the value of the flag for -n to reduce the size of > > readlink_main() (shown here with CONFIG_FEATURE_READLINK_FOLLOW off) > > on x86_64. > > > > function old new delta > > readlink_main 121 118 -3 > > - printf((opt & 1) ? "%s" : "%s\n", buf); > > + printf("%s%s", buf, "\n"[opt & 1]); > > free(buf); > > > > fflush_stdout_and_exit_SUCCESS(); > > > > base-commit: d2b81b3dc2b31d32e1060d3ea8bd998d30a37d8a > > Hi, > I was just curious as with my limited C skills I didn't understand how "\n"[opt & 1] works, If it makes it easier, you could use the more verbose: const char *tail = "\n"; printf("%s%s", buf, tail[opt & 1]); but I didn't see a reason to declare a one-shot variable. In C, both 'pointer[integer]' and 'integer[pointer]' are shorthands for the same thing (you usually write the pointer outside of the [], but its a nice obfuscation trick to know that you could equally write (opt & 1)["\n"] for the same results). Either way, those shorthands are turned by the compiler into *(pointer+offset), that is, treat the given pointer as an array and dereference the integer offset into that array (where the integer is scaled by the size of the array element as determined by the underlying type of the pointer). The other thing to know is that string literals are pointers. That is, "\n" is a 'const char *' pointing to at least the two bytes '\n' and '\0'. So [opt & 1] is the integer offset that says how far into that array to read. If opt&1 is 0 (-n was not passed), we want offset 0, effectively matching %s to the sub-array beginning {'\n','\0'} (in short form "\n") and printing the trailing newline. If opt&1 is 1 (-n was passed), we want offset 1, effectively matching %s to the sub-array beginning {'\0'} (in short form "") and printing nothing. > so I applied your patch and compiled it, > but it seems to me that something is wrong: > > Prepare a link for testing: > tito at devuan:~/Desktop/SourceCode/busybox_new$ ln -s busybox prova > > Busybox with your patch applied: > $ ./busybox readlink prova > Segmentation fault > $ ./busybox readlink -n prova > busybox(null)$ Eww - that wasn't happening for me; but I had CONFIG_REATURE_READLINK_FOLLOW turned off; when I re-enable that, I'm seeing the same crash. :( This patch specifically depends on -n mapping to bit 0 (value 1) (as otherwise, [opt & 1] dereferences out of bounds of the 2-element array referenced by "\n"). Beyond that, I'm not sure why things are behaving differently; maybe I'm misunderstanding how getopt32() works? > > Real readlink; > readlink prova > busybox > $ readlink -n prova > busybox$ > > Did you intend something like: > > printf("%s%c", buf, '\n'*!(opt & 1)); No, because that prints an actual NUL byte, which is incorrect. The point of -n is to print nothing (0 bytes output), not a NUL byte (1 byte output). > > I did not test if this reduces size. Doesn't matter if it reduces size if it is wrong. But I'm still trying to figure out why CONFIG_REATURE_READLINK_FOLLOW doesn't work with my patch? I'll have to figure out how to recompile with debugging symbols left intact to run it under gdb, to get a more informative stack trace than: #0 __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:76 #1 0x00007ffff7d2e828 in __vfprintf_internal ( s=0x7ffff7ea3780 <_IO_2_1_stdout_>, format=0x4e09e0 "%s%s", ap=ap at entry=0x7fffffffda50, mode_flags=mode_flags at entry=0) at /usr/src/debug/glibc-2.36-9.fc37.x86_64/stdio-common/vfprintf-process-arg.c:397 #2 0x00007ffff7d228ff in __printf (format=) at printf.c:33 #3 0x0000000000499a42 in readlink_main () #4 0x0000000000000000 in ?? () -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org From farmatito at tiscali.it Mon Apr 17 22:44:22 2023 From: farmatito at tiscali.it (tito) Date: Tue, 18 Apr 2023 00:44:22 +0200 Subject: [PATCH v2] readlink: slight size optimization In-Reply-To: References: <20230417191540.1773858-1-eblake@redhat.com> <20230417232121.2faaff1c@devuan> Message-ID: <20230418004422.47ab54bd@devuan> On Mon, 17 Apr 2023 17:23:04 -0500 Eric Blake wrote: > On Mon, Apr 17, 2023 at 11:21:21PM +0200, tito wrote: > > On Mon, 17 Apr 2023 14:15:40 -0500 > > Eric Blake wrote: > > > > > Exploit the value of the flag for -n to reduce the size of > > > readlink_main() (shown here with CONFIG_FEATURE_READLINK_FOLLOW off) > > > on x86_64. > > > > > > function old new delta > > > readlink_main 121 118 -3 > > > > - printf((opt & 1) ? "%s" : "%s\n", buf); > > > + printf("%s%s", buf, "\n"[opt & 1]); > > > free(buf); > > > > > > fflush_stdout_and_exit_SUCCESS(); > > > > > > base-commit: d2b81b3dc2b31d32e1060d3ea8bd998d30a37d8a > > > > Hi, > > I was just curious as with my limited C skills I didn't understand how "\n"[opt & 1] works, > > If it makes it easier, you could use the more verbose: > > const char *tail = "\n"; > printf("%s%s", buf, tail[opt & 1]); > > but I didn't see a reason to declare a one-shot variable. > > In C, both 'pointer[integer]' and 'integer[pointer]' are shorthands > for the same thing (you usually write the pointer outside of the [], > but its a nice obfuscation trick to know that you could equally write > (opt & 1)["\n"] for the same results). Either way, those shorthands > are turned by the compiler into *(pointer+offset), that is, treat the > given pointer as an array and dereference the integer offset into that > array (where the integer is scaled by the size of the array element as > determined by the underlying type of the pointer). > > The other thing to know is that string literals are pointers. That > is, "\n" is a 'const char *' pointing to at least the two bytes '\n' > and '\0'. So [opt & 1] is the integer offset that says how far into > that array to read. If opt&1 is 0 (-n was not passed), we want offset > 0, effectively matching %s to the sub-array beginning {'\n','\0'} (in > short form "\n") and printing the trailing newline. If opt&1 is 1 (-n > was passed), we want offset 1, effectively matching %s to the > sub-array beginning {'\0'} (in short form "") and printing nothing. Thanks for the explanation, I see how it was intended to work. > > so I applied your patch and compiled it, > > but it seems to me that something is wrong: > > > > Prepare a link for testing: > > tito at devuan:~/Desktop/SourceCode/busybox_new$ ln -s busybox prova > > > > Busybox with your patch applied: > > $ ./busybox readlink prova > > Segmentation fault > > $ ./busybox readlink -n prova > > busybox(null)$ > > Eww - that wasn't happening for me; but I had > CONFIG_REATURE_READLINK_FOLLOW turned off; when I re-enable that, I'm > seeing the same crash. :( Just for the record I've tested it with # CONFIG_FEATURE_READLINK_FOLLOW is not set > This patch specifically depends on -n mapping to bit 0 (value 1) (as > otherwise, [opt & 1] dereferences out of bounds of the 2-element array > referenced by "\n"). > > Beyond that, I'm not sure why things are behaving differently; maybe > I'm misunderstanding how getopt32() works? > > > > > Real readlink; > > readlink prova > > busybox > > $ readlink -n prova > > busybox$ > > > > Did you intend something like: > > > > printf("%s%c", buf, '\n'*!(opt & 1)); > > No, because that prints an actual NUL byte, which is incorrect. The > point of -n is to print nothing (0 bytes output), not a NUL byte (1 > byte output). > > > > > I did not test if this reduces size. > > Doesn't matter if it reduces size if it is wrong. But I'm still > trying to figure out why CONFIG_REATURE_READLINK_FOLLOW doesn't work > with my patch? I'll have to figure out how to recompile with > debugging symbols left intact to run it under gdb, to get a more > informative stack trace than: > > #0 __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:76 > #1 0x00007ffff7d2e828 in __vfprintf_internal ( > s=0x7ffff7ea3780 <_IO_2_1_stdout_>, format=0x4e09e0 "%s%s", > ap=ap at entry=0x7fffffffda50, mode_flags=mode_flags at entry=0) > at /usr/src/debug/glibc-2.36-9.fc37.x86_64/stdio-common/vfprintf-process-arg.c:397 > #2 0x00007ffff7d228ff in __printf (format=) at printf.c:33 > #3 0x0000000000499a42 in readlink_main () > #4 0x0000000000000000 in ?? () > From rafdev at dinapo.li Tue Apr 18 01:58:12 2023 From: rafdev at dinapo.li (Raffaello D. Di Napoli) Date: Mon, 17 Apr 2023 21:58:12 -0400 Subject: [PATCH v2] readlink: slight size optimization In-Reply-To: <20230417191540.1773858-1-eblake@redhat.com> References: <20230417191540.1773858-1-eblake@redhat.com> Message-ID: <5d721180-03a0-c061-27b4-a9f279c06fa5@dinapo.li> On 4/17/23 15:15, Eric Blake wrote: > Exploit the value of the flag for -n to reduce the size of > readlink_main() (shown here with CONFIG_FEATURE_READLINK_FOLLOW off) > on x86_64. > > function old new delta > readlink_main 121 118 -3 > > Signed-off-by: Eric Blake > > --- > > v2: Add 'make bloatcheck' details > --- > coreutils/readlink.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/coreutils/readlink.c b/coreutils/readlink.c > index 0a9aa957e..83c417e66 100644 > --- a/coreutils/readlink.c > +++ b/coreutils/readlink.c > @@ -88,7 +88,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) > > if (!buf) > return EXIT_FAILURE; > - printf((opt & 1) ? "%s" : "%s\n", buf); > + printf("%s%s", buf, "\n"[opt & 1]); I don?t think this works (as Tito empirically determined). The type of "\n" is char const *, so subscripting that gives you just char, not a pointer. You then pass that char (either '\0' or '\n') to printf, but as %s, so it?s implicitly cast to a pointer inside printf. Passing (char*)'\0' for %s results in "(null)" due to printf being graceful with NULL strings, but there?s no forgiveness for passing (char*)'\n', so you get a segfault. This is exactly the output Tito obtained when he tried out your patch. What you probably meant to do here is + printf("%s%s", buf, "\n" + (opt & 1)); which evaluates to "" or "\n" due to (opt & 1) skipping \n or not. > free(buf); > > fflush_stdout_and_exit_SUCCESS(); > > base-commit: d2b81b3dc2b31d32e1060d3ea8bd998d30a37d8a -- Raf From ksperling at apple.com Tue Apr 18 03:24:34 2023 From: ksperling at apple.com (Karsten Sperling) Date: Tue, 18 Apr 2023 15:24:34 +1200 Subject: [PATCH] ash: use-after-free in bash pattern substitution (resubmit) Message-ID: <186950C9-64AC-43EA-B038-0097DB70AE08@apple.com> Commit daa66ed6 fixed a number of use-after-free bugs in bash pattern substitution, however one "unguarded" STPUTC remained, which is fixed here. Signed-off-by: Karsten Sperling --- shell/ash.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell/ash.c b/shell/ash.c index d2c5c5d50..51b627fcc 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7370,6 +7370,8 @@ subevalvar(char *start, char *str, int strloc, char *restart_detect = stackblock(); if (quotes && *loc == '\\') { STPUTC(CTLESC, expdest); + if (stackblock() != restart_detect) + goto restart; len++; } STPUTC(*loc, expdest); -- 2.39.0 From David.Laight at ACULAB.COM Tue Apr 18 07:48:30 2023 From: David.Laight at ACULAB.COM (David Laight) Date: Tue, 18 Apr 2023 07:48:30 +0000 Subject: [PATCH v2] readlink: slight size optimization In-Reply-To: References: <20230417191540.1773858-1-eblake@redhat.com> <20230417232121.2faaff1c@devuan> Message-ID: <654c94a0591d4df5805a699aec7aaf1d@AcuMS.aculab.com> From: Harald van Dijk > Sent: 17 April 2023 22:44 ... > I am assuming it was intended to be > > printf("%s%s", buf, &"\n"[opt & 1]); That is fine, as is "\n" + (opt & 1) It can also be written: &(opt & 1)["\n"] since [] is commutative in C. Basically x[y] <=> *(x+y) <=> *(y+x) <=> y[x]. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) From eblake at redhat.com Tue Apr 18 12:14:33 2023 From: eblake at redhat.com (Eric Blake) Date: Tue, 18 Apr 2023 07:14:33 -0500 Subject: [PATCH v2] readlink: slight size optimization In-Reply-To: References: <20230417191540.1773858-1-eblake@redhat.com> <20230417232121.2faaff1c@devuan> Message-ID: <3jk5gybi7l7eiahutg72olee5lfj5hk7obklaf7cc24oc3ijvg@wikf2sxuxyid> On Mon, Apr 17, 2023 at 10:43:36PM +0100, Harald van Dijk wrote: > > I am assuming it was intended to be > > printf("%s%s", buf, &"\n"[opt & 1]); Bah, yes, the missing & is the culprit. I don't want to dereference the pointer, I want the adjusted pointer. It might look better as "\n" + (opt & 1), although that's a matter of opinion. > > > I did not test if this reduces size. With the typo fixed (I must have tested one version, then posted a different one), tests pass, and bloatcheck now shows with either corrected spelling: function old new delta readlink_main 121 117 -4 Will post corrected v3. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org From eblake at redhat.com Tue Apr 18 12:17:20 2023 From: eblake at redhat.com (Eric Blake) Date: Tue, 18 Apr 2023 07:17:20 -0500 Subject: [PATCH v3] readlink: slight size optimization Message-ID: <20230418121720.1819152-1-eblake@redhat.com> Exploit the value of the flag for -n to reduce the size of readlink_main() (regardless of the value of CONFIG_FEATURE_READLINK_FOLLOW) on x86_64. function old new delta readlink_main 121 117 -4 Signed-off-by: Eric Blake --- v3: Fix typo that killed the previous version by passing char instead of char* to printf("%s") --- coreutils/readlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/readlink.c b/coreutils/readlink.c index 0a9aa957e..83c417e66 100644 --- a/coreutils/readlink.c +++ b/coreutils/readlink.c @@ -88,7 +88,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) if (!buf) return EXIT_FAILURE; - printf((opt & 1) ? "%s" : "%s\n", buf); + printf("%s%s", buf, "\n"[opt & 1]); free(buf); fflush_stdout_and_exit_SUCCESS(); base-commit: d2b81b3dc2b31d32e1060d3ea8bd998d30a37d8a -- 2.40.0 From eblake at redhat.com Tue Apr 18 12:21:53 2023 From: eblake at redhat.com (Eric Blake) Date: Tue, 18 Apr 2023 07:21:53 -0500 Subject: [PATCH v3] readlink: slight size optimization In-Reply-To: <20230418121720.1819152-1-eblake@redhat.com> References: <20230418121720.1819152-1-eblake@redhat.com> Message-ID: On Tue, Apr 18, 2023 at 07:17:20AM -0500, Eric Blake wrote: > Exploit the value of the flag for -n to reduce the size of > readlink_main() (regardless of the value of > CONFIG_FEATURE_READLINK_FOLLOW) on x86_64. > > function old new delta > readlink_main 121 117 -4 > > Signed-off-by: Eric Blake > > --- > > v3: Fix typo that killed the previous version by passing char instead > of char* to printf("%s") Bah. Hit send before save. v4 coming up. :( Not my morning at the keyboard. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org From eblake at redhat.com Tue Apr 18 12:22:37 2023 From: eblake at redhat.com (Eric Blake) Date: Tue, 18 Apr 2023 07:22:37 -0500 Subject: [PATCH v4] readlink: slight size optimization Message-ID: <20230418122237.1820276-1-eblake@redhat.com> Exploit the value of the flag for -n to reduce the size of readlink_main() (regardless of the value of CONFIG_FEATURE_READLINK_FOLLOW) on x86_64. function old new delta readlink_main 121 117 -4 Signed-off-by: Eric Blake --- v4: Actually fix typo that killed the previous version by passing char instead of char* to printf("%s") --- coreutils/readlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/readlink.c b/coreutils/readlink.c index 0a9aa957e..8c4113cee 100644 --- a/coreutils/readlink.c +++ b/coreutils/readlink.c @@ -88,7 +88,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) if (!buf) return EXIT_FAILURE; - printf((opt & 1) ? "%s" : "%s\n", buf); + printf("%s%s", buf, "\n" + (opt & 1)); free(buf); fflush_stdout_and_exit_SUCCESS(); base-commit: d2b81b3dc2b31d32e1060d3ea8bd998d30a37d8a -- 2.40.0 From raphael.melotte at mind.be Wed Apr 19 12:39:43 2023 From: raphael.melotte at mind.be (=?UTF-8?q?Rapha=C3=ABl=20M=C3=A9lotte?=) Date: Wed, 19 Apr 2023 14:39:43 +0200 Subject: [PATCH] seedrng: fix getrandom() detection for non-glibc libc Message-ID: <20230419123943.3075709-1-raphael.melotte@mind.be> glibc <= 2.24 does not provide getrandom(). A check for it has been added in 200a9669fbf6f06894e4243cccc9fc11a1a6073a and fixed in cb57abb46f06f4ede8d9ccbdaac67377fdf416cf. However, building with a libc other than glibc can lead to the same problem as not every other libc has getrandom() either: - uClibc provides it from v1.0.2 onwards, but requires to define _GNU_SOURCE (all versions - we already define it by default), and stddef to be included first (when using uClibc < 1.0.35 - we already include it through libbb.h). - musl libc has getrandom(), but only from version 1.1.20 onwards. As musl does not provide __MUSL__ or version information, it's not possible to check for it like we did for glibc. All of this makes it difficult (or impossible in case of musl) to check what we need to do to have getrandom() based on each libc versions. On top of that, getrandom() is also not available on older kernels. As an example, when using a 3.10 kernel with uClibc 1.0.26, getrandom() is declared so compiling works, but it fails at link time because getrandom() is not defined. To make it easier, take a similar approach to what was done for the crypt library: try to build a sample program to see if we have getrandom(). Based on the new Makefile variable, we now either use the libc-provided getrandom() when it's available, or use our own implementation when it's not (like it was the case already for glibc < 2.25). This should fix compiling with many libc/kernel combinations. Signed-off-by: Rapha?l M?lotte --- Note that I was not able to test every single combination, but I could confirm it builds successfully for: uClibc 10.0.24, linux headers 3.10 (libc getrandom NOT used) uClibc 1.0.36, linux headers 4.9 (libc getrandom used) musl 1.1.16, linux headers 4.12 (libc getrandom NOT used) musl 1.2.1, linux headers (libc getrandom used) glibc 2.25, linux headers 4.10 (libc getrandom used) Makefile.flags | 7 +++++++ miscutils/seedrng.c | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Makefile.flags b/Makefile.flags index 1cec5ba20..88c11862f 100644 --- a/Makefile.flags +++ b/Makefile.flags @@ -161,6 +161,13 @@ ifeq ($(RT_AVAILABLE),y) LDLIBS += rt endif +# Not all libc versions have getrandom, so check for it. +HAVE_GETRANDOM := $(shell printf '#include \n#include \nint main(void){char buf[256];\ngetrandom(buf,sizeof(buf),GRND_NONBLOCK);}' >bb_libtest.c; $(CC) $(CFLAGS) $(CFLAGS_busybox) -D_GNU_SOURCE -o /dev/null bb_libtest.c >/dev/null 2>&1 && echo "y"; rm bb_libtest.c) + +ifeq ($(HAVE_GETRANDOM),y) +CFLAGS += -DHAVE_GETRANDOM +endif + # libpam may use libpthread, libdl and/or libaudit. # On some platforms that requires an explicit -lpthread, -ldl, -laudit. # However, on *other platforms* it fails when some of those flags diff --git a/miscutils/seedrng.c b/miscutils/seedrng.c index 3bf6e2ea7..2f1e18c32 100644 --- a/miscutils/seedrng.c +++ b/miscutils/seedrng.c @@ -44,8 +44,10 @@ #include #include -/* Fix up glibc <= 2.24 not having getrandom() */ -#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 24 +/* Fix up some libc (e.g. glibc <= 2.24) not having getrandom() */ +#if defined HAVE_GETRANDOM +#include +#else /* No getrandom */ #include static ssize_t getrandom(void *buffer, size_t length, unsigned flags) { @@ -56,8 +58,6 @@ static ssize_t getrandom(void *buffer, size_t length, unsigned flags) return -1; # endif } -#else -#include #endif /* Apparently some headers don't ship with this yet. */ -- 2.39.1 From explorer09 at gmail.com Wed Apr 19 12:52:23 2023 From: explorer09 at gmail.com (Kang-Che Sung) Date: Wed, 19 Apr 2023 20:52:23 +0800 Subject: [PATCH] seedrng: fix getrandom() detection for non-glibc libc In-Reply-To: <20230419123943.3075709-1-raphael.melotte@mind.be> References: <20230419123943.3075709-1-raphael.melotte@mind.be> Message-ID: Just my two cents... On Wednesday, April 19, 2023, Rapha?l M?lotte wrote: > +# Not all libc versions have getrandom, so check for it. > +HAVE_GETRANDOM := $(shell printf '#include \n#include \nint main(void){char buf[256];\ngetrandom(buf,sizeof(buf),GRND_NONBLOCK);}' >bb_libtest.c; $(CC) $(CFLAGS) $(CFLAGS_busybox) -D_GNU_SOURCE -o /dev/null bb_libtest.c >/dev/null 2>&1 && echo "y"; rm bb_libtest.c) How about putting the define line '#define _GNU_SOURCE' into bb_libtest.c ? I don't like defining the feature test macros externally in '-D' options. -------------- next part -------------- An HTML attachment was scrubbed... URL: From raphael.melotte at mind.be Wed Apr 19 13:17:19 2023 From: raphael.melotte at mind.be (=?UTF-8?B?UmFwaGHDq2wgTcOpbG90dGU=?=) Date: Wed, 19 Apr 2023 15:17:19 +0200 Subject: [PATCH] seedrng: fix getrandom() detection for non-glibc libc In-Reply-To: References: <20230419123943.3075709-1-raphael.melotte@mind.be> Message-ID: <6b339111-5267-b29a-2bb8-a433a60483e4@mind.be> On 4/19/23 14:52, Kang-Che Sung wrote: > Just my two cents... > > On Wednesday, April 19, 2023, Rapha?l M?lotte > wrote: > > +# Not all libc versions have getrandom, so check for it. > > +HAVE_GETRANDOM := $(shell printf '#include \n#include \nint main(void){char buf[256];\ngetrandom(buf,sizeof(buf),GRND_NONBLOCK);}' >bb_libtest.c; $(CC) $(CFLAGS) $(CFLAGS_busybox) -D_GNU_SOURCE -o /dev/null bb_libtest.c >/dev/null 2>&1 && echo "y"; rm bb_libtest.c) > > How about putting the define line '#define _GNU_SOURCE' into bb_libtest.c ? I don't like defining the feature test macros externally in '-D' options. Sure, it's only added here for the test, either should work. From thomas at devoogdt.com Wed Apr 19 20:24:13 2023 From: thomas at devoogdt.com (Thomas Devoogdt) Date: Wed, 19 Apr 2023 22:24:13 +0200 Subject: [PATCH] seedrng: fix getrandom() detection for non-glibc libc Message-ID: Hi, About: >> HAVE_GETRANDOM := $(shell printf '#include \n#include \nint main(void){char buf[256];\ngetrandom(buf,sizeof(buf),GRND_NONBLOCK);}' >bb_libtest.c; $(CC) $(CFLAGS) $(CFLAGS_busybox) -D_GNU_SOURCE -o /dev/null Is it a good idea to have GRND_NONBLOCK in that check? What if it's not defined, but getrandom() is, then HAVE_GETRANDOM might incorrectly be false? We do anyway define it in seedrng.c if needed. Kind regards, Thomas From raphael.melotte at mind.be Wed Apr 19 21:01:54 2023 From: raphael.melotte at mind.be (=?ISO-8859-1?Q?Rapha=EBl_M=E9lotte?=) Date: Wed, 19 Apr 2023 23:01:54 +0200 Subject: [PATCH] seedrng: fix getrandom() detection for non-glibc libc In-Reply-To: References: Message-ID: <74A528DD-FAD1-4D07-A5DD-E010F7796D21@mind.be> Hello, On 19 April 2023 22:24:13 CEST, Thomas Devoogdt wrote: >Is it a good idea to have GRND_NONBLOCK in that check? What if it's >not defined, but getrandom() is, then HAVE_GETRANDOM might incorrectly >be false? >We do anyway define it in seedrng.c if needed. Indeed, maybe it should be removed. Kind regards, Rapha?l From steffen at sdaoden.eu Wed Apr 19 22:35:14 2023 From: steffen at sdaoden.eu (Steffen Nurpmeso) Date: Thu, 20 Apr 2023 00:35:14 +0200 Subject: [PATCH] seedrng: fix getrandom() detection for non-glibc libc In-Reply-To: References: Message-ID: <20230419223514.i6BoH%steffen@sdaoden.eu> Thomas Devoogdt wrote in : |About: |>> HAVE_GETRANDOM := $(shell printf '#include \n#include \ |>> \nint main(void){char buf[256];\ngetrandom(buf,sizeof(buf)\ |>> ,GRND_NONBLOCK);}' >bb_libtest.c; $(CC) $(CFLAGS) $(CFLAGS_busybox) \ |>> -D_GNU_SOURCE -o /dev/null | |Is it a good idea to have GRND_NONBLOCK in that check? What if it's |not defined, but getrandom() is, then HAVE_GETRANDOM might incorrectly |be false? |We do anyway define it in seedrng.c if needed. Heck, this entire thing is grazy from the start. The kernel random code mutilates input coming via the /dev/*random devices, instead of treating that as just the same regular input as through ioctl or whatever (i am too lazy to look again). They should all simply reject going that route along the random maintainer, and insist on using # Load random seed /bin/cat /var/lib/urandom/seed > /dev/urandom like my Linux distribution does (even though *i* repeatedly prodded using my entropy thing, then that Friday the 13th thing for years, before i had to go, mind you). Moreover, even GLibC 2.36 / current manual pages still does not document the other flag that the busybox applet uses. Even on super-async modern boot, some things have to be synchronized, why not random. (If i recall correctly, people knowing about systemd even said that is done, last time i said that, hm.) Just my off-topic one cent. seedrng.c is an intellectually penetrated piece of software. Having said that, the current implementation as it is here is surely wrong, since the fallback getrandom returns ENOSYS, instead of setting errno to ENOSYS? 200a9669fbf6f06894e4243cccc9fc11a1a6073a as of -04-10. --steffen | |Der Kragenbaer, The moon bear, |der holt sich munter he cheerfully and one by one |einen nach dem anderen runter wa.ks himself off |(By Robert Gernhardt) From thomas at devoogdt.com Thu Apr 20 04:41:57 2023 From: thomas at devoogdt.com (Thomas Devoogdt) Date: Thu, 20 Apr 2023 06:41:57 +0200 Subject: [PATCH] seedrng: fix getrandom() detection for non-glibc libc Message-ID: Hi, I can't follow everything in your mail, but about: >> Having said that, the current implementation as it is here is >> surely wrong, since the fallback getrandom returns ENOSYS, instead >> of setting errno to ENOSYS? >> 200a9669fbf6f06894e4243cccc9fc11a1a6073a as of -04-10. Already fixed here: https://git.busybox.net/busybox/commit/?id=cb57abb46f06f4ede8d9ccbdaac67377fdf416cf Kind regards, Thomas -------------- next part -------------- An HTML attachment was scrubbed... URL: From uwe at kleine-koenig.org Thu Apr 20 12:13:17 2023 From: uwe at kleine-koenig.org (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=) Date: Thu, 20 Apr 2023 14:13:17 +0200 Subject: [PATCH] build system: Make it possible to build with 64bit time_t Message-ID: <20230420121317.444127-1-uwe@kleine-koenig.org> From: Uwe Kleine-K?nig On most 32bit architectures time_t (and a few other time related types) are a signed 32bit wide integer type. As a consequence they can only represent dates between Fri Dec 13 08:45:52 PM UTC 1901 (-0x80000000 seconds before Jan 1 1970) and Tue Jan 19 03:14:07 AM UTC 2038 (0x7fffffff seconds after Jan 1 1970). Given that some machines that are built today have an expected lifetime of >15 years, this needs to be extended. To to that, define the cpp symbol _TIME_BITS to 64 which results in some magic in glibc to make time_t (and the few other time related types) 64 bit wide. This new switch CONFIG_TIME64 is in the spirit of CONFIG_LFS and only expected to have the expected effect with glibc. On musl for examples time_t already defaults to 64bit wide types. --- Config.in | 10 ++++++++++ Makefile.flags | 1 + 2 files changed, 11 insertions(+) diff --git a/Config.in b/Config.in index a98a8b15b854..214eba54630e 100644 --- a/Config.in +++ b/Config.in @@ -108,6 +108,16 @@ config LFS programs that can benefit from large file support include dd, gzip, cp, mount, tar. +config TIME64 + bool "Support 64bit wide time types" + default y + depends on LFS + help + Make times later than 2038 representable for several libc syscalls + (stat, clk_gettime etc.). Note this switch is specific to glibc and has + no effect on platforms that already use 64bit wide time types (i.e. all + 64bit archs and some selected 32bit archs (currently riscv and x32)). + config PAM bool "Support PAM (Pluggable Authentication Modules)" default n diff --git a/Makefile.flags b/Makefile.flags index c34356230a9f..e17defbd00f9 100644 --- a/Makefile.flags +++ b/Makefile.flags @@ -15,6 +15,7 @@ CPPFLAGS += \ -include include/autoconf.h \ -D_GNU_SOURCE -DNDEBUG \ $(if $(CONFIG_LFS),-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64) \ + $(if $(CONFIG_TIME64),-D_TIME_BITS=64) \ -DBB_VER=$(squote)$(quote)$(BB_VER)$(quote)$(squote) CFLAGS += $(call cc-option,-Wall,) base-commit: e512aeb0fb3c585948ae6517cfdf4a53cf99774d -- 2.39.2 From steffen at sdaoden.eu Thu Apr 20 12:58:47 2023 From: steffen at sdaoden.eu (Steffen Nurpmeso) Date: Thu, 20 Apr 2023 14:58:47 +0200 Subject: [PATCH] seedrng: fix getrandom() detection for non-glibc libc In-Reply-To: References: Message-ID: <20230420125847.vENuU%steffen@sdaoden.eu> Thomas Devoogdt wrote in : |I can't follow everything in your mail, |but about: | |>> Having said that, the current implementation as it is here is |>> surely wrong, since the fallback getrandom returns ENOSYS, instead |>> of setting errno to ENOSYS? |>> 200a9669fbf6f06894e4243cccc9fc11a1a6073a as of -04-10. | |Already fixed here: |https://git.busybox.net/busybox/commit/?id=cb57abb46f06f4ede8d9ccbdaac67\ |377fdf416cf Ok. I am out of bandwidth and did not update, yes. --steffen | |Der Kragenbaer, The moon bear, |der holt sich munter he cheerfully and one by one |einen nach dem anderen runter wa.ks himself off |(By Robert Gernhardt) From dario.binacchi at amarulasolutions.com Thu Apr 20 19:35:33 2023 From: dario.binacchi at amarulasolutions.com (Dario Binacchi) Date: Thu, 20 Apr 2023 21:35:33 +0200 Subject: [RFC PATCH] ip link: support for the CAN netlink Message-ID: <20230420193533.1963524-1-dario.binacchi@amarulasolutions.com> I developed this application to test the Linux kernel series [1]. As described in the cover letter I could not use the iproute2 package since the microcontroller is without MMU. cc: Marc Kleine-Budde [1] https://marc.info/?l=linux-netdev&m=167999323611710&w=2 Signed-off-by: Dario Binacchi --- configs/TEST_nommu_defconfig | 1 + networking/ip.c | 84 ++++++++++ networking/libiproute/iplink.c | 298 ++++++++++++++++++++++++++++++++- 3 files changed, 374 insertions(+), 9 deletions(-) diff --git a/configs/TEST_nommu_defconfig b/configs/TEST_nommu_defconfig index 415f5a8027f9..fa3e9632622a 100644 --- a/configs/TEST_nommu_defconfig +++ b/configs/TEST_nommu_defconfig @@ -703,6 +703,7 @@ CONFIG_FEATURE_INETD_RPC=y CONFIG_IP=y CONFIG_FEATURE_IP_ADDRESS=y CONFIG_FEATURE_IP_LINK=y +CONFIG_FEATURE_IP_LINK_CAN=y CONFIG_FEATURE_IP_ROUTE=y CONFIG_FEATURE_IP_TUNNEL=y CONFIG_FEATURE_IP_RULE=y diff --git a/networking/ip.c b/networking/ip.c index 7c320869958a..4959e9f25288 100644 --- a/networking/ip.c +++ b/networking/ip.c @@ -32,6 +32,14 @@ //config: help //config: Short form of "ip link" //config: +//config:config IPLINK_CAN +//config: bool "iplink for CAN (4.6 kb)" +//config: default n +//config: depends on IPLINK +//config: select FEATURE_IP_LINK_CAN +//config: help +//config: Short form of "ip link" for CAN +//config: //config:config IPROUTE //config: bool "iproute (15 kb)" //config: default y @@ -74,6 +82,13 @@ //config: help //config: Configure network devices with "ip". //config: +//config:config FEATURE_IP_LINK_CAN +//config: bool "ip link can" +//config: default n +//config: depends on IP_LINK_CAN +//config: help +//config: Configure CAN devices with "ip". +//config: //config:config FEATURE_IP_ROUTE //config: bool "ip route" //config: default y @@ -122,6 +137,7 @@ //applet:IF_IP( APPLET_NOEXEC(ip , ip , BB_DIR_SBIN, BB_SUID_DROP, ip )) //applet:IF_IPADDR( APPLET_NOEXEC(ipaddr , ipaddr , BB_DIR_SBIN, BB_SUID_DROP, ipaddr )) //applet:IF_IPLINK( APPLET_NOEXEC(iplink , iplink , BB_DIR_SBIN, BB_SUID_DROP, iplink )) +//applet:IF_IPLINK_CAN(APPLET_NOEXEC(iplinkcan , iplinkcan , BB_DIR_SBIN, BB_SUID_DROP, iplinkcan)) //applet:IF_IPROUTE( APPLET_NOEXEC(iproute , iproute , BB_DIR_SBIN, BB_SUID_DROP, iproute )) //applet:IF_IPRULE( APPLET_NOEXEC(iprule , iprule , BB_DIR_SBIN, BB_SUID_DROP, iprule )) //applet:IF_IPTUNNEL(APPLET_NOEXEC(iptunnel, iptunnel, BB_DIR_SBIN, BB_SUID_DROP, iptunnel)) @@ -130,6 +146,7 @@ //kbuild:lib-$(CONFIG_IP) += ip.o //kbuild:lib-$(CONFIG_IPADDR) += ip.o //kbuild:lib-$(CONFIG_IPLINK) += ip.o +//kbuild:lib-$(CONFIG_IPLINK_CAN) += ip.o //kbuild:lib-$(CONFIG_IPROUTE) += ip.o //kbuild:lib-$(CONFIG_IPRULE) += ip.o //kbuild:lib-$(CONFIG_IPTUNNEL) += ip.o @@ -149,10 +166,16 @@ //usage: "ipaddr show|flush [dev IFACE] [scope SCOPE] [to PREFIX] [label PATTERN]" //usage: //--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 +//usage:#if ENABLE_FEATURE_IP_LINK_CAN +//usage:#define iplink_type_usage "\n [type TYPE ARGS]" +//usage:#else +//usage:#define iplink_type_usage "" +//usage:#endif //usage:#define iplink_trivial_usage //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" //usage: " [master IFACE | nomaster] [netns PID]" +//usage: IF_FEATURE_IP_LINK(iplink_type_usage) // * short help shows only "set" command, long help continues (with just one "\n") // * and shows all other commands: //usage:#define iplink_full_usage "\n" @@ -207,6 +230,59 @@ // bond_slave | ipvlan | geneve | bridge_slave | vrf } //usage: //--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 +//usage:#define iplinkcan_trivial_usage +//usage: /*Usage:iplinkcan*/"set DEVICE type can" +//usage:#define iplinkcan_full_usage "\n\n" +//usage: " [bitrate BITRATE [sample-point SAMPLE-POINT]] |\n" +//usage: " [tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1\n" +//usage: " phase-seg2 PHASE-SEG2 [sjw SJW]]\n" +//usage: "\n" +//usage: " [dbitrate BITRATE [dsample-point SAMPLE-POINT]] |\n" +//usage: " [dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1\n" +//usage: " dphase-seg2 PHASE-SEG2 [dsjw SJW]]\n" +//usage: "\n" +//usage: " [loopback on|off] [listen-only on|off] [triple-sampling on|off]\n" +//usage: " [one-shot on|off] [berr-reporting on|off]\n" +//usage: " [fd on|off] [fd-non-iso on|off] [presume-ack on|off]\n" +//usage: "\n" +//usage: " [restart-ms TIME-MS] [restart]\n" +//usage: "\n" +//usage: " [termination 0..65535]\n" +//usage: +//upstream man ip-link-can: +//Usage: ip link set DEVICE type can +// [ bitrate BITRATE [ sample-point SAMPLE-POINT] ] | +// [ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1 +// phase-seg2 PHASE-SEG2 [ sjw SJW ] ] +// +// [ dbitrate BITRATE [ dsample-point SAMPLE-POINT] ] | +// [ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1 +// dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ] +// +// [ loopback { on | off } ] +// [ listen-only { on | off } ] +// [ triple-sampling { on | off } ] +// [ one-shot { on | off } ] +// [ berr-reporting { on | off } ] +// [ fd { on | off } ] +// [ fd-non-iso { on | off } ] +// [ presume-ack { on | off } ] +// +// [ restart-ms TIME-MS ] +// [ restart ] +// +// [ termination { 0..65535 } ] +// +// Where: BITRATE := { 1..1000000 } +// SAMPLE-POINT := { 0.000..0.999 } +// TQ := { NUMBER } +// PROP-SEG := { 1..8 } +// PHASE-SEG1 := { 1..8 } +// PHASE-SEG2 := { 1..8 } +// SJW := { 1..4 } +// RESTART-MS := { 0 | NUMBER } +//usage: +//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 //usage:#define iproute_trivial_usage //usage: "list|flush|add|del|change|append|replace|test ROUTE" //usage:#define iproute_full_usage "\n\n" @@ -327,6 +403,7 @@ typedef int FAST_FUNC (*ip_func_ptr_t)(char**); #if ENABLE_IPADDR \ || ENABLE_IPLINK \ + || ENABLE_IPLINK_CAN \ || ENABLE_IPROUTE \ || ENABLE_IPRULE \ || ENABLE_IPTUNNEL \ @@ -352,6 +429,13 @@ int iplink_main(int argc UNUSED_PARAM, char **argv) return ip_do(do_iplink, argv); } #endif +#if ENABLE_IPLINK_CAN +int iplinkcan_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int iplinkcan_main(int argc UNUSED_PARAM, char **argv) +{ + return ip_do(do_iplink, argv); +} +#endif #if ENABLE_IPROUTE int iproute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int iproute_main(int argc UNUSED_PARAM, char **argv) diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index 68d1990445fe..f97169714d0f 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c @@ -11,10 +11,17 @@ #include #include +#include #include "ip_common.h" /* #include "libbb.h" is inside */ #include "rt_names.h" #include "utils.h" +#if ENABLE_FEATURE_IP_LINK_CAN +#define ENABLE_FEATURE_IP_LINK_IFACE 1 +#else +#define ENABLE_FEATURE_IP_LINK_IFACE 0 +#endif + #undef ETH_P_8021AD #define ETH_P_8021AD 0x88A8 #undef VLAN_FLAG_REORDER_HDR @@ -28,6 +35,11 @@ #undef IFLA_VLAN_PROTOCOL #define IFLA_VLAN_PROTOCOL 5 +#ifndef NLMSG_TAIL +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) +#endif + #ifndef IFLA_LINKINFO # define IFLA_LINKINFO 18 # define IFLA_INFO_KIND 1 @@ -55,6 +67,13 @@ struct ifla_vlan_flags { #define str_on_off "on\0""off\0" +enum { + PARM_on = 0, + PARM_off +}; + +typedef void FAST_FUNC(*ip_type_set_func_ptr_t)(char*, char**); + /* Exits on error */ static int get_ctl_fd(void) { @@ -241,10 +260,261 @@ static void die_must_be_on_off(const char *msg) bb_error_msg_and_die("argument of \"%s\" must be \"on\" or \"off\"", msg); } +#if ENABLE_FEATURE_IP_LINK_CAN +static float FAST_FUNC get_float(char *arg, const char *errmsg) +{ + float ret; + char *ptr; + + if (!arg || !*arg) + invarg_1_to_2(arg, errmsg); /* does not return */ + + ret = strtof(arg, &ptr); + if (!ptr || ptr == arg || *ptr) + invarg_1_to_2(arg, errmsg); /* does not return */ + + return ret; +} + +static void do_set_can(char *dev, char **argv) +{ + struct can_bittiming bt = {}, dbt = {}; + struct can_ctrlmode cm = {}; + char *keyword; + static const char keywords[] ALIGN1 = + "bitrate\0""sample-point\0""tq\0" + "prop-seg\0""phase-seg1\0""phase-seg2\0""sjw\0" + "dbitrate\0""dsample-point\0""dtq\0" + "dprop-seg\0""dphase-seg1\0""dphase-seg2\0""dsjw\0" + "loopback\0""listen-only\0""triple-sampling\0" + "one-shot\0""berr-reporting\0" + "fd\0""fd-non-iso\0""presume-ack\0" + "cc-len8-dlc\0""restart\0""restart-ms\0" + "termination\0"; + enum { ARG_bitrate = 0, ARG_sample_point, ARG_tq, + ARG_prop_seg, ARG_phase_seg1, ARG_phase_seg2, ARG_sjw, + ARG_dbitrate, ARG_dsample_point, ARG_dtq, + ARG_dprop_seg, ARG_dphase_seg1, ARG_dphase_seg2, ARG_dsjw, + ARG_loopback, ARG_listen_only, ARG_triple_sampling, + ARG_one_shot, ARG_berr_reporting, + ARG_fd, ARG_fd_non_iso, ARG_presume_ack, + ARG_cc_len8_dlc, ARG_restart, ARG_restart_ms, + ARG_termination }; + struct rtnl_handle rth; + struct { + struct nlmsghdr n; + struct ifinfomsg i; + char buf[1024]; + } req; + size_t dev_len; + struct rtattr *linkinfo, *data; + smalluint key, param; + + memset(&req, 0, sizeof(req)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_NEWLINK; + req.i.ifi_family = preferred_family; + xrtnl_open(&rth); + req.i.ifi_index = xll_name_to_index(dev); + dev_len = strlen(dev); + if (dev_len < 2 || dev_len > IFNAMSIZ) + invarg_1_to_2(dev, "dev"); + + addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, dev_len); + linkinfo = NLMSG_TAIL(&req.n); + addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); + addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (void *)"can", + strlen("can")); + data = NLMSG_TAIL(&req.n); + addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0); + while (*argv) { + key = index_in_substrings(keywords, *argv); + keyword = *argv; + //printf("%s: key: %d, *argv: %s\n", __func__, key, *argv); + switch (key) { + case ARG_bitrate: + case ARG_tq: + case ARG_prop_seg: + case ARG_phase_seg1: + case ARG_phase_seg2: + case ARG_sjw: { + __u32 *val; + + NEXT_ARG(); + if (key == ARG_bitrate) + val = &bt.bitrate; + else if (key == ARG_tq) + val = &bt.tq; + else if (key == ARG_prop_seg) + val = &bt.prop_seg; + else if (key == ARG_phase_seg1) + val = &bt.phase_seg1; + else if (key == ARG_phase_seg2) + val = &bt.phase_seg2; + else + val = &bt.sjw; + + *val = get_u32(*argv, keyword); + break; + } + case ARG_sample_point: { + float sp; + + NEXT_ARG(); + sp = get_float(*argv, keyword); + bt.sample_point = (__u32)(sp * 1000); + break; + } + case ARG_dbitrate: + case ARG_dtq: + case ARG_dprop_seg: + case ARG_dphase_seg1: + case ARG_dphase_seg2: + case ARG_dsjw: { + __u32 *val; + + NEXT_ARG(); + if (key == ARG_dbitrate) + val = &dbt.bitrate; + else if (key == ARG_dtq) + val = &dbt.tq; + else if (key == ARG_dprop_seg) + val = &dbt.prop_seg; + else if (key == ARG_dphase_seg1) + val = &dbt.phase_seg1; + else if (key == ARG_dphase_seg2) + val = &dbt.phase_seg2; + else + val = &dbt.sjw; + + *val = get_u32(*argv, keyword); + break; + } + case ARG_dsample_point: { + float sp; + + NEXT_ARG(); + sp = get_float(*argv, keyword); + dbt.sample_point = (__u32)(sp * 1000); + break; + } + case ARG_loopback: + case ARG_listen_only: + case ARG_triple_sampling: + case ARG_one_shot: + case ARG_berr_reporting: + case ARG_fd: + case ARG_fd_non_iso: + case ARG_presume_ack: + case ARG_cc_len8_dlc: { + __u32 flag = 0; + + NEXT_ARG(); + param = index_in_strings(str_on_off, *argv); + if (param < 0) + die_must_be_on_off(keyword); + + if (key == ARG_loopback) + flag = CAN_CTRLMODE_LOOPBACK; + else if (key == ARG_listen_only) + flag = CAN_CTRLMODE_LISTENONLY; + else if (key == ARG_triple_sampling) + flag = CAN_CTRLMODE_3_SAMPLES; + else if (key == ARG_one_shot) + flag = CAN_CTRLMODE_ONE_SHOT; + else if (key == ARG_berr_reporting) + flag = CAN_CTRLMODE_BERR_REPORTING; + else if (key == ARG_fd) + flag = CAN_CTRLMODE_FD; + else if (key == ARG_fd_non_iso) + flag = CAN_CTRLMODE_FD_NON_ISO; + else if (key == ARG_presume_ack) + flag = CAN_CTRLMODE_PRESUME_ACK; + else +#if defined(CAN_CTRLMODE_CC_LEN8_DLC) + flag = CAN_CTRLMODE_CC_LEN8_DLC; +#else + die_must_be_on_off(keyword); +#endif + cm.mask |= flag; + if (param == PARM_on) + cm.flags |= flag; + + break; + } + case ARG_restart: { + __u32 val = 1; + + NEXT_ARG(); + addattr_l(&req.n, sizeof(req), IFLA_CAN_RESTART, &val, sizeof(val)); + break; + } + case ARG_restart_ms: { + __u32 val; + + NEXT_ARG(); + val = get_u32(*argv, keyword); + addattr_l(&req.n, sizeof(req), IFLA_CAN_RESTART_MS, &val, sizeof(val)); + break; + } + case ARG_termination: { + __u16 val; + + NEXT_ARG(); + val = get_u16(*argv, keyword); + addattr_l(&req.n, sizeof(req), IFLA_CAN_TERMINATION, &val, sizeof(val)); + break; + } + default: + break; + } + + argv++; + } + + if (bt.bitrate || bt.tq) + addattr_l(&req.n, sizeof(req), IFLA_CAN_BITTIMING, &bt, sizeof(bt)); + + if (cm.mask) + addattr_l(&req.n, sizeof(req), IFLA_CAN_CTRLMODE, &cm, sizeof(cm)); + + data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; + linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; + + if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) + xfunc_die(); +} +#endif + +#if ENABLE_FEATURE_IP_LINK_IFACE +static void do_set_iface(char *type, char *dev, char **argv) +{ + static const char keywords[] ALIGN1 = "" + IF_FEATURE_IP_LINK_CAN("can\0") + ; + static const ip_type_set_func_ptr_t funcs[] ALIGN_PTR = { + IF_FEATURE_IP_LINK_CAN(do_set_can,) + }; + ip_type_set_func_ptr_t func; + int key; + + key = index_in_substrings(keywords, type); + if (key < 0) + return; + func = funcs[key]; + func(dev, argv); +} +#endif + /* Return value becomes exitcode. It's okay to not return at all */ static int do_set(char **argv) { char *dev = NULL; +#if ENABLE_FEATURE_IP_LINK_IFACE + char *type = NULL; +#endif uint32_t mask = 0; uint32_t flags = 0; int qlen = -1; @@ -261,18 +531,24 @@ static int do_set(char **argv) "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" "arp\0""promisc\0""address\0""netns\0" "master\0""nomaster\0" +#if ENABLE_FEATURE_IP_LINK_IFACE + "type\0" +#endif "dev\0" /* must be last */; enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, ARG_arp, ARG_promisc, ARG_addr, ARG_netns, ARG_master, ARG_nomaster, +#if ENABLE_FEATURE_IP_LINK_IFACE + ARG_type, +#endif ARG_dev }; - enum { PARM_on = 0, PARM_off }; smalluint key; while (*argv) { /* substring search ensures that e.g. "addr" and "address" * are both accepted */ key = index_in_substrings(keywords, *argv); + //printf("%s: key: %d, *argv: %s\n", __func__, key, *argv); if (key == ARG_up) { mask |= IFF_UP; flags |= IFF_UP; @@ -304,6 +580,13 @@ static int do_set(char **argv) } else if (key == ARG_netns) { NEXT_ARG(); netns = get_unsigned(*argv, "netns"); +#if ENABLE_FEATURE_IP_LINK_IFACE + } else if (key == ARG_type) { + NEXT_ARG(); + type = *argv; + argv++; + break; +#endif } else if (key >= ARG_dev) { /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */ if (key == ARG_dev) { @@ -311,6 +594,7 @@ static int do_set(char **argv) } if (dev) duparg2("dev", *argv); + dev = *argv; } else { /* "on|off" options */ @@ -496,6 +780,10 @@ static int do_set(char **argv) } if (mask) do_chflags(dev, flags, mask); +#if ENABLE_FEATURE_IP_LINK_IFACE + if (type) + do_set_iface(type, dev, argv); +#endif return 0; } @@ -531,10 +819,6 @@ static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size) PROTO_8021Q = 0, PROTO_8021AD, }; - enum { - PARM_on = 0, - PARM_off - }; int arg; uint16_t id, proto; struct ifla_vlan_flags flags = {}; @@ -610,10 +894,6 @@ static void vrf_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size) addattr_l(n, size, IFLA_VRF_TABLE, &table, sizeof(table)); } -#ifndef NLMSG_TAIL -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) -#endif /* Return value becomes exitcode. It's okay to not return at all */ static int do_add_or_delete(char **argv, const unsigned rtm) { -- 2.32.0 From harald at gigawatt.nl Mon Apr 24 21:05:42 2023 From: harald at gigawatt.nl (Harald van Dijk) Date: Mon, 24 Apr 2023 22:05:42 +0100 Subject: [PATCH v4] readlink: slight size optimization In-Reply-To: <20230418122237.1820276-1-eblake@redhat.com> References: <20230418122237.1820276-1-eblake@redhat.com> Message-ID: <7045c162-75e6-8dcf-3aae-311d13d7c4fa@gigawatt.nl> On 18/04/2023 13:22, Eric Blake wrote: > Exploit the value of the flag for -n to reduce the size of > readlink_main() (regardless of the value of > CONFIG_FEATURE_READLINK_FOLLOW) on x86_64. > > function old new delta > readlink_main 121 117 -4 > > Signed-off-by: Eric Blake > > --- > > v4: Actually fix typo that killed the previous version by passing char > instead of char* to printf("%s") > --- > coreutils/readlink.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/coreutils/readlink.c b/coreutils/readlink.c > index 0a9aa957e..8c4113cee 100644 > --- a/coreutils/readlink.c > +++ b/coreutils/readlink.c > @@ -88,7 +88,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) > > if (!buf) > return EXIT_FAILURE; > - printf((opt & 1) ? "%s" : "%s\n", buf); > + printf("%s%s", buf, "\n" + (opt & 1)); > free(buf); > > fflush_stdout_and_exit_SUCCESS(); > > base-commit: d2b81b3dc2b31d32e1060d3ea8bd998d30a37d8a This results in another instance of a warning that is meant to be suppressed, but is not suppressed, when building with CC=clang-16 (or any other name for clang other than exactly "clang"): coreutils/readlink.c:91:27: warning: adding 'unsigned int' to a string does not append to the string [-Wstring-plus-int] printf("%s%s", buf, "\n" + (opt & 1)); ~~~~~^~~~~~~~~~~ coreutils/readlink.c:91:27: note: use array indexing to silence this warning printf("%s%s", buf, "\n" + (opt & 1)); ^ & [ ] This warning is meant to be suppressed: from Makefile.flags: # clang-9 does not like "str" + N and "if (CONFIG_ITEM && cond)" constructs ifeq ($(CC),clang) CFLAGS += $(call cc-option,-Wno-string-plus-int -Wno-constant-logical-operand) endif However, as has been reported before, this check does not handle things like CC=clang-16. I am not sure what busybox's intent is here. If busybox decides that this warning is useless, it would be nice if it got suppressed reliably. Otherwise, if the suppression was meant to be temporary to allow code to be adapted (in which case it is more than understandable that the suppression is left imperfect: it is not worth extra effort), it would be nice to write new code in the style they recommend to suppress the warning, as &"\n"[opt & 1]. The rationale for the warning is that a novice user might be confused by the fact that the + operator is overloaded in C++ to concatenate strings, and despite the fact that this is not C++, might expect it to do the same here, whereas &"\n"[opt & 1] indicates clear intent on the programmer's part. Whether busybox agrees with this rationale is up to them, but the warnings are unfortunate either way, just for different reasons. Cheers, Harald van Dijk From d+busybox at adaptive-enterprises.com Tue Apr 25 00:52:45 2023 From: d+busybox at adaptive-enterprises.com (David Leonard) Date: Tue, 25 Apr 2023 10:52:45 +1000 (AEST) Subject: [PATCH v4] readlink: slight size optimization In-Reply-To: <7045c162-75e6-8dcf-3aae-311d13d7c4fa@gigawatt.nl> References: <20230418122237.1820276-1-eblake@redhat.com> <7045c162-75e6-8dcf-3aae-311d13d7c4fa@gigawatt.nl> Message-ID: On Mon, 24 Apr 2023, Harald van Dijk wrote: > coreutils/readlink.c:91:27: warning: adding 'unsigned int' to a string does > not append to the string [-Wstring-plus-int] > printf("%s%s", buf, "\n" + (opt & 1)); > ~~~~~^~~~~~~~~~~ > coreutils/readlink.c:91:27: note: use array indexing to silence this warning > printf("%s%s", buf, "\n" + (opt & 1)); > ^ > & [ ] > > I am not sure what busybox's intent is here. If busybox decides that this > warning is useless, it would be nice if it got suppressed reliably. Alternatively, avoid warnings with this construction which gives pretty good size results: if (opt) fputs(buf, stdout); else puts(buf); The rest of this email is cc/size experiment results. $ ./cc-size -c f1.c -Os cc -c f1.c -Os -DT0 -DT1 -DT2 -DT3 aarch64 1584 -80 -8 +48 arm 1008 -48 -20 +0 mips 1396 -72 +8 +64 x86_64 1520 -80 -32 +0 gcc 1552 -96 +8 +72 clang 1280 -80 +0 +72 The numbers represent the increase in byte size of f1.o compared to when compiled with baseline -DT0. $ cat f1.c #include /* suppress trailing newline when opt */ int f1(int opt, char buf[]) { #if defined(T0) if (opt) printf("%s", buf); else printf("%s\n", buf); #elif defined(T1) if (opt) fputs(buf, stdout); else puts(buf); #elif defined(T2) printf("%s%s", buf, "\n" + (opt & 1)); #elif defined(T3) printf("%s%s", buf, opt ? "" : "\n"); #else # error "forgot to -DTx" #endif } The compilers were: aarch64-linux-musl-gcc (GCC) 11.2.0 arm-linux-musleabi-gcc (GCC) 11.2.0 mips-linux-musl-gcc (GCC) 11.2.0 x86_64-linux-musl-gcc (GCC) 11.2.0 gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0 Ubuntu clang version 14.0.0-1ubuntu1 (x86_64-pc-linux-gnu) From eblake at redhat.com Tue Apr 25 12:51:57 2023 From: eblake at redhat.com (Eric Blake) Date: Tue, 25 Apr 2023 07:51:57 -0500 Subject: [PATCH v4] readlink: slight size optimization In-Reply-To: References: <20230418122237.1820276-1-eblake@redhat.com> <7045c162-75e6-8dcf-3aae-311d13d7c4fa@gigawatt.nl> Message-ID: On Tue, Apr 25, 2023 at 10:52:45AM +1000, David Leonard wrote: > On Mon, 24 Apr 2023, Harald van Dijk wrote: > > coreutils/readlink.c:91:27: warning: adding 'unsigned int' to a string > > does not append to the string [-Wstring-plus-int] > > printf("%s%s", buf, "\n" + (opt & 1)); > > ~~~~~^~~~~~~~~~~ > > coreutils/readlink.c:91:27: note: use array indexing to silence this warning > > printf("%s%s", buf, "\n" + (opt & 1)); > > ^ > > & [ ] > > > > I am not sure what busybox's intent is here. If busybox decides that > > this warning is useless, it would be nice if it got suppressed reliably. > > Alternatively, avoid warnings with this construction which gives pretty > good size results: > > if (opt) That's not the same as 'if (opt & 1)'. As such, you are not comparing apples to oranges... > fputs(buf, stdout); > else > puts(buf); > > > > The rest of this email is cc/size experiment results. > > $ ./cc-size -c f1.c -Os > cc -c f1.c -Os > -DT0 -DT1 -DT2 -DT3 > aarch64 1584 -80 -8 +48 > arm 1008 -48 -20 +0 > mips 1396 -72 +8 +64 > x86_64 1520 -80 -32 +0 > gcc 1552 -96 +8 +72 > clang 1280 -80 +0 +72 Still, the numbers for -DT1 are compelling, despite the potential change for a slight increase in bytes once you use correct logic. > > The numbers represent the increase in byte size of f1.o compared to when > compiled with baseline -DT0. > > $ cat f1.c > #include > > /* suppress trailing newline when opt */ > int f1(int opt, char buf[]) { > #if defined(T0) > if (opt) printf("%s", buf); else printf("%s\n", buf); > #elif defined(T1) > if (opt) fputs(buf, stdout); else puts(buf); > #elif defined(T2) > printf("%s%s", buf, "\n" + (opt & 1)); Of the four tests, T2 is the only one with correct semantics. > #elif defined(T3) > printf("%s%s", buf, opt ? "" : "\n"); > #else > # error "forgot to -DTx" > #endif > } > -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org From eblake at redhat.com Tue Apr 25 13:09:48 2023 From: eblake at redhat.com (Eric Blake) Date: Tue, 25 Apr 2023 08:09:48 -0500 Subject: [PATCH v4] readlink: slight size optimization In-Reply-To: References: <20230418122237.1820276-1-eblake@redhat.com> <7045c162-75e6-8dcf-3aae-311d13d7c4fa@gigawatt.nl> Message-ID: On Tue, Apr 25, 2023 at 07:51:57AM -0500, Eric Blake wrote: > On Tue, Apr 25, 2023 at 10:52:45AM +1000, David Leonard wrote: > > On Mon, 24 Apr 2023, Harald van Dijk wrote: > > > coreutils/readlink.c:91:27: warning: adding 'unsigned int' to a string > > > does not append to the string [-Wstring-plus-int] > > > printf("%s%s", buf, "\n" + (opt & 1)); > > > ~~~~~^~~~~~~~~~~ > > > coreutils/readlink.c:91:27: note: use array indexing to silence this warning > > > printf("%s%s", buf, "\n" + (opt & 1)); > > > ^ > > > & [ ] > > > > > > I am not sure what busybox's intent is here. If busybox decides that > > > this warning is useless, it would be nice if it got suppressed reliably. > > > > Alternatively, avoid warnings with this construction which gives pretty > > good size results: > > > > if (opt) > > That's not the same as 'if (opt & 1)'. As such, you are not comparing > apples to oranges... > > > $ cat f1.c > > #include > > > > /* suppress trailing newline when opt */ > > int f1(int opt, char buf[]) { > > #if defined(T0) > > if (opt) printf("%s", buf); else printf("%s\n", buf); > > #elif defined(T1) > > if (opt) fputs(buf, stdout); else puts(buf); > > #elif defined(T2) > > printf("%s%s", buf, "\n" + (opt & 1)); > > Of the four tests, T2 is the only one with correct semantics. > > > #elif defined(T3) > > printf("%s%s", buf, opt ? "" : "\n"); > > #else > > # error "forgot to -DTx" > > #endif The baseline in the existing coreutils/readlink.c is: printf((opt & 1) ? "%s" : "%s\n", buf); which I don't see in your tests. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org From farmatito at tiscali.it Tue Apr 25 16:22:37 2023 From: farmatito at tiscali.it (tito) Date: Tue, 25 Apr 2023 18:22:37 +0200 Subject: [PATCH v5] readlink: more size optimization In-Reply-To: References: <20230418122237.1820276-1-eblake@redhat.com> <7045c162-75e6-8dcf-3aae-311d13d7c4fa@gigawatt.nl> Message-ID: <20230425182237.369dad0f@devuan> On Tue, 25 Apr 2023 08:09:48 -0500 Eric Blake wrote: > On Tue, Apr 25, 2023 at 07:51:57AM -0500, Eric Blake wrote: > > On Tue, Apr 25, 2023 at 10:52:45AM +1000, David Leonard wrote: > > > On Mon, 24 Apr 2023, Harald van Dijk wrote: > > > > coreutils/readlink.c:91:27: warning: adding 'unsigned int' to a string > > > > does not append to the string [-Wstring-plus-int] > > > > printf("%s%s", buf, "\n" + (opt & 1)); > > > > ~~~~~^~~~~~~~~~~ > > > > coreutils/readlink.c:91:27: note: use array indexing to silence this warning > > > > printf("%s%s", buf, "\n" + (opt & 1)); > > > > ^ > > > > & [ ] > > > > > > > > I am not sure what busybox's intent is here. If busybox decides that > > > > this warning is useless, it would be nice if it got suppressed reliably. > > > > > > Alternatively, avoid warnings with this construction which gives pretty > > > good size results: > > > > > > if (opt) > > > > That's not the same as 'if (opt & 1)'. As such, you are not comparing > > apples to oranges... > > > > > $ cat f1.c > > > #include > > > > > > /* suppress trailing newline when opt */ > > > int f1(int opt, char buf[]) { > > > #if defined(T0) > > > if (opt) printf("%s", buf); else printf("%s\n", buf); > > > #elif defined(T1) > > > if (opt) fputs(buf, stdout); else puts(buf); > > > #elif defined(T2) > > > printf("%s%s", buf, "\n" + (opt & 1)); > > > > Of the four tests, T2 is the only one with correct semantics. > > > > > #elif defined(T3) > > > printf("%s%s", buf, opt ? "" : "\n"); > > > #else > > > # error "forgot to -DTx" > > > #endif > > The baseline in the existing coreutils/readlink.c is: > > printf((opt & 1) ? "%s" : "%s\n", buf); > > which I don't see in your tests. > Hi, more size reduction for readlink. Ciao, Tito make bloatcheck function old new delta readlink_main 127 118 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-9) Total: -9 bytes text data bss dec hex filename 1007549 16467 1840 1025856 fa740 busybox_old 1007540 16467 1840 1025847 fa737 busybox_unstripped Signed-off-by: Tito Ragusa --- coreutils/readlink.c.orig 2023-04-25 18:09:38.728944000 +0200 +++ coreutils/readlink.c 2023-04-25 18:10:31.160915398 +0200 @@ -68,12 +68,10 @@ int readlink_main(int argc, char **argv) int readlink_main(int argc UNUSED_PARAM, char **argv) { char *buf; - char *fname; unsigned opt; opt = getopt32(argv, "^" "n" IF_FEATURE_READLINK_FOLLOW("fvsq") "\0" "=1"); - fname = argv[optind]; /* compat: coreutils readlink reports errors silently via exit code */ if (!(opt & 4)) /* not -v */ @@ -81,14 +79,18 @@ int readlink_main(int argc UNUSED_PARAM, /* NOFORK: only one alloc is allowed; must free */ if (opt & 2) { /* -f */ - buf = xmalloc_realpath_coreutils(fname); + buf = xmalloc_realpath_coreutils(argv[optind]); } else { - buf = xmalloc_readlink_or_warn(fname); + buf = xmalloc_readlink_or_warn(argv[optind]); } if (!buf) return EXIT_FAILURE; - printf((opt & 1) ? "%s" : "%s\n", buf); + + fputs_stdout(buf); + if (!(opt & 1)) + bb_putchar('\n'); + free(buf); fflush_stdout_and_exit_SUCCESS(); -------------- next part -------------- A non-text attachment was scrubbed... Name: readlink.patch Type: text/x-patch Size: 1625 bytes Desc: not available URL: From raphael.melotte at mind.be Wed Apr 26 12:09:47 2023 From: raphael.melotte at mind.be (=?UTF-8?q?Rapha=C3=ABl=20M=C3=A9lotte?=) Date: Wed, 26 Apr 2023 14:09:47 +0200 Subject: [PATCH v2] seedrng: fix getrandom() detection for non-glibc libc Message-ID: <20230426120947.1337099-1-raphael.melotte@mind.be> glibc <= 2.24 does not provide getrandom(). A check for it has been added in 200a9669fbf6f06894e4243cccc9fc11a1a6073a and fixed in cb57abb46f06f4ede8d9ccbdaac67377fdf416cf. However, building with a libc other than glibc can lead to the same problem as not every other libc has getrandom() either: - uClibc provides it from v1.0.2 onwards, but requires to define _GNU_SOURCE (all versions - we already define it by default), and stddef to be included first (when using uClibc < 1.0.35 - we already include it through libbb.h). - musl libc has getrandom(), but only from version 1.1.20 onwards. As musl does not provide __MUSL__ or version information, it's not possible to check for it like we did for glibc. All of this makes it difficult (or impossible in case of musl) to check what we need to do to have getrandom() based on each libc versions. On top of that, getrandom() is also not available on older kernels. As an example, when using a 3.10 kernel with uClibc 1.0.26, getrandom() is declared so compiling works, but it fails at link time because getrandom() is not defined. To make it easier, take a similar approach to what was done for the crypt library: try to build a sample program to see if we have getrandom(). Based on the new Makefile variable, we now either use the libc-provided getrandom() when it's available, or use our own implementation when it's not (like it was the case already for glibc < 2.25). This should fix compiling with many libc/kernel combinations. Signed-off-by: Rapha?l M?lotte --- Changes v1 -> v2: - move _GNU_SOURCE to bb_libtest.c - remove GRND_NONBLOCK Note that I was not able to test every single combination, but I could confirm it builds successfully for: uClibc 10.0.24, linux headers 3.10 (libc getrandom NOT used) uClibc 1.0.36, linux headers 4.9 (libc getrandom used) musl 1.1.16, linux headers 4.12 (libc getrandom NOT used) musl 1.2.1, linux headers (libc getrandom used) glibc 2.25, linux headers 4.10 (libc getrandom used) Makefile.flags | 7 +++++++ miscutils/seedrng.c | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Makefile.flags b/Makefile.flags index 1cec5ba20..ff593748f 100644 --- a/Makefile.flags +++ b/Makefile.flags @@ -161,6 +161,13 @@ ifeq ($(RT_AVAILABLE),y) LDLIBS += rt endif +# Not all libc versions have getrandom, so check for it. +HAVE_GETRANDOM := $(shell printf '#include \n#include \n#define _GNU_SOURCE\nint main(void){char buf[256];\ngetrandom(buf,sizeof(buf),0);}' >bb_libtest.c; $(CC) $(CFLAGS) $(CFLAGS_busybox) -o /dev/null bb_libtest.c >/dev/null 2>&1 && echo "y"; rm bb_libtest.c) + +ifeq ($(HAVE_GETRANDOM),y) +CFLAGS += -DHAVE_GETRANDOM +endif + # libpam may use libpthread, libdl and/or libaudit. # On some platforms that requires an explicit -lpthread, -ldl, -laudit. # However, on *other platforms* it fails when some of those flags diff --git a/miscutils/seedrng.c b/miscutils/seedrng.c index 3bf6e2ea7..2f1e18c32 100644 --- a/miscutils/seedrng.c +++ b/miscutils/seedrng.c @@ -44,8 +44,10 @@ #include #include -/* Fix up glibc <= 2.24 not having getrandom() */ -#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 24 +/* Fix up some libc (e.g. glibc <= 2.24) not having getrandom() */ +#if defined HAVE_GETRANDOM +#include +#else /* No getrandom */ #include static ssize_t getrandom(void *buffer, size_t length, unsigned flags) { @@ -56,8 +58,6 @@ static ssize_t getrandom(void *buffer, size_t length, unsigned flags) return -1; # endif } -#else -#include #endif /* Apparently some headers don't ship with this yet. */ -- 2.39.1 From mjt at tls.msk.ru Wed Apr 26 12:30:21 2023 From: mjt at tls.msk.ru (Michael Tokarev) Date: Wed, 26 Apr 2023 15:30:21 +0300 Subject: [PATCH v2] seedrng: fix getrandom() detection for non-glibc libc In-Reply-To: <20230426120947.1337099-1-raphael.melotte@mind.be> References: <20230426120947.1337099-1-raphael.melotte@mind.be> Message-ID: 26.04.2023 15:09, Rapha?l M?lotte ?????: > glibc <= 2.24 does not provide getrandom(). A check for it has been > added in 200a9669fbf6f06894e4243cccc9fc11a1a6073a and fixed in > cb57abb46f06f4ede8d9ccbdaac67377fdf416cf. > > However, building with a libc other than glibc can lead to the same > problem as not every other libc has getrandom() either: > > - uClibc provides it from v1.0.2 onwards, but requires to define > _GNU_SOURCE (all versions - we already define it by default), and > stddef to be included first (when using uClibc < 1.0.35 - we already > include it through libbb.h). > > - musl libc has getrandom(), but only from version 1.1.20 onwards. As > musl does not provide __MUSL__ or version information, it's not > possible to check for it like we did for glibc. > > All of this makes it difficult (or impossible in case of musl) to > check what we need to do to have getrandom() based on each libc > versions. > > On top of that, getrandom() is also not available on older kernels. As > an example, when using a 3.10 kernel with uClibc 1.0.26, getrandom() > is declared so compiling works, but it fails at link time because > getrandom() is not defined. > > To make it easier, take a similar approach to what was done for the > crypt library: try to build a sample program to see if we have > getrandom(). > > Based on the new Makefile variable, we now either use the > libc-provided getrandom() when it's available, or use our own > implementation when it's not (like it was the case already for glibc < > 2.25). > > This should fix compiling with many libc/kernel combinations. > > Signed-off-by: Rapha?l M?lotte > --- > Changes v1 -> v2: > - move _GNU_SOURCE to bb_libtest.c > - remove GRND_NONBLOCK > > Note that I was not able to test every single combination, but I could > confirm it builds successfully for: > uClibc 10.0.24, linux headers 3.10 (libc getrandom NOT used) > uClibc 1.0.36, linux headers 4.9 (libc getrandom used) > musl 1.1.16, linux headers 4.12 (libc getrandom NOT used) > musl 1.2.1, linux headers (libc getrandom used) > glibc 2.25, linux headers 4.10 (libc getrandom used) > > Makefile.flags | 7 +++++++ > miscutils/seedrng.c | 8 ++++---- > 2 files changed, 11 insertions(+), 4 deletions(-) > > diff --git a/Makefile.flags b/Makefile.flags > index 1cec5ba20..ff593748f 100644 > --- a/Makefile.flags > +++ b/Makefile.flags > @@ -161,6 +161,13 @@ ifeq ($(RT_AVAILABLE),y) > LDLIBS += rt > endif > > +# Not all libc versions have getrandom, so check for it. > +HAVE_GETRANDOM := $(shell printf '#include \n#include \n#define _GNU_SOURCE\nint main(void){char buf[256];\ngetrandom(buf,sizeof(buf),0);}' >bb_libtest.c; $(CC) $(CFLAGS) $(CFLAGS_busybox) -o /dev/null bb_libtest.c >/dev/null 2>&1 && echo "y"; rm bb_libtest.c) What defining _GNU_SOURCE is supposed to do here? It's a very interesting place to #define it. It's like doing LFS this way: #include #define _FILE_OFFSET_BITS 64 // use 64bit off_t here It just doesn't work. In both cases, those definitions are checked within the header files to enable/disable certain functionality. Such #define does absolutely nothing after #includes. If anything, you can use -D_GNU_SOURCE=1 on the command line. /mjt From raphael.melotte at mind.be Wed Apr 26 12:39:50 2023 From: raphael.melotte at mind.be (=?UTF-8?B?UmFwaGHDq2wgTcOpbG90dGU=?=) Date: Wed, 26 Apr 2023 14:39:50 +0200 Subject: [PATCH v2] seedrng: fix getrandom() detection for non-glibc libc In-Reply-To: References: <20230426120947.1337099-1-raphael.melotte@mind.be> Message-ID: <8432e8d8-f42c-f614-0797-f44e9f9cea23@mind.be> On 4/26/23 14:30, Michael Tokarev wrote: > What defining _GNU_SOURCE is supposed to do here? > It's a very interesting place to #define it. > It's like doing LFS this way: Nothing, that's an oversight from my side.. Thanks for pointing it out! > #include > #define _FILE_OFFSET_BITS 64 > // use 64bit off_t here > > It just doesn't work. In both cases, those definitions are checked > within the header files to enable/disable certain functionality. > Such #define does absolutely nothing after #includes. > If anything, you can use -D_GNU_SOURCE=1 on the command line. This is actually what I did in v1, I was later suggested to move it into the bb_libtest.c file (see [1] - in this specific case I have no preference on the matter) and I was apparently not really awake when I sent the v2. I'll send a v3 shortly. [1]: http://lists.busybox.net/pipermail/busybox/2023-April/090287.html From raphael.melotte at mind.be Wed Apr 26 12:43:25 2023 From: raphael.melotte at mind.be (=?UTF-8?q?Rapha=C3=ABl=20M=C3=A9lotte?=) Date: Wed, 26 Apr 2023 14:43:25 +0200 Subject: [PATCH v3] seedrng: fix getrandom() detection for non-glibc libc Message-ID: <20230426124325.1338854-1-raphael.melotte@mind.be> glibc <= 2.24 does not provide getrandom(). A check for it has been added in 200a9669fbf6f06894e4243cccc9fc11a1a6073a and fixed in cb57abb46f06f4ede8d9ccbdaac67377fdf416cf. However, building with a libc other than glibc can lead to the same problem as not every other libc has getrandom() either: - uClibc provides it from v1.0.2 onwards, but requires to define _GNU_SOURCE (all versions - we already define it by default), and stddef to be included first (when using uClibc < 1.0.35 - we already include it through libbb.h). - musl libc has getrandom(), but only from version 1.1.20 onwards. As musl does not provide __MUSL__ or version information, it's not possible to check for it like we did for glibc. All of this makes it difficult (or impossible in case of musl) to check what we need to do to have getrandom() based on each libc versions. On top of that, getrandom() is also not available on older kernels. As an example, when using a 3.10 kernel with uClibc 1.0.26, getrandom() is declared so compiling works, but it fails at link time because getrandom() is not defined. To make it easier, take a similar approach to what was done for the crypt library: try to build a sample program to see if we have getrandom(). Based on the new Makefile variable, we now either use the libc-provided getrandom() when it's available, or use our own implementation when it's not (like it was the case already for glibc < 2.25). This should fix compiling with many libc/kernel combinations. Signed-off-by: Rapha?l M?lotte --- Changes v2 -> v3: - fix _GNU_SOURCE define location Changes v1 -> v2: - move _GNU_SOURCE to bb_libtest.c - remove GRND_NONBLOCK Note that I was not able to test every single combination, but I could confirm it builds successfully for: uClibc 10.0.24, linux headers 3.10 (libc getrandom NOT used) uClibc 1.0.36, linux headers 4.9 (libc getrandom used) musl 1.1.16, linux headers 4.12 (libc getrandom NOT used) musl 1.2.1, linux headers (libc getrandom used) glibc 2.25, linux headers 4.10 (libc getrandom used) Makefile.flags | 7 +++++++ miscutils/seedrng.c | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Makefile.flags b/Makefile.flags index 1cec5ba20..4ee12d2d9 100644 --- a/Makefile.flags +++ b/Makefile.flags @@ -161,6 +161,13 @@ ifeq ($(RT_AVAILABLE),y) LDLIBS += rt endif +# Not all libc versions have getrandom, so check for it. +HAVE_GETRANDOM := $(shell printf '#define _GNU_SOURCE\n#include \n#include \nint main(void){char buf[256];\ngetrandom(buf,sizeof(buf),0);}' >bb_libtest.c; $(CC) $(CFLAGS) $(CFLAGS_busybox) -o /dev/null bb_libtest.c >/dev/null 2>&1 && echo "y"; rm bb_libtest.c) + +ifeq ($(HAVE_GETRANDOM),y) +CFLAGS += -DHAVE_GETRANDOM +endif + # libpam may use libpthread, libdl and/or libaudit. # On some platforms that requires an explicit -lpthread, -ldl, -laudit. # However, on *other platforms* it fails when some of those flags diff --git a/miscutils/seedrng.c b/miscutils/seedrng.c index 3bf6e2ea7..2f1e18c32 100644 --- a/miscutils/seedrng.c +++ b/miscutils/seedrng.c @@ -44,8 +44,10 @@ #include #include -/* Fix up glibc <= 2.24 not having getrandom() */ -#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 24 +/* Fix up some libc (e.g. glibc <= 2.24) not having getrandom() */ +#if defined HAVE_GETRANDOM +#include +#else /* No getrandom */ #include static ssize_t getrandom(void *buffer, size_t length, unsigned flags) { @@ -56,8 +58,6 @@ static ssize_t getrandom(void *buffer, size_t length, unsigned flags) return -1; # endif } -#else -#include #endif /* Apparently some headers don't ship with this yet. */ -- 2.39.1 From nv at vosn.de Thu Apr 27 09:28:34 2023 From: nv at vosn.de (Nikolaus Voss) Date: Thu, 27 Apr 2023 11:28:34 +0200 (CEST) Subject: [RFC PATCH] ip link: support for the CAN netlink In-Reply-To: <20230420193533.1963524-1-dario.binacchi@amarulasolutions.com> References: <20230420193533.1963524-1-dario.binacchi@amarulasolutions.com> Message-ID: Hi Dario, I posted a more minimalistic approach some time ago: http://lists.busybox.net/pipermail/busybox/2022-August/089822.html Thanks, Niko On Thu, 20 Apr 2023, Dario Binacchi wrote: > I developed this application to test the Linux kernel series [1]. As > described in the cover letter I could not use the iproute2 package > since the microcontroller is without MMU. > > cc: Marc Kleine-Budde > [1] https://marc.info/?l=linux-netdev&m=167999323611710&w=2 > Signed-off-by: Dario Binacchi > --- > configs/TEST_nommu_defconfig | 1 + > networking/ip.c | 84 ++++++++++ > networking/libiproute/iplink.c | 298 ++++++++++++++++++++++++++++++++- > 3 files changed, 374 insertions(+), 9 deletions(-) > > diff --git a/configs/TEST_nommu_defconfig b/configs/TEST_nommu_defconfig > index 415f5a8027f9..fa3e9632622a 100644 > --- a/configs/TEST_nommu_defconfig > +++ b/configs/TEST_nommu_defconfig > @@ -703,6 +703,7 @@ CONFIG_FEATURE_INETD_RPC=y > CONFIG_IP=y > CONFIG_FEATURE_IP_ADDRESS=y > CONFIG_FEATURE_IP_LINK=y > +CONFIG_FEATURE_IP_LINK_CAN=y > CONFIG_FEATURE_IP_ROUTE=y > CONFIG_FEATURE_IP_TUNNEL=y > CONFIG_FEATURE_IP_RULE=y > diff --git a/networking/ip.c b/networking/ip.c > index 7c320869958a..4959e9f25288 100644 > --- a/networking/ip.c > +++ b/networking/ip.c > @@ -32,6 +32,14 @@ > //config: help > //config: Short form of "ip link" > //config: > +//config:config IPLINK_CAN > +//config: bool "iplink for CAN (4.6 kb)" > +//config: default n > +//config: depends on IPLINK > +//config: select FEATURE_IP_LINK_CAN > +//config: help > +//config: Short form of "ip link" for CAN > +//config: > //config:config IPROUTE > //config: bool "iproute (15 kb)" > //config: default y > @@ -74,6 +82,13 @@ > //config: help > //config: Configure network devices with "ip". > //config: > +//config:config FEATURE_IP_LINK_CAN > +//config: bool "ip link can" > +//config: default n > +//config: depends on IP_LINK_CAN > +//config: help > +//config: Configure CAN devices with "ip". > +//config: > //config:config FEATURE_IP_ROUTE > //config: bool "ip route" > //config: default y > @@ -122,6 +137,7 @@ > //applet:IF_IP( APPLET_NOEXEC(ip , ip , BB_DIR_SBIN, BB_SUID_DROP, ip )) > //applet:IF_IPADDR( APPLET_NOEXEC(ipaddr , ipaddr , BB_DIR_SBIN, BB_SUID_DROP, ipaddr )) > //applet:IF_IPLINK( APPLET_NOEXEC(iplink , iplink , BB_DIR_SBIN, BB_SUID_DROP, iplink )) > +//applet:IF_IPLINK_CAN(APPLET_NOEXEC(iplinkcan , iplinkcan , BB_DIR_SBIN, BB_SUID_DROP, iplinkcan)) > //applet:IF_IPROUTE( APPLET_NOEXEC(iproute , iproute , BB_DIR_SBIN, BB_SUID_DROP, iproute )) > //applet:IF_IPRULE( APPLET_NOEXEC(iprule , iprule , BB_DIR_SBIN, BB_SUID_DROP, iprule )) > //applet:IF_IPTUNNEL(APPLET_NOEXEC(iptunnel, iptunnel, BB_DIR_SBIN, BB_SUID_DROP, iptunnel)) > @@ -130,6 +146,7 @@ > //kbuild:lib-$(CONFIG_IP) += ip.o > //kbuild:lib-$(CONFIG_IPADDR) += ip.o > //kbuild:lib-$(CONFIG_IPLINK) += ip.o > +//kbuild:lib-$(CONFIG_IPLINK_CAN) += ip.o > //kbuild:lib-$(CONFIG_IPROUTE) += ip.o > //kbuild:lib-$(CONFIG_IPRULE) += ip.o > //kbuild:lib-$(CONFIG_IPTUNNEL) += ip.o > @@ -149,10 +166,16 @@ > //usage: "ipaddr show|flush [dev IFACE] [scope SCOPE] [to PREFIX] [label PATTERN]" > //usage: > //--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 > +//usage:#if ENABLE_FEATURE_IP_LINK_CAN > +//usage:#define iplink_type_usage "\n [type TYPE ARGS]" > +//usage:#else > +//usage:#define iplink_type_usage "" > +//usage:#endif > //usage:#define iplink_trivial_usage > //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" > //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" > //usage: " [master IFACE | nomaster] [netns PID]" > +//usage: IF_FEATURE_IP_LINK(iplink_type_usage) > // * short help shows only "set" command, long help continues (with just one "\n") > // * and shows all other commands: > //usage:#define iplink_full_usage "\n" > @@ -207,6 +230,59 @@ > // bond_slave | ipvlan | geneve | bridge_slave | vrf } > //usage: > //--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 > +//usage:#define iplinkcan_trivial_usage > +//usage: /*Usage:iplinkcan*/"set DEVICE type can" > +//usage:#define iplinkcan_full_usage "\n\n" > +//usage: " [bitrate BITRATE [sample-point SAMPLE-POINT]] |\n" > +//usage: " [tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1\n" > +//usage: " phase-seg2 PHASE-SEG2 [sjw SJW]]\n" > +//usage: "\n" > +//usage: " [dbitrate BITRATE [dsample-point SAMPLE-POINT]] |\n" > +//usage: " [dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1\n" > +//usage: " dphase-seg2 PHASE-SEG2 [dsjw SJW]]\n" > +//usage: "\n" > +//usage: " [loopback on|off] [listen-only on|off] [triple-sampling on|off]\n" > +//usage: " [one-shot on|off] [berr-reporting on|off]\n" > +//usage: " [fd on|off] [fd-non-iso on|off] [presume-ack on|off]\n" > +//usage: "\n" > +//usage: " [restart-ms TIME-MS] [restart]\n" > +//usage: "\n" > +//usage: " [termination 0..65535]\n" > +//usage: > +//upstream man ip-link-can: > +//Usage: ip link set DEVICE type can > +// [ bitrate BITRATE [ sample-point SAMPLE-POINT] ] | > +// [ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1 > +// phase-seg2 PHASE-SEG2 [ sjw SJW ] ] > +// > +// [ dbitrate BITRATE [ dsample-point SAMPLE-POINT] ] | > +// [ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1 > +// dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ] > +// > +// [ loopback { on | off } ] > +// [ listen-only { on | off } ] > +// [ triple-sampling { on | off } ] > +// [ one-shot { on | off } ] > +// [ berr-reporting { on | off } ] > +// [ fd { on | off } ] > +// [ fd-non-iso { on | off } ] > +// [ presume-ack { on | off } ] > +// > +// [ restart-ms TIME-MS ] > +// [ restart ] > +// > +// [ termination { 0..65535 } ] > +// > +// Where: BITRATE := { 1..1000000 } > +// SAMPLE-POINT := { 0.000..0.999 } > +// TQ := { NUMBER } > +// PROP-SEG := { 1..8 } > +// PHASE-SEG1 := { 1..8 } > +// PHASE-SEG2 := { 1..8 } > +// SJW := { 1..4 } > +// RESTART-MS := { 0 | NUMBER } > +//usage: > +//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 > //usage:#define iproute_trivial_usage > //usage: "list|flush|add|del|change|append|replace|test ROUTE" > //usage:#define iproute_full_usage "\n\n" > @@ -327,6 +403,7 @@ typedef int FAST_FUNC (*ip_func_ptr_t)(char**); > > #if ENABLE_IPADDR \ > || ENABLE_IPLINK \ > + || ENABLE_IPLINK_CAN \ > || ENABLE_IPROUTE \ > || ENABLE_IPRULE \ > || ENABLE_IPTUNNEL \ > @@ -352,6 +429,13 @@ int iplink_main(int argc UNUSED_PARAM, char **argv) > return ip_do(do_iplink, argv); > } > #endif > +#if ENABLE_IPLINK_CAN > +int iplinkcan_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; > +int iplinkcan_main(int argc UNUSED_PARAM, char **argv) > +{ > + return ip_do(do_iplink, argv); > +} > +#endif > #if ENABLE_IPROUTE > int iproute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; > int iproute_main(int argc UNUSED_PARAM, char **argv) > diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c > index 68d1990445fe..f97169714d0f 100644 > --- a/networking/libiproute/iplink.c > +++ b/networking/libiproute/iplink.c > @@ -11,10 +11,17 @@ > #include > > #include > +#include > #include "ip_common.h" /* #include "libbb.h" is inside */ > #include "rt_names.h" > #include "utils.h" > > +#if ENABLE_FEATURE_IP_LINK_CAN > +#define ENABLE_FEATURE_IP_LINK_IFACE 1 > +#else > +#define ENABLE_FEATURE_IP_LINK_IFACE 0 > +#endif > + > #undef ETH_P_8021AD > #define ETH_P_8021AD 0x88A8 > #undef VLAN_FLAG_REORDER_HDR > @@ -28,6 +35,11 @@ > #undef IFLA_VLAN_PROTOCOL > #define IFLA_VLAN_PROTOCOL 5 > > +#ifndef NLMSG_TAIL > +#define NLMSG_TAIL(nmsg) \ > + ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) > +#endif > + > #ifndef IFLA_LINKINFO > # define IFLA_LINKINFO 18 > # define IFLA_INFO_KIND 1 > @@ -55,6 +67,13 @@ struct ifla_vlan_flags { > > #define str_on_off "on\0""off\0" > > +enum { > + PARM_on = 0, > + PARM_off > +}; > + > +typedef void FAST_FUNC(*ip_type_set_func_ptr_t)(char*, char**); > + > /* Exits on error */ > static int get_ctl_fd(void) > { > @@ -241,10 +260,261 @@ static void die_must_be_on_off(const char *msg) > bb_error_msg_and_die("argument of \"%s\" must be \"on\" or \"off\"", msg); > } > > +#if ENABLE_FEATURE_IP_LINK_CAN > +static float FAST_FUNC get_float(char *arg, const char *errmsg) > +{ > + float ret; > + char *ptr; > + > + if (!arg || !*arg) > + invarg_1_to_2(arg, errmsg); /* does not return */ > + > + ret = strtof(arg, &ptr); > + if (!ptr || ptr == arg || *ptr) > + invarg_1_to_2(arg, errmsg); /* does not return */ > + > + return ret; > +} > + > +static void do_set_can(char *dev, char **argv) > +{ > + struct can_bittiming bt = {}, dbt = {}; > + struct can_ctrlmode cm = {}; > + char *keyword; > + static const char keywords[] ALIGN1 = > + "bitrate\0""sample-point\0""tq\0" > + "prop-seg\0""phase-seg1\0""phase-seg2\0""sjw\0" > + "dbitrate\0""dsample-point\0""dtq\0" > + "dprop-seg\0""dphase-seg1\0""dphase-seg2\0""dsjw\0" > + "loopback\0""listen-only\0""triple-sampling\0" > + "one-shot\0""berr-reporting\0" > + "fd\0""fd-non-iso\0""presume-ack\0" > + "cc-len8-dlc\0""restart\0""restart-ms\0" > + "termination\0"; > + enum { ARG_bitrate = 0, ARG_sample_point, ARG_tq, > + ARG_prop_seg, ARG_phase_seg1, ARG_phase_seg2, ARG_sjw, > + ARG_dbitrate, ARG_dsample_point, ARG_dtq, > + ARG_dprop_seg, ARG_dphase_seg1, ARG_dphase_seg2, ARG_dsjw, > + ARG_loopback, ARG_listen_only, ARG_triple_sampling, > + ARG_one_shot, ARG_berr_reporting, > + ARG_fd, ARG_fd_non_iso, ARG_presume_ack, > + ARG_cc_len8_dlc, ARG_restart, ARG_restart_ms, > + ARG_termination }; > + struct rtnl_handle rth; > + struct { > + struct nlmsghdr n; > + struct ifinfomsg i; > + char buf[1024]; > + } req; > + size_t dev_len; > + struct rtattr *linkinfo, *data; > + smalluint key, param; > + > + memset(&req, 0, sizeof(req)); > + > + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); > + req.n.nlmsg_flags = NLM_F_REQUEST; > + req.n.nlmsg_type = RTM_NEWLINK; > + req.i.ifi_family = preferred_family; > + xrtnl_open(&rth); > + req.i.ifi_index = xll_name_to_index(dev); > + dev_len = strlen(dev); > + if (dev_len < 2 || dev_len > IFNAMSIZ) > + invarg_1_to_2(dev, "dev"); > + > + addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, dev_len); > + linkinfo = NLMSG_TAIL(&req.n); > + addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); > + addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (void *)"can", > + strlen("can")); > + data = NLMSG_TAIL(&req.n); > + addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0); > + while (*argv) { > + key = index_in_substrings(keywords, *argv); > + keyword = *argv; > + //printf("%s: key: %d, *argv: %s\n", __func__, key, *argv); > + switch (key) { > + case ARG_bitrate: > + case ARG_tq: > + case ARG_prop_seg: > + case ARG_phase_seg1: > + case ARG_phase_seg2: > + case ARG_sjw: { > + __u32 *val; > + > + NEXT_ARG(); > + if (key == ARG_bitrate) > + val = &bt.bitrate; > + else if (key == ARG_tq) > + val = &bt.tq; > + else if (key == ARG_prop_seg) > + val = &bt.prop_seg; > + else if (key == ARG_phase_seg1) > + val = &bt.phase_seg1; > + else if (key == ARG_phase_seg2) > + val = &bt.phase_seg2; > + else > + val = &bt.sjw; > + > + *val = get_u32(*argv, keyword); > + break; > + } > + case ARG_sample_point: { > + float sp; > + > + NEXT_ARG(); > + sp = get_float(*argv, keyword); > + bt.sample_point = (__u32)(sp * 1000); > + break; > + } > + case ARG_dbitrate: > + case ARG_dtq: > + case ARG_dprop_seg: > + case ARG_dphase_seg1: > + case ARG_dphase_seg2: > + case ARG_dsjw: { > + __u32 *val; > + > + NEXT_ARG(); > + if (key == ARG_dbitrate) > + val = &dbt.bitrate; > + else if (key == ARG_dtq) > + val = &dbt.tq; > + else if (key == ARG_dprop_seg) > + val = &dbt.prop_seg; > + else if (key == ARG_dphase_seg1) > + val = &dbt.phase_seg1; > + else if (key == ARG_dphase_seg2) > + val = &dbt.phase_seg2; > + else > + val = &dbt.sjw; > + > + *val = get_u32(*argv, keyword); > + break; > + } > + case ARG_dsample_point: { > + float sp; > + > + NEXT_ARG(); > + sp = get_float(*argv, keyword); > + dbt.sample_point = (__u32)(sp * 1000); > + break; > + } > + case ARG_loopback: > + case ARG_listen_only: > + case ARG_triple_sampling: > + case ARG_one_shot: > + case ARG_berr_reporting: > + case ARG_fd: > + case ARG_fd_non_iso: > + case ARG_presume_ack: > + case ARG_cc_len8_dlc: { > + __u32 flag = 0; > + > + NEXT_ARG(); > + param = index_in_strings(str_on_off, *argv); > + if (param < 0) > + die_must_be_on_off(keyword); > + > + if (key == ARG_loopback) > + flag = CAN_CTRLMODE_LOOPBACK; > + else if (key == ARG_listen_only) > + flag = CAN_CTRLMODE_LISTENONLY; > + else if (key == ARG_triple_sampling) > + flag = CAN_CTRLMODE_3_SAMPLES; > + else if (key == ARG_one_shot) > + flag = CAN_CTRLMODE_ONE_SHOT; > + else if (key == ARG_berr_reporting) > + flag = CAN_CTRLMODE_BERR_REPORTING; > + else if (key == ARG_fd) > + flag = CAN_CTRLMODE_FD; > + else if (key == ARG_fd_non_iso) > + flag = CAN_CTRLMODE_FD_NON_ISO; > + else if (key == ARG_presume_ack) > + flag = CAN_CTRLMODE_PRESUME_ACK; > + else > +#if defined(CAN_CTRLMODE_CC_LEN8_DLC) > + flag = CAN_CTRLMODE_CC_LEN8_DLC; > +#else > + die_must_be_on_off(keyword); > +#endif > + cm.mask |= flag; > + if (param == PARM_on) > + cm.flags |= flag; > + > + break; > + } > + case ARG_restart: { > + __u32 val = 1; > + > + NEXT_ARG(); > + addattr_l(&req.n, sizeof(req), IFLA_CAN_RESTART, &val, sizeof(val)); > + break; > + } > + case ARG_restart_ms: { > + __u32 val; > + > + NEXT_ARG(); > + val = get_u32(*argv, keyword); > + addattr_l(&req.n, sizeof(req), IFLA_CAN_RESTART_MS, &val, sizeof(val)); > + break; > + } > + case ARG_termination: { > + __u16 val; > + > + NEXT_ARG(); > + val = get_u16(*argv, keyword); > + addattr_l(&req.n, sizeof(req), IFLA_CAN_TERMINATION, &val, sizeof(val)); > + break; > + } > + default: > + break; > + } > + > + argv++; > + } > + > + if (bt.bitrate || bt.tq) > + addattr_l(&req.n, sizeof(req), IFLA_CAN_BITTIMING, &bt, sizeof(bt)); > + > + if (cm.mask) > + addattr_l(&req.n, sizeof(req), IFLA_CAN_CTRLMODE, &cm, sizeof(cm)); > + > + data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; > + linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; > + > + if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) > + xfunc_die(); > +} > +#endif > + > +#if ENABLE_FEATURE_IP_LINK_IFACE > +static void do_set_iface(char *type, char *dev, char **argv) > +{ > + static const char keywords[] ALIGN1 = "" > + IF_FEATURE_IP_LINK_CAN("can\0") > + ; > + static const ip_type_set_func_ptr_t funcs[] ALIGN_PTR = { > + IF_FEATURE_IP_LINK_CAN(do_set_can,) > + }; > + ip_type_set_func_ptr_t func; > + int key; > + > + key = index_in_substrings(keywords, type); > + if (key < 0) > + return; > + func = funcs[key]; > + func(dev, argv); > +} > +#endif > + > /* Return value becomes exitcode. It's okay to not return at all */ > static int do_set(char **argv) > { > char *dev = NULL; > +#if ENABLE_FEATURE_IP_LINK_IFACE > + char *type = NULL; > +#endif > uint32_t mask = 0; > uint32_t flags = 0; > int qlen = -1; > @@ -261,18 +531,24 @@ static int do_set(char **argv) > "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" > "arp\0""promisc\0""address\0""netns\0" > "master\0""nomaster\0" > +#if ENABLE_FEATURE_IP_LINK_IFACE > + "type\0" > +#endif > "dev\0" /* must be last */; > enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, > ARG_arp, ARG_promisc, ARG_addr, ARG_netns, > ARG_master, ARG_nomaster, > +#if ENABLE_FEATURE_IP_LINK_IFACE > + ARG_type, > +#endif > ARG_dev }; > - enum { PARM_on = 0, PARM_off }; > smalluint key; > > while (*argv) { > /* substring search ensures that e.g. "addr" and "address" > * are both accepted */ > key = index_in_substrings(keywords, *argv); > + //printf("%s: key: %d, *argv: %s\n", __func__, key, *argv); > if (key == ARG_up) { > mask |= IFF_UP; > flags |= IFF_UP; > @@ -304,6 +580,13 @@ static int do_set(char **argv) > } else if (key == ARG_netns) { > NEXT_ARG(); > netns = get_unsigned(*argv, "netns"); > +#if ENABLE_FEATURE_IP_LINK_IFACE > + } else if (key == ARG_type) { > + NEXT_ARG(); > + type = *argv; > + argv++; > + break; > +#endif > } else if (key >= ARG_dev) { > /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */ > if (key == ARG_dev) { > @@ -311,6 +594,7 @@ static int do_set(char **argv) > } > if (dev) > duparg2("dev", *argv); > + > dev = *argv; > } else { > /* "on|off" options */ > @@ -496,6 +780,10 @@ static int do_set(char **argv) > } > if (mask) > do_chflags(dev, flags, mask); > +#if ENABLE_FEATURE_IP_LINK_IFACE > + if (type) > + do_set_iface(type, dev, argv); > +#endif > return 0; > } > > @@ -531,10 +819,6 @@ static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size) > PROTO_8021Q = 0, > PROTO_8021AD, > }; > - enum { > - PARM_on = 0, > - PARM_off > - }; > int arg; > uint16_t id, proto; > struct ifla_vlan_flags flags = {}; > @@ -610,10 +894,6 @@ static void vrf_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size) > addattr_l(n, size, IFLA_VRF_TABLE, &table, sizeof(table)); > } > > -#ifndef NLMSG_TAIL > -#define NLMSG_TAIL(nmsg) \ > - ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) > -#endif > /* Return value becomes exitcode. It's okay to not return at all */ > static int do_add_or_delete(char **argv, const unsigned rtm) > { > From yetanothergeek at gmail.com Fri Apr 28 14:19:48 2023 From: yetanothergeek at gmail.com (Jeff Pohlmeyer) Date: Fri, 28 Apr 2023 09:19:48 -0500 Subject: Busybox modprobe brings error "Invalid ELF header magic: !=ELF" In-Reply-To: References: <6fe13fa9-bc25-1aec-ac1f-59e34435be51@mayer-emi.at> <1c951152-2011-6184-10a4-95c51266c906@mayer-emi.at> Message-ID: On Fri, Mar 31, 2023 at 6:20?AM Denys Vlasenko wrote: > Kernel does not auto-detect compressed modules. > We need to call finit_module() with MODULE_INIT_COMPRESSED_FILE flag > if module is compressed. > > Fixed it in git. Please try it now. This is not working for me. In the best case, finit_module() tries the MODULE_INIT_COMPRESSED_FILE flag and returns -1 with errno set to ENOEXEC (Exec format error). It then tries again with the flag set to zero and returns the same error. Then it continues on to the init_module() call, which successfully loads the module. But in the worst case (which seems to happen randomly), finit_module() tries the MODULE_INIT_COMPRESSED_FILE flag and immediately receives a SIGKILL, killing busybox and failing to load the module. (See attachment for dmesg output.) This is on Artix Linux with their stock kernel 6.2.11. The modules are zstd compressed and my busybox has the zstd patch applied, but I don't think that is causing the problem since the random crashes occur when the kernel is asked to do the decompression. If the code makes it to the part where busybox does the decompression, all is well. If I completely disable the `#ifdef __NR_finit_module` block, everything works just fine. I wonder how many people actually need this feature -- maybe there could be a build option to disable it? I didn't find any usage of MODULE_INIT_COMPRESSED_FILE in the kmod-30 sources, and there is scant mention of it on google or bing. - Jeff -------------- next part -------------- A non-text attachment was scrubbed... Name: bb-modprobe.dmesg Type: application/octet-stream Size: 5108 bytes Desc: not available URL: From saproj at gmail.com Sat Apr 29 08:40:24 2023 From: saproj at gmail.com (Sergei Antonov) Date: Sat, 29 Apr 2023 11:40:24 +0300 Subject: [PATCH] ed: shift curNum after inserting a line before it Message-ID: <20230429084024.302826-1-saproj@gmail.com> Steps to reproduce the bug: echo "A B C D" > file ed file << END 1 i a . w q END --- editors/ed.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/editors/ed.c b/editors/ed.c index 4a84f7433808..de40614bb213 100644 --- a/editors/ed.c +++ b/editors/ed.c @@ -346,6 +346,8 @@ static int insertLine(int num, const char *data, int len) lp->prev = newLp; lastNum++; + if (curNum > 0 && curNum >= num) + curNum++; dirty = TRUE; return setCurNum(num); } -- 2.37.2 From dario.binacchi at amarulasolutions.com Sun Apr 30 09:52:26 2023 From: dario.binacchi at amarulasolutions.com (Dario Binacchi) Date: Sun, 30 Apr 2023 11:52:26 +0200 Subject: [RFC PATCH] ip link: support for the CAN netlink In-Reply-To: References: <20230420193533.1963524-1-dario.binacchi@amarulasolutions.com> Message-ID: Hi Nikolaus, On Thu, Apr 27, 2023 at 11:28?AM Nikolaus Voss wrote: > > Hi Dario, > > I posted a more minimalistic approach This is the reason why I added the CONFIG_IPLINK_CAN option. My use case also required management of the 'loopback' and 'listenonly' options: ip link set can0 type can bitrate 125000 loopback on listen-only on https://lore.kernel.org/all/20230328073328.3949796-6-dario.binacchi at amarulasolutions.com/ Anyway, I think we both agree that busybox lacks a CAN-type management for the 'ip link' command Thanks and regards, Dario > some time ago: > > http://lists.busybox.net/pipermail/busybox/2022-August/089822.html > > Thanks, > Niko > > > On Thu, 20 Apr 2023, Dario Binacchi wrote: > > > I developed this application to test the Linux kernel series [1]. As > > described in the cover letter I could not use the iproute2 package > > since the microcontroller is without MMU. > > > > cc: Marc Kleine-Budde > > [1] https://marc.info/?l=linux-netdev&m=167999323611710&w=2 > > Signed-off-by: Dario Binacchi > > --- > > configs/TEST_nommu_defconfig | 1 + > > networking/ip.c | 84 ++++++++++ > > networking/libiproute/iplink.c | 298 ++++++++++++++++++++++++++++++++- > > 3 files changed, 374 insertions(+), 9 deletions(-) > > > > diff --git a/configs/TEST_nommu_defconfig b/configs/TEST_nommu_defconfig > > index 415f5a8027f9..fa3e9632622a 100644 > > --- a/configs/TEST_nommu_defconfig > > +++ b/configs/TEST_nommu_defconfig > > @@ -703,6 +703,7 @@ CONFIG_FEATURE_INETD_RPC=y > > CONFIG_IP=y > > CONFIG_FEATURE_IP_ADDRESS=y > > CONFIG_FEATURE_IP_LINK=y > > +CONFIG_FEATURE_IP_LINK_CAN=y > > CONFIG_FEATURE_IP_ROUTE=y > > CONFIG_FEATURE_IP_TUNNEL=y > > CONFIG_FEATURE_IP_RULE=y > > diff --git a/networking/ip.c b/networking/ip.c > > index 7c320869958a..4959e9f25288 100644 > > --- a/networking/ip.c > > +++ b/networking/ip.c > > @@ -32,6 +32,14 @@ > > //config: help > > //config: Short form of "ip link" > > //config: > > +//config:config IPLINK_CAN > > +//config: bool "iplink for CAN (4.6 kb)" > > +//config: default n > > +//config: depends on IPLINK > > +//config: select FEATURE_IP_LINK_CAN > > +//config: help > > +//config: Short form of "ip link" for CAN > > +//config: > > //config:config IPROUTE > > //config: bool "iproute (15 kb)" > > //config: default y > > @@ -74,6 +82,13 @@ > > //config: help > > //config: Configure network devices with "ip". > > //config: > > +//config:config FEATURE_IP_LINK_CAN > > +//config: bool "ip link can" > > +//config: default n > > +//config: depends on IP_LINK_CAN > > +//config: help > > +//config: Configure CAN devices with "ip". > > +//config: > > //config:config FEATURE_IP_ROUTE > > //config: bool "ip route" > > //config: default y > > @@ -122,6 +137,7 @@ > > //applet:IF_IP( APPLET_NOEXEC(ip , ip , BB_DIR_SBIN, BB_SUID_DROP, ip )) > > //applet:IF_IPADDR( APPLET_NOEXEC(ipaddr , ipaddr , BB_DIR_SBIN, BB_SUID_DROP, ipaddr )) > > //applet:IF_IPLINK( APPLET_NOEXEC(iplink , iplink , BB_DIR_SBIN, BB_SUID_DROP, iplink )) > > +//applet:IF_IPLINK_CAN(APPLET_NOEXEC(iplinkcan , iplinkcan , BB_DIR_SBIN, BB_SUID_DROP, iplinkcan)) > > //applet:IF_IPROUTE( APPLET_NOEXEC(iproute , iproute , BB_DIR_SBIN, BB_SUID_DROP, iproute )) > > //applet:IF_IPRULE( APPLET_NOEXEC(iprule , iprule , BB_DIR_SBIN, BB_SUID_DROP, iprule )) > > //applet:IF_IPTUNNEL(APPLET_NOEXEC(iptunnel, iptunnel, BB_DIR_SBIN, BB_SUID_DROP, iptunnel)) > > @@ -130,6 +146,7 @@ > > //kbuild:lib-$(CONFIG_IP) += ip.o > > //kbuild:lib-$(CONFIG_IPADDR) += ip.o > > //kbuild:lib-$(CONFIG_IPLINK) += ip.o > > +//kbuild:lib-$(CONFIG_IPLINK_CAN) += ip.o > > //kbuild:lib-$(CONFIG_IPROUTE) += ip.o > > //kbuild:lib-$(CONFIG_IPRULE) += ip.o > > //kbuild:lib-$(CONFIG_IPTUNNEL) += ip.o > > @@ -149,10 +166,16 @@ > > //usage: "ipaddr show|flush [dev IFACE] [scope SCOPE] [to PREFIX] [label PATTERN]" > > //usage: > > //--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 > > +//usage:#if ENABLE_FEATURE_IP_LINK_CAN > > +//usage:#define iplink_type_usage "\n [type TYPE ARGS]" > > +//usage:#else > > +//usage:#define iplink_type_usage "" > > +//usage:#endif > > //usage:#define iplink_trivial_usage > > //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" > > //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" > > //usage: " [master IFACE | nomaster] [netns PID]" > > +//usage: IF_FEATURE_IP_LINK(iplink_type_usage) > > // * short help shows only "set" command, long help continues (with just one "\n") > > // * and shows all other commands: > > //usage:#define iplink_full_usage "\n" > > @@ -207,6 +230,59 @@ > > // bond_slave | ipvlan | geneve | bridge_slave | vrf } > > //usage: > > //--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 > > +//usage:#define iplinkcan_trivial_usage > > +//usage: /*Usage:iplinkcan*/"set DEVICE type can" > > +//usage:#define iplinkcan_full_usage "\n\n" > > +//usage: " [bitrate BITRATE [sample-point SAMPLE-POINT]] |\n" > > +//usage: " [tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1\n" > > +//usage: " phase-seg2 PHASE-SEG2 [sjw SJW]]\n" > > +//usage: "\n" > > +//usage: " [dbitrate BITRATE [dsample-point SAMPLE-POINT]] |\n" > > +//usage: " [dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1\n" > > +//usage: " dphase-seg2 PHASE-SEG2 [dsjw SJW]]\n" > > +//usage: "\n" > > +//usage: " [loopback on|off] [listen-only on|off] [triple-sampling on|off]\n" > > +//usage: " [one-shot on|off] [berr-reporting on|off]\n" > > +//usage: " [fd on|off] [fd-non-iso on|off] [presume-ack on|off]\n" > > +//usage: "\n" > > +//usage: " [restart-ms TIME-MS] [restart]\n" > > +//usage: "\n" > > +//usage: " [termination 0..65535]\n" > > +//usage: > > +//upstream man ip-link-can: > > +//Usage: ip link set DEVICE type can > > +// [ bitrate BITRATE [ sample-point SAMPLE-POINT] ] | > > +// [ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1 > > +// phase-seg2 PHASE-SEG2 [ sjw SJW ] ] > > +// > > +// [ dbitrate BITRATE [ dsample-point SAMPLE-POINT] ] | > > +// [ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1 > > +// dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ] > > +// > > +// [ loopback { on | off } ] > > +// [ listen-only { on | off } ] > > +// [ triple-sampling { on | off } ] > > +// [ one-shot { on | off } ] > > +// [ berr-reporting { on | off } ] > > +// [ fd { on | off } ] > > +// [ fd-non-iso { on | off } ] > > +// [ presume-ack { on | off } ] > > +// > > +// [ restart-ms TIME-MS ] > > +// [ restart ] > > +// > > +// [ termination { 0..65535 } ] > > +// > > +// Where: BITRATE := { 1..1000000 } > > +// SAMPLE-POINT := { 0.000..0.999 } > > +// TQ := { NUMBER } > > +// PROP-SEG := { 1..8 } > > +// PHASE-SEG1 := { 1..8 } > > +// PHASE-SEG2 := { 1..8 } > > +// SJW := { 1..4 } > > +// RESTART-MS := { 0 | NUMBER } > > +//usage: > > +//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 > > //usage:#define iproute_trivial_usage > > //usage: "list|flush|add|del|change|append|replace|test ROUTE" > > //usage:#define iproute_full_usage "\n\n" > > @@ -327,6 +403,7 @@ typedef int FAST_FUNC (*ip_func_ptr_t)(char**); > > > > #if ENABLE_IPADDR \ > > || ENABLE_IPLINK \ > > + || ENABLE_IPLINK_CAN \ > > || ENABLE_IPROUTE \ > > || ENABLE_IPRULE \ > > || ENABLE_IPTUNNEL \ > > @@ -352,6 +429,13 @@ int iplink_main(int argc UNUSED_PARAM, char **argv) > > return ip_do(do_iplink, argv); > > } > > #endif > > +#if ENABLE_IPLINK_CAN > > +int iplinkcan_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; > > +int iplinkcan_main(int argc UNUSED_PARAM, char **argv) > > +{ > > + return ip_do(do_iplink, argv); > > +} > > +#endif > > #if ENABLE_IPROUTE > > int iproute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; > > int iproute_main(int argc UNUSED_PARAM, char **argv) > > diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c > > index 68d1990445fe..f97169714d0f 100644 > > --- a/networking/libiproute/iplink.c > > +++ b/networking/libiproute/iplink.c > > @@ -11,10 +11,17 @@ > > #include > > > > #include > > +#include > > #include "ip_common.h" /* #include "libbb.h" is inside */ > > #include "rt_names.h" > > #include "utils.h" > > > > +#if ENABLE_FEATURE_IP_LINK_CAN > > +#define ENABLE_FEATURE_IP_LINK_IFACE 1 > > +#else > > +#define ENABLE_FEATURE_IP_LINK_IFACE 0 > > +#endif > > + > > #undef ETH_P_8021AD > > #define ETH_P_8021AD 0x88A8 > > #undef VLAN_FLAG_REORDER_HDR > > @@ -28,6 +35,11 @@ > > #undef IFLA_VLAN_PROTOCOL > > #define IFLA_VLAN_PROTOCOL 5 > > > > +#ifndef NLMSG_TAIL > > +#define NLMSG_TAIL(nmsg) \ > > + ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) > > +#endif > > + > > #ifndef IFLA_LINKINFO > > # define IFLA_LINKINFO 18 > > # define IFLA_INFO_KIND 1 > > @@ -55,6 +67,13 @@ struct ifla_vlan_flags { > > > > #define str_on_off "on\0""off\0" > > > > +enum { > > + PARM_on = 0, > > + PARM_off > > +}; > > + > > +typedef void FAST_FUNC(*ip_type_set_func_ptr_t)(char*, char**); > > + > > /* Exits on error */ > > static int get_ctl_fd(void) > > { > > @@ -241,10 +260,261 @@ static void die_must_be_on_off(const char *msg) > > bb_error_msg_and_die("argument of \"%s\" must be \"on\" or \"off\"", msg); > > } > > > > +#if ENABLE_FEATURE_IP_LINK_CAN > > +static float FAST_FUNC get_float(char *arg, const char *errmsg) > > +{ > > + float ret; > > + char *ptr; > > + > > + if (!arg || !*arg) > > + invarg_1_to_2(arg, errmsg); /* does not return */ > > + > > + ret = strtof(arg, &ptr); > > + if (!ptr || ptr == arg || *ptr) > > + invarg_1_to_2(arg, errmsg); /* does not return */ > > + > > + return ret; > > +} > > + > > +static void do_set_can(char *dev, char **argv) > > +{ > > + struct can_bittiming bt = {}, dbt = {}; > > + struct can_ctrlmode cm = {}; > > + char *keyword; > > + static const char keywords[] ALIGN1 = > > + "bitrate\0""sample-point\0""tq\0" > > + "prop-seg\0""phase-seg1\0""phase-seg2\0""sjw\0" > > + "dbitrate\0""dsample-point\0""dtq\0" > > + "dprop-seg\0""dphase-seg1\0""dphase-seg2\0""dsjw\0" > > + "loopback\0""listen-only\0""triple-sampling\0" > > + "one-shot\0""berr-reporting\0" > > + "fd\0""fd-non-iso\0""presume-ack\0" > > + "cc-len8-dlc\0""restart\0""restart-ms\0" > > + "termination\0"; > > + enum { ARG_bitrate = 0, ARG_sample_point, ARG_tq, > > + ARG_prop_seg, ARG_phase_seg1, ARG_phase_seg2, ARG_sjw, > > + ARG_dbitrate, ARG_dsample_point, ARG_dtq, > > + ARG_dprop_seg, ARG_dphase_seg1, ARG_dphase_seg2, ARG_dsjw, > > + ARG_loopback, ARG_listen_only, ARG_triple_sampling, > > + ARG_one_shot, ARG_berr_reporting, > > + ARG_fd, ARG_fd_non_iso, ARG_presume_ack, > > + ARG_cc_len8_dlc, ARG_restart, ARG_restart_ms, > > + ARG_termination }; > > + struct rtnl_handle rth; > > + struct { > > + struct nlmsghdr n; > > + struct ifinfomsg i; > > + char buf[1024]; > > + } req; > > + size_t dev_len; > > + struct rtattr *linkinfo, *data; > > + smalluint key, param; > > + > > + memset(&req, 0, sizeof(req)); > > + > > + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); > > + req.n.nlmsg_flags = NLM_F_REQUEST; > > + req.n.nlmsg_type = RTM_NEWLINK; > > + req.i.ifi_family = preferred_family; > > + xrtnl_open(&rth); > > + req.i.ifi_index = xll_name_to_index(dev); > > + dev_len = strlen(dev); > > + if (dev_len < 2 || dev_len > IFNAMSIZ) > > + invarg_1_to_2(dev, "dev"); > > + > > + addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, dev_len); > > + linkinfo = NLMSG_TAIL(&req.n); > > + addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); > > + addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (void *)"can", > > + strlen("can")); > > + data = NLMSG_TAIL(&req.n); > > + addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0); > > + while (*argv) { > > + key = index_in_substrings(keywords, *argv); > > + keyword = *argv; > > + //printf("%s: key: %d, *argv: %s\n", __func__, key, *argv); > > + switch (key) { > > + case ARG_bitrate: > > + case ARG_tq: > > + case ARG_prop_seg: > > + case ARG_phase_seg1: > > + case ARG_phase_seg2: > > + case ARG_sjw: { > > + __u32 *val; > > + > > + NEXT_ARG(); > > + if (key == ARG_bitrate) > > + val = &bt.bitrate; > > + else if (key == ARG_tq) > > + val = &bt.tq; > > + else if (key == ARG_prop_seg) > > + val = &bt.prop_seg; > > + else if (key == ARG_phase_seg1) > > + val = &bt.phase_seg1; > > + else if (key == ARG_phase_seg2) > > + val = &bt.phase_seg2; > > + else > > + val = &bt.sjw; > > + > > + *val = get_u32(*argv, keyword); > > + break; > > + } > > + case ARG_sample_point: { > > + float sp; > > + > > + NEXT_ARG(); > > + sp = get_float(*argv, keyword); > > + bt.sample_point = (__u32)(sp * 1000); > > + break; > > + } > > + case ARG_dbitrate: > > + case ARG_dtq: > > + case ARG_dprop_seg: > > + case ARG_dphase_seg1: > > + case ARG_dphase_seg2: > > + case ARG_dsjw: { > > + __u32 *val; > > + > > + NEXT_ARG(); > > + if (key == ARG_dbitrate) > > + val = &dbt.bitrate; > > + else if (key == ARG_dtq) > > + val = &dbt.tq; > > + else if (key == ARG_dprop_seg) > > + val = &dbt.prop_seg; > > + else if (key == ARG_dphase_seg1) > > + val = &dbt.phase_seg1; > > + else if (key == ARG_dphase_seg2) > > + val = &dbt.phase_seg2; > > + else > > + val = &dbt.sjw; > > + > > + *val = get_u32(*argv, keyword); > > + break; > > + } > > + case ARG_dsample_point: { > > + float sp; > > + > > + NEXT_ARG(); > > + sp = get_float(*argv, keyword); > > + dbt.sample_point = (__u32)(sp * 1000); > > + break; > > + } > > + case ARG_loopback: > > + case ARG_listen_only: > > + case ARG_triple_sampling: > > + case ARG_one_shot: > > + case ARG_berr_reporting: > > + case ARG_fd: > > + case ARG_fd_non_iso: > > + case ARG_presume_ack: > > + case ARG_cc_len8_dlc: { > > + __u32 flag = 0; > > + > > + NEXT_ARG(); > > + param = index_in_strings(str_on_off, *argv); > > + if (param < 0) > > + die_must_be_on_off(keyword); > > + > > + if (key == ARG_loopback) > > + flag = CAN_CTRLMODE_LOOPBACK; > > + else if (key == ARG_listen_only) > > + flag = CAN_CTRLMODE_LISTENONLY; > > + else if (key == ARG_triple_sampling) > > + flag = CAN_CTRLMODE_3_SAMPLES; > > + else if (key == ARG_one_shot) > > + flag = CAN_CTRLMODE_ONE_SHOT; > > + else if (key == ARG_berr_reporting) > > + flag = CAN_CTRLMODE_BERR_REPORTING; > > + else if (key == ARG_fd) > > + flag = CAN_CTRLMODE_FD; > > + else if (key == ARG_fd_non_iso) > > + flag = CAN_CTRLMODE_FD_NON_ISO; > > + else if (key == ARG_presume_ack) > > + flag = CAN_CTRLMODE_PRESUME_ACK; > > + else > > +#if defined(CAN_CTRLMODE_CC_LEN8_DLC) > > + flag = CAN_CTRLMODE_CC_LEN8_DLC; > > +#else > > + die_must_be_on_off(keyword); > > +#endif > > + cm.mask |= flag; > > + if (param == PARM_on) > > + cm.flags |= flag; > > + > > + break; > > + } > > + case ARG_restart: { > > + __u32 val = 1; > > + > > + NEXT_ARG(); > > + addattr_l(&req.n, sizeof(req), IFLA_CAN_RESTART, &val, sizeof(val)); > > + break; > > + } > > + case ARG_restart_ms: { > > + __u32 val; > > + > > + NEXT_ARG(); > > + val = get_u32(*argv, keyword); > > + addattr_l(&req.n, sizeof(req), IFLA_CAN_RESTART_MS, &val, sizeof(val)); > > + break; > > + } > > + case ARG_termination: { > > + __u16 val; > > + > > + NEXT_ARG(); > > + val = get_u16(*argv, keyword); > > + addattr_l(&req.n, sizeof(req), IFLA_CAN_TERMINATION, &val, sizeof(val)); > > + break; > > + } > > + default: > > + break; > > + } > > + > > + argv++; > > + } > > + > > + if (bt.bitrate || bt.tq) > > + addattr_l(&req.n, sizeof(req), IFLA_CAN_BITTIMING, &bt, sizeof(bt)); > > + > > + if (cm.mask) > > + addattr_l(&req.n, sizeof(req), IFLA_CAN_CTRLMODE, &cm, sizeof(cm)); > > + > > + data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; > > + linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; > > + > > + if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) > > + xfunc_die(); > > +} > > +#endif > > + > > +#if ENABLE_FEATURE_IP_LINK_IFACE > > +static void do_set_iface(char *type, char *dev, char **argv) > > +{ > > + static const char keywords[] ALIGN1 = "" > > + IF_FEATURE_IP_LINK_CAN("can\0") > > + ; > > + static const ip_type_set_func_ptr_t funcs[] ALIGN_PTR = { > > + IF_FEATURE_IP_LINK_CAN(do_set_can,) > > + }; > > + ip_type_set_func_ptr_t func; > > + int key; > > + > > + key = index_in_substrings(keywords, type); > > + if (key < 0) > > + return; > > + func = funcs[key]; > > + func(dev, argv); > > +} > > +#endif > > + > > /* Return value becomes exitcode. It's okay to not return at all */ > > static int do_set(char **argv) > > { > > char *dev = NULL; > > +#if ENABLE_FEATURE_IP_LINK_IFACE > > + char *type = NULL; > > +#endif > > uint32_t mask = 0; > > uint32_t flags = 0; > > int qlen = -1; > > @@ -261,18 +531,24 @@ static int do_set(char **argv) > > "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" > > "arp\0""promisc\0""address\0""netns\0" > > "master\0""nomaster\0" > > +#if ENABLE_FEATURE_IP_LINK_IFACE > > + "type\0" > > +#endif > > "dev\0" /* must be last */; > > enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, > > ARG_arp, ARG_promisc, ARG_addr, ARG_netns, > > ARG_master, ARG_nomaster, > > +#if ENABLE_FEATURE_IP_LINK_IFACE > > + ARG_type, > > +#endif > > ARG_dev }; > > - enum { PARM_on = 0, PARM_off }; > > smalluint key; > > > > while (*argv) { > > /* substring search ensures that e.g. "addr" and "address" > > * are both accepted */ > > key = index_in_substrings(keywords, *argv); > > + //printf("%s: key: %d, *argv: %s\n", __func__, key, *argv); > > if (key == ARG_up) { > > mask |= IFF_UP; > > flags |= IFF_UP; > > @@ -304,6 +580,13 @@ static int do_set(char **argv) > > } else if (key == ARG_netns) { > > NEXT_ARG(); > > netns = get_unsigned(*argv, "netns"); > > +#if ENABLE_FEATURE_IP_LINK_IFACE > > + } else if (key == ARG_type) { > > + NEXT_ARG(); > > + type = *argv; > > + argv++; > > + break; > > +#endif > > } else if (key >= ARG_dev) { > > /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */ > > if (key == ARG_dev) { > > @@ -311,6 +594,7 @@ static int do_set(char **argv) > > } > > if (dev) > > duparg2("dev", *argv); > > + > > dev = *argv; > > } else { > > /* "on|off" options */ > > @@ -496,6 +780,10 @@ static int do_set(char **argv) > > } > > if (mask) > > do_chflags(dev, flags, mask); > > +#if ENABLE_FEATURE_IP_LINK_IFACE > > + if (type) > > + do_set_iface(type, dev, argv); > > +#endif > > return 0; > > } > > > > @@ -531,10 +819,6 @@ static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size) > > PROTO_8021Q = 0, > > PROTO_8021AD, > > }; > > - enum { > > - PARM_on = 0, > > - PARM_off > > - }; > > int arg; > > uint16_t id, proto; > > struct ifla_vlan_flags flags = {}; > > @@ -610,10 +894,6 @@ static void vrf_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size) > > addattr_l(n, size, IFLA_VRF_TABLE, &table, sizeof(table)); > > } > > > > -#ifndef NLMSG_TAIL > > -#define NLMSG_TAIL(nmsg) \ > > - ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) > > -#endif > > /* Return value becomes exitcode. It's okay to not return at all */ > > static int do_add_or_delete(char **argv, const unsigned rtm) > > { > > > -- Dario Binacchi Senior Embedded Linux Developer dario.binacchi at amarulasolutions.com __________________________________ Amarula Solutions SRL Via Le Canevare 30, 31100 Treviso, Veneto, IT T. +39 042 243 5310 info at amarulasolutions.com www.amarulasolutions.com