X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Farp.c;h=6519f8156c3f4bab13e71550716e8f89b3fad7f5;hb=260bd21169843fc00ee294a5f75da9e53cb2bc14;hp=7a36f44bbf2a2f3082f5aee4fc60f7c522fff0ee;hpb=7f2527e5a7f513b9f415643ddc0ecd236b596887;p=oweals%2Fbusybox.git diff --git a/networking/arp.c b/networking/arp.c index 7a36f44bb..6519f8156 100644 --- a/networking/arp.c +++ b/networking/arp.c @@ -12,8 +12,37 @@ * * modified for getopt32 by Arne Bernin */ - -#include "busybox.h" +//config:config ARP +//config: bool "arp (10 kb)" +//config: default y +//config: select PLATFORM_LINUX +//config: help +//config: Manipulate the system ARP cache. + +//applet:IF_ARP(APPLET(arp, BB_DIR_SBIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_ARP) += arp.o interface.o + +//usage:#define arp_trivial_usage +//usage: "\n[-vn] [-H HWTYPE] [-i IF] -a [HOSTNAME]" +//usage: "\n[-v] [-i IF] -d HOSTNAME [pub]" +//usage: "\n[-v] [-H HWTYPE] [-i IF] -s HOSTNAME HWADDR [temp]" +//usage: "\n[-v] [-H HWTYPE] [-i IF] -s HOSTNAME HWADDR [netmask MASK] pub" +//usage: "\n[-v] [-H HWTYPE] [-i IF] -Ds HOSTNAME IFACE [netmask MASK] pub" +//usage:#define arp_full_usage "\n\n" +//usage: "Manipulate ARP cache\n" +//usage: "\n -a Display (all) hosts" +//usage: "\n -d Delete ARP entry" +//usage: "\n -s Set new entry" +//usage: "\n -v Verbose" +//usage: "\n -n Don't resolve names" +//usage: "\n -i IF Network interface" +//usage: "\n -D Read HWADDR from IFACE" +//usage: "\n -A,-p AF Protocol family" +//usage: "\n -H HWTYPE Hardware address type" + +#include "libbb.h" +#include "common_bufsiz.h" #include "inet_common.h" #include @@ -27,37 +56,51 @@ #define DFLT_AF "inet" #define DFLT_HW "ether" -#define ARP_OPT_A (0x1) -#define ARP_OPT_p (0x2) -#define ARP_OPT_H (0x4) -#define ARP_OPT_t (0x8) -#define ARP_OPT_i (0x10) -#define ARP_OPT_a (0x20) -#define ARP_OPT_d (0x40) -#define ARP_OPT_n (0x80) /* do not resolve addresses */ -#define ARP_OPT_D (0x100) /* HW-address is devicename */ -#define ARP_OPT_s (0x200) -#define ARP_OPT_v (0x400 * DEBUG) /* debugging output flag */ - - -static const struct aftype *ap; /* current address family */ -static const struct hwtype *hw; /* current hardware type */ -static int sockfd; /* active socket descriptor */ -static smallint hw_set; /* flag if hw-type was set (-H) */ -static const char *device = ""; /* current device */ - -static const char *const options[] = { - "pub", - "priv", - "temp", - "trail", - "dontpub", - "auto", - "dev", - "netmask", - NULL +enum { + ARP_OPT_A = (1 << 0), + ARP_OPT_p = (1 << 1), + ARP_OPT_H = (1 << 2), + ARP_OPT_t = (1 << 3), + ARP_OPT_i = (1 << 4), + ARP_OPT_a = (1 << 5), + ARP_OPT_d = (1 << 6), + ARP_OPT_n = (1 << 7), /* do not resolve addresses */ + ARP_OPT_D = (1 << 8), /* HW-address is devicename */ + ARP_OPT_s = (1 << 9), + ARP_OPT_v = (1 << 10) * DEBUG, /* debugging output flag */ +}; + +enum { + sockfd = 3, /* active socket descriptor */ }; +struct globals { + const struct aftype *ap; /* current address family */ + const struct hwtype *hw; /* current hardware type */ + const char *device; /* current device */ + smallint hw_set; /* flag if hw-type was set (-H) */ +} FIX_ALIASING; +#define G (*(struct globals*)bb_common_bufsiz1) +#define ap (G.ap ) +#define hw (G.hw ) +#define device (G.device ) +#define hw_set (G.hw_set ) +#define INIT_G() do { \ + setup_common_bufsiz(); \ + device = ""; \ +} while (0) + + +static const char options[] ALIGN1 = + "pub\0" + "priv\0" + "temp\0" + "trail\0" + "dontpub\0" + "auto\0" + "dev\0" + "netmask\0"; + /* Delete an entry from the ARP cache. */ /* Called only from main, once */ static int arp_del(char **args) @@ -73,7 +116,7 @@ static int arp_del(char **args) /* Resolve the host name. */ host = *args; if (ap->input(host, &sa) < 0) { - bb_herror_msg_and_die("%s", host); + bb_simple_herror_msg_and_die(host); } /* If a host has more than one address, use the correct one! */ @@ -85,7 +128,7 @@ static int arp_del(char **args) req.arp_flags = ATF_PERM; args++; while (*args != NULL) { - switch (index_in_str_array(options, *args)) { + switch (index_in_strings(options, *args)) { case 0: /* "pub" */ flags |= 1; args++; @@ -106,7 +149,7 @@ static int arp_del(char **args) #ifdef HAVE_ATF_DONTPUB req.arp_flags |= ATF_DONTPUB; #else - bb_error_msg("feature ATF_DONTPUB is not supported"); + bb_simple_error_msg("feature ATF_DONTPUB is not supported"); #endif args++; break; @@ -114,7 +157,7 @@ static int arp_del(char **args) #ifdef HAVE_ATF_MAGIC req.arp_flags |= ATF_MAGIC; #else - bb_error_msg("feature ATF_MAGIC is not supported"); + bb_simple_error_msg("feature ATF_MAGIC is not supported"); #endif args++; break; @@ -130,7 +173,7 @@ static int arp_del(char **args) if (strcmp(*args, "255.255.255.255") != 0) { host = *args; if (ap->input(host, &sa) < 0) { - bb_herror_msg_and_die("%s", host); + bb_simple_herror_msg_and_die(host); } memcpy(&req.arp_netmask, &sa, sizeof(struct sockaddr)); req.arp_flags |= ATF_NETMASK; @@ -145,14 +188,14 @@ static int arp_del(char **args) if (flags == 0) flags = 3; - strncpy(req.arp_dev, device, sizeof(req.arp_dev)); + strncpy_IFNAMSIZ(req.arp_dev, device); err = -1; /* Call the kernel. */ if (flags & 2) { if (option_mask32 & ARP_OPT_v) - bb_error_msg("SIOCDARP(nopub)"); + bb_simple_error_msg("SIOCDARP(nopub)"); err = ioctl(sockfd, SIOCDARP, &req); if (err < 0) { if (errno == ENXIO) { @@ -161,38 +204,36 @@ static int arp_del(char **args) printf("No ARP entry for %s\n", host); return -1; } - bb_perror_msg_and_die("SIOCDARP(priv)"); + bb_simple_perror_msg_and_die("SIOCDARP(priv)"); } } if ((flags & 1) && err) { nopub: req.arp_flags |= ATF_PUBL; if (option_mask32 & ARP_OPT_v) - bb_error_msg("SIOCDARP(pub)"); + bb_simple_error_msg("SIOCDARP(pub)"); if (ioctl(sockfd, SIOCDARP, &req) < 0) { if (errno == ENXIO) { printf("No ARP entry for %s\n", host); return -1; } - bb_perror_msg_and_die("SIOCDARP(pub)"); + bb_simple_perror_msg_and_die("SIOCDARP(pub)"); } } return 0; } /* Get the hardware address to a specified interface name */ -static void arp_getdevhw(char *ifname, struct sockaddr *sa, - const struct hwtype *hwt) +static void arp_getdevhw(char *ifname, struct sockaddr *sa) { struct ifreq ifr; const struct hwtype *xhw; - strcpy(ifr.ifr_name, ifname); - if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) { - bb_perror_msg_and_die("cant get HW-Address for '%s'", ifname); - } - if (hwt && (ifr.ifr_hwaddr.sa_family != hw->type)) { - bb_error_msg_and_die("protocol type mismatch"); + strncpy_IFNAMSIZ(ifr.ifr_name, ifname); + ioctl_or_perror_and_die(sockfd, SIOCGIFHWADDR, &ifr, + "can't get HW-Address for '%s'", ifname); + if (hw_set && (ifr.ifr_hwaddr.sa_family != hw->type)) { + bb_simple_error_msg_and_die("protocol type mismatch"); } memcpy(sa, &(ifr.ifr_hwaddr), sizeof(struct sockaddr)); @@ -202,8 +243,8 @@ static void arp_getdevhw(char *ifname, struct sockaddr *sa, xhw = get_hwntype(-1); } bb_error_msg("device '%s' has HW address %s '%s'", - ifname, xhw->name, - xhw->print((char *) &ifr.ifr_hwaddr.sa_data)); + ifname, xhw->name, + xhw->print((unsigned char *) &ifr.ifr_hwaddr.sa_data)); } } @@ -220,27 +261,27 @@ static int arp_set(char **args) host = *args++; if (ap->input(host, &sa) < 0) { - bb_herror_msg_and_die("%s", host); + bb_simple_herror_msg_and_die(host); } /* If a host has more than one address, use the correct one! */ memcpy(&req.arp_pa, &sa, sizeof(struct sockaddr)); /* Fetch the hardware address. */ if (*args == NULL) { - bb_error_msg_and_die("need hardware address"); + bb_simple_error_msg_and_die("need hardware address"); } if (option_mask32 & ARP_OPT_D) { - arp_getdevhw(*args++, &req.arp_ha, hw_set ? hw : NULL); + arp_getdevhw(*args++, &req.arp_ha); } else { if (hw->input(*args++, &req.arp_ha) < 0) { - bb_error_msg_and_die("invalid hardware address"); + bb_simple_error_msg_and_die("invalid hardware address"); } } /* Check out any modifiers. */ flags = ATF_PERM | ATF_COM; while (*args != NULL) { - switch (index_in_str_array(options, *args)) { + switch (index_in_strings(options, *args)) { case 0: /* "pub" */ flags |= ATF_PUBL; args++; @@ -261,7 +302,7 @@ static int arp_set(char **args) #ifdef HAVE_ATF_DONTPUB flags |= ATF_DONTPUB; #else - bb_error_msg("feature ATF_DONTPUB is not supported"); + bb_simple_error_msg("feature ATF_DONTPUB is not supported"); #endif args++; break; @@ -269,7 +310,7 @@ static int arp_set(char **args) #ifdef HAVE_ATF_MAGIC flags |= ATF_MAGIC; #else - bb_error_msg("feature ATF_MAGIC is not supported"); + bb_simple_error_msg("feature ATF_MAGIC is not supported"); #endif args++; break; @@ -285,7 +326,7 @@ static int arp_set(char **args) if (strcmp(*args, "255.255.255.255") != 0) { host = *args; if (ap->input(host, &sa) < 0) { - bb_herror_msg_and_die("%s", host); + bb_simple_herror_msg_and_die(host); } memcpy(&req.arp_netmask, &sa, sizeof(struct sockaddr)); flags |= ATF_NETMASK; @@ -301,14 +342,12 @@ static int arp_set(char **args) /* Fill in the remainder of the request. */ req.arp_flags = flags; - strncpy(req.arp_dev, device, sizeof(req.arp_dev)); + strncpy_IFNAMSIZ(req.arp_dev, device); /* Call the kernel. */ if (option_mask32 & ARP_OPT_v) - bb_error_msg("SIOCSARP()"); - if (ioctl(sockfd, SIOCSARP, &req) < 0) { - bb_perror_msg_and_die("SIOCSARP"); - } + bb_simple_error_msg("SIOCSARP()"); + xioctl(sockfd, SIOCSARP, &req); return 0; } @@ -316,8 +355,28 @@ static int arp_set(char **args) /* Print the contents of an ARP request block. */ static void arp_disp(const char *name, char *ip, int type, int arp_flags, - char *hwa, char *mask, char *dev) + char *hwa, char *mask, char *dev) { + static const int arp_masks[] = { + ATF_PERM, ATF_PUBL, +#ifdef HAVE_ATF_MAGIC + ATF_MAGIC, +#endif +#ifdef HAVE_ATF_DONTPUB + ATF_DONTPUB, +#endif + ATF_USETRAILERS, + }; + static const char arp_labels[] ALIGN1 = "PERM\0""PUP\0" +#ifdef HAVE_ATF_MAGIC + "AUTO\0" +#endif +#ifdef HAVE_ATF_DONTPUB + "DONTPUB\0" +#endif + "TRAIL\0" + ; + const struct hwtype *xhw; xhw = get_hwntype(type); @@ -338,22 +397,8 @@ arp_disp(const char *name, char *ip, int type, int arp_flags, if (arp_flags & ATF_NETMASK) printf("netmask %s ", mask); - if (arp_flags & ATF_PERM) - printf("PERM "); - if (arp_flags & ATF_PUBL) - printf("PUP "); -#ifdef HAVE_ATF_MAGIC - if (arp_flags & ATF_MAGIC) - printf("AUTO "); -#endif -#ifdef HAVE_ATF_DONTPUB - if (arp_flags & ATF_DONTPUB) - printf("DONTPUB "); -#endif - if (arp_flags & ATF_USETRAILERS) - printf("TRAIL "); - - printf("on %s\n", dev); + print_flags_separated(arp_masks, arp_labels, arp_flags, " "); + printf(" on %s\n", dev); } /* Display the contents of the ARP cache in the kernel. */ @@ -377,11 +422,11 @@ static int arp_show(char *name) if (name != NULL) { /* Resolve the host name. */ if (ap->input(name, &sa) < 0) { - bb_herror_msg_and_die("%s", name); + bb_simple_herror_msg_and_die(name); } host = xstrdup(ap->sprint(&sa, 1)); } - fp = xfopen("/proc/net/arp", "r"); + fp = xfopen_for_read("/proc/net/arp"); /* Bypass header -- read one line */ fgets(line, sizeof(line), fp); @@ -393,7 +438,7 @@ static int arp_show(char *name) /* All these strings can't overflow * because fgets above reads limited amount of data */ num = sscanf(line, "%s 0x%x 0x%x %s %s %s\n", - ip, &type, &flags, hwa, mask, dev); + ip, &type, &flags, hwa, mask, dev); if (num < 4) break; @@ -425,12 +470,12 @@ static int arp_show(char *name) arp_disp(hostname, ip, type, flags, hwa, mask, dev); } if (option_mask32 & ARP_OPT_v) - printf("Entries: %d\tSkipped: %d\tFound: %d\n", - entries, entries - shown, shown); + printf("Entries: %u\tSkipped: %u\tFound: %u\n", + entries, entries - shown, shown); if (!shown) { if (hw_set || host || device[0]) - printf("No match found in %d entries\n", entries); + printf("No match found in %u entries\n", entries); } if (ENABLE_FEATURE_CLEAN_UP) { free((char*)host); @@ -439,58 +484,58 @@ static int arp_show(char *name) return 0; } -int arp_main(int argc, char **argv); -int arp_main(int argc, char **argv) +int arp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int arp_main(int argc UNUSED_PARAM, char **argv) { - char *hw_type; - char *protocol; + const char *hw_type; + const char *protocol; + unsigned opts; - /* Initialize variables... */ - ap = get_aftype(DFLT_AF); - if (!ap) - bb_error_msg_and_die("%s: %s not supported", DFLT_AF, "address family"); + INIT_G(); + + xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sockfd); - getopt32(argc, argv, "A:p:H:t:i:adnDsv", &protocol, &protocol, + ap = get_aftype(DFLT_AF); + /* Defaults are always supported */ + //if (!ap) + // bb_error_msg_and_die("%s: %s not supported", DFLT_AF, "address family"); + hw = get_hwtype(DFLT_HW); + //if (!hw) + // bb_error_msg_and_die("%s: %s not supported", DFLT_HW, "hardware type"); + + opts = getopt32(argv, "A:p:H:t:i:adnDsv", &protocol, &protocol, &hw_type, &hw_type, &device); argv += optind; - if (option_mask32 & ARP_OPT_A || option_mask32 & ARP_OPT_p) { + if (opts & (ARP_OPT_A | ARP_OPT_p)) { ap = get_aftype(protocol); - if (ap == NULL) + if (!ap) bb_error_msg_and_die("%s: unknown %s", protocol, "address family"); } - if (option_mask32 & ARP_OPT_A || option_mask32 & ARP_OPT_p) { + if (opts & (ARP_OPT_H | ARP_OPT_t)) { hw = get_hwtype(hw_type); - if (hw == NULL) + if (!hw) bb_error_msg_and_die("%s: unknown %s", hw_type, "hardware type"); hw_set = 1; } - //if (option_mask32 & ARP_OPT_i)... -i + //if (opts & ARP_OPT_i)... -i if (ap->af != AF_INET) { bb_error_msg_and_die("%s: kernel only supports 'inet'", ap->name); } - - /* If no hw type specified get default */ - if (!hw) { - hw = get_hwtype(DFLT_HW); - if (!hw) - bb_error_msg_and_die("%s: %s not supported", DFLT_HW, "hardware type"); - } - if (hw->alen <= 0) { bb_error_msg_and_die("%s: %s without ARP support", - hw->name, "hardware type"); + hw->name, "hardware type"); } - sockfd = xsocket(AF_INET, SOCK_DGRAM, 0); /* Now see what we have to do here... */ - if (option_mask32 & (ARP_OPT_d|ARP_OPT_s)) { + if (opts & (ARP_OPT_d | ARP_OPT_s)) { if (argv[0] == NULL) - bb_error_msg_and_die("need host name"); - if (option_mask32 & ARP_OPT_s) + bb_simple_error_msg_and_die("need host name"); + if (opts & ARP_OPT_s) return arp_set(argv); return arp_del(argv); } - //if (option_mask32 & ARP_OPT_a) - default + + //if (opts & ARP_OPT_a) - default return arp_show(argv[0]); }