mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Support IPv6 shorthand and IPv4-mapped addresses in inet_{pton,ntop}(3).
This commit is contained in:
parent
8d4b932f0f
commit
185a9fa221
2 changed files with 103 additions and 17 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2016, 2020 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -21,8 +21,8 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
const char* inet_ntop(int af,
|
||||
const void* restrict src,
|
||||
|
@ -42,18 +42,53 @@ const char* inet_ntop(int af,
|
|||
}
|
||||
else if ( af == AF_INET6 )
|
||||
{
|
||||
// TODO: Support for :: syntax.
|
||||
// TODO: Support for x:x:x:x:x:x:d.d.d.d syntax.
|
||||
// TODO: When should x:x:x:x:x:x:d.d.d.d notation be used?
|
||||
const unsigned char* ip = (const unsigned char*) src;
|
||||
int len = snprintf(dst, size, "%x:%x:%x:%x:%x:%x:%x:%x",
|
||||
ip[0] << 8 | ip[1], ip[2] << 8 | ip[3],
|
||||
ip[4] << 8 | ip[5], ip[6] << 8 | ip[7],
|
||||
ip[8] << 8 | ip[9], ip[10] << 8 | ip[11],
|
||||
ip[12] << 8 | ip[13], ip[14] << 8 | ip[15]);
|
||||
if ( len < 0 )
|
||||
return NULL;
|
||||
if ( size <= (size_t) len )
|
||||
size_t longest_zeroes_offset = 0;
|
||||
size_t longest_zeroes_length = 0;
|
||||
size_t current_zeroes_offset = 0;
|
||||
size_t current_zeroes_length = 0;
|
||||
for ( size_t i = 0; i < 8; i++ )
|
||||
{
|
||||
const unsigned char* data = ip + i * 2;
|
||||
if ( !data[0] && !data[1] )
|
||||
{
|
||||
current_zeroes_length++;
|
||||
if ( longest_zeroes_length < current_zeroes_length )
|
||||
{
|
||||
longest_zeroes_offset = current_zeroes_offset;
|
||||
longest_zeroes_length = current_zeroes_length;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
current_zeroes_offset = i + 1;
|
||||
current_zeroes_length = 0;
|
||||
}
|
||||
}
|
||||
char buffer[INET6_ADDRSTRLEN];
|
||||
size_t offset = 0;
|
||||
for ( size_t i = 0; i < 8; i++ )
|
||||
{
|
||||
const unsigned char* data = ip + i * 2;
|
||||
if ( i == longest_zeroes_offset && 2 <= longest_zeroes_length )
|
||||
{
|
||||
buffer[offset++] = ':';
|
||||
buffer[offset++] = ':';
|
||||
i += longest_zeroes_length - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( offset && buffer[offset - 1] != ':' )
|
||||
buffer[offset++] = ':';
|
||||
offset += snprintf(buffer + offset, sizeof(buffer) - offset,
|
||||
"%x", data[0] << 8 | data[1]);
|
||||
}
|
||||
}
|
||||
buffer[offset] = '\0';
|
||||
if ( size <= (size_t) offset )
|
||||
return errno = ENOSPC, (const char*) NULL;
|
||||
memcpy(dst, buffer, offset + 1);
|
||||
return dst;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2016, 2020 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -61,15 +61,55 @@ int inet_pton(int af, const char* restrict src, void* restrict dst)
|
|||
{
|
||||
unsigned char ip[16];
|
||||
size_t index = 0;
|
||||
// TODO: Support for :: syntax.
|
||||
// TODO: Support for x:x:x:x:x:x:d.d.d.d syntax.
|
||||
for ( int i = 0; i < 8; i++ )
|
||||
int compressed_at = -1;
|
||||
int i;
|
||||
for ( i = 0; i < 8; i++ )
|
||||
{
|
||||
if ( i && src[index++] != ':' )
|
||||
if ( compressed_at == -1 &&
|
||||
src[index + 0] == ':' &&
|
||||
src[index + 1] == ':' )
|
||||
{
|
||||
index += 2;
|
||||
compressed_at = i;
|
||||
}
|
||||
else if ( !src[index] )
|
||||
break;
|
||||
else if ( i && src[index++] != ':' )
|
||||
return 0;
|
||||
int num = 0;
|
||||
for ( int j = 0; j < 4; j++ )
|
||||
{
|
||||
if ( src[index] == '.' &&
|
||||
((compressed_at == -1 && i == 6) ||
|
||||
(0 < compressed_at && i <= 6)) )
|
||||
{
|
||||
index -= j;
|
||||
for ( int n = 0; n < 4; n++ )
|
||||
{
|
||||
if ( n && src[index++] != '.' )
|
||||
return 0;
|
||||
num = 0;
|
||||
for ( int m = 0; m < 3; m++ )
|
||||
{
|
||||
if ( !m && src[index] == '0' )
|
||||
{
|
||||
index++;
|
||||
break;
|
||||
}
|
||||
if ( '0' <= src[index] && src[index] <= '9' )
|
||||
num = num * 10 + src[index++] - '0';
|
||||
else if ( !m )
|
||||
return 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if ( 255 < num )
|
||||
return 0;
|
||||
ip[2 * i + n] = num;
|
||||
}
|
||||
i += 2;
|
||||
goto done;
|
||||
}
|
||||
int dgt;
|
||||
if ( '0' <= src[index] && src[index] <= '9' )
|
||||
dgt = src[index] - '0';
|
||||
|
@ -89,8 +129,19 @@ int inet_pton(int af, const char* restrict src, void* restrict dst)
|
|||
ip[2 * i + 0] = num >> 8 & 0xFF;
|
||||
ip[2 * i + 1] = num >> 0 & 0xFF;
|
||||
}
|
||||
done:
|
||||
if ( src[index] )
|
||||
return 0;
|
||||
if ( 0 <= compressed_at )
|
||||
{
|
||||
if ( i == 8 )
|
||||
return 0;
|
||||
memmove(ip + 16 - 2 * (i - compressed_at), ip + 2 * compressed_at,
|
||||
(i - compressed_at) * 2);
|
||||
memset(ip + 2 * compressed_at, 0, (8 - i) * 2);
|
||||
}
|
||||
else if ( i < 8 )
|
||||
return 0;
|
||||
memcpy(dst, ip, sizeof(ip));
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue