From df72b1602285127aa3bf4f99700959cae93bab71 Mon Sep 17 00:00:00 2001 From: Dave Marquardt Date: Fri, 6 Jan 2023 10:00:58 -0600 Subject: [PATCH 01/10] Start to fix AIX ARP support --- jc/parsers/arp.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/jc/parsers/arp.py b/jc/parsers/arp.py index 130fa7a1..2036f39e 100644 --- a/jc/parsers/arp.py +++ b/jc/parsers/arp.py @@ -222,14 +222,24 @@ def parse( else: for line in cleandata: splitline = line.split() - if '' not in splitline: + + # Ignore AIX bucket information + if 'bucket:' in splitline[0]: + continue + elif 'There' in splitline[0] and 'are' in splitline[1]: + continue + + elif '' not in splitline: output_line = { 'name': splitline[0], 'address': splitline[1].lstrip('(').rstrip(')'), 'hwtype': splitline[4].lstrip('[').rstrip(']'), 'hwaddress': splitline[3], - 'iface': splitline[6], } + # AIX tells what bucket the entry is in, and no interface + # information + if 'in' not in splitline[6]: + output_line['iface'] = splitline[6] else: output_line = { From 02a7e5fd8a986c498367bdfeb5b872cbe5495c87 Mon Sep 17 00:00:00 2001 From: Dave Marquardt Date: Fri, 6 Jan 2023 10:08:33 -0600 Subject: [PATCH 02/10] Updated ARP incomplete handling for AIX --- jc/parsers/arp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jc/parsers/arp.py b/jc/parsers/arp.py index 2036f39e..805d30d5 100644 --- a/jc/parsers/arp.py +++ b/jc/parsers/arp.py @@ -229,7 +229,7 @@ def parse( elif 'There' in splitline[0] and 'are' in splitline[1]: continue - elif '' not in splitline: + elif ('','(incomplete)') not in splitline: output_line = { 'name': splitline[0], 'address': splitline[1].lstrip('(').rstrip(')'), From 19a67daabf89d5a61b171778723c97d3720f5963 Mon Sep 17 00:00:00 2001 From: Dave Marquardt Date: Fri, 6 Jan 2023 10:12:50 -0600 Subject: [PATCH 03/10] rewrite check for incomplete ARP entries --- jc/parsers/arp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jc/parsers/arp.py b/jc/parsers/arp.py index 805d30d5..f82f9dc4 100644 --- a/jc/parsers/arp.py +++ b/jc/parsers/arp.py @@ -229,7 +229,7 @@ def parse( elif 'There' in splitline[0] and 'are' in splitline[1]: continue - elif ('','(incomplete)') not in splitline: + elif '' not in splitline and '(incomplete)' not in splitline: output_line = { 'name': splitline[0], 'address': splitline[1].lstrip('(').rstrip(')'), From 3582497ed4aa65988a20aafde5d0ab11497b74e0 Mon Sep 17 00:00:00 2001 From: Dave Marquardt Date: Fri, 6 Jan 2023 10:16:13 -0600 Subject: [PATCH 04/10] Fix interface parsing for incomplete ARP entry on AIX --- jc/parsers/arp.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jc/parsers/arp.py b/jc/parsers/arp.py index f82f9dc4..d001915b 100644 --- a/jc/parsers/arp.py +++ b/jc/parsers/arp.py @@ -247,8 +247,9 @@ def parse( 'address': splitline[1].lstrip('(').rstrip(')'), 'hwtype': None, 'hwaddress': None, - 'iface': splitline[5], } + if len(splitline) >= 5: + output_line['iface'] = splitline[5] raw_output.append(output_line) From 3fae50e305a16ba6972e95126a5fc5e222cb46f7 Mon Sep 17 00:00:00 2001 From: Dave Marquardt Date: Fri, 6 Jan 2023 10:21:32 -0600 Subject: [PATCH 05/10] Handle permanent ARP entries on AIX --- jc/parsers/arp.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jc/parsers/arp.py b/jc/parsers/arp.py index d001915b..f816283f 100644 --- a/jc/parsers/arp.py +++ b/jc/parsers/arp.py @@ -248,7 +248,9 @@ def parse( 'hwtype': None, 'hwaddress': None, } - if len(splitline) >= 5: + if 'permanent' in splitline: + output_line['permanent'] = True + elif len(splitline) >= 5: output_line['iface'] = splitline[5] raw_output.append(output_line) From 9190a0833265cc336c420261b940dae92cae2a1a Mon Sep 17 00:00:00 2001 From: Dave Marquardt Date: Fri, 6 Jan 2023 10:25:04 -0600 Subject: [PATCH 06/10] More AIX permanent ARP entry fixes --- jc/parsers/arp.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jc/parsers/arp.py b/jc/parsers/arp.py index f816283f..86f9ba77 100644 --- a/jc/parsers/arp.py +++ b/jc/parsers/arp.py @@ -238,7 +238,9 @@ def parse( } # AIX tells what bucket the entry is in, and no interface # information - if 'in' not in splitline[6]: + if 'permanent' in splitline: + output_line['permanent'] = True + elif 'in' not in splitline[6]: output_line['iface'] = splitline[6] else: @@ -248,9 +250,7 @@ def parse( 'hwtype': None, 'hwaddress': None, } - if 'permanent' in splitline: - output_line['permanent'] = True - elif len(splitline) >= 5: + if len(splitline) >= 5: output_line['iface'] = splitline[5] raw_output.append(output_line) From 1c16d3242049fa39482e7172b48439f52b06f2e5 Mon Sep 17 00:00:00 2001 From: Dave Marquardt Date: Fri, 6 Jan 2023 14:51:09 -0600 Subject: [PATCH 07/10] Added test data for AIX ARP --- tests/fixtures/aix-7.1/arp-a.json | 1 + tests/fixtures/aix-7.1/arp-a.out | 163 ++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 tests/fixtures/aix-7.1/arp-a.json create mode 100644 tests/fixtures/aix-7.1/arp-a.out diff --git a/tests/fixtures/aix-7.1/arp-a.json b/tests/fixtures/aix-7.1/arp-a.json new file mode 100644 index 00000000..919b6b20 --- /dev/null +++ b/tests/fixtures/aix-7.1/arp-a.json @@ -0,0 +1 @@ +[{"name":null,"address":"1.2.3.4","hwtype":"ethernet","hwaddress":"5:6:7:8:9:a","permanent":true},{"name":"v630gw9-3-63-1","address":"9.3.63.1","hwtype":"ethernet","hwaddress":"0:0:5e:0:1:5c"},{"name":"v630vrrp9-3-63-2","address":"9.3.63.2","hwtype":"ethernet","hwaddress":"4c:96:14:59:d7:f0"},{"name":"v630vrrp9-3-63-3","address":"9.3.63.3","hwtype":"ethernet","hwaddress":"3c:8a:b0:0:8f:f0"},{"name":"caju6","address":"9.3.63.4","hwtype":null,"hwaddress":null},{"name":"rock-lp8","address":"9.3.63.173","hwtype":"ethernet","hwaddress":"b6:1b:da:7e:1f:2"}] diff --git a/tests/fixtures/aix-7.1/arp-a.out b/tests/fixtures/aix-7.1/arp-a.out new file mode 100644 index 00000000..dd275873 --- /dev/null +++ b/tests/fixtures/aix-7.1/arp-a.out @@ -0,0 +1,163 @@ + ? (1.2.3.4) at 5:6:7:8:9:a [ethernet] permanent published stored in bucket 93 + + v630gw9-3-63-1 (9.3.63.1) at 0:0:5e:0:1:5c [ethernet] stored in bucket 97 + + v630vrrp9-3-63-2 (9.3.63.2) at 4c:96:14:59:d7:f0 [ethernet] stored in bucket 98 + + v630vrrp9-3-63-3 (9.3.63.3) at 3c:8a:b0:0:8f:f0 [ethernet] stored in bucket 99 + + caju6 (9.3.63.4) at (incomplete) + rock-lp8 (9.3.63.173) at b6:1b:da:7e:1f:2 [ethernet] stored in bucket 120 + +bucket: 0 contains: 0 entries +bucket: 1 contains: 0 entries +bucket: 2 contains: 0 entries +bucket: 3 contains: 0 entries +bucket: 4 contains: 0 entries +bucket: 5 contains: 0 entries +bucket: 6 contains: 0 entries +bucket: 7 contains: 0 entries +bucket: 8 contains: 0 entries +bucket: 9 contains: 0 entries +bucket: 10 contains: 0 entries +bucket: 11 contains: 0 entries +bucket: 12 contains: 0 entries +bucket: 13 contains: 0 entries +bucket: 14 contains: 0 entries +bucket: 15 contains: 0 entries +bucket: 16 contains: 0 entries +bucket: 17 contains: 0 entries +bucket: 18 contains: 0 entries +bucket: 19 contains: 0 entries +bucket: 20 contains: 0 entries +bucket: 21 contains: 0 entries +bucket: 22 contains: 0 entries +bucket: 23 contains: 0 entries +bucket: 24 contains: 0 entries +bucket: 25 contains: 0 entries +bucket: 26 contains: 0 entries +bucket: 27 contains: 0 entries +bucket: 28 contains: 0 entries +bucket: 29 contains: 0 entries +bucket: 30 contains: 0 entries +bucket: 31 contains: 0 entries +bucket: 32 contains: 0 entries +bucket: 33 contains: 0 entries +bucket: 34 contains: 0 entries +bucket: 35 contains: 0 entries +bucket: 36 contains: 0 entries +bucket: 37 contains: 0 entries +bucket: 38 contains: 0 entries +bucket: 39 contains: 0 entries +bucket: 40 contains: 0 entries +bucket: 41 contains: 0 entries +bucket: 42 contains: 0 entries +bucket: 43 contains: 0 entries +bucket: 44 contains: 0 entries +bucket: 45 contains: 0 entries +bucket: 46 contains: 0 entries +bucket: 47 contains: 0 entries +bucket: 48 contains: 0 entries +bucket: 49 contains: 0 entries +bucket: 50 contains: 0 entries +bucket: 51 contains: 0 entries +bucket: 52 contains: 0 entries +bucket: 53 contains: 0 entries +bucket: 54 contains: 0 entries +bucket: 55 contains: 0 entries +bucket: 56 contains: 0 entries +bucket: 57 contains: 0 entries +bucket: 58 contains: 0 entries +bucket: 59 contains: 0 entries +bucket: 60 contains: 0 entries +bucket: 61 contains: 0 entries +bucket: 62 contains: 0 entries +bucket: 63 contains: 0 entries +bucket: 64 contains: 0 entries +bucket: 65 contains: 0 entries +bucket: 66 contains: 0 entries +bucket: 67 contains: 0 entries +bucket: 68 contains: 0 entries +bucket: 69 contains: 0 entries +bucket: 70 contains: 0 entries +bucket: 71 contains: 0 entries +bucket: 72 contains: 0 entries +bucket: 73 contains: 0 entries +bucket: 74 contains: 0 entries +bucket: 75 contains: 0 entries +bucket: 76 contains: 0 entries +bucket: 77 contains: 0 entries +bucket: 78 contains: 0 entries +bucket: 79 contains: 0 entries +bucket: 80 contains: 0 entries +bucket: 81 contains: 0 entries +bucket: 82 contains: 0 entries +bucket: 83 contains: 0 entries +bucket: 84 contains: 0 entries +bucket: 85 contains: 0 entries +bucket: 86 contains: 0 entries +bucket: 87 contains: 0 entries +bucket: 88 contains: 0 entries +bucket: 89 contains: 0 entries +bucket: 90 contains: 0 entries +bucket: 91 contains: 0 entries +bucket: 92 contains: 0 entries +bucket: 93 contains: 1 entries +bucket: 94 contains: 0 entries +bucket: 95 contains: 0 entries +bucket: 96 contains: 0 entries +bucket: 97 contains: 1 entries +bucket: 98 contains: 1 entries +bucket: 99 contains: 1 entries +bucket: 100 contains: 0 entries +bucket: 101 contains: 0 entries +bucket: 102 contains: 0 entries +bucket: 103 contains: 0 entries +bucket: 104 contains: 0 entries +bucket: 105 contains: 0 entries +bucket: 106 contains: 0 entries +bucket: 107 contains: 0 entries +bucket: 108 contains: 0 entries +bucket: 109 contains: 0 entries +bucket: 110 contains: 0 entries +bucket: 111 contains: 0 entries +bucket: 112 contains: 0 entries +bucket: 113 contains: 0 entries +bucket: 114 contains: 0 entries +bucket: 115 contains: 0 entries +bucket: 116 contains: 0 entries +bucket: 117 contains: 0 entries +bucket: 118 contains: 0 entries +bucket: 119 contains: 0 entries +bucket: 120 contains: 1 entries +bucket: 121 contains: 0 entries +bucket: 122 contains: 0 entries +bucket: 123 contains: 0 entries +bucket: 124 contains: 0 entries +bucket: 125 contains: 0 entries +bucket: 126 contains: 0 entries +bucket: 127 contains: 0 entries +bucket: 128 contains: 0 entries +bucket: 129 contains: 0 entries +bucket: 130 contains: 0 entries +bucket: 131 contains: 0 entries +bucket: 132 contains: 0 entries +bucket: 133 contains: 0 entries +bucket: 134 contains: 0 entries +bucket: 135 contains: 0 entries +bucket: 136 contains: 0 entries +bucket: 137 contains: 0 entries +bucket: 138 contains: 0 entries +bucket: 139 contains: 0 entries +bucket: 140 contains: 0 entries +bucket: 141 contains: 0 entries +bucket: 142 contains: 0 entries +bucket: 143 contains: 0 entries +bucket: 144 contains: 0 entries +bucket: 145 contains: 0 entries +bucket: 146 contains: 0 entries +bucket: 147 contains: 0 entries +bucket: 148 contains: 0 entries + +There are 5 entries in the arp table. + From 5fb73f4ad59ccf92f57eb439cdf4ecd3369768ed Mon Sep 17 00:00:00 2001 From: Dave Marquardt Date: Fri, 6 Jan 2023 14:53:50 -0600 Subject: [PATCH 08/10] Added AIX support for ARP, along with AIX ARP test support --- jc/parsers/arp.py | 3 +-- tests/test_arp.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/jc/parsers/arp.py b/jc/parsers/arp.py index 86f9ba77..183be0fc 100644 --- a/jc/parsers/arp.py +++ b/jc/parsers/arp.py @@ -236,8 +236,7 @@ def parse( 'hwtype': splitline[4].lstrip('[').rstrip(']'), 'hwaddress': splitline[3], } - # AIX tells what bucket the entry is in, and no interface - # information + # Handle permanence and ignore interface in AIX if 'permanent' in splitline: output_line['permanent'] = True elif 'in' not in splitline[6]: diff --git a/tests/test_arp.py b/tests/test_arp.py index 0dccf7f2..152c1fee 100644 --- a/tests/test_arp.py +++ b/tests/test_arp.py @@ -42,6 +42,9 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-8/arp-a.out'), 'r', encoding='utf-8') as f: centos8_arp_a = f.read() + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/aix-7.1/arp-a.out'), 'r', encoding='utf-8') as f: + aix_7_1_arp_a = f.read() + # output with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/arp.json'), 'r', encoding='utf-8') as f: centos_7_7_arp_json = json.loads(f.read()) @@ -76,6 +79,9 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-8/arp-a.json'), 'r', encoding='utf-8') as f: centos8_arp_a_json = json.loads(f.read()) + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/aix-7.1/arp-a.json'), 'r', encoding='utf-8') as f: + aix_7_1_arp_a_json = json.loads(f.read()) + def test_arp_nodata(self): """ Test 'arp' with no data @@ -148,6 +154,12 @@ class MyTests(unittest.TestCase): """ self.assertEqual(jc.parsers.arp.parse(self.centos8_arp_a, quiet=True), self.centos8_arp_a_json) + def test_arp_a_aix_7_1(self): + """ + Test 'arp -a' on CentOS 8 with incomplete hw addresses + """ + self.assertEqual(jc.parsers.arp.parse(self.aix_7_1_arp_a, quiet=True), self.aix_7_1_arp_a_json) + if __name__ == '__main__': unittest.main() From f64dfbf79db4886cc1348a3467c105a7ed909203 Mon Sep 17 00:00:00 2001 From: Dave Marquardt Date: Fri, 6 Jan 2023 15:10:02 -0600 Subject: [PATCH 09/10] Update comments about AIX ARP --- jc/parsers/arp.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jc/parsers/arp.py b/jc/parsers/arp.py index 183be0fc..ec1c3ca1 100644 --- a/jc/parsers/arp.py +++ b/jc/parsers/arp.py @@ -229,6 +229,7 @@ def parse( elif 'There' in splitline[0] and 'are' in splitline[1]: continue + # AIX uses (incomplete) elif '' not in splitline and '(incomplete)' not in splitline: output_line = { 'name': splitline[0], @@ -239,7 +240,7 @@ def parse( # Handle permanence and ignore interface in AIX if 'permanent' in splitline: output_line['permanent'] = True - elif 'in' not in splitline[6]: + elif 'in' not in splitline[6]: # AIX doesn't show interface output_line['iface'] = splitline[6] else: @@ -249,6 +250,7 @@ def parse( 'hwtype': None, 'hwaddress': None, } + # AIX doesn't show interface if len(splitline) >= 5: output_line['iface'] = splitline[5] From 081fdb802651990d5f611ef8d243cabc01af739e Mon Sep 17 00:00:00 2001 From: Dave Marquardt Date: Fri, 6 Jan 2023 15:13:03 -0600 Subject: [PATCH 10/10] Updated AIX ARP test comments --- tests/test_arp.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_arp.py b/tests/test_arp.py index 152c1fee..052a9153 100644 --- a/tests/test_arp.py +++ b/tests/test_arp.py @@ -156,7 +156,8 @@ class MyTests(unittest.TestCase): def test_arp_a_aix_7_1(self): """ - Test 'arp -a' on CentOS 8 with incomplete hw addresses + Test 'arp -a' on AIX 7.1 with incomplete hw addresses and permanent ARP + entries """ self.assertEqual(jc.parsers.arp.parse(self.aix_7_1_arp_a, quiet=True), self.aix_7_1_arp_a_json)