diff --git a/changelog.txt b/changelog.txt index a5c4514b..a167ef3f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -7,6 +7,8 @@ jc changelog - Update netstat parser to change osx_flags field name to unix_flags - Update netstat parser to strip whitespace from state field - Update route parser to add flags_pretty field +- Update arp parser to add permanent field (freebsd and osx) +- Update arp parser to add expires field (freebsd) - Fix freebsd compatibility message for df, fstab, mount, ntpq, stat, and uname parsers - Fix compatibility message for platforms that include the version number at the end (e.g. freebsd12) diff --git a/docs/parsers/arp.md b/docs/parsers/arp.md index 98536ef9..569fdcfd 100644 --- a/docs/parsers/arp.md +++ b/docs/parsers/arp.md @@ -59,6 +59,8 @@ Examples: "hwtype": "ether", "hwaddress": "00:50:56:f0:98:26", "iface": "ens33" + "permanent": false, + "expires": 1182 }, { "name": "gateway", @@ -66,6 +68,8 @@ Examples: "hwtype": "ether", "hwaddress": "00:50:56:f7:4a:fc", "iface": "ens33" + "permanent": false, + "expires": 110 } ] @@ -77,6 +81,8 @@ Examples: "hwtype": "ether", "hwaddress": "00:50:56:fe:7a:b4", "iface": "ens33" + "permanent": false, + "expires": "1182" }, { "name": "_gateway", @@ -84,6 +90,8 @@ Examples: "hwtype": "ether", "hwaddress": "00:50:56:f7:4a:fc", "iface": "ens33" + "permanent": false, + "expires": "110" } ] @@ -114,7 +122,9 @@ Returns: "hwtype": string, "hwaddress": string, "flags_mask": string, - "iface": string + "iface": string, + "permanent": boolean, + "expires": integer } ] diff --git a/jc/parsers/arp.py b/jc/parsers/arp.py index e4acb6b5..bec019cf 100644 --- a/jc/parsers/arp.py +++ b/jc/parsers/arp.py @@ -58,6 +58,8 @@ Examples: "hwtype": "ether", "hwaddress": "00:50:56:f0:98:26", "iface": "ens33" + "permanent": false, + "expires": 1182 }, { "name": "gateway", @@ -65,6 +67,8 @@ Examples: "hwtype": "ether", "hwaddress": "00:50:56:f7:4a:fc", "iface": "ens33" + "permanent": false, + "expires": 110 } ] @@ -76,6 +80,8 @@ Examples: "hwtype": "ether", "hwaddress": "00:50:56:fe:7a:b4", "iface": "ens33" + "permanent": false, + "expires": "1182" }, { "name": "_gateway", @@ -83,6 +89,8 @@ Examples: "hwtype": "ether", "hwaddress": "00:50:56:f7:4a:fc", "iface": "ens33" + "permanent": false, + "expires": "110" } ] """ @@ -91,7 +99,7 @@ import jc.parsers.universal class info(): - version = '1.3' + version = '1.4' description = 'arp command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -123,7 +131,9 @@ def process(proc_data): "hwtype": string, "hwaddress": string, "flags_mask": string, - "iface": string + "iface": string, + "permanent": boolean, + "expires": integer } ] """ @@ -133,6 +143,14 @@ def process(proc_data): if 'name' in entry and entry['name'] == '?': entry['name'] = None + int_list = ['expires'] + for key in int_list: + if key in entry: + try: + entry[key] = int(entry[key]) + except (ValueError): + entry[key] = None + return proc_data @@ -159,7 +177,7 @@ def parse(data, raw=False, quiet=False): if cleandata[-1].startswith('Entries:'): cleandata.pop(-1) - # detect if osx style was used + # detect if freebsd/osx style was used if cleandata[0][-1] == ']': raw_output = [] for line in cleandata: @@ -171,6 +189,15 @@ def parse(data, raw=False, quiet=False): 'hwaddress': splitline[3], 'iface': splitline[5] } + + if 'permanent' in splitline: + output_line['permanent'] = True + else: + output_line['permanent'] = False + + if 'expires' in splitline: + output_line['expires'] = splitline[-3] + raw_output.append(output_line) if raw: diff --git a/tests/fixtures/freebsd12/arp-a.json b/tests/fixtures/freebsd12/arp-a.json new file mode 100644 index 00000000..0176652d --- /dev/null +++ b/tests/fixtures/freebsd12/arp-a.json @@ -0,0 +1 @@ +[{"name": null, "address": "192.168.71.163", "hwtype": "ethernet", "hwaddress": "00:0c:29:1a:4e:3b", "iface": "em0", "permanent": true}, {"name": null, "address": "192.168.71.2", "hwtype": "ethernet", "hwaddress": "00:50:56:f7:4a:fc", "iface": "em0", "permanent": false, "expires": 942}, {"name": null, "address": "192.168.71.1", "hwtype": "ethernet", "hwaddress": "00:50:56:c0:00:08", "iface": "em0", "permanent": false, "expires": 1182}] diff --git a/tests/fixtures/freebsd12/arp-a.out b/tests/fixtures/freebsd12/arp-a.out new file mode 100644 index 00000000..e51e7121 --- /dev/null +++ b/tests/fixtures/freebsd12/arp-a.out @@ -0,0 +1,3 @@ +? (192.168.71.163) at 00:0c:29:1a:4e:3b on em0 permanent [ethernet] +? (192.168.71.2) at 00:50:56:f7:4a:fc on em0 expires in 942 seconds [ethernet] +? (192.168.71.1) at 00:50:56:c0:00:08 on em0 expires in 1182 seconds [ethernet] diff --git a/tests/test_arp.py b/tests/test_arp.py index 011eb267..1db88555 100644 --- a/tests/test_arp.py +++ b/tests/test_arp.py @@ -37,6 +37,9 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/arp-a2.out'), 'r', encoding='utf-8') as f: self.osx_10_14_6_arp_a2 = f.read() + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/arp-a.out'), 'r', encoding='utf-8') as f: + self.freebsd_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: self.centos_7_7_arp_json = json.loads(f.read()) @@ -65,6 +68,9 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/arp-a2.json'), 'r', encoding='utf-8') as f: self.osx_10_14_6_arp_a2_json = json.loads(f.read()) + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/arp-a.json'), 'r', encoding='utf-8') as f: + self.freebsd12_arp_a_json = json.loads(f.read()) + def test_arp_centos_7_7(self): """ Test 'arp' on Centos 7.7 @@ -119,6 +125,12 @@ class MyTests(unittest.TestCase): """ self.assertEqual(jc.parsers.arp.parse(self.osx_10_14_6_arp_a2, quiet=True), self.osx_10_14_6_arp_a2_json) + def test_arp_a_freebsd12(self): + """ + Test 'arp -a' on FreeBSD12 + """ + self.assertEqual(jc.parsers.arp.parse(self.freebsd_arp_a, quiet=True), self.freebsd12_arp_a_json) + if __name__ == '__main__': unittest.main()