summaryrefslogtreecommitdiff
path: root/release/src/router/busybox/networking/libiproute
diff options
context:
space:
mode:
Diffstat (limited to 'release/src/router/busybox/networking/libiproute')
-rw-r--r--release/src/router/busybox/networking/libiproute/Kbuild64
-rw-r--r--release/src/router/busybox/networking/libiproute/Makefile30
-rwxr-xr-xrelease/src/router/busybox/networking/libiproute/Makefile.in44
-rw-r--r--release/src/router/busybox/networking/libiproute/ip_common.h49
-rw-r--r--release/src/router/busybox/networking/libiproute/ip_parse_common_args.c98
-rw-r--r--release/src/router/busybox/networking/libiproute/ipaddress.c408
-rw-r--r--release/src/router/busybox/networking/libiproute/iplink.c334
-rw-r--r--release/src/router/busybox/networking/libiproute/iproute.c608
-rw-r--r--release/src/router/busybox/networking/libiproute/iprule.c330
-rw-r--r--release/src/router/busybox/networking/libiproute/iptunnel.c448
-rw-r--r--release/src/router/busybox/networking/libiproute/libnetlink.c347
-rw-r--r--release/src/router/busybox/networking/libiproute/libnetlink.h60
-rw-r--r--release/src/router/busybox/networking/libiproute/linux/pkt_sched.h413
-rw-r--r--release/src/router/busybox/networking/libiproute/ll_addr.c54
-rw-r--r--release/src/router/busybox/networking/libiproute/ll_map.c146
-rw-r--r--release/src/router/busybox/networking/libiproute/ll_map.h29
-rw-r--r--release/src/router/busybox/networking/libiproute/ll_proto.c121
-rw-r--r--release/src/router/busybox/networking/libiproute/ll_types.c250
-rw-r--r--release/src/router/busybox/networking/libiproute/rt_names.c320
-rw-r--r--release/src/router/busybox/networking/libiproute/rt_names.h43
-rw-r--r--release/src/router/busybox/networking/libiproute/rtm_map.c44
-rw-r--r--release/src/router/busybox/networking/libiproute/rtm_map.h14
-rw-r--r--release/src/router/busybox/networking/libiproute/utils.c290
-rw-r--r--release/src/router/busybox/networking/libiproute/utils.h97
24 files changed, 2226 insertions, 2415 deletions
diff --git a/release/src/router/busybox/networking/libiproute/Kbuild b/release/src/router/busybox/networking/libiproute/Kbuild
new file mode 100644
index 00000000..5f9dd32b
--- /dev/null
+++ b/release/src/router/busybox/networking/libiproute/Kbuild
@@ -0,0 +1,64 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+#
+# Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+#
+
+lib-y:=
+
+lib-$(CONFIG_SLATTACH) += \
+ utils.o
+
+lib-$(CONFIG_IP) += \
+ ip_parse_common_args.o \
+ libnetlink.o \
+ ll_addr.o \
+ ll_map.o \
+ ll_proto.o \
+ ll_types.o \
+ rt_names.o \
+ rtm_map.o \
+ utils.o
+
+lib-$(CONFIG_FEATURE_IP_ADDRESS) += \
+ ip_parse_common_args.o \
+ ipaddress.o \
+ libnetlink.o \
+ ll_addr.o \
+ ll_map.o \
+ ll_types.o \
+ rt_names.o \
+ utils.o
+
+lib-$(CONFIG_FEATURE_IP_LINK) += \
+ ip_parse_common_args.o \
+ ipaddress.o \
+ iplink.o \
+ libnetlink.o \
+ ll_addr.o \
+ ll_map.o \
+ ll_types.o \
+ rt_names.o \
+ utils.o
+
+lib-$(CONFIG_FEATURE_IP_ROUTE) += \
+ ip_parse_common_args.o \
+ iproute.o \
+ libnetlink.o \
+ ll_map.o \
+ rt_names.o \
+ rtm_map.o \
+ utils.o
+
+lib-$(CONFIG_FEATURE_IP_TUNNEL) += \
+ ip_parse_common_args.o \
+ iptunnel.o \
+ rt_names.o \
+ utils.o
+
+lib-$(CONFIG_FEATURE_IP_RULE) += \
+ ip_parse_common_args.o \
+ iprule.o \
+ rt_names.o \
+ utils.o
diff --git a/release/src/router/busybox/networking/libiproute/Makefile b/release/src/router/busybox/networking/libiproute/Makefile
deleted file mode 100644
index c1f18be7..00000000
--- a/release/src/router/busybox/networking/libiproute/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-TOPDIR:= ../../
-LIBIPROUTE_DIR:=./
-include $(TOPDIR).config
-include $(TOPDIR)Rules.mak
-include Makefile.in
-all: $(libraries-y)
--include $(TOPDIR).depend
-
-clean:
- rm -f *.o *.a $(AR_TARGET)
-
diff --git a/release/src/router/busybox/networking/libiproute/Makefile.in b/release/src/router/busybox/networking/libiproute/Makefile.in
deleted file mode 100755
index f39eeb3e..00000000
--- a/release/src/router/busybox/networking/libiproute/Makefile.in
+++ /dev/null
@@ -1,44 +0,0 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-LIBIPROUTE_AR:=libiproute.a
-ifndef $(LIBIPROUTE_DIR)
-LIBIPROUTE_DIR:=$(TOPDIR)networking/libiproute/
-endif
-
-LIBIPROUTE-$(CONFIG_IP) += \
- ip_parse_common_args.o \
- ipaddress.o \
- iplink.o \
- iproute.o \
- iptunnel.o \
- libnetlink.o \
- ll_addr.o \
- ll_map.o \
- ll_proto.o \
- ll_types.o \
- rt_names.o \
- rtm_map.o \
- utils.o
-
-libraries-y+=$(LIBIPROUTE_DIR)$(LIBIPROUTE_AR)
-
-$(LIBIPROUTE_DIR)$(LIBIPROUTE_AR): $(patsubst %,$(LIBIPROUTE_DIR)%, $(LIBIPROUTE-y))
- $(AR) -ro $@ $(patsubst %,$(LIBIPROUTE_DIR)%, $(LIBIPROUTE-y))
-
diff --git a/release/src/router/busybox/networking/libiproute/ip_common.h b/release/src/router/busybox/networking/libiproute/ip_common.h
index 25e9c6c8..aef32528 100644
--- a/release/src/router/busybox/networking/libiproute/ip_common.h
+++ b/release/src/router/busybox/networking/libiproute/ip_common.h
@@ -1,18 +1,37 @@
-extern int preferred_family;
-extern char * _SL_;
+/* vi: set sw=4 ts=4: */
+#ifndef IP_COMMON_H
+#define IP_COMMON_H 1
-extern void ip_parse_common_args(int *argcp, char ***argvp);
+#include "libbb.h"
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#if !defined IFA_RTA
+#include <linux/if_addr.h>
+#endif
+#if !defined IFLA_RTA
+#include <linux/if_link.h>
+#endif
+
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
+
+extern char **ip_parse_common_args(char **argv);
extern int print_neigh(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
-extern int ipaddr_list_or_flush(int argc, char **argv, int flush);
-extern int iproute_monitor(int argc, char **argv);
-extern void iplink_usage(void) __attribute__((noreturn));
+extern int ipaddr_list_or_flush(char **argv, int flush);
+extern int iproute_monitor(char **argv);
+extern void iplink_usage(void) NORETURN;
extern void ipneigh_reset_filter(void);
-extern int do_ipaddr(int argc, char **argv);
-extern int do_iproute(int argc, char **argv);
-extern int do_iprule(int argc, char **argv);
-extern int do_ipneigh(int argc, char **argv);
-extern int do_iptunnel(int argc, char **argv);
-extern int do_iplink(int argc, char **argv);
-extern int do_ipmonitor(int argc, char **argv);
-extern int do_multiaddr(int argc, char **argv);
-extern int do_multiroute(int argc, char **argv);
+
+extern int do_ipaddr(char **argv);
+extern int do_iproute(char **argv);
+extern int do_iprule(char **argv);
+extern int do_ipneigh(char **argv);
+extern int do_iptunnel(char **argv);
+extern int do_iplink(char **argv);
+extern int do_ipmonitor(char **argv);
+extern int do_multiaddr(char **argv);
+extern int do_multiroute(char **argv);
+
+POP_SAVED_FUNCTION_VISIBILITY
+
+#endif
diff --git a/release/src/router/busybox/networking/libiproute/ip_parse_common_args.c b/release/src/router/busybox/networking/libiproute/ip_parse_common_args.c
index 21e9f74b..5e4012b8 100644
--- a/release/src/router/busybox/networking/libiproute/ip_parse_common_args.c
+++ b/release/src/router/busybox/networking/libiproute/ip_parse_common_args.c
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
/*
* ip.c "ip" utility frontend.
*
@@ -14,61 +15,70 @@
* Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
*/
-#include <string.h>
-
+#include "ip_common.h" /* #include "libbb.h" is inside */
#include "utils.h"
-#include "ip_common.h"
-
-#include "busybox.h"
-int preferred_family = AF_UNSPEC;
-int oneline = 0;
-char * _SL_ = NULL;
+family_t preferred_family = AF_UNSPEC;
+smallint oneline;
+char _SL_;
-void ip_parse_common_args(int *argcp, char ***argvp)
+char **ip_parse_common_args(char **argv)
{
- int argc = *argcp;
- char **argv = *argvp;
-
- while (argc > 1) {
- char *opt = argv[1];
+ static const char ip_common_commands[] ALIGN1 =
+ "oneline" "\0"
+ "family" "\0"
+ "4" "\0"
+ "6" "\0"
+ "0" "\0"
+ ;
+ enum {
+ ARG_oneline,
+ ARG_family,
+ ARG_IPv4,
+ ARG_IPv6,
+ ARG_packet,
+ };
+ static const family_t af_numbers[] = { AF_INET, AF_INET6, AF_PACKET };
+ int arg;
- if (strcmp(opt,"--") == 0) {
- argc--; argv++;
- break;
- }
+ while (*argv) {
+ char *opt = *argv;
if (opt[0] != '-')
break;
-
- if (opt[1] == '-')
+ opt++;
+ if (opt[0] == '-') {
opt++;
-
- if (matches(opt, "-family") == 0) {
- argc--;
+ if (!opt[0]) { /* "--" */
+ argv++;
+ break;
+ }
+ }
+ arg = index_in_substrings(ip_common_commands, opt);
+ if (arg < 0)
+ bb_show_usage();
+ if (arg == ARG_oneline) {
+ oneline = 1;
argv++;
- if (! argv[1])
- bb_show_usage();
- if (strcmp(argv[1], "inet") == 0)
- preferred_family = AF_INET;
- else if (strcmp(argv[1], "inet6") == 0)
- preferred_family = AF_INET6;
- else if (strcmp(argv[1], "link") == 0)
- preferred_family = AF_PACKET;
- else
- invarg(argv[1], "invalid protocol family");
- } else if (strcmp(opt, "-4") == 0) {
- preferred_family = AF_INET;
- } else if (strcmp(opt, "-6") == 0) {
- preferred_family = AF_INET6;
- } else if (strcmp(opt, "-0") == 0) {
- preferred_family = AF_PACKET;
- } else if (matches(opt, "-oneline") == 0) {
- ++oneline;
+ continue;
+ }
+ if (arg == ARG_family) {
+ static const char families[] ALIGN1 =
+ "inet" "\0" "inet6" "\0" "link" "\0";
+ argv++;
+ if (!*argv)
+ bb_show_usage();
+ arg = index_in_strings(families, *argv);
+ if (arg < 0)
+ invarg(*argv, "protocol family");
+ /* now arg == 0, 1 or 2 */
} else {
- bb_show_usage();
+ arg -= ARG_IPv4;
+ /* now arg == 0, 1 or 2 */
}
- argc--; argv++;
+ preferred_family = af_numbers[arg];
+ argv++;
}
- _SL_ = oneline ? "\\" : "\n" ;
+ _SL_ = oneline ? '\\' : '\n';
+ return argv;
}
diff --git a/release/src/router/busybox/networking/libiproute/ipaddress.c b/release/src/router/busybox/networking/libiproute/ipaddress.c
index 44e871ee..644874f4 100644
--- a/release/src/router/busybox/networking/libiproute/ipaddress.c
+++ b/release/src/router/busybox/networking/libiproute/ipaddress.c
@@ -1,10 +1,8 @@
+/* vi: set sw=4 ts=4: */
/*
* ipaddress.c "ip address".
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
@@ -12,54 +10,50 @@
* Laszlo Valko <valko@linux.karinthy.hu> 990223: address label must be zero terminated
*/
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-
#include <fnmatch.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <arpa/inet.h>
-
#include <net/if.h>
#include <net/if_arp.h>
+#include "ip_common.h" /* #include "libbb.h" is inside */
#include "rt_names.h"
#include "utils.h"
-#include "libbb.h"
+#ifndef IFF_LOWER_UP
+/* from linux/if.h */
+#define IFF_LOWER_UP 0x10000 /* driver signals L1 up*/
+#endif
-static struct
-{
- int ifindex;
- int family;
- int oneline;
- int showqueue;
- inet_prefix pfx;
- int scope, scopemask;
- int flags, flagmask;
- int up;
+typedef struct filter_t {
char *label;
- int flushed;
char *flushb;
+ struct rtnl_handle *rth;
+ int scope, scopemask;
+ int flags, flagmask;
int flushp;
int flushe;
- struct rtnl_handle *rth;
-} filter;
+ int ifindex;
+ family_t family;
+ smallint showqueue;
+ smallint oneline;
+ smallint up;
+ smallint flushed;
+ inet_prefix pfx;
+} filter_t;
+
+#define filter (*(filter_t*)&bb_common_bufsiz1)
+
-void print_link_flags(FILE *fp, unsigned flags, unsigned mdown)
+static void print_link_flags(unsigned flags, unsigned mdown)
{
- fprintf(fp, "<");
+ static const int flag_masks[] = {
+ IFF_LOOPBACK, IFF_BROADCAST, IFF_POINTOPOINT,
+ IFF_MULTICAST, IFF_NOARP, IFF_UP, IFF_LOWER_UP };
+ static const char flag_labels[] ALIGN1 =
+ "LOOPBACK\0""BROADCAST\0""POINTOPOINT\0"
+ "MULTICAST\0""NOARP\0""UP\0""LOWER_UP\0";
+
+ bb_putchar('<');
flags &= ~IFF_RUNNING;
-#define _PF(f) if (flags&IFF_##f) { \
- flags &= ~IFF_##f ; \
- fprintf(fp, #f "%s", flags ? "," : ""); }
- _PF(LOOPBACK);
- _PF(BROADCAST);
- _PF(POINTOPOINT);
- _PF(MULTICAST);
- _PF(NOARP);
#if 0
_PF(ALLMULTI);
_PF(PROMISC);
@@ -71,13 +65,12 @@ void print_link_flags(FILE *fp, unsigned flags, unsigned mdown)
_PF(PORTSEL);
_PF(NOTRAILERS);
#endif
- _PF(UP);
-#undef _PF
- if (flags)
- fprintf(fp, "%x", flags);
+ flags = print_flags_separated(flag_masks, flag_labels, flags, ",");
+ if (flags)
+ printf("%x", flags);
if (mdown)
- fprintf(fp, ",M-DOWN");
- fprintf(fp, "> ");
+ printf(",M-DOWN");
+ printf("> ");
}
static void print_queuelen(char *name)
@@ -90,9 +83,8 @@ static void print_queuelen(char *name)
return;
memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, name);
- if (ioctl(s, SIOCGIFTXQLEN, &ifr) < 0) {
- perror("SIOCGIFXQLEN");
+ strncpy_IFNAMSIZ(ifr.ifr_name, name);
+ if (ioctl_or_warn(s, SIOCGIFTXQLEN, &ifr) < 0) {
close(s);
return;
}
@@ -102,9 +94,8 @@ static void print_queuelen(char *name)
printf("qlen %d", ifr.ifr_qlen);
}
-static int print_linkinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+static int print_linkinfo(const struct nlmsghdr *n)
{
- FILE *fp = (FILE*)arg;
struct ifinfomsg *ifi = NLMSG_DATA(n);
struct rtattr * tb[IFLA_MAX+1];
int len = n->nlmsg_len;
@@ -119,7 +110,7 @@ static int print_linkinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg
if (filter.ifindex && ifi->ifi_index != filter.ifindex)
return 0;
- if (filter.up && !(ifi->ifi_flags&IFF_UP))
+ if (filter.up && !(ifi->ifi_flags & IFF_UP))
return 0;
memset(tb, 0, sizeof(tb));
@@ -128,85 +119,86 @@ static int print_linkinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg
bb_error_msg("nil ifname");
return -1;
}
- if (filter.label &&
- (!filter.family || filter.family == AF_PACKET) &&
- fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0))
+ if (filter.label
+ && (!filter.family || filter.family == AF_PACKET)
+ && fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0)
+ ) {
return 0;
+ }
if (n->nlmsg_type == RTM_DELLINK)
- fprintf(fp, "Deleted ");
+ printf("Deleted ");
- fprintf(fp, "%d: %s", ifi->ifi_index,
+ printf("%d: %s", ifi->ifi_index,
tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>");
if (tb[IFLA_LINK]) {
SPRINT_BUF(b1);
int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]);
if (iflink == 0)
- fprintf(fp, "@NONE: ");
+ printf("@NONE: ");
else {
- fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
+ printf("@%s: ", ll_idx_n2a(iflink, b1));
m_flag = ll_index_to_flags(iflink);
m_flag = !(m_flag & IFF_UP);
}
} else {
- fprintf(fp, ": ");
+ printf(": ");
}
- print_link_flags(fp, ifi->ifi_flags, m_flag);
+ print_link_flags(ifi->ifi_flags, m_flag);
if (tb[IFLA_MTU])
- fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU]));
+ printf("mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU]));
if (tb[IFLA_QDISC])
- fprintf(fp, "qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC]));
+ printf("qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC]));
#ifdef IFLA_MASTER
if (tb[IFLA_MASTER]) {
SPRINT_BUF(b1);
- fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
+ printf("master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
}
#endif
if (filter.showqueue)
print_queuelen((char*)RTA_DATA(tb[IFLA_IFNAME]));
-
+
if (!filter.family || filter.family == AF_PACKET) {
SPRINT_BUF(b1);
- fprintf(fp, "%s", _SL_);
- fprintf(fp, " link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1)));
+ printf("%c link/%s ", _SL_, ll_type_n2a(ifi->ifi_type, b1, sizeof(b1)));
if (tb[IFLA_ADDRESS]) {
- fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
+ fputs(ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
RTA_PAYLOAD(tb[IFLA_ADDRESS]),
ifi->ifi_type,
- b1, sizeof(b1)));
+ b1, sizeof(b1)), stdout);
}
if (tb[IFLA_BROADCAST]) {
- if (ifi->ifi_flags&IFF_POINTOPOINT)
- fprintf(fp, " peer ");
+ if (ifi->ifi_flags & IFF_POINTOPOINT)
+ printf(" peer ");
else
- fprintf(fp, " brd ");
- fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
+ printf(" brd ");
+ fputs(ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
RTA_PAYLOAD(tb[IFLA_BROADCAST]),
ifi->ifi_type,
- b1, sizeof(b1)));
+ b1, sizeof(b1)), stdout);
}
}
- fprintf(fp, "\n");
- fflush(fp);
+ bb_putchar('\n');
+ /*fflush(stdout);*/
return 0;
}
static int flush_update(void)
{
if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) {
- perror("Failed to send flush request\n");
+ bb_perror_msg("failed to send flush request");
return -1;
}
filter.flushp = 0;
return 0;
}
-static int print_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+static int print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
+ struct nlmsghdr *n, void *arg UNUSED_PARAM)
{
- FILE *fp = (FILE*)arg;
struct ifaddrmsg *ifa = NLMSG_DATA(n);
int len = n->nlmsg_len;
struct rtattr * rta_tb[IFA_MAX+1];
@@ -234,9 +226,9 @@ static int print_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg
if (filter.ifindex && filter.ifindex != ifa->ifa_index)
return 0;
- if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
+ if ((filter.scope ^ ifa->ifa_scope) & filter.scopemask)
return 0;
- if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
+ if ((filter.flags ^ ifa->ifa_flags) & filter.flagmask)
return 0;
if (filter.label) {
const char *label;
@@ -270,35 +262,34 @@ static int print_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg
fn->nlmsg_flags = NLM_F_REQUEST;
fn->nlmsg_seq = ++filter.rth->seq;
filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
- filter.flushed++;
+ filter.flushed = 1;
return 0;
}
if (n->nlmsg_type == RTM_DELADDR)
- fprintf(fp, "Deleted ");
+ printf("Deleted ");
if (filter.oneline)
- fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));
+ printf("%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));
if (ifa->ifa_family == AF_INET)
- fprintf(fp, " inet ");
+ printf(" inet ");
else if (ifa->ifa_family == AF_INET6)
- fprintf(fp, " inet6 ");
+ printf(" inet6 ");
else
- fprintf(fp, " family %d ", ifa->ifa_family);
+ printf(" family %d ", ifa->ifa_family);
if (rta_tb[IFA_LOCAL]) {
- fprintf(fp, "%s", rt_addr_n2a(ifa->ifa_family,
- RTA_PAYLOAD(rta_tb[IFA_LOCAL]),
+ fputs(rt_addr_n2a(ifa->ifa_family,
RTA_DATA(rta_tb[IFA_LOCAL]),
- abuf, sizeof(abuf)));
+ abuf, sizeof(abuf)), stdout);
- if (rta_tb[IFA_ADDRESS] == NULL ||
- memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0) {
- fprintf(fp, "/%d ", ifa->ifa_prefixlen);
+ if (rta_tb[IFA_ADDRESS] == NULL
+ || memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0
+ ) {
+ printf("/%d ", ifa->ifa_prefixlen);
} else {
- fprintf(fp, " peer %s/%d ",
+ printf(" peer %s/%d ",
rt_addr_n2a(ifa->ifa_family,
- RTA_PAYLOAD(rta_tb[IFA_ADDRESS]),
RTA_DATA(rta_tb[IFA_ADDRESS]),
abuf, sizeof(abuf)),
ifa->ifa_prefixlen);
@@ -306,44 +297,42 @@ static int print_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg
}
if (rta_tb[IFA_BROADCAST]) {
- fprintf(fp, "brd %s ",
+ printf("brd %s ",
rt_addr_n2a(ifa->ifa_family,
- RTA_PAYLOAD(rta_tb[IFA_BROADCAST]),
RTA_DATA(rta_tb[IFA_BROADCAST]),
abuf, sizeof(abuf)));
}
if (rta_tb[IFA_ANYCAST]) {
- fprintf(fp, "any %s ",
+ printf("any %s ",
rt_addr_n2a(ifa->ifa_family,
- RTA_PAYLOAD(rta_tb[IFA_ANYCAST]),
RTA_DATA(rta_tb[IFA_ANYCAST]),
abuf, sizeof(abuf)));
}
- fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
- if (ifa->ifa_flags&IFA_F_SECONDARY) {
+ printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
+ if (ifa->ifa_flags & IFA_F_SECONDARY) {
ifa->ifa_flags &= ~IFA_F_SECONDARY;
- fprintf(fp, "secondary ");
+ printf("secondary ");
}
- if (ifa->ifa_flags&IFA_F_TENTATIVE) {
+ if (ifa->ifa_flags & IFA_F_TENTATIVE) {
ifa->ifa_flags &= ~IFA_F_TENTATIVE;
- fprintf(fp, "tentative ");
+ printf("tentative ");
}
- if (ifa->ifa_flags&IFA_F_DEPRECATED) {
+ if (ifa->ifa_flags & IFA_F_DEPRECATED) {
ifa->ifa_flags &= ~IFA_F_DEPRECATED;
- fprintf(fp, "deprecated ");
+ printf("deprecated ");
}
- if (!(ifa->ifa_flags&IFA_F_PERMANENT)) {
- fprintf(fp, "dynamic ");
+ if (!(ifa->ifa_flags & IFA_F_PERMANENT)) {
+ printf("dynamic ");
} else
ifa->ifa_flags &= ~IFA_F_PERMANENT;
if (ifa->ifa_flags)
- fprintf(fp, "flags %02x ", ifa->ifa_flags);
+ printf("flags %02x ", ifa->ifa_flags);
if (rta_tb[IFA_LABEL])
- fprintf(fp, "%s", (char*)RTA_DATA(rta_tb[IFA_LABEL]));
+ fputs((char*)RTA_DATA(rta_tb[IFA_LABEL]), stdout);
if (rta_tb[IFA_CACHEINFO]) {
struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
char buf[128];
- fprintf(fp, "%s", _SL_);
+ bb_putchar(_SL_);
if (ci->ifa_valid == 0xFFFFFFFFU)
sprintf(buf, "valid_lft forever");
else
@@ -352,10 +341,10 @@ static int print_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg
sprintf(buf+strlen(buf), " preferred_lft forever");
else
sprintf(buf+strlen(buf), " preferred_lft %dsec", ci->ifa_prefered);
- fprintf(fp, " %s", buf);
+ printf(" %s", buf);
}
- fprintf(fp, "\n");
- fflush(fp);
+ bb_putchar('\n');
+ /*fflush(stdout);*/
return 0;
}
@@ -366,9 +355,9 @@ struct nlmsg_list
struct nlmsghdr h;
};
-static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *fp)
+static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo)
{
- for ( ;ainfo ; ainfo = ainfo->next) {
+ for (; ainfo; ainfo = ainfo->next) {
struct nlmsghdr *n = &ainfo->h;
struct ifaddrmsg *ifa = NLMSG_DATA(n);
@@ -378,17 +367,17 @@ static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *
if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifa)))
return -1;
- if (ifa->ifa_index != ifindex ||
+ if (ifa->ifa_index != ifindex ||
(filter.family && filter.family != ifa->ifa_family))
continue;
- print_addrinfo(NULL, n, fp);
+ print_addrinfo(NULL, n, NULL);
}
return 0;
}
-static int store_nlmsg(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
struct nlmsg_list **linfo = (struct nlmsg_list**)arg;
struct nlmsg_list *h;
@@ -401,7 +390,8 @@ static int store_nlmsg(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
memcpy(&h->h, n, n->nlmsg_len);
h->next = NULL;
- for (lp = linfo; *lp; lp = &(*lp)->next) /* NOTHING */;
+ for (lp = linfo; *lp; lp = &(*lp)->next)
+ continue;
*lp = h;
ll_remember_index(who, n, NULL);
@@ -414,9 +404,11 @@ static void ipaddr_reset_filter(int _oneline)
filter.oneline = _oneline;
}
-extern int ipaddr_list_or_flush(int argc, char **argv, int flush)
+/* Return value becomes exitcode. It's okay to not return at all */
+int ipaddr_list_or_flush(char **argv, int flush)
{
- const char *option[] = { "to", "scope", "up", "label", "dev", 0 };
+ static const char option[] ALIGN1 = "to\0""scope\0""up\0""label\0""dev\0";
+
struct nlmsg_list *linfo = NULL;
struct nlmsg_list *ainfo = NULL;
struct nlmsg_list *l;
@@ -431,18 +423,16 @@ extern int ipaddr_list_or_flush(int argc, char **argv, int flush)
filter.family = preferred_family;
if (flush) {
- if (argc <= 0) {
- fprintf(stderr, "Flush requires arguments.\n");
- return -1;
+ if (!*argv) {
+ bb_error_msg_and_die(bb_msg_requires_arg, "flush");
}
if (filter.family == AF_PACKET) {
- fprintf(stderr, "Cannot flush link addresses.\n");
- return -1;
+ bb_error_msg_and_die("cannot flush link addresses");
}
}
- while (argc > 0) {
- const unsigned short option_num = compare_string_array(option, *argv);
+ while (*argv) {
+ const int option_num = index_in_strings(option, *argv);
switch (option_num) {
case 0: /* to */
NEXT_ARG();
@@ -453,12 +443,12 @@ extern int ipaddr_list_or_flush(int argc, char **argv, int flush)
break;
case 1: /* scope */
{
- int scope = 0;
+ uint32_t scope = 0;
NEXT_ARG();
filter.scopemask = -1;
if (rtnl_rtscope_a2n(&scope, *argv)) {
if (strcmp(*argv, "all") != 0) {
- invarg("invalid \"scope\"\n", *argv);
+ invarg(*argv, "scope");
}
scope = RT_SCOPE_NOWHERE;
filter.scopemask = 0;
@@ -482,30 +472,18 @@ extern int ipaddr_list_or_flush(int argc, char **argv, int flush)
filter_dev = *argv;
}
argv++;
- argc--;
}
- if (rtnl_open(&rth, 0) < 0)
- exit(1);
+ xrtnl_open(&rth);
- if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) {
- bb_perror_msg_and_die("Cannot send dump request");
- }
-
- if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) {
- bb_error_msg_and_die("Dump terminated");
- }
+ xrtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK);
+ xrtnl_dump_filter(&rth, store_nlmsg, &linfo);
if (filter_dev) {
- filter.ifindex = ll_name_to_index(filter_dev);
- if (filter.ifindex <= 0) {
- bb_error_msg("Device \"%s\" does not exist.", filter_dev);
- return -1;
- }
+ filter.ifindex = xll_name_to_index(filter_dev);
}
if (flush) {
- int round = 0;
char flushb[4096-512];
filter.flushb = flushb;
@@ -514,62 +492,45 @@ extern int ipaddr_list_or_flush(int argc, char **argv, int flush)
filter.rth = &rth;
for (;;) {
- if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
- perror("Cannot send dump request");
- exit(1);
- }
+ xrtnl_wilddump_request(&rth, filter.family, RTM_GETADDR);
filter.flushed = 0;
- if (rtnl_dump_filter(&rth, print_addrinfo, stdout, NULL, NULL) < 0) {
- fprintf(stderr, "Flush terminated\n");
- exit(1);
- }
+ xrtnl_dump_filter(&rth, print_addrinfo, NULL);
if (filter.flushed == 0) {
-#if 0
- if (round == 0)
- fprintf(stderr, "Nothing to flush.\n");
-#endif
- fflush(stdout);
return 0;
}
- round++;
if (flush_update() < 0)
- exit(1);
+ return 1;
}
}
if (filter.family != AF_PACKET) {
- if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
- bb_perror_msg_and_die("Cannot send dump request");
- }
-
- if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) {
- bb_error_msg_and_die("Dump terminated");
- }
+ xrtnl_wilddump_request(&rth, filter.family, RTM_GETADDR);
+ xrtnl_dump_filter(&rth, store_nlmsg, &ainfo);
}
if (filter.family && filter.family != AF_PACKET) {
struct nlmsg_list **lp;
- lp=&linfo;
+ lp = &linfo;
if (filter.oneline)
no_link = 1;
- while ((l=*lp)!=NULL) {
+ while ((l = *lp) != NULL) {
int ok = 0;
struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
struct nlmsg_list *a;
- for (a=ainfo; a; a=a->next) {
+ for (a = ainfo; a; a = a->next) {
struct nlmsghdr *n = &a->h;
struct ifaddrmsg *ifa = NLMSG_DATA(n);
- if (ifa->ifa_index != ifi->ifi_index ||
+ if (ifa->ifa_index != ifi->ifi_index ||
(filter.family && filter.family != ifa->ifa_family))
continue;
- if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
+ if ((filter.scope ^ ifa->ifa_scope) & filter.scopemask)
continue;
- if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
+ if ((filter.flags ^ ifa->ifa_flags) & filter.flagmask)
continue;
if (filter.pfx.family || filter.label) {
struct rtattr *tb[IFA_MAX+1];
@@ -608,46 +569,47 @@ extern int ipaddr_list_or_flush(int argc, char **argv, int flush)
}
}
- for (l=linfo; l; l = l->next) {
- if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
+ for (l = linfo; l; l = l->next) {
+ if (no_link || print_linkinfo(&l->h) == 0) {
struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
if (filter.family != AF_PACKET)
- print_selected_addrinfo(ifi->ifi_index, ainfo, stdout);
+ print_selected_addrinfo(ifi->ifi_index, ainfo);
}
- fflush(stdout);
}
- exit(0);
+ return 0;
}
static int default_scope(inet_prefix *lcl)
{
if (lcl->family == AF_INET) {
- if (lcl->bytelen >= 1 && *(__u8*)&lcl->data == 127)
+ if (lcl->bytelen >= 1 && *(uint8_t*)&lcl->data == 127)
return RT_SCOPE_HOST;
}
return 0;
}
-static int ipaddr_modify(int cmd, int argc, char **argv)
+/* Return value becomes exitcode. It's okay to not return at all */
+static int ipaddr_modify(int cmd, char **argv)
{
- const char *option[] = { "peer", "remote", "broadcast", "brd",
- "anycast", "scope", "dev", "label", "local", 0 };
+ static const char option[] ALIGN1 =
+ "peer\0""remote\0""broadcast\0""brd\0"
+ "anycast\0""scope\0""dev\0""label\0""local\0";
struct rtnl_handle rth;
struct {
- struct nlmsghdr n;
- struct ifaddrmsg ifa;
- char buf[256];
+ struct nlmsghdr n;
+ struct ifaddrmsg ifa;
+ char buf[256];
} req;
- char *d = NULL;
- char *l = NULL;
+ char *d = NULL;
+ char *l = NULL;
inet_prefix lcl;
inet_prefix peer;
int local_len = 0;
int peer_len = 0;
int brd_len = 0;
int any_len = 0;
- int scoped = 0;
+ bool scoped = 0;
memset(&req, 0, sizeof(req));
@@ -656,8 +618,8 @@ static int ipaddr_modify(int cmd, int argc, char **argv)
req.n.nlmsg_type = cmd;
req.ifa.ifa_family = preferred_family;
- while (argc > 0) {
- const unsigned short option_num = compare_string_array(option, *argv);
+ while (*argv) {
+ const int option_num = index_in_strings(option, *argv);
switch (option_num) {
case 0: /* peer */
case 1: /* remote */
@@ -682,10 +644,9 @@ static int ipaddr_modify(int cmd, int argc, char **argv)
if (brd_len) {
duparg("broadcast", *argv);
}
- if (strcmp(*argv, "+") == 0) {
+ if (LONE_CHAR(*argv, '+')) {
brd_len = -1;
- }
- else if (strcmp(*argv, "-") == 0) {
+ } else if (LONE_DASH(*argv)) {
brd_len = -2;
} else {
get_addr(&addr, *argv, req.ifa.ifa_family);
@@ -713,10 +674,10 @@ static int ipaddr_modify(int cmd, int argc, char **argv)
}
case 5: /* scope */
{
- int scope = 0;
+ uint32_t scope = 0;
NEXT_ARG();
if (rtnl_rtscope_a2n(&scope, *argv)) {
- invarg(*argv, "invalid scope value.");
+ invarg(*argv, "scope");
}
req.ifa.ifa_scope = scope;
scoped = 1;
@@ -744,16 +705,15 @@ static int ipaddr_modify(int cmd, int argc, char **argv)
addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen);
local_len = lcl.bytelen;
}
- argc--;
argv++;
}
if (d == NULL) {
- bb_error_msg("Not enough information: \"dev\" argument is required.");
+ bb_error_msg(bb_msg_requires_arg, "\"dev\"");
return -1;
}
- if (l && matches(d, l) != 0) {
- bb_error_msg_and_die("\"dev\" (%s) must match \"label\" (%s).", d, l);
+ if (l && strncmp(d, l, strlen(d)) != 0) {
+ bb_error_msg_and_die("\"dev\" (%s) must match \"label\" (%s)", d, l);
}
if (peer_len == 0 && local_len && cmd != RTM_DELADDR) {
@@ -767,8 +727,7 @@ static int ipaddr_modify(int cmd, int argc, char **argv)
inet_prefix brd;
int i;
if (req.ifa.ifa_family != AF_INET) {
- bb_error_msg("Broadcast can be set only for IPv4 addresses");
- return -1;
+ bb_error_msg_and_die("broadcast can be set only for IPv4 addresses");
}
brd = peer;
if (brd.bitlen <= 30) {
@@ -785,41 +744,38 @@ static int ipaddr_modify(int cmd, int argc, char **argv)
if (!scoped && cmd != RTM_DELADDR)
req.ifa.ifa_scope = default_scope(&lcl);
- if (rtnl_open(&rth, 0) < 0)
- exit(1);
+ xrtnl_open(&rth);
ll_init_map(&rth);
- if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) {
- bb_error_msg("Cannot find device \"%s\"", d);
- return -1;
- }
+ req.ifa.ifa_index = xll_name_to_index(d);
if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
- exit(2);
+ return 2;
- exit(0);
+ return 0;
}
-extern int do_ipaddr(int argc, char **argv)
+/* Return value becomes exitcode. It's okay to not return at all */
+int do_ipaddr(char **argv)
{
- const char *commands[] = { "add", "delete", "list", "show", "lst", "flush", 0 };
- unsigned short command_num = 2;
+ static const char commands[] ALIGN1 =
+ "add\0""delete\0""list\0""show\0""lst\0""flush\0";
+
+ int command_num = 2; /* default command is list */
if (*argv) {
- command_num = compare_string_array(commands, *argv);
- }
- switch (command_num) {
- case 0: /* add */
- return ipaddr_modify(RTM_NEWADDR, argc-1, argv+1);
- case 1: /* delete */
- return ipaddr_modify(RTM_DELADDR, argc-1, argv+1);
- case 2: /* list */
- case 3: /* show */
- case 4: /* lst */
- return ipaddr_list_or_flush(argc-1, argv+1, 0);
- case 5: /* flush */
- return ipaddr_list_or_flush(argc-1, argv+1, 1);
- }
- bb_error_msg_and_die("Unknown command %s", *argv);
+ command_num = index_in_substrings(commands, *argv);
+ if (command_num < 0 || command_num > 5)
+ bb_error_msg_and_die("unknown command %s", *argv);
+ argv++;
+ }
+ if (command_num == 0) /* add */
+ return ipaddr_modify(RTM_NEWADDR, argv);
+ if (command_num == 1) /* delete */
+ return ipaddr_modify(RTM_DELADDR, argv);
+ if (command_num == 5) /* flush */
+ return ipaddr_list_or_flush(argv, 1);
+ /* 2 == list, 3 == show, 4 == lst */
+ return ipaddr_list_or_flush(argv, 0);
}
diff --git a/release/src/router/busybox/networking/libiproute/iplink.c b/release/src/router/busybox/networking/libiproute/iplink.c
index daab6938..1e7ee07d 100644
--- a/release/src/router/busybox/networking/libiproute/iplink.c
+++ b/release/src/router/busybox/networking/libiproute/iplink.c
@@ -1,248 +1,171 @@
+/* vi: set sw=4 ts=4: */
/*
- * iplink.c "ip link".
+ * iplink.c "ip link".
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <linux/version.h>
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
+//#include <sys/ioctl.h>
+//#include <sys/socket.h>
#include <net/if.h>
#include <net/if_packet.h>
#include <netpacket/packet.h>
-
-#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1
#include <net/ethernet.h>
-#else
-#include <linux/if_ether.h>
-#endif
+#include "ip_common.h" /* #include "libbb.h" is inside */
#include "rt_names.h"
#include "utils.h"
-#include "ip_common.h"
-
-#include "libbb.h"
-
-/* take from linux/sockios.h */
+/* taken from linux/sockios.h */
#define SIOCSIFNAME 0x8923 /* set interface name */
-static int do_link;
-
-static int on_off(char *msg)
-{
- bb_error_msg("Error: argument of \"%s\" must be \"on\" or \"off\"", msg);
- return -1;
-}
-
+/* Exits on error */
static int get_ctl_fd(void)
{
- int s_errno;
int fd;
fd = socket(PF_INET, SOCK_DGRAM, 0);
if (fd >= 0)
return fd;
- s_errno = errno;
fd = socket(PF_PACKET, SOCK_DGRAM, 0);
if (fd >= 0)
return fd;
- fd = socket(PF_INET6, SOCK_DGRAM, 0);
- if (fd >= 0)
- return fd;
- errno = s_errno;
- perror("Cannot create control socket");
- return -1;
+ return xsocket(PF_INET6, SOCK_DGRAM, 0);
}
-static int do_chflags(char *dev, __u32 flags, __u32 mask)
+/* Exits on error */
+static void do_chflags(char *dev, uint32_t flags, uint32_t mask)
{
struct ifreq ifr;
int fd;
- int err;
- strcpy(ifr.ifr_name, dev);
+ strncpy_IFNAMSIZ(ifr.ifr_name, dev);
fd = get_ctl_fd();
- if (fd < 0)
- return -1;
- err = ioctl(fd, SIOCGIFFLAGS, &ifr);
- if (err) {
- perror("SIOCGIFFLAGS");
- close(fd);
- return -1;
- }
- if ((ifr.ifr_flags^flags)&mask) {
+ xioctl(fd, SIOCGIFFLAGS, &ifr);
+ if ((ifr.ifr_flags ^ flags) & mask) {
ifr.ifr_flags &= ~mask;
- ifr.ifr_flags |= mask&flags;
- err = ioctl(fd, SIOCSIFFLAGS, &ifr);
- if (err)
- perror("SIOCSIFFLAGS");
+ ifr.ifr_flags |= mask & flags;
+ xioctl(fd, SIOCSIFFLAGS, &ifr);
}
close(fd);
- return err;
}
-static int do_changename(char *dev, char *newdev)
+/* Exits on error */
+static void do_changename(char *dev, char *newdev)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
struct ifreq ifr;
int fd;
- int err;
- strcpy(ifr.ifr_name, dev);
- strcpy(ifr.ifr_newname, newdev);
+ strncpy_IFNAMSIZ(ifr.ifr_name, dev);
+ strncpy_IFNAMSIZ(ifr.ifr_newname, newdev);
fd = get_ctl_fd();
- if (fd < 0)
- return -1;
- err = ioctl(fd, SIOCSIFNAME, &ifr);
- if (err) {
- perror("SIOCSIFNAME");
- close(fd);
- return -1;
- }
+ xioctl(fd, SIOCSIFNAME, &ifr);
close(fd);
- return err;
-#endif
- return 0;
}
-static int set_qlen(char *dev, int qlen)
+/* Exits on error */
+static void set_qlen(char *dev, int qlen)
{
struct ifreq ifr;
int s;
s = get_ctl_fd();
- if (s < 0)
- return -1;
-
memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, dev);
- ifr.ifr_qlen = qlen;
- if (ioctl(s, SIOCSIFTXQLEN, &ifr) < 0) {
- perror("SIOCSIFXQLEN");
- close(s);
- return -1;
- }
+ strncpy_IFNAMSIZ(ifr.ifr_name, dev);
+ ifr.ifr_qlen = qlen;
+ xioctl(s, SIOCSIFTXQLEN, &ifr);
close(s);
-
- return 0;
}
-static int set_mtu(char *dev, int mtu)
+/* Exits on error */
+static void set_mtu(char *dev, int mtu)
{
struct ifreq ifr;
int s;
s = get_ctl_fd();
- if (s < 0)
- return -1;
-
memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, dev);
- ifr.ifr_mtu = mtu;
- if (ioctl(s, SIOCSIFMTU, &ifr) < 0) {
- perror("SIOCSIFMTU");
- close(s);
- return -1;
- }
+ strncpy_IFNAMSIZ(ifr.ifr_name, dev);
+ ifr.ifr_mtu = mtu;
+ xioctl(s, SIOCSIFMTU, &ifr);
close(s);
-
- return 0;
}
+/* Exits on error */
static int get_address(char *dev, int *htype)
{
struct ifreq ifr;
struct sockaddr_ll me;
- int alen;
+ socklen_t alen;
int s;
- s = socket(PF_PACKET, SOCK_DGRAM, 0);
- if (s < 0) {
- perror("socket(PF_PACKET)");
- return -1;
- }
+ s = xsocket(PF_PACKET, SOCK_DGRAM, 0);
memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, dev);
- if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
- perror("SIOCGIFINDEX");
- close(s);
- return -1;
- }
+ strncpy_IFNAMSIZ(ifr.ifr_name, dev);
+ xioctl(s, SIOCGIFINDEX, &ifr);
memset(&me, 0, sizeof(me));
me.sll_family = AF_PACKET;
me.sll_ifindex = ifr.ifr_ifindex;
me.sll_protocol = htons(ETH_P_LOOP);
- if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) {
- perror("bind");
- close(s);
- return -1;
- }
+ xbind(s, (struct sockaddr*)&me, sizeof(me));
alen = sizeof(me);
if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) {
- perror("getsockname");
- close(s);
- return -1;
+ bb_perror_msg_and_die("getsockname");
}
close(s);
*htype = me.sll_hatype;
return me.sll_halen;
}
-static int parse_address(char *dev, int hatype, int halen, char *lla, struct ifreq *ifr)
+/* Exits on error */
+static void parse_address(char *dev, int hatype, int halen, char *lla, struct ifreq *ifr)
{
int alen;
memset(ifr, 0, sizeof(*ifr));
- strcpy(ifr->ifr_name, dev);
+ strncpy_IFNAMSIZ(ifr->ifr_name, dev);
ifr->ifr_hwaddr.sa_family = hatype;
- alen = ll_addr_a2n(ifr->ifr_hwaddr.sa_data, 14, lla);
+
+ alen = hatype == 1/*ARPHRD_ETHER*/ ? 14/*ETH_HLEN*/ : 19/*INFINIBAND_HLEN*/;
+ alen = ll_addr_a2n((unsigned char *)(ifr->ifr_hwaddr.sa_data), alen, lla);
if (alen < 0)
- return -1;
+ exit(EXIT_FAILURE);
if (alen != halen) {
- bb_error_msg("Wrong address (%s) length: expected %d bytes", lla, halen);
- return -1;
+ bb_error_msg_and_die("wrong address (%s) length: expected %d bytes", lla, halen);
}
- return 0;
}
-static int set_address(struct ifreq *ifr, int brd)
+/* Exits on error */
+static void set_address(struct ifreq *ifr, int brd)
{
int s;
s = get_ctl_fd();
- if (s < 0)
- return -1;
- if (ioctl(s, brd?SIOCSIFHWBROADCAST:SIOCSIFHWADDR, ifr) < 0) {
- perror(brd?"SIOCSIFHWBROADCAST":"SIOCSIFHWADDR");
- close(s);
- return -1;
- }
+ if (brd)
+ xioctl(s, SIOCSIFHWBROADCAST, ifr);
+ else
+ xioctl(s, SIOCSIFHWADDR, ifr);
close(s);
- return 0;
}
-static int do_set(int argc, char **argv)
+static void die_must_be_on_off(const char *msg) NORETURN;
+static void die_must_be_on_off(const char *msg)
+{
+ bb_error_msg_and_die("argument of \"%s\" must be \"on\" or \"off\"", msg);
+}
+
+/* Return value becomes exitcode. It's okay to not return at all */
+static int do_set(char **argv)
{
char *dev = NULL;
- __u32 mask = 0;
- __u32 flags = 0;
+ uint32_t mask = 0;
+ uint32_t flags = 0;
int qlen = -1;
int mtu = -1;
char *newaddr = NULL;
@@ -250,118 +173,133 @@ static int do_set(int argc, char **argv)
struct ifreq ifr0, ifr1;
char *newname = NULL;
int htype, halen;
-
- while (argc > 0) {
- if (strcmp(*argv, "up") == 0) {
+ static const char keywords[] ALIGN1 =
+ "up\0""down\0""name\0""mtu\0""multicast\0"
+ "arp\0""address\0""dev\0";
+ enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_multicast,
+ ARG_arp, ARG_addr, ARG_dev };
+ static const char str_on_off[] ALIGN1 = "on\0""off\0";
+ 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);
+ if (key == ARG_up) {
mask |= IFF_UP;
flags |= IFF_UP;
- } else if (strcmp(*argv, "down") == 0) {
+ }
+ if (key == ARG_down) {
mask |= IFF_UP;
flags &= ~IFF_UP;
- } else if (strcmp(*argv, "name") == 0) {
+ }
+ if (key == ARG_name) {
NEXT_ARG();
newname = *argv;
- } else if (strcmp(*argv, "mtu") == 0) {
+ }
+ if (key == ARG_mtu) {
NEXT_ARG();
if (mtu != -1)
duparg("mtu", *argv);
- if (get_integer(&mtu, *argv, 0))
- invarg("Invalid \"mtu\" value\n", *argv);
- } else if (strcmp(*argv, "multicast") == 0) {
+ mtu = get_unsigned(*argv, "mtu");
+ }
+ if (key == ARG_multicast) {
+ int param;
NEXT_ARG();
mask |= IFF_MULTICAST;
- if (strcmp(*argv, "on") == 0) {
+ param = index_in_strings(str_on_off, *argv);
+ if (param < 0)
+ die_must_be_on_off("multicast");
+ if (param == PARM_on)
flags |= IFF_MULTICAST;
- } else if (strcmp(*argv, "off") == 0) {
+ else
flags &= ~IFF_MULTICAST;
- } else
- return on_off("multicast");
- } else if (strcmp(*argv, "arp") == 0) {
+ }
+ if (key == ARG_arp) {
+ int param;
NEXT_ARG();
mask |= IFF_NOARP;
- if (strcmp(*argv, "on") == 0) {
+ param = index_in_strings(str_on_off, *argv);
+ if (param < 0)
+ die_must_be_on_off("arp");
+ if (param == PARM_on)
flags &= ~IFF_NOARP;
- } else if (strcmp(*argv, "off") == 0) {
+ else
flags |= IFF_NOARP;
- } else
- return on_off("noarp");
- } else {
- if (strcmp(*argv, "dev") == 0) {
+ }
+ if (key == ARG_addr) {
+ NEXT_ARG();
+ newaddr = *argv;
+ }
+ if (key >= ARG_dev) {
+ if (key == ARG_dev) {
NEXT_ARG();
}
if (dev)
duparg2("dev", *argv);
dev = *argv;
}
- argc--; argv++;
+ argv++;
}
if (!dev) {
- bb_error_msg("Not enough of information: \"dev\" argument is required.");
- exit(-1);
+ bb_error_msg_and_die(bb_msg_requires_arg, "\"dev\"");
}
if (newaddr || newbrd) {
halen = get_address(dev, &htype);
- if (halen < 0)
- return -1;
if (newaddr) {
- if (parse_address(dev, htype, halen, newaddr, &ifr0) < 0)
- return -1;
+ parse_address(dev, htype, halen, newaddr, &ifr0);
}
if (newbrd) {
- if (parse_address(dev, htype, halen, newbrd, &ifr1) < 0)
- return -1;
+ parse_address(dev, htype, halen, newbrd, &ifr1);
}
}
if (newname && strcmp(dev, newname)) {
- if (do_changename(dev, newname) < 0)
- return -1;
+ do_changename(dev, newname);
dev = newname;
}
- if (qlen != -1) {
- if (set_qlen(dev, qlen) < 0)
- return -1;
+ if (qlen != -1) {
+ set_qlen(dev, qlen);
}
- if (mtu != -1) {
- if (set_mtu(dev, mtu) < 0)
- return -1;
+ if (mtu != -1) {
+ set_mtu(dev, mtu);
}
if (newaddr || newbrd) {
if (newbrd) {
- if (set_address(&ifr1, 1) < 0)
- return -1;
+ set_address(&ifr1, 1);
}
if (newaddr) {
- if (set_address(&ifr0, 0) < 0)
- return -1;
+ set_address(&ifr0, 0);
}
}
if (mask)
- return do_chflags(dev, flags, mask);
+ do_chflags(dev, flags, mask);
return 0;
}
-static int ipaddr_list_link(int argc, char **argv)
+static int ipaddr_list_link(char **argv)
{
preferred_family = AF_PACKET;
- do_link = 1;
- return ipaddr_list_or_flush(argc, argv, 0);
+ return ipaddr_list_or_flush(argv, 0);
}
-int do_iplink(int argc, char **argv)
+/* Return value becomes exitcode. It's okay to not return at all */
+int do_iplink(char **argv)
{
- if (argc > 0) {
- if (matches(*argv, "set") == 0)
- return do_set(argc-1, argv+1);
- if (matches(*argv, "show") == 0 ||
- matches(*argv, "lst") == 0 ||
- matches(*argv, "list") == 0)
- return ipaddr_list_link(argc-1, argv+1);
- } else
- return ipaddr_list_link(0, NULL);
-
- bb_error_msg("Command \"%s\" is unknown, try \"ip link help\".", *argv);
- exit(-1);
+ static const char keywords[] ALIGN1 =
+ "set\0""show\0""lst\0""list\0";
+ int key;
+ if (!*argv)
+ return ipaddr_list_link(argv);
+ key = index_in_substrings(keywords, *argv);
+ if (key < 0)
+ bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
+ argv++;
+ if (key == 0) /* set */
+ return do_set(argv);
+ /* show, lst, list */
+ return ipaddr_list_link(argv);
}
diff --git a/release/src/router/busybox/networking/libiproute/iproute.c b/release/src/router/busybox/networking/libiproute/iproute.c
index 70ddf9f4..66557d8f 100644
--- a/release/src/router/busybox/networking/libiproute/iproute.c
+++ b/release/src/router/busybox/networking/libiproute/iproute.c
@@ -1,10 +1,8 @@
+/* vi: set sw=4 ts=4: */
/*
* iproute.c "ip route".
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
@@ -15,27 +13,18 @@
* Kunihiro Ishiguro <kunihiro@zebra.org> 001102: rtnh_ifindex was not initialized
*/
-#include <sys/socket.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-
+#include "ip_common.h" /* #include "libbb.h" is inside */
#include "rt_names.h"
#include "utils.h"
-#include "libbb.h"
-
#ifndef RTAX_RTTVAR
#define RTAX_RTTVAR RTAX_HOPS
#endif
-static struct
-{
+typedef struct filter_t {
int tb;
- int flushed;
+ smallint flushed;
char *flushb;
int flushp;
int flushe;
@@ -53,21 +42,45 @@ static struct
inet_prefix mdst;
inet_prefix rsrc;
inet_prefix msrc;
-} filter;
+} filter_t;
+
+#define filter (*(filter_t*)&bb_common_bufsiz1)
static int flush_update(void)
{
if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) {
- perror("Failed to send flush request\n");
+ bb_perror_msg("failed to send flush request");
return -1;
}
filter.flushp = 0;
return 0;
}
-static int print_route(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+static unsigned get_hz(void)
+{
+ static unsigned hz_internal;
+ FILE *fp;
+
+ if (hz_internal)
+ return hz_internal;
+
+ fp = fopen_for_read("/proc/net/psched");
+ if (fp) {
+ unsigned nom, denom;
+
+ if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
+ if (nom == 1000000)
+ hz_internal = denom;
+ fclose(fp);
+ }
+ if (!hz_internal)
+ hz_internal = sysconf(_SC_CLK_TCK);
+ return hz_internal;
+}
+
+static int print_route(const struct sockaddr_nl *who UNUSED_PARAM,
+ struct nlmsghdr *n, void *arg UNUSED_PARAM)
{
- FILE *fp = (FILE*)arg;
struct rtmsg *r = NLMSG_DATA(n);
int len = n->nlmsg_len;
struct rtattr * tb[RTA_MAX+1];
@@ -76,7 +89,6 @@ static int print_route(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
inet_prefix src;
int host_len = -1;
SPRINT_BUF(b1);
-
if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
fprintf(stderr, "Not a route: %08x %08x %08x\n",
@@ -86,10 +98,8 @@ static int print_route(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
if (filter.flushb && n->nlmsg_type != RTM_NEWROUTE)
return 0;
len -= NLMSG_LENGTH(sizeof(*r));
- if (len < 0) {
- bb_error_msg("wrong nlmsg len %d", len);
- return -1;
- }
+ if (len < 0)
+ bb_error_msg_and_die("wrong nlmsg len %d", len);
if (r->rtm_family == AF_INET6)
host_len = 128;
@@ -99,11 +109,11 @@ static int print_route(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
if (r->rtm_family == AF_INET6) {
if (filter.tb) {
if (filter.tb < 0) {
- if (!(r->rtm_flags&RTM_F_CLONED)) {
+ if (!(r->rtm_flags & RTM_F_CLONED)) {
return 0;
}
} else {
- if (r->rtm_flags&RTM_F_CLONED) {
+ if (r->rtm_flags & RTM_F_CLONED) {
return 0;
}
if (filter.tb == RT_TABLE_LOCAL) {
@@ -170,7 +180,7 @@ static int print_route(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
struct nlmsghdr *fn;
if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
if (flush_update())
- return -1;
+ bb_error_msg_and_die("flush");
}
fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp));
memcpy(fn, n, n->nlmsg_len);
@@ -178,78 +188,73 @@ static int print_route(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
fn->nlmsg_flags = NLM_F_REQUEST;
fn->nlmsg_seq = ++filter.rth->seq;
filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
- filter.flushed++;
+ filter.flushed = 1;
return 0;
}
if (n->nlmsg_type == RTM_DELROUTE) {
- fprintf(fp, "Deleted ");
+ printf("Deleted ");
}
if (r->rtm_type != RTN_UNICAST && !filter.type) {
- fprintf(fp, "%s ", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
+ printf("%s ", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
}
if (tb[RTA_DST]) {
if (r->rtm_dst_len != host_len) {
- fprintf(fp, "%s/%u ", rt_addr_n2a(r->rtm_family,
- RTA_PAYLOAD(tb[RTA_DST]),
- RTA_DATA(tb[RTA_DST]),
- abuf, sizeof(abuf)),
- r->rtm_dst_len
- );
+ printf("%s/%u ", rt_addr_n2a(r->rtm_family,
+ RTA_DATA(tb[RTA_DST]),
+ abuf, sizeof(abuf)),
+ r->rtm_dst_len
+ );
} else {
- fprintf(fp, "%s ", format_host(r->rtm_family,
- RTA_PAYLOAD(tb[RTA_DST]),
- RTA_DATA(tb[RTA_DST]),
- abuf, sizeof(abuf))
- );
+ printf("%s ", format_host(r->rtm_family,
+ RTA_PAYLOAD(tb[RTA_DST]),
+ RTA_DATA(tb[RTA_DST]),
+ abuf, sizeof(abuf))
+ );
}
} else if (r->rtm_dst_len) {
- fprintf(fp, "0/%d ", r->rtm_dst_len);
+ printf("0/%d ", r->rtm_dst_len);
} else {
- fprintf(fp, "default ");
+ printf("default ");
}
if (tb[RTA_SRC]) {
if (r->rtm_src_len != host_len) {
- fprintf(fp, "from %s/%u ", rt_addr_n2a(r->rtm_family,
- RTA_PAYLOAD(tb[RTA_SRC]),
- RTA_DATA(tb[RTA_SRC]),
- abuf, sizeof(abuf)),
- r->rtm_src_len
- );
+ printf("from %s/%u ", rt_addr_n2a(r->rtm_family,
+ RTA_DATA(tb[RTA_SRC]),
+ abuf, sizeof(abuf)),
+ r->rtm_src_len
+ );
} else {
- fprintf(fp, "from %s ", format_host(r->rtm_family,
- RTA_PAYLOAD(tb[RTA_SRC]),
- RTA_DATA(tb[RTA_SRC]),
- abuf, sizeof(abuf))
- );
+ printf("from %s ", format_host(r->rtm_family,
+ RTA_PAYLOAD(tb[RTA_SRC]),
+ RTA_DATA(tb[RTA_SRC]),
+ abuf, sizeof(abuf))
+ );
}
} else if (r->rtm_src_len) {
- fprintf(fp, "from 0/%u ", r->rtm_src_len);
+ printf("from 0/%u ", r->rtm_src_len);
}
if (tb[RTA_GATEWAY] && filter.rvia.bitlen != host_len) {
- fprintf(fp, "via %s ",
- format_host(r->rtm_family,
- RTA_PAYLOAD(tb[RTA_GATEWAY]),
- RTA_DATA(tb[RTA_GATEWAY]),
- abuf, sizeof(abuf)));
+ printf("via %s ", format_host(r->rtm_family,
+ RTA_PAYLOAD(tb[RTA_GATEWAY]),
+ RTA_DATA(tb[RTA_GATEWAY]),
+ abuf, sizeof(abuf)));
}
if (tb[RTA_OIF] && filter.oifmask != -1) {
- fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
+ printf("dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
}
if (tb[RTA_PREFSRC] && filter.rprefsrc.bitlen != host_len) {
/* Do not use format_host(). It is our local addr
and symbolic name will not be useful.
*/
- fprintf(fp, " src %s ",
- rt_addr_n2a(r->rtm_family,
- RTA_PAYLOAD(tb[RTA_PREFSRC]),
- RTA_DATA(tb[RTA_PREFSRC]),
- abuf, sizeof(abuf)));
+ printf(" src %s ", rt_addr_n2a(r->rtm_family,
+ RTA_DATA(tb[RTA_PREFSRC]),
+ abuf, sizeof(abuf)));
}
if (tb[RTA_PRIORITY]) {
- fprintf(fp, " metric %d ", *(__u32*)RTA_DATA(tb[RTA_PRIORITY]));
+ printf(" metric %d ", *(uint32_t*)RTA_DATA(tb[RTA_PRIORITY]));
}
if (r->rtm_family == AF_INET6) {
struct rta_cacheinfo *ci = NULL;
@@ -257,57 +262,73 @@ static int print_route(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
ci = RTA_DATA(tb[RTA_CACHEINFO]);
}
if ((r->rtm_flags & RTM_F_CLONED) || (ci && ci->rta_expires)) {
- static int hz;
- if (!hz) {
- hz = get_hz();
- }
if (r->rtm_flags & RTM_F_CLONED) {
- fprintf(fp, "%s cache ", _SL_);
+ printf("%c cache ", _SL_);
}
if (ci->rta_expires) {
- fprintf(fp, " expires %dsec", ci->rta_expires/hz);
+ printf(" expires %dsec", ci->rta_expires / get_hz());
}
if (ci->rta_error != 0) {
- fprintf(fp, " error %d", ci->rta_error);
+ printf(" error %d", ci->rta_error);
}
} else if (ci) {
if (ci->rta_error != 0)
- fprintf(fp, " error %d", ci->rta_error);
+ printf(" error %d", ci->rta_error);
}
}
if (tb[RTA_IIF] && filter.iifmask != -1) {
- fprintf(fp, " iif %s", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_IIF])));
+ printf(" iif %s", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_IIF])));
}
- fprintf(fp, "\n");
- fflush(fp);
+ bb_putchar('\n');
return 0;
}
-static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
+/* Return value becomes exitcode. It's okay to not return at all */
+static int iproute_modify(int cmd, unsigned flags, char **argv)
{
+ static const char keywords[] ALIGN1 =
+ "src\0""via\0""mtu\0""lock\0""protocol\0"USE_FEATURE_IP_RULE("table\0")
+ "dev\0""oif\0""to\0""metric\0";
+ enum {
+ ARG_src,
+ ARG_via,
+ ARG_mtu, PARM_lock,
+ ARG_protocol,
+USE_FEATURE_IP_RULE(ARG_table,)
+ ARG_dev,
+ ARG_oif,
+ ARG_to,
+ ARG_metric,
+ };
+ enum {
+ gw_ok = 1 << 0,
+ dst_ok = 1 << 1,
+ proto_ok = 1 << 2,
+ type_ok = 1 << 3
+ };
struct rtnl_handle rth;
struct {
- struct nlmsghdr n;
- struct rtmsg r;
- char buf[1024];
+ struct nlmsghdr n;
+ struct rtmsg r;
+ char buf[1024];
} req;
- char mxbuf[256];
+ char mxbuf[256];
struct rtattr * mxrta = (void*)mxbuf;
unsigned mxlock = 0;
- char *d = NULL;
- int gw_ok = 0;
- int dst_ok = 0;
- int proto_ok = 0;
- int type_ok = 0;
+ char *d = NULL;
+ smalluint ok = 0;
+ int arg;
memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- req.n.nlmsg_flags = NLM_F_REQUEST|flags;
+ req.n.nlmsg_flags = NLM_F_REQUEST | flags;
req.n.nlmsg_type = cmd;
req.r.rtm_family = preferred_family;
- req.r.rtm_table = RT_TABLE_MAIN;
- req.r.rtm_scope = RT_SCOPE_NOWHERE;
+ if (RT_TABLE_MAIN) /* if it is zero, memset already did it */
+ req.r.rtm_table = RT_TABLE_MAIN;
+ if (RT_SCOPE_NOWHERE)
+ req.r.rtm_scope = RT_SCOPE_NOWHERE;
if (cmd != RTM_DELROUTE) {
req.r.rtm_protocol = RTPROT_BOOT;
@@ -318,61 +339,71 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
mxrta->rta_type = RTA_METRICS;
mxrta->rta_len = RTA_LENGTH(0);
- while (argc > 0) {
- if (strcmp(*argv, "src") == 0) {
+ while (*argv) {
+ arg = index_in_substrings(keywords, *argv);
+ if (arg == ARG_src) {
inet_prefix addr;
NEXT_ARG();
get_addr(&addr, *argv, req.r.rtm_family);
- if (req.r.rtm_family == AF_UNSPEC) {
+ if (req.r.rtm_family == AF_UNSPEC)
req.r.rtm_family = addr.family;
- }
addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &addr.data, addr.bytelen);
- } else if (strcmp(*argv, "via") == 0) {
+ } else if (arg == ARG_via) {
inet_prefix addr;
- gw_ok = 1;
+ ok |= gw_ok;
NEXT_ARG();
get_addr(&addr, *argv, req.r.rtm_family);
if (req.r.rtm_family == AF_UNSPEC) {
req.r.rtm_family = addr.family;
}
addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen);
- } else if (strcmp(*argv, "mtu") == 0) {
+ } else if (arg == ARG_mtu) {
unsigned mtu;
NEXT_ARG();
- if (strcmp(*argv, "lock") == 0) {
- mxlock |= (1<<RTAX_MTU);
+ if (index_in_strings(keywords, *argv) == PARM_lock) {
+ mxlock |= (1 << RTAX_MTU);
NEXT_ARG();
}
- if (get_unsigned(&mtu, *argv, 0)) {
- invarg("\"mtu\" value is invalid\n", *argv);
- }
+ mtu = get_unsigned(*argv, "mtu");
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu);
- } else if (matches(*argv, "protocol") == 0) {
- int prot;
+ } else if (arg == ARG_protocol) {
+ uint32_t prot;
NEXT_ARG();
if (rtnl_rtprot_a2n(&prot, *argv))
- invarg("\"protocol\" value is invalid\n", *argv);
+ invarg(*argv, "protocol");
req.r.rtm_protocol = prot;
- proto_ok =1;
- } else if (strcmp(*argv, "dev") == 0 ||
- strcmp(*argv, "oif") == 0) {
+ ok |= proto_ok;
+#if ENABLE_FEATURE_IP_RULE
+ } else if (arg == ARG_table) {
+ uint32_t tid;
+ NEXT_ARG();
+ if (rtnl_rttable_a2n(&tid, *argv))
+ invarg(*argv, "table");
+ req.r.rtm_table = tid;
+#endif
+ } else if (arg == ARG_dev || arg == ARG_oif) {
NEXT_ARG();
d = *argv;
+ } else if (arg == ARG_metric) {
+ uint32_t metric;
+ NEXT_ARG();
+ metric = get_u32(*argv, "metric");
+ addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric);
} else {
int type;
inet_prefix dst;
- if (strcmp(*argv, "to") == 0) {
+ if (arg == ARG_to) {
NEXT_ARG();
}
- if ((**argv < '0' || **argv > '9') &&
- rtnl_rtntype_a2n(&type, *argv) == 0) {
+ if ((**argv < '0' || **argv > '9')
+ && rtnl_rtntype_a2n(&type, *argv) == 0) {
NEXT_ARG();
req.r.rtm_type = type;
- type_ok = 1;
+ ok |= type_ok;
}
- if (dst_ok) {
+ if (ok & dst_ok) {
duparg2("to", *argv);
}
get_prefix(&dst, *argv, req.r.rtm_family);
@@ -380,17 +411,15 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
req.r.rtm_family = dst.family;
}
req.r.rtm_dst_len = dst.bitlen;
- dst_ok = 1;
+ ok |= dst_ok;
if (dst.bytelen) {
addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen);
}
}
- argc--; argv++;
+ argv++;
}
- if (rtnl_open(&rth, 0) < 0) {
- exit(1);
- }
+ xrtnl_open(&rth);
if (d) {
int idx;
@@ -398,10 +427,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
ll_init_map(&rth);
if (d) {
- if ((idx = ll_name_to_index(d)) == 0) {
- bb_error_msg("Cannot find device \"%s\"", d);
- return -1;
- }
+ idx = xll_name_to_index(d);
addattr32(&req.n, sizeof(req), RTA_OIF, idx);
}
}
@@ -413,12 +439,25 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta));
}
+ if (req.r.rtm_type == RTN_LOCAL || req.r.rtm_type == RTN_NAT)
+ req.r.rtm_scope = RT_SCOPE_HOST;
+ else if (req.r.rtm_type == RTN_BROADCAST ||
+ req.r.rtm_type == RTN_MULTICAST ||
+ req.r.rtm_type == RTN_ANYCAST)
+ req.r.rtm_scope = RT_SCOPE_LINK;
+ else if (req.r.rtm_type == RTN_UNICAST || req.r.rtm_type == RTN_UNSPEC) {
+ if (cmd == RTM_DELROUTE)
+ req.r.rtm_scope = RT_SCOPE_NOWHERE;
+ else if (!(ok & gw_ok))
+ req.r.rtm_scope = RT_SCOPE_LINK;
+ }
+
if (req.r.rtm_family == AF_UNSPEC) {
req.r.rtm_family = AF_INET;
}
if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) {
- exit(2);
+ return 2;
}
return 0;
@@ -437,37 +476,33 @@ static int rtnl_rtcache_request(struct rtnl_handle *rth, int family)
nladdr.nl_family = AF_NETLINK;
req.nlh.nlmsg_len = sizeof(req);
- req.nlh.nlmsg_type = RTM_GETROUTE;
- req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST;
- req.nlh.nlmsg_pid = 0;
+ if (RTM_GETROUTE)
+ req.nlh.nlmsg_type = RTM_GETROUTE;
+ if (NLM_F_ROOT | NLM_F_REQUEST)
+ req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
+ /*req.nlh.nlmsg_pid = 0; - memset did it already */
req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
req.rtm.rtm_family = family;
- req.rtm.rtm_flags |= RTM_F_CLONED;
+ if (RTM_F_CLONED)
+ req.rtm.rtm_flags = RTM_F_CLONED;
- return sendto(rth->fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
+ return xsendto(rth->fd, (void*)&req, sizeof(req), (struct sockaddr*)&nladdr, sizeof(nladdr));
}
-static int iproute_flush_cache(void)
+static void iproute_flush_cache(void)
{
-#define ROUTE_FLUSH_PATH "/proc/sys/net/ipv4/route/flush"
-
- int len;
- int flush_fd = open (ROUTE_FLUSH_PATH, O_WRONLY);
- char *buffer = "-1";
+ static const char fn[] ALIGN1 = "/proc/sys/net/ipv4/route/flush";
+ int flush_fd = open_or_warn(fn, O_WRONLY);
if (flush_fd < 0) {
- fprintf (stderr, "Cannot open \"%s\"\n", ROUTE_FLUSH_PATH);
- return -1;
+ return;
}
- len = strlen (buffer);
-
- if ((write (flush_fd, (void *)buffer, len)) < len) {
- fprintf (stderr, "Cannot flush routing cache\n");
- return -1;
+ if (write(flush_fd, "-1", 2) < 2) {
+ bb_perror_msg("cannot flush routing cache");
+ return;
}
close(flush_fd);
- return 0;
}
static void iproute_reset_filter(void)
@@ -477,112 +512,150 @@ static void iproute_reset_filter(void)
filter.msrc.bitlen = -1;
}
-static int iproute_list_or_flush(int argc, char **argv, int flush)
+/* Return value becomes exitcode. It's okay to not return at all */
+static int iproute_list_or_flush(char **argv, int flush)
{
int do_ipv6 = preferred_family;
struct rtnl_handle rth;
char *id = NULL;
char *od = NULL;
+ static const char keywords[] ALIGN1 =
+ /* "ip route list/flush" parameters: */
+ "protocol\0" "dev\0" "oif\0" "iif\0"
+ "via\0" "table\0" "cache\0"
+ "from\0" "to\0"
+ /* and possible further keywords */
+ "all\0"
+ "root\0"
+ "match\0"
+ "exact\0"
+ "main\0"
+ ;
+ enum {
+ KW_proto, KW_dev, KW_oif, KW_iif,
+ KW_via, KW_table, KW_cache,
+ KW_from, KW_to,
+ /* */
+ KW_all,
+ KW_root,
+ KW_match,
+ KW_exact,
+ KW_main,
+ };
+ int arg, parm;
iproute_reset_filter();
filter.tb = RT_TABLE_MAIN;
- if (flush && argc <= 0) {
- fprintf(stderr, "\"ip route flush\" requires arguments.\n");
- return -1;
- }
+ if (flush && !*argv)
+ bb_error_msg_and_die(bb_msg_requires_arg, "\"ip route flush\"");
- while (argc > 0) {
- if (matches(*argv, "protocol") == 0) {
- int prot = 0;
+ while (*argv) {
+ arg = index_in_substrings(keywords, *argv);
+ if (arg == KW_proto) {
+ uint32_t prot = 0;
NEXT_ARG();
filter.protocolmask = -1;
if (rtnl_rtprot_a2n(&prot, *argv)) {
- if (strcmp(*argv, "all") != 0) {
- invarg("invalid \"protocol\"\n", *argv);
- }
+ if (index_in_strings(keywords, *argv) != KW_all)
+ invarg(*argv, "protocol");
prot = 0;
filter.protocolmask = 0;
}
filter.protocol = prot;
- } else if (strcmp(*argv, "dev") == 0 ||
- strcmp(*argv, "oif") == 0) {
+ } else if (arg == KW_dev || arg == KW_oif) {
NEXT_ARG();
od = *argv;
- } else if (strcmp(*argv, "iif") == 0) {
+ } else if (arg == KW_iif) {
NEXT_ARG();
id = *argv;
- } else if (matches(*argv, "from") == 0) {
+ } else if (arg == KW_via) {
+ NEXT_ARG();
+ get_prefix(&filter.rvia, *argv, do_ipv6);
+ } else if (arg == KW_table) { /* table all/cache/main */
+ NEXT_ARG();
+ parm = index_in_substrings(keywords, *argv);
+ if (parm == KW_cache)
+ filter.tb = -1;
+ else if (parm == KW_all)
+ filter.tb = 0;
+ else if (parm != KW_main) {
+#if ENABLE_FEATURE_IP_RULE
+ uint32_t tid;
+ if (rtnl_rttable_a2n(&tid, *argv))
+ invarg(*argv, "table");
+ filter.tb = tid;
+#else
+ invarg(*argv, "table");
+#endif
+ }
+ } else if (arg == KW_cache) {
+ /* The command 'ip route flush cache' is used by OpenSWAN.
+ * Assuming it's a synonym for 'ip route flush table cache' */
+ filter.tb = -1;
+ } else if (arg == KW_from) {
NEXT_ARG();
- if (matches(*argv, "root") == 0) {
+ parm = index_in_substrings(keywords, *argv);
+ if (parm == KW_root) {
NEXT_ARG();
get_prefix(&filter.rsrc, *argv, do_ipv6);
- } else if (matches(*argv, "match") == 0) {
+ } else if (parm == KW_match) {
NEXT_ARG();
get_prefix(&filter.msrc, *argv, do_ipv6);
} else {
- if (matches(*argv, "exact") == 0) {
+ if (parm == KW_exact)
NEXT_ARG();
- }
get_prefix(&filter.msrc, *argv, do_ipv6);
filter.rsrc = filter.msrc;
}
- } else {
- if (matches(*argv, "to") == 0) {
+ } else { /* "to" is the default parameter */
+ if (arg == KW_to) {
NEXT_ARG();
+ arg = index_in_substrings(keywords, *argv);
}
- if (matches(*argv, "root") == 0) {
+ /* parm = arg; - would be more plausible, but we reuse 'arg' here */
+ if (arg == KW_root) {
NEXT_ARG();
get_prefix(&filter.rdst, *argv, do_ipv6);
- } else if (matches(*argv, "match") == 0) {
+ } else if (arg == KW_match) {
NEXT_ARG();
get_prefix(&filter.mdst, *argv, do_ipv6);
- } else {
- if (matches(*argv, "exact") == 0) {
+ } else { /* "to exact" is the default */
+ if (arg == KW_exact)
NEXT_ARG();
- }
get_prefix(&filter.mdst, *argv, do_ipv6);
filter.rdst = filter.mdst;
}
}
- argc--; argv++;
+ argv++;
}
if (do_ipv6 == AF_UNSPEC && filter.tb) {
do_ipv6 = AF_INET;
}
- if (rtnl_open(&rth, 0) < 0) {
- exit(1);
- }
-
+ xrtnl_open(&rth);
ll_init_map(&rth);
if (id || od) {
int idx;
if (id) {
- if ((idx = ll_name_to_index(id)) == 0) {
- bb_error_msg("Cannot find device \"%s\"", id);
- return -1;
- }
+ idx = xll_name_to_index(id);
filter.iif = idx;
filter.iifmask = -1;
}
if (od) {
- if ((idx = ll_name_to_index(od)) == 0) {
- bb_error_msg("Cannot find device \"%s\"", od);
- }
+ idx = xll_name_to_index(od);
filter.oif = idx;
filter.oifmask = -1;
}
}
if (flush) {
- int round = 0;
char flushb[4096-512];
- if (filter.tb == -1) {
+ if (filter.tb == -1) { /* "flush table cache" */
if (do_ipv6 != AF_INET6)
iproute_flush_cache();
if (do_ipv6 == AF_INET)
@@ -595,79 +668,63 @@ static int iproute_list_or_flush(int argc, char **argv, int flush)
filter.rth = &rth;
for (;;) {
- if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
- perror("Cannot send dump request");
- return -1;
- }
+ xrtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE);
filter.flushed = 0;
- if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) {
- bb_error_msg("Flush terminated\n");
- return -1;
- }
- if (filter.flushed == 0) {
- if (round == 0) {
- if (filter.tb != -1 || do_ipv6 == AF_INET6)
- fprintf(stderr, "Nothing to flush.\n");
- }
- fflush(stdout);
+ xrtnl_dump_filter(&rth, print_route, NULL);
+ if (filter.flushed == 0)
return 0;
- }
- round++;
- if (flush_update() < 0)
- exit(1);
+ if (flush_update())
+ return 1;
}
}
if (filter.tb != -1) {
- if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
- bb_perror_msg_and_die("Cannot send dump request");
- }
- } else {
- if (rtnl_rtcache_request(&rth, do_ipv6) < 0) {
- bb_perror_msg_and_die("Cannot send dump request");
- }
- }
-
- if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) {
- bb_error_msg_and_die("Dump terminated");
+ xrtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE);
+ } else if (rtnl_rtcache_request(&rth, do_ipv6) < 0) {
+ bb_perror_msg_and_die("cannot send dump request");
}
+ xrtnl_dump_filter(&rth, print_route, NULL);
- exit(0);
+ return 0;
}
-static int iproute_get(int argc, char **argv)
+/* Return value becomes exitcode. It's okay to not return at all */
+static int iproute_get(char **argv)
{
struct rtnl_handle rth;
struct {
- struct nlmsghdr n;
- struct rtmsg r;
- char buf[1024];
+ struct nlmsghdr n;
+ struct rtmsg r;
+ char buf[1024];
} req;
- char *idev = NULL;
- char *odev = NULL;
- int connected = 0;
- int from_ok = 0;
- const char *options[] = { "from", "iif", "oif", "dev", "notify", "connected", "to", 0 };
+ char *idev = NULL;
+ char *odev = NULL;
+ bool connected = 0;
+ bool from_ok = 0;
+ static const char options[] ALIGN1 =
+ "from\0""iif\0""oif\0""dev\0""notify\0""connected\0""to\0";
memset(&req, 0, sizeof(req));
iproute_reset_filter();
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- req.n.nlmsg_type = RTM_GETROUTE;
+ if (NLM_F_REQUEST)
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ if (RTM_GETROUTE)
+ req.n.nlmsg_type = RTM_GETROUTE;
req.r.rtm_family = preferred_family;
- req.r.rtm_table = 0;
- req.r.rtm_protocol = 0;
- req.r.rtm_scope = 0;
- req.r.rtm_type = 0;
- req.r.rtm_src_len = 0;
- req.r.rtm_dst_len = 0;
- req.r.rtm_tos = 0;
-
- while (argc > 0) {
- switch (compare_string_array(options, *argv)) {
+ /*req.r.rtm_table = 0; - memset did this already */
+ /*req.r.rtm_protocol = 0;*/
+ /*req.r.rtm_scope = 0;*/
+ /*req.r.rtm_type = 0;*/
+ /*req.r.rtm_src_len = 0;*/
+ /*req.r.rtm_dst_len = 0;*/
+ /*req.r.rtm_tos = 0;*/
+
+ while (*argv) {
+ switch (index_in_strings(options, *argv)) {
case 0: /* from */
{
inet_prefix addr;
@@ -712,7 +769,7 @@ static int iproute_get(int argc, char **argv)
}
req.r.rtm_dst_len = addr.bitlen;
}
- argc--; argv++;
+ argv++;
}
}
@@ -720,8 +777,7 @@ static int iproute_get(int argc, char **argv)
bb_error_msg_and_die("need at least destination address");
}
- if (rtnl_open(&rth, 0) < 0)
- exit(1);
+ xrtnl_open(&rth);
ll_init_map(&rth);
@@ -729,17 +785,11 @@ static int iproute_get(int argc, char **argv)
int idx;
if (idev) {
- if ((idx = ll_name_to_index(idev)) == 0) {
- bb_error_msg("Cannot find device \"%s\"", idev);
- return -1;
- }
+ idx = xll_name_to_index(idev);
addattr32(&req.n, sizeof(req), RTA_IIF, idx);
}
if (odev) {
- if ((idx = ll_name_to_index(odev)) == 0) {
- bb_error_msg("Cannot find device \"%s\"", odev);
- return -1;
- }
+ idx = xll_name_to_index(odev);
addattr32(&req.n, sizeof(req), RTA_OIF, idx);
}
}
@@ -749,7 +799,7 @@ static int iproute_get(int argc, char **argv)
}
if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) {
- exit(2);
+ return 2;
}
if (connected && !from_ok) {
@@ -757,18 +807,14 @@ static int iproute_get(int argc, char **argv)
int len = req.n.nlmsg_len;
struct rtattr * tb[RTA_MAX+1];
- if (print_route(NULL, &req.n, (void*)stdout) < 0) {
- bb_error_msg_and_die("An error :-)");
- }
+ print_route(NULL, &req.n, NULL);
if (req.n.nlmsg_type != RTM_NEWROUTE) {
- bb_error_msg("Not a route?");
- return -1;
+ bb_error_msg_and_die("not a route?");
}
len -= NLMSG_LENGTH(sizeof(*r));
if (len < 0) {
- bb_error_msg("Wrong len %d", len);
- return -1;
+ bb_error_msg_and_die("wrong len %d", len);
}
memset(tb, 0, sizeof(tb));
@@ -778,8 +824,7 @@ static int iproute_get(int argc, char **argv)
tb[RTA_PREFSRC]->rta_type = RTA_SRC;
r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]);
} else if (!tb[RTA_SRC]) {
- bb_error_msg("Failed to connect the route");
- return -1;
+ bb_error_msg_and_die("failed to connect the route");
}
if (!odev && tb[RTA_OIF]) {
tb[RTA_OIF]->rta_type = 0;
@@ -794,30 +839,33 @@ static int iproute_get(int argc, char **argv)
req.n.nlmsg_type = RTM_GETROUTE;
if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) {
- exit(2);
+ return 2;
}
}
-
- if (print_route(NULL, &req.n, (void*)stdout) < 0) {
- bb_error_msg_and_die("An error :-)");
- }
-
- exit(0);
+ print_route(NULL, &req.n, NULL);
+ return 0;
}
-int do_iproute(int argc, char **argv)
+/* Return value becomes exitcode. It's okay to not return at all */
+int do_iproute(char **argv)
{
- const char *ip_route_commands[] = { "add", "append", "change", "chg",
- "delete", "get", "list", "show", "prepend", "replace", "test", "flush", 0 };
- unsigned short command_num = 6;
- unsigned int flags = 0;
+ static const char ip_route_commands[] ALIGN1 =
+ /*0-3*/ "add\0""append\0""change\0""chg\0"
+ /*4-7*/ "delete\0""get\0""list\0""show\0"
+ /*8..*/ "prepend\0""replace\0""test\0""flush\0";
+ int command_num;
+ unsigned flags = 0;
int cmd = RTM_NEWROUTE;
- if (*argv) {
- command_num = compare_string_array(ip_route_commands, *argv);
- }
- switch(command_num) {
- case 0: /* add*/
+ if (!*argv)
+ return iproute_list_or_flush(argv, 0);
+
+ /* "Standard" 'ip r a' treats 'a' as 'add', not 'append' */
+ /* It probably means that it is using "first match" rule */
+ command_num = index_in_substrings(ip_route_commands, *argv);
+
+ switch (command_num) {
+ case 0: /* add */
flags = NLM_F_CREATE|NLM_F_EXCL;
break;
case 1: /* append */
@@ -831,22 +879,24 @@ int do_iproute(int argc, char **argv)
cmd = RTM_DELROUTE;
break;
case 5: /* get */
- return iproute_get(argc-1, argv+1);
+ return iproute_get(argv+1);
case 6: /* list */
case 7: /* show */
- return iproute_list_or_flush(argc-1, argv+1, 0);
+ return iproute_list_or_flush(argv+1, 0);
case 8: /* prepend */
flags = NLM_F_CREATE;
+ break;
case 9: /* replace */
flags = NLM_F_CREATE|NLM_F_REPLACE;
+ break;
case 10: /* test */
flags = NLM_F_EXCL;
+ break;
case 11: /* flush */
- return iproute_list_or_flush(argc-1, argv+1, 1);
+ return iproute_list_or_flush(argv+1, 1);
default:
- bb_error_msg_and_die("Unknown command %s", *argv);
+ bb_error_msg_and_die("unknown command %s", *argv);
}
- return iproute_modify(cmd, flags, argc-1, argv+1);
+ return iproute_modify(cmd, flags, argv+1);
}
-
diff --git a/release/src/router/busybox/networking/libiproute/iprule.c b/release/src/router/busybox/networking/libiproute/iprule.c
new file mode 100644
index 00000000..6c90c6d2
--- /dev/null
+++ b/release/src/router/busybox/networking/libiproute/iprule.c
@@ -0,0 +1,330 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * iprule.c "ip rule".
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ *
+ * Changes:
+ *
+ * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
+ * initially integrated into busybox by Bernhard Reutner-Fischer
+ */
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+
+#include "ip_common.h" /* #include "libbb.h" is inside */
+#include "rt_names.h"
+#include "utils.h"
+
+/*
+static void usage(void) __attribute__((noreturn));
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: ip rule [ list | add | del ] SELECTOR ACTION\n");
+ fprintf(stderr, "SELECTOR := [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK ]\n");
+ fprintf(stderr, " [ dev STRING ] [ pref NUMBER ]\n");
+ fprintf(stderr, "ACTION := [ table TABLE_ID ] [ nat ADDRESS ]\n");
+ fprintf(stderr, " [ prohibit | reject | unreachable ]\n");
+ fprintf(stderr, " [ realms [SRCREALM/]DSTREALM ]\n");
+ fprintf(stderr, "TABLE_ID := [ local | main | default | NUMBER ]\n");
+ exit(-1);
+}
+*/
+
+static int print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
+ struct nlmsghdr *n, void *arg UNUSED_PARAM)
+{
+ struct rtmsg *r = NLMSG_DATA(n);
+ int len = n->nlmsg_len;
+ int host_len = -1;
+ struct rtattr * tb[RTA_MAX+1];
+ char abuf[256];
+ SPRINT_BUF(b1);
+
+ if (n->nlmsg_type != RTM_NEWRULE)
+ return 0;
+
+ len -= NLMSG_LENGTH(sizeof(*r));
+ if (len < 0)
+ return -1;
+
+ memset(tb, 0, sizeof(tb));
+ parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
+
+ if (r->rtm_family == AF_INET)
+ host_len = 32;
+ else if (r->rtm_family == AF_INET6)
+ host_len = 128;
+/* else if (r->rtm_family == AF_DECnet)
+ host_len = 16;
+ else if (r->rtm_family == AF_IPX)
+ host_len = 80;
+*/
+ if (tb[RTA_PRIORITY])
+ printf("%u:\t", *(unsigned*)RTA_DATA(tb[RTA_PRIORITY]));
+ else
+ printf("0:\t");
+
+ printf("from ");
+ if (tb[RTA_SRC]) {
+ if (r->rtm_src_len != host_len) {
+ printf("%s/%u", rt_addr_n2a(r->rtm_family,
+ RTA_DATA(tb[RTA_SRC]),
+ abuf, sizeof(abuf)),
+ r->rtm_src_len
+ );
+ } else {
+ fputs(format_host(r->rtm_family,
+ RTA_PAYLOAD(tb[RTA_SRC]),
+ RTA_DATA(tb[RTA_SRC]),
+ abuf, sizeof(abuf)), stdout);
+ }
+ } else if (r->rtm_src_len) {
+ printf("0/%d", r->rtm_src_len);
+ } else {
+ printf("all");
+ }
+ bb_putchar(' ');
+
+ if (tb[RTA_DST]) {
+ if (r->rtm_dst_len != host_len) {
+ printf("to %s/%u ", rt_addr_n2a(r->rtm_family,
+ RTA_DATA(tb[RTA_DST]),
+ abuf, sizeof(abuf)),
+ r->rtm_dst_len
+ );
+ } else {
+ printf("to %s ", format_host(r->rtm_family,
+ RTA_PAYLOAD(tb[RTA_DST]),
+ RTA_DATA(tb[RTA_DST]),
+ abuf, sizeof(abuf)));
+ }
+ } else if (r->rtm_dst_len) {
+ printf("to 0/%d ", r->rtm_dst_len);
+ }
+
+ if (r->rtm_tos) {
+ printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1)));
+ }
+ if (tb[RTA_PROTOINFO]) {
+ printf("fwmark %#x ", *(uint32_t*)RTA_DATA(tb[RTA_PROTOINFO]));
+ }
+
+ if (tb[RTA_IIF]) {
+ printf("iif %s ", (char*)RTA_DATA(tb[RTA_IIF]));
+ }
+
+ if (r->rtm_table)
+ printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table, b1, sizeof(b1)));
+
+ if (tb[RTA_FLOW]) {
+ uint32_t to = *(uint32_t*)RTA_DATA(tb[RTA_FLOW]);
+ uint32_t from = to>>16;
+ to &= 0xFFFF;
+ if (from) {
+ printf("realms %s/",
+ rtnl_rtrealm_n2a(from, b1, sizeof(b1)));
+ }
+ printf("%s ",
+ rtnl_rtrealm_n2a(to, b1, sizeof(b1)));
+ }
+
+ if (r->rtm_type == RTN_NAT) {
+ if (tb[RTA_GATEWAY]) {
+ printf("map-to %s ",
+ format_host(r->rtm_family,
+ RTA_PAYLOAD(tb[RTA_GATEWAY]),
+ RTA_DATA(tb[RTA_GATEWAY]),
+ abuf, sizeof(abuf)));
+ } else
+ printf("masquerade");
+ } else if (r->rtm_type != RTN_UNICAST)
+ fputs(rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)), stdout);
+
+ bb_putchar('\n');
+ /*fflush(stdout);*/
+ return 0;
+}
+
+/* Return value becomes exitcode. It's okay to not return at all */
+static int iprule_list(char **argv)
+{
+ struct rtnl_handle rth;
+ int af = preferred_family;
+
+ if (af == AF_UNSPEC)
+ af = AF_INET;
+
+ if (*argv) {
+ //bb_error_msg("\"rule show\" needs no arguments");
+ bb_warn_ignoring_args(1);
+ return -1;
+ }
+
+ xrtnl_open(&rth);
+
+ xrtnl_wilddump_request(&rth, af, RTM_GETRULE);
+ xrtnl_dump_filter(&rth, print_rule, NULL);
+
+ return 0;
+}
+
+/* Return value becomes exitcode. It's okay to not return at all */
+static int iprule_modify(int cmd, char **argv)
+{
+ static const char keywords[] ALIGN1 =
+ "from\0""to\0""preference\0""order\0""priority\0"
+ "tos\0""fwmark\0""realms\0""table\0""lookup\0""dev\0"
+ "iif\0""nat\0""map-to\0""type\0""help\0";
+ enum {
+ ARG_from = 1, ARG_to, ARG_preference, ARG_order, ARG_priority,
+ ARG_tos, ARG_fwmark, ARG_realms, ARG_table, ARG_lookup, ARG_dev,
+ ARG_iif, ARG_nat, ARG_map_to, ARG_type, ARG_help
+ };
+ bool table_ok = 0;
+ struct rtnl_handle rth;
+ struct {
+ struct nlmsghdr n;
+ struct rtmsg r;
+ char buf[1024];
+ } req;
+ smalluint key;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_type = cmd;
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.r.rtm_family = preferred_family;
+ req.r.rtm_protocol = RTPROT_BOOT;
+ req.r.rtm_scope = RT_SCOPE_UNIVERSE;
+ req.r.rtm_table = 0;
+ req.r.rtm_type = RTN_UNSPEC;
+
+ if (cmd == RTM_NEWRULE) {
+ req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
+ req.r.rtm_type = RTN_UNICAST;
+ }
+
+ while (*argv) {
+ key = index_in_substrings(keywords, *argv) + 1;
+ if (key == 0) /* no match found in keywords array, bail out. */
+ bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
+ if (key == ARG_from) {
+ inet_prefix dst;
+ NEXT_ARG();
+ get_prefix(&dst, *argv, req.r.rtm_family);
+ req.r.rtm_src_len = dst.bitlen;
+ addattr_l(&req.n, sizeof(req), RTA_SRC, &dst.data, dst.bytelen);
+ } else if (key == ARG_to) {
+ inet_prefix dst;
+ NEXT_ARG();
+ get_prefix(&dst, *argv, req.r.rtm_family);
+ req.r.rtm_dst_len = dst.bitlen;
+ addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen);
+ } else if (key == ARG_preference ||
+ key == ARG_order ||
+ key == ARG_priority) {
+ uint32_t pref;
+ NEXT_ARG();
+ pref = get_u32(*argv, "preference");
+ addattr32(&req.n, sizeof(req), RTA_PRIORITY, pref);
+ } else if (key == ARG_tos) {
+ uint32_t tos;
+ NEXT_ARG();
+ if (rtnl_dsfield_a2n(&tos, *argv))
+ invarg(*argv, "TOS");
+ req.r.rtm_tos = tos;
+ } else if (key == ARG_fwmark) {
+ uint32_t fwmark;
+ NEXT_ARG();
+ fwmark = get_u32(*argv, "fwmark");
+ addattr32(&req.n, sizeof(req), RTA_PROTOINFO, fwmark);
+ } else if (key == ARG_realms) {
+ uint32_t realm;
+ NEXT_ARG();
+ if (get_rt_realms(&realm, *argv))
+ invarg(*argv, "realms");
+ addattr32(&req.n, sizeof(req), RTA_FLOW, realm);
+ } else if (key == ARG_table ||
+ key == ARG_lookup) {
+ uint32_t tid;
+ NEXT_ARG();
+ if (rtnl_rttable_a2n(&tid, *argv))
+ invarg(*argv, "table ID");
+ req.r.rtm_table = tid;
+ table_ok = 1;
+ } else if (key == ARG_dev ||
+ key == ARG_iif) {
+ NEXT_ARG();
+ addattr_l(&req.n, sizeof(req), RTA_IIF, *argv, strlen(*argv)+1);
+ } else if (key == ARG_nat ||
+ key == ARG_map_to) {
+ NEXT_ARG();
+ addattr32(&req.n, sizeof(req), RTA_GATEWAY, get_addr32(*argv));
+ req.r.rtm_type = RTN_NAT;
+ } else {
+ int type;
+
+ if (key == ARG_type) {
+ NEXT_ARG();
+ }
+ if (key == ARG_help)
+ bb_show_usage();
+ if (rtnl_rtntype_a2n(&type, *argv))
+ invarg(*argv, "type");
+ req.r.rtm_type = type;
+ }
+ argv++;
+ }
+
+ if (req.r.rtm_family == AF_UNSPEC)
+ req.r.rtm_family = AF_INET;
+
+ if (!table_ok && cmd == RTM_NEWRULE)
+ req.r.rtm_table = RT_TABLE_MAIN;
+
+ xrtnl_open(&rth);
+
+ if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
+ return 2;
+
+ return 0;
+}
+
+/* Return value becomes exitcode. It's okay to not return at all */
+int do_iprule(char **argv)
+{
+ static const char ip_rule_commands[] ALIGN1 =
+ "add\0""delete\0""list\0""show\0";
+ int cmd = 2; /* list */
+
+ if (!*argv)
+ return iprule_list(argv);
+
+ cmd = index_in_substrings(ip_rule_commands, *argv);
+ switch (cmd) {
+ case 0: /* add */
+ cmd = RTM_NEWRULE;
+ break;
+ case 1: /* delete */
+ cmd = RTM_DELRULE;
+ break;
+ case 2: /* list */
+ case 3: /* show */
+ return iprule_list(argv+1);
+ break;
+ default:
+ bb_error_msg_and_die("unknown command %s", *argv);
+ }
+ return iprule_modify(cmd, argv+1);
+}
diff --git a/release/src/router/busybox/networking/libiproute/iptunnel.c b/release/src/router/busybox/networking/libiproute/iptunnel.c
index eae5bb09..6a841aad 100644
--- a/release/src/router/busybox/networking/libiproute/iptunnel.c
+++ b/release/src/router/busybox/networking/libiproute/iptunnel.c
@@ -1,14 +1,11 @@
+/* vi: set sw=4 ts=4: */
/*
* iptunnel.c "ip tunnel"
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
- *
* Changes:
*
* Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
@@ -16,40 +13,71 @@
* Phil Karn <karn@ka9q.ampr.org> 990408: "pmtudisc" flag
*/
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <arpa/inet.h>
#include <netinet/ip.h>
-#include <netinet/in.h>
-
#include <net/if.h>
#include <net/if_arp.h>
-
#include <asm/types.h>
+
+#ifndef __constant_htons
#define __constant_htons htons
-#include <linux/if_tunnel.h>
+#endif
+// FYI: #define SIOCDEVPRIVATE 0x89F0
+
+/* From linux/if_tunnel.h. #including it proved troublesome
+ * (redefiniton errors due to name collisions in linux/ and net[inet]/) */
+#define SIOCGETTUNNEL (SIOCDEVPRIVATE + 0)
+#define SIOCADDTUNNEL (SIOCDEVPRIVATE + 1)
+#define SIOCDELTUNNEL (SIOCDEVPRIVATE + 2)
+#define SIOCCHGTUNNEL (SIOCDEVPRIVATE + 3)
+//#define SIOCGETPRL (SIOCDEVPRIVATE + 4)
+//#define SIOCADDPRL (SIOCDEVPRIVATE + 5)
+//#define SIOCDELPRL (SIOCDEVPRIVATE + 6)
+//#define SIOCCHGPRL (SIOCDEVPRIVATE + 7)
+#define GRE_CSUM __constant_htons(0x8000)
+//#define GRE_ROUTING __constant_htons(0x4000)
+#define GRE_KEY __constant_htons(0x2000)
+#define GRE_SEQ __constant_htons(0x1000)
+//#define GRE_STRICT __constant_htons(0x0800)
+//#define GRE_REC __constant_htons(0x0700)
+//#define GRE_FLAGS __constant_htons(0x00F8)
+//#define GRE_VERSION __constant_htons(0x0007)
+struct ip_tunnel_parm {
+ char name[IFNAMSIZ];
+ int link;
+ uint16_t i_flags;
+ uint16_t o_flags;
+ uint32_t i_key;
+ uint32_t o_key;
+ struct iphdr iph;
+};
+/* SIT-mode i_flags */
+//#define SIT_ISATAP 0x0001
+//struct ip_tunnel_prl {
+// uint32_t addr;
+// uint16_t flags;
+// uint16_t __reserved;
+// uint32_t datalen;
+// uint32_t __reserved2;
+// /* data follows */
+//};
+///* PRL flags */
+//#define PRL_DEFAULT 0x0001
+
+#include "ip_common.h" /* #include "libbb.h" is inside */
#include "rt_names.h"
#include "utils.h"
-#include "libbb.h"
+/* Dies on error */
static int do_ioctl_get_ifindex(char *dev)
{
struct ifreq ifr;
int fd;
- strcpy(ifr.ifr_name, dev);
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (ioctl(fd, SIOCGIFINDEX, &ifr)) {
- bb_perror_msg("ioctl");
- return 0;
- }
+ strncpy_IFNAMSIZ(ifr.ifr_name, dev);
+ fd = xsocket(AF_INET, SOCK_DGRAM, 0);
+ xioctl(fd, SIOCGIFINDEX, &ifr);
close(fd);
return ifr.ifr_ifindex;
}
@@ -58,137 +86,145 @@ static int do_ioctl_get_iftype(char *dev)
{
struct ifreq ifr;
int fd;
+ int err;
- strcpy(ifr.ifr_name, dev);
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (ioctl(fd, SIOCGIFHWADDR, &ifr)) {
- bb_perror_msg("ioctl");
- return -1;
- }
+ strncpy_IFNAMSIZ(ifr.ifr_name, dev);
+ fd = xsocket(AF_INET, SOCK_DGRAM, 0);
+ err = ioctl_or_warn(fd, SIOCGIFHWADDR, &ifr);
close(fd);
- return ifr.ifr_addr.sa_family;
+ return err ? -1 : ifr.ifr_addr.sa_family;
}
-
static char *do_ioctl_get_ifname(int idx)
{
- static struct ifreq ifr;
+ struct ifreq ifr;
int fd;
+ int err;
ifr.ifr_ifindex = idx;
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (ioctl(fd, SIOCGIFNAME, &ifr)) {
- bb_perror_msg("ioctl");
- return NULL;
- }
+ fd = xsocket(AF_INET, SOCK_DGRAM, 0);
+ err = ioctl_or_warn(fd, SIOCGIFNAME, &ifr);
close(fd);
- return ifr.ifr_name;
+ return err ? NULL : xstrndup(ifr.ifr_name, sizeof(ifr.ifr_name));
}
-
-
-static int do_get_ioctl(char *basedev, struct ip_tunnel_parm *p)
+static int do_get_ioctl(const char *basedev, struct ip_tunnel_parm *p)
{
struct ifreq ifr;
int fd;
int err;
- strcpy(ifr.ifr_name, basedev);
+ strncpy_IFNAMSIZ(ifr.ifr_name, basedev);
ifr.ifr_ifru.ifru_data = (void*)p;
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- err = ioctl(fd, SIOCGETTUNNEL, &ifr);
- if (err) {
- bb_perror_msg("ioctl");
- }
+ fd = xsocket(AF_INET, SOCK_DGRAM, 0);
+ err = ioctl_or_warn(fd, SIOCGETTUNNEL, &ifr);
close(fd);
return err;
}
-static int do_add_ioctl(int cmd, char *basedev, struct ip_tunnel_parm *p)
+/* Dies on error, otherwise returns 0 */
+static int do_add_ioctl(int cmd, const char *basedev, struct ip_tunnel_parm *p)
{
struct ifreq ifr;
int fd;
- int err;
if (cmd == SIOCCHGTUNNEL && p->name[0]) {
- strcpy(ifr.ifr_name, p->name);
+ strncpy_IFNAMSIZ(ifr.ifr_name, p->name);
} else {
- strcpy(ifr.ifr_name, basedev);
+ strncpy_IFNAMSIZ(ifr.ifr_name, basedev);
}
ifr.ifr_ifru.ifru_data = (void*)p;
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- err = ioctl(fd, cmd, &ifr);
- if (err) {
- bb_perror_msg("ioctl");
- }
+ fd = xsocket(AF_INET, SOCK_DGRAM, 0);
+#if ENABLE_IOCTL_HEX2STR_ERROR
+ /* #define magic will turn ioctl# into string */
+ if (cmd == SIOCCHGTUNNEL)
+ xioctl(fd, SIOCCHGTUNNEL, &ifr);
+ else
+ xioctl(fd, SIOCADDTUNNEL, &ifr);
+#else
+ xioctl(fd, cmd, &ifr);
+#endif
close(fd);
- return err;
+ return 0;
}
-static int do_del_ioctl(char *basedev, struct ip_tunnel_parm *p)
+/* Dies on error, otherwise returns 0 */
+static int do_del_ioctl(const char *basedev, struct ip_tunnel_parm *p)
{
struct ifreq ifr;
int fd;
- int err;
if (p->name[0]) {
- strcpy(ifr.ifr_name, p->name);
+ strncpy_IFNAMSIZ(ifr.ifr_name, p->name);
} else {
- strcpy(ifr.ifr_name, basedev);
+ strncpy_IFNAMSIZ(ifr.ifr_name, basedev);
}
ifr.ifr_ifru.ifru_data = (void*)p;
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- err = ioctl(fd, SIOCDELTUNNEL, &ifr);
- if (err) {
- bb_perror_msg("ioctl");
- }
+ fd = xsocket(AF_INET, SOCK_DGRAM, 0);
+ xioctl(fd, SIOCDELTUNNEL, &ifr);
close(fd);
- return err;
+ return 0;
}
-static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
+/* Dies on error */
+static void parse_args(char **argv, int cmd, struct ip_tunnel_parm *p)
{
+ static const char keywords[] ALIGN1 =
+ "mode\0""ipip\0""ip/ip\0""gre\0""gre/ip\0""sit\0""ipv6/ip\0"
+ "key\0""ikey\0""okey\0""seq\0""iseq\0""oseq\0"
+ "csum\0""icsum\0""ocsum\0""nopmtudisc\0""pmtudisc\0"
+ "remote\0""any\0""local\0""dev\0"
+ "ttl\0""inherit\0""tos\0""dsfield\0"
+ "name\0";
+ enum {
+ ARG_mode, ARG_ipip, ARG_ip_ip, ARG_gre, ARG_gre_ip, ARG_sit, ARG_ip6_ip,
+ ARG_key, ARG_ikey, ARG_okey, ARG_seq, ARG_iseq, ARG_oseq,
+ ARG_csum, ARG_icsum, ARG_ocsum, ARG_nopmtudisc, ARG_pmtudisc,
+ ARG_remote, ARG_any, ARG_local, ARG_dev,
+ ARG_ttl, ARG_inherit, ARG_tos, ARG_dsfield,
+ ARG_name
+ };
int count = 0;
char medium[IFNAMSIZ];
+ int key;
+
memset(p, 0, sizeof(*p));
- memset(&medium, 0, sizeof(medium));
+ medium[0] = '\0';
p->iph.version = 4;
p->iph.ihl = 5;
#ifndef IP_DF
-#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
+#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
#endif
p->iph.frag_off = htons(IP_DF);
- while (argc > 0) {
- if (strcmp(*argv, "mode") == 0) {
+ while (*argv) {
+ key = index_in_strings(keywords, *argv);
+ if (key == ARG_mode) {
NEXT_ARG();
- if (strcmp(*argv, "ipip") == 0 ||
- strcmp(*argv, "ip/ip") == 0) {
+ key = index_in_strings(keywords, *argv);
+ if (key == ARG_ipip ||
+ key == ARG_ip_ip) {
if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) {
- bb_error_msg("You managed to ask for more than one tunnel mode.");
- exit(-1);
+ bb_error_msg_and_die("%s tunnel mode", "you managed to ask for more than one");
}
p->iph.protocol = IPPROTO_IPIP;
- } else if (strcmp(*argv, "gre") == 0 ||
- strcmp(*argv, "gre/ip") == 0) {
+ } else if (key == ARG_gre ||
+ key == ARG_gre_ip) {
if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) {
- bb_error_msg("You managed to ask for more than one tunnel mode.");
- exit(-1);
+ bb_error_msg_and_die("%s tunnel mode", "you managed to ask for more than one");
}
p->iph.protocol = IPPROTO_GRE;
- } else if (strcmp(*argv, "sit") == 0 ||
- strcmp(*argv, "ipv6/ip") == 0) {
+ } else if (key == ARG_sit ||
+ key == ARG_ip6_ip) {
if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) {
- bb_error_msg("You managed to ask for more than one tunnel mode.");
- exit(-1);
+ bb_error_msg_and_die("%s tunnel mode", "you managed to ask for more than one");
}
p->iph.protocol = IPPROTO_IPV6;
} else {
- bb_error_msg("Cannot guess tunnel mode.");
- exit(-1);
+ bb_error_msg_and_die("%s tunnel mode", "cannot guess");
}
- } else if (strcmp(*argv, "key") == 0) {
+ } else if (key == ARG_key) {
unsigned uval;
NEXT_ARG();
p->i_flags |= GRE_KEY;
@@ -196,107 +232,100 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
if (strchr(*argv, '.'))
p->i_key = p->o_key = get_addr32(*argv);
else {
- if (get_unsigned(&uval, *argv, 0)<0) {
- bb_error_msg("invalid value of \"key\"");
- exit(-1);
- }
+ uval = get_unsigned(*argv, "key");
p->i_key = p->o_key = htonl(uval);
}
- } else if (strcmp(*argv, "ikey") == 0) {
+ } else if (key == ARG_ikey) {
unsigned uval;
NEXT_ARG();
p->i_flags |= GRE_KEY;
if (strchr(*argv, '.'))
p->o_key = get_addr32(*argv);
else {
- if (get_unsigned(&uval, *argv, 0)<0) {
- bb_error_msg("invalid value of \"ikey\"");
- exit(-1);
- }
+ uval = get_unsigned(*argv, "ikey");
p->i_key = htonl(uval);
}
- } else if (strcmp(*argv, "okey") == 0) {
+ } else if (key == ARG_okey) {
unsigned uval;
NEXT_ARG();
p->o_flags |= GRE_KEY;
if (strchr(*argv, '.'))
p->o_key = get_addr32(*argv);
else {
- if (get_unsigned(&uval, *argv, 0)<0) {
- bb_error_msg("invalid value of \"okey\"");
- exit(-1);
- }
+ uval = get_unsigned(*argv, "okey");
p->o_key = htonl(uval);
}
- } else if (strcmp(*argv, "seq") == 0) {
+ } else if (key == ARG_seq) {
p->i_flags |= GRE_SEQ;
p->o_flags |= GRE_SEQ;
- } else if (strcmp(*argv, "iseq") == 0) {
+ } else if (key == ARG_iseq) {
p->i_flags |= GRE_SEQ;
- } else if (strcmp(*argv, "oseq") == 0) {
+ } else if (key == ARG_oseq) {
p->o_flags |= GRE_SEQ;
- } else if (strcmp(*argv, "csum") == 0) {
+ } else if (key == ARG_csum) {
p->i_flags |= GRE_CSUM;
p->o_flags |= GRE_CSUM;
- } else if (strcmp(*argv, "icsum") == 0) {
+ } else if (key == ARG_icsum) {
p->i_flags |= GRE_CSUM;
- } else if (strcmp(*argv, "ocsum") == 0) {
+ } else if (key == ARG_ocsum) {
p->o_flags |= GRE_CSUM;
- } else if (strcmp(*argv, "nopmtudisc") == 0) {
+ } else if (key == ARG_nopmtudisc) {
p->iph.frag_off = 0;
- } else if (strcmp(*argv, "pmtudisc") == 0) {
+ } else if (key == ARG_pmtudisc) {
p->iph.frag_off = htons(IP_DF);
- } else if (strcmp(*argv, "remote") == 0) {
+ } else if (key == ARG_remote) {
NEXT_ARG();
- if (strcmp(*argv, "any"))
+ key = index_in_strings(keywords, *argv);
+ if (key != ARG_any)
p->iph.daddr = get_addr32(*argv);
- } else if (strcmp(*argv, "local") == 0) {
+ } else if (key == ARG_local) {
NEXT_ARG();
- if (strcmp(*argv, "any"))
+ key = index_in_strings(keywords, *argv);
+ if (key != ARG_any)
p->iph.saddr = get_addr32(*argv);
- } else if (strcmp(*argv, "dev") == 0) {
+ } else if (key == ARG_dev) {
NEXT_ARG();
- strncpy(medium, *argv, IFNAMSIZ-1);
- } else if (strcmp(*argv, "ttl") == 0) {
+ strncpy_IFNAMSIZ(medium, *argv);
+ } else if (key == ARG_ttl) {
unsigned uval;
NEXT_ARG();
- if (strcmp(*argv, "inherit") != 0) {
- if (get_unsigned(&uval, *argv, 0))
- invarg("invalid TTL\n", *argv);
+ key = index_in_strings(keywords, *argv);
+ if (key != ARG_inherit) {
+ uval = get_unsigned(*argv, "TTL");
if (uval > 255)
- invarg("TTL must be <=255\n", *argv);
+ invarg(*argv, "TTL must be <=255");
p->iph.ttl = uval;
}
- } else if (strcmp(*argv, "tos") == 0 ||
- matches(*argv, "dsfield") == 0) {
- __u32 uval;
+ } else if (key == ARG_tos ||
+ key == ARG_dsfield) {
+ uint32_t uval;
NEXT_ARG();
- if (strcmp(*argv, "inherit") != 0) {
+ key = index_in_strings(keywords, *argv);
+ if (key != ARG_inherit) {
if (rtnl_dsfield_a2n(&uval, *argv))
- invarg("bad TOS value", *argv);
+ invarg(*argv, "TOS");
p->iph.tos = uval;
} else
p->iph.tos = 1;
} else {
- if (strcmp(*argv, "name") == 0) {
+ if (key == ARG_name) {
NEXT_ARG();
}
if (p->name[0])
duparg2("name", *argv);
- strncpy(p->name, *argv, IFNAMSIZ);
+ strncpy_IFNAMSIZ(p->name, *argv);
if (cmd == SIOCCHGTUNNEL && count == 0) {
struct ip_tunnel_parm old_p;
memset(&old_p, 0, sizeof(old_p));
if (do_get_ioctl(*argv, &old_p))
- return -1;
+ exit(EXIT_FAILURE);
*p = old_p;
}
}
count++;
- argc--; argv++;
+ argv++;
}
-
if (p->iph.protocol == 0) {
if (memcmp(p->name, "gre", 3) == 0)
p->iph.protocol = IPPROTO_GRE;
@@ -308,15 +337,12 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) {
if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) {
- bb_error_msg("Keys are not allowed with ipip and sit.");
- return -1;
+ bb_error_msg_and_die("keys are not allowed with ipip and sit");
}
}
if (medium[0]) {
p->link = do_ioctl_get_ifindex(medium);
- if (p->link == 0)
- return -1;
}
if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) {
@@ -328,23 +354,19 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
p->o_flags |= GRE_KEY;
}
if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) {
- bb_error_msg("Broadcast tunnel requires a source address.");
- return -1;
+ bb_error_msg_and_die("broadcast tunnel requires a source address");
}
- return 0;
}
-
-static int do_add(int cmd, int argc, char **argv)
+/* Return value becomes exitcode. It's okay to not return at all */
+static int do_add(int cmd, char **argv)
{
struct ip_tunnel_parm p;
- if (parse_args(argc, argv, cmd, &p) < 0)
- return -1;
+ parse_args(argv, cmd, &p);
if (p.iph.ttl && p.iph.frag_off == 0) {
- bb_error_msg("ttl != 0 and noptmudisc are incompatible");
- return -1;
+ bb_error_msg_and_die("ttl != 0 and noptmudisc are incompatible");
}
switch (p.iph.protocol) {
@@ -354,19 +376,17 @@ static int do_add(int cmd, int argc, char **argv)
return do_add_ioctl(cmd, "gre0", &p);
case IPPROTO_IPV6:
return do_add_ioctl(cmd, "sit0", &p);
- default:
- bb_error_msg("cannot determine tunnel mode (ipip, gre or sit)");
- return -1;
+ default:
+ bb_error_msg_and_die("cannot determine tunnel mode (ipip, gre or sit)");
}
- return -1;
}
-int do_del(int argc, char **argv)
+/* Return value becomes exitcode. It's okay to not return at all */
+static int do_del(char **argv)
{
struct ip_tunnel_parm p;
- if (parse_args(argc, argv, SIOCDELTUNNEL, &p) < 0)
- return -1;
+ parse_args(argv, SIOCDELTUNNEL, &p);
switch (p.iph.protocol) {
case IPPROTO_IPIP:
@@ -375,13 +395,12 @@ int do_del(int argc, char **argv)
return do_del_ioctl("gre0", &p);
case IPPROTO_IPV6:
return do_del_ioctl("sit0", &p);
- default:
+ default:
return do_del_ioctl(p.name, &p);
}
- return -1;
}
-void print_tunnel(struct ip_tunnel_parm *p)
+static void print_tunnel(struct ip_tunnel_parm *p)
{
char s1[256];
char s2[256];
@@ -401,8 +420,10 @@ void print_tunnel(struct ip_tunnel_parm *p)
p->iph.daddr ? s1 : "any", p->iph.saddr ? s2 : "any");
if (p->link) {
char *n = do_ioctl_get_ifname(p->link);
- if (n)
+ if (n) {
printf(" dev %s ", n);
+ free(n);
+ }
}
if (p->iph.ttl)
printf(" ttl %d ", p->iph.ttl);
@@ -411,63 +432,64 @@ void print_tunnel(struct ip_tunnel_parm *p)
if (p->iph.tos) {
SPRINT_BUF(b1);
printf(" tos");
- if (p->iph.tos&1)
+ if (p->iph.tos & 1)
printf(" inherit");
- if (p->iph.tos&~1)
- printf("%c%s ", p->iph.tos&1 ? '/' : ' ',
- rtnl_dsfield_n2a(p->iph.tos&~1, b1, sizeof(b1)));
+ if (p->iph.tos & ~1)
+ printf("%c%s ", p->iph.tos & 1 ? '/' : ' ',
+ rtnl_dsfield_n2a(p->iph.tos & ~1, b1, sizeof(b1)));
}
- if (!(p->iph.frag_off&htons(IP_DF)))
+ if (!(p->iph.frag_off & htons(IP_DF)))
printf(" nopmtudisc");
- if ((p->i_flags&GRE_KEY) && (p->o_flags&GRE_KEY) && p->o_key == p->i_key)
+ if ((p->i_flags & GRE_KEY) && (p->o_flags & GRE_KEY) && p->o_key == p->i_key)
printf(" key %s", s3);
- else if ((p->i_flags|p->o_flags)&GRE_KEY) {
- if (p->i_flags&GRE_KEY)
+ else if ((p->i_flags | p->o_flags) & GRE_KEY) {
+ if (p->i_flags & GRE_KEY)
printf(" ikey %s ", s3);
- if (p->o_flags&GRE_KEY)
+ if (p->o_flags & GRE_KEY)
printf(" okey %s ", s4);
}
- if (p->i_flags&GRE_SEQ)
- printf("%s Drop packets out of sequence.\n", _SL_);
- if (p->i_flags&GRE_CSUM)
- printf("%s Checksum in received packet is required.", _SL_);
- if (p->o_flags&GRE_SEQ)
- printf("%s Sequence packets on output.", _SL_);
- if (p->o_flags&GRE_CSUM)
- printf("%s Checksum output packets.", _SL_);
+ if (p->i_flags & GRE_SEQ)
+ printf("%c Drop packets out of sequence.\n", _SL_);
+ if (p->i_flags & GRE_CSUM)
+ printf("%c Checksum in received packet is required.", _SL_);
+ if (p->o_flags & GRE_SEQ)
+ printf("%c Sequence packets on output.", _SL_);
+ if (p->o_flags & GRE_CSUM)
+ printf("%c Checksum output packets.", _SL_);
}
-static int do_tunnels_list(struct ip_tunnel_parm *p)
+static void do_tunnels_list(struct ip_tunnel_parm *p)
{
char name[IFNAMSIZ];
- unsigned long rx_bytes, rx_packets, rx_errs, rx_drops,
- rx_fifo, rx_frame,
- tx_bytes, tx_packets, tx_errs, tx_drops,
- tx_fifo, tx_colls, tx_carrier, rx_multi;
+ unsigned long rx_bytes, rx_packets, rx_errs, rx_drops,
+ rx_fifo, rx_frame,
+ tx_bytes, tx_packets, tx_errs, tx_drops,
+ tx_fifo, tx_colls, tx_carrier, rx_multi;
int type;
struct ip_tunnel_parm p1;
-
char buf[512];
- FILE *fp = fopen("/proc/net/dev", "r");
+ FILE *fp = fopen_or_warn("/proc/net/dev", "r");
+
if (fp == NULL) {
- perror("fopen");
- return -1;
+ return;
}
-
+ /* skip headers */
fgets(buf, sizeof(buf), fp);
fgets(buf, sizeof(buf), fp);
while (fgets(buf, sizeof(buf), fp) != NULL) {
char *ptr;
- buf[sizeof(buf) - 1] = 0;
- if ((ptr = strchr(buf, ':')) == NULL ||
+
+ /*buf[sizeof(buf) - 1] = 0; - fgets is safe anyway */
+ ptr = strchr(buf, ':');
+ if (ptr == NULL ||
(*ptr++ = 0, sscanf(buf, "%s", name) != 1)) {
- bb_error_msg("Wrong format of /proc/net/dev. Sorry.");
- return -1;
+ bb_error_msg("wrong format of /proc/net/dev");
+ return;
}
- if (sscanf(ptr, "%ld%ld%ld%ld%ld%ld%ld%*d%ld%ld%ld%ld%ld%ld%ld",
+ if (sscanf(ptr, "%lu%lu%lu%lu%lu%lu%lu%*d%lu%lu%lu%lu%lu%lu%lu",
&rx_bytes, &rx_packets, &rx_errs, &rx_drops,
&rx_fifo, &rx_frame, &rx_multi,
&tx_bytes, &tx_packets, &tx_errs, &tx_drops,
@@ -477,7 +499,7 @@ static int do_tunnels_list(struct ip_tunnel_parm *p)
continue;
type = do_ioctl_get_iftype(name);
if (type == -1) {
- bb_error_msg("Failed to get type of [%s]", name);
+ bb_error_msg("cannot get type of [%s]", name);
continue;
}
if (type != ARPHRD_TUNNEL && type != ARPHRD_IPGRE && type != ARPHRD_SIT)
@@ -492,21 +514,20 @@ static int do_tunnels_list(struct ip_tunnel_parm *p)
(p->i_key && p1.i_key != p->i_key))
continue;
print_tunnel(&p1);
- printf("\n");
+ bb_putchar('\n');
}
- return 0;
}
-static int do_show(int argc, char **argv)
+/* Return value becomes exitcode. It's okay to not return at all */
+static int do_show(char **argv)
{
int err;
struct ip_tunnel_parm p;
- if (parse_args(argc, argv, SIOCGETTUNNEL, &p) < 0)
- return -1;
+ parse_args(argv, SIOCGETTUNNEL, &p);
switch (p.iph.protocol) {
- case IPPROTO_IPIP:
+ case IPPROTO_IPIP:
err = do_get_ioctl(p.name[0] ? p.name : "tunl0", &p);
break;
case IPPROTO_GRE:
@@ -523,26 +544,29 @@ static int do_show(int argc, char **argv)
return -1;
print_tunnel(&p);
- printf("\n");
+ bb_putchar('\n');
return 0;
}
-int do_iptunnel(int argc, char **argv)
+/* Return value becomes exitcode. It's okay to not return at all */
+int do_iptunnel(char **argv)
{
- if (argc > 0) {
- if (matches(*argv, "add") == 0)
- return do_add(SIOCADDTUNNEL, argc-1, argv+1);
- if (matches(*argv, "change") == 0)
- return do_add(SIOCCHGTUNNEL, argc-1, argv+1);
- if (matches(*argv, "del") == 0)
- return do_del(argc-1, argv+1);
- if (matches(*argv, "show") == 0 ||
- matches(*argv, "lst") == 0 ||
- matches(*argv, "list") == 0)
- return do_show(argc-1, argv+1);
- } else
- return do_show(0, NULL);
-
- bb_error_msg("Command \"%s\" is unknown, try \"ip tunnel help\".", *argv);
- exit(-1);
+ static const char keywords[] ALIGN1 =
+ "add\0""change\0""delete\0""show\0""list\0""lst\0";
+ enum { ARG_add = 0, ARG_change, ARG_del, ARG_show, ARG_list, ARG_lst };
+ int key;
+
+ if (*argv) {
+ key = index_in_substrings(keywords, *argv);
+ if (key < 0)
+ bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
+ argv++;
+ if (key == ARG_add)
+ return do_add(SIOCADDTUNNEL, argv);
+ if (key == ARG_change)
+ return do_add(SIOCCHGTUNNEL, argv);
+ if (key == ARG_del)
+ return do_del(argv);
+ }
+ return do_show(argv);
}
diff --git a/release/src/router/busybox/networking/libiproute/libnetlink.c b/release/src/router/busybox/networking/libiproute/libnetlink.c
index 9390e56f..6d51d8de 100644
--- a/release/src/router/busybox/networking/libiproute/libnetlink.c
+++ b/release/src/router/busybox/networking/libiproute/libnetlink.c
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
/*
* libnetlink.c RTnetlink service routines.
*
@@ -11,61 +12,41 @@
*/
#include <sys/socket.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
#include <sys/uio.h>
-#include "libnetlink.h"
#include "libbb.h"
+#include "libnetlink.h"
-void rtnl_close(struct rtnl_handle *rth)
+void FAST_FUNC rtnl_close(struct rtnl_handle *rth)
{
close(rth->fd);
}
-int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
+int FAST_FUNC xrtnl_open(struct rtnl_handle *rth/*, unsigned subscriptions*/)
{
- int addr_len;
+ socklen_t addr_len;
memset(rth, 0, sizeof(rth));
- rth->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (rth->fd < 0) {
- bb_perror_msg("Cannot open netlink socket");
- return -1;
- }
+ rth->fd = xsocket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
memset(&rth->local, 0, sizeof(rth->local));
rth->local.nl_family = AF_NETLINK;
- rth->local.nl_groups = subscriptions;
+ /*rth->local.nl_groups = subscriptions;*/
- if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
- bb_perror_msg("Cannot bind netlink socket");
- return -1;
- }
+ xbind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local));
addr_len = sizeof(rth->local);
- if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
- bb_perror_msg("Cannot getsockname");
- return -1;
- }
- if (addr_len != sizeof(rth->local)) {
- bb_error_msg("Wrong address length %d", addr_len);
- return -1;
- }
- if (rth->local.nl_family != AF_NETLINK) {
- bb_error_msg("Wrong address family %d", rth->local.nl_family);
- return -1;
- }
+ if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0)
+ bb_perror_msg_and_die("getsockname");
+ if (addr_len != sizeof(rth->local))
+ bb_error_msg_and_die("wrong address length %d", addr_len);
+ if (rth->local.nl_family != AF_NETLINK)
+ bb_error_msg_and_die("wrong address family %d", rth->local.nl_family);
rth->seq = time(NULL);
return 0;
}
-int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
+int FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
{
struct {
struct nlmsghdr nlh;
@@ -83,20 +64,21 @@ int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
req.g.rtgen_family = family;
- return sendto(rth->fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
+ return xsendto(rth->fd, (void*)&req, sizeof(req),
+ (struct sockaddr*)&nladdr, sizeof(nladdr));
}
-int rtnl_send(struct rtnl_handle *rth, char *buf, int len)
+int FAST_FUNC rtnl_send(struct rtnl_handle *rth, char *buf, int len)
{
struct sockaddr_nl nladdr;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
- return sendto(rth->fd, buf, len, 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
+ return xsendto(rth->fd, buf, len, (struct sockaddr*)&nladdr, sizeof(nladdr));
}
-int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
+int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
{
struct nlmsghdr nlh;
struct sockaddr_nl nladdr;
@@ -120,15 +102,16 @@ int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
return sendmsg(rth->fd, &msg, 0);
}
-int rtnl_dump_filter(struct rtnl_handle *rth,
- int (*filter)(struct sockaddr_nl *, struct nlmsghdr *n, void *),
- void *arg1,
- int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
- void *arg2)
+static int rtnl_dump_filter(struct rtnl_handle *rth,
+ int (*filter)(const struct sockaddr_nl *, struct nlmsghdr *n, void *),
+ void *arg1/*,
+ int (*junk)(struct sockaddr_nl *, struct nlmsghdr *n, void *),
+ void *arg2*/)
{
- char buf[8192];
+ int retval = -1;
+ char *buf = xmalloc(8*1024); /* avoid big stack buffer */
struct sockaddr_nl nladdr;
- struct iovec iov = { buf, sizeof(buf) };
+ struct iovec iov = { buf, 8*1024 };
while (1) {
int status;
@@ -151,7 +134,7 @@ int rtnl_dump_filter(struct rtnl_handle *rth,
}
if (status == 0) {
bb_error_msg("EOF on netlink");
- return -1;
+ goto ret;
}
if (msg.msg_namelen != sizeof(nladdr)) {
bb_error_msg_and_die("sender address length == %d", msg.msg_namelen);
@@ -161,19 +144,21 @@ int rtnl_dump_filter(struct rtnl_handle *rth,
while (NLMSG_OK(h, status)) {
int err;
- if (h->nlmsg_pid != rth->local.nl_pid ||
+ if (nladdr.nl_pid != 0 ||
+ h->nlmsg_pid != rth->local.nl_pid ||
h->nlmsg_seq != rth->dump) {
- if (junk) {
- err = junk(&nladdr, h, arg2);
- if (err < 0) {
- return err;
- }
- }
+// if (junk) {
+// err = junk(&nladdr, h, arg2);
+// if (err < 0) {
+// retval = err;
+// goto ret;
+// }
+// }
goto skip_it;
}
if (h->nlmsg_type == NLMSG_DONE) {
- return 0;
+ goto ret_0;
}
if (h->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *l_err = (struct nlmsgerr*)NLMSG_DATA(h);
@@ -183,37 +168,60 @@ int rtnl_dump_filter(struct rtnl_handle *rth,
errno = -l_err->error;
bb_perror_msg("RTNETLINK answers");
}
- return -1;
+ goto ret;
}
err = filter(&nladdr, h, arg1);
if (err < 0) {
- return err;
+ retval = err;
+ goto ret;
}
-skip_it:
+ skip_it:
h = NLMSG_NEXT(h, status);
}
if (msg.msg_flags & MSG_TRUNC) {
- bb_error_msg("Message truncated");
+ bb_error_msg("message truncated");
continue;
}
if (status) {
- bb_error_msg_and_die("!!!Remnant of size %d", status);
+ bb_error_msg_and_die("remnant of size %d!", status);
}
- }
+ } /* while (1) */
+ ret_0:
+ retval++; /* = 0 */
+ ret:
+ free(buf);
+ return retval;
}
-int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
- unsigned groups, struct nlmsghdr *answer,
- int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
+int FAST_FUNC xrtnl_dump_filter(struct rtnl_handle *rth,
+ int (*filter)(const struct sockaddr_nl *, struct nlmsghdr *, void *),
+ void *arg1)
+{
+ int ret = rtnl_dump_filter(rth, filter, arg1/*, NULL, NULL*/);
+ if (ret < 0)
+ bb_error_msg_and_die("dump terminated");
+ return ret;
+}
+
+int FAST_FUNC rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
+ pid_t peer, unsigned groups,
+ struct nlmsghdr *answer,
+ int (*junk)(struct sockaddr_nl *, struct nlmsghdr *, void *),
void *jarg)
{
+/* bbox doesn't use parameters no. 3, 4, 6, 7, they are stubbed out */
+#define peer 0
+#define groups 0
+#define junk NULL
+#define jarg NULL
+ int retval = -1;
int status;
unsigned seq;
struct nlmsghdr *h;
struct sockaddr_nl nladdr;
struct iovec iov = { (void*)n, n->nlmsg_len };
- char buf[8192];
+ char *buf = xmalloc(8*1024); /* avoid big stack buffer */
struct msghdr msg = {
(void*)&nladdr, sizeof(nladdr),
&iov, 1,
@@ -223,8 +231,8 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
- nladdr.nl_pid = peer;
- nladdr.nl_groups = groups;
+// nladdr.nl_pid = peer;
+// nladdr.nl_groups = groups;
n->nlmsg_seq = seq = ++rtnl->seq;
if (answer == NULL) {
@@ -233,14 +241,14 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
status = sendmsg(rtnl->fd, &msg, 0);
if (status < 0) {
- bb_perror_msg("Cannot talk to rtnetlink");
- return -1;
+ bb_perror_msg("cannot talk to rtnetlink");
+ goto ret;
}
iov.iov_base = buf;
while (1) {
- iov.iov_len = sizeof(buf);
+ iov.iov_len = 8*1024;
status = recvmsg(rtnl->fd, &msg, 0);
if (status < 0) {
@@ -252,219 +260,98 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
}
if (status == 0) {
bb_error_msg("EOF on netlink");
- return -1;
+ goto ret;
}
if (msg.msg_namelen != sizeof(nladdr)) {
bb_error_msg_and_die("sender address length == %d", msg.msg_namelen);
}
- for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
- int l_err;
+ for (h = (struct nlmsghdr*)buf; status >= (int)sizeof(*h); ) {
+// int l_err;
int len = h->nlmsg_len;
int l = len - sizeof(*h);
- if (l<0 || len>status) {
+ if (l < 0 || len > status) {
if (msg.msg_flags & MSG_TRUNC) {
- bb_error_msg("Truncated message");
- return -1;
+ bb_error_msg("truncated message");
+ goto ret;
}
- bb_error_msg_and_die("!!!malformed message: len=%d", len);
+ bb_error_msg_and_die("malformed message: len=%d!", len);
}
- if (h->nlmsg_pid != rtnl->local.nl_pid ||
+ if (nladdr.nl_pid != peer ||
+ h->nlmsg_pid != rtnl->local.nl_pid ||
h->nlmsg_seq != seq) {
- if (junk) {
- l_err = junk(&nladdr, h, jarg);
- if (l_err < 0) {
- return l_err;
- }
- }
+// if (junk) {
+// l_err = junk(&nladdr, h, jarg);
+// if (l_err < 0) {
+// retval = l_err;
+// goto ret;
+// }
+// }
continue;
}
if (h->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
- if (l < sizeof(struct nlmsgerr)) {
+ if (l < (int)sizeof(struct nlmsgerr)) {
bb_error_msg("ERROR truncated");
} else {
- errno = -err->error;
+ errno = - err->error;
if (errno == 0) {
if (answer) {
memcpy(answer, h, h->nlmsg_len);
}
- return 0;
+ goto ret_0;
}
bb_perror_msg("RTNETLINK answers");
}
- return -1;
+ goto ret;
}
if (answer) {
memcpy(answer, h, h->nlmsg_len);
- return 0;
+ goto ret_0;
}
- bb_error_msg("Unexpected reply!!!");
+ bb_error_msg("unexpected reply!");
status -= NLMSG_ALIGN(len);
h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
}
if (msg.msg_flags & MSG_TRUNC) {
- bb_error_msg("Message truncated");
+ bb_error_msg("message truncated");
continue;
}
if (status) {
- bb_error_msg_and_die("!!!Remnant of size %d", status);
- }
- }
-}
-
-int rtnl_listen(struct rtnl_handle *rtnl,
- int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
- void *jarg)
-{
- int status;
- struct nlmsghdr *h;
- struct sockaddr_nl nladdr;
- struct iovec iov;
- char buf[8192];
- struct msghdr msg = {
- (void*)&nladdr, sizeof(nladdr),
- &iov, 1,
- NULL, 0,
- 0
- };
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
- nladdr.nl_pid = 0;
- nladdr.nl_groups = 0;
-
-
- iov.iov_base = buf;
-
- while (1) {
- iov.iov_len = sizeof(buf);
- status = recvmsg(rtnl->fd, &msg, 0);
-
- if (status < 0) {
- if (errno == EINTR)
- continue;
- bb_perror_msg("OVERRUN");
- continue;
+ bb_error_msg_and_die("remnant of size %d!", status);
}
- if (status == 0) {
- bb_error_msg("EOF on netlink");
- return -1;
- }
- if (msg.msg_namelen != sizeof(nladdr)) {
- bb_error_msg_and_die("Sender address length == %d", msg.msg_namelen);
- }
- for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
- int err;
- int len = h->nlmsg_len;
- int l = len - sizeof(*h);
-
- if (l<0 || len>status) {
- if (msg.msg_flags & MSG_TRUNC) {
- bb_error_msg("Truncated message");
- return -1;
- }
- bb_error_msg_and_die("!!!malformed message: len=%d", len);
- }
-
- err = handler(&nladdr, h, jarg);
- if (err < 0) {
- return err;
- }
-
- status -= NLMSG_ALIGN(len);
- h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
- }
- if (msg.msg_flags & MSG_TRUNC) {
- bb_error_msg("Message truncated");
- continue;
- }
- if (status) {
- bb_error_msg_and_die("!!!Remnant of size %d", status);
- }
- }
-}
-
-int rtnl_from_file(FILE *rtnl,
- int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
- void *jarg)
-{
- int status;
- struct sockaddr_nl nladdr;
- char buf[8192];
- struct nlmsghdr *h = (void*)buf;
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
- nladdr.nl_pid = 0;
- nladdr.nl_groups = 0;
-
- while (1) {
- int err, len, type;
- int l;
-
- status = fread(&buf, 1, sizeof(*h), rtnl);
-
- if (status < 0) {
- if (errno == EINTR)
- continue;
- bb_perror_msg("rtnl_from_file: fread");
- return -1;
- }
- if (status == 0)
- return 0;
-
- len = h->nlmsg_len;
- type= h->nlmsg_type;
- l = len - sizeof(*h);
-
- if (l<0 || len>sizeof(buf)) {
- bb_error_msg("!!!malformed message: len=%d @%lu",
- len, ftell(rtnl));
- return -1;
- }
-
- status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl);
-
- if (status < 0) {
- bb_perror_msg("rtnl_from_file: fread");
- return -1;
- }
- if (status < l) {
- bb_error_msg("rtnl-from_file: truncated message");
- return -1;
- }
-
- err = handler(&nladdr, h, jarg);
- if (err < 0)
- return err;
- }
+ } /* while (1) */
+ ret_0:
+ retval++; /* = 0 */
+ ret:
+ free(buf);
+ return retval;
}
-int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data)
+int FAST_FUNC addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data)
{
int len = RTA_LENGTH(4);
struct rtattr *rta;
- if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
+ if ((int)(NLMSG_ALIGN(n->nlmsg_len) + len) > maxlen)
return -1;
rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
rta->rta_type = type;
rta->rta_len = len;
- memcpy(RTA_DATA(rta), &data, 4);
+ move_to_unaligned32(RTA_DATA(rta), data);
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
return 0;
}
-int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
+int FAST_FUNC addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
{
int len = RTA_LENGTH(alen);
struct rtattr *rta;
- if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
+ if ((int)(NLMSG_ALIGN(n->nlmsg_len) + len) > maxlen)
return -1;
rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
rta->rta_type = type;
@@ -474,7 +361,7 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
return 0;
}
-int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data)
+int FAST_FUNC rta_addattr32(struct rtattr *rta, int maxlen, int type, uint32_t data)
{
int len = RTA_LENGTH(4);
struct rtattr *subrta;
@@ -485,12 +372,12 @@ int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data)
subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
subrta->rta_type = type;
subrta->rta_len = len;
- memcpy(RTA_DATA(subrta), &data, 4);
+ move_to_unaligned32(RTA_DATA(subrta), data);
rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;
return 0;
}
-int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen)
+int FAST_FUNC rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen)
{
struct rtattr *subrta;
int len = RTA_LENGTH(alen);
@@ -507,7 +394,7 @@ int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen
}
-int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+int FAST_FUNC parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
{
while (RTA_OK(rta, len)) {
if (rta->rta_type <= max) {
@@ -516,7 +403,7 @@ int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
rta = RTA_NEXT(rta,len);
}
if (len) {
- bb_error_msg("!!!Deficit %d, rta_len=%d", len, rta->rta_len);
+ bb_error_msg("deficit %d, rta_len=%d!", len, rta->rta_len);
}
return 0;
}
diff --git a/release/src/router/busybox/networking/libiproute/libnetlink.h b/release/src/router/busybox/networking/libiproute/libnetlink.h
index 45d3ad2b..e5fee4dd 100644
--- a/release/src/router/busybox/networking/libiproute/libnetlink.h
+++ b/release/src/router/busybox/networking/libiproute/libnetlink.h
@@ -1,46 +1,50 @@
-#ifndef __LIBNETLINK_H__
-#define __LIBNETLINK_H__ 1
+/* vi: set sw=4 ts=4: */
+#ifndef LIBNETLINK_H
+#define LIBNETLINK_H 1
-#include <asm/types.h>
+#include <linux/types.h>
+/* We need linux/types.h because older kernels use __u32 etc
+ * in linux/[rt]netlink.h. 2.6.19 seems to be ok, though */
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
+
struct rtnl_handle
{
int fd;
struct sockaddr_nl local;
struct sockaddr_nl peer;
- __u32 seq;
- __u32 dump;
+ uint32_t seq;
+ uint32_t dump;
};
-extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions);
-extern void rtnl_close(struct rtnl_handle *rth);
-extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type);
-extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len);
-extern int rtnl_dump_filter(struct rtnl_handle *rth,
- int (*filter)(struct sockaddr_nl *, struct nlmsghdr *n, void *),
- void *arg1,
- int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
- void *arg2);
+extern int xrtnl_open(struct rtnl_handle *rth) FAST_FUNC;
+extern void rtnl_close(struct rtnl_handle *rth) FAST_FUNC;
+extern int 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*),
+ void *arg1) FAST_FUNC;
+
+/* bbox doesn't use parameters no. 3, 4, 6, 7, stub them out */
+#define rtnl_talk(rtnl, n, peer, groups, answer, junk, jarg) \
+ rtnl_talk(rtnl, n, answer)
extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
- unsigned groups, struct nlmsghdr *answer,
- int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
- void *jarg);
-extern int rtnl_send(struct rtnl_handle *rth, char *buf, int);
+ unsigned groups, struct nlmsghdr *answer,
+ 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;
-extern int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data);
-extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen);
-extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
-extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen);
-extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
+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;
+extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, uint32_t data) FAST_FUNC;
+extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen) FAST_FUNC;
-extern int rtnl_listen(struct rtnl_handle *, int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
- void *jarg);
-extern int rtnl_from_file(FILE *, int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
- void *jarg);
+extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) FAST_FUNC;
-#endif /* __LIBNETLINK_H__ */
+POP_SAVED_FUNCTION_VISIBILITY
+#endif
diff --git a/release/src/router/busybox/networking/libiproute/linux/pkt_sched.h b/release/src/router/busybox/networking/libiproute/linux/pkt_sched.h
deleted file mode 100644
index e174588f..00000000
--- a/release/src/router/busybox/networking/libiproute/linux/pkt_sched.h
+++ /dev/null
@@ -1,413 +0,0 @@
-#ifndef __LINUX_PKT_SCHED_H
-#define __LINUX_PKT_SCHED_H
-
-/* Logical priority bands not depending on specific packet scheduler.
- Every scheduler will map them to real traffic classes, if it has
- no more precise mechanism to classify packets.
-
- These numbers have no special meaning, though their coincidence
- with obsolete IPv6 values is not occasional :-). New IPv6 drafts
- preferred full anarchy inspired by diffserv group.
-
- Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy
- class, actually, as rule it will be handled with more care than
- filler or even bulk.
- */
-
-#include <asm/types.h>
-
-#define TC_PRIO_BESTEFFORT 0
-#define TC_PRIO_FILLER 1
-#define TC_PRIO_BULK 2
-#define TC_PRIO_INTERACTIVE_BULK 4
-#define TC_PRIO_INTERACTIVE 6
-#define TC_PRIO_CONTROL 7
-
-#define TC_PRIO_MAX 15
-
-/* Generic queue statistics, available for all the elements.
- Particular schedulers may have also their private records.
- */
-
-struct tc_stats
-{
- __u64 bytes; /* NUmber of enqueues bytes */
- __u32 packets; /* Number of enqueued packets */
- __u32 drops; /* Packets dropped because of lack of resources */
- __u32 overlimits; /* Number of throttle events when this
- * flow goes out of allocated bandwidth */
- __u32 bps; /* Current flow byte rate */
- __u32 pps; /* Current flow packet rate */
- __u32 qlen;
- __u32 backlog;
-#ifdef __KERNEL__
- spinlock_t *lock;
-#endif
-};
-
-struct tc_estimator
-{
- char interval;
- unsigned char ewma_log;
-};
-
-/* "Handles"
- ---------
-
- All the traffic control objects have 32bit identifiers, or "handles".
-
- They can be considered as opaque numbers from user API viewpoint,
- but actually they always consist of two fields: major and
- minor numbers, which are interpreted by kernel specially,
- that may be used by applications, though not recommended.
-
- F.e. qdisc handles always have minor number equal to zero,
- classes (or flows) have major equal to parent qdisc major, and
- minor uniquely identifying class inside qdisc.
-
- Macros to manipulate handles:
- */
-
-#define TC_H_MAJ_MASK (0xFFFF0000U)
-#define TC_H_MIN_MASK (0x0000FFFFU)
-#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK)
-#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK)
-#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK))
-
-#define TC_H_UNSPEC (0U)
-#define TC_H_ROOT (0xFFFFFFFFU)
-#define TC_H_INGRESS (0xFFFFFFF1U)
-
-struct tc_ratespec
-{
- unsigned char cell_log;
- unsigned char __reserved;
- unsigned short feature;
- short addend;
- unsigned short mpu;
- __u32 rate;
-};
-
-/* FIFO section */
-
-struct tc_fifo_qopt
-{
- __u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */
-};
-
-/* PRIO section */
-
-#define TCQ_PRIO_BANDS 16
-
-struct tc_prio_qopt
-{
- int bands; /* Number of bands */
- __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
-};
-
-/* CSZ section */
-
-struct tc_csz_qopt
-{
- int flows; /* Maximal number of guaranteed flows */
- unsigned char R_log; /* Fixed point position for round number */
- unsigned char delta_log; /* Log of maximal managed time interval */
- __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> CSZ band */
-};
-
-struct tc_csz_copt
-{
- struct tc_ratespec slice;
- struct tc_ratespec rate;
- struct tc_ratespec peakrate;
- __u32 limit;
- __u32 buffer;
- __u32 mtu;
-};
-
-enum
-{
- TCA_CSZ_UNSPEC,
- TCA_CSZ_PARMS,
- TCA_CSZ_RTAB,
- TCA_CSZ_PTAB,
-};
-
-/* TBF section */
-
-struct tc_tbf_qopt
-{
- struct tc_ratespec rate;
- struct tc_ratespec peakrate;
- __u32 limit;
- __u32 buffer;
- __u32 mtu;
-};
-
-enum
-{
- TCA_TBF_UNSPEC,
- TCA_TBF_PARMS,
- TCA_TBF_RTAB,
- TCA_TBF_PTAB,
-};
-
-
-/* TEQL section */
-
-/* TEQL does not require any parameters */
-
-/* SFQ section */
-
-struct tc_sfq_qopt
-{
- unsigned quantum; /* Bytes per round allocated to flow */
- int perturb_period; /* Period of hash perturbation */
- __u32 limit; /* Maximal packets in queue */
- unsigned divisor; /* Hash divisor */
- unsigned flows; /* Maximal number of flows */
-};
-
-/*
- * NOTE: limit, divisor and flows are hardwired to code at the moment.
- *
- * limit=flows=128, divisor=1024;
- *
- * The only reason for this is efficiency, it is possible
- * to change these parameters in compile time.
- */
-
-/* RED section */
-
-enum
-{
- TCA_RED_UNSPEC,
- TCA_RED_PARMS,
- TCA_RED_STAB,
-};
-
-struct tc_red_qopt
-{
- __u32 limit; /* HARD maximal queue length (bytes) */
- __u32 qth_min; /* Min average length threshold (bytes) */
- __u32 qth_max; /* Max average length threshold (bytes) */
- unsigned char Wlog; /* log(W) */
- unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
- unsigned char Scell_log; /* cell size for idle damping */
- unsigned char flags;
-#define TC_RED_ECN 1
-};
-
-struct tc_red_xstats
-{
- __u32 early; /* Early drops */
- __u32 pdrop; /* Drops due to queue limits */
- __u32 other; /* Drops due to drop() calls */
- __u32 marked; /* Marked packets */
-};
-
-/* GRED section */
-
-#define MAX_DPs 16
-
-enum
-{
- TCA_GRED_UNSPEC,
- TCA_GRED_PARMS,
- TCA_GRED_STAB,
- TCA_GRED_DPS,
-};
-
-#define TCA_SET_OFF TCA_GRED_PARMS
-struct tc_gred_qopt
-{
- __u32 limit; /* HARD maximal queue length (bytes)
-*/
- __u32 qth_min; /* Min average length threshold (bytes)
-*/
- __u32 qth_max; /* Max average length threshold (bytes)
-*/
- __u32 DP; /* upto 2^32 DPs */
- __u32 backlog;
- __u32 qave;
- __u32 forced;
- __u32 early;
- __u32 other;
- __u32 pdrop;
-
- unsigned char Wlog; /* log(W) */
- unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
- unsigned char Scell_log; /* cell size for idle damping */
- __u8 prio; /* prio of this VQ */
- __u32 packets;
- __u32 bytesin;
-};
-/* gred setup */
-struct tc_gred_sopt
-{
- __u32 DPs;
- __u32 def_DP;
- __u8 grio;
-};
-
-/* HTB section */
-#define TC_HTB_NUMPRIO 4
-#define TC_HTB_MAXDEPTH 4
-
-struct tc_htb_opt
-{
- struct tc_ratespec rate;
- struct tc_ratespec ceil;
- __u32 buffer;
- __u32 cbuffer;
- __u32 quantum; /* out only */
- __u32 level; /* out only */
- __u8 prio;
- __u8 injectd; /* inject class distance */
- __u8 pad[2];
-};
-struct tc_htb_glob
-{
- __u32 rate2quantum; /* bps->quantum divisor */
- __u32 defcls; /* default class number */
- __u32 use_dcache; /* use dequeue cache ? */
- __u32 debug; /* debug flags */
-
-
- /* stats */
- __u32 deq_rate; /* dequeue rate */
- __u32 utilz; /* dequeue utilization */
- __u32 trials; /* deq_prio trials per dequeue */
- __u32 dcache_hits;
- __u32 direct_pkts; /* count of non shapped packets */
-};
-enum
-{
- TCA_HTB_UNSPEC,
- TCA_HTB_PARMS,
- TCA_HTB_INIT,
- TCA_HTB_CTAB,
- TCA_HTB_RTAB,
-};
-struct tc_htb_xstats
-{
- __u32 lends;
- __u32 borrows;
- __u32 giants; /* too big packets (rate will not be accurate) */
- __u32 injects; /* how many times leaf used injected bw */
- __u32 tokens;
- __u32 ctokens;
-};
-
-/* CBQ section */
-
-#define TC_CBQ_MAXPRIO 8
-#define TC_CBQ_MAXLEVEL 8
-#define TC_CBQ_DEF_EWMA 5
-
-struct tc_cbq_lssopt
-{
- unsigned char change;
- unsigned char flags;
-#define TCF_CBQ_LSS_BOUNDED 1
-#define TCF_CBQ_LSS_ISOLATED 2
- unsigned char ewma_log;
- unsigned char level;
-#define TCF_CBQ_LSS_FLAGS 1
-#define TCF_CBQ_LSS_EWMA 2
-#define TCF_CBQ_LSS_MAXIDLE 4
-#define TCF_CBQ_LSS_MINIDLE 8
-#define TCF_CBQ_LSS_OFFTIME 0x10
-#define TCF_CBQ_LSS_AVPKT 0x20
- __u32 maxidle;
- __u32 minidle;
- __u32 offtime;
- __u32 avpkt;
-};
-
-struct tc_cbq_wrropt
-{
- unsigned char flags;
- unsigned char priority;
- unsigned char cpriority;
- unsigned char __reserved;
- __u32 allot;
- __u32 weight;
-};
-
-struct tc_cbq_ovl
-{
- unsigned char strategy;
-#define TC_CBQ_OVL_CLASSIC 0
-#define TC_CBQ_OVL_DELAY 1
-#define TC_CBQ_OVL_LOWPRIO 2
-#define TC_CBQ_OVL_DROP 3
-#define TC_CBQ_OVL_RCLASSIC 4
- unsigned char priority2;
- __u32 penalty;
-};
-
-struct tc_cbq_police
-{
- unsigned char police;
- unsigned char __res1;
- unsigned short __res2;
-};
-
-struct tc_cbq_fopt
-{
- __u32 split;
- __u32 defmap;
- __u32 defchange;
-};
-
-struct tc_cbq_xstats
-{
- __u32 borrows;
- __u32 overactions;
- __s32 avgidle;
- __s32 undertime;
-};
-
-enum
-{
- TCA_CBQ_UNSPEC,
- TCA_CBQ_LSSOPT,
- TCA_CBQ_WRROPT,
- TCA_CBQ_FOPT,
- TCA_CBQ_OVL_STRATEGY,
- TCA_CBQ_RATE,
- TCA_CBQ_RTAB,
- TCA_CBQ_POLICE,
-};
-
-#define TCA_CBQ_MAX TCA_CBQ_POLICE
-
-/* dsmark section */
-
-enum {
- TCA_DSMARK_UNSPEC,
- TCA_DSMARK_INDICES,
- TCA_DSMARK_DEFAULT_INDEX,
- TCA_DSMARK_SET_TC_INDEX,
- TCA_DSMARK_MASK,
- TCA_DSMARK_VALUE
-};
-
-#define TCA_DSMARK_MAX TCA_DSMARK_VALUE
-
-/* ATM section */
-
-enum {
- TCA_ATM_UNSPEC,
- TCA_ATM_FD, /* file/socket descriptor */
- TCA_ATM_PTR, /* pointer to descriptor - later */
- TCA_ATM_HDR, /* LL header */
- TCA_ATM_EXCESS, /* excess traffic class (0 for CLP) */
- TCA_ATM_ADDR, /* PVC address (for output only) */
- TCA_ATM_STATE /* VC state (ATM_VS_*; for output only) */
-};
-
-#define TCA_ATM_MAX TCA_ATM_STATE
-
-#endif
diff --git a/release/src/router/busybox/networking/libiproute/ll_addr.c b/release/src/router/busybox/networking/libiproute/ll_addr.c
index ada685f4..f50e3719 100644
--- a/release/src/router/busybox/networking/libiproute/ll_addr.c
+++ b/release/src/router/busybox/networking/libiproute/ll_addr.c
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
/*
* ll_addr.c
*
@@ -9,11 +10,12 @@
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*/
-#include <arpa/inet.h>
-#include <string.h>
#include <net/if_arp.h>
-#include "utils.h"
+
#include "libbb.h"
+#include "rt_names.h"
+#include "utils.h"
+
const char *ll_addr_n2a(unsigned char *addr, int alen, int type, char *buf, int blen)
{
@@ -27,7 +29,7 @@ const char *ll_addr_n2a(unsigned char *addr, int alen, int type, char *buf, int
l = 0;
for (i=0; i<alen; i++) {
if (i==0) {
- snprintf(buf+l, blen, "%02x", addr[i]);
+ snprintf(buf+l, blen, ":%02x"+1, addr[i]);
blen -= 2;
l += 2;
} else {
@@ -41,10 +43,12 @@ const char *ll_addr_n2a(unsigned char *addr, int alen, int type, char *buf, int
int ll_addr_a2n(unsigned char *lladdr, int len, char *arg)
{
+ int i;
+
if (strchr(arg, '.')) {
inet_prefix pfx;
if (get_addr_1(&pfx, arg, AF_INET)) {
- bb_error_msg("\"%s\" is invalid lladdr.", arg);
+ bb_error_msg("\"%s\" is invalid lladdr", arg);
return -1;
}
if (len < 4) {
@@ -52,30 +56,24 @@ int ll_addr_a2n(unsigned char *lladdr, int len, char *arg)
}
memcpy(lladdr, pfx.data, 4);
return 4;
- } else {
- int i;
+ }
- for (i=0; i<len; i++) {
- int temp;
- char *cp = strchr(arg, ':');
- if (cp) {
- *cp = 0;
- cp++;
- }
- if (sscanf(arg, "%x", &temp) != 1) {
- bb_error_msg("\"%s\" is invalid lladdr.", arg);
- return -1;
- }
- if (temp < 0 || temp > 255) {
- bb_error_msg("\"%s\" is invalid lladdr.", arg);
- return -1;
- }
- lladdr[i] = temp;
- if (!cp) {
- break;
- }
- arg = cp;
+ for (i = 0; i < len; i++) {
+ int temp;
+ char *cp = strchr(arg, ':');
+ if (cp) {
+ *cp = 0;
+ cp++;
+ }
+ if (sscanf(arg, "%x", &temp) != 1 || (temp < 0 || temp > 255)) {
+ bb_error_msg("\"%s\" is invalid lladdr", arg);
+ return -1;
+ }
+ lladdr[i] = temp;
+ if (!cp) {
+ break;
}
- return i+1;
+ arg = cp;
}
+ return i+1;
}
diff --git a/release/src/router/busybox/networking/libiproute/ll_map.c b/release/src/router/busybox/networking/libiproute/ll_map.c
index b7a82842..2ed7fbbb 100644
--- a/release/src/router/busybox/networking/libiproute/ll_map.c
+++ b/release/src/router/busybox/networking/libiproute/ll_map.c
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
/*
* ll_map.c
*
@@ -10,27 +11,37 @@
*
*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <netinet/in.h>
+#include <net/if.h> /* struct ifreq and co. */
+#include "libbb.h"
#include "libnetlink.h"
-
-struct idxmap
-{
- struct idxmap * next;
- int index;
- int type;
- int alen;
- unsigned flags;
- unsigned char addr[8];
- char name[16];
+#include "ll_map.h"
+
+struct idxmap {
+ struct idxmap *next;
+ int index;
+ int type;
+ int alen;
+ unsigned flags;
+ unsigned char addr[8];
+ char name[16];
};
static struct idxmap *idxmap[16];
-int ll_remember_index(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+static struct idxmap *find_by_index(int idx)
+{
+ struct idxmap *im;
+
+ for (im = idxmap[idx & 0xF]; im; im = im->next)
+ if (im->index == idx)
+ return im;
+ return NULL;
+}
+
+int ll_remember_index(const struct sockaddr_nl *who UNUSED_PARAM,
+ struct nlmsghdr *n,
+ void *arg UNUSED_PARAM)
{
int h;
struct ifinfomsg *ifi = NLMSG_DATA(n);
@@ -43,33 +54,28 @@ int ll_remember_index(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))
return -1;
-
memset(tb, 0, sizeof(tb));
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
if (tb[IFLA_IFNAME] == NULL)
return 0;
- h = ifi->ifi_index&0xF;
+ h = ifi->ifi_index & 0xF;
- for (imp=&idxmap[h]; (im=*imp)!=NULL; imp = &im->next)
+ for (imp = &idxmap[h]; (im = *imp) != NULL; imp = &im->next)
if (im->index == ifi->ifi_index)
- break;
-
- if (im == NULL) {
- im = malloc(sizeof(*im));
- if (im == NULL)
- return 0;
- im->next = *imp;
- im->index = ifi->ifi_index;
- *imp = im;
- }
+ goto found;
+ im = xmalloc(sizeof(*im));
+ im->next = *imp;
+ im->index = ifi->ifi_index;
+ *imp = im;
+ found:
im->type = ifi->ifi_type;
im->flags = ifi->ifi_flags;
if (tb[IFLA_ADDRESS]) {
int alen;
im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
- if (alen > sizeof(im->addr))
+ if (alen > (int)sizeof(im->addr))
alen = sizeof(im->addr);
memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen);
} else {
@@ -86,9 +92,9 @@ const char *ll_idx_n2a(int idx, char *buf)
if (idx == 0)
return "*";
- for (im = idxmap[idx&0xF]; im; im = im->next)
- if (im->index == idx)
- return im->name;
+ im = find_by_index(idx);
+ if (im)
+ return im->name;
snprintf(buf, 16, "if%d", idx);
return buf;
}
@@ -101,17 +107,19 @@ const char *ll_index_to_name(int idx)
return ll_idx_n2a(idx, nbuf);
}
+#ifdef UNUSED
int ll_index_to_type(int idx)
{
struct idxmap *im;
if (idx == 0)
return -1;
- for (im = idxmap[idx&0xF]; im; im = im->next)
- if (im->index == idx)
- return im->type;
+ im = find_by_index(idx);
+ if (im)
+ return im->type;
return -1;
}
+#endif
unsigned ll_index_to_flags(int idx)
{
@@ -119,46 +127,74 @@ unsigned ll_index_to_flags(int idx)
if (idx == 0)
return 0;
-
- for (im = idxmap[idx&0xF]; im; im = im->next)
- if (im->index == idx)
- return im->flags;
+ im = find_by_index(idx);
+ if (im)
+ return im->flags;
return 0;
}
-int ll_name_to_index(char *name)
+int xll_name_to_index(const char *const name)
{
+ int ret = 0;
+ int sock_fd;
+
+/* caching is not warranted - no users which repeatedly call it */
+#ifdef UNUSED
static char ncache[16];
static int icache;
+
struct idxmap *im;
int i;
if (name == NULL)
- return 0;
- if (icache && strcmp(name, ncache) == 0)
- return icache;
- for (i=0; i<16; i++) {
+ goto out;
+ if (icache && strcmp(name, ncache) == 0) {
+ ret = icache;
+ goto out;
+ }
+ for (i = 0; i < 16; i++) {
for (im = idxmap[i]; im; im = im->next) {
if (strcmp(im->name, name) == 0) {
icache = im->index;
strcpy(ncache, name);
- return im->index;
+ ret = im->index;
+ goto out;
}
}
}
- return 0;
+ /* We have not found the interface in our cache, but the kernel
+ * may still know about it. One reason is that we may be using
+ * module on-demand loading, which means that the kernel will
+ * load the module and make the interface exist only when
+ * we explicitely request it (check for dev_load() in net/core/dev.c).
+ * I can think of other similar scenario, but they are less common...
+ * Jean II */
+#endif
+
+ sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock_fd >= 0) {
+ struct ifreq ifr;
+ int tmp;
+
+ strncpy_IFNAMSIZ(ifr.ifr_name, name);
+ ifr.ifr_ifindex = -1;
+ tmp = ioctl(sock_fd, SIOCGIFINDEX, &ifr);
+ close(sock_fd);
+ if (tmp >= 0)
+ /* In theory, we should redump the interface list
+ * to update our cache, this is left as an exercise
+ * to the reader... Jean II */
+ ret = ifr.ifr_ifindex;
+ }
+/* out:*/
+ if (ret <= 0)
+ bb_error_msg_and_die("cannot find device \"%s\"", name);
+ return ret;
}
int ll_init_map(struct rtnl_handle *rth)
{
- if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) {
- perror("Cannot send dump request");
- exit(1);
- }
-
- if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) {
- fprintf(stderr, "Dump terminated\n");
- exit(1);
- }
+ xrtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK);
+ xrtnl_dump_filter(rth, ll_remember_index, &idxmap);
return 0;
}
diff --git a/release/src/router/busybox/networking/libiproute/ll_map.h b/release/src/router/busybox/networking/libiproute/ll_map.h
index 739f157e..3966def1 100644
--- a/release/src/router/busybox/networking/libiproute/ll_map.h
+++ b/release/src/router/busybox/networking/libiproute/ll_map.h
@@ -1,12 +1,17 @@
-#ifndef __LL_MAP_H__
-#define __LL_MAP_H__ 1
-
-extern int ll_remember_index(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
-extern int ll_init_map(struct rtnl_handle *rth);
-extern int ll_name_to_index(char *name);
-extern const char *ll_index_to_name(int idx);
-extern const char *ll_idx_n2a(int idx, char *buf);
-extern int ll_index_to_type(int idx);
-extern unsigned ll_index_to_flags(int idx);
-
-#endif /* __LL_MAP_H__ */
+/* vi: set sw=4 ts=4: */
+#ifndef LL_MAP_H
+#define LL_MAP_H 1
+
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
+
+int ll_remember_index(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
+int ll_init_map(struct rtnl_handle *rth);
+int xll_name_to_index(const char *const name);
+const char *ll_index_to_name(int idx);
+const char *ll_idx_n2a(int idx, char *buf);
+/* int ll_index_to_type(int idx); */
+unsigned ll_index_to_flags(int idx);
+
+POP_SAVED_FUNCTION_VISIBILITY
+
+#endif
diff --git a/release/src/router/busybox/networking/libiproute/ll_proto.c b/release/src/router/busybox/networking/libiproute/ll_proto.c
index 45afdb82..a9349353 100644
--- a/release/src/router/busybox/networking/libiproute/ll_proto.c
+++ b/release/src/router/busybox/networking/libiproute/ll_proto.c
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
/*
* ll_proto.c
*
@@ -9,79 +10,86 @@
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*/
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
+#include "libbb.h"
+#include "rt_names.h"
#include "utils.h"
-#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1
+#if defined(__GLIBC__) && __GLIBC__ >=2 && __GLIBC_MINOR__ >= 1
#include <net/ethernet.h>
#else
#include <linux/if_ether.h>
#endif
+#if !ENABLE_WERROR
+#warning de-bloat
+#endif
+/* Before re-enabling this, please (1) conditionalize exotic protocols
+ * on CONFIG_something, and (2) decouple strings and numbers
+ * (use llproto_ids[] = n,n,n..; and llproto_names[] = "loop\0" "pup\0" ...;)
+ */
+
#define __PF(f,n) { ETH_P_##f, #n },
static struct {
int id;
- char *name;
+ const char *name;
} llproto_names[] = {
__PF(LOOP,loop)
-__PF(PUP,pup)
+__PF(PUP,pup)
#ifdef ETH_P_PUPAT
-__PF(PUPAT,pupat)
+__PF(PUPAT,pupat)
#endif
__PF(IP,ip)
__PF(X25,x25)
__PF(ARP,arp)
__PF(BPQ,bpq)
#ifdef ETH_P_IEEEPUP
-__PF(IEEEPUP,ieeepup)
+__PF(IEEEPUP,ieeepup)
#endif
#ifdef ETH_P_IEEEPUPAT
-__PF(IEEEPUPAT,ieeepupat)
+__PF(IEEEPUPAT,ieeepupat)
#endif
-__PF(DEC,dec)
-__PF(DNA_DL,dna_dl)
-__PF(DNA_RC,dna_rc)
-__PF(DNA_RT,dna_rt)
-__PF(LAT,lat)
-__PF(DIAG,diag)
-__PF(CUST,cust)
-__PF(SCA,sca)
-__PF(RARP,rarp)
-__PF(ATALK,atalk)
-__PF(AARP,aarp)
-__PF(IPX,ipx)
-__PF(IPV6,ipv6)
+__PF(DEC,dec)
+__PF(DNA_DL,dna_dl)
+__PF(DNA_RC,dna_rc)
+__PF(DNA_RT,dna_rt)
+__PF(LAT,lat)
+__PF(DIAG,diag)
+__PF(CUST,cust)
+__PF(SCA,sca)
+__PF(RARP,rarp)
+__PF(ATALK,atalk)
+__PF(AARP,aarp)
+__PF(IPX,ipx)
+__PF(IPV6,ipv6)
#ifdef ETH_P_PPP_DISC
-__PF(PPP_DISC,ppp_disc)
+__PF(PPP_DISC,ppp_disc)
#endif
#ifdef ETH_P_PPP_SES
-__PF(PPP_SES,ppp_ses)
+__PF(PPP_SES,ppp_ses)
#endif
#ifdef ETH_P_ATMMPOA
-__PF(ATMMPOA,atmmpoa)
+__PF(ATMMPOA,atmmpoa)
#endif
#ifdef ETH_P_ATMFATE
-__PF(ATMFATE,atmfate)
+__PF(ATMFATE,atmfate)
#endif
-__PF(802_3,802_3)
-__PF(AX25,ax25)
-__PF(ALL,all)
-__PF(802_2,802_2)
-__PF(SNAP,snap)
-__PF(DDCMP,ddcmp)
-__PF(WAN_PPP,wan_ppp)
-__PF(PPP_MP,ppp_mp)
-__PF(LOCALTALK,localtalk)
-__PF(PPPTALK,ppptalk)
-__PF(TR_802_2,tr_802_2)
-__PF(MOBITEX,mobitex)
-__PF(CONTROL,control)
-__PF(IRDA,irda)
+__PF(802_3,802_3)
+__PF(AX25,ax25)
+__PF(ALL,all)
+__PF(802_2,802_2)
+__PF(SNAP,snap)
+__PF(DDCMP,ddcmp)
+__PF(WAN_PPP,wan_ppp)
+__PF(PPP_MP,ppp_mp)
+__PF(LOCALTALK,localtalk)
+__PF(PPPTALK,ppptalk)
+__PF(TR_802_2,tr_802_2)
+__PF(MOBITEX,mobitex)
+__PF(CONTROL,control)
+__PF(IRDA,irda)
#ifdef ETH_P_ECONET
-__PF(ECONET,econet)
+__PF(ECONET,econet)
#endif
{ 0x8100, "802.1Q" },
@@ -90,31 +98,32 @@ __PF(ECONET,econet)
#undef __PF
-char * ll_proto_n2a(unsigned short id, char *buf, int len)
+const char *ll_proto_n2a(unsigned short id, char *buf, int len)
{
- int i;
-
+ unsigned i;
id = ntohs(id);
-
- for (i=0; i<sizeof(llproto_names)/sizeof(llproto_names[0]); i++) {
- if (llproto_names[i].id == id)
+ for (i = 0; i < ARRAY_SIZE(llproto_names); i++) {
+ if (llproto_names[i].id == id)
return llproto_names[i].name;
}
- snprintf(buf, len, "[%d]", id);
- return buf;
+ snprintf(buf, len, "[%d]", id);
+ return buf;
}
int ll_proto_a2n(unsigned short *id, char *buf)
{
- int i;
- for (i=0; i<sizeof(llproto_names)/sizeof(llproto_names[0]); i++) {
- if (strcasecmp(llproto_names[i].name, buf) == 0) {
- *id = htons(llproto_names[i].id);
- return 0;
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(llproto_names); i++) {
+ if (strcasecmp(llproto_names[i].name, buf) == 0) {
+ i = llproto_names[i].id;
+ goto good;
}
}
- if (get_u16(id, buf, 0))
+ i = bb_strtou(buf, NULL, 0);
+ if (errno || i > 0xffff)
return -1;
- *id = htons(*id);
+ good:
+ *id = htons(i);
return 0;
}
+
diff --git a/release/src/router/busybox/networking/libiproute/ll_types.c b/release/src/router/busybox/networking/libiproute/ll_types.c
index f39f777e..d5d2a1f3 100644
--- a/release/src/router/busybox/networking/libiproute/ll_types.c
+++ b/release/src/router/busybox/networking/libiproute/ll_types.c
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
/*
* ll_types.c
*
@@ -8,108 +9,197 @@
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*/
-#include <stdio.h>
#include <arpa/inet.h>
-
#include <linux/if_arp.h>
-char * ll_type_n2a(int type, char *buf, int len)
+#include "libbb.h"
+#include "rt_names.h"
+
+const char *ll_type_n2a(int type, char *buf, int len)
{
-#define __PF(f,n) { ARPHRD_##f, #n },
-static struct {
- int type;
- char *name;
-} arphrd_names[] = {
-{ 0, "generic" },
-__PF(ETHER,ether)
-__PF(EETHER,eether)
-__PF(AX25,ax25)
-__PF(PRONET,pronet)
-__PF(CHAOS,chaos)
+ static const char arphrd_name[] =
+ /* 0, */ "generic" "\0"
+ /* ARPHRD_LOOPBACK, */ "loopback" "\0"
+ /* ARPHRD_ETHER, */ "ether" "\0"
+#ifdef ARPHRD_INFINIBAND
+ /* ARPHRD_INFINIBAND, */ "infiniband" "\0"
+#endif
#ifdef ARPHRD_IEEE802_TR
-__PF(IEEE802,ieee802)
+ /* ARPHRD_IEEE802, */ "ieee802" "\0"
+ /* ARPHRD_IEEE802_TR, */ "tr" "\0"
#else
-__PF(IEEE802,tr)
+ /* ARPHRD_IEEE802, */ "tr" "\0"
#endif
-__PF(ARCNET,arcnet)
-__PF(APPLETLK,atalk)
-__PF(DLCI,dlci)
-#ifdef ARPHRD_ATM
-__PF(ATM,atm)
+#ifdef ARPHRD_IEEE80211
+ /* ARPHRD_IEEE80211, */ "ieee802.11" "\0"
#endif
-__PF(METRICOM,metricom)
#ifdef ARPHRD_IEEE1394
-__PF(IEEE1394,ieee1394)
+ /* ARPHRD_IEEE1394, */ "ieee1394" "\0"
+#endif
+ /* ARPHRD_IRDA, */ "irda" "\0"
+ /* ARPHRD_SLIP, */ "slip" "\0"
+ /* ARPHRD_CSLIP, */ "cslip" "\0"
+ /* ARPHRD_SLIP6, */ "slip6" "\0"
+ /* ARPHRD_CSLIP6, */ "cslip6" "\0"
+ /* ARPHRD_PPP, */ "ppp" "\0"
+ /* ARPHRD_TUNNEL, */ "ipip" "\0"
+ /* ARPHRD_TUNNEL6, */ "tunnel6" "\0"
+ /* ARPHRD_SIT, */ "sit" "\0"
+ /* ARPHRD_IPGRE, */ "gre" "\0"
+#ifdef ARPHRD_VOID
+ /* ARPHRD_VOID, */ "void" "\0"
#endif
-__PF(SLIP,slip)
-__PF(CSLIP,cslip)
-__PF(SLIP6,slip6)
-__PF(CSLIP6,cslip6)
-__PF(RSRVD,rsrvd)
-__PF(ADAPT,adapt)
-__PF(ROSE,rose)
-__PF(X25,x25)
+#if ENABLE_FEATURE_IP_RARE_PROTOCOLS
+ /* ARPHRD_EETHER, */ "eether" "\0"
+ /* ARPHRD_AX25, */ "ax25" "\0"
+ /* ARPHRD_PRONET, */ "pronet" "\0"
+ /* ARPHRD_CHAOS, */ "chaos" "\0"
+ /* ARPHRD_ARCNET, */ "arcnet" "\0"
+ /* ARPHRD_APPLETLK, */ "atalk" "\0"
+ /* ARPHRD_DLCI, */ "dlci" "\0"
+#ifdef ARPHRD_ATM
+ /* ARPHRD_ATM, */ "atm" "\0"
+#endif
+ /* ARPHRD_METRICOM, */ "metricom" "\0"
+ /* ARPHRD_RSRVD, */ "rsrvd" "\0"
+ /* ARPHRD_ADAPT, */ "adapt" "\0"
+ /* ARPHRD_ROSE, */ "rose" "\0"
+ /* ARPHRD_X25, */ "x25" "\0"
#ifdef ARPHRD_HWX25
-__PF(HWX25,hwx25)
+ /* ARPHRD_HWX25, */ "hwx25" "\0"
#endif
-__PF(PPP,ppp)
-__PF(HDLC,hdlc)
-__PF(LAPB,lapb)
+ /* ARPHRD_HDLC, */ "hdlc" "\0"
+ /* ARPHRD_LAPB, */ "lapb" "\0"
#ifdef ARPHRD_DDCMP
-__PF(DDCMP,ddcmp)
-__PF(RAWHDLC,rawhdlc)
+ /* ARPHRD_DDCMP, */ "ddcmp" "\0"
+ /* ARPHRD_RAWHDLC, */ "rawhdlc" "\0"
#endif
+ /* ARPHRD_FRAD, */ "frad" "\0"
+ /* ARPHRD_SKIP, */ "skip" "\0"
+ /* ARPHRD_LOCALTLK, */ "ltalk" "\0"
+ /* ARPHRD_FDDI, */ "fddi" "\0"
+ /* ARPHRD_BIF, */ "bif" "\0"
+ /* ARPHRD_IPDDP, */ "ip/ddp" "\0"
+ /* ARPHRD_PIMREG, */ "pimreg" "\0"
+ /* ARPHRD_HIPPI, */ "hippi" "\0"
+ /* ARPHRD_ASH, */ "ash" "\0"
+ /* ARPHRD_ECONET, */ "econet" "\0"
+ /* ARPHRD_FCPP, */ "fcpp" "\0"
+ /* ARPHRD_FCAL, */ "fcal" "\0"
+ /* ARPHRD_FCPL, */ "fcpl" "\0"
+ /* ARPHRD_FCFABRIC, */ "fcfb0" "\0"
+ /* ARPHRD_FCFABRIC+1, */ "fcfb1" "\0"
+ /* ARPHRD_FCFABRIC+2, */ "fcfb2" "\0"
+ /* ARPHRD_FCFABRIC+3, */ "fcfb3" "\0"
+ /* ARPHRD_FCFABRIC+4, */ "fcfb4" "\0"
+ /* ARPHRD_FCFABRIC+5, */ "fcfb5" "\0"
+ /* ARPHRD_FCFABRIC+6, */ "fcfb6" "\0"
+ /* ARPHRD_FCFABRIC+7, */ "fcfb7" "\0"
+ /* ARPHRD_FCFABRIC+8, */ "fcfb8" "\0"
+ /* ARPHRD_FCFABRIC+9, */ "fcfb9" "\0"
+ /* ARPHRD_FCFABRIC+10, */ "fcfb10" "\0"
+ /* ARPHRD_FCFABRIC+11, */ "fcfb11" "\0"
+ /* ARPHRD_FCFABRIC+12, */ "fcfb12" "\0"
+#endif /* FEATURE_IP_RARE_PROTOCOLS */
+ ;
-__PF(TUNNEL,ipip)
-__PF(TUNNEL6,tunnel6)
-__PF(FRAD,frad)
-__PF(SKIP,skip)
-__PF(LOOPBACK,loopback)
-__PF(LOCALTLK,ltalk)
-__PF(FDDI,fddi)
-__PF(BIF,bif)
-__PF(SIT,sit)
-__PF(IPDDP,ip/ddp)
-__PF(IPGRE,gre)
-__PF(PIMREG,pimreg)
-__PF(HIPPI,hippi)
-__PF(ASH,ash)
-__PF(ECONET,econet)
-__PF(IRDA,irda)
-__PF(FCPP,fcpp)
-__PF(FCAL,fcal)
-__PF(FCPL,fcpl)
-__PF(FCFABRIC,fcfb0)
-__PF(FCFABRIC+1,fcfb1)
-__PF(FCFABRIC+2,fcfb2)
-__PF(FCFABRIC+3,fcfb3)
-__PF(FCFABRIC+4,fcfb4)
-__PF(FCFABRIC+5,fcfb5)
-__PF(FCFABRIC+6,fcfb6)
-__PF(FCFABRIC+7,fcfb7)
-__PF(FCFABRIC+8,fcfb8)
-__PF(FCFABRIC+9,fcfb9)
-__PF(FCFABRIC+10,fcfb10)
-__PF(FCFABRIC+11,fcfb11)
-__PF(FCFABRIC+12,fcfb12)
+ /* Keep these arrays in sync! */
+
+ static const uint16_t arphrd_type[] = {
+ 0, /* "generic" "\0" */
+ ARPHRD_LOOPBACK, /* "loopback" "\0" */
+ ARPHRD_ETHER, /* "ether" "\0" */
+#ifdef ARPHRD_INFINIBAND
+ ARPHRD_INFINIBAND, /* "infiniband" "\0" */
+#endif
#ifdef ARPHRD_IEEE802_TR
-__PF(IEEE802_TR,tr)
+ ARPHRD_IEEE802, /* "ieee802" "\0" */
+ ARPHRD_IEEE802_TR, /* "tr" "\0" */
+#else
+ ARPHRD_IEEE802, /* "tr" "\0" */
#endif
#ifdef ARPHRD_IEEE80211
-__PF(IEEE80211,ieee802.11)
+ ARPHRD_IEEE80211, /* "ieee802.11" "\0" */
+#endif
+#ifdef ARPHRD_IEEE1394
+ ARPHRD_IEEE1394, /* "ieee1394" "\0" */
#endif
+ ARPHRD_IRDA, /* "irda" "\0" */
+ ARPHRD_SLIP, /* "slip" "\0" */
+ ARPHRD_CSLIP, /* "cslip" "\0" */
+ ARPHRD_SLIP6, /* "slip6" "\0" */
+ ARPHRD_CSLIP6, /* "cslip6" "\0" */
+ ARPHRD_PPP, /* "ppp" "\0" */
+ ARPHRD_TUNNEL, /* "ipip" "\0" */
+ ARPHRD_TUNNEL6, /* "tunnel6" "\0" */
+ ARPHRD_SIT, /* "sit" "\0" */
+ ARPHRD_IPGRE, /* "gre" "\0" */
#ifdef ARPHRD_VOID
-__PF(VOID,void)
+ ARPHRD_VOID, /* "void" "\0" */
+#endif
+
+#if ENABLE_FEATURE_IP_RARE_PROTOCOLS
+ ARPHRD_EETHER, /* "eether" "\0" */
+ ARPHRD_AX25, /* "ax25" "\0" */
+ ARPHRD_PRONET, /* "pronet" "\0" */
+ ARPHRD_CHAOS, /* "chaos" "\0" */
+ ARPHRD_ARCNET, /* "arcnet" "\0" */
+ ARPHRD_APPLETLK, /* "atalk" "\0" */
+ ARPHRD_DLCI, /* "dlci" "\0" */
+#ifdef ARPHRD_ATM
+ ARPHRD_ATM, /* "atm" "\0" */
+#endif
+ ARPHRD_METRICOM, /* "metricom" "\0" */
+ ARPHRD_RSRVD, /* "rsrvd" "\0" */
+ ARPHRD_ADAPT, /* "adapt" "\0" */
+ ARPHRD_ROSE, /* "rose" "\0" */
+ ARPHRD_X25, /* "x25" "\0" */
+#ifdef ARPHRD_HWX25
+ ARPHRD_HWX25, /* "hwx25" "\0" */
+#endif
+ ARPHRD_HDLC, /* "hdlc" "\0" */
+ ARPHRD_LAPB, /* "lapb" "\0" */
+#ifdef ARPHRD_DDCMP
+ ARPHRD_DDCMP, /* "ddcmp" "\0" */
+ ARPHRD_RAWHDLC, /* "rawhdlc" "\0" */
#endif
-};
-#undef __PF
+ ARPHRD_FRAD, /* "frad" "\0" */
+ ARPHRD_SKIP, /* "skip" "\0" */
+ ARPHRD_LOCALTLK, /* "ltalk" "\0" */
+ ARPHRD_FDDI, /* "fddi" "\0" */
+ ARPHRD_BIF, /* "bif" "\0" */
+ ARPHRD_IPDDP, /* "ip/ddp" "\0" */
+ ARPHRD_PIMREG, /* "pimreg" "\0" */
+ ARPHRD_HIPPI, /* "hippi" "\0" */
+ ARPHRD_ASH, /* "ash" "\0" */
+ ARPHRD_ECONET, /* "econet" "\0" */
+ ARPHRD_FCPP, /* "fcpp" "\0" */
+ ARPHRD_FCAL, /* "fcal" "\0" */
+ ARPHRD_FCPL, /* "fcpl" "\0" */
+ ARPHRD_FCFABRIC, /* "fcfb0" "\0" */
+ ARPHRD_FCFABRIC+1, /* "fcfb1" "\0" */
+ ARPHRD_FCFABRIC+2, /* "fcfb2" "\0" */
+ ARPHRD_FCFABRIC+3, /* "fcfb3" "\0" */
+ ARPHRD_FCFABRIC+4, /* "fcfb4" "\0" */
+ ARPHRD_FCFABRIC+5, /* "fcfb5" "\0" */
+ ARPHRD_FCFABRIC+6, /* "fcfb6" "\0" */
+ ARPHRD_FCFABRIC+7, /* "fcfb7" "\0" */
+ ARPHRD_FCFABRIC+8, /* "fcfb8" "\0" */
+ ARPHRD_FCFABRIC+9, /* "fcfb9" "\0" */
+ ARPHRD_FCFABRIC+10, /* "fcfb10" "\0" */
+ ARPHRD_FCFABRIC+11, /* "fcfb11" "\0" */
+ ARPHRD_FCFABRIC+12, /* "fcfb12" "\0" */
+#endif /* FEATURE_IP_RARE_PROTOCOLS */
+ };
- int i;
- for (i=0; i<sizeof(arphrd_names)/sizeof(arphrd_names[0]); i++) {
- if (arphrd_names[i].type == type)
- return arphrd_names[i].name;
+ unsigned i;
+ const char *aname = arphrd_name;
+ for (i = 0; i < ARRAY_SIZE(arphrd_type); i++) {
+ if (arphrd_type[i] == type)
+ return aname;
+ aname += strlen(aname) + 1;
}
- snprintf(buf, len, "[%d]", type);
- return buf;
+ snprintf(buf, len, "[%d]", type);
+ return buf;
}
diff --git a/release/src/router/busybox/networking/libiproute/rt_names.c b/release/src/router/busybox/networking/libiproute/rt_names.c
index d503645b..e4d10613 100644
--- a/release/src/router/busybox/networking/libiproute/rt_names.c
+++ b/release/src/router/busybox/networking/libiproute/rt_names.c
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
/*
* rt_names.c rtnetlink names DB.
*
@@ -8,84 +9,66 @@
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
+#include "libbb.h"
+#include "rt_names.h"
-static void rtnl_tab_initialize(char *file, char **tab, int size)
+/* so far all callers have size == 256 */
+#define rtnl_tab_initialize(file, tab, size) rtnl_tab_initialize(file, tab)
+#define size 256
+static void rtnl_tab_initialize(const char *file, const char **tab, int size)
{
- char buf[512];
- FILE *fp;
-
- fp = fopen(file, "r");
- if (!fp)
- return;
- while (fgets(buf, sizeof(buf), fp)) {
- char *p = buf;
- int id;
- char namebuf[512];
-
- while (*p == ' ' || *p == '\t')
- p++;
- if (*p == '#' || *p == '\n' || *p == 0)
- continue;
- if (sscanf(p, "0x%x %s\n", &id, namebuf) != 2 &&
- sscanf(p, "0x%x %s #", &id, namebuf) != 2 &&
- sscanf(p, "%d %s\n", &id, namebuf) != 2 &&
- sscanf(p, "%d %s #", &id, namebuf) != 2) {
- fprintf(stderr, "Database %s is corrupted at %s\n",
- file, p);
- return;
+ char *token[2];
+ parser_t *parser = config_open2(file, fopen_for_read);
+ while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
+ int id = bb_strtou(token[0], NULL, 0);
+ if (id < 0 || id > size) {
+ bb_error_msg("database %s is corrupted at line %d",
+ file, parser->lineno);
+ break;
}
-
- if (id<0 || id>size)
- continue;
-
- tab[id] = strdup(namebuf);
+ tab[id] = xstrdup(token[1]);
}
- fclose(fp);
+ config_close(parser);
}
+#undef size
-
-static char * rtnl_rtprot_tab[256] = {
- "none",
- "redirect",
- "kernel",
- "boot",
- "static",
- NULL,
- NULL,
- NULL,
- "gated",
- "ra",
- "mrt",
- "zebra",
- "bird",
-};
-
-
-
-static int rtnl_rtprot_init;
+static const char **rtnl_rtprot_tab; /* [256] */
static void rtnl_rtprot_initialize(void)
{
- rtnl_rtprot_init = 1;
+ static const char *const init_tab[] = {
+ "none",
+ "redirect",
+ "kernel",
+ "boot",
+ "static",
+ NULL,
+ NULL,
+ NULL,
+ "gated",
+ "ra",
+ "mrt",
+ "zebra",
+ "bird",
+ };
+ if (rtnl_rtprot_tab) return;
+ rtnl_rtprot_tab = xzalloc(256 * sizeof(rtnl_rtprot_tab[0]));
+ memcpy(rtnl_rtprot_tab, init_tab, sizeof(init_tab));
rtnl_tab_initialize("/etc/iproute2/rt_protos",
rtnl_rtprot_tab, 256);
}
-char * rtnl_rtprot_n2a(int id, char *buf, int len)
+
+const char* rtnl_rtprot_n2a(int id, char *buf, int len)
{
- if (id<0 || id>=256) {
+ if (id < 0 || id >= 256) {
snprintf(buf, len, "%d", id);
return buf;
}
- if (!rtnl_rtprot_tab[id]) {
- if (!rtnl_rtprot_init)
- rtnl_rtprot_initialize();
- }
+
+ rtnl_rtprot_initialize();
+
if (rtnl_rtprot_tab[id])
return rtnl_rtprot_tab[id];
snprintf(buf, len, "%d", id);
@@ -94,9 +77,8 @@ char * rtnl_rtprot_n2a(int id, char *buf, int len)
int rtnl_rtprot_a2n(uint32_t *id, char *arg)
{
- static char *cache = NULL;
+ static const char *cache = NULL;
static unsigned long res;
- char *end;
int i;
if (cache && strcmp(cache, arg) == 0) {
@@ -104,10 +86,9 @@ int rtnl_rtprot_a2n(uint32_t *id, char *arg)
return 0;
}
- if (!rtnl_rtprot_init)
- rtnl_rtprot_initialize();
+ rtnl_rtprot_initialize();
- for (i=0; i<256; i++) {
+ for (i = 0; i < 256; i++) {
if (rtnl_rtprot_tab[i] &&
strcmp(rtnl_rtprot_tab[i], arg) == 0) {
cache = rtnl_rtprot_tab[i];
@@ -117,24 +98,21 @@ int rtnl_rtprot_a2n(uint32_t *id, char *arg)
}
}
- res = strtoul(arg, &end, 0);
- if (!end || end == arg || *end || res > 255)
+ res = bb_strtoul(arg, NULL, 0);
+ if (errno || res > 255)
return -1;
*id = res;
return 0;
}
-
-static char * rtnl_rtscope_tab[256] = {
- "global",
-};
-
-static int rtnl_rtscope_init;
+static const char **rtnl_rtscope_tab; /* [256] */
static void rtnl_rtscope_initialize(void)
{
- rtnl_rtscope_init = 1;
+ if (rtnl_rtscope_tab) return;
+ rtnl_rtscope_tab = xzalloc(256 * sizeof(rtnl_rtscope_tab[0]));
+ rtnl_rtscope_tab[0] = "global";
rtnl_rtscope_tab[255] = "nowhere";
rtnl_rtscope_tab[254] = "host";
rtnl_rtscope_tab[253] = "link";
@@ -143,16 +121,16 @@ static void rtnl_rtscope_initialize(void)
rtnl_rtscope_tab, 256);
}
-char * rtnl_rtscope_n2a(int id, char *buf, int len)
+
+const char* rtnl_rtscope_n2a(int id, char *buf, int len)
{
- if (id<0 || id>=256) {
+ if (id < 0 || id >= 256) {
snprintf(buf, len, "%d", id);
return buf;
}
- if (!rtnl_rtscope_tab[id]) {
- if (!rtnl_rtscope_init)
- rtnl_rtscope_initialize();
- }
+
+ rtnl_rtscope_initialize();
+
if (rtnl_rtscope_tab[id])
return rtnl_rtscope_tab[id];
snprintf(buf, len, "%d", id);
@@ -161,9 +139,8 @@ char * rtnl_rtscope_n2a(int id, char *buf, int len)
int rtnl_rtscope_a2n(uint32_t *id, char *arg)
{
- static char *cache = NULL;
+ static const char *cache = NULL;
static unsigned long res;
- char *end;
int i;
if (cache && strcmp(cache, arg) == 0) {
@@ -171,10 +148,9 @@ int rtnl_rtscope_a2n(uint32_t *id, char *arg)
return 0;
}
- if (!rtnl_rtscope_init)
- rtnl_rtscope_initialize();
+ rtnl_rtscope_initialize();
- for (i=0; i<256; i++) {
+ for (i = 0; i < 256; i++) {
if (rtnl_rtscope_tab[i] &&
strcmp(rtnl_rtscope_tab[i], arg) == 0) {
cache = rtnl_rtscope_tab[i];
@@ -184,50 +160,30 @@ int rtnl_rtscope_a2n(uint32_t *id, char *arg)
}
}
- res = strtoul(arg, &end, 0);
- if (!end || end == arg || *end || res > 255)
+ res = bb_strtoul(arg, NULL, 0);
+ if (errno || res > 255)
return -1;
*id = res;
return 0;
}
-
-static char * rtnl_rtrealm_tab[256] = {
- "unknown",
-};
-
-static int rtnl_rtrealm_init;
+static const char **rtnl_rtrealm_tab; /* [256] */
static void rtnl_rtrealm_initialize(void)
{
- rtnl_rtrealm_init = 1;
+ if (rtnl_rtrealm_tab) return;
+ rtnl_rtrealm_tab = xzalloc(256 * sizeof(rtnl_rtrealm_tab[0]));
+ rtnl_rtrealm_tab[0] = "unknown";
rtnl_tab_initialize("/etc/iproute2/rt_realms",
rtnl_rtrealm_tab, 256);
}
-char * rtnl_rtrealm_n2a(int id, char *buf, int len)
-{
- if (id<0 || id>=256) {
- snprintf(buf, len, "%d", id);
- return buf;
- }
- if (!rtnl_rtrealm_tab[id]) {
- if (!rtnl_rtrealm_init)
- rtnl_rtrealm_initialize();
- }
- if (rtnl_rtrealm_tab[id])
- return rtnl_rtrealm_tab[id];
- snprintf(buf, len, "%d", id);
- return buf;
-}
-
int rtnl_rtrealm_a2n(uint32_t *id, char *arg)
{
- static char *cache = NULL;
+ static const char *cache = NULL;
static unsigned long res;
- char *end;
int i;
if (cache && strcmp(cache, arg) == 0) {
@@ -235,10 +191,9 @@ int rtnl_rtrealm_a2n(uint32_t *id, char *arg)
return 0;
}
- if (!rtnl_rtrealm_init)
- rtnl_rtrealm_initialize();
+ rtnl_rtrealm_initialize();
- for (i=0; i<256; i++) {
+ for (i = 0; i < 256; i++) {
if (rtnl_rtrealm_tab[i] &&
strcmp(rtnl_rtrealm_tab[i], arg) == 0) {
cache = rtnl_rtrealm_tab[i];
@@ -248,51 +203,63 @@ int rtnl_rtrealm_a2n(uint32_t *id, char *arg)
}
}
- res = strtoul(arg, &end, 0);
- if (!end || end == arg || *end || res > 255)
+ res = bb_strtoul(arg, NULL, 0);
+ if (errno || res > 255)
return -1;
*id = res;
return 0;
}
+#if ENABLE_FEATURE_IP_RULE
+const char* rtnl_rtrealm_n2a(int id, char *buf, int len)
+{
+ if (id < 0 || id >= 256) {
+ snprintf(buf, len, "%d", id);
+ return buf;
+ }
+
+ rtnl_rtrealm_initialize();
+ if (rtnl_rtrealm_tab[id])
+ return rtnl_rtrealm_tab[id];
+ snprintf(buf, len, "%d", id);
+ return buf;
+}
+#endif
-static char * rtnl_rttable_tab[256] = {
- "unspec",
-};
-static int rtnl_rttable_init;
+static const char **rtnl_rtdsfield_tab; /* [256] */
-static void rtnl_rttable_initialize(void)
+static void rtnl_rtdsfield_initialize(void)
{
- rtnl_rttable_init = 1;
- rtnl_rttable_tab[255] = "local";
- rtnl_rttable_tab[254] = "main";
- rtnl_tab_initialize("/etc/iproute2/rt_tables",
- rtnl_rttable_tab, 256);
+ if (rtnl_rtdsfield_tab) return;
+ rtnl_rtdsfield_tab = xzalloc(256 * sizeof(rtnl_rtdsfield_tab[0]));
+ rtnl_rtdsfield_tab[0] = "0";
+ rtnl_tab_initialize("/etc/iproute2/rt_dsfield",
+ rtnl_rtdsfield_tab, 256);
}
-char * rtnl_rttable_n2a(int id, char *buf, int len)
+
+const char * rtnl_dsfield_n2a(int id, char *buf, int len)
{
- if (id<0 || id>=256) {
+ if (id < 0 || id >= 256) {
snprintf(buf, len, "%d", id);
return buf;
}
- if (!rtnl_rttable_tab[id]) {
- if (!rtnl_rttable_init)
- rtnl_rttable_initialize();
- }
- if (rtnl_rttable_tab[id])
- return rtnl_rttable_tab[id];
- snprintf(buf, len, "%d", id);
+
+ rtnl_rtdsfield_initialize();
+
+ if (rtnl_rtdsfield_tab[id])
+ return rtnl_rtdsfield_tab[id];
+ snprintf(buf, len, "0x%02x", id);
return buf;
}
-int rtnl_rttable_a2n(uint32_t *id, char *arg)
+
+int rtnl_dsfield_a2n(uint32_t *id, char *arg)
{
- static char *cache = NULL;
+ static const char *cache = NULL;
static unsigned long res;
- char *end;
int i;
if (cache && strcmp(cache, arg) == 0) {
@@ -300,62 +267,60 @@ int rtnl_rttable_a2n(uint32_t *id, char *arg)
return 0;
}
- if (!rtnl_rttable_init)
- rtnl_rttable_initialize();
+ rtnl_rtdsfield_initialize();
- for (i=0; i<256; i++) {
- if (rtnl_rttable_tab[i] &&
- strcmp(rtnl_rttable_tab[i], arg) == 0) {
- cache = rtnl_rttable_tab[i];
+ for (i = 0; i < 256; i++) {
+ if (rtnl_rtdsfield_tab[i] &&
+ strcmp(rtnl_rtdsfield_tab[i], arg) == 0) {
+ cache = rtnl_rtdsfield_tab[i];
res = i;
*id = res;
return 0;
}
}
- i = strtoul(arg, &end, 0);
- if (!end || end == arg || *end || i > 255)
+ res = bb_strtoul(arg, NULL, 16);
+ if (errno || res > 255)
return -1;
- *id = i;
+ *id = res;
return 0;
}
-static char * rtnl_rtdsfield_tab[256] = {
- "0",
-};
+#if ENABLE_FEATURE_IP_RULE
+static const char **rtnl_rttable_tab; /* [256] */
-static int rtnl_rtdsfield_init;
-
-static void rtnl_rtdsfield_initialize(void)
+static void rtnl_rttable_initialize(void)
{
- rtnl_rtdsfield_init = 1;
- rtnl_tab_initialize("/etc/iproute2/rt_dsfield",
- rtnl_rtdsfield_tab, 256);
+ if (rtnl_rtdsfield_tab) return;
+ rtnl_rttable_tab = xzalloc(256 * sizeof(rtnl_rttable_tab[0]));
+ rtnl_rttable_tab[0] = "unspec";
+ rtnl_rttable_tab[255] = "local";
+ rtnl_rttable_tab[254] = "main";
+ rtnl_rttable_tab[253] = "default";
+ rtnl_tab_initialize("/etc/iproute2/rt_tables", rtnl_rttable_tab, 256);
}
-char * rtnl_dsfield_n2a(int id, char *buf, int len)
+
+const char *rtnl_rttable_n2a(int id, char *buf, int len)
{
- if (id<0 || id>=256) {
+ if (id < 0 || id >= 256) {
snprintf(buf, len, "%d", id);
return buf;
}
- if (!rtnl_rtdsfield_tab[id]) {
- if (!rtnl_rtdsfield_init)
- rtnl_rtdsfield_initialize();
- }
- if (rtnl_rtdsfield_tab[id])
- return rtnl_rtdsfield_tab[id];
- snprintf(buf, len, "0x%02x", id);
+
+ rtnl_rttable_initialize();
+
+ if (rtnl_rttable_tab[id])
+ return rtnl_rttable_tab[id];
+ snprintf(buf, len, "%d", id);
return buf;
}
-
-int rtnl_dsfield_a2n(uint32_t *id, char *arg)
+int rtnl_rttable_a2n(uint32_t * id, char *arg)
{
static char *cache = NULL;
static unsigned long res;
- char *end;
int i;
if (cache && strcmp(cache, arg) == 0) {
@@ -363,23 +328,22 @@ int rtnl_dsfield_a2n(uint32_t *id, char *arg)
return 0;
}
- if (!rtnl_rtdsfield_init)
- rtnl_rtdsfield_initialize();
+ rtnl_rttable_initialize();
- for (i=0; i<256; i++) {
- if (rtnl_rtdsfield_tab[i] &&
- strcmp(rtnl_rtdsfield_tab[i], arg) == 0) {
- cache = rtnl_rtdsfield_tab[i];
+ for (i = 0; i < 256; i++) {
+ if (rtnl_rttable_tab[i] && strcmp(rtnl_rttable_tab[i], arg) == 0) {
+ cache = (char*)rtnl_rttable_tab[i];
res = i;
*id = res;
return 0;
}
}
- res = strtoul(arg, &end, 16);
- if (!end || end == arg || *end || res > 255)
+ i = bb_strtoul(arg, NULL, 0);
+ if (errno || i > 255)
return -1;
- *id = res;
+ *id = i;
return 0;
}
+#endif
diff --git a/release/src/router/busybox/networking/libiproute/rt_names.h b/release/src/router/busybox/networking/libiproute/rt_names.h
index 97bc6169..a2d4fd14 100644
--- a/release/src/router/busybox/networking/libiproute/rt_names.h
+++ b/release/src/router/busybox/networking/libiproute/rt_names.h
@@ -1,30 +1,29 @@
-#ifndef RT_NAMES_H_
-#define RT_NAMES_H_ 1
+/* vi: set sw=4 ts=4: */
+#ifndef RT_NAMES_H
+#define RT_NAMES_H 1
-#include <stdint.h>
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
-const char* rtnl_rtprot_n2a(int id, char *buf, int len);
-const char* rtnl_rtscope_n2a(int id, char *buf, int len);
-const char* rtnl_rttable_n2a(int id, char *buf, int len);
-const char* rtnl_rtrealm_n2a(int id, char *buf, int len);
-const char* rtnl_dsfield_n2a(int id, char *buf, int len);
-int rtnl_rtprot_a2n(int *id, char *arg);
-int rtnl_rtscope_a2n(int *id, char *arg);
-int rtnl_rttable_a2n(int *id, char *arg);
-int rtnl_rtrealm_a2n(uint32_t *id, char *arg);
-int rtnl_dsfield_a2n(uint32_t *id, char *arg);
+extern const char* rtnl_rtprot_n2a(int id, char *buf, int len);
+extern const char* rtnl_rtscope_n2a(int id, char *buf, int len);
+extern const char* rtnl_rtrealm_n2a(int id, char *buf, int len);
+extern const char* rtnl_dsfield_n2a(int id, char *buf, int len);
+extern const char* rtnl_rttable_n2a(int id, char *buf, int len);
+extern int rtnl_rtprot_a2n(uint32_t *id, char *arg);
+extern int rtnl_rtscope_a2n(uint32_t *id, char *arg);
+extern int rtnl_rtrealm_a2n(uint32_t *id, char *arg);
+extern int rtnl_dsfield_a2n(uint32_t *id, char *arg);
+extern int rtnl_rttable_a2n(uint32_t *id, char *arg);
-const char *inet_proto_n2a(int proto, char *buf, int len);
-int inet_proto_a2n(char *buf);
+extern const char* ll_type_n2a(int type, char *buf, int len);
+extern const char* ll_addr_n2a(unsigned char *addr, int alen, int type,
+ char *buf, int blen);
+extern int ll_addr_a2n(unsigned char *lladdr, int len, char *arg);
-const char * ll_type_n2a(int type, char *buf, int len);
-
-const char *ll_addr_n2a(unsigned char *addr, int alen, int type, char *buf, int blen);
-int ll_addr_a2n(unsigned char *lladdr, int len, char *arg);
-
-const char * ll_proto_n2a(unsigned short id, char *buf, int len);
-int ll_proto_a2n(unsigned short *id, char *buf);
+extern const char* ll_proto_n2a(unsigned short id, char *buf, int len);
+extern int ll_proto_a2n(unsigned short *id, char *buf);
+POP_SAVED_FUNCTION_VISIBILITY
#endif
diff --git a/release/src/router/busybox/networking/libiproute/rtm_map.c b/release/src/router/busybox/networking/libiproute/rtm_map.c
index 5f6a9e69..ca2f4436 100644
--- a/release/src/router/busybox/networking/libiproute/rtm_map.c
+++ b/release/src/router/busybox/networking/libiproute/rtm_map.c
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
/*
* rtm_map.c
*
@@ -10,13 +11,11 @@
*
*/
-#include <stdlib.h>
-#include <string.h>
-
+#include "libbb.h"
#include "rt_names.h"
#include "utils.h"
-char *rtnl_rtntype_n2a(int id, char *buf, int len)
+const char *rtnl_rtntype_n2a(int id, char *buf, int len)
{
switch (id) {
case RTN_UNSPEC:
@@ -52,31 +51,40 @@ char *rtnl_rtntype_n2a(int id, char *buf, int len)
int rtnl_rtntype_a2n(int *id, char *arg)
{
+ static const char keywords[] ALIGN1 =
+ "local\0""nat\0""broadcast\0""brd\0""anycast\0"
+ "multicast\0""prohibit\0""unreachable\0""blackhole\0"
+ "xresolve\0""unicast\0""throw\0";
+ enum {
+ ARG_local = 1, ARG_nat, ARG_broadcast, ARG_brd, ARG_anycast,
+ ARG_multicast, ARG_prohibit, ARG_unreachable, ARG_blackhole,
+ ARG_xresolve, ARG_unicast, ARG_throw
+ };
+ const smalluint key = index_in_substrings(keywords, arg) + 1;
char *end;
unsigned long res;
- if (strcmp(arg, "local") == 0)
+ if (key == ARG_local)
res = RTN_LOCAL;
- else if (strcmp(arg, "nat") == 0)
+ else if (key == ARG_nat)
res = RTN_NAT;
- else if (matches(arg, "broadcast") == 0 ||
- strcmp(arg, "brd") == 0)
+ else if (key == ARG_broadcast || key == ARG_brd)
res = RTN_BROADCAST;
- else if (matches(arg, "anycast") == 0)
+ else if (key == ARG_anycast)
res = RTN_ANYCAST;
- else if (matches(arg, "multicast") == 0)
+ else if (key == ARG_multicast)
res = RTN_MULTICAST;
- else if (matches(arg, "prohibit") == 0)
+ else if (key == ARG_prohibit)
res = RTN_PROHIBIT;
- else if (matches(arg, "unreachable") == 0)
+ else if (key == ARG_unreachable)
res = RTN_UNREACHABLE;
- else if (matches(arg, "blackhole") == 0)
+ else if (key == ARG_blackhole)
res = RTN_BLACKHOLE;
- else if (matches(arg, "xresolve") == 0)
+ else if (key == ARG_xresolve)
res = RTN_XRESOLVE;
- else if (matches(arg, "unicast") == 0)
+ else if (key == ARG_unicast)
res = RTN_UNICAST;
- else if (strcmp(arg, "throw") == 0)
+ else if (key == ARG_throw)
res = RTN_THROW;
else {
res = strtoul(arg, &end, 0);
@@ -87,9 +95,9 @@ int rtnl_rtntype_a2n(int *id, char *arg)
return 0;
}
-int get_rt_realms(__u32 *realms, char *arg)
+int get_rt_realms(uint32_t *realms, char *arg)
{
- __u32 realm = 0;
+ uint32_t realm = 0;
char *p = strchr(arg, '/');
*realms = 0;
diff --git a/release/src/router/busybox/networking/libiproute/rtm_map.h b/release/src/router/busybox/networking/libiproute/rtm_map.h
index 70bda7d0..ab1b70e4 100644
--- a/release/src/router/busybox/networking/libiproute/rtm_map.h
+++ b/release/src/router/busybox/networking/libiproute/rtm_map.h
@@ -1,10 +1,14 @@
-#ifndef __RTM_MAP_H__
-#define __RTM_MAP_H__ 1
+/* vi: set sw=4 ts=4: */
+#ifndef RTM_MAP_H
+#define RTM_MAP_H 1
-char *rtnl_rtntype_n2a(int id, char *buf, int len);
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
+
+const char *rtnl_rtntype_n2a(int id, char *buf, int len);
int rtnl_rtntype_a2n(int *id, char *arg);
-int get_rt_realms(__u32 *realms, char *arg);
+int get_rt_realms(uint32_t *realms, char *arg);
+POP_SAVED_FUNCTION_VISIBILITY
-#endif /* __RTM_MAP_H__ */
+#endif
diff --git a/release/src/router/busybox/networking/libiproute/utils.c b/release/src/router/busybox/networking/libiproute/utils.c
index fa154860..c84d018e 100644
--- a/release/src/router/busybox/networking/libiproute/utils.c
+++ b/release/src/router/busybox/networking/libiproute/utils.c
@@ -1,135 +1,70 @@
+/* vi: set sw=4 ts=4: */
/*
* utils.c
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
- *
* Changes:
*
* Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
*/
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-
-#include "utils.h"
#include "libbb.h"
+#include "utils.h"
+#include "inet_common.h"
-int get_integer(int *val, char *arg, int base)
-{
- long res;
- char *ptr;
-
- if (!arg || !*arg)
- return -1;
- res = strtol(arg, &ptr, base);
- if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
- return -1;
- *val = res;
- return 0;
-}
-
-int get_unsigned(unsigned *val, char *arg, int base)
-{
- unsigned long res;
- char *ptr;
-
- if (!arg || !*arg)
- return -1;
- res = strtoul(arg, &ptr, base);
- if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
- return -1;
- *val = res;
- return 0;
-}
-
-int get_u32(__u32 * val, char *arg, int base)
+unsigned get_unsigned(char *arg, const char *errmsg)
{
unsigned long res;
char *ptr;
- if (!arg || !*arg)
- return -1;
- res = strtoul(arg, &ptr, base);
- if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
- return -1;
- *val = res;
- return 0;
+ if (*arg) {
+ res = strtoul(arg, &ptr, 0);
+ if (!*ptr && res <= UINT_MAX) {
+ return res;
+ }
+ }
+ invarg(arg, errmsg); /* does not return */
}
-int get_u16(__u16 * val, char *arg, int base)
+uint32_t get_u32(char *arg, const char *errmsg)
{
unsigned long res;
char *ptr;
- if (!arg || !*arg)
- return -1;
- res = strtoul(arg, &ptr, base);
- if (!ptr || ptr == arg || *ptr || res > 0xFFFF)
- return -1;
- *val = res;
- return 0;
+ if (*arg) {
+ res = strtoul(arg, &ptr, 0);
+ if (!*ptr && res <= 0xFFFFFFFFUL) {
+ return res;
+ }
+ }
+ invarg(arg, errmsg); /* does not return */
}
-int get_u8(__u8 * val, char *arg, int base)
+uint16_t get_u16(char *arg, const char *errmsg)
{
unsigned long res;
char *ptr;
- if (!arg || !*arg)
- return -1;
- res = strtoul(arg, &ptr, base);
- if (!ptr || ptr == arg || *ptr || res > 0xFF)
- return -1;
- *val = res;
- return 0;
-}
-
-int get_s16(__s16 * val, char *arg, int base)
-{
- long res;
- char *ptr;
-
- if (!arg || !*arg)
- return -1;
- res = strtol(arg, &ptr, base);
- if (!ptr || ptr == arg || *ptr || res > 0x7FFF || res < -0x8000)
- return -1;
- *val = res;
- return 0;
-}
-
-int get_s8(__s8 * val, char *arg, int base)
-{
- long res;
- char *ptr;
-
- if (!arg || !*arg)
- return -1;
- res = strtol(arg, &ptr, base);
- if (!ptr || ptr == arg || *ptr || res > 0x7F || res < -0x80)
- return -1;
- *val = res;
- return 0;
+ if (*arg) {
+ res = strtoul(arg, &ptr, 0);
+ if (!*ptr && res <= 0xFFFF) {
+ return res;
+ }
+ }
+ invarg(arg, errmsg); /* does not return */
}
-int get_addr_1(inet_prefix * addr, char *name, int family)
+int get_addr_1(inet_prefix *addr, char *name, int family)
{
- char *cp;
- unsigned char *ap = (unsigned char *) addr->data;
- int i;
-
memset(addr, 0, sizeof(*addr));
- if (strcmp(name, "default") == 0 ||
- strcmp(name, "all") == 0 || strcmp(name, "any") == 0) {
+ if (strcmp(name, bb_str_default) == 0
+ || strcmp(name, "all") == 0
+ || strcmp(name, "any") == 0
+ ) {
addr->family = family;
addr->bytelen = (family == AF_INET6 ? 16 : 4);
addr->bitlen = -1;
@@ -150,21 +85,14 @@ int get_addr_1(inet_prefix * addr, char *name, int family)
addr->family = AF_INET;
if (family != AF_UNSPEC && family != AF_INET)
return -1;
+ if (inet_pton(AF_INET, name, addr->data) <= 0)
+ return -1;
addr->bytelen = 4;
addr->bitlen = -1;
- for (cp = name, i = 0; *cp; cp++) {
- if (*cp <= '9' && *cp >= '0') {
- ap[i] = 10 * ap[i] + (*cp - '0');
- continue;
- }
- if (*cp == '.' && ++i <= 3)
- continue;
- return -1;
- }
return 0;
}
-int get_prefix_1(inet_prefix * dst, char *arg, int family)
+static int get_prefix_1(inet_prefix *dst, char *arg, int family)
{
int err;
unsigned plen;
@@ -172,111 +100,114 @@ int get_prefix_1(inet_prefix * dst, char *arg, int family)
memset(dst, 0, sizeof(*dst));
- if (strcmp(arg, "default") == 0 || strcmp(arg, "any") == 0) {
+ if (strcmp(arg, bb_str_default) == 0
+ || strcmp(arg, "all") == 0
+ || strcmp(arg, "any") == 0
+ ) {
dst->family = family;
- dst->bytelen = 0;
- dst->bitlen = 0;
+ /*dst->bytelen = 0; - done by memset */
+ /*dst->bitlen = 0;*/
return 0;
}
slash = strchr(arg, '/');
if (slash)
- *slash = 0;
+ *slash = '\0';
err = get_addr_1(dst, arg, family);
if (err == 0) {
- switch (dst->family) {
- case AF_INET6:
- dst->bitlen = 128;
- break;
- default:
- case AF_INET:
- dst->bitlen = 32;
- }
+ dst->bitlen = (dst->family == AF_INET6) ? 128 : 32;
if (slash) {
- if (get_integer(&plen, slash + 1, 0) || plen > dst->bitlen) {
+ inet_prefix netmask_pfx;
+
+ netmask_pfx.family = AF_UNSPEC;
+ plen = bb_strtou(slash + 1, NULL, 0);
+ if ((errno || plen > dst->bitlen)
+ && (get_addr_1(&netmask_pfx, slash + 1, family)))
err = -1;
- goto done;
+ else if (netmask_pfx.family == AF_INET) {
+ /* fill in prefix length of dotted quad */
+ uint32_t mask = ntohl(netmask_pfx.data[0]);
+ uint32_t host = ~mask;
+
+ /* a valid netmask must be 2^n - 1 */
+ if (!(host & (host + 1))) {
+ for (plen = 0; mask; mask <<= 1)
+ ++plen;
+ if (plen >= 0 && plen <= dst->bitlen) {
+ dst->bitlen = plen;
+ /* dst->flags |= PREFIXLEN_SPECIFIED; */
+ } else
+ err = -1;
+ } else
+ err = -1;
+ } else {
+ /* plain prefix */
+ dst->bitlen = plen;
}
- dst->bitlen = plen;
}
}
- done:
if (slash)
*slash = '/';
return err;
}
-int get_addr(inet_prefix * dst, char *arg, int family)
+int get_addr(inet_prefix *dst, char *arg, int family)
{
if (family == AF_PACKET) {
- bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context.", arg);
+ bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "address");
}
if (get_addr_1(dst, arg, family)) {
- bb_error_msg_and_die("an inet address is expected rather than \"%s\".", arg);
+ bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "address", arg);
}
return 0;
}
-int get_prefix(inet_prefix * dst, char *arg, int family)
+int get_prefix(inet_prefix *dst, char *arg, int family)
{
if (family == AF_PACKET) {
- bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context.", arg);
+ bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "prefix");
}
if (get_prefix_1(dst, arg, family)) {
- bb_error_msg_and_die("an inet address is expected rather than \"%s\".", arg);
+ bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "prefix", arg);
}
return 0;
}
-__u32 get_addr32(char *name)
+uint32_t get_addr32(char *name)
{
inet_prefix addr;
if (get_addr_1(&addr, name, AF_INET)) {
- bb_error_msg_and_die("an IP address is expected rather than \"%s\"", name);
+ bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "IP", "address", name);
}
return addr.data[0];
}
-void incomplete_command()
+void incomplete_command(void)
{
- bb_error_msg("Command line is not complete. Try option \"help\"");
- exit(-1);
+ bb_error_msg_and_die("command line is not complete, try option \"help\"");
}
-void invarg(char *msg, char *arg)
+void invarg(const char *arg, const char *opt)
{
- bb_error_msg("argument \"%s\" is wrong: %s", arg, msg);
- exit(-1);
+ bb_error_msg_and_die(bb_msg_invalid_arg, arg, opt);
}
-void duparg(char *key, char *arg)
+void duparg(const char *key, const char *arg)
{
- bb_error_msg("duplicate \"%s\": \"%s\" is the second value.", key, arg);
- exit(-1);
+ bb_error_msg_and_die("duplicate \"%s\": \"%s\" is the second value", key, arg);
}
-void duparg2(char *key, char *arg)
+void duparg2(const char *key, const char *arg)
{
- bb_error_msg("either \"%s\" is duplicate, or \"%s\" is a garbage.", key, arg);
- exit(-1);
+ bb_error_msg_and_die("either \"%s\" is duplicate, or \"%s\" is garbage", key, arg);
}
-int matches(char *cmd, char *pattern)
+int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits)
{
- int len = strlen(cmd);
-
- if (len > strlen(pattern)) {
- return -1;
- }
- return memcmp(pattern, cmd, len);
-}
-
-int inet_addr_match(inet_prefix * a, inet_prefix * b, int bits)
-{
- __u32 *a1 = a->data;
- __u32 *a2 = b->data;
- int words = bits >> 0x05;
+ uint32_t *a1 = a->data;
+ uint32_t *a2 = b->data;
+ int words = bits >> 5;
bits &= 0x1f;
@@ -285,8 +216,8 @@ int inet_addr_match(inet_prefix * a, inet_prefix * b, int bits)
return -1;
if (bits) {
- __u32 w1, w2;
- __u32 mask;
+ uint32_t w1, w2;
+ uint32_t mask;
w1 = a1[words];
w2 = a2[words];
@@ -300,27 +231,8 @@ int inet_addr_match(inet_prefix * a, inet_prefix * b, int bits)
return 0;
}
-int __iproute2_hz_internal;
-
-int __get_hz(void)
-{
- int hz = 0;
- FILE *fp = fopen("/proc/net/psched", "r");
-
- if (fp) {
- unsigned nom, denom;
-
- if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
- if (nom == 1000000)
- hz = denom;
- fclose(fp);
- }
- if (hz)
- return hz;
- return sysconf(_SC_CLK_TCK);
-}
-
-const char *rt_addr_n2a(int af, int len, void *addr, char *buf, int buflen)
+const char *rt_addr_n2a(int af,
+ void *addr, char *buf, int buflen)
{
switch (af) {
case AF_INET:
@@ -331,10 +243,9 @@ const char *rt_addr_n2a(int af, int len, void *addr, char *buf, int buflen)
}
}
-
+#ifdef RESOLVE_HOSTNAMES
const char *format_host(int af, int len, void *addr, char *buf, int buflen)
{
-#ifdef RESOLVE_HOSTNAMES
if (resolve_hosts) {
struct hostent *h_ent;
@@ -349,11 +260,14 @@ const char *format_host(int af, int len, void *addr, char *buf, int buflen)
default:;
}
}
- if (len > 0 && (h_ent = gethostbyaddr(addr, len, af)) != NULL) {
- snprintf(buf, buflen - 1, "%s", h_ent->h_name);
- return buf;
+ if (len > 0) {
+ h_ent = gethostbyaddr(addr, len, af);
+ if (h_ent != NULL) {
+ safe_strncpy(buf, h_ent->h_name, buflen);
+ return buf;
+ }
}
}
-#endif
- return rt_addr_n2a(af, len, addr, buf, buflen);
+ return rt_addr_n2a(af, addr, buf, buflen);
}
+#endif
diff --git a/release/src/router/busybox/networking/libiproute/utils.h b/release/src/router/busybox/networking/libiproute/utils.h
index dc28c1b6..ed03e785 100644
--- a/release/src/router/busybox/networking/libiproute/utils.h
+++ b/release/src/router/busybox/networking/libiproute/utils.h
@@ -1,20 +1,20 @@
-#ifndef __UTILS_H__
-#define __UTILS_H__ 1
-
-#include <asm/types.h>
-#include <resolv.h>
+/* vi: set sw=4 ts=4: */
+#ifndef UTILS_H
+#define UTILS_H 1
#include "libnetlink.h"
#include "ll_map.h"
#include "rtm_map.h"
-extern int preferred_family;
-extern int show_stats;
-extern int show_details;
-extern int show_raw;
-extern int resolve_hosts;
-extern int oneline;
-extern char * _SL_;
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
+
+extern family_t preferred_family;
+extern smallint show_stats; /* UNUSED */
+extern smallint show_details; /* UNUSED */
+extern smallint show_raw; /* UNUSED */
+extern smallint resolve_hosts; /* UNUSED */
+extern smallint oneline;
+extern char _SL_;
#ifndef IPPROTO_ESP
#define IPPROTO_ESP 50
@@ -26,61 +26,58 @@ extern char * _SL_;
#define SPRINT_BSIZE 64
#define SPRINT_BUF(x) char x[SPRINT_BSIZE]
-extern void incomplete_command(void) __attribute__((noreturn));
+extern void incomplete_command(void) NORETURN;
-#define NEXT_ARG() do { argv++; if (--argc <= 0) incomplete_command(); } while(0)
+#define NEXT_ARG() do { if (!*++argv) incomplete_command(); } while (0)
-typedef struct
-{
- __u8 family;
- __u8 bytelen;
- __s16 bitlen;
- __u32 data[4];
+typedef struct {
+ uint8_t family;
+ uint8_t bytelen;
+ int16_t bitlen;
+ uint32_t data[4];
} inet_prefix;
+#define PREFIXLEN_SPECIFIED 1
+
#define DN_MAXADDL 20
#ifndef AF_DECnet
#define AF_DECnet 12
#endif
-struct dn_naddr
-{
- unsigned short a_len;
- unsigned char a_addr[DN_MAXADDL];
+struct dn_naddr {
+ unsigned short a_len;
+ unsigned char a_addr[DN_MAXADDL];
};
#define IPX_NODE_LEN 6
struct ipx_addr {
- u_int32_t ipx_net;
- u_int8_t ipx_node[IPX_NODE_LEN];
+ uint32_t ipx_net;
+ uint8_t ipx_node[IPX_NODE_LEN];
};
-extern __u32 get_addr32(char *name);
+extern uint32_t get_addr32(char *name);
extern int get_addr_1(inet_prefix *dst, char *arg, int family);
-extern int get_prefix_1(inet_prefix *dst, char *arg, int family);
+/*extern int get_prefix_1(inet_prefix *dst, char *arg, int family);*/
extern int get_addr(inet_prefix *dst, char *arg, int family);
extern int get_prefix(inet_prefix *dst, char *arg, int family);
-extern int get_integer(int *val, char *arg, int base);
-extern int get_unsigned(unsigned *val, char *arg, int base);
-#define get_byte get_u8
-#define get_ushort get_u16
-#define get_short get_s16
-extern int get_u32(__u32 *val, char *arg, int base);
-extern int get_u16(__u16 *val, char *arg, int base);
-extern int get_s16(__s16 *val, char *arg, int base);
-extern int get_u8(__u8 *val, char *arg, int base);
-extern int get_s8(__s8 *val, char *arg, int base);
+extern unsigned get_unsigned(char *arg, const char *errmsg);
+extern uint32_t get_u32(char *arg, const char *errmsg);
+extern uint16_t get_u16(char *arg, const char *errmsg);
+extern const char *rt_addr_n2a(int af, void *addr, char *buf, int buflen);
+#ifdef RESOLVE_HOSTNAMES
extern const char *format_host(int af, int len, void *addr, char *buf, int buflen);
-extern const char *rt_addr_n2a(int af, int len, void *addr, char *buf, int buflen);
+#else
+#define format_host(af, len, addr, buf, buflen) \
+ rt_addr_n2a(af, addr, buf, buflen)
+#endif
-void invarg(char *, char *) __attribute__((noreturn));
-void duparg(char *, char *) __attribute__((noreturn));
-void duparg2(char *, char *) __attribute__((noreturn));
-int matches(char *arg, char *pattern);
-extern int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits);
+void invarg(const char *, const char *) NORETURN;
+void duparg(const char *, const char *) NORETURN;
+void duparg2(const char *, const char *) NORETURN;
+int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits);
const char *dnet_ntop(int af, const void *addr, char *str, size_t len);
int dnet_pton(int af, const char *src, void *addr);
@@ -88,14 +85,6 @@ int dnet_pton(int af, const char *src, void *addr);
const char *ipx_ntop(int af, const void *addr, char *str, size_t len);
int ipx_pton(int af, const char *src, void *addr);
-extern int __iproute2_hz_internal;
-extern int __get_hz(void);
-
-static __inline__ int get_hz(void)
-{
- if (__iproute2_hz_internal == 0)
- __iproute2_hz_internal = __get_hz();
- return __iproute2_hz_internal;
-}
+POP_SAVED_FUNCTION_VISIBILITY
-#endif /* __UTILS_H__ */
+#endif