/*====================================================================*
*
* size_t ipv6spec (char const * string, byte memory []);
*
* memory.h
*
* encode a 16-byte memory region with the binary equivalent of an
* ipv6 address string; ipv6 addresses are defined as 8 16-bit hex
* numbers separated with colons; two consecutive colons represent
* one or more 0000 fields;
*
* Motley Tools by Charles Maier <cmaier@cmassoc.net>;
* Copyright (c) 2001-2006 by Charles Maier Associates;
* Licensed under the Internet Software Consortium License;
*
*--------------------------------------------------------------------*/
#ifndef IPV6SPEC_SOURCE
#define IPV6SPEC_SOURCE
#include <memory.h>
#include <ctype.h>
#include <errno.h>
#include "../tools/memory.h"
#include "../tools/number.h"
#include "../tools/error.h"
size_t ipv6spec (char const * string, void * memory)
{
char const * number = string;
byte * origin = (byte *)(memory);
byte * offset = (byte *)(memory);
byte * extent = offset + IPv6_LEN;
byte * marker = offset + IPv6_LEN;
unsigned radix = RADIX_HEX;
unsigned digit = 0;
while ((*number) && (offset < extent))
{
uint32_t value = 0;
if (offset > origin)
{
if (*number == HEX_EXTENDER)
{
number++;
}
if (*number == HEX_EXTENDER)
{
marker = offset;
}
}
while ((digit = todigit (*number)) < radix)
{
value *= radix;
value += digit;
if (value >> 16)
{
error (1, ERANGE, "IPv6 '%s' field %d exceeds 16 bits", string, 1 + ((unsigned)(offset - origin) >> 1));
}
number++;
}
*offset++ = (byte)(value >> 8);
*offset++ = (byte)(value >> 0);
}
#if defined (WIN32)
while (isspace (*number))
{
number++;
}
#endif
if (*number)
{
error (1, EINVAL, "IPv6 '%s' includes trash '%s'", string, number);
}
if (offset < extent)
{
while (offset > marker)
{
*--extent = *--offset;
}
while (extent > offset)
{
*--extent = 0;
}
}
if (offset < marker)
{
error (1, EINVAL, "IPv6 '%s' has only %d fields", string, (unsigned)(offset - origin) >> 1);
}
return (offset - origin);
}
/*====================================================================*
* demo/test program;
*--------------------------------------------------------------------*/
#if 0
#include <stdio.h>
char const * program_name = "ipv6spec";
int main (int argc, char * argv [])
{
byte memory [16];
char string [48];
while (*++argv)
{
ipv6spec (* argv, memory);
hexdecode (memory, sizeof (memory), string, sizeof (string));
printf ("%s %s\n", string, * argv);
}
return (0);
}
#endif
/*====================================================================*
*
*--------------------------------------------------------------------*/
#endif