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 /networking | |
parent | b05955e0a5aa5c16ef9460cf4bfed1ee589f5f64 (diff) | |
download | busybox-fa85b86f388fb037b67fa7fcc3b5502c8d0fa84a.tar.gz |
add arp applet - thanks to
"Eric Spakman" <E.Spakman@inter.nl.net>
Diffstat (limited to 'networking')
-rw-r--r-- | networking/Config.in | 6 | ||||
-rw-r--r-- | networking/Kbuild | 1 | ||||
-rw-r--r-- | networking/interface.c | 200 |
3 files changed, 172 insertions, 35 deletions
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 Enable IPv6 support in busybox. This adds IPv6 support in the networking applets. +config ARP + bool "arp" + default n + help + Manipulate the system ARP cache + config ARPING bool "arping" default n diff --git a/networking/Kbuild b/networking/Kbuild index a9a51fc2e..4c29e45a8 100644 --- a/networking/Kbuild +++ b/networking/Kbuild @@ -5,6 +5,7 @@ # Licensed under the GPL v2, see the file LICENSE in this tarball. lib-y:= +lib-$(CONFIG_ARP) += arp.o interface.o lib-$(CONFIG_ARPING) += arping.o lib-$(CONFIG_DNSD) += dnsd.o 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 { #define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */ #endif -/* This structure defines protocol families and their handlers. */ -struct aftype { - const char *name; - const char *title; - int af; - int alen; - char *(*print) (unsigned char *); - char *(*sprint) (struct sockaddr *, int numeric); - int (*input) (int type, char *bufp, struct sockaddr *); - void (*herror) (char *text); - int (*rprint) (int options); - int (*rinput) (int typ, int ext, char **argv); - - /* may modify src */ - int (*getmask) (char *src, struct sockaddr * mask, char *name); - - int fd; - char *flag_file; -}; - /* Display an Internet socket address. */ static char *INET_sprint(struct sockaddr *sap, int numeric) { @@ -126,12 +106,66 @@ static char *INET_sprint(struct sockaddr *sap, int numeric) return buff; } +static int INET_getsock(char *bufp, struct sockaddr *sap) +{ + char *sp = bufp, *bp; + unsigned int i; + unsigned val; + struct sockaddr_in *sock_in; + + sock_in = (struct sockaddr_in *) sap; + sock_in->sin_family = AF_INET; + sock_in->sin_port = 0; + + val = 0; + bp = (char *) &val; + for (i = 0; i < sizeof(sock_in->sin_addr.s_addr); i++) { + *sp = toupper(*sp); + + if ((unsigned)(*sp - 'A') <= 5) + bp[i] |= (int) (*sp - ('A' - 10)); + else if (isdigit(*sp)) + bp[i] |= (int) (*sp - '0'); + else + return -1; + + bp[i] <<= 4; + sp++; + *sp = toupper(*sp); + + if ((unsigned)(*sp - 'A') <= 5) + bp[i] |= (int) (*sp - ('A' - 10)); + else if (isdigit(*sp)) + bp[i] |= (int) (*sp - '0'); + else + return -1; + + sp++; + } + sock_in->sin_addr.s_addr = htonl(val); + + return (sp - bufp); +} + +static int INET_input(int type, char *bufp, struct sockaddr *sap) +{ + switch (type) { + case 1: + return (INET_getsock(bufp, sap)); + case 256: + return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1)); + default: + return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0)); + } +} + static struct aftype inet_aftype = { .name = "inet", .title = "DARPA Internet", .af = AF_INET, .alen = 4, .sprint = INET_sprint, + .input = INET_input, .fd = -1 }; @@ -151,12 +185,37 @@ static char *INET6_sprint(struct sockaddr *sap, int numeric) return buff; } +static int INET6_getsock(char *bufp, struct sockaddr *sap) +{ + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *) sap; + sin6->sin6_family = AF_INET6; + sin6->sin6_port = 0; + + if (inet_pton(AF_INET6, bufp, sin6->sin6_addr.s6_addr) <= 0) + return -1; + + return 16; /* ?;) */ +} + +static int INET6_input(int type, char *bufp, struct sockaddr *sap) +{ + switch (type) { + case 1: + return (INET6_getsock(bufp, sap)); + default: + return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap)); + } +} + static struct aftype inet6_aftype = { .name = "inet6", .title = "IPv6", .af = AF_INET6, .alen = sizeof(struct in6_addr), .sprint = INET6_sprint, + .input = INET6_input, .fd = -1 }; @@ -206,6 +265,20 @@ static struct aftype * const aftypes[] = { }; /* Check our protocol family table for this family. */ +struct aftype *get_aftype(const char *name) +{ + struct aftype * const *afp; + + afp = aftypes; + while (*afp != NULL) { + if (!strcmp((*afp)->name, name)) + return (*afp); + afp++; + } + return NULL; +} + +/* Check our protocol family table for this family. */ static struct aftype *get_afntype(int af) { struct aftype * const *afp; @@ -714,18 +787,6 @@ static int do_if_fetch(struct interface *ife) return 0; } -/* This structure defines hardware protocols and their handlers. */ -struct hwtype { - const char * const name; - const char *title; - int type; - int alen; - char *(*print) (unsigned char *); - int (*input) (char *, struct sockaddr *); - int (*activate) (int fd); - int suppress_null_addr; -}; - static const struct hwtype unspec_hwtype = { .name = "unspec", .title = "UNSPEC", @@ -759,14 +820,69 @@ static char *pr_ether(unsigned char *ptr) return buff; } -static const struct hwtype ether_hwtype = { +static int in_ether(char *bufp, struct sockaddr *sap); + +static struct hwtype ether_hwtype = { .name = "ether", .title = "Ethernet", .type = ARPHRD_ETHER, .alen = ETH_ALEN, - .print = pr_ether + .print = pr_ether, + .input = in_ether }; +static unsigned hexchar2int(char c) +{ + if (isdigit(c)) + return c - '0'; + c &= ~0x20; /* a -> A */ + if ((unsigned)(c - 'A') <= 5) + return c - ('A' - 10); + return ~0U; +} + +/* Input an Ethernet address and convert to binary. */ +static int in_ether(char *bufp, struct sockaddr *sap) +{ + unsigned char *ptr; + char c, *orig; + int i; + unsigned val; + + sap->sa_family = ether_hwtype.type; + ptr = sap->sa_data; + + i = 0; + orig = bufp; + while ((*bufp != '\0') && (i < ETH_ALEN)) { + val = hexchar2int(*bufp++) * 0x10; + if (val > 0xff) { + errno = EINVAL; + return -1; + } + c = *bufp; + if (c == ':' || c == 0) + val >>= 4; + else { + val |= hexchar2int(c); + if (val > 0xff) { + errno = EINVAL; + return -1; + } + } + if (c != 0) + bufp++; + *ptr++ = (unsigned char) val; + i++; + + /* We might get a semicolon here - not required. */ + if (*bufp == ':') { + bufp++; + } + } + return 0; +} + #include <net/if_arp.h> static const struct hwtype ppp_hwtype = { @@ -811,7 +927,21 @@ static const char * const if_port_text[] = { #endif /* Check our hardware type table for this type. */ -static const struct hwtype *get_hwntype(int type) +const struct hwtype *get_hwtype(const char *name) +{ + const struct hwtype * const *hwp; + + hwp = hwtypes; + while (*hwp != NULL) { + if (!strcmp((*hwp)->name, name)) + return (*hwp); + hwp++; + } + return NULL; +} + +/* Check our hardware type table for this type. */ +const struct hwtype *get_hwntype(int type) { const struct hwtype * const *hwp; |