aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
Diffstat (limited to 'networking')
-rw-r--r--networking/Config.in6
-rw-r--r--networking/Kbuild1
-rw-r--r--networking/interface.c200
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;