summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2007-09-15 08:12:15 +0000
committerMike Frysinger <vapier@gentoo.org>2007-09-15 08:12:15 +0000
commitb5a7ad59209216ead9ded5b2cd69ac5e0dd63d2c (patch)
tree806e068d96eb4bc6f2bf0c8b319456194bac90a4 /libc
parentb9a82d5b22c68a57e6a9fa51cc4d1ec507f266a5 (diff)
switch to a smaller/more robust implementation by Andrey Simonenko and as suggested by Natanael Copa
harvested from: http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/92880
Diffstat (limited to 'libc')
-rw-r--r--libc/inet/inet_net.c84
1 files changed, 41 insertions, 43 deletions
diff --git a/libc/inet/inet_net.c b/libc/inet/inet_net.c
index f8148c274..51edcf212 100644
--- a/libc/inet/inet_net.c
+++ b/libc/inet/inet_net.c
@@ -37,6 +37,7 @@
#include <ctype.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+
#ifdef __UCLIBC_HAS_XLOCALE__
libc_hidden_proto(__ctype_b_loc)
#elif __UCLIBC_HAS_CTYPE_TABLES__
@@ -52,57 +53,54 @@ libc_hidden_proto(inet_network)
in_addr_t
inet_network(const char *cp)
{
- register in_addr_t val, base, n;
- register char c;
- in_addr_t parts[4], *pp = parts;
- register unsigned int i;
+ u_char c;
+ int got_data;
+ u_int base, dots;
+ in_addr_t res, val;
-again:
- /*
- * Collect number up to ``.''.
- * Values are specified as for C:
- * 0x=hex, 0=octal, other=decimal.
- */
- val = 0; base = 10;
- /*
- * The 4.4BSD version of this file also accepts 'x__' as a hexa
- * number. I don't think this is correct. -- Uli
- */
+ res = 0;
+ dots = 0;
+ again:
+ val = 0;
+ got_data = 0;
if (*cp == '0') {
- if (*++cp == 'x' || *cp == 'X')
- base = 16, cp++;
- else
- base = 8;
- }
- while ((c = *cp)) {
- if (isdigit(c)) {
- val = (val * base) + (c - '0');
- cp++;
- continue;
- }
- if (base == 16 && isxdigit(c)) {
- val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
+ cp++;
+ if (*cp == 'x' || *cp == 'X') {
cp++;
- continue;
+ base = 16;
+ } else {
+ base = 8;
+ got_data = 1;
}
- break;
+ } else
+ base = 10;
+ while ((c = *cp) != '\0') {
+ if (isdigit(c)) {
+ if (base == 8 && c > '7')
+ return (INADDR_NONE);
+ val = val * base + c - '0';
+ } else if (base == 16 && isxdigit(c))
+ val = (val << 4) + 10 - (islower(c) ? 'a' : 'A');
+ else
+ break;
+ if (val > 0xff)
+ return (INADDR_NONE);
+ cp++;
+ got_data = 1;
}
- if (*cp == '.') {
- if (pp >= parts + 4)
+ if (!got_data)
+ return (INADDR_NONE);
+ if (dots != 0)
+ res <<= 8;
+ res |= val;
+ if (c == '.') {
+ if (++dots == 4)
return (INADDR_NONE);
- *pp++ = val, cp++;
+ cp++;
goto again;
}
- if (*cp && !isspace(*cp))
- return (INADDR_NONE);
- *pp++ = val;
- n = pp - parts;
- if (n > 4)
+ if (c != '\0')
return (INADDR_NONE);
- for (val = 0, i = 0; i < n; i++) {
- val <<= 8;
- val |= parts[i] & 0xff;
- }
- return (val);
+ return (res);
}
libc_hidden_def(inet_network)