#include <arpa/inet.h>
#include <ctype.h>
#ifdef _LIBC
+# include <endian.h>
+# include <stdint.h>
# include <stdlib.h>
# include <limits.h>
# include <errno.h>
#ifndef _LIBC
register int base;
#endif
- register int n;
register char c;
- u_int32_t parts[4];
- register u_int32_t *pp = parts;
+ union iaddr {
+ uint8_t bytes[4];
+ uint32_t word;
+ } res;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ register uint8_t *pp = res.bytes;
+#else
+ register uint8_t *pp = &res.bytes[4];
+#endif
+ int digit;
#ifdef _LIBC
int saved_errno = errno;
__set_errno (0);
#endif
- memset (parts, '\0', sizeof (parts));
+ res.word = 0;
c = *cp;
for (;;) {
goto ret_0;
#ifdef _LIBC
{
- unsigned long ul = strtoul (cp, (char **) &cp, 0);
+ char *endp;
+ unsigned long ul = strtoul (cp, (char **) &endp, 0);
if (ul == ULONG_MAX && errno == ERANGE)
goto ret_0;
if (ul > 0xfffffffful)
goto ret_0;
val = ul;
+ digit = cp != endp;
+ cp = endp;
}
c = *cp;
#else
* a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
*/
- if (pp >= parts + 3)
+ if ((BYTE_ORDER == LITTLE_ENDIAN
+ && pp >= res.bytes + 3)
+ || (BYTE_ORDER == BIG_ENDIAN
+ && pp == res.bytes)
+ || val > 0xff)
goto ret_0;
+#if BYTE_ORDER == LITTLE_ENDIAN
*pp++ = val;
+#else
+ *--pp = val;
+#endif
c = *++cp;
} else
break;
*/
if (c != '\0' && (!isascii(c) || !isspace(c)))
goto ret_0;
+
/*
- * Concoct the address according to
- * the number of parts specified.
+ * Did we get a valid digit?
*/
- n = pp - parts + 1;
+ if (!digit)
+ goto ret_0;
- if (n == 0 /* initial nondigit */
- || parts[0] > 0xff || parts[1] > 0xff || parts[2] > 0xff
- || val > max[n - 1])
+ /* Check whether the last part is in its limits depending on
+ the number of parts in total. */
+ if ((BYTE_ORDER == LITTLE_ENDIAN && val > max[pp - res.bytes])
+ || (BYTE_ORDER == BIG_ENDIAN && val > max[res.bytes - pp]))
goto ret_0;
- val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
-
if (addr)
- addr->s_addr = htonl(val);
+ addr->s_addr = res.word | htonl (val);
#ifdef _LIBC
__set_errno (saved_errno);
#include <netinet/in.h>
#include <arpa/inet.h>
-enum { buf_size = 16 };
-static char buf[buf_size] = "323543357756889";
+
+static struct tests
+{
+ const char *input;
+ int valid;
+ uint32_t result;
+} tests[] =
+{
+ { "", 0, 0 },
+ { "-1", 0, 0 },
+ { "256", 1, 0x00000100 },
+ { "256.", 0, 0 },
+ { "256a", 0, 0 },
+ { "0x100", 1, 0x00000100 },
+ { "0200.0x123456", 1, 0x80123456 },
+ { "0300.0x89123456.", 0 ,0 },
+ { "0100.-0xffff0000", 0, 0 },
+ { "0.0xffffff", 1, 0x00ffffff },
+ { "0.0x1000000", 0, 0 },
+ { "0377.16777215", 1, 0xffffffff },
+ { "0377.16777216", 0, 0 },
+ { "0x87.077777777", 1, 0x87ffffff },
+ { "0x87.0100000000", 0, 0 },
+ { "0.1.3", 1, 0x00010003 },
+ { "0.256.3", 0, 0 },
+ { "256.1.3", 0, 0 },
+ { "0.1.0x10000", 0, 0 },
+ { "0.1.0xffff", 1, 0x0001ffff },
+ { "0.1a.3", 0, 0 },
+ { "0.1.a3", 0, 0 },
+ { "1.2.3.4", 1, 0x01020304 },
+ { "0400.2.3.4", 0, 0 },
+ { "1.0x100.3.4", 0, 0 },
+ { "1.2.256.4", 0, 0 },
+ { "1.2.3.0x100", 0, 0 },
+ { "323543357756889", 0, 0 },
+};
+
int
main (int argc, char *argv[])
{
- struct in_addr addr;
int result = 0;
+ int cnt;
- if (inet_aton (buf, &addr) != 0)
+ for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt)
{
- printf ("%s is seen as a valid IP address\n", buf);
- result = 1;
+ struct in_addr addr;
+
+ if (inet_aton (tests[cnt].input, &addr) != tests[cnt].valid)
+ {
+ if (tests[cnt].valid)
+ printf ("\"%s\" not seen as valid IP address\n", tests[cnt].input);
+ else
+ printf ("\"%s\" seen as valid IP address\n", tests[cnt].input);
+ result = 1;
+ }
+ else if (tests[cnt].valid && addr.s_addr != ntohl (tests[cnt].result))
+ {
+ printf ("\"%s\" not converted correctly: is %08x, should be %08x\n",
+ tests[cnt].input, addr.s_addr, tests[cnt].result);
+ result = 1;
+ }
}
return result;