[ipv6] Expose IPv6 link-local address settings
Originally-implemented-by: Hannes Reinecke <hare@suse.de> Originally-implemented-by: Marin Hannache <git@mareo.fr> Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
parent
03d19cf14d
commit
1fdc7da435
|
@ -238,6 +238,9 @@ static inline void ipv6_all_routers ( struct in6_addr *addr ) {
|
||||||
addr->s6_addr[15] = 2;
|
addr->s6_addr[15] = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** IPv6 link-local address settings block name */
|
||||||
|
#define IPV6_SETTINGS_NAME "link"
|
||||||
|
|
||||||
extern struct list_head ipv6_miniroutes;
|
extern struct list_head ipv6_miniroutes;
|
||||||
|
|
||||||
extern struct net_protocol ipv6_protocol __net_protocol;
|
extern struct net_protocol ipv6_protocol __net_protocol;
|
||||||
|
|
113
src/net/ipv6.c
113
src/net/ipv6.c
|
@ -1088,6 +1088,115 @@ const struct setting gateway6_setting __setting ( SETTING_IP6, gateway6 ) = {
|
||||||
.scope = &ipv6_scope,
|
.scope = &ipv6_scope,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check applicability of IPv6 link-local address setting
|
||||||
|
*
|
||||||
|
* @v settings Settings block
|
||||||
|
* @v setting Setting to fetch
|
||||||
|
* @ret applies Setting applies within this settings block
|
||||||
|
*/
|
||||||
|
static int ipv6_applies ( struct settings *settings __unused,
|
||||||
|
const struct setting *setting ) {
|
||||||
|
|
||||||
|
return ( setting->scope == &ipv6_scope );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch IPv6 link-local address setting
|
||||||
|
*
|
||||||
|
* @v settings Settings block
|
||||||
|
* @v setting Setting to fetch
|
||||||
|
* @v data Buffer to fill with setting data
|
||||||
|
* @v len Length of buffer
|
||||||
|
* @ret len Length of setting data, or negative error
|
||||||
|
*/
|
||||||
|
static int ipv6_fetch ( struct settings *settings, struct setting *setting,
|
||||||
|
void *data, size_t len ) {
|
||||||
|
struct net_device *netdev =
|
||||||
|
container_of ( settings->parent, struct net_device,
|
||||||
|
settings.settings );
|
||||||
|
struct in6_addr ip6;
|
||||||
|
uint8_t *len6;
|
||||||
|
int prefix_len;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Construct link-local address from EUI-64 as per RFC 2464 */
|
||||||
|
memset ( &ip6, 0, sizeof ( ip6 ) );
|
||||||
|
prefix_len = ipv6_link_local ( &ip6, netdev );
|
||||||
|
if ( prefix_len < 0 ) {
|
||||||
|
rc = prefix_len;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle setting */
|
||||||
|
if ( setting_cmp ( setting, &ip6_setting ) == 0 ) {
|
||||||
|
|
||||||
|
/* Return link-local ip6 */
|
||||||
|
if ( len > sizeof ( ip6 ) )
|
||||||
|
len = sizeof ( ip6 );
|
||||||
|
memcpy ( data, &ip6, len );
|
||||||
|
return sizeof ( ip6 );
|
||||||
|
|
||||||
|
} else if ( setting_cmp ( setting, &len6_setting ) == 0 ) {
|
||||||
|
|
||||||
|
/* Return prefix length */
|
||||||
|
if ( len ) {
|
||||||
|
len6 = data;
|
||||||
|
*len6 = prefix_len;
|
||||||
|
}
|
||||||
|
return sizeof ( *len6 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** IPv6 link-local address settings operations */
|
||||||
|
static struct settings_operations ipv6_settings_operations = {
|
||||||
|
.applies = ipv6_applies,
|
||||||
|
.fetch = ipv6_fetch,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** IPv6 link-local address settings */
|
||||||
|
struct ipv6_settings {
|
||||||
|
/** Reference counter */
|
||||||
|
struct refcnt refcnt;
|
||||||
|
/** Settings interface */
|
||||||
|
struct settings settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register IPv6 link-local address settings
|
||||||
|
*
|
||||||
|
* @v netdev Network device
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int ipv6_register_settings ( struct net_device *netdev ) {
|
||||||
|
struct settings *parent = netdev_settings ( netdev );
|
||||||
|
struct ipv6_settings *ipv6set;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Allocate and initialise structure */
|
||||||
|
ipv6set = zalloc ( sizeof ( *ipv6set ) );
|
||||||
|
if ( ! ipv6set ) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err_alloc;
|
||||||
|
}
|
||||||
|
ref_init ( &ipv6set->refcnt, NULL );
|
||||||
|
settings_init ( &ipv6set->settings, &ipv6_settings_operations,
|
||||||
|
&ipv6set->refcnt, &ipv6_scope );
|
||||||
|
|
||||||
|
/* Register settings */
|
||||||
|
if ( ( rc = register_settings ( &ipv6set->settings, parent,
|
||||||
|
IPV6_SETTINGS_NAME ) ) != 0 )
|
||||||
|
goto err_register;
|
||||||
|
|
||||||
|
err_register:
|
||||||
|
ref_put ( &ipv6set->refcnt );
|
||||||
|
err_alloc:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create IPv6 network device
|
* Create IPv6 network device
|
||||||
*
|
*
|
||||||
|
@ -1116,6 +1225,10 @@ static int ipv6_probe ( struct net_device *netdev ) {
|
||||||
if ( ! miniroute )
|
if ( ! miniroute )
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* Register link-local address settings */
|
||||||
|
if ( ( rc = ipv6_register_settings ( netdev ) ) != 0 )
|
||||||
|
return rc;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue