mirror of https://github.com/ipxe/ipxe.git
[ipv6] Add IPv6 socket address converter
Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/14/merge
parent
365a09d867
commit
2c76c1a6d8
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue