# -*- coding: utf-8 -*- # # Copyright (C) 2014 Red Hat, Inc. # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions of # the GNU General Public License v.2, or (at your option) any later version. # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY expressed or implied, including the implied warranties of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. You should have received a copy of the # GNU General Public License along with this program; if not, write to the # Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. Any Red Hat trademarks that are incorporated in the # source code or documentation are not subject to the GNU General Public # License and may only be used or replicated with the express permission of # Red Hat, Inc. from pyanaconda import network import unittest class NetworkTests(unittest.TestCase): def test_is_valid_hostname(self): """Test hostname validation.""" assert not network.is_valid_hostname("")[0] assert not network.is_valid_hostname(None)[0] # section length < 64 assert network.is_valid_hostname("h"*63)[0] assert not network.is_valid_hostname("h"*64)[0] # length < 65 assert network.is_valid_hostname("section." * 7+"sectionx")[0] assert not network.is_valid_hostname("section." * 7+"sectionxx")[0] assert not network.is_valid_hostname( "section.must.be..nonempty.")[0] assert not network.is_valid_hostname( ".section.must.be.nonempty.")[0] assert network.is_valid_hostname( "section.can.contain.only.alphanums.012.or.hyp-hens")[0] assert not network.is_valid_hostname( "section.can.contain.only.alphanums.012.or.hyp-hens!!!")[0] assert not network.is_valid_hostname( "section.may.not.start.with.-hyphen")[0] assert not network.is_valid_hostname( "section.may.not.end.with.hyphen-")[0] assert network.is_valid_hostname("0-0.")[0] assert network.is_valid_hostname("0.")[0] assert not network.is_valid_hostname("Lennart's Laptop")[0] assert not network.is_valid_hostname("own.hostname.cannot.end.in.dot.", local=True)[0] def test_prefix2netmask2prefix(self): """Test netmask and prefix conversion.""" lore = [ (0, "0.0.0.0"), (1, "128.0.0.0"), (2, "192.0.0.0"), (3, "224.0.0.0"), (4, "240.0.0.0"), (5, "248.0.0.0"), (6, "252.0.0.0"), (7, "254.0.0.0"), (8, "255.0.0.0"), (9, "255.128.0.0"), (10, "255.192.0.0"), (11, "255.224.0.0"), (12, "255.240.0.0"), (13, "255.248.0.0"), (14, "255.252.0.0"), (15, "255.254.0.0"), (16, "255.255.0.0"), (17, "255.255.128.0"), (18, "255.255.192.0"), (19, "255.255.224.0"), (20, "255.255.240.0"), (21, "255.255.248.0"), (22, "255.255.252.0"), (23, "255.255.254.0"), (24, "255.255.255.0"), (25, "255.255.255.128"), (26, "255.255.255.192"), (27, "255.255.255.224"), (28, "255.255.255.240"), (29, "255.255.255.248"), (30, "255.255.255.252"), (31, "255.255.255.254"), (32, "255.255.255.255"), ] for prefix, netmask in lore: assert network.prefix_to_netmask(prefix) == netmask assert network.netmask_to_prefix(netmask) == prefix assert network.prefix_to_netmask(33) == "255.255.255.255" def test_nm_check_ip_address(self,): """Test IPv4 and IPv6 address checks.""" good_IPv4_tests = [ '1.2.3.4', '0.0.0.0', '10.20.30.40', '255.255.255.255', '249.249.249.249' ] good_IPv6_tests = [ '0000:0000:0000:0000:0000:0000:0000:0000', '0000:0000:0000:0000:0000:0000:1.2.3.4', '::a:b:c:d:e:f:1', '::a:b:c:d:e:255.255.255.255', '1::a:b:c:d:e:f', '1::a:b:c:d:255.255.255.255', '1:12::a:b:c:d:e', '1:12::a:b:c:10.20.30.40', '12::a:b:c:d:e', '12::a:b:c:10.20.30.40', '1:12:123::a:b:c:d', '1:12:123::a:b:100.200.250.249', '12:123::a:b:c:d', '12:123::a:b:100.200.250.249', '123::a:b:c:d', '123::a:b:100.200.250.249', '::a:b:c:d', '::a:b:100.200.250.249', '1:12:123:1234::a:b:c', '1:12:123:1234::a:1.20.30.99', '12:123:1234::a:b:c', '12:123:1234::a:1.20.30.99', '123:1234::a:b:c', '123:1234::a:1.20.30.99', '1234::a:b:c', '1234::a:1.20.30.99', '::a:b:c', '::a:1.20.30.99', '1:12:123:1234:abcd::a:b', '1:12:123:1234:abcd::0.0.0.0', '12:123:1234:abcd::a:b', '12:123:1234:abcd::0.0.0.0', '123:1234:abcd::a:b', '123:1234:abcd::0.0.0.0', '1234:abcd::a:b', '1234:abcd::0.0.0.0', 'abcd::a:b', 'abcd::0.0.0.0', '::a:b', '::0.0.0.0', '1:12:123:1234:dead:beef::aaaa', '12:123:1234:dead:beef::aaaa', '123:1234:dead:beef::aaaa', '1234:dead:beef::aaaa', 'dead:beef::aaaa', 'beef::aaaa', '::aaaa', '::' ] bad_IPv4_tests = [ '1.2.3.', '1.2.3', '256.2.3.4', 'a.b.c.d', '1.2.3.400' '....', '1..2.3' ] bad_IPv6_tests = [ # Too many bits '0000:0000:0000:0000:0000:0000:0000:0000:0000' '0000:0000:0000:0000:0000:0000:0000:1.2.3.4', '0000:0000:0000:0000:0000:0000:1.2.3.4.5', # Not enough bits '0000:0000:0000:0000:0000:0000:0000', '0000:0000:0000:0000:0000:1.2.3.4', # zero-length contractions '0000::0000:0000:0000:0000:0000:1.2.3.4', '0000:0000::0000:0000:0000:0000:1.2.3.4', '0000:0000:0000::0000:0000:0000:1.2.3.4', '0000:0000:0000:0000::0000:0000:1.2.3.4', '0000:0000:0000:0000:0000::0000:1.2.3.4', '0000:0000:0000:0000:0000:0000::1.2.3.4', '123::4567:89:a:bcde:f0f0:aaaa:8', '123:4567::89:a:bcde:f0f0:aaaa:8', '123:4567:89::a:bcde:f0f0:aaaa:8', '123:4567:89:a:bcde::f0f0:aaaa:8', '123:4567:89:a:bcde:f0f0::aaaa:8', '123:4567:89:a:bcde:f0f0:aaaa::8', # too many contractions 'a::b::c', '::a::b', 'a::b::', # invalid numbers '00000::0000', 'defg::', '12345::abcd', 'ffff::0x1e' ] # test good IPv4 for i in good_IPv4_tests: assert network.check_ip_address(i, version=4) assert network.check_ip_address(i) assert not network.check_ip_address(i, version=6) # test bad Ipv4 for i in bad_IPv4_tests: assert not network.check_ip_address(i) assert not network.check_ip_address(i, version=4) assert not network.check_ip_address(i, version=6) # test good IPv6 for i in good_IPv6_tests: assert network.check_ip_address(i, version=6) assert network.check_ip_address(i) assert not network.check_ip_address(i, version=4) # test bad IPv6 for i in bad_IPv6_tests: assert not network.check_ip_address(i) assert not network.check_ip_address(i, version=6) assert not network.check_ip_address(i, version=4) def test_hostname_from_cmdline(self): """Test extraction of hostname from cmdline.""" cmdline = {"ip": "10.34.102.244::10.34.102.54:255.255.255.0:myhostname:ens9:none"} assert network.hostname_from_cmdline(cmdline) == "myhostname" # This case is not officially supported according to dracut.cmdline but # the ip configuration is actually working and we care not to break # hostname setting for it (#1988521) cmdline = {"ip": "10.34.102.244::10.34.102.54:255.255.255.0:myhostname:"} assert network.hostname_from_cmdline(cmdline) == "myhostname" # ip takes precedence cmdline = {"ip": "10.34.102.244::10.34.102.54:255.255.255.0:myhostname:ens9:none", "hostname": "hostname_bootopt"} assert network.hostname_from_cmdline(cmdline) == "myhostname" cmdline = {"ip": "ens3:dhcp"} assert network.hostname_from_cmdline(cmdline) == "" cmdline = {"ip": "ens3:dhcp:1500"} assert network.hostname_from_cmdline(cmdline) == "" cmdline = {"ip": "ens3:dhcp", "hostname": "hostname_bootopt"} assert network.hostname_from_cmdline(cmdline) == "hostname_bootopt" # two ip configurations cmdline = {"ip": "ens3:dhcp 10.34.102.244::10.34.102.54:255.255.255.0:myhostname:ens9:none"} assert network.hostname_from_cmdline(cmdline) == "myhostname" # ipv6 configuration cmdline = {"ip": "[fd00:10:100::84:5]::[fd00:10:100::86:49]:80:myhostname:ens50:none"} assert network.hostname_from_cmdline(cmdline) == "myhostname" cmdline = {"ip": "[fd00:10:100::84:5]:::80:myhostname:ens50:none"} assert network.hostname_from_cmdline(cmdline) == "myhostname" cmdline = {"ip": "[fd00:10:100::84:5]::[fd00:10:100::86:49]:80::ens50:none"} assert network.hostname_from_cmdline(cmdline) == "" cmdline = {"ip": "[fd00:10:100::84:5]::[fd00:10:100::86:49]:80::ens50:none " "ens3:dhcp 10.34.102.244::10.34.102.54:255.255.255.0:myhostname:ens9:none"} assert network.hostname_from_cmdline(cmdline) == "myhostname" # automatic ip= whith MAC address set cmdline = {"ip": "ens3:dhcp::52:54:00:12:34:56"} assert network.hostname_from_cmdline(cmdline) == ""