diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-07 01:24:12 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-07 01:24:12 +0000 |
| commit | fa85b86f388fb037b67fa7fcc3b5502c8d0fa84a (patch) | |
| tree | 0d2f47866709f0a555d28166b4aeca04dfb7808c | |
| parent | b05955e0a5aa5c16ef9460cf4bfed1ee589f5f64 (diff) | |
| download | busybox-w32-fa85b86f388fb037b67fa7fcc3b5502c8d0fa84a.tar.gz busybox-w32-fa85b86f388fb037b67fa7fcc3b5502c8d0fa84a.tar.bz2 busybox-w32-fa85b86f388fb037b67fa7fcc3b5502c8d0fa84a.zip | |
add arp applet - thanks to
"Eric Spakman" <E.Spakman@inter.nl.net>
| -rw-r--r-- | include/applets.h | 1 | ||||
| -rw-r--r-- | include/libbb.h | 37 | ||||
| -rw-r--r-- | include/usage.h | 20 | ||||
| -rw-r--r-- | networking/Config.in | 6 | ||||
| -rw-r--r-- | networking/Kbuild | 1 | ||||
| -rw-r--r-- | networking/interface.c | 200 |
6 files changed, 230 insertions, 35 deletions
diff --git a/include/applets.h b/include/applets.h index 8586ffc86..465ecdbdd 100644 --- a/include/applets.h +++ b/include/applets.h | |||
| @@ -56,6 +56,7 @@ USE_ADDGROUP(APPLET(addgroup, _BB_DIR_BIN, _BB_SUID_NEVER)) | |||
| 56 | USE_ADDUSER(APPLET(adduser, _BB_DIR_BIN, _BB_SUID_NEVER)) | 56 | USE_ADDUSER(APPLET(adduser, _BB_DIR_BIN, _BB_SUID_NEVER)) |
| 57 | USE_ADJTIMEX(APPLET(adjtimex, _BB_DIR_SBIN, _BB_SUID_NEVER)) | 57 | USE_ADJTIMEX(APPLET(adjtimex, _BB_DIR_SBIN, _BB_SUID_NEVER)) |
| 58 | USE_AR(APPLET(ar, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 58 | USE_AR(APPLET(ar, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
| 59 | USE_ARP(APPLET(arp, _BB_DIR_SBIN, _BB_SUID_NEVER)) | ||
| 59 | USE_ARPING(APPLET(arping, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 60 | USE_ARPING(APPLET(arping, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
| 60 | USE_ASH(APPLET_NOUSAGE(ash, ash, _BB_DIR_BIN, _BB_SUID_NEVER)) | 61 | USE_ASH(APPLET_NOUSAGE(ash, ash, _BB_DIR_BIN, _BB_SUID_NEVER)) |
| 61 | USE_AWK(APPLET(awk, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 62 | USE_AWK(APPLET(awk, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
diff --git a/include/libbb.h b/include/libbb.h index e92e4db1c..6f66c8545 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
| @@ -121,6 +121,38 @@ | |||
| 121 | /* scary. better ideas? (but do *test* them first!) */ | 121 | /* scary. better ideas? (but do *test* them first!) */ |
| 122 | #define OFF_T_MAX ((off_t)~((off_t)1 << (sizeof(off_t)*8-1))) | 122 | #define OFF_T_MAX ((off_t)~((off_t)1 << (sizeof(off_t)*8-1))) |
| 123 | 123 | ||
| 124 | /* This structure defines protocol families and their handlers. */ | ||
| 125 | struct aftype { | ||
| 126 | char *name; | ||
| 127 | char *title; | ||
| 128 | int af; | ||
| 129 | int alen; | ||
| 130 | char *(*print) (unsigned char *); | ||
| 131 | char *(*sprint) (struct sockaddr *, int numeric); | ||
| 132 | int (*input) (int type, char *bufp, struct sockaddr *); | ||
| 133 | void (*herror) (char *text); | ||
| 134 | int (*rprint) (int options); | ||
| 135 | int (*rinput) (int typ, int ext, char **argv); | ||
| 136 | |||
| 137 | /* may modify src */ | ||
| 138 | int (*getmask) (char *src, struct sockaddr * mask, char *name); | ||
| 139 | |||
| 140 | int fd; | ||
| 141 | char *flag_file; | ||
| 142 | }; | ||
| 143 | |||
| 144 | /* This structure defines hardware protocols and their handlers. */ | ||
| 145 | struct hwtype { | ||
| 146 | char *name; | ||
| 147 | char *title; | ||
| 148 | int type; | ||
| 149 | int alen; | ||
| 150 | char *(*print) (unsigned char *); | ||
| 151 | int (*input) (char *, struct sockaddr *); | ||
| 152 | int (*activate) (int fd); | ||
| 153 | int suppress_null_addr; | ||
| 154 | }; | ||
| 155 | |||
| 124 | /* Some useful definitions */ | 156 | /* Some useful definitions */ |
| 125 | #undef FALSE | 157 | #undef FALSE |
| 126 | #define FALSE ((int) 0) | 158 | #define FALSE ((int) 0) |
| @@ -426,8 +458,13 @@ extern int bb_test(int argc, char** argv); | |||
| 426 | int create_icmp_socket(void); | 458 | int create_icmp_socket(void); |
| 427 | int create_icmp6_socket(void); | 459 | int create_icmp6_socket(void); |
| 428 | /* interface.c */ | 460 | /* interface.c */ |
| 461 | struct aftype; | ||
| 462 | struct hwtype; | ||
| 429 | extern int interface_opt_a; | 463 | extern int interface_opt_a; |
| 430 | int display_interfaces(char *ifname); | 464 | int display_interfaces(char *ifname); |
| 465 | struct aftype *get_aftype(const char *name); | ||
| 466 | const struct hwtype *get_hwtype(const char *name); | ||
| 467 | const struct hwtype *get_hwntype(int type); | ||
| 431 | 468 | ||
| 432 | 469 | ||
| 433 | #ifndef BUILD_INDIVIDUAL | 470 | #ifndef BUILD_INDIVIDUAL |
diff --git a/include/usage.h b/include/usage.h index ae03d5431..cfae4e1e1 100644 --- a/include/usage.h +++ b/include/usage.h | |||
| @@ -55,6 +55,26 @@ | |||
| 55 | " -x Extract\n" \ | 55 | " -x Extract\n" \ |
| 56 | " -v Verbosely list files processed" | 56 | " -v Verbosely list files processed" |
| 57 | 57 | ||
| 58 | #define arp_trivial_usage \ | ||
| 59 | "\n" \ | ||
| 60 | "[-vn] [-H type] [-i if] -a [hostname]\n" \ | ||
| 61 | "[-v] [-i if] -d hostname [pub]\n" \ | ||
| 62 | "[-v] [-H type] [-i if] -s hostname hw_addr [temp]\n" \ | ||
| 63 | "[-v] [-H type] [-i if] -s hostname hw_addr [netmask nm] pub\n" \ | ||
| 64 | "[-v] [-H type] [-i if] -Ds hostname ifa [netmask nm] pub\n" | ||
| 65 | #define arp_full_usage \ | ||
| 66 | "Manipulate the system ARP cache" \ | ||
| 67 | "\n\nOptions:" \ | ||
| 68 | "\n -a Display (all) hosts" \ | ||
| 69 | "\n -s Set a new ARP entry" \ | ||
| 70 | "\n -d Delete a specified entry" \ | ||
| 71 | "\n -v Verbose" \ | ||
| 72 | "\n -n Don't resolve names" \ | ||
| 73 | "\n -i if Specify network interface (e.g. eth0)" \ | ||
| 74 | "\n -D Read <hwaddr> from given device" \ | ||
| 75 | "\n -A, -p Specify protocol family" \ | ||
| 76 | "\n -H hwtype Specify hardware address type" | ||
| 77 | |||
| 58 | #define arping_trivial_usage \ | 78 | #define arping_trivial_usage \ |
| 59 | "[-fqbDUA] [-c count] [-w timeout] [-i device] [-s sender] target" | 79 | "[-fqbDUA] [-c count] [-w timeout] [-i device] [-s sender] target" |
| 60 | #define arping_full_usage \ | 80 | #define arping_full_usage \ |
diff --git a/networking/Config.in b/networking/Config.in index b2d973f0c..88ccb16ab 100644 --- a/networking/Config.in +++ b/networking/Config.in | |||
| @@ -12,6 +12,12 @@ config FEATURE_IPV6 | |||
| 12 | Enable IPv6 support in busybox. | 12 | Enable IPv6 support in busybox. |
| 13 | This adds IPv6 support in the networking applets. | 13 | This adds IPv6 support in the networking applets. |
| 14 | 14 | ||
| 15 | config ARP | ||
| 16 | bool "arp" | ||
| 17 | default n | ||
| 18 | help | ||
| 19 | Manipulate the system ARP cache | ||
| 20 | |||
| 15 | config ARPING | 21 | config ARPING |
| 16 | bool "arping" | 22 | bool "arping" |
| 17 | default n | 23 | default n |
diff --git a/networking/Kbuild b/networking/Kbuild index a9a51fc2e..4c29e45a8 100644 --- a/networking/Kbuild +++ b/networking/Kbuild | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | # Licensed under the GPL v2, see the file LICENSE in this tarball. | 5 | # Licensed under the GPL v2, see the file LICENSE in this tarball. |
| 6 | 6 | ||
| 7 | lib-y:= | 7 | lib-y:= |
| 8 | lib-$(CONFIG_ARP) += arp.o interface.o | ||
| 8 | lib-$(CONFIG_ARPING) += arping.o | 9 | lib-$(CONFIG_ARPING) += arping.o |
| 9 | lib-$(CONFIG_DNSD) += dnsd.o | 10 | lib-$(CONFIG_DNSD) += dnsd.o |
| 10 | lib-$(CONFIG_ETHER_WAKE) += ether-wake.o | 11 | lib-$(CONFIG_ETHER_WAKE) += ether-wake.o |
diff --git a/networking/interface.c b/networking/interface.c index b39298cfe..6d23e9bfc 100644 --- a/networking/interface.c +++ b/networking/interface.c | |||
| @@ -91,26 +91,6 @@ struct in6_ifreq { | |||
| 91 | #define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */ | 91 | #define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */ |
| 92 | #endif | 92 | #endif |
| 93 | 93 | ||
| 94 | /* This structure defines protocol families and their handlers. */ | ||
| 95 | struct aftype { | ||
| 96 | const char *name; | ||
| 97 | const char *title; | ||
| 98 | int af; | ||
| 99 | int alen; | ||
| 100 | char *(*print) (unsigned char *); | ||
| 101 | char *(*sprint) (struct sockaddr *, int numeric); | ||
| 102 | int (*input) (int type, char *bufp, struct sockaddr *); | ||
| 103 | void (*herror) (char *text); | ||
| 104 | int (*rprint) (int options); | ||
| 105 | int (*rinput) (int typ, int ext, char **argv); | ||
| 106 | |||
| 107 | /* may modify src */ | ||
| 108 | int (*getmask) (char *src, struct sockaddr * mask, char *name); | ||
| 109 | |||
| 110 | int fd; | ||
| 111 | char *flag_file; | ||
| 112 | }; | ||
| 113 | |||
| 114 | /* Display an Internet socket address. */ | 94 | /* Display an Internet socket address. */ |
| 115 | static char *INET_sprint(struct sockaddr *sap, int numeric) | 95 | static char *INET_sprint(struct sockaddr *sap, int numeric) |
| 116 | { | 96 | { |
| @@ -126,12 +106,66 @@ static char *INET_sprint(struct sockaddr *sap, int numeric) | |||
| 126 | return buff; | 106 | return buff; |
| 127 | } | 107 | } |
| 128 | 108 | ||
| 109 | static int INET_getsock(char *bufp, struct sockaddr *sap) | ||
| 110 | { | ||
| 111 | char *sp = bufp, *bp; | ||
| 112 | unsigned int i; | ||
| 113 | unsigned val; | ||
| 114 | struct sockaddr_in *sock_in; | ||
| 115 | |||
| 116 | sock_in = (struct sockaddr_in *) sap; | ||
| 117 | sock_in->sin_family = AF_INET; | ||
| 118 | sock_in->sin_port = 0; | ||
| 119 | |||
| 120 | val = 0; | ||
| 121 | bp = (char *) &val; | ||
| 122 | for (i = 0; i < sizeof(sock_in->sin_addr.s_addr); i++) { | ||
| 123 | *sp = toupper(*sp); | ||
| 124 | |||
| 125 | if ((unsigned)(*sp - 'A') <= 5) | ||
| 126 | bp[i] |= (int) (*sp - ('A' - 10)); | ||
| 127 | else if (isdigit(*sp)) | ||
| 128 | bp[i] |= (int) (*sp - '0'); | ||
| 129 | else | ||
| 130 | return -1; | ||
| 131 | |||
| 132 | bp[i] <<= 4; | ||
| 133 | sp++; | ||
| 134 | *sp = toupper(*sp); | ||
| 135 | |||
| 136 | if ((unsigned)(*sp - 'A') <= 5) | ||
| 137 | bp[i] |= (int) (*sp - ('A' - 10)); | ||
| 138 | else if (isdigit(*sp)) | ||
| 139 | bp[i] |= (int) (*sp - '0'); | ||
| 140 | else | ||
| 141 | return -1; | ||
| 142 | |||
| 143 | sp++; | ||
| 144 | } | ||
| 145 | sock_in->sin_addr.s_addr = htonl(val); | ||
| 146 | |||
| 147 | return (sp - bufp); | ||
| 148 | } | ||
| 149 | |||
| 150 | static int INET_input(int type, char *bufp, struct sockaddr *sap) | ||
| 151 | { | ||
| 152 | switch (type) { | ||
| 153 | case 1: | ||
| 154 | return (INET_getsock(bufp, sap)); | ||
| 155 | case 256: | ||
| 156 | return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1)); | ||
| 157 | default: | ||
| 158 | return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0)); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 129 | static struct aftype inet_aftype = { | 162 | static struct aftype inet_aftype = { |
| 130 | .name = "inet", | 163 | .name = "inet", |
| 131 | .title = "DARPA Internet", | 164 | .title = "DARPA Internet", |
| 132 | .af = AF_INET, | 165 | .af = AF_INET, |
| 133 | .alen = 4, | 166 | .alen = 4, |
| 134 | .sprint = INET_sprint, | 167 | .sprint = INET_sprint, |
| 168 | .input = INET_input, | ||
| 135 | .fd = -1 | 169 | .fd = -1 |
| 136 | }; | 170 | }; |
| 137 | 171 | ||
| @@ -151,12 +185,37 @@ static char *INET6_sprint(struct sockaddr *sap, int numeric) | |||
| 151 | return buff; | 185 | return buff; |
| 152 | } | 186 | } |
| 153 | 187 | ||
| 188 | static int INET6_getsock(char *bufp, struct sockaddr *sap) | ||
| 189 | { | ||
| 190 | struct sockaddr_in6 *sin6; | ||
| 191 | |||
| 192 | sin6 = (struct sockaddr_in6 *) sap; | ||
| 193 | sin6->sin6_family = AF_INET6; | ||
| 194 | sin6->sin6_port = 0; | ||
| 195 | |||
| 196 | if (inet_pton(AF_INET6, bufp, sin6->sin6_addr.s6_addr) <= 0) | ||
| 197 | return -1; | ||
| 198 | |||
| 199 | return 16; /* ?;) */ | ||
| 200 | } | ||
| 201 | |||
| 202 | static int INET6_input(int type, char *bufp, struct sockaddr *sap) | ||
| 203 | { | ||
| 204 | switch (type) { | ||
| 205 | case 1: | ||
| 206 | return (INET6_getsock(bufp, sap)); | ||
| 207 | default: | ||
| 208 | return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap)); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 154 | static struct aftype inet6_aftype = { | 212 | static struct aftype inet6_aftype = { |
| 155 | .name = "inet6", | 213 | .name = "inet6", |
| 156 | .title = "IPv6", | 214 | .title = "IPv6", |
| 157 | .af = AF_INET6, | 215 | .af = AF_INET6, |
| 158 | .alen = sizeof(struct in6_addr), | 216 | .alen = sizeof(struct in6_addr), |
| 159 | .sprint = INET6_sprint, | 217 | .sprint = INET6_sprint, |
| 218 | .input = INET6_input, | ||
| 160 | .fd = -1 | 219 | .fd = -1 |
| 161 | }; | 220 | }; |
| 162 | 221 | ||
| @@ -206,6 +265,20 @@ static struct aftype * const aftypes[] = { | |||
| 206 | }; | 265 | }; |
| 207 | 266 | ||
| 208 | /* Check our protocol family table for this family. */ | 267 | /* Check our protocol family table for this family. */ |
| 268 | struct aftype *get_aftype(const char *name) | ||
| 269 | { | ||
| 270 | struct aftype * const *afp; | ||
| 271 | |||
| 272 | afp = aftypes; | ||
| 273 | while (*afp != NULL) { | ||
| 274 | if (!strcmp((*afp)->name, name)) | ||
| 275 | return (*afp); | ||
| 276 | afp++; | ||
| 277 | } | ||
| 278 | return NULL; | ||
| 279 | } | ||
| 280 | |||
| 281 | /* Check our protocol family table for this family. */ | ||
| 209 | static struct aftype *get_afntype(int af) | 282 | static struct aftype *get_afntype(int af) |
| 210 | { | 283 | { |
| 211 | struct aftype * const *afp; | 284 | struct aftype * const *afp; |
| @@ -714,18 +787,6 @@ static int do_if_fetch(struct interface *ife) | |||
| 714 | return 0; | 787 | return 0; |
| 715 | } | 788 | } |
| 716 | 789 | ||
| 717 | /* This structure defines hardware protocols and their handlers. */ | ||
| 718 | struct hwtype { | ||
| 719 | const char * const name; | ||
| 720 | const char *title; | ||
| 721 | int type; | ||
| 722 | int alen; | ||
| 723 | char *(*print) (unsigned char *); | ||
| 724 | int (*input) (char *, struct sockaddr *); | ||
| 725 | int (*activate) (int fd); | ||
| 726 | int suppress_null_addr; | ||
| 727 | }; | ||
| 728 | |||
| 729 | static const struct hwtype unspec_hwtype = { | 790 | static const struct hwtype unspec_hwtype = { |
| 730 | .name = "unspec", | 791 | .name = "unspec", |
| 731 | .title = "UNSPEC", | 792 | .title = "UNSPEC", |
| @@ -759,14 +820,69 @@ static char *pr_ether(unsigned char *ptr) | |||
| 759 | return buff; | 820 | return buff; |
| 760 | } | 821 | } |
| 761 | 822 | ||
| 762 | static const struct hwtype ether_hwtype = { | 823 | static int in_ether(char *bufp, struct sockaddr *sap); |
| 824 | |||
| 825 | static struct hwtype ether_hwtype = { | ||
| 763 | .name = "ether", | 826 | .name = "ether", |
| 764 | .title = "Ethernet", | 827 | .title = "Ethernet", |
| 765 | .type = ARPHRD_ETHER, | 828 | .type = ARPHRD_ETHER, |
| 766 | .alen = ETH_ALEN, | 829 | .alen = ETH_ALEN, |
| 767 | .print = pr_ether | 830 | .print = pr_ether, |
| 831 | .input = in_ether | ||
| 768 | }; | 832 | }; |
| 769 | 833 | ||
| 834 | static unsigned hexchar2int(char c) | ||
| 835 | { | ||
| 836 | if (isdigit(c)) | ||
| 837 | return c - '0'; | ||
| 838 | c &= ~0x20; /* a -> A */ | ||
| 839 | if ((unsigned)(c - 'A') <= 5) | ||
| 840 | return c - ('A' - 10); | ||
| 841 | return ~0U; | ||
| 842 | } | ||
| 843 | |||
| 844 | /* Input an Ethernet address and convert to binary. */ | ||
| 845 | static int in_ether(char *bufp, struct sockaddr *sap) | ||
| 846 | { | ||
| 847 | unsigned char *ptr; | ||
| 848 | char c, *orig; | ||
| 849 | int i; | ||
| 850 | unsigned val; | ||
| 851 | |||
| 852 | sap->sa_family = ether_hwtype.type; | ||
| 853 | ptr = sap->sa_data; | ||
| 854 | |||
| 855 | i = 0; | ||
| 856 | orig = bufp; | ||
| 857 | while ((*bufp != '\0') && (i < ETH_ALEN)) { | ||
| 858 | val = hexchar2int(*bufp++) * 0x10; | ||
| 859 | if (val > 0xff) { | ||
| 860 | errno = EINVAL; | ||
| 861 | return -1; | ||
| 862 | } | ||
| 863 | c = *bufp; | ||
| 864 | if (c == ':' || c == 0) | ||
| 865 | val >>= 4; | ||
| 866 | else { | ||
| 867 | val |= hexchar2int(c); | ||
| 868 | if (val > 0xff) { | ||
| 869 | errno = EINVAL; | ||
| 870 | return -1; | ||
| 871 | } | ||
| 872 | } | ||
| 873 | if (c != 0) | ||
| 874 | bufp++; | ||
| 875 | *ptr++ = (unsigned char) val; | ||
| 876 | i++; | ||
| 877 | |||
| 878 | /* We might get a semicolon here - not required. */ | ||
| 879 | if (*bufp == ':') { | ||
| 880 | bufp++; | ||
| 881 | } | ||
| 882 | } | ||
| 883 | return 0; | ||
| 884 | } | ||
| 885 | |||
| 770 | #include <net/if_arp.h> | 886 | #include <net/if_arp.h> |
| 771 | 887 | ||
| 772 | static const struct hwtype ppp_hwtype = { | 888 | static const struct hwtype ppp_hwtype = { |
| @@ -811,7 +927,21 @@ static const char * const if_port_text[] = { | |||
| 811 | #endif | 927 | #endif |
| 812 | 928 | ||
| 813 | /* Check our hardware type table for this type. */ | 929 | /* Check our hardware type table for this type. */ |
| 814 | static const struct hwtype *get_hwntype(int type) | 930 | const struct hwtype *get_hwtype(const char *name) |
| 931 | { | ||
| 932 | const struct hwtype * const *hwp; | ||
| 933 | |||
| 934 | hwp = hwtypes; | ||
| 935 | while (*hwp != NULL) { | ||
| 936 | if (!strcmp((*hwp)->name, name)) | ||
| 937 | return (*hwp); | ||
| 938 | hwp++; | ||
| 939 | } | ||
| 940 | return NULL; | ||
| 941 | } | ||
| 942 | |||
| 943 | /* Check our hardware type table for this type. */ | ||
| 944 | const struct hwtype *get_hwntype(int type) | ||
| 815 | { | 945 | { |
| 816 | const struct hwtype * const *hwp; | 946 | const struct hwtype * const *hwp; |
| 817 | 947 | ||
