|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# Copyright (c) 2018-2019 Red Hat, Inc.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# This file is part of nmstate
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# This program is free software: you can redistribute it and/or modify
|
|
Packit Service |
0535c1 |
# it under the terms of the GNU Lesser General Public License as published by
|
|
Packit Service |
0535c1 |
# the Free Software Foundation, either version 2.1 of the License, or
|
|
Packit Service |
0535c1 |
# (at your option) any later version.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# This program is distributed in the hope that it will be useful,
|
|
Packit Service |
0535c1 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
0535c1 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
0535c1 |
# GNU Lesser General Public License for more details.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
0535c1 |
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
import logging
|
|
Packit Service |
0535c1 |
import socket
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
from libnmstate import iplib
|
|
Packit Service |
0535c1 |
from libnmstate.error import NmstateNotImplementedError
|
|
Packit Service |
0535c1 |
from libnmstate.nm import dns as nm_dns
|
|
Packit Service |
0535c1 |
from libnmstate.nm import route as nm_route
|
|
Packit Service |
0535c1 |
from libnmstate.schema import InterfaceIPv6
|
|
Packit Service |
0535c1 |
from libnmstate.schema import Route
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
from ..ifaces import BaseIface
|
|
Packit Service |
0535c1 |
from .common import NM
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
IPV6_DEFAULT_ROUTE_METRIC = 1024
|
|
Packit Service |
0535c1 |
INT32_MAX = 2 ** 31 - 1
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def get_info(active_connection):
|
|
Packit Service |
0535c1 |
info = {InterfaceIPv6.ENABLED: False}
|
|
Packit Service |
0535c1 |
if active_connection is None:
|
|
Packit Service |
0535c1 |
return info
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.DHCP] = False
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.AUTOCONF] = False
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
is_link_local_method = False
|
|
Packit Service |
0535c1 |
ip_profile = get_ip_profile(active_connection)
|
|
Packit Service |
0535c1 |
if ip_profile:
|
|
Packit Service |
0535c1 |
method = ip_profile.get_method()
|
|
Packit Service |
0535c1 |
if method == NM.SETTING_IP6_CONFIG_METHOD_AUTO:
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.DHCP] = True
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.AUTOCONF] = True
|
|
Packit Service |
0535c1 |
elif method == NM.SETTING_IP6_CONFIG_METHOD_DHCP:
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.DHCP] = True
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.AUTOCONF] = False
|
|
Packit Service |
0535c1 |
elif method == NM.SETTING_IP6_CONFIG_METHOD_LINK_LOCAL:
|
|
Packit Service |
0535c1 |
is_link_local_method = True
|
|
Packit Service |
0535c1 |
elif method == NM.SETTING_IP6_CONFIG_METHOD_DISABLED:
|
|
Packit Service |
0535c1 |
return info
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
if info[InterfaceIPv6.DHCP] or info[InterfaceIPv6.AUTOCONF]:
|
|
Packit Service |
0535c1 |
props = ip_profile.props
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.AUTO_ROUTES] = not props.ignore_auto_routes
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.AUTO_GATEWAY] = not props.never_default
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.AUTO_DNS] = not props.ignore_auto_dns
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
ipconfig = active_connection.get_ip6_config()
|
|
Packit Service |
0535c1 |
if ipconfig is None:
|
|
Packit Service |
0535c1 |
# When DHCP is enable, it might be possible, the active_connection does
|
|
Packit Service |
0535c1 |
# not got IP address yet. In that case, we still mark
|
|
Packit Service |
0535c1 |
# info[InterfaceIPv6.ENABLED] as True.
|
|
Packit Service |
0535c1 |
if (
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.DHCP]
|
|
Packit Service |
0535c1 |
or info[InterfaceIPv6.AUTOCONF]
|
|
Packit Service |
0535c1 |
or is_link_local_method
|
|
Packit Service |
0535c1 |
):
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.ENABLED] = True
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.ADDRESS] = []
|
|
Packit Service |
0535c1 |
else:
|
|
Packit Service |
0535c1 |
del info[InterfaceIPv6.DHCP]
|
|
Packit Service |
0535c1 |
del info[InterfaceIPv6.AUTOCONF]
|
|
Packit Service |
0535c1 |
return info
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
addresses = [
|
|
Packit Service |
0535c1 |
{
|
|
Packit Service |
0535c1 |
InterfaceIPv6.ADDRESS_IP: address.get_address(),
|
|
Packit Service |
0535c1 |
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: int(address.get_prefix()),
|
|
Packit Service |
0535c1 |
}
|
|
Packit Service |
0535c1 |
for address in ipconfig.get_addresses()
|
|
Packit Service |
0535c1 |
]
|
|
Packit Service |
0535c1 |
if not addresses:
|
|
Packit Service |
0535c1 |
return info
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.ENABLED] = True
|
|
Packit Service |
0535c1 |
info[InterfaceIPv6.ADDRESS] = addresses
|
|
Packit Service |
0535c1 |
return info
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def create_setting(config, base_con_profile):
|
|
Packit Service |
0535c1 |
setting_ip = None
|
|
Packit Service |
0535c1 |
if base_con_profile and config and config.get(InterfaceIPv6.ENABLED):
|
|
Packit Service |
0535c1 |
setting_ip = base_con_profile.get_setting_ip6_config()
|
|
Packit Service |
0535c1 |
if setting_ip:
|
|
Packit Service |
0535c1 |
setting_ip = setting_ip.duplicate()
|
|
Packit Service |
0535c1 |
setting_ip.clear_addresses()
|
|
Packit Service |
0535c1 |
setting_ip.props.ignore_auto_routes = False
|
|
Packit Service |
0535c1 |
setting_ip.props.never_default = False
|
|
Packit Service |
0535c1 |
setting_ip.props.ignore_auto_dns = False
|
|
Packit Service |
0535c1 |
setting_ip.clear_routes()
|
|
Packit Service |
fec588 |
setting_ip.clear_routing_rules()
|
|
Packit Service |
0535c1 |
setting_ip.props.gateway = None
|
|
Packit Service |
0535c1 |
setting_ip.props.route_table = Route.USE_DEFAULT_ROUTE_TABLE
|
|
Packit Service |
0535c1 |
setting_ip.props.route_metric = Route.USE_DEFAULT_METRIC
|
|
Packit Service |
0535c1 |
setting_ip.clear_dns()
|
|
Packit Service |
0535c1 |
setting_ip.clear_dns_searches()
|
|
Packit Service |
0535c1 |
setting_ip.props.dns_priority = nm_dns.DEFAULT_DNS_PRIORITY
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
if not setting_ip:
|
|
Packit Service |
0535c1 |
setting_ip = NM.SettingIP6Config.new()
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
# Ensure IPv6 RA and DHCPv6 is based on MAC address only
|
|
Packit Service |
0535c1 |
setting_ip.props.addr_gen_mode = NM.SettingIP6ConfigAddrGenMode.EUI64
|
|
Packit Service |
0535c1 |
setting_ip.props.dhcp_duid = "ll"
|
|
Packit Service |
0535c1 |
setting_ip.props.dhcp_iaid = "mac"
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
if not config or not config.get(InterfaceIPv6.ENABLED):
|
|
Packit Service |
0535c1 |
setting_ip.props.method = NM.SETTING_IP6_CONFIG_METHOD_DISABLED
|
|
Packit Service |
0535c1 |
return setting_ip
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
is_dhcp = config.get(InterfaceIPv6.DHCP, False)
|
|
Packit Service |
0535c1 |
is_autoconf = config.get(InterfaceIPv6.AUTOCONF, False)
|
|
Packit Service |
0535c1 |
ip_addresses = config.get(InterfaceIPv6.ADDRESS, ())
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
if is_dhcp or is_autoconf:
|
|
Packit Service |
0535c1 |
_set_dynamic(setting_ip, is_dhcp, is_autoconf)
|
|
Packit Service |
0535c1 |
# NetworkManager will remove the virtual interface when DHCPv6 or
|
|
Packit Service |
0535c1 |
# IPv6-RA timeout, set them to infinity.
|
|
Packit Service |
0535c1 |
setting_ip.props.dhcp_timeout = INT32_MAX
|
|
Packit Service |
0535c1 |
setting_ip.props.ra_timeout = INT32_MAX
|
|
Packit Service |
0535c1 |
setting_ip.props.ignore_auto_routes = not config.get(
|
|
Packit Service |
0535c1 |
InterfaceIPv6.AUTO_ROUTES, True
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
setting_ip.props.never_default = not config.get(
|
|
Packit Service |
0535c1 |
InterfaceIPv6.AUTO_GATEWAY, True
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
setting_ip.props.ignore_auto_dns = not config.get(
|
|
Packit Service |
0535c1 |
InterfaceIPv6.AUTO_DNS, True
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
elif ip_addresses:
|
|
Packit Service |
0535c1 |
_set_static(setting_ip, ip_addresses)
|
|
Packit Service |
0535c1 |
else:
|
|
Packit Service |
0535c1 |
setting_ip.props.method = NM.SETTING_IP6_CONFIG_METHOD_LINK_LOCAL
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
nm_route.add_routes(setting_ip, config.get(BaseIface.ROUTES_METADATA, []))
|
|
Packit Service |
0535c1 |
nm_dns.add_dns(setting_ip, config.get(BaseIface.DNS_METADATA, {}))
|
|
Packit Service |
0535c1 |
nm_route.add_route_rules(
|
|
Packit Service |
0535c1 |
setting_ip,
|
|
Packit Service |
0535c1 |
socket.AF_INET6,
|
|
Packit Service |
0535c1 |
config.get(BaseIface.ROUTE_RULES_METADATA, []),
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
return setting_ip
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def _set_dynamic(setting_ip, is_dhcp, is_autoconf):
|
|
Packit Service |
0535c1 |
if not is_dhcp and is_autoconf:
|
|
Packit Service |
0535c1 |
raise NmstateNotImplementedError(
|
|
Packit Service |
0535c1 |
"Autoconf without DHCP is not supported yet"
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
if is_dhcp and is_autoconf:
|
|
Packit Service |
0535c1 |
setting_ip.props.method = NM.SETTING_IP6_CONFIG_METHOD_AUTO
|
|
Packit Service |
0535c1 |
elif is_dhcp and not is_autoconf:
|
|
Packit Service |
0535c1 |
setting_ip.props.method = NM.SETTING_IP6_CONFIG_METHOD_DHCP
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def _set_static(setting_ip, ip_addresses):
|
|
Packit Service |
0535c1 |
for address in ip_addresses:
|
|
Packit Service |
0535c1 |
if iplib.is_ipv6_link_local_addr(
|
|
Packit Service |
0535c1 |
address[InterfaceIPv6.ADDRESS_IP],
|
|
Packit Service |
0535c1 |
address[InterfaceIPv6.ADDRESS_PREFIX_LENGTH],
|
|
Packit Service |
0535c1 |
):
|
|
Packit Service |
0535c1 |
logging.warning(
|
|
Packit Service |
0535c1 |
"IPv6 link local address "
|
|
Packit Service |
0535c1 |
"{a[ip]}/{a[prefix-length]} is ignored "
|
|
Packit Service |
0535c1 |
"when applying desired state".format(a=address)
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
else:
|
|
Packit Service |
0535c1 |
naddr = NM.IPAddress.new(
|
|
Packit Service |
0535c1 |
socket.AF_INET6,
|
|
Packit Service |
0535c1 |
address[InterfaceIPv6.ADDRESS_IP],
|
|
Packit Service |
0535c1 |
address[InterfaceIPv6.ADDRESS_PREFIX_LENGTH],
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
setting_ip.add_address(naddr)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
if setting_ip.props.addresses:
|
|
Packit Service |
0535c1 |
setting_ip.props.method = NM.SETTING_IP6_CONFIG_METHOD_MANUAL
|
|
Packit Service |
0535c1 |
else:
|
|
Packit Service |
0535c1 |
setting_ip.props.method = NM.SETTING_IP6_CONFIG_METHOD_LINK_LOCAL
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def get_ip_profile(active_connection):
|
|
Packit Service |
0535c1 |
"""
|
|
Packit Service |
0535c1 |
Get NMSettingIP6Config from NMActiveConnection.
|
|
Packit Service |
0535c1 |
For any error, return None.
|
|
Packit Service |
0535c1 |
"""
|
|
Packit Service |
0535c1 |
remote_conn = active_connection.get_connection()
|
|
Packit Service |
0535c1 |
if remote_conn:
|
|
Packit Service |
0535c1 |
return remote_conn.get_setting_ip6_config()
|
|
Packit Service |
0535c1 |
return None
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def get_route_running(nm_client):
|
|
Packit Service |
0535c1 |
return nm_route.get_running(_acs_and_ip_cfgs(nm_client))
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def get_route_config(nm_client):
|
|
Packit Service |
0535c1 |
routes = nm_route.get_config(acs_and_ip_profiles(nm_client))
|
|
Packit Service |
0535c1 |
for route in routes:
|
|
Packit Service |
0535c1 |
if route[Route.METRIC] == 0:
|
|
Packit Service |
0535c1 |
# Kernel will convert 0 to IPV6_DEFAULT_ROUTE_METRIC.
|
|
Packit Service |
0535c1 |
route[Route.METRIC] = IPV6_DEFAULT_ROUTE_METRIC
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
return routes
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def _acs_and_ip_cfgs(nm_client):
|
|
Packit Service |
0535c1 |
for ac in nm_client.get_active_connections():
|
|
Packit Service |
0535c1 |
ip_cfg = ac.get_ip6_config()
|
|
Packit Service |
0535c1 |
if not ip_cfg:
|
|
Packit Service |
0535c1 |
continue
|
|
Packit Service |
0535c1 |
yield ac, ip_cfg
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def acs_and_ip_profiles(nm_client):
|
|
Packit Service |
0535c1 |
for ac in nm_client.get_active_connections():
|
|
Packit Service |
0535c1 |
ip_profile = get_ip_profile(ac)
|
|
Packit Service |
0535c1 |
if not ip_profile:
|
|
Packit Service |
0535c1 |
continue
|
|
Packit Service |
0535c1 |
yield ac, ip_profile
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def is_dynamic(active_connection):
|
|
Packit Service |
0535c1 |
ip_profile = get_ip_profile(active_connection)
|
|
Packit Service |
0535c1 |
if ip_profile:
|
|
Packit Service |
0535c1 |
method = ip_profile.get_method()
|
|
Packit Service |
0535c1 |
return method in (
|
|
Packit Service |
0535c1 |
NM.SETTING_IP6_CONFIG_METHOD_AUTO,
|
|
Packit Service |
0535c1 |
NM.SETTING_IP6_CONFIG_METHOD_DHCP,
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
return False
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def get_routing_rule_config(nm_client):
|
|
Packit Service |
0535c1 |
return nm_route.get_routing_rule_config(acs_and_ip_profiles(nm_client))
|