mirror of
https://github.com/xcat2/xNBA.git
synced 2024-11-28 12:19:46 +00:00
[ipv6] Add inet6_aton()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
parent
8dd180f165
commit
a9fa0d5f2b
@ -120,6 +120,7 @@ struct sockaddr_in6 {
|
||||
|
||||
extern int inet_aton ( const char *cp, struct in_addr *inp );
|
||||
extern char * inet_ntoa ( struct in_addr in );
|
||||
extern char * inet6_ntoa ( const struct in6_addr *in6 );
|
||||
extern int inet6_aton ( const char *string, struct in6_addr *in );
|
||||
extern char * inet6_ntoa ( const struct in6_addr *in );
|
||||
|
||||
#endif /* _IPXE_IN_H */
|
||||
|
@ -622,11 +622,80 @@ static int ipv6_rx ( struct io_buffer *iobuf, struct net_device *netdev,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse IPv6 address
|
||||
*
|
||||
* @v string IPv6 address string
|
||||
* @ret in IPv6 address to fill in
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int inet6_aton ( const char *string, struct in6_addr *in ) {
|
||||
uint16_t *word = in->s6_addr16;
|
||||
uint16_t *end = ( word + ( sizeof ( in->s6_addr16 ) /
|
||||
sizeof ( in->s6_addr16[0] ) ) );
|
||||
uint16_t *pad = NULL;
|
||||
const char *nptr = string;
|
||||
char *endptr;
|
||||
unsigned long value;
|
||||
size_t pad_len;
|
||||
size_t move_len;
|
||||
|
||||
/* Parse string */
|
||||
while ( 1 ) {
|
||||
|
||||
/* Parse current word */
|
||||
value = strtoul ( nptr, &endptr, 16 );
|
||||
if ( value > 0xffff ) {
|
||||
DBG ( "IPv6 invalid word value %#lx in \"%s\"\n",
|
||||
value, string );
|
||||
return -EINVAL;
|
||||
}
|
||||
*(word++) = htons ( value );
|
||||
|
||||
/* Parse separator */
|
||||
if ( ! *endptr )
|
||||
break;
|
||||
if ( *endptr != ':' ) {
|
||||
DBG ( "IPv6 invalid separator '%c' in \"%s\"\n",
|
||||
*endptr, string );
|
||||
return -EINVAL;
|
||||
}
|
||||
if ( ( endptr == nptr ) && ( nptr != string ) ) {
|
||||
if ( pad ) {
|
||||
DBG ( "IPv6 invalid multiple \"::\" in "
|
||||
"\"%s\"\n", string );
|
||||
return -EINVAL;
|
||||
}
|
||||
pad = word;
|
||||
}
|
||||
nptr = ( endptr + 1 );
|
||||
|
||||
/* Check for overrun */
|
||||
if ( word == end ) {
|
||||
DBG ( "IPv6 too many words in \"%s\"\n", string );
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert padding if specified */
|
||||
if ( pad ) {
|
||||
move_len = ( ( ( void * ) word ) - ( ( void * ) pad ) );
|
||||
pad_len = ( ( ( void * ) end ) - ( ( void * ) word ) );
|
||||
memmove ( ( ( ( void * ) pad ) + pad_len ), pad, move_len );
|
||||
memset ( pad, 0, pad_len );
|
||||
} else if ( word != end ) {
|
||||
DBG ( "IPv6 underlength address \"%s\"\n", string );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert IPv6 address to standard notation
|
||||
*
|
||||
* @v in IPv6 address
|
||||
* @ret string IPv6 address in standard notation
|
||||
* @v in IPv6 address
|
||||
* @ret string IPv6 address string in canonical format
|
||||
*
|
||||
* RFC5952 defines the canonical format for IPv6 textual representation.
|
||||
*/
|
||||
@ -672,8 +741,8 @@ char * inet6_ntoa ( const struct in6_addr *in ) {
|
||||
/**
|
||||
* Transcribe IPv6 address
|
||||
*
|
||||
* @v net_addr IPv6 address
|
||||
* @ret string IPv6 address in standard notation
|
||||
* @v net_addr IPv6 address
|
||||
* @ret string IPv6 address in standard notation
|
||||
*
|
||||
*/
|
||||
static const char * ipv6_ntoa ( const void *net_addr ) {
|
||||
|
@ -60,6 +60,37 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
ok ( strcmp ( actual, expected ) == 0 ); \
|
||||
} while ( 0 )
|
||||
|
||||
/**
|
||||
* Report an inet6_aton() test result
|
||||
*
|
||||
* @v text Textual representation
|
||||
* @v addr Expected IPv6 address
|
||||
*/
|
||||
#define inet6_aton_ok( text, addr ) do { \
|
||||
static const char string[] = text; \
|
||||
static const struct in6_addr expected = { \
|
||||
.s6_addr = addr, \
|
||||
}; \
|
||||
struct in6_addr actual; \
|
||||
\
|
||||
ok ( inet6_aton ( string, &actual ) == 0 ); \
|
||||
DBG ( "inet6_aton ( \"%s\" ) = %s\n", string, \
|
||||
inet6_ntoa ( &actual ) ); \
|
||||
ok ( memcmp ( &actual, &expected, sizeof ( actual ) ) == 0 ); \
|
||||
} while ( 0 )
|
||||
|
||||
/**
|
||||
* Report an inet6_aton() failure test result
|
||||
*
|
||||
* @v text Textual representation
|
||||
*/
|
||||
#define inet6_aton_fail_ok( text ) do { \
|
||||
static const char string[] = text; \
|
||||
struct in6_addr dummy; \
|
||||
\
|
||||
ok ( inet6_aton ( string, &dummy ) != 0 ); \
|
||||
} while ( 0 )
|
||||
|
||||
/**
|
||||
* Perform IPv6 self-tests
|
||||
*
|
||||
@ -106,6 +137,41 @@ static void ipv6_test_exec ( void ) {
|
||||
inet6_ntoa_ok ( IPV6 ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ),
|
||||
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" );
|
||||
|
||||
/* inet6_aton() tests */
|
||||
inet6_aton_ok ( "2001:ba8:0:1d4::6950:5845",
|
||||
IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
|
||||
0x00, 0x00, 0x00, 0x00, 0x69, 0x50, 0x58, 0x45));
|
||||
/* No zeros */
|
||||
inet6_aton_ok ( "2001:db8:1:1:1:1:1:1",
|
||||
IPV6 ( 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x01,
|
||||
0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01));
|
||||
/* All intervening zeros */
|
||||
inet6_aton_ok ( "fe80::1",
|
||||
IPV6 ( 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01));
|
||||
/* Trailing run of zeros */
|
||||
inet6_aton_ok ( "fe80::",
|
||||
IPV6 ( 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
|
||||
/* Leading run of zeros */
|
||||
inet6_aton_ok ( "::1",
|
||||
IPV6 ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01));
|
||||
/* All zeros */
|
||||
inet6_aton_ok ( "::",
|
||||
IPV6 ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
|
||||
|
||||
/* inet6_aton() failure tests */
|
||||
inet6_aton_fail_ok ( "20012:ba8:0:1d4::6950:5845" );
|
||||
inet6_aton_fail_ok ( "200z:ba8:0:1d4::6950:5845" );
|
||||
inet6_aton_fail_ok ( "2001.ba8:0:1d4::6950:5845" );
|
||||
inet6_aton_fail_ok ( "2001:db8:1:1:1:1:1" );
|
||||
inet6_aton_fail_ok ( "2001:db8:1:1:1:1:1:1:2" );
|
||||
inet6_aton_fail_ok ( "2001:db8::1::2" );
|
||||
inet6_aton_fail_ok ( "2001:ba8:0:1d4:::6950:5845" );
|
||||
inet6_aton_fail_ok ( ":::" );
|
||||
}
|
||||
|
||||
/** IPv6 self-test */
|
||||
|
Loading…
Reference in New Issue
Block a user