Skip to content

Commit 56db162

Browse files
authored
[config] Fix config int add incorrect ip (sonic-net#1414)
* Added ip and mask check to config int Signed-off-by: d-dashkov <Dmytro_Dashkov@Jabil.com>
1 parent 1da879c commit 56db162

File tree

2 files changed

+183
-2
lines changed

2 files changed

+183
-2
lines changed

config/main.py

100755100644
+26-2
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,22 @@ def validate_mirror_session_config(config_db, session_name, dst_port, src_port,
779779

780780
return True
781781

782+
def validate_ip_mask(ctx, ip_addr):
783+
split_ip_mask = ip_addr.split("/")
784+
# Check if the IP address is correct or if there are leading zeros.
785+
ip_obj = ipaddress.ip_address(split_ip_mask[0])
786+
787+
# Check if the mask is correct
788+
mask_range = 33 if isinstance(ip_obj, ipaddress.IPv4Address) else 129
789+
# If mask is not specified
790+
if len(split_ip_mask) < 2:
791+
return 0
792+
793+
if not int(split_ip_mask[1]) in range(1, mask_range):
794+
return 0
795+
796+
return str(ip_obj) + '/' + str(int(split_ip_mask[1]))
797+
782798
def cli_sroute_to_config(ctx, command_str, strict_nh = True):
783799
if len(command_str) < 2 or len(command_str) > 9:
784800
ctx.fail("argument is not in pattern prefix [vrf <vrf_name>] <A.B.C.D/M> nexthop <[vrf <vrf_name>] <A.B.C.D>>|<dev <dev_name>>!")
@@ -3473,6 +3489,10 @@ def add(ctx, interface_name, ip_addr, gw):
34733489
if '/' not in ip_addr:
34743490
ip_addr = str(net)
34753491

3492+
ip_addr = validate_ip_mask(ctx, ip_addr)
3493+
if not ip_addr:
3494+
raise ValueError('')
3495+
34763496
if interface_name == 'eth0':
34773497

34783498
# Configuring more than 1 IPv4 or more than 1 IPv6 address fails.
@@ -3509,7 +3529,7 @@ def add(ctx, interface_name, ip_addr, gw):
35093529
config_db.set_entry(table_name, interface_name, {"NULL": "NULL"})
35103530
config_db.set_entry(table_name, (interface_name, ip_addr), {"NULL": "NULL"})
35113531
except ValueError:
3512-
ctx.fail("'ip_addr' is not valid.")
3532+
ctx.fail("ip address or mask is not valid.")
35133533

35143534
#
35153535
# 'del' subcommand
@@ -3533,6 +3553,10 @@ def remove(ctx, interface_name, ip_addr):
35333553
net = ipaddress.ip_network(ip_addr, strict=False)
35343554
if '/' not in ip_addr:
35353555
ip_addr = str(net)
3556+
3557+
ip_addr = validate_ip_mask(ctx, ip_addr)
3558+
if not ip_addr:
3559+
raise ValueError('')
35363560

35373561
if interface_name == 'eth0':
35383562
config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), None)
@@ -3572,7 +3596,7 @@ def remove(ctx, interface_name, ip_addr):
35723596
command = "ip neigh flush dev {} {}".format(interface_name, ip_addr)
35733597
clicommon.run_command(command)
35743598
except ValueError:
3575-
ctx.fail("'ip_addr' is not valid.")
3599+
ctx.fail("ip address or mask is not valid.")
35763600

35773601

35783602
#

tests/ip_config_test.py

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import os
2+
import traceback
3+
from unittest import mock
4+
5+
from click.testing import CliRunner
6+
7+
import config.main as config
8+
import show.main as show
9+
from utilities_common.db import Db
10+
11+
ERROR_MSG = '''
12+
Error: ip address or mask is not valid.
13+
'''
14+
15+
class TestConfigIP(object):
16+
@classmethod
17+
def setup_class(cls):
18+
os.environ['UTILITIES_UNIT_TESTING'] = "1"
19+
print("SETUP")
20+
21+
''' Tests for IPv4 '''
22+
23+
def test_add_del_interface_valid_ipv4(self):
24+
db = Db()
25+
runner = CliRunner()
26+
obj = {'config_db':db.cfgdb}
27+
28+
# config int ip add Ethernet64 10.10.10.1/24
29+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Ethernet64", "10.10.10.1/24"], obj=obj)
30+
print(result.exit_code, result.output)
31+
assert result.exit_code == 0
32+
assert ('Ethernet64', '10.10.10.1/24') in db.cfgdb.get_table('INTERFACE')
33+
34+
# config int ip remove Ethernet64 10.10.10.1/24
35+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Ethernet64", "10.10.10.1/24"], obj=obj)
36+
print(result.exit_code, result.output)
37+
assert result.exit_code != 0
38+
assert ('Ethernet64', '10.10.10.1/24') not in db.cfgdb.get_table('INTERFACE')
39+
40+
def test_add_interface_invalid_ipv4(self):
41+
db = Db()
42+
runner = CliRunner()
43+
obj = {'config_db':db.cfgdb}
44+
45+
# config int ip add Ethernet64 10000.10.10.1/24
46+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Ethernet64", "10000.10.10.1/24"], obj=obj)
47+
print(result.exit_code, result.output)
48+
assert result.exit_code != 0
49+
assert ERROR_MSG in result.output
50+
51+
def test_add_interface_ipv4_invalid_mask(self):
52+
db = Db()
53+
runner = CliRunner()
54+
obj = {'config_db':db.cfgdb}
55+
56+
# config int ip add Ethernet64 10.10.10.1/37
57+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Ethernet64", "10.10.10.1/37"], obj=obj)
58+
print(result.exit_code, result.output)
59+
assert result.exit_code != 0
60+
assert ERROR_MSG in result.output
61+
62+
def test_add_del_interface_ipv4_with_leading_zeros(self):
63+
db = Db()
64+
runner = CliRunner()
65+
obj = {'config_db':db.cfgdb}
66+
67+
# config int ip add Ethernet68 10.10.10.002/24
68+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Ethernet68", "10.10.10.002/24"], obj=obj)
69+
print(result.exit_code, result.output)
70+
assert result.exit_code == 0
71+
assert ('Ethernet68', '10.10.10.2/24') in db.cfgdb.get_table('INTERFACE')
72+
73+
# config int ip remove Ethernet68 10.10.10.002/24
74+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Ethernet68", "10.10.10.002/24"], obj=obj)
75+
print(result.exit_code, result.output)
76+
assert result.exit_code != 0
77+
assert ('Ethernet68', '10.10.10.2/24') not in db.cfgdb.get_table('INTERFACE')
78+
79+
''' Tests for IPv6 '''
80+
81+
def test_add_del_interface_valid_ipv6(self):
82+
db = Db()
83+
runner = CliRunner()
84+
obj = {'config_db':db.cfgdb}
85+
86+
# config int ip add Ethernet72 2001:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34
87+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Ethernet72", "2001:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34"], obj=obj)
88+
print(result.exit_code, result.output)
89+
assert result.exit_code == 0
90+
assert ('Ethernet72', '2001:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34') in db.cfgdb.get_table('INTERFACE')
91+
92+
# config int ip remove Ethernet72 2001:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34
93+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Ethernet72", "2001:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34"], obj=obj)
94+
print(result.exit_code, result.output)
95+
assert result.exit_code != 0
96+
assert ('Ethernet72', '2001:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34') not in db.cfgdb.get_table('INTERFACE')
97+
98+
def test_add_interface_invalid_ipv6(self):
99+
db = Db()
100+
runner = CliRunner()
101+
obj = {'config_db':db.cfgdb}
102+
103+
# config int ip add Ethernet72 20001:0db8:11a3:09d7:1f34:8a2e:07a0:765d/34
104+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Ethernet72", "20001:0db8:11a3:19d7:1f34:8a2e:17a0:765d/34"], obj=obj)
105+
print(result.exit_code, result.output)
106+
assert result.exit_code != 0
107+
assert ERROR_MSG in result.output
108+
109+
def test_add_interface_ipv6_invalid_mask(self):
110+
db = Db()
111+
runner = CliRunner()
112+
obj = {'config_db':db.cfgdb}
113+
114+
# config int ip add Ethernet72 2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d/200
115+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Ethernet72", "2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d/200"], obj=obj)
116+
print(result.exit_code, result.output)
117+
assert result.exit_code != 0
118+
assert ERROR_MSG in result.output
119+
120+
def test_add_del_interface_ipv6_with_leading_zeros(self):
121+
db = Db()
122+
runner = CliRunner()
123+
obj = {'config_db':db.cfgdb}
124+
125+
# config int ip del Ethernet68 2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d/34
126+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Ethernet68", "2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d/34"], obj=obj)
127+
print(result.exit_code, result.output)
128+
assert result.exit_code == 0
129+
assert ('Ethernet68', '2001:db8:11a3:9d7:1f34:8a2e:7a0:765d/34') in db.cfgdb.get_table('INTERFACE')
130+
131+
# config int ip remove Ethernet68 2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d/34
132+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Ethernet68", "2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d/34"], obj=obj)
133+
print(result.exit_code, result.output)
134+
assert result.exit_code != 0
135+
assert ('Ethernet68', '2001:db8:11a3:9d7:1f34:8a2e:7a0:765d/34') not in db.cfgdb.get_table('INTERFACE')
136+
137+
def test_add_del_interface_shortened_ipv6_with_leading_zeros(self):
138+
db = Db()
139+
runner = CliRunner()
140+
obj = {'config_db':db.cfgdb}
141+
142+
# config int ip del Ethernet68 3000::001/64
143+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Ethernet68", "3000::001/64"], obj=obj)
144+
print(result.exit_code, result.output)
145+
assert result.exit_code == 0
146+
assert ('Ethernet68', '3000::1/64') in db.cfgdb.get_table('INTERFACE')
147+
148+
# config int ip remove Ethernet68 3000::001/64
149+
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Ethernet68", "3000::001/64"], obj=obj)
150+
print(result.exit_code, result.output)
151+
assert result.exit_code != 0
152+
assert ('Ethernet68', '3000::1/64') not in db.cfgdb.get_table('INTERFACE')
153+
154+
@classmethod
155+
def teardown_class(cls):
156+
os.environ['UTILITIES_UNIT_TESTING'] = "0"
157+
print("TEARDOWN")

0 commit comments

Comments
 (0)