From 5d0dbece9317e84a47d9f4b2d18a9ffa33fbee6e Mon Sep 17 00:00:00 2001
From: Kelly Brazil <kellyjonbrazil@gmail.com>
Date: Fri, 22 May 2020 11:09:41 -0700
Subject: [PATCH] add netstat -r functionality for OSX

---
 docs/parsers/netstat.md                     | 17 +++-
 jc/parsers/netstat.py                       | 23 ++++-
 jc/parsers/netstat_osx.py                   | 37 +++++++-
 tests/fixtures/osx-10.14.6/netstat-r.json   |  1 +
 tests/fixtures/osx-10.14.6/netstat-r.out    | 93 ++++++++++++++++++++
 tests/fixtures/osx-10.14.6/netstat-rnl.json |  1 +
 tests/fixtures/osx-10.14.6/netstat-rnl.out  | 96 +++++++++++++++++++++
 tests/test_netstat.py                       | 25 ++++++
 8 files changed, 288 insertions(+), 5 deletions(-)
 create mode 100644 tests/fixtures/osx-10.14.6/netstat-r.json
 create mode 100644 tests/fixtures/osx-10.14.6/netstat-r.out
 create mode 100644 tests/fixtures/osx-10.14.6/netstat-rnl.json
 create mode 100644 tests/fixtures/osx-10.14.6/netstat-rnl.out

diff --git a/docs/parsers/netstat.md b/docs/parsers/netstat.md
index 42c94b5e..62cc6154 100644
--- a/docs/parsers/netstat.md
+++ b/docs/parsers/netstat.md
@@ -5,6 +5,11 @@ Usage:
 
     Specify --netstat as the first argument if the piped input is coming from netstat
 
+Caveats:
+
+    - Use of multiple 'l' options is not supported on OSX (e.g. 'netstat -rlll')
+    - Use of the 'A' option is not supported on OSX when using the 'r' option (e.g. netstat -rA)
+
 Compatibility:
 
     'linux', 'darwin'
@@ -368,7 +373,17 @@ Returns:
         "rcvbuf":            integer,
         "sndbuf":            integer,
         "rxbytes":           integer,
-        "txbytes":           integer
+        "txbytes":           integer,
+
+
+        "destination":       string,
+        "gateway":           string,
+        "route_flags":       string,
+        "route_refs":        integer,
+        "use":               integer,
+        "mtu":               integer,
+        "netif":             string,
+        "expire":            string
       }
     ]
 
diff --git a/jc/parsers/netstat.py b/jc/parsers/netstat.py
index 96a0cd88..a34e27e0 100644
--- a/jc/parsers/netstat.py
+++ b/jc/parsers/netstat.py
@@ -4,6 +4,11 @@ Usage:
 
     Specify --netstat as the first argument if the piped input is coming from netstat
 
+Caveats:
+
+    - Use of multiple 'l' options is not supported on OSX (e.g. 'netstat -rlll')
+    - Use of the 'A' option is not supported on OSX when using the 'r' option (e.g. netstat -rA)
+
 Compatibility:
 
     'linux', 'darwin'
@@ -375,14 +380,25 @@ def process(proc_data):
             "rcvbuf":            integer,
             "sndbuf":            integer,
             "rxbytes":           integer,
-            "txbytes":           integer
+            "txbytes":           integer,
+
+
+            "destination":       string,
+            "gateway":           string,
+            "route_flags":       string,
+            "route_refs":        integer,
+            "use":               integer,
+            "mtu":               integer,
+            "netif":             string,
+            "expire":            string
           }
         ]
     """
     for entry in proc_data:
         # integer changes
         int_list = ['recv_q', 'send_q', 'pid', 'refcnt', 'inode', 'unit', 'vendor', 'class',
-                    'osx_flags', 'subcla', 'pcbcount', 'rcvbuf', 'sndbuf', 'rxbytes', 'txbytes']
+                    'osx_flags', 'subcla', 'pcbcount', 'rcvbuf', 'sndbuf', 'rxbytes', 'txbytes',
+                    'route_refs', 'use', 'mtu']
         for key in int_list:
             if key in entry:
                 try:
@@ -436,7 +452,8 @@ def parse(data, raw=False, quiet=False):
        or cleandata[0] == 'Active LOCAL (UNIX) domain sockets' \
        or cleandata[0] == 'Registered kernel control modules' \
        or cleandata[0] == 'Active kernel event sockets' \
-       or cleandata[0] == 'Active kernel control sockets':
+       or cleandata[0] == 'Active kernel control sockets' \
+       or cleandata[0] == 'Routing tables':
         import jc.parsers.netstat_osx
         raw_output = jc.parsers.netstat_osx.parse(cleandata)
 
diff --git a/jc/parsers/netstat_osx.py b/jc/parsers/netstat_osx.py
index 9386932d..0febb801 100644
--- a/jc/parsers/netstat_osx.py
+++ b/jc/parsers/netstat_osx.py
@@ -13,6 +13,15 @@ def normalize_headers(header):
     return header
 
 
+def normalize_route_headers(header):
+    header = header.lower()
+    header = header.replace('flags', 'route_flags')
+    header = header.replace('refs', 'route_refs')
+    header = header.replace('-', '_')
+
+    return header
+
+
 def parse_item(headers, entry, kind):
     entry = entry.split(maxsplit=len(headers) - 1)
 
@@ -82,10 +91,11 @@ def parse(cleandata):
     raw_output = []
     network = False
     multipath = False
+    socket = False
     reg_kernel_control = False
     active_kernel_event = False
     active_kernel_control = False
-    socket = False
+    routing_table = False
 
     for line in cleandata:
 
@@ -96,6 +106,7 @@ def parse(cleandata):
             reg_kernel_control = False
             active_kernel_event = False
             active_kernel_control = False
+            routing_table = False
             continue
 
         if line.startswith('Active Multipath Internet connections'):
@@ -105,6 +116,7 @@ def parse(cleandata):
             reg_kernel_control = False
             active_kernel_event = False
             active_kernel_control = False
+            routing_table = False
             continue
 
         if line.startswith('Active LOCAL (UNIX) domain sockets'):
@@ -114,6 +126,7 @@ def parse(cleandata):
             reg_kernel_control = False
             active_kernel_event = False
             active_kernel_control = False
+            routing_table = False
             continue
 
         if line.startswith('Registered kernel control modules'):
@@ -123,6 +136,7 @@ def parse(cleandata):
             reg_kernel_control = True
             active_kernel_event = False
             active_kernel_control = False
+            routing_table = False
             continue
 
         if line.startswith('Active kernel event sockets'):
@@ -132,6 +146,7 @@ def parse(cleandata):
             reg_kernel_control = False
             active_kernel_event = True
             active_kernel_control = False
+            routing_table = False
             continue
 
         if line.startswith('Active kernel control sockets'):
@@ -141,6 +156,17 @@ def parse(cleandata):
             reg_kernel_control = False
             active_kernel_event = False
             active_kernel_control = True
+            routing_table = False
+            continue
+
+        if line.startswith('Routing tables'):
+            network = False
+            multipath = False
+            socket = False
+            reg_kernel_control = False
+            active_kernel_event = False
+            active_kernel_control = False
+            routing_table = True
             continue
 
         # get headers
@@ -169,6 +195,11 @@ def parse(cleandata):
             headers = header_text.split()
             continue
 
+        if routing_table and line.startswith('Destination '):
+            header_text = normalize_route_headers(line)
+            headers = header_text.split()
+            continue
+
         # get items
         if network:
             raw_output.append(parse_item(headers, line, 'network'))
@@ -194,4 +225,8 @@ def parse(cleandata):
             raw_output.append(parse_item(headers, line, 'Active kernel control socket'))
             continue
 
+        if routing_table and not (line.startswith('Internet:') or line.startswith('Internet6:')):
+            raw_output.append(parse_item(headers, line, 'route'))
+            continue
+
     return parse_post(raw_output)
diff --git a/tests/fixtures/osx-10.14.6/netstat-r.json b/tests/fixtures/osx-10.14.6/netstat-r.json
new file mode 100644
index 00000000..7b70df05
--- /dev/null
+++ b/tests/fixtures/osx-10.14.6/netstat-r.json
@@ -0,0 +1 @@
+[{"destination": "default", "gateway": "dsldevice.attlocal", "route_flags": "UGSc", "route_refs": 85, "use": 24, "netif": "en0", "kind": "route"}, {"destination": "127", "gateway": "localhost", "route_flags": "UCS", "route_refs": 0, "use": 0, "netif": "lo0", "kind": "route"}, {"destination": "localhost", "gateway": "localhost", "route_flags": "UH", "route_refs": 20, "use": 1266183, "netif": "lo0", "kind": "route"}, {"destination": "169.254", "gateway": "link#10", "route_flags": "UCS", "route_refs": 1, "use": 0, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "192.168.1", "gateway": "link#10", "route_flags": "UCS", "route_refs": 11, "use": 0, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "kellys-iphone.attl", "gateway": "e0:33:8e:68:38:d6", "route_flags": "UHLWIi", "route_refs": 2, "use": 466, "netif": "en0", "expire": "866", "kind": "route"}, {"destination": "kellys-mbp.attloca", "gateway": "f0:18:98:3:d8:39", "route_flags": "UHLWIi", "route_refs": 2, "use": 8877, "netif": "en0", "expire": "187", "kind": "route"}, {"destination": "ipad.attlocal.net", "gateway": "4c:56:9d:5f:b7:4c", "route_flags": "UHLWI", "route_refs": 0, "use": 600, "netif": "en0", "expire": "786", "kind": "route"}, {"destination": "mycloudex2ultra.at", "gateway": "0:90:a9:ed:e4:35", "route_flags": "UHLWIi", "route_refs": 1, "use": 265596, "netif": "en0", "expire": "1044", "kind": "route"}, {"destination": "family-room-5.attl", "gateway": "c8:d0:83:cd:e3:2d", "route_flags": "UHLWIi", "route_refs": 1, "use": 4308, "netif": "en0", "expire": "391", "kind": "route"}, {"destination": "bedroom.attlocal.n", "gateway": "d0:3:4b:3b:28:d5", "route_flags": "UHLWIi", "route_refs": 1, "use": 4586, "netif": "en0", "expire": "36", "kind": "route"}, {"destination": "upstairs.attlocal.", "gateway": "50:32:37:d7:f5:9b", "route_flags": "UHLWIi", "route_refs": 1, "use": 6117, "netif": "en0", "expire": "1161", "kind": "route"}, {"destination": "rbr50.attlocal.net", "gateway": "3c:37:86:15:ad:f7", "route_flags": "UHLWI", "route_refs": 0, "use": 16, "netif": "en0", "expire": "678", "kind": "route"}, {"destination": "192.168.1.221/32", "gateway": "link#10", "route_flags": "UCS", "route_refs": 1, "use": 0, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "kbrazil-mac.attloc", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHLWI", "route_refs": 0, "use": 36, "netif": "lo0", "kind": "route"}, {"destination": "irobot-f5788f2e24e", "gateway": "50:14:79:12:42:3e", "route_flags": "UHLWI", "route_refs": 0, "use": 0, "netif": "en0", "expire": "1173", "kind": "route"}, {"destination": "victoriasiphone.at", "gateway": "14:60:cb:10:ec:17", "route_flags": "UHLWI", "route_refs": 0, "use": 54, "netif": "en0", "expire": "64", "kind": "route"}, {"destination": "rbs50.attlocal.net", "gateway": "3c:37:86:15:dd:b3", "route_flags": "UHLWI", "route_refs": 0, "use": 3300, "netif": "en0", "expire": "952", "kind": "route"}, {"destination": "192.168.1.254/32", "gateway": "link#10", "route_flags": "UCS", "route_refs": 1, "use": 0, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "dsldevice.attlocal", "gateway": "fc:ae:34:a1:3a:80", "route_flags": "UHLWIir", "route_refs": 30, "use": 69452, "netif": "en0", "expire": "1180", "kind": "route"}, {"destination": "192.168.71", "gateway": "link#20", "route_flags": "UC", "route_refs": 2, "use": 0, "netif": "vmnet8", "expire": "!", "kind": "route"}, {"destination": "192.168.71.160", "gateway": "link#20", "route_flags": "UHLWIi", "route_refs": 1, "use": 1708, "netif": "vmnet8", "expire": "!", "kind": "route"}, {"destination": "192.168.101", "gateway": "link#19", "route_flags": "UC", "route_refs": 1, "use": 0, "netif": "vmnet1", "expire": "!", "kind": "route"}, {"destination": "224.0.0/4", "gateway": "link#10", "route_flags": "UmCS", "route_refs": 2, "use": 0, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "224.0.0.251", "gateway": "1:0:5e:0:0:fb", "route_flags": "UHmLWI", "route_refs": 0, "use": 312, "netif": "en0", "kind": "route"}, {"destination": "239.255.255.250", "gateway": "1:0:5e:7f:ff:fa", "route_flags": "UHmLWI", "route_refs": 0, "use": 9914, "netif": "en0", "kind": "route"}, {"destination": "255.255.255.255/32", "gateway": "link#10", "route_flags": "UCS", "route_refs": 0, "use": 0, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "default", "gateway": "fe80::feae:34ff:fe", "route_flags": "UGc", "netif": "en0", "kind": "route"}, {"destination": "default", "gateway": "fe80::%utun0", "route_flags": "UGcI", "netif": "utun0", "kind": "route"}, {"destination": "default", "gateway": "fe80::%utun1", "route_flags": "UGcI", "netif": "utun1", "kind": "route"}, {"destination": "default", "gateway": "fe80::%utun2", "route_flags": "UGcI", "netif": "utun2", "kind": "route"}, {"destination": "default", "gateway": "fe80::%utun3", "route_flags": "UGcI", "netif": "utun3", "kind": "route"}, {"destination": "localhost", "gateway": "localhost", "route_flags": "UHL", "netif": "lo0", "kind": "route"}, {"destination": "2600:1700:bab0:d40", "gateway": "link#10", "route_flags": "UC", "netif": "en0", "kind": "route"}, {"destination": "dsldevice6.attloca", "gateway": "fc:ae:34:a1:3a:80", "route_flags": "UHLWIi", "netif": "en0", "kind": "route"}, {"destination": "2600:1700:bab0:d40", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "netif": "lo0", "kind": "route"}, {"destination": "2600:1700:bab0:d40", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "netif": "lo0", "kind": "route"}, {"destination": "2600:1700:bab0:d40", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "netif": "lo0", "kind": "route"}, {"destination": "kbrazil-mac.attloc", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "netif": "lo0", "kind": "route"}, {"destination": "kbrazil-mac.attloc", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "netif": "lo0", "kind": "route"}, {"destination": "kbrazil-mac.attloc", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "netif": "lo0", "kind": "route"}, {"destination": "fe80::%lo0", "gateway": "fe80::1%lo0", "route_flags": "UcI", "netif": "lo0", "kind": "route"}, {"destination": "fe80::1%lo0", "gateway": "link#1", "route_flags": "UHLI", "netif": "lo0", "kind": "route"}, {"destination": "fe80::%en5", "gateway": "link#8", "route_flags": "UCI", "netif": "en5", "kind": "route"}, {"destination": "fe80::aede:48ff:fe", "gateway": "ac:de:48:0:11:22", "route_flags": "UHLI", "netif": "lo0", "kind": "route"}, {"destination": "fe80::aede:48ff:fe", "gateway": "ac:de:48:33:44:55", "route_flags": "UHLWIi", "netif": "en5", "kind": "route"}, {"destination": "fe80::%en0", "gateway": "link#10", "route_flags": "UCI", "netif": "en0", "kind": "route"}, {"destination": "fe80::df:eea7:d8e0", "gateway": "14:60:cb:10:ec:17", "route_flags": "UHLWI", "netif": "en0", "kind": "route"}, {"destination": "fe80::472:ae33:7f7", "gateway": "b4:18:d1:9d:bc:2d", "route_flags": "UHLWI", "netif": "en0", "kind": "route"}, {"destination": "ipad.local", "gateway": "4c:56:9d:5f:b7:4c", "route_flags": "UHLWI", "netif": "en0", "kind": "route"}, {"destination": "fe80::ced:5f18:1d1", "gateway": "14:60:cb:10:ec:17", "route_flags": "UHLWI", "netif": "en0", "kind": "route"}, {"destination": "kbrazil-mac.local", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHLI", "netif": "lo0", "kind": "route"}, {"destination": "fe80::10f2:d51c:68", "gateway": "e0:33:8e:68:38:d6", "route_flags": "UHLWI", "netif": "en0", "kind": "route"}, {"destination": "upstairs.local", "gateway": "50:32:37:d7:f5:9b", "route_flags": "UHLWIi", "netif": "en0", "kind": "route"}, {"destination": "fe80::1899:d8f6:dc", "gateway": "50:32:37:d7:f5:9b", "route_flags": "UHLWI", "netif": "en0", "kind": "route"}, {"destination": "kellys-macbook-pro", "gateway": "f0:18:98:3:d8:39", "route_flags": "UHLWI", "netif": "en0", "kind": "route"}, {"destination": "bedroom.local", "gateway": "d0:3:4b:3b:28:d5", "route_flags": "UHLWI", "netif": "en0", "kind": "route"}, {"destination": "kellys-airport-exp", "gateway": "48:d7:5:f1:86:e8", "route_flags": "UHLWI", "netif": "en0", "kind": "route"}, {"destination": "hp9cb654545bb9.loc", "gateway": "9c:b6:54:5a:5a:7c", "route_flags": "UHLWI", "netif": "en0", "kind": "route"}, {"destination": "fe80::feae:34ff:fe", "gateway": "fc:ae:34:a1:3a:80", "route_flags": "UHLWIir", "netif": "en0", "kind": "route"}, {"destination": "fe80::%awdl0", "gateway": "link#12", "route_flags": "UCI", "netif": "awdl0", "kind": "route"}, {"destination": "fe80::b41f:b7ff:fe", "gateway": "b6:1f:b7:57:a5:4f", "route_flags": "UHLI", "netif": "lo0", "kind": "route"}, {"destination": "fe80::%utun0", "gateway": "kbrazil-mac.local", "route_flags": "UcI", "netif": "utun0", "kind": "route"}, {"destination": "kbrazil-mac.local", "gateway": "link#18", "route_flags": "UHLI", "netif": "lo0", "kind": "route"}, {"destination": "fe80::%utun1", "gateway": "kbrazil-mac.local", "route_flags": "UcI", "netif": "utun1", "kind": "route"}, {"destination": "kbrazil-mac.local", "gateway": "link#21", "route_flags": "UHLI", "netif": "lo0", "kind": "route"}, {"destination": "fe80::%utun2", "gateway": "kbrazil-mac.local", "route_flags": "UcI", "netif": "utun2", "kind": "route"}, {"destination": "kbrazil-mac.local", "gateway": "link#22", "route_flags": "UHLI", "netif": "lo0", "kind": "route"}, {"destination": "fe80::%utun3", "gateway": "kbrazil-mac.local", "route_flags": "UcI", "netif": "utun3", "kind": "route"}, {"destination": "kbrazil-mac.local", "gateway": "link#23", "route_flags": "UHLI", "netif": "lo0", "kind": "route"}, {"destination": "ff01::%lo0", "gateway": "localhost", "route_flags": "UmCI", "netif": "lo0", "kind": "route"}, {"destination": "ff01::%en5", "gateway": "link#8", "route_flags": "UmCI", "netif": "en5", "kind": "route"}, {"destination": "ff01::%en0", "gateway": "link#10", "route_flags": "UmCI", "netif": "en0", "kind": "route"}, {"destination": "ff01::%awdl0", "gateway": "link#12", "route_flags": "UmCI", "netif": "awdl0", "kind": "route"}, {"destination": "ff01::%utun0", "gateway": "kbrazil-mac.local", "route_flags": "UmCI", "netif": "utun0", "kind": "route"}, {"destination": "ff01::%utun1", "gateway": "kbrazil-mac.local", "route_flags": "UmCI", "netif": "utun1", "kind": "route"}, {"destination": "ff01::%utun2", "gateway": "kbrazil-mac.local", "route_flags": "UmCI", "netif": "utun2", "kind": "route"}, {"destination": "ff01::%utun3", "gateway": "kbrazil-mac.local", "route_flags": "UmCI", "netif": "utun3", "kind": "route"}, {"destination": "ff02::%lo0", "gateway": "localhost", "route_flags": "UmCI", "netif": "lo0", "kind": "route"}, {"destination": "ff02::%en5", "gateway": "link#8", "route_flags": "UmCI", "netif": "en5", "kind": "route"}, {"destination": "ff02::%en0", "gateway": "link#10", "route_flags": "UmCI", "netif": "en0", "kind": "route"}, {"destination": "ff02::%awdl0", "gateway": "link#12", "route_flags": "UmCI", "netif": "awdl0", "kind": "route"}, {"destination": "ff02::%utun0", "gateway": "kbrazil-mac.local", "route_flags": "UmCI", "netif": "utun0", "kind": "route"}, {"destination": "ff02::%utun1", "gateway": "kbrazil-mac.local", "route_flags": "UmCI", "netif": "utun1", "kind": "route"}, {"destination": "ff02::%utun2", "gateway": "kbrazil-mac.local", "route_flags": "UmCI", "netif": "utun2", "kind": "route"}, {"destination": "ff02::%utun3", "gateway": "kbrazil-mac.local", "route_flags": "UmCI", "netif": "utun3", "kind": "route"}]
diff --git a/tests/fixtures/osx-10.14.6/netstat-r.out b/tests/fixtures/osx-10.14.6/netstat-r.out
new file mode 100644
index 00000000..155d3cea
--- /dev/null
+++ b/tests/fixtures/osx-10.14.6/netstat-r.out
@@ -0,0 +1,93 @@
+Routing tables
+
+Internet:
+Destination        Gateway            Flags        Refs      Use   Netif Expire
+default            dsldevice.attlocal UGSc           85       24     en0       
+127                localhost          UCS             0        0     lo0       
+localhost          localhost          UH             20  1266183     lo0       
+169.254            link#10            UCS             1        0     en0      !
+192.168.1          link#10            UCS            11        0     en0      !
+kellys-iphone.attl e0:33:8e:68:38:d6  UHLWIi          2      466     en0    866
+kellys-mbp.attloca f0:18:98:3:d8:39   UHLWIi          2     8877     en0    187
+ipad.attlocal.net  4c:56:9d:5f:b7:4c  UHLWI           0      600     en0    786
+mycloudex2ultra.at 0:90:a9:ed:e4:35   UHLWIi          1   265596     en0   1044
+family-room-5.attl c8:d0:83:cd:e3:2d  UHLWIi          1     4308     en0    391
+bedroom.attlocal.n d0:3:4b:3b:28:d5   UHLWIi          1     4586     en0     36
+upstairs.attlocal. 50:32:37:d7:f5:9b  UHLWIi          1     6117     en0   1161
+rbr50.attlocal.net 3c:37:86:15:ad:f7  UHLWI           0       16     en0    678
+192.168.1.221/32   link#10            UCS             1        0     en0      !
+kbrazil-mac.attloc a4:83:e7:2d:62:8f  UHLWI           0       36     lo0       
+irobot-f5788f2e24e 50:14:79:12:42:3e  UHLWI           0        0     en0   1173
+victoriasiphone.at 14:60:cb:10:ec:17  UHLWI           0       54     en0     64
+rbs50.attlocal.net 3c:37:86:15:dd:b3  UHLWI           0     3300     en0    952
+192.168.1.254/32   link#10            UCS             1        0     en0      !
+dsldevice.attlocal fc:ae:34:a1:3a:80  UHLWIir        30    69452     en0   1180
+192.168.71         link#20            UC              2        0  vmnet8      !
+192.168.71.160     link#20            UHLWIi          1     1708  vmnet8      !
+192.168.101        link#19            UC              1        0  vmnet1      !
+224.0.0/4          link#10            UmCS            2        0     en0      !
+224.0.0.251        1:0:5e:0:0:fb      UHmLWI          0      312     en0       
+239.255.255.250    1:0:5e:7f:ff:fa    UHmLWI          0     9914     en0       
+255.255.255.255/32 link#10            UCS             0        0     en0      !
+
+Internet6:
+Destination        Gateway            Flags         Netif Expire
+default            fe80::feae:34ff:fe UGc             en0       
+default            fe80::%utun0       UGcI          utun0       
+default            fe80::%utun1       UGcI          utun1       
+default            fe80::%utun2       UGcI          utun2       
+default            fe80::%utun3       UGcI          utun3       
+localhost          localhost          UHL             lo0       
+2600:1700:bab0:d40 link#10            UC              en0       
+dsldevice6.attloca fc:ae:34:a1:3a:80  UHLWIi          en0       
+2600:1700:bab0:d40 a4:83:e7:2d:62:8f  UHL             lo0       
+2600:1700:bab0:d40 a4:83:e7:2d:62:8f  UHL             lo0       
+2600:1700:bab0:d40 a4:83:e7:2d:62:8f  UHL             lo0       
+kbrazil-mac.attloc a4:83:e7:2d:62:8f  UHL             lo0       
+kbrazil-mac.attloc a4:83:e7:2d:62:8f  UHL             lo0       
+kbrazil-mac.attloc a4:83:e7:2d:62:8f  UHL             lo0       
+fe80::%lo0         fe80::1%lo0        UcI             lo0       
+fe80::1%lo0        link#1             UHLI            lo0       
+fe80::%en5         link#8             UCI             en5       
+fe80::aede:48ff:fe ac:de:48:0:11:22   UHLI            lo0       
+fe80::aede:48ff:fe ac:de:48:33:44:55  UHLWIi          en5       
+fe80::%en0         link#10            UCI             en0       
+fe80::df:eea7:d8e0 14:60:cb:10:ec:17  UHLWI           en0       
+fe80::472:ae33:7f7 b4:18:d1:9d:bc:2d  UHLWI           en0       
+ipad.local         4c:56:9d:5f:b7:4c  UHLWI           en0       
+fe80::ced:5f18:1d1 14:60:cb:10:ec:17  UHLWI           en0       
+kbrazil-mac.local  a4:83:e7:2d:62:8f  UHLI            lo0       
+fe80::10f2:d51c:68 e0:33:8e:68:38:d6  UHLWI           en0       
+upstairs.local     50:32:37:d7:f5:9b  UHLWIi          en0       
+fe80::1899:d8f6:dc 50:32:37:d7:f5:9b  UHLWI           en0       
+kellys-macbook-pro f0:18:98:3:d8:39   UHLWI           en0       
+bedroom.local      d0:3:4b:3b:28:d5   UHLWI           en0       
+kellys-airport-exp 48:d7:5:f1:86:e8   UHLWI           en0       
+hp9cb654545bb9.loc 9c:b6:54:5a:5a:7c  UHLWI           en0       
+fe80::feae:34ff:fe fc:ae:34:a1:3a:80  UHLWIir         en0       
+fe80::%awdl0       link#12            UCI           awdl0       
+fe80::b41f:b7ff:fe b6:1f:b7:57:a5:4f  UHLI            lo0       
+fe80::%utun0       kbrazil-mac.local  UcI           utun0       
+kbrazil-mac.local  link#18            UHLI            lo0       
+fe80::%utun1       kbrazil-mac.local  UcI           utun1       
+kbrazil-mac.local  link#21            UHLI            lo0       
+fe80::%utun2       kbrazil-mac.local  UcI           utun2       
+kbrazil-mac.local  link#22            UHLI            lo0       
+fe80::%utun3       kbrazil-mac.local  UcI           utun3       
+kbrazil-mac.local  link#23            UHLI            lo0       
+ff01::%lo0         localhost          UmCI            lo0       
+ff01::%en5         link#8             UmCI            en5       
+ff01::%en0         link#10            UmCI            en0       
+ff01::%awdl0       link#12            UmCI          awdl0       
+ff01::%utun0       kbrazil-mac.local  UmCI          utun0       
+ff01::%utun1       kbrazil-mac.local  UmCI          utun1       
+ff01::%utun2       kbrazil-mac.local  UmCI          utun2       
+ff01::%utun3       kbrazil-mac.local  UmCI          utun3       
+ff02::%lo0         localhost          UmCI            lo0       
+ff02::%en5         link#8             UmCI            en5       
+ff02::%en0         link#10            UmCI            en0       
+ff02::%awdl0       link#12            UmCI          awdl0       
+ff02::%utun0       kbrazil-mac.local  UmCI          utun0       
+ff02::%utun1       kbrazil-mac.local  UmCI          utun1       
+ff02::%utun2       kbrazil-mac.local  UmCI          utun2       
+ff02::%utun3       kbrazil-mac.local  UmCI          utun3       
diff --git a/tests/fixtures/osx-10.14.6/netstat-rnl.json b/tests/fixtures/osx-10.14.6/netstat-rnl.json
new file mode 100644
index 00000000..bb7f9502
--- /dev/null
+++ b/tests/fixtures/osx-10.14.6/netstat-rnl.json
@@ -0,0 +1 @@
+[{"destination": "default", "gateway": "192.168.1.254", "route_flags": "UGSc", "route_refs": 83, "use": 24, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "127", "gateway": "127.0.0.1", "route_flags": "UCS", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "127.0.0.1", "gateway": "127.0.0.1", "route_flags": "UH", "route_refs": 18, "use": 1266231, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "169.254", "gateway": "link#10", "route_flags": "UCS", "route_refs": 1, "use": 0, "mtu": 1500, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "192.168.1", "gateway": "link#10", "route_flags": "UCS", "route_refs": 12, "use": 0, "mtu": 1500, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "192.168.1.64", "gateway": "e0:33:8e:68:38:d6", "route_flags": "UHLWIi", "route_refs": 2, "use": 470, "mtu": 1500, "netif": "en0", "expire": "753", "kind": "route"}, {"destination": "192.168.1.72", "gateway": "f0:18:98:3:d8:39", "route_flags": "UHLWIi", "route_refs": 1, "use": 8878, "mtu": 1500, "netif": "en0", "expire": "1105", "kind": "route"}, {"destination": "192.168.1.75", "gateway": "4c:56:9d:5f:b7:4c", "route_flags": "UHLWIi", "route_refs": 1, "use": 600, "mtu": 1500, "netif": "en0", "expire": "673", "kind": "route"}, {"destination": "192.168.1.80", "gateway": "0:90:a9:ed:e4:35", "route_flags": "UHLWIi", "route_refs": 1, "use": 265604, "mtu": 1500, "netif": "en0", "expire": "931", "kind": "route"}, {"destination": "192.168.1.88", "gateway": "c8:d0:83:cd:e3:2d", "route_flags": "UHLWIi", "route_refs": 1, "use": 4310, "mtu": 1500, "netif": "en0", "expire": "278", "kind": "route"}, {"destination": "192.168.1.89", "gateway": "d0:3:4b:3b:28:d5", "route_flags": "UHLWIi", "route_refs": 1, "use": 4588, "mtu": 1500, "netif": "en0", "expire": "1132", "kind": "route"}, {"destination": "192.168.1.186", "gateway": "50:32:37:d7:f5:9b", "route_flags": "UHLWIi", "route_refs": 1, "use": 6123, "mtu": 1500, "netif": "en0", "expire": "1181", "kind": "route"}, {"destination": "192.168.1.216", "gateway": "3c:37:86:15:ad:f7", "route_flags": "UHLWI", "route_refs": 0, "use": 16, "mtu": 1500, "netif": "en0", "expire": "565", "kind": "route"}, {"destination": "192.168.1.221/32", "gateway": "link#10", "route_flags": "UCS", "route_refs": 1, "use": 0, "mtu": 1500, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "192.168.1.221", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHLWI", "route_refs": 0, "use": 36, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "192.168.1.242", "gateway": "50:14:79:12:42:3e", "route_flags": "UHLWI", "route_refs": 0, "use": 0, "mtu": 1500, "netif": "en0", "expire": "1182", "kind": "route"}, {"destination": "192.168.1.251", "gateway": "14:60:cb:10:ec:17", "route_flags": "UHLWI", "route_refs": 0, "use": 54, "mtu": 1500, "netif": "en0", "expire": "1157", "kind": "route"}, {"destination": "192.168.1.253", "gateway": "3c:37:86:15:dd:b3", "route_flags": "UHLWI", "route_refs": 0, "use": 3300, "mtu": 1500, "netif": "en0", "expire": "839", "kind": "route"}, {"destination": "192.168.1.254/32", "gateway": "link#10", "route_flags": "UCS", "route_refs": 1, "use": 0, "mtu": 1500, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "192.168.1.254", "gateway": "fc:ae:34:a1:3a:80", "route_flags": "UHLWIir", "route_refs": 29, "use": 69464, "mtu": 1500, "netif": "en0", "expire": "1200", "kind": "route"}, {"destination": "192.168.1.255", "gateway": "ff:ff:ff:ff:ff:ff", "route_flags": "UHLWbI", "route_refs": 0, "use": 4, "mtu": 1500, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "192.168.71", "gateway": "link#20", "route_flags": "UC", "route_refs": 3, "use": 0, "mtu": 1500, "netif": "vmnet8", "expire": "!", "kind": "route"}, {"destination": "192.168.71.160", "gateway": "link#20", "route_flags": "UHLWIi", "route_refs": 1, "use": 1708, "mtu": 1500, "netif": "vmnet8", "expire": "!", "kind": "route"}, {"destination": "192.168.71.255", "gateway": "ff:ff:ff:ff:ff:ff", "route_flags": "UHLWbI", "route_refs": 0, "use": 4, "mtu": 1500, "netif": "vmnet8", "expire": "!", "kind": "route"}, {"destination": "192.168.101", "gateway": "link#19", "route_flags": "UC", "route_refs": 2, "use": 0, "mtu": 1500, "netif": "vmnet1", "expire": "!", "kind": "route"}, {"destination": "192.168.101.255", "gateway": "ff:ff:ff:ff:ff:ff", "route_flags": "UHLWbI", "route_refs": 0, "use": 4, "mtu": 1500, "netif": "vmnet1", "expire": "!", "kind": "route"}, {"destination": "224.0.0/4", "gateway": "link#10", "route_flags": "UmCS", "route_refs": 2, "use": 0, "mtu": 1500, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "224.0.0.251", "gateway": "1:0:5e:0:0:fb", "route_flags": "UHmLWI", "route_refs": 0, "use": 312, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "239.255.255.250", "gateway": "1:0:5e:7f:ff:fa", "route_flags": "UHmLWI", "route_refs": 0, "use": 9918, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "255.255.255.255/32", "gateway": "link#10", "route_flags": "UCS", "route_refs": 0, "use": 0, "mtu": 1500, "netif": "en0", "expire": "!", "kind": "route"}, {"destination": "default", "gateway": "fe80::feae:34ff:fea1:3a80%en0", "route_flags": "UGc", "route_refs": 7, "use": 0, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "default", "gateway": "fe80::%utun0", "route_flags": "UGcI", "route_refs": 0, "use": 0, "mtu": 2000, "netif": "utun0", "kind": "route"}, {"destination": "default", "gateway": "fe80::%utun1", "route_flags": "UGcI", "route_refs": 0, "use": 0, "mtu": 1380, "netif": "utun1", "kind": "route"}, {"destination": "default", "gateway": "fe80::%utun2", "route_flags": "UGcI", "route_refs": 0, "use": 0, "mtu": 1380, "netif": "utun2", "kind": "route"}, {"destination": "default", "gateway": "fe80::%utun3", "route_flags": "UGcI", "route_refs": 0, "use": 0, "mtu": 1380, "netif": "utun3", "kind": "route"}, {"destination": "::1", "gateway": "::1", "route_flags": "UHL", "route_refs": 1, "use": 4513, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "2600:1700:bab0:d40::/64", "gateway": "link#10", "route_flags": "UC", "route_refs": 2, "use": 0, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "2600:1700:bab0:d40::1", "gateway": "fc:ae:34:a1:3a:80", "route_flags": "UHLWIi", "route_refs": 12, "use": 68412, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "2600:1700:bab0:d40::39", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "2600:1700:bab0:d40:1874:4566:6499:f3d1", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "2600:1700:bab0:d40:5894:f4c5:a982:26be", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "2600:1700:bab0:d40:c9de:af8a:762c:422c", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "2600:1700:bab0:d40:edd2:2cbf:f03a:d14f", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "2600:1700:bab0:d40:f078:690e:f0ba:dfb", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHL", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "fe80::%lo0/64", "gateway": "fe80::1%lo0", "route_flags": "UcI", "route_refs": 1, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "fe80::1%lo0", "gateway": "link#1", "route_flags": "UHLI", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "fe80::%en5/64", "gateway": "link#8", "route_flags": "UCI", "route_refs": 2, "use": 0, "mtu": 1500, "netif": "en5", "kind": "route"}, {"destination": "fe80::aede:48ff:fe00:1122%en5", "gateway": "ac:de:48:0:11:22", "route_flags": "UHLI", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "fe80::aede:48ff:fe33:4455%en5", "gateway": "ac:de:48:33:44:55", "route_flags": "UHLWIi", "route_refs": 77, "use": 826, "mtu": 1500, "netif": "en5", "kind": "route"}, {"destination": "fe80::%en0/64", "gateway": "link#10", "route_flags": "UCI", "route_refs": 13, "use": 0, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::df:eea7:d8e0:237a%en0", "gateway": "14:60:cb:10:ec:17", "route_flags": "UHLWI", "route_refs": 0, "use": 293, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::472:ae33:7f74:8baf%en0", "gateway": "b4:18:d1:9d:bc:2d", "route_flags": "UHLWI", "route_refs": 0, "use": 2, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::c73:1ab9:79c2:c193%en0", "gateway": "4c:56:9d:5f:b7:4c", "route_flags": "UHLWI", "route_refs": 0, "use": 1597, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::ced:5f18:1d1e:2d6b%en0", "gateway": "14:60:cb:10:ec:17", "route_flags": "UHLWI", "route_refs": 0, "use": 14, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::cf9:ca6f:7d7a:50a2%en0", "gateway": "a4:83:e7:2d:62:8f", "route_flags": "UHLI", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "fe80::10f2:d51c:68e3:bfbb%en0", "gateway": "e0:33:8e:68:38:d6", "route_flags": "UHLWI", "route_refs": 0, "use": 656, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::1406:1bd5:a957:6df2%en0", "gateway": "50:32:37:d7:f5:9b", "route_flags": "UHLWI", "route_refs": 0, "use": 2100, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::1899:d8f6:dca5:207%en0", "gateway": "50:32:37:d7:f5:9b", "route_flags": "UHLWI", "route_refs": 0, "use": 4619, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::1c4d:12ea:5e57:24ad%en0", "gateway": "f0:18:98:3:d8:39", "route_flags": "UHLWIi", "route_refs": 1, "use": 8, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::1cff:a835:c99b:22c1%en0", "gateway": "d0:3:4b:3b:28:d5", "route_flags": "UHLWI", "route_refs": 0, "use": 477, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::4ad7:5ff:fef1:86e8%en0", "gateway": "48:d7:5:f1:86:e8", "route_flags": "UHLWI", "route_refs": 0, "use": 862, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::9eb6:54ff:fe5a:5a7c%en0", "gateway": "9c:b6:54:5a:5a:7c", "route_flags": "UHLWI", "route_refs": 0, "use": 322, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::feae:34ff:fea1:3a80%en0", "gateway": "fc:ae:34:a1:3a:80", "route_flags": "UHLWIir", "route_refs": 7, "use": 27100, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "fe80::%awdl0/64", "gateway": "link#12", "route_flags": "UCI", "route_refs": 1, "use": 0, "mtu": 1484, "netif": "awdl0", "kind": "route"}, {"destination": "fe80::b41f:b7ff:fe57:a54f%awdl0", "gateway": "b6:1f:b7:57:a5:4f", "route_flags": "UHLI", "route_refs": 1, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "fe80::%utun0/64", "gateway": "fe80::30fe:52f1:103c:c66c%utun0", "route_flags": "UcI", "route_refs": 2, "use": 0, "mtu": 2000, "netif": "utun0", "kind": "route"}, {"destination": "fe80::30fe:52f1:103c:c66c%utun0", "gateway": "link#18", "route_flags": "UHLI", "route_refs": 1, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "fe80::%utun1/64", "gateway": "fe80::aaf6:1785:571a:57a9%utun1", "route_flags": "UcI", "route_refs": 2, "use": 0, "mtu": 1380, "netif": "utun1", "kind": "route"}, {"destination": "fe80::aaf6:1785:571a:57a9%utun1", "gateway": "link#21", "route_flags": "UHLI", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "fe80::%utun2/64", "gateway": "fe80::ce02:efdc:708:5411%utun2", "route_flags": "UcI", "route_refs": 2, "use": 0, "mtu": 1380, "netif": "utun2", "kind": "route"}, {"destination": "fe80::ce02:efdc:708:5411%utun2", "gateway": "link#22", "route_flags": "UHLI", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "fe80::%utun3/64", "gateway": "fe80::1188:a032:c478:4b13%utun3", "route_flags": "UcI", "route_refs": 2, "use": 0, "mtu": 1380, "netif": "utun3", "kind": "route"}, {"destination": "fe80::1188:a032:c478:4b13%utun3", "gateway": "link#23", "route_flags": "UHLI", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "ff01::%lo0/32", "gateway": "::1", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "ff01::%en5/32", "gateway": "link#8", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1500, "netif": "en5", "kind": "route"}, {"destination": "ff01::%en0/32", "gateway": "link#10", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "ff01::%awdl0/32", "gateway": "link#12", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1484, "netif": "awdl0", "kind": "route"}, {"destination": "ff01::%utun0/32", "gateway": "fe80::30fe:52f1:103c:c66c%utun0", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 2000, "netif": "utun0", "kind": "route"}, {"destination": "ff01::%utun1/32", "gateway": "fe80::aaf6:1785:571a:57a9%utun1", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1380, "netif": "utun1", "kind": "route"}, {"destination": "ff01::%utun2/32", "gateway": "fe80::ce02:efdc:708:5411%utun2", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1380, "netif": "utun2", "kind": "route"}, {"destination": "ff01::%utun3/32", "gateway": "fe80::1188:a032:c478:4b13%utun3", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1380, "netif": "utun3", "kind": "route"}, {"destination": "ff02::%lo0/32", "gateway": "::1", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 16384, "netif": "lo0", "kind": "route"}, {"destination": "ff02::%en5/32", "gateway": "link#8", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1500, "netif": "en5", "kind": "route"}, {"destination": "ff02::%en0/32", "gateway": "link#10", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1500, "netif": "en0", "kind": "route"}, {"destination": "ff02::%awdl0/32", "gateway": "link#12", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1484, "netif": "awdl0", "kind": "route"}, {"destination": "ff02::%utun0/32", "gateway": "fe80::30fe:52f1:103c:c66c%utun0", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 2000, "netif": "utun0", "kind": "route"}, {"destination": "ff02::%utun1/32", "gateway": "fe80::aaf6:1785:571a:57a9%utun1", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1380, "netif": "utun1", "kind": "route"}, {"destination": "ff02::%utun2/32", "gateway": "fe80::ce02:efdc:708:5411%utun2", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1380, "netif": "utun2", "kind": "route"}, {"destination": "ff02::%utun3/32", "gateway": "fe80::1188:a032:c478:4b13%utun3", "route_flags": "UmCI", "route_refs": 0, "use": 0, "mtu": 1380, "netif": "utun3", "kind": "route"}]
diff --git a/tests/fixtures/osx-10.14.6/netstat-rnl.out b/tests/fixtures/osx-10.14.6/netstat-rnl.out
new file mode 100644
index 00000000..74cd1781
--- /dev/null
+++ b/tests/fixtures/osx-10.14.6/netstat-rnl.out
@@ -0,0 +1,96 @@
+Routing tables
+
+Internet:
+Destination        Gateway            Flags        Refs      Use    Mtu   Netif Expire
+default            192.168.1.254      UGSc           83       24   1500     en0       
+127                127.0.0.1          UCS             0        0  16384     lo0       
+127.0.0.1          127.0.0.1          UH             18  1266231  16384     lo0       
+169.254            link#10            UCS             1        0   1500     en0      !
+192.168.1          link#10            UCS            12        0   1500     en0      !
+192.168.1.64       e0:33:8e:68:38:d6  UHLWIi          2      470   1500     en0    753
+192.168.1.72       f0:18:98:3:d8:39   UHLWIi          1     8878   1500     en0   1105
+192.168.1.75       4c:56:9d:5f:b7:4c  UHLWIi          1      600   1500     en0    673
+192.168.1.80       0:90:a9:ed:e4:35   UHLWIi          1   265604   1500     en0    931
+192.168.1.88       c8:d0:83:cd:e3:2d  UHLWIi          1     4310   1500     en0    278
+192.168.1.89       d0:3:4b:3b:28:d5   UHLWIi          1     4588   1500     en0   1132
+192.168.1.186      50:32:37:d7:f5:9b  UHLWIi          1     6123   1500     en0   1181
+192.168.1.216      3c:37:86:15:ad:f7  UHLWI           0       16   1500     en0    565
+192.168.1.221/32   link#10            UCS             1        0   1500     en0      !
+192.168.1.221      a4:83:e7:2d:62:8f  UHLWI           0       36  16384     lo0       
+192.168.1.242      50:14:79:12:42:3e  UHLWI           0        0   1500     en0   1182
+192.168.1.251      14:60:cb:10:ec:17  UHLWI           0       54   1500     en0   1157
+192.168.1.253      3c:37:86:15:dd:b3  UHLWI           0     3300   1500     en0    839
+192.168.1.254/32   link#10            UCS             1        0   1500     en0      !
+192.168.1.254      fc:ae:34:a1:3a:80  UHLWIir        29    69464   1500     en0   1200
+192.168.1.255      ff:ff:ff:ff:ff:ff  UHLWbI          0        4   1500     en0      !
+192.168.71         link#20            UC              3        0   1500  vmnet8      !
+192.168.71.160     link#20            UHLWIi          1     1708   1500  vmnet8      !
+192.168.71.255     ff:ff:ff:ff:ff:ff  UHLWbI          0        4   1500  vmnet8      !
+192.168.101        link#19            UC              2        0   1500  vmnet1      !
+192.168.101.255    ff:ff:ff:ff:ff:ff  UHLWbI          0        4   1500  vmnet1      !
+224.0.0/4          link#10            UmCS            2        0   1500     en0      !
+224.0.0.251        1:0:5e:0:0:fb      UHmLWI          0      312   1500     en0       
+239.255.255.250    1:0:5e:7f:ff:fa    UHmLWI          0     9918   1500     en0       
+255.255.255.255/32 link#10            UCS             0        0   1500     en0      !
+
+Internet6:
+Destination                             Gateway                         Flags        Refs      Use    Mtu    Netif Expire
+default                                 fe80::feae:34ff:fea1:3a80%en0   UGc             7        0   1500      en0       
+default                                 fe80::%utun0                    UGcI            0        0   2000    utun0       
+default                                 fe80::%utun1                    UGcI            0        0   1380    utun1       
+default                                 fe80::%utun2                    UGcI            0        0   1380    utun2       
+default                                 fe80::%utun3                    UGcI            0        0   1380    utun3       
+::1                                     ::1                             UHL             1     4513  16384      lo0       
+2600:1700:bab0:d40::/64                 link#10                         UC              2        0   1500      en0       
+2600:1700:bab0:d40::1                   fc:ae:34:a1:3a:80               UHLWIi         12    68412   1500      en0       
+2600:1700:bab0:d40::39                  a4:83:e7:2d:62:8f               UHL             0        0  16384      lo0       
+2600:1700:bab0:d40:1874:4566:6499:f3d1  a4:83:e7:2d:62:8f               UHL             0        0  16384      lo0       
+2600:1700:bab0:d40:5894:f4c5:a982:26be  a4:83:e7:2d:62:8f               UHL             0        0  16384      lo0       
+2600:1700:bab0:d40:c9de:af8a:762c:422c  a4:83:e7:2d:62:8f               UHL             0        0  16384      lo0       
+2600:1700:bab0:d40:edd2:2cbf:f03a:d14f  a4:83:e7:2d:62:8f               UHL             0        0  16384      lo0       
+2600:1700:bab0:d40:f078:690e:f0ba:dfb   a4:83:e7:2d:62:8f               UHL             0        0  16384      lo0       
+fe80::%lo0/64                           fe80::1%lo0                     UcI             1        0  16384      lo0       
+fe80::1%lo0                             link#1                          UHLI            0        0  16384      lo0       
+fe80::%en5/64                           link#8                          UCI             2        0   1500      en5       
+fe80::aede:48ff:fe00:1122%en5           ac:de:48:0:11:22                UHLI            0        0  16384      lo0       
+fe80::aede:48ff:fe33:4455%en5           ac:de:48:33:44:55               UHLWIi         77      826   1500      en5       
+fe80::%en0/64                           link#10                         UCI            13        0   1500      en0       
+fe80::df:eea7:d8e0:237a%en0             14:60:cb:10:ec:17               UHLWI           0      293   1500      en0       
+fe80::472:ae33:7f74:8baf%en0            b4:18:d1:9d:bc:2d               UHLWI           0        2   1500      en0       
+fe80::c73:1ab9:79c2:c193%en0            4c:56:9d:5f:b7:4c               UHLWI           0     1597   1500      en0       
+fe80::ced:5f18:1d1e:2d6b%en0            14:60:cb:10:ec:17               UHLWI           0       14   1500      en0       
+fe80::cf9:ca6f:7d7a:50a2%en0            a4:83:e7:2d:62:8f               UHLI            0        0  16384      lo0       
+fe80::10f2:d51c:68e3:bfbb%en0           e0:33:8e:68:38:d6               UHLWI           0      656   1500      en0       
+fe80::1406:1bd5:a957:6df2%en0           50:32:37:d7:f5:9b               UHLWI           0     2100   1500      en0       
+fe80::1899:d8f6:dca5:207%en0            50:32:37:d7:f5:9b               UHLWI           0     4619   1500      en0       
+fe80::1c4d:12ea:5e57:24ad%en0           f0:18:98:3:d8:39                UHLWIi          1        8   1500      en0       
+fe80::1cff:a835:c99b:22c1%en0           d0:3:4b:3b:28:d5                UHLWI           0      477   1500      en0       
+fe80::4ad7:5ff:fef1:86e8%en0            48:d7:5:f1:86:e8                UHLWI           0      862   1500      en0       
+fe80::9eb6:54ff:fe5a:5a7c%en0           9c:b6:54:5a:5a:7c               UHLWI           0      322   1500      en0       
+fe80::feae:34ff:fea1:3a80%en0           fc:ae:34:a1:3a:80               UHLWIir         7    27100   1500      en0       
+fe80::%awdl0/64                         link#12                         UCI             1        0   1484    awdl0       
+fe80::b41f:b7ff:fe57:a54f%awdl0         b6:1f:b7:57:a5:4f               UHLI            1        0  16384      lo0       
+fe80::%utun0/64                         fe80::30fe:52f1:103c:c66c%utun0 UcI             2        0   2000    utun0       
+fe80::30fe:52f1:103c:c66c%utun0         link#18                         UHLI            1        0  16384      lo0       
+fe80::%utun1/64                         fe80::aaf6:1785:571a:57a9%utun1 UcI             2        0   1380    utun1       
+fe80::aaf6:1785:571a:57a9%utun1         link#21                         UHLI            0        0  16384      lo0       
+fe80::%utun2/64                         fe80::ce02:efdc:708:5411%utun2  UcI             2        0   1380    utun2       
+fe80::ce02:efdc:708:5411%utun2          link#22                         UHLI            0        0  16384      lo0       
+fe80::%utun3/64                         fe80::1188:a032:c478:4b13%utun3 UcI             2        0   1380    utun3       
+fe80::1188:a032:c478:4b13%utun3         link#23                         UHLI            0        0  16384      lo0       
+ff01::%lo0/32                           ::1                             UmCI            0        0  16384      lo0       
+ff01::%en5/32                           link#8                          UmCI            0        0   1500      en5       
+ff01::%en0/32                           link#10                         UmCI            0        0   1500      en0       
+ff01::%awdl0/32                         link#12                         UmCI            0        0   1484    awdl0       
+ff01::%utun0/32                         fe80::30fe:52f1:103c:c66c%utun0 UmCI            0        0   2000    utun0       
+ff01::%utun1/32                         fe80::aaf6:1785:571a:57a9%utun1 UmCI            0        0   1380    utun1       
+ff01::%utun2/32                         fe80::ce02:efdc:708:5411%utun2  UmCI            0        0   1380    utun2       
+ff01::%utun3/32                         fe80::1188:a032:c478:4b13%utun3 UmCI            0        0   1380    utun3       
+ff02::%lo0/32                           ::1                             UmCI            0        0  16384      lo0       
+ff02::%en5/32                           link#8                          UmCI            0        0   1500      en5       
+ff02::%en0/32                           link#10                         UmCI            0        0   1500      en0       
+ff02::%awdl0/32                         link#12                         UmCI            0        0   1484    awdl0       
+ff02::%utun0/32                         fe80::30fe:52f1:103c:c66c%utun0 UmCI            0        0   2000    utun0       
+ff02::%utun1/32                         fe80::aaf6:1785:571a:57a9%utun1 UmCI            0        0   1380    utun1       
+ff02::%utun2/32                         fe80::ce02:efdc:708:5411%utun2  UmCI            0        0   1380    utun2       
+ff02::%utun3/32                         fe80::1188:a032:c478:4b13%utun3 UmCI            0        0   1380    utun3       
diff --git a/tests/test_netstat.py b/tests/test_netstat.py
index 3bbe8bf7..38634343 100644
--- a/tests/test_netstat.py
+++ b/tests/test_netstat.py
@@ -52,6 +52,13 @@ class MyTests(unittest.TestCase):
         with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/netstat-Abn.out'), 'r', encoding='utf-8') as f:
             self.osx_14_6_netstat_Abn = f.read()
 
+
+        with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/netstat-r.out'), 'r', encoding='utf-8') as f:
+            self.osx_14_6_netstat_r = f.read()
+
+        with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/netstat-rnl.out'), 'r', encoding='utf-8') as f:
+            self.osx_14_6_netstat_rnl = f.read()
+
         # output
         with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/netstat.json'), 'r', encoding='utf-8') as f:
             self.centos_7_7_netstat_json = json.loads(f.read())
@@ -95,6 +102,12 @@ class MyTests(unittest.TestCase):
         with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/netstat-Abn.json'), 'r', encoding='utf-8') as f:
             self.osx_14_6_netstat_Abn_json = json.loads(f.read())
 
+        with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/netstat-r.json'), 'r', encoding='utf-8') as f:
+            self.osx_14_6_netstat_r_json = json.loads(f.read())
+
+        with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/netstat-rnl.json'), 'r', encoding='utf-8') as f:
+            self.osx_14_6_netstat_rnl_json = json.loads(f.read())
+
     def test_netstat_centos_7_7(self):
         """
         Test 'netstat' on Centos 7.7
@@ -179,6 +192,18 @@ class MyTests(unittest.TestCase):
         """
         self.assertEqual(jc.parsers.netstat.parse(self.osx_14_6_netstat_Abn, quiet=True), self.osx_14_6_netstat_Abn_json)
 
+    def test_netstat_r_osx_16_4(self):
+        """
+        Test 'netstat -r' on OSX 16.4
+        """
+        self.assertEqual(jc.parsers.netstat.parse(self.osx_14_6_netstat_r, quiet=True), self.osx_14_6_netstat_r_json)
+
+    def test_netstat_rnl_osx_16_4(self):
+        """
+        Test 'netstat -rnl' on OSX 16.4
+        """
+        self.assertEqual(jc.parsers.netstat.parse(self.osx_14_6_netstat_rnl, quiet=True), self.osx_14_6_netstat_rnl_json)
+
 
 if __name__ == '__main__':
     unittest.main()