david/ipxe
Archived
1
0

[ipv6] Add IPv6 socket address converter

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2013-10-21 14:06:07 +01:00
parent 365a09d867
commit 2c76c1a6d8
2 changed files with 102 additions and 2 deletions

View File

@ -292,6 +292,9 @@ struct net_device_stats {
struct net_device_error errors[NETDEV_MAX_UNIQUE_ERRORS]; struct net_device_error errors[NETDEV_MAX_UNIQUE_ERRORS];
}; };
/** Maximum length of a network device name */
#define NETDEV_NAME_LEN 12
/** /**
* A network device * A network device
* *
@ -312,7 +315,7 @@ struct net_device {
/** Index of this network device */ /** Index of this network device */
unsigned int index; unsigned int index;
/** Name of this network device */ /** Name of this network device */
char name[12]; char name[NETDEV_NAME_LEN];
/** Underlying hardware device */ /** Underlying hardware device */
struct device *dev; struct device *dev;

View File

@ -190,7 +190,7 @@ static void del_ipv6_miniroute ( struct ipv6_miniroute *miniroute ) {
* @ret miniroute Routing table entry to use, or NULL if no route * @ret miniroute Routing table entry to use, or NULL if no route
*/ */
static struct ipv6_miniroute * ipv6_route ( unsigned int scope_id, static struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
struct in6_addr **dest ) { struct in6_addr **dest ) {
struct ipv6_miniroute *miniroute; struct ipv6_miniroute *miniroute;
int local; int local;
@ -749,6 +749,96 @@ static const char * ipv6_ntoa ( const void *net_addr ) {
return inet6_ntoa ( net_addr ); return inet6_ntoa ( net_addr );
} }
/**
* Transcribe IPv6 socket address
*
* @v sa Socket address
* @ret string Socket address in standard notation
*/
static const char * ipv6_sock_ntoa ( struct sockaddr *sa ) {
static char buf[ 39 /* "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx" */ +
1 /* "%" */ + NETDEV_NAME_LEN + 1 /* NUL */ ];
struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) sa );
struct in6_addr *in = &sin6->sin6_addr;
struct net_device *netdev;
const char *netdev_name;
/* Identify network device, if applicable */
if ( IN6_IS_ADDR_LINKLOCAL ( in ) ) {
netdev = find_netdev_by_index ( sin6->sin6_scope_id );
netdev_name = ( netdev ? netdev->name : "UNKNOWN" );
} else {
netdev_name = NULL;
}
/* Format socket address */
snprintf ( buf, sizeof ( buf ), "%s%s%s", inet6_ntoa ( in ),
( netdev_name ? "%" : "" ),
( netdev_name ? netdev_name : "" ) );
return buf;
}
/**
* Parse IPv6 socket address
*
* @v string Socket address string
* @v sa Socket address to fill in
* @ret rc Return status code
*/
static int ipv6_sock_aton ( const char *string, struct sockaddr *sa ) {
struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) sa );
struct in6_addr in;
struct net_device *netdev;
size_t len;
char *tmp;
char *in_string;
char *netdev_string;
int rc;
/* Create modifiable copy of string */
tmp = strdup ( string );
if ( ! tmp ) {
rc = -ENOMEM;
goto err_alloc;
}
in_string = tmp;
/* Strip surrounding "[...]", if present */
len = strlen ( in_string );
if ( ( in_string[0] == '[' ) && ( in_string[ len - 1 ] == ']' ) ) {
in_string[ len - 1 ] = '\0';
in_string++;
}
/* Split at network device name, if present */
netdev_string = strchr ( in_string, '%' );
if ( netdev_string )
*(netdev_string++) = '\0';
/* Parse IPv6 address portion */
if ( ( rc = inet6_aton ( in_string, &in ) ) != 0 )
goto err_inet6_aton;
/* Parse network device name, if present */
if ( netdev_string ) {
netdev = find_netdev ( netdev_string );
if ( ! netdev ) {
rc = -ENODEV;
goto err_find_netdev;
}
sin6->sin6_scope_id = netdev->index;
}
/* Copy IPv6 address portion to socket address */
memcpy ( &sin6->sin6_addr, &in, sizeof ( sin6->sin6_addr ) );
err_find_netdev:
err_inet6_aton:
free ( tmp );
err_alloc:
return rc;
}
/** IPv6 protocol */ /** IPv6 protocol */
struct net_protocol ipv6_protocol __net_protocol = { struct net_protocol ipv6_protocol __net_protocol = {
.name = "IPv6", .name = "IPv6",
@ -765,6 +855,13 @@ struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol = {
.tx = ipv6_tx, .tx = ipv6_tx,
}; };
/** IPv6 socket address converter */
struct sockaddr_converter ipv6_sockaddr_converter __sockaddr_converter = {
.family = AF_INET6,
.ntoa = ipv6_sock_ntoa,
.aton = ipv6_sock_aton,
};
/** /**
* Create IPv6 network device * Create IPv6 network device
* *