From c1570d3dfb24c08377cc6cf5a335892e39bd9bd2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 14 Nov 2013 12:34:35 +0000 Subject: [PATCH] [ipv6] Add "ipv6" setting type Signed-off-by: Michael Brown --- src/include/ipxe/settings.h | 1 + src/net/ipv6.c | 53 +++++++++++++++++++++++++++++++++++++ src/tests/settings_test.c | 16 +++++++++++ 3 files changed, 70 insertions(+) diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h index a7f76cf9d..a6dfd2102 100644 --- a/src/include/ipxe/settings.h +++ b/src/include/ipxe/settings.h @@ -377,6 +377,7 @@ extern char * expand_settings ( const char *string ); extern struct setting_type setting_type_string __setting_type; extern struct setting_type setting_type_uristring __setting_type; extern struct setting_type setting_type_ipv4 __setting_type; +extern struct setting_type setting_type_ipv6 __setting_type; extern struct setting_type setting_type_int8 __setting_type; extern struct setting_type setting_type_int16 __setting_type; extern struct setting_type setting_type_int32 __setting_type; diff --git a/src/net/ipv6.c b/src/net/ipv6.c index abe993d0f..b9619a1aa 100644 --- a/src/net/ipv6.c +++ b/src/net/ipv6.c @@ -866,6 +866,59 @@ struct sockaddr_converter ipv6_sockaddr_converter __sockaddr_converter = { .aton = ipv6_sock_aton, }; +/** + * Parse IPv6 address setting value + * + * @v type Setting type + * @v value Formatted setting value + * @v buf Buffer to contain raw value + * @v len Length of buffer + * @ret len Length of raw value, or negative error + */ +static int parse_ipv6_setting ( struct setting_type *type __unused, + const char *value, void *buf, size_t len ) { + struct in6_addr ipv6; + int rc; + + /* Parse IPv6 address */ + if ( ( rc = inet6_aton ( value, &ipv6 ) ) != 0 ) + return rc; + + /* Copy to buffer */ + if ( len > sizeof ( ipv6 ) ) + len = sizeof ( ipv6 ); + memcpy ( buf, &ipv6, len ); + + return ( sizeof ( ipv6 ) ); +} + +/** + * Format IPv6 address setting value + * + * @v type Setting type + * @v raw Raw setting value + * @v raw_len Length of raw setting value + * @v buf Buffer to contain formatted value + * @v len Length of buffer + * @ret len Length of formatted value, or negative error + */ +static int format_ipv6_setting ( struct setting_type *type __unused, + const void *raw, size_t raw_len, char *buf, + size_t len ) { + const struct in6_addr *ipv6 = raw; + + if ( raw_len < sizeof ( *ipv6 ) ) + return -EINVAL; + return snprintf ( buf, len, "%s", inet6_ntoa ( ipv6 ) ); +} + +/** An IPv6 address setting type */ +struct setting_type setting_type_ipv6 __setting_type = { + .name = "ipv6", + .parse = parse_ipv6_setting, + .format = format_ipv6_setting, +}; + /** * Perform IPv6 stateless address autoconfiguration (SLAAC) * diff --git a/src/tests/settings_test.c b/src/tests/settings_test.c index d1d923a4b..1be2cc323 100644 --- a/src/tests/settings_test.c +++ b/src/tests/settings_test.c @@ -173,6 +173,12 @@ static struct setting test_ipv4_setting = { .type = &setting_type_ipv4, }; +/** Test IPv6 address setting type */ +static struct setting test_ipv6_setting = { + .name = "test_ipv6", + .type = &setting_type_ipv6, +}; + /** Test signed 8-bit integer setting type */ static struct setting test_int8_setting = { .name = "test_int8", @@ -267,6 +273,16 @@ static void settings_test_exec ( void ) { fetchf_ok ( &test_settings, &test_ipv4_setting, RAW ( 212, 13, 204, 60 ), "212.13.204.60" ); + /* "ipv6" setting type */ + storef_ok ( &test_settings, &test_ipv6_setting, + "2001:ba8:0:1d4::6950:5845", + RAW ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4, + 0x00, 0x00, 0x00, 0x00, 0x69, 0x50, 0x58, 0x45 ) ); + fetchf_ok ( &test_settings, &test_ipv6_setting, + RAW ( 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x0c, 0x29, 0xff, 0xfe, 0xc5, 0x39, 0xa1 ), + "fe80::20c:29ff:fec5:39a1" ); + /* Integer setting types (as formatted strings) */ storef_ok ( &test_settings, &test_int8_setting, "54", RAW ( 54 ) );