Initial commit

This commit is contained in:
domenico
2025-06-24 16:03:39 +02:00
commit f3256cdaf2
6949 changed files with 1441681 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
--- a/scripts/trylink
+++ b/scripts/trylink
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
debug=false

View File

@@ -0,0 +1,8 @@
--- a/scripts/gen_build_files.sh
+++ b/scripts/gen_build_files.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
# Note: was using sed OPTS CMD -- FILES
# but users complain that many sed implementations

View File

@@ -0,0 +1,11 @@
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -51,7 +51,7 @@ CFLAGS += $(call cc-option,-fno-builtin-
# -fno-guess-branch-probability: prohibit pseudo-random guessing
# of branch probabilities (hopefully makes bloatcheck more stable):
CFLAGS += $(call cc-option,-fno-guess-branch-probability,)
-CFLAGS += $(call cc-option,-funsigned-char -static-libgcc,)
+CFLAGS += $(call cc-option,-funsigned-char,)
CFLAGS += $(call cc-option,-falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1,)
# Defeat .eh_frame bloat (gcc 4.6.3 x86-32 defconfig: 20% smaller busybox binary):
CFLAGS += $(call cc-option,-fno-unwind-tables,)

View File

@@ -0,0 +1,27 @@
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -130,7 +130,7 @@ make-cmd = $(subst \#,\\\#,$(subst $$,$$
#
if_changed = $(if $(strip $(filter-out $(PHONY),$?) \
$(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
- @set -e; \
+ +@set -e; \
$(echo-cmd) $(cmd_$(1)); \
echo 'cmd_$@ := $(make-cmd)' > $(@D)/.$(@F).cmd)
@@ -139,7 +139,7 @@ if_changed = $(if $(strip $(filter-out $
if_changed_dep = $(if $(strip $(filter-out $(PHONY),$?) \
$(filter-out FORCE $(wildcard $^),$^) \
$(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
- @set -e; \
+ +@set -e; \
$(echo-cmd) $(cmd_$(1)); \
scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
@@ -150,5 +150,5 @@ if_changed_dep = $(if $(strip $(filter-o
# and if so will execute $(rule_foo)
if_changed_rule = $(if $(strip $(filter-out $(PHONY),$?) \
$(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
- @set -e; \
+ +@set -e; \
$(rule_$(1)))

View File

@@ -0,0 +1,18 @@
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -713,6 +713,7 @@ static int bcast_or_ucast(struct dhcp_pa
static NOINLINE int send_discover(uint32_t xid, uint32_t requested)
{
struct dhcp_packet packet;
+ static int msgs = 0;
/* Fill in: op, htype, hlen, cookie, chaddr fields,
* random xid field (we override it below),
@@ -730,6 +731,7 @@ static NOINLINE int send_discover(uint32
*/
add_client_options(&packet);
+ if (msgs++ < 3)
bb_error_msg("sending %s", "discover");
return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
}

View File

@@ -0,0 +1,15 @@
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -1417,6 +1417,12 @@ int udhcpc_main(int argc UNUSED_PARAM, c
/* silence "uninitialized!" warning */
unsigned timestamp_before_wait = timestamp_before_wait;
+ /* When running on a bridge, the ifindex may have changed (e.g. if
+ * member interfaces were added/removed or if the status of the
+ * bridge changed).
+ * Workaround: refresh it here before processing the next packet */
+ udhcp_read_interface(client_config.interface, &client_config.ifindex, NULL, client_config.client_mac);
+
//bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode);
/* Was opening raw or udp socket here

View File

@@ -0,0 +1,10 @@
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -1128,7 +1128,6 @@ static void perform_renew(void)
state = RENEW_REQUESTED;
break;
case RENEW_REQUESTED: /* impatient are we? fine, square 1 */
- udhcp_run_script(NULL, "deconfig");
case REQUESTING:
case RELEASED:
change_listen_mode(LISTEN_RAW);

View File

@@ -0,0 +1,79 @@
--- /dev/null
+++ b/networking/netmsg.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2006 Felix Fietkau <nbd@nbd.name>
+ *
+ * This is free software, licensed under the GNU General Public License v2.
+ */
+
+//config:config NETMSG
+//config: bool "netmsg"
+//config: default n
+//config: help
+//config: simple program for sending udp broadcast messages
+
+//applet:IF_NETMSG(APPLET(netmsg, BB_DIR_BIN, BB_SUID_REQUIRE))
+
+//kbuild:lib-$(CONFIG_NETMSG) += netmsg.o
+
+//usage:#define netmsg_trivial_usage NOUSAGE_STR
+//usage:#define netmsg_full_usage ""
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "busybox.h"
+
+#ifndef CONFIG_NETMSG
+int main(int argc, char **argv)
+#else
+int netmsg_main(int argc, char **argv)
+#endif
+{
+ int s;
+ struct sockaddr_in addr;
+ int optval = 1;
+ unsigned char buf[1001];
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s <ip> \"<message>\"\n", argv[0]);
+ exit(1);
+ }
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("Opening socket");
+ exit(1);
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr(argv[1]);
+ addr.sin_port = htons(0x1337);
+
+ memset(buf, 0, 1001);
+ buf[0] = 0xde;
+ buf[1] = 0xad;
+
+ strncpy(buf + 2, argv[2], 998);
+
+ if (setsockopt (s, SOL_SOCKET, SO_BROADCAST, (caddr_t) &optval, sizeof (optval)) < 0) {
+ perror("setsockopt()");
+ goto fail;
+ }
+
+ if (sendto(s, buf, 1001, 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("sendto()");
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ close(s);
+ exit(1);
+}

View File

@@ -0,0 +1,158 @@
--- /dev/null
+++ b/miscutils/lock.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2006 Felix Fietkau <nbd@nbd.name>
+ *
+ * This is free software, licensed under the GNU General Public License v2.
+ */
+
+//config:config LOCK
+//config: bool "lock"
+//config: default n
+//config: help
+//config: Small utility for using locks in scripts
+
+//applet:IF_LOCK(APPLET(lock, BB_DIR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_LOCK) += lock.o
+
+//usage:#define lock_trivial_usage NOUSAGE_STR
+//usage:#define lock_full_usage ""
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "busybox.h"
+
+static int unlock = 0;
+static int shared = 0;
+static int waitonly = 0;
+static int try_lock = 0;
+static int fd;
+static char *file;
+
+static void usage(char *name)
+{
+ fprintf(stderr, "Usage: %s [-suw] <filename>\n"
+ " -s Use shared locking\n"
+ " -u Unlock\n"
+ " -w Wait for the lock to become free, don't acquire lock\n"
+ " -n Don't wait for the lock to become free. Fail with exit code\n"
+ "\n", name);
+ exit(1);
+}
+
+static void exit_unlock(int sig)
+{
+ flock(fd, LOCK_UN);
+ exit(0);
+}
+
+static int do_unlock(void)
+{
+ FILE *f;
+ int i;
+
+ if ((f = fopen(file, "r")) == NULL)
+ return 0;
+
+ fscanf(f, "%d", &i);
+ if (i > 0)
+ kill(i, SIGTERM);
+
+ fclose(f);
+
+ return 0;
+}
+
+static int do_lock(void)
+{
+ int pid;
+ int flags;
+ char pidstr[8];
+
+ if ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0700)) < 0) {
+ if ((fd = open(file, O_RDWR)) < 0) {
+ fprintf(stderr, "Can't open %s\n", file);
+ return 1;
+ }
+ }
+
+ flags = shared ? LOCK_SH : LOCK_EX;
+ flags |= try_lock ? LOCK_NB : 0;
+
+ if (flock(fd, flags) < 0) {
+ fprintf(stderr, "Can't lock %s\n", file);
+ return 1;
+ }
+
+ pid = fork();
+
+ if (pid < 0)
+ return -1;
+
+ if (pid == 0) {
+ signal(SIGKILL, exit_unlock);
+ signal(SIGTERM, exit_unlock);
+ signal(SIGINT, exit_unlock);
+ if (waitonly)
+ exit_unlock(0);
+ else
+ while (1)
+ sleep(1);
+ } else {
+ if (!waitonly) {
+ lseek(fd, 0, SEEK_SET);
+ ftruncate(fd, 0);
+ sprintf(pidstr, "%d\n", pid);
+ write(fd, pidstr, strlen(pidstr));
+ close(fd);
+ }
+
+ return 0;
+ }
+ return 0;
+}
+
+int lock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int lock_main(int argc, char **argv)
+{
+ char **args = &argv[1];
+ int c = argc - 1;
+
+ while ((*args != NULL) && (*args)[0] == '-') {
+ char *ch = *args;
+ while (*(++ch) > 0) {
+ switch(*ch) {
+ case 'w':
+ waitonly = 1;
+ break;
+ case 's':
+ shared = 1;
+ break;
+ case 'u':
+ unlock = 1;
+ break;
+ case 'n':
+ try_lock = 1;
+ break;
+ }
+ }
+ c--;
+ args++;
+ }
+
+ if (c != 1)
+ usage(argv[0]);
+
+ file = *args;
+ if (unlock)
+ return do_unlock();
+ else
+ return do_lock();
+}

View File

@@ -0,0 +1,951 @@
From ab0f8bb80527928f513297ab93e3ec8c8b48dd50 Mon Sep 17 00:00:00 2001
From: Jo-Philipp Wich <jo@mein.io>
Date: Tue, 14 Mar 2017 22:21:34 +0100
Subject: [PATCH] networking: add LEDE nslookup applet
Add a new LEDE nslookup applet which is compatible with musl libc
and providing more features like ability to specify query type.
In contrast to busybox' builtin nslookup applet, this variant does
not rely on libc resolver internals but uses explicit send logic
and the libresolv primitives to parse received DNS responses.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
---
Makefile.flags | 6 +
networking/nslookup_lede.c | 915 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 921 insertions(+)
create mode 100644 networking/nslookup_lede.c
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -134,6 +134,12 @@ else
LDLIBS += m
endif
+# nslookup_lede might need the resolv library
+RESOLV_AVAILABLE := $(shell echo 'int main(void){res_init();return 0;}' >resolvtest.c; $(CC) $(CFLAGS) -include resolv.h -lresolv -o /dev/null resolvtest.c >/dev/null 2>&1 && echo "y"; rm resolvtest.c)
+ifeq ($(RESOLV_AVAILABLE),y)
+LDLIBS += resolv
+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
--- /dev/null
+++ b/networking/nslookup_lede.c
@@ -0,0 +1,914 @@
+/*
+ * nslookup_lede - musl compatible replacement for busybox nslookup
+ *
+ * Copyright (C) 2017 Jo-Philipp Wich <jo@mein.io>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+//config:config NSLOOKUP_OPENWRT
+//config: bool "nslookup_openwrt"
+//config: depends on !NSLOOKUP
+//config: default y
+//config: help
+//config: nslookup is a tool to query Internet name servers (LEDE flavor).
+//config:
+//config:config FEATURE_NSLOOKUP_OPENWRT_LONG_OPTIONS
+//config: bool "Enable long options"
+//config: default y
+//config: depends on NSLOOKUP_OPENWRT && LONG_OPTS
+//config: help
+//config: Support long options for the nslookup applet.
+
+//applet:IF_NSLOOKUP_OPENWRT(APPLET(nslookup, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_NSLOOKUP_OPENWRT) += nslookup_lede.o
+
+//usage:#define nslookup_lede_trivial_usage
+//usage: "[HOST] [SERVER]"
+//usage:#define nslookup_lede_full_usage "\n\n"
+//usage: "Query the nameserver for the IP address of the given HOST\n"
+//usage: "optionally using a specified DNS server"
+//usage:
+//usage:#define nslookup_lede_example_usage
+//usage: "$ nslookup localhost\n"
+//usage: "Server: default\n"
+//usage: "Address: default\n"
+//usage: "\n"
+//usage: "Name: debian\n"
+//usage: "Address: 127.0.0.1\n"
+
+#include <stdio.h>
+#include <resolv.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <poll.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netdb.h>
+
+#include "libbb.h"
+
+struct ns {
+ const char *name;
+ len_and_sockaddr addr;
+ int failures;
+ int replies;
+};
+
+struct query {
+ const char *name;
+ size_t qlen, rlen;
+ unsigned char query[512], reply[512];
+ unsigned long latency;
+ int rcode, n_ns;
+};
+
+static struct {
+ int type;
+ const char *name;
+} qtypes[] = {
+ { ns_t_soa, "SOA" },
+ { ns_t_ns, "NS" },
+ { ns_t_a, "A" },
+#if ENABLE_FEATURE_IPV6
+ { ns_t_aaaa, "AAAA" },
+#endif
+ { ns_t_cname, "CNAME" },
+ { ns_t_mx, "MX" },
+ { ns_t_txt, "TXT" },
+ { ns_t_ptr, "PTR" },
+ { ns_t_any, "ANY" },
+ { }
+};
+
+static const char *rcodes[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "NOTZONE",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15",
+ "BADVERS"
+};
+
+static unsigned int default_port = 53;
+static unsigned int default_retry = 2;
+static unsigned int default_timeout = 5;
+
+
+static int parse_reply(const unsigned char *msg, size_t len, int *bb_style_counter)
+{
+ ns_msg handle;
+ ns_rr rr;
+ int i, n, rdlen;
+ const char *format = NULL;
+ char astr[INET6_ADDRSTRLEN], dname[MAXDNAME];
+ const unsigned char *cp;
+
+ if (ns_initparse(msg, len, &handle) != 0) {
+ //fprintf(stderr, "Unable to parse reply: %s\n", strerror(errno));
+ return -1;
+ }
+
+ for (i = 0; i < ns_msg_count(handle, ns_s_an); i++) {
+ if (ns_parserr(&handle, ns_s_an, i, &rr) != 0) {
+ //fprintf(stderr, "Unable to parse resource record: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (bb_style_counter && *bb_style_counter == 1)
+ printf("Name: %s\n", ns_rr_name(rr));
+
+ rdlen = ns_rr_rdlen(rr);
+
+ switch (ns_rr_type(rr))
+ {
+ case ns_t_a:
+ if (rdlen != 4) {
+ //fprintf(stderr, "Unexpected A record length\n");
+ return -1;
+ }
+ inet_ntop(AF_INET, ns_rr_rdata(rr), astr, sizeof(astr));
+ if (bb_style_counter)
+ printf("Address %d: %s\n", (*bb_style_counter)++, astr);
+ else
+ printf("Name:\t%s\nAddress: %s\n", ns_rr_name(rr), astr);
+ break;
+
+#if ENABLE_FEATURE_IPV6
+ case ns_t_aaaa:
+ if (rdlen != 16) {
+ //fprintf(stderr, "Unexpected AAAA record length\n");
+ return -1;
+ }
+ inet_ntop(AF_INET6, ns_rr_rdata(rr), astr, sizeof(astr));
+ if (bb_style_counter)
+ printf("Address %d: %s\n", (*bb_style_counter)++, astr);
+ else
+ printf("%s\thas AAAA address %s\n", ns_rr_name(rr), astr);
+ break;
+#endif
+
+ case ns_t_ns:
+ if (!format)
+ format = "%s\tnameserver = %s\n";
+ /* fall through */
+
+ case ns_t_cname:
+ if (!format)
+ format = "%s\tcanonical name = %s\n";
+ /* fall through */
+
+ case ns_t_ptr:
+ if (!format)
+ format = "%s\tname = %s\n";
+ if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle),
+ ns_rr_rdata(rr), dname, sizeof(dname)) < 0) {
+ //fprintf(stderr, "Unable to uncompress domain: %s\n", strerror(errno));
+ return -1;
+ }
+ printf(format, ns_rr_name(rr), dname);
+ break;
+
+ case ns_t_mx:
+ if (rdlen < 2) {
+ fprintf(stderr, "MX record too short\n");
+ return -1;
+ }
+ n = ns_get16(ns_rr_rdata(rr));
+ if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle),
+ ns_rr_rdata(rr) + 2, dname, sizeof(dname)) < 0) {
+ //fprintf(stderr, "Cannot uncompress MX domain: %s\n", strerror(errno));
+ return -1;
+ }
+ printf("%s\tmail exchanger = %d %s\n", ns_rr_name(rr), n, dname);
+ break;
+
+ case ns_t_txt:
+ if (rdlen < 1) {
+ //fprintf(stderr, "TXT record too short\n");
+ return -1;
+ }
+ n = *(unsigned char *)ns_rr_rdata(rr);
+ if (n > 0) {
+ memset(dname, 0, sizeof(dname));
+ memcpy(dname, ns_rr_rdata(rr) + 1, n);
+ printf("%s\ttext = \"%s\"\n", ns_rr_name(rr), dname);
+ }
+ break;
+
+ case ns_t_soa:
+ if (rdlen < 20) {
+ //fprintf(stderr, "SOA record too short\n");
+ return -1;
+ }
+
+ printf("%s\n", ns_rr_name(rr));
+
+ cp = ns_rr_rdata(rr);
+ n = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle),
+ cp, dname, sizeof(dname));
+
+ if (n < 0) {
+ //fprintf(stderr, "Unable to uncompress domain: %s\n", strerror(errno));
+ return -1;
+ }
+
+ printf("\torigin = %s\n", dname);
+ cp += n;
+
+ n = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle),
+ cp, dname, sizeof(dname));
+
+ if (n < 0) {
+ //fprintf(stderr, "Unable to uncompress domain: %s\n", strerror(errno));
+ return -1;
+ }
+
+ printf("\tmail addr = %s\n", dname);
+ cp += n;
+
+ printf("\tserial = %lu\n", ns_get32(cp));
+ cp += 4;
+
+ printf("\trefresh = %lu\n", ns_get32(cp));
+ cp += 4;
+
+ printf("\tretry = %lu\n", ns_get32(cp));
+ cp += 4;
+
+ printf("\texpire = %lu\n", ns_get32(cp));
+ cp += 4;
+
+ printf("\tminimum = %lu\n", ns_get32(cp));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return i;
+}
+
+static int parse_nsaddr(const char *addrstr, len_and_sockaddr *lsa)
+{
+ char *eptr, *hash, ifname[IFNAMSIZ];
+ unsigned int port = default_port;
+ unsigned int scope = 0;
+
+ hash = strchr(addrstr, '#');
+
+ if (hash) {
+ *hash++ = '\0';
+ port = strtoul(hash, &eptr, 10);
+
+ if (eptr == hash || *eptr != '\0' || port > 65535) {
+ errno = EINVAL;
+ return -1;
+ }
+ }
+
+ hash = strchr(addrstr, '%');
+
+ if (hash) {
+ for (eptr = ++hash; *eptr != '\0' && *eptr != '#'; eptr++) {
+ if ((eptr - hash) >= IFNAMSIZ) {
+ errno = ENODEV;
+ return -1;
+ }
+
+ ifname[eptr - hash] = *eptr;
+ }
+
+ ifname[eptr - hash] = '\0';
+ scope = if_nametoindex(ifname);
+
+ if (scope == 0) {
+ errno = ENODEV;
+ return -1;
+ }
+ }
+
+#if ENABLE_FEATURE_IPV6
+ if (inet_pton(AF_INET6, addrstr, &lsa->u.sin6.sin6_addr)) {
+ lsa->u.sin6.sin6_family = AF_INET6;
+ lsa->u.sin6.sin6_port = htons(port);
+ lsa->u.sin6.sin6_scope_id = scope;
+ lsa->len = sizeof(lsa->u.sin6);
+ return 0;
+ }
+#endif
+
+ if (!scope && inet_pton(AF_INET, addrstr, &lsa->u.sin.sin_addr)) {
+ lsa->u.sin.sin_family = AF_INET;
+ lsa->u.sin.sin_port = htons(port);
+ lsa->len = sizeof(lsa->u.sin);
+ return 0;
+ }
+
+ errno = EINVAL;
+ return -1;
+}
+
+static char *make_ptr(const char *addrstr)
+{
+ const char *hexdigit = "0123456789abcdef";
+ static char ptrstr[73];
+ unsigned char addr[16];
+ char *ptr = ptrstr;
+ int i;
+
+ if (inet_pton(AF_INET6, addrstr, addr)) {
+ if (memcmp(addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12) != 0) {
+ for (i = 0; i < 16; i++) {
+ *ptr++ = hexdigit[(unsigned char)addr[15 - i] & 0xf];
+ *ptr++ = '.';
+ *ptr++ = hexdigit[(unsigned char)addr[15 - i] >> 4];
+ *ptr++ = '.';
+ }
+ strcpy(ptr, "ip6.arpa");
+ }
+ else {
+ sprintf(ptr, "%u.%u.%u.%u.in-addr.arpa",
+ addr[15], addr[14], addr[13], addr[12]);
+ }
+
+ return ptrstr;
+ }
+
+ if (inet_pton(AF_INET, addrstr, addr)) {
+ sprintf(ptr, "%u.%u.%u.%u.in-addr.arpa",
+ addr[3], addr[2], addr[1], addr[0]);
+ return ptrstr;
+ }
+
+ return NULL;
+}
+
+static unsigned long mtime(void)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ return (unsigned long)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+}
+
+#if ENABLE_FEATURE_IPV6
+static void to_v4_mapped(len_and_sockaddr *a)
+{
+ if (a->u.sa.sa_family != AF_INET)
+ return;
+
+ memcpy(a->u.sin6.sin6_addr.s6_addr + 12,
+ &a->u.sin.sin_addr, 4);
+
+ memcpy(a->u.sin6.sin6_addr.s6_addr,
+ "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
+
+ a->u.sin6.sin6_family = AF_INET6;
+ a->u.sin6.sin6_flowinfo = 0;
+ a->u.sin6.sin6_scope_id = 0;
+ a->len = sizeof(a->u.sin6);
+}
+#endif
+
+
+/*
+ * Function logic borrowed & modified from musl libc, res_msend.c
+ */
+
+static int send_queries(struct ns *ns, int n_ns, struct query *queries, int n_queries)
+{
+ int fd;
+ int timeout = default_timeout * 1000, retry_interval, servfail_retry = 0;
+ len_and_sockaddr from = { };
+#if ENABLE_FEATURE_IPV6
+ int one = 1;
+#endif
+ int recvlen = 0;
+ int n_replies = 0;
+ struct pollfd pfd;
+ unsigned long t0, t1, t2;
+ int nn, qn, next_query = 0;
+
+ from.u.sa.sa_family = AF_INET;
+ from.len = sizeof(from.u.sin);
+
+#if ENABLE_FEATURE_IPV6
+ for (nn = 0; nn < n_ns; nn++) {
+ if (ns[nn].addr.u.sa.sa_family == AF_INET6) {
+ from.u.sa.sa_family = AF_INET6;
+ from.len = sizeof(from.u.sin6);
+ break;
+ }
+ }
+#endif
+
+ /* Get local address and open/bind a socket */
+ fd = socket(from.u.sa.sa_family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+
+#if ENABLE_FEATURE_IPV6
+ /* Handle case where system lacks IPv6 support */
+ if (fd < 0 && from.u.sa.sa_family == AF_INET6 && errno == EAFNOSUPPORT) {
+ fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ from.u.sa.sa_family = AF_INET;
+ }
+#endif
+
+ if (fd < 0)
+ return -1;
+
+ if (bind(fd, &from.u.sa, from.len) < 0) {
+ close(fd);
+ return -1;
+ }
+
+#if ENABLE_FEATURE_IPV6
+ /* Convert any IPv4 addresses in a mixed environment to v4-mapped */
+ if (from.u.sa.sa_family == AF_INET6) {
+ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
+
+ for (nn = 0; nn < n_ns; nn++)
+ to_v4_mapped(&ns[nn].addr);
+ }
+#endif
+
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+ retry_interval = timeout / default_retry;
+ t0 = t2 = mtime();
+ t1 = t2 - retry_interval;
+
+ for (; t2 - t0 < timeout; t2 = mtime()) {
+ if (t2 - t1 >= retry_interval) {
+ for (qn = 0; qn < n_queries; qn++) {
+ if (queries[qn].rlen)
+ continue;
+
+ for (nn = 0; nn < n_ns; nn++) {
+ sendto(fd, queries[qn].query, queries[qn].qlen,
+ MSG_NOSIGNAL, &ns[nn].addr.u.sa, ns[nn].addr.len);
+ }
+ }
+
+ t1 = t2;
+ servfail_retry = 2 * n_queries;
+ }
+
+ /* Wait for a response, or until time to retry */
+ if (poll(&pfd, 1, t1+retry_interval-t2) <= 0)
+ continue;
+
+ while (1) {
+ recvlen = recvfrom(fd, queries[next_query].reply,
+ sizeof(queries[next_query].reply), 0,
+ &from.u.sa, &from.len);
+
+ /* read error */
+ if (recvlen < 0)
+ break;
+
+ /* Ignore non-identifiable packets */
+ if (recvlen < 4)
+ continue;
+
+ /* Ignore replies from addresses we didn't send to */
+ for (nn = 0; nn < n_ns; nn++)
+ if (memcmp(&from.u.sa, &ns[nn].addr.u.sa, from.len) == 0)
+ break;
+
+ if (nn >= n_ns)
+ continue;
+
+ /* Find which query this answer goes with, if any */
+ for (qn = next_query; qn < n_queries; qn++)
+ if (!memcmp(queries[next_query].reply, queries[qn].query, 2))
+ break;
+
+ if (qn >= n_queries || queries[qn].rlen)
+ continue;
+
+ queries[qn].rcode = queries[next_query].reply[3] & 15;
+ queries[qn].latency = mtime() - t0;
+ queries[qn].n_ns = nn;
+
+ ns[nn].replies++;
+
+ /* Only accept positive or negative responses;
+ * retry immediately on server failure, and ignore
+ * all other codes such as refusal. */
+ switch (queries[qn].rcode) {
+ case 0:
+ case 3:
+ break;
+
+ case 2:
+ if (servfail_retry && servfail_retry--) {
+ ns[nn].failures++;
+ sendto(fd, queries[qn].query, queries[qn].qlen,
+ MSG_NOSIGNAL, &ns[nn].addr.u.sa, ns[nn].addr.len);
+ }
+ /* fall through */
+
+ default:
+ continue;
+ }
+
+ /* Store answer */
+ n_replies++;
+
+ queries[qn].rlen = recvlen;
+
+ if (qn == next_query) {
+ while (next_query < n_queries) {
+ if (!queries[next_query].rlen)
+ break;
+
+ next_query++;
+ }
+ }
+ else {
+ memcpy(queries[qn].reply, queries[next_query].reply, recvlen);
+ }
+
+ if (next_query >= n_queries)
+ return n_replies;
+ }
+ }
+
+ return n_replies;
+}
+
+static struct ns *add_ns(struct ns **ns, int *n_ns, const char *addr)
+{
+ char portstr[sizeof("65535")], *p;
+ len_and_sockaddr a = { };
+ struct ns *tmp;
+ struct addrinfo *ai, *aip, hints = {
+ .ai_flags = AI_NUMERICSERV,
+ .ai_socktype = SOCK_DGRAM
+ };
+
+ if (parse_nsaddr(addr, &a)) {
+ /* Maybe we got a domain name, attempt to resolve it using the standard
+ * resolver routines */
+
+ p = strchr(addr, '#');
+ snprintf(portstr, sizeof(portstr), "%hu",
+ (unsigned short)(p ? strtoul(p, NULL, 10) : default_port));
+
+ if (!getaddrinfo(addr, portstr, &hints, &ai)) {
+ for (aip = ai; aip; aip = aip->ai_next) {
+ if (aip->ai_addr->sa_family != AF_INET &&
+ aip->ai_addr->sa_family != AF_INET6)
+ continue;
+
+#if ! ENABLE_FEATURE_IPV6
+ if (aip->ai_addr->sa_family != AF_INET)
+ continue;
+#endif
+
+ tmp = realloc(*ns, sizeof(**ns) * (*n_ns + 1));
+
+ if (!tmp)
+ return NULL;
+
+ *ns = tmp;
+
+ (*ns)[*n_ns].name = addr;
+ (*ns)[*n_ns].replies = 0;
+ (*ns)[*n_ns].failures = 0;
+ (*ns)[*n_ns].addr.len = aip->ai_addrlen;
+
+ memcpy(&(*ns)[*n_ns].addr.u.sa, aip->ai_addr, aip->ai_addrlen);
+
+ (*n_ns)++;
+ }
+
+ freeaddrinfo(ai);
+
+ return &(*ns)[*n_ns];
+ }
+
+ return NULL;
+ }
+
+ tmp = realloc(*ns, sizeof(**ns) * (*n_ns + 1));
+
+ if (!tmp)
+ return NULL;
+
+ *ns = tmp;
+
+ (*ns)[*n_ns].addr = a;
+ (*ns)[*n_ns].name = addr;
+ (*ns)[*n_ns].replies = 0;
+ (*ns)[*n_ns].failures = 0;
+
+ return &(*ns)[(*n_ns)++];
+}
+
+static int parse_resolvconf(struct ns **ns, int *n_ns)
+{
+ int prev_n_ns = *n_ns;
+ char line[128], *p;
+ FILE *resolv;
+
+ if ((resolv = fopen("/etc/resolv.conf", "r")) != NULL) {
+ while (fgets(line, sizeof(line), resolv)) {
+ p = strtok(line, " \t\n");
+
+ if (!p || strcmp(p, "nameserver"))
+ continue;
+
+ p = strtok(NULL, " \t\n");
+
+ if (!p)
+ continue;
+
+ if (!add_ns(ns, n_ns, strdup(p))) {
+ free(p);
+ break;
+ }
+ }
+
+ fclose(resolv);
+ }
+
+ return *n_ns - prev_n_ns;
+}
+
+static struct query *add_query(struct query **queries, int *n_queries,
+ int type, const char *dname)
+{
+ struct query *tmp;
+ ssize_t qlen;
+
+ tmp = realloc(*queries, sizeof(**queries) * (*n_queries + 1));
+
+ if (!tmp)
+ return NULL;
+
+ memset(&tmp[*n_queries], 0, sizeof(*tmp));
+
+ qlen = res_mkquery(QUERY, dname, C_IN, type, NULL, 0, NULL,
+ tmp[*n_queries].query, sizeof(tmp[*n_queries].query));
+
+ tmp[*n_queries].qlen = qlen;
+ tmp[*n_queries].name = dname;
+ *queries = tmp;
+
+ return &tmp[(*n_queries)++];
+}
+
+static char *sal2str(len_and_sockaddr *a)
+{
+ static char buf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1 + 5 + 1];
+ char *p = buf;
+
+#if ENABLE_FEATURE_IPV6
+ if (a->u.sa.sa_family == AF_INET6) {
+ inet_ntop(AF_INET6, &a->u.sin6.sin6_addr, buf, sizeof(buf));
+ p += strlen(p);
+
+ if (a->u.sin6.sin6_scope_id) {
+ if (if_indextoname(a->u.sin6.sin6_scope_id, p + 1)) {
+ *p++ = '%';
+ p += strlen(p);
+ }
+ }
+ }
+ else
+#endif
+ {
+ inet_ntop(AF_INET, &a->u.sin.sin_addr, buf, sizeof(buf));
+ p += strlen(p);
+ }
+
+ sprintf(p, "#%hu", ntohs(a->u.sin.sin_port));
+
+ return buf;
+}
+
+int nslookup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int nslookup_main(int argc, char **argv)
+{
+ int rc = 1;
+ char *ptr, *chr;
+ struct ns *ns = NULL;
+ struct query *queries = NULL;
+ llist_t *type_strings = NULL;
+ int n_ns = 0, n_queries = 0;
+ int c, opts, option_index = 0;
+ int stats = 0, bb_style_counter = 0;
+ unsigned int types = 0;
+ HEADER *header;
+
+#if ENABLE_FEATURE_NSLOOKUP_OPENWRT_LONG_OPTIONS
+ static const char nslookup_longopts[] ALIGN1 =
+ "type\0" Required_argument "q"
+ "querytype\0" Required_argument "q"
+ "port\0" Required_argument "p"
+ "retry\0" Required_argument "r"
+ "timeout\0" Required_argument "t"
+ "stats\0" No_argument "s"
+ ;
+
+ opts = getopt32long(argv, "^" "+q:*p:+r:+t:+s" "\0" "q::",
+ nslookup_longopts,
+ &type_strings, &default_port,
+ &default_retry, &default_timeout);
+#else
+ opts = getopt32(argv, "^" "+q:*p:+r:+t:+s" "\0" "q::",
+ &type_strings, &default_port,
+ &default_retry, &default_timeout);
+#endif
+
+ while (type_strings) {
+ ptr = llist_pop(&type_strings);
+
+ /* skip leading text, e.g. when invoked with -querytype=AAAA */
+ if ((chr = strchr(ptr, '=')) != NULL)
+ ptr = chr + 1;
+
+ for (c = 0; qtypes[c].name; c++)
+ if (!strcmp(qtypes[c].name, ptr))
+ break;
+
+ if (!qtypes[c].name) {
+ fprintf(stderr, "Invalid query type \"%s\"\n", ptr);
+ goto out;
+ }
+
+ types |= (1 << c);
+ }
+
+ if (default_port > 65535) {
+ fprintf(stderr, "Invalid server port\n");
+ goto out;
+ }
+
+ if (!default_retry) {
+ fprintf(stderr, "Invalid retry value\n");
+ goto out;
+ }
+
+ if (!default_timeout) {
+ fprintf(stderr, "Invalid timeout value\n");
+ goto out;
+ }
+
+ stats = (opts & 16);
+
+ if (optind >= argc)
+ bb_show_usage();
+
+ for (option_index = optind;
+ option_index < ((argc - optind) > 1 ? argc - 1 : argc);
+ option_index++) {
+
+ /* No explicit type given, guess query type.
+ * If we can convert the domain argument into a ptr (means that
+ * inet_pton() could read it) we assume a PTR request, else
+ * we issue A+AAAA queries and switch to an output format
+ * mimicking the one of the traditional nslookup applet. */
+ if (types == 0) {
+ ptr = make_ptr(argv[option_index]);
+
+ if (ptr) {
+ add_query(&queries, &n_queries, T_PTR, ptr);
+ }
+ else {
+ bb_style_counter = 1;
+ add_query(&queries, &n_queries, T_A, argv[option_index]);
+#if ENABLE_FEATURE_IPV6
+ add_query(&queries, &n_queries, T_AAAA, argv[option_index]);
+#endif
+ }
+ }
+ else {
+ for (c = 0; qtypes[c].name; c++)
+ if (types & (1 << c))
+ add_query(&queries, &n_queries, qtypes[c].type,
+ argv[option_index]);
+ }
+ }
+
+ /* Use given DNS server if present */
+ if (option_index < argc) {
+ if (!add_ns(&ns, &n_ns, argv[option_index])) {
+ fprintf(stderr, "Invalid NS server address \"%s\": %s\n",
+ argv[option_index], strerror(errno));
+ goto out;
+ }
+ }
+ else {
+ parse_resolvconf(&ns, &n_ns);
+ }
+
+ /* Fall back to localhost if we could not find NS in resolv.conf */
+ if (n_ns == 0) {
+ add_ns(&ns, &n_ns, "127.0.0.1");
+ }
+
+ for (c = 0; c < n_ns; c++) {
+ rc = send_queries(&ns[c], 1, queries, n_queries);
+
+ if (rc < 0) {
+ fprintf(stderr, "Failed to send queries: %s\n", strerror(errno));
+ goto out;
+ } else if (rc > 0) {
+ break;
+ }
+ }
+
+ if (c >= n_ns) {
+ fprintf(stderr,
+ ";; connection timed out; no servers could be reached\n\n");
+
+ return 1;
+ }
+
+ printf("Server:\t\t%s\n", ns[c].name);
+ printf("Address:\t%s\n", sal2str(&ns[c].addr));
+
+ if (stats) {
+ printf("Replies:\t%d\n", ns[c].replies);
+ printf("Failures:\t%d\n", ns[c].failures);
+ }
+
+ printf("\n");
+
+ for (rc = 0; rc < n_queries; rc++) {
+ if (stats) {
+ printf("Query #%d completed in %lums:\n", rc, queries[rc].latency);
+ }
+
+ if (queries[rc].rcode != 0) {
+ printf("** server can't find %s: %s\n", queries[rc].name,
+ rcodes[queries[rc].rcode]);
+ continue;
+ }
+
+ c = 0;
+
+ if (queries[rc].rlen) {
+ if (!bb_style_counter) {
+ header = (HEADER *)queries[rc].reply;
+
+ if (!header->aa)
+ printf("Non-authoritative answer:\n");
+
+ c = parse_reply(queries[rc].reply, queries[rc].rlen, NULL);
+ }
+ else {
+ c = parse_reply(queries[rc].reply, queries[rc].rlen,
+ &bb_style_counter);
+ }
+ }
+
+ if (c == 0)
+ printf("*** Can't find %s: No answer\n", queries[rc].name);
+ else if (c < 0)
+ printf("*** Can't find %s: Parse error\n", queries[rc].name);
+
+ if (!bb_style_counter)
+ printf("\n");
+ }
+
+ rc = 0;
+
+out:
+ if (n_ns)
+ free(ns);
+
+ if (n_queries)
+ free(queries);
+
+ return rc;
+}

View File

@@ -0,0 +1,10 @@
--- a/networking/telnetd.c
+++ b/networking/telnetd.c
@@ -497,6 +497,7 @@ make_new_session(
/* Restore default signal handling ASAP */
bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL);
+ signal(SIGINT, SIG_DFL);
pid = getpid();

View File

@@ -0,0 +1,92 @@
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -123,6 +123,7 @@
//usage: IF_FEATURE_DATE_ISOFMT(
//usage: "\n -D FMT Use FMT for -d TIME conversion"
//usage: )
+//usage: "\n -k Set Kernel timezone from localtime and exit"
//usage: "\n"
//usage: "\nRecognized TIME formats:"
//usage: "\n hh:mm[:ss]"
@@ -139,9 +140,8 @@
#include "libbb.h"
#include "common_bufsiz.h"
-#if ENABLE_FEATURE_DATE_NANO
-# include <sys/syscall.h>
-#endif
+#include <sys/time.h>
+#include <sys/syscall.h>
enum {
OPT_RFC2822 = (1 << 0), /* R */
@@ -149,8 +149,9 @@ enum {
OPT_UTC = (1 << 2), /* u */
OPT_DATE = (1 << 3), /* d */
OPT_REFERENCE = (1 << 4), /* r */
- OPT_TIMESPEC = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */
- OPT_HINT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */
+ OPT_KERNELTZ = (1 << 5), /* k */
+ OPT_TIMESPEC = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* I */
+ OPT_HINT = (1 << 7) * ENABLE_FEATURE_DATE_ISOFMT, /* D */
};
#if ENABLE_LONG_OPTS
@@ -162,6 +163,7 @@ static const char date_longopts[] ALIGN1
/* "universal\0" No_argument "u" */
"date\0" Required_argument "d"
"reference\0" Required_argument "r"
+ "set-kernel-tz\0" No_argument "k"
;
#endif
@@ -181,6 +183,8 @@ static void maybe_set_utc(int opt)
int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int date_main(int argc UNUSED_PARAM, char **argv)
{
+ time_t tt;
+ struct timezone tz;
struct timespec ts;
struct tm tm_time;
char buf_fmt_dt2str[64];
@@ -193,7 +197,7 @@ int date_main(int argc UNUSED_PARAM, cha
char *isofmt_arg = NULL;
opt = getopt32long(argv, "^"
- "Rs:ud:r:"
+ "Rs:ud:r:k"
IF_FEATURE_DATE_ISOFMT("I::D:")
"\0"
"d--s:s--d"
@@ -256,6 +260,31 @@ int date_main(int argc UNUSED_PARAM, cha
if (*argv)
bb_show_usage();
+ /* Setting of kernel timezone was requested */
+ if (opt & OPT_KERNELTZ) {
+ tt = time(NULL);
+ localtime_r(&tt, &tm_time);
+
+ /* workaround warp_clock() on first invocation */
+ memset(&tz, 0, sizeof(tz));
+ syscall(SYS_settimeofday, NULL, &tz);
+
+ memset(&tz, 0, sizeof(tz));
+#ifdef __USE_MISC
+ tz.tz_minuteswest = -(tm_time.tm_gmtoff / 60);
+#else
+ tz.tz_minuteswest = -(tm_time.__tm_gmtoff / 60);
+#endif
+
+ if (syscall(SYS_settimeofday, NULL, &tz))
+ {
+ bb_perror_msg("can't set kernel time zone");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+ }
+
/* Now we have parsed all the information except the date format
* which depends on whether the clock is being set or read */

View File

@@ -0,0 +1,20 @@
--- a/libbb/printable_string.c
+++ b/libbb/printable_string.c
@@ -28,8 +28,6 @@ const char* FAST_FUNC printable_string2(
}
if (c < ' ')
break;
- if (c >= 0x7f)
- break;
s++;
}
@@ -42,7 +40,7 @@ const char* FAST_FUNC printable_string2(
unsigned char c = *d;
if (c == '\0')
break;
- if (c < ' ' || c >= 0x7f)
+ if (c < ' ')
*d = '?';
d++;
}

View File

@@ -0,0 +1,11 @@
--- a/networking/libiproute/iplink.c
+++ b/networking/libiproute/iplink.c
@@ -652,7 +652,7 @@ static int do_add_or_delete(char **argv,
}
xrtnl_open(&rth);
ll_init_map(&rth);
- if (type_str) {
+ if (type_str && rtm == RTM_NEWLINK) {
struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);

View File

@@ -0,0 +1,13 @@
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -237,8 +237,8 @@
//config: depends on TRACEROUTE || TRACEROUTE6
/* Needs socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), therefore BB_SUID_MAYBE: */
-//applet:IF_TRACEROUTE(APPLET(traceroute, BB_DIR_USR_BIN, BB_SUID_MAYBE))
-//applet:IF_TRACEROUTE6(APPLET(traceroute6, BB_DIR_USR_BIN, BB_SUID_MAYBE))
+//applet:IF_TRACEROUTE(APPLET(traceroute, BB_DIR_BIN, BB_SUID_MAYBE))
+//applet:IF_TRACEROUTE6(APPLET(traceroute6, BB_DIR_BIN, BB_SUID_MAYBE))
//kbuild:lib-$(CONFIG_TRACEROUTE) += traceroute.o
//kbuild:lib-$(CONFIG_TRACEROUTE6) += traceroute.o

View File

@@ -0,0 +1,11 @@
--- a/loginutils/passwd.c
+++ b/loginutils/passwd.c
@@ -23,7 +23,7 @@
//config: With this option passwd will refuse new passwords which are "weak".
//applet:/* Needs to be run by root or be suid root - needs to change /etc/{passwd,shadow}: */
-//applet:IF_PASSWD(APPLET(passwd, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
+//applet:IF_PASSWD(APPLET(passwd, BB_DIR_BIN, BB_SUID_REQUIRE))
//kbuild:lib-$(CONFIG_PASSWD) += passwd.o

View File

@@ -0,0 +1,53 @@
--- a/loginutils/chpasswd.c
+++ b/loginutils/chpasswd.c
@@ -97,6 +97,11 @@ int chpasswd_main(int argc UNUSED_PARAM,
crypt_make_pw_salt(salt, algo);
free_me = pass = pw_encrypt(pass, salt, 0);
+
+ if (pass[0] == 0) {
+ free(free_me);
+ bb_perror_msg_and_die("password encryption failed");
+ }
}
/* This is rather complex: if user is not found in /etc/shadow,
--- a/loginutils/cryptpw.c
+++ b/loginutils/cryptpw.c
@@ -95,7 +95,7 @@ int cryptpw_main(int argc UNUSED_PARAM,
/* Supports: cryptpw -m sha256 PASS 'rounds=999999999$SALT' */
char salt[MAX_PW_SALT_LEN + sizeof("rounds=999999999$")];
char *salt_ptr;
- char *password;
+ char *password, *hash;
const char *opt_m, *opt_S;
int fd;
@@ -140,8 +140,12 @@ int cryptpw_main(int argc UNUSED_PARAM,
/* may still be NULL on EOF/error */
}
- if (password)
- puts(pw_encrypt(password, salt, 1));
+ if (password) {
+ hash = pw_encrypt(password, salt, 1);
+ if (hash[0] == 0)
+ bb_perror_msg_and_die("password encryption failed");
+ puts(hash);
+ }
return EXIT_SUCCESS;
}
--- a/loginutils/passwd.c
+++ b/loginutils/passwd.c
@@ -187,6 +187,10 @@ int passwd_main(int argc UNUSED_PARAM, c
if (!newp) {
logmode = LOGMODE_STDIO;
bb_error_msg_and_die("password for %s is unchanged", name);
+ } else if (newp[0] == 0) {
+ logmode = LOGMODE_STDIO;
+ free(newp);
+ bb_perror_msg_and_die("password encryption failed");
}
} else if (opt & OPT_lock) {
if (!c)

View File

@@ -0,0 +1,214 @@
From 028c5aa18b5273c029f0278232d922ee1a164de6 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 22 May 2019 13:54:46 +0200
Subject: ip: use rtnl_send_check() on flush commands, closes 6962
function old new delta
rtnl_send_check - 160 +160
xrtnl_wilddump_request 64 66 +2
ipneigh_list_or_flush 714 706 -8
rtnl_send 69 - -69
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 1/1 up/down: 162/-77) Total: 85 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
networking/libiproute/ipaddress.c | 6 ++++--
networking/libiproute/ipneigh.c | 9 ++++----
networking/libiproute/iproute.c | 5 ++++-
networking/libiproute/libnetlink.c | 43 +++++++++++++++++++++++++++++++-------
networking/libiproute/libnetlink.h | 19 +++++++++++++++--
5 files changed, 65 insertions(+), 17 deletions(-)
--- a/networking/libiproute/ipaddress.c
+++ b/networking/libiproute/ipaddress.c
@@ -23,6 +23,7 @@
struct filter_t {
char *label;
+ /* Flush cmd buf. If !NULL, print_addrinfo() constructs flush commands in it */
char *flushb;
struct rtnl_handle *rth;
int scope, scopemask;
@@ -34,6 +35,8 @@ struct filter_t {
smallint showqueue;
smallint oneline;
smallint up;
+ /* Misnomer. Does not mean "flushed something" */
+ /* More like "flush commands were constructed by print_addrinfo()" */
smallint flushed;
inet_prefix pfx;
} FIX_ALIASING;
@@ -201,7 +204,7 @@ static NOINLINE int print_linkinfo(const
static int flush_update(void)
{
- if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) {
+ if (rtnl_send_check(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) {
bb_perror_msg("can't send flush request");
return -1;
}
@@ -507,7 +510,6 @@ int FAST_FUNC ipaddr_list_or_flush(char
xrtnl_dump_filter(&rth, store_nlmsg, &ainfo);
}
-
if (G_filter.family && G_filter.family != AF_PACKET) {
struct nlmsg_list **lp;
lp = &linfo;
--- a/networking/libiproute/ipneigh.c
+++ b/networking/libiproute/ipneigh.c
@@ -32,7 +32,10 @@ struct filter_t {
int state;
int unused_only;
inet_prefix pfx;
+ /* Misnomer. Does not mean "flushed N something" */
+ /* More like "no_of_flush_commands_constructed_by_print_neigh()" */
int flushed;
+ /* Flush cmd buf. If !NULL, print_neigh() constructs flush commands in it */
char *flushb;
int flushp;
int flushe;
@@ -45,7 +48,7 @@ typedef struct filter_t filter_t;
static int flush_update(void)
{
- if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) {
+ if (rtnl_send_check(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) {
bb_perror_msg("can't send flush request");
return -1;
}
@@ -299,9 +302,7 @@ static int FAST_FUNC ipneigh_list_or_flu
G_filter.rth = &rth;
while (round < MAX_ROUNDS) {
- if (xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETNEIGH) < 0) {
- bb_perror_msg_and_die("can't send dump request");
- }
+ xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETNEIGH);
G_filter.flushed = 0;
if (xrtnl_dump_filter(&rth, print_neigh, NULL) < 0) {
bb_perror_msg_and_die("flush terminated");
--- a/networking/libiproute/iproute.c
+++ b/networking/libiproute/iproute.c
@@ -26,7 +26,10 @@
struct filter_t {
int tb;
+ /* Misnomer. Does not mean "flushed something" */
+ /* More like "flush commands were constructed by print_route()" */
smallint flushed;
+ /* Flush cmd buf. If !NULL, print_route() constructs flush commands in it */
char *flushb;
int flushp;
int flushe;
@@ -53,7 +56,7 @@ typedef struct filter_t filter_t;
static int flush_update(void)
{
- if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) {
+ if (rtnl_send_check(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) {
bb_perror_msg("can't send flush request");
return -1;
}
--- a/networking/libiproute/libnetlink.c
+++ b/networking/libiproute/libnetlink.c
@@ -34,7 +34,7 @@ void FAST_FUNC xrtnl_open(struct rtnl_ha
rth->seq = time(NULL);
}
-int FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
+void FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
{
struct {
struct nlmsghdr nlh;
@@ -48,18 +48,45 @@ int FAST_FUNC xrtnl_wilddump_request(str
req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
req.g.rtgen_family = family;
- return rtnl_send(rth, (void*)&req, sizeof(req));
+ rtnl_send(rth, (void*)&req, sizeof(req));
}
-//TODO: pass rth->fd instead of full rth?
-int FAST_FUNC rtnl_send(struct rtnl_handle *rth, char *buf, int len)
+/* A version which checks for e.g. EPERM errors.
+ * Try: setuidgid 1:1 ip addr flush dev eth0
+ */
+int FAST_FUNC rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len)
{
- struct sockaddr_nl nladdr;
+ struct nlmsghdr *h;
+ int status;
+ char resp[1024];
+
+ status = write(rth->fd, buf, len);
+ if (status < 0)
+ return status;
+
+ /* Check for immediate errors */
+ status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT|MSG_PEEK);
+ if (status < 0) {
+ if (errno == EAGAIN) /* if no error, this happens */
+ return 0;
+ return -1;
+ }
+
+ for (h = (struct nlmsghdr *)resp;
+ NLMSG_OK(h, status);
+ h = NLMSG_NEXT(h, status)
+ ) {
+ if (h->nlmsg_type == NLMSG_ERROR) {
+ struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
+ if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
+ bb_error_msg("ERROR truncated");
+ else
+ errno = -err->error;
+ return -1;
+ }
+ }
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
-
- return xsendto(rth->fd, buf, len, (struct sockaddr*)&nladdr, sizeof(nladdr));
+ return 0;
}
int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
--- a/networking/libiproute/libnetlink.h
+++ b/networking/libiproute/libnetlink.h
@@ -20,7 +20,7 @@ struct rtnl_handle {
extern void xrtnl_open(struct rtnl_handle *rth) FAST_FUNC;
#define rtnl_close(rth) (close((rth)->fd))
-extern int xrtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type) FAST_FUNC;
+extern void xrtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type) FAST_FUNC;
extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) FAST_FUNC;
extern int xrtnl_dump_filter(struct rtnl_handle *rth,
int (*filter)(const struct sockaddr_nl*, struct nlmsghdr *n, void*) FAST_FUNC,
@@ -34,8 +34,23 @@ extern int rtnl_talk(struct rtnl_handle
int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
void *jarg) FAST_FUNC;
-extern int rtnl_send(struct rtnl_handle *rth, char *buf, int) FAST_FUNC;
+int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len) FAST_FUNC;
+//TODO: pass rth->fd instead of full rth?
+static ALWAYS_INLINE void rtnl_send(struct rtnl_handle *rth, const void *buf, int len)
+{
+ // Used to be:
+ //struct sockaddr_nl nladdr;
+ //memset(&nladdr, 0, sizeof(nladdr));
+ //nladdr.nl_family = AF_NETLINK;
+ //return xsendto(rth->fd, buf, len, (struct sockaddr*)&nladdr, sizeof(nladdr));
+ // iproute2-4.2.0 simplified the above to:
+ //return send(rth->fd, buf, len, 0);
+
+ // We are using even shorter:
+ xwrite(rth->fd, buf, len);
+ // and convert to void, inline.
+}
extern int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data) FAST_FUNC;
extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) FAST_FUNC;