mirror of
https://github.com/systemd/systemd.git
synced 2024-11-07 18:27:04 +03:00
networkd: add support for IPv6 tokens
This allows the admin to set the host-specific part of IPv6 addresses, but still receive the prefix via SLAAC. .network file snippet: [Network] IPv6Token=::12 gives: $ ip token token ::12 dev eth0 This closes https://bugs.freedesktop.org/show_bug.cgi?id=81177.
This commit is contained in:
parent
d0d6a4cd70
commit
7f77697a17
@ -1097,36 +1097,44 @@ static int link_up(Link *link) {
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_open_container(req, IFLA_AF_SPEC);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not open IFLA_AF_SPEC container: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_open_container(req, AF_INET6);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not open AF_INET6 container: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!link_ipv6ll_enabled(link)) {
|
||||
r = sd_rtnl_message_open_container(req, IFLA_AF_SPEC);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not open IFLA_AF_SPEC container: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_open_container(req, AF_INET6);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not open AF_INET6 container: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, IN6_ADDR_GEN_MODE_NONE);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not append IFLA_INET6_ADDR_GEN_MODE: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_close_container(req);
|
||||
if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) {
|
||||
r = sd_rtnl_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not close AF_INET6 contaire: %s", strerror(-r));
|
||||
log_link_error(link, "Could not append IFLA_INET6_TOKEN: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_close_container(req);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not close IFLA_AF_SPEC contaire: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
r = sd_rtnl_message_close_container(req);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not close AF_INET6 container: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_close_container(req);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not close IFLA_AF_SPEC contaire: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link,
|
||||
|
@ -38,6 +38,7 @@ Network.DHCP, config_parse_dhcp, 0,
|
||||
Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server)
|
||||
Network.LinkLocal, config_parse_address_family_boolean,0, offsetof(Network, link_local)
|
||||
Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route)
|
||||
Network.IPv6Token, config_parse_token, 0, offsetof(Network, ipv6_token)
|
||||
Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp)
|
||||
Network.Address, config_parse_address, 0, 0
|
||||
Network.Gateway, config_parse_gateway, 0, 0
|
||||
|
@ -626,7 +626,7 @@ int config_parse_llmnr(
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
assert(llmnr);
|
||||
|
||||
/* Our enum shall be a superset of booleans, hence first try
|
||||
* to parse as boolean, and then as enum */
|
||||
@ -650,3 +650,46 @@ int config_parse_llmnr(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_token(
|
||||
const char* unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
union in_addr_union buffer;
|
||||
struct in6_addr *token = data;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(token);
|
||||
|
||||
r = in_addr_from_string(AF_INET6, rvalue, &buffer);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse IPv6 token, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = in_addr_is_null(AF_INET6, &buffer);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, -r, "IPv6 token canno t be the ANY address, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, EINVAL, "IPv6 token canno t be longer than 64 bits, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*token = buffer.in6;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -128,6 +128,7 @@ struct Network {
|
||||
unsigned dhcp_route_metric;
|
||||
AddressFamilyBoolean link_local;
|
||||
bool ipv4ll_route;
|
||||
union in_addr_union ipv6_token;
|
||||
|
||||
bool dhcp_server;
|
||||
|
||||
@ -405,6 +406,11 @@ int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line,
|
||||
const char *section, unsigned section_line, const char *lvalue,
|
||||
int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
/* IPv6 support */
|
||||
int config_parse_token(const char *unit, const char *filename, unsigned line,
|
||||
const char *section, unsigned section_line, const char *lvalue,
|
||||
int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
/* LLMNR support */
|
||||
|
||||
const char* llmnr_support_to_string(LLMNRSupport i) _const_;
|
||||
|
Loading…
Reference in New Issue
Block a user