networking: code shrink

function                                             old     new   delta
in_ether                                               -     124    +124
hexchar2int                                           42       -     -42
ifconfig_main                                       1237    1106    -131
ether_input                                          141       -    -141
------------------------------------------------------------------------------
(add/remove: 2/2 grow/shrink: 0/1 up/down: 124/-314)         Total: -190 bytes

Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/libbb/in_ether.c b/libbb/in_ether.c
new file mode 100644
index 0000000..dadadba
--- /dev/null
+++ b/libbb/in_ether.c
@@ -0,0 +1,58 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ */
+
+//kbuild:lib-$(CONFIG_IFCONFIG) += in_ether.o
+//kbuild:lib-$(CONFIG_IFENSLAVE) += in_ether.o
+
+#include "libbb.h"
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+
+/* Convert Ethernet address from "XX[:]XX[:]XX[:]XX[:]XX[:]XX" to sockaddr.
+ * Return nonzero on error.
+ */
+int FAST_FUNC in_ether(const char *bufp, struct sockaddr *sap)
+{
+	char *ptr;
+	int i, j;
+	unsigned char val;
+	unsigned char c;
+
+	sap->sa_family = ARPHRD_ETHER;
+	ptr = (char *) sap->sa_data;
+
+	i = ETH_ALEN;
+	goto first;
+	do {
+		/* We might get a semicolon here */
+		if (*bufp == ':')
+			bufp++;
+ first:
+		j = val = 0;
+		do {
+			c = *bufp;
+			if (((unsigned char)(c - '0')) <= 9) {
+				c -= '0';
+			} else if ((unsigned char)((c|0x20) - 'a') <= 5) {
+				c = (unsigned char)((c|0x20) - 'a') + 10;
+			} else {
+				if (j && (c == ':' || c == '\0'))
+					/* One-digit byte: __:X:__ */
+					break;
+				return -1;
+			}
+			++bufp;
+			val <<= 4;
+			val += c;
+			j ^= 1;
+		} while (j);
+
+		*ptr++ = val;
+
+	} while (--i);
+
+	/* Error if we aren't at end of string */
+	return *bufp;
+}