From 4aca87515a5083ae0e31ce3177189fd43b6d05ac Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 3 Jan 2015 13:58:15 +0100 Subject: patch to Vanilla Tomato 1.28 --- .../router/busybox/networking/libiproute/Kbuild | 64 +++ .../router/busybox/networking/libiproute/Makefile | 30 - .../busybox/networking/libiproute/Makefile.in | 44 -- .../busybox/networking/libiproute/ip_common.h | 49 +- .../networking/libiproute/ip_parse_common_args.c | 98 ++-- .../busybox/networking/libiproute/ipaddress.c | 408 ++++++-------- .../router/busybox/networking/libiproute/iplink.c | 334 +++++------ .../router/busybox/networking/libiproute/iproute.c | 608 +++++++++++---------- .../router/busybox/networking/libiproute/iprule.c | 330 +++++++++++ .../busybox/networking/libiproute/iptunnel.c | 448 ++++++++------- .../busybox/networking/libiproute/libnetlink.c | 347 ++++-------- .../busybox/networking/libiproute/libnetlink.h | 60 +- .../networking/libiproute/linux/pkt_sched.h | 413 -------------- .../router/busybox/networking/libiproute/ll_addr.c | 54 +- .../router/busybox/networking/libiproute/ll_map.c | 146 +++-- .../router/busybox/networking/libiproute/ll_map.h | 29 +- .../busybox/networking/libiproute/ll_proto.c | 121 ++-- .../busybox/networking/libiproute/ll_types.c | 250 ++++++--- .../busybox/networking/libiproute/rt_names.c | 320 +++++------ .../busybox/networking/libiproute/rt_names.h | 43 +- .../router/busybox/networking/libiproute/rtm_map.c | 44 +- .../router/busybox/networking/libiproute/rtm_map.h | 14 +- .../router/busybox/networking/libiproute/utils.c | 290 ++++------ .../router/busybox/networking/libiproute/utils.h | 97 ++-- 24 files changed, 2226 insertions(+), 2415 deletions(-) create mode 100644 release/src/router/busybox/networking/libiproute/Kbuild delete mode 100644 release/src/router/busybox/networking/libiproute/Makefile delete mode 100755 release/src/router/busybox/networking/libiproute/Makefile.in create mode 100644 release/src/router/busybox/networking/libiproute/iprule.c delete mode 100644 release/src/router/busybox/networking/libiproute/linux/pkt_sched.h (limited to 'release/src/router/busybox/networking/libiproute') 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 +# +# 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 -# -# 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 -# -# 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 +#include +#include +#if !defined IFA_RTA +#include +#endif +#if !defined IFLA_RTA +#include +#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 980929: resolve addresses */ -#include - +#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, * @@ -12,54 +10,50 @@ * Laszlo Valko 990223: address label must be zero terminated */ -#include -#include - #include -#include -#include -#include - -#include - #include #include +#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]) : ""); 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, + * Authors: Alexey Kuznetsov, * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include -#include -#include - -#include -#include -#include -#include - +//#include +//#include #include #include #include - -#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1 #include -#else -#include -#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, * @@ -15,27 +13,18 @@ * Kunihiro Ishiguro 001102: rtnh_ifindex was not initialized */ -#include - -#include -#include -#include -#include - +#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< '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, + * + * + * Changes: + * + * Rani Assaf 980929: resolve addresses + * initially integrated into busybox by Bernhard Reutner-Fischer + */ + +#include +#include +#include + +#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, * - * * Changes: * * Rani Assaf 980929: resolve addresses @@ -16,40 +13,71 @@ * Phil Karn 990408: "pmtudisc" flag */ -#include -#include - -#include -#include -#include - -#include #include -#include - #include #include - #include + +#ifndef __constant_htons #define __constant_htons htons -#include +#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 - -#include -#include -#include -#include -#include - #include -#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 +#include +/* 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 #include +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 - -#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, */ -#include -#include #include -#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 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 -#include -#include -#include +#include /* 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, */ -#include -#include -#include +#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 #else #include #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 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, */ -#include #include - #include -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 */ -#include -#include -#include -#include +#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 +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 -#include - +#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, * - * * Changes: * * Rani Assaf 980929: resolve addresses */ -#include -#include -#include -#include - -#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 -#include +/* 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 -- cgit v1.2.3-54-g00ecf