mirror of
https://github.com/ipxe/ipxe
synced 2025-12-15 00:12:19 +03:00
@@ -120,6 +120,7 @@ struct sockaddr_in6 {
|
|||||||
|
|
||||||
extern int inet_aton ( const char *cp, struct in_addr *inp );
|
extern int inet_aton ( const char *cp, struct in_addr *inp );
|
||||||
extern char * inet_ntoa ( struct in_addr in );
|
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 */
|
#endif /* _IPXE_IN_H */
|
||||||
|
|||||||
@@ -622,11 +622,80 @@ static int ipv6_rx ( struct io_buffer *iobuf, struct net_device *netdev,
|
|||||||
return rc;
|
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
|
* Convert IPv6 address to standard notation
|
||||||
*
|
*
|
||||||
* @v in IPv6 address
|
* @v in IPv6 address
|
||||||
* @ret string IPv6 address in standard notation
|
* @ret string IPv6 address string in canonical format
|
||||||
*
|
*
|
||||||
* RFC5952 defines the canonical format for IPv6 textual representation.
|
* RFC5952 defines the canonical format for IPv6 textual representation.
|
||||||
*/
|
*/
|
||||||
@@ -672,8 +741,8 @@ char * inet6_ntoa ( const struct in6_addr *in ) {
|
|||||||
/**
|
/**
|
||||||
* Transcribe IPv6 address
|
* Transcribe IPv6 address
|
||||||
*
|
*
|
||||||
* @v net_addr IPv6 address
|
* @v net_addr IPv6 address
|
||||||
* @ret string IPv6 address in standard notation
|
* @ret string IPv6 address in standard notation
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static const char * ipv6_ntoa ( const void *net_addr ) {
|
static const char * ipv6_ntoa ( const void *net_addr ) {
|
||||||
|
|||||||
@@ -60,6 +60,37 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||||||
ok ( strcmp ( actual, expected ) == 0 ); \
|
ok ( strcmp ( actual, expected ) == 0 ); \
|
||||||
} while ( 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
|
* 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,
|
inet6_ntoa_ok ( IPV6 ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ),
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ),
|
||||||
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" );
|
"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 */
|
/** IPv6 self-test */
|
||||||
|
|||||||
Reference in New Issue
Block a user