summaryrefslogtreecommitdiffstats
path: root/src/net/ipv6.c
diff options
context:
space:
mode:
authorMichael Brown2013-09-11 05:26:39 +0200
committerMichael Brown2013-09-11 12:27:13 +0200
commita9fa0d5f2bd5254464f63a7312857fcec83bf37f (patch)
tree53ff15f22819b38c29219ed1a76513040f07bd2d /src/net/ipv6.c
parent[tcp] Reduce path MTU to 1280 bytes (diff)
downloadipxe-a9fa0d5f2bd5254464f63a7312857fcec83bf37f.tar.gz
ipxe-a9fa0d5f2bd5254464f63a7312857fcec83bf37f.tar.xz
ipxe-a9fa0d5f2bd5254464f63a7312857fcec83bf37f.zip
[ipv6] Add inet6_aton()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/ipv6.c')
-rw-r--r--src/net/ipv6.c77
1 files changed, 73 insertions, 4 deletions
diff --git a/src/net/ipv6.c b/src/net/ipv6.c
index 69feba19..8dc251ba 100644
--- a/src/net/ipv6.c
+++ b/src/net/ipv6.c
@@ -623,10 +623,79 @@ static int ipv6_rx ( struct io_buffer *iobuf, struct net_device *netdev,
}
/**
+ * 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 ) {