    /*====================================================================*
     *
     *   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

[PREV] [HOME] [NEXT]