aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/applets.h1
-rw-r--r--include/libbb.h37
-rw-r--r--include/usage.h20
-rw-r--r--networking/Config.in6
-rw-r--r--networking/Kbuild1
-rw-r--r--networking/interface.c200
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))
USE_ADDUSER(APPLET(adduser, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_ADJTIMEX(APPLET(adjtimex, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_AR(APPLET(ar, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_ARP(APPLET(arp, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_ARPING(APPLET(arping, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_ASH(APPLET_NOUSAGE(ash, ash, _BB_DIR_BIN, _BB_SUID_NEVER))
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 @@
/* scary. better ideas? (but do *test* them first!) */
#define OFF_T_MAX ((off_t)~((off_t)1 << (sizeof(off_t)*8-1)))
+/* This structure defines protocol families and their handlers. */
+struct aftype {
+ char *name;
+ 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;
+};
+
+/* This structure defines hardware protocols and their handlers. */
+struct hwtype {
+ char *name;
+ char *title;
+ int type;
+ int alen;
+ char *(*print) (unsigned char *);
+ int (*input) (char *, struct sockaddr *);
+ int (*activate) (int fd);
+ int suppress_null_addr;
+};
+
/* Some useful definitions */
#undef FALSE
#define FALSE ((int) 0)
@@ -426,8 +458,13 @@ extern int bb_test(int argc, char** argv);
int create_icmp_socket(void);
int create_icmp6_socket(void);
/* interface.c */
+struct aftype;
+struct hwtype;
extern int interface_opt_a;
int display_interfaces(char *ifname);
+struct aftype *get_aftype(const char *name);
+const struct hwtype *get_hwtype(const char *name);
+const struct hwtype *get_hwntype(int type);
#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 @@
" -x Extract\n" \
" -v Verbosely list files processed"
+#define arp_trivial_usage \
+ "\n" \
+ "[-vn] [-H type] [-i if] -a [hostname]\n" \
+ "[-v] [-i if] -d hostname [pub]\n" \
+ "[-v] [-H type] [-i if] -s hostname hw_addr [temp]\n" \
+ "[-v] [-H type] [-i if] -s hostname hw_addr [netmask nm] pub\n" \
+ "[-v] [-H type] [-i if] -Ds hostname ifa [netmask nm] pub\n"
+#define arp_full_usage \
+ "Manipulate the system ARP cache" \
+ "\n\nOptions:" \
+ "\n -a Display (all) hosts" \
+ "\n -s Set a new ARP entry" \
+ "\n -d Delete a specified entry" \
+ "\n -v Verbose" \
+ "\n -n Don't resolve names" \
+ "\n -i if Specify network interface (e.g. eth0)" \
+ "\n -D Read <hwaddr> from given device" \
+ "\n -A, -p Specify protocol family" \
+ "\n -H hwtype Specify hardware address type"
+
#define arping_trivial_usage \
"[-fqbDUA] [-c count] [-w timeout] [-i device] [-s sender] target"
#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
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;