inet_ntop.c   [plain text]



#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/socket.h>

void __res_close()
{
}

#define MAX_V6_ADDR_LEN 64

static const char *hexchars = "0123456789abcdef";

const char *
inet_ntop6(const struct in6_addr *addr, char *dst, size_t size)
{
	char hexa[8][5], tmp[MAX_V6_ADDR_LEN];
	int zr[8];
	size_t len;
	int32_t i, j, k, skip;
	uint8_t x8, hx8;
	uint16_t x16;
	struct in_addr a4;
	
	if (addr == NULL) return NULL;
	
	memset(tmp, 0, MAX_V6_ADDR_LEN);
	
	/*  check for mapped or compat addresses */
	i = IN6_IS_ADDR_V4MAPPED(addr);
	j = IN6_IS_ADDR_V4COMPAT(addr);
	if ((i != 0) || (j != 0))
	{
		a4.s_addr = addr->__u6_addr.__u6_addr32[3];
		sprintf(tmp, "::%s%s", (i != 0) ? "ffff:" : "", inet_ntoa(a4));
		len = strlen(tmp) + 1;
		if (len > size) return NULL;
		memcpy(dst, tmp, len);
		return dst;
	}
	
	k = 0;
	for (i = 0; i < 16; i += 2)
	{
		j = 0;
		skip = 1;
		
		memset(hexa[k], 0, 5);
		
		x8 = addr->__u6_addr.__u6_addr8[i];
		
		hx8 = x8 >> 4;
		if (hx8 != 0)
		{
			skip = 0;
			hexa[k][j++] = hexchars[hx8];
		}
		
		hx8 = x8 & 0x0f;
		if ((skip == 0) || ((skip == 1) && (hx8 != 0)))
		{
			skip = 0;
			hexa[k][j++] = hexchars[hx8];
		}
		
		x8 = addr->__u6_addr.__u6_addr8[i + 1];
		
		hx8 = x8 >> 4;
		if ((skip == 0) || ((skip == 1) && (hx8 != 0)))
		{
			hexa[k][j++] = hexchars[hx8];
		}
		
		hx8 = x8 & 0x0f;
		hexa[k][j++] = hexchars[hx8];
		
		k++;
	}
	
	/* find runs of zeros for :: convention */
	j = 0;
	for (i = 7; i >= 0; i--)
	{
		zr[i] = j;
		x16 = addr->__u6_addr.__u6_addr16[i];
		if (x16 == 0) j++;
		else j = 0;
		zr[i] = j;
	}
	
	/* find longest run of zeros */
	k = -1;
	j = 0;
	for(i = 0; i < 8; i++)
	{
		if (zr[i] > j)
		{
			k = i;
			j = zr[i];
		}
	}
	
	for(i = 0; i < 8; i++)
	{
		if (i != k) zr[i] = 0;
	}
	
	len = 0;
	for (i = 0; i < 8; i++)
	{
		if (zr[i] != 0)
		{
			/* check for leading zero */
			if (i == 0) tmp[len++] = ':';
			tmp[len++] = ':';
			i += (zr[i] - 1);
			continue;
		}
		for (j = 0; hexa[i][j] != '\0'; j++) tmp[len++] = hexa[i][j];
		if (i != 7) tmp[len++] = ':';
	}

	/* trailing NULL */
	len++;

	if (len > size) return NULL;
	memcpy(dst, tmp, len);
	return dst;
}

const char *
inet_ntop4(const struct in_addr *addr, char *buf, size_t len)
{
	const u_int8_t *ap = (u_int8_t *)&addr->s_addr;
	int i;
	char *bp=buf;
	
	for (i = 0; i < 4; i++, ap++)
	{
		if (bp >= buf + len - 1)
		{
			buf[len-1] = 0;
			return buf;
		}

		sprintf(bp, "%d", *ap);
		bp += strlen(bp);
		if (i != 3) *bp++='.';
	}

	*bp = 0;
	return buf;
}

const char *
inet_ntop(int af, const void *addr, char *buf, size_t len)
{
	if(af==AF_INET6)
		return inet_ntop6(addr, buf, len);
	if(af==AF_INET)
		return inet_ntop4(addr, buf, len);
	return NULL;
}