tplinkrouterc6u 5.7.0__py3-none-any.whl → 5.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- test/test_client_c1200.py +4 -40
- test/test_client_c6u.py +141 -0
- test/test_client_wdr.py +292 -0
- tplinkrouterc6u/__init__.py +1 -0
- tplinkrouterc6u/client/c1200.py +0 -36
- tplinkrouterc6u/client/c6u.py +50 -3
- tplinkrouterc6u/client/c80.py +5 -2
- tplinkrouterc6u/client/wdr.py +672 -0
- tplinkrouterc6u/provider.py +2 -1
- {tplinkrouterc6u-5.7.0.dist-info → tplinkrouterc6u-5.9.0.dist-info}/METADATA +8 -1
- {tplinkrouterc6u-5.7.0.dist-info → tplinkrouterc6u-5.9.0.dist-info}/RECORD +14 -12
- {tplinkrouterc6u-5.7.0.dist-info → tplinkrouterc6u-5.9.0.dist-info}/WHEEL +1 -1
- {tplinkrouterc6u-5.7.0.dist-info → tplinkrouterc6u-5.9.0.dist-info}/licenses/LICENSE +0 -0
- {tplinkrouterc6u-5.7.0.dist-info → tplinkrouterc6u-5.9.0.dist-info}/top_level.txt +0 -0
test/test_client_c1200.py
CHANGED
|
@@ -5,7 +5,6 @@ from tplinkrouterc6u import (
|
|
|
5
5
|
Connection,
|
|
6
6
|
ClientException,
|
|
7
7
|
)
|
|
8
|
-
from tplinkrouterc6u.common.package_enum import VPN
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
class TestTPLinkC1200Client(TestCase):
|
|
@@ -201,13 +200,13 @@ class TestTPLinkC1200Client(TestCase):
|
|
|
201
200
|
ignore_response: bool = False,
|
|
202
201
|
ignore_errors: bool = False,
|
|
203
202
|
) -> dict | None:
|
|
204
|
-
if path == "
|
|
203
|
+
if path == "admin/openvpn?form=config&operation=read":
|
|
205
204
|
return loads(response_openvpn_read)
|
|
206
|
-
if path == "
|
|
205
|
+
if path == "admin/pptpd?form=config&operation=read":
|
|
207
206
|
return loads(response_pptp_read)
|
|
208
|
-
if path == "
|
|
207
|
+
if path == "admin/vpnconn?form=config&operation=list&vpntype=openvpn":
|
|
209
208
|
return loads(respone_vpnconn_openvpn)
|
|
210
|
-
if path == "
|
|
209
|
+
if path == "admin/vpnconn?form=config&operation=list&vpntype=pptp":
|
|
211
210
|
return loads(respone_vpnconn_pptpvpn)
|
|
212
211
|
raise ClientException()
|
|
213
212
|
|
|
@@ -219,41 +218,6 @@ class TestTPLinkC1200Client(TestCase):
|
|
|
219
218
|
self.assertEqual(vpn_status.openvpn_clients_total, 2)
|
|
220
219
|
self.assertEqual(vpn_status.pptpvpn_clients_total, 3)
|
|
221
220
|
|
|
222
|
-
def test_set_vpn(self) -> None:
|
|
223
|
-
response_openvpn_read = """
|
|
224
|
-
{
|
|
225
|
-
"enabled": "on",
|
|
226
|
-
"proto": "udp",
|
|
227
|
-
"access": "home",
|
|
228
|
-
"cert_exist": true,
|
|
229
|
-
"mask": "255.255.255.0",
|
|
230
|
-
"port": "1194",
|
|
231
|
-
"serverip": "10.8.0.0"
|
|
232
|
-
}
|
|
233
|
-
"""
|
|
234
|
-
|
|
235
|
-
class TPLinkRouterTest(TplinkC1200Router):
|
|
236
|
-
def request(
|
|
237
|
-
self,
|
|
238
|
-
path: str,
|
|
239
|
-
data: str,
|
|
240
|
-
ignore_response: bool = False,
|
|
241
|
-
ignore_errors: bool = False,
|
|
242
|
-
) -> dict | None:
|
|
243
|
-
if path == "/admin/openvpn?form=config&operation=read":
|
|
244
|
-
return loads(response_openvpn_read)
|
|
245
|
-
self.captured_path = path
|
|
246
|
-
|
|
247
|
-
client = TPLinkRouterTest("", "")
|
|
248
|
-
client.set_vpn(VPN.OPEN_VPN, True)
|
|
249
|
-
|
|
250
|
-
expected_path = (
|
|
251
|
-
"/admin/openvpn?form=config&operation=write&enabled=on"
|
|
252
|
-
"&proto=udp&access=home&cert_exist=True"
|
|
253
|
-
"&mask=255.255.255.0&port=1194&serverip=10.8.0.0"
|
|
254
|
-
)
|
|
255
|
-
self.assertEqual(client.captured_path, expected_path)
|
|
256
|
-
|
|
257
221
|
|
|
258
222
|
if __name__ == "__main__":
|
|
259
223
|
main()
|
test/test_client_c6u.py
CHANGED
|
@@ -9,6 +9,7 @@ from tplinkrouterc6u import (
|
|
|
9
9
|
IPv4Status,
|
|
10
10
|
Device,
|
|
11
11
|
ClientException,
|
|
12
|
+
VPN,
|
|
12
13
|
)
|
|
13
14
|
|
|
14
15
|
|
|
@@ -729,6 +730,146 @@ class TestTPLinkClient(TestCase):
|
|
|
729
730
|
self.assertEqual(result.lan_ipv4_dhcp_enable, False)
|
|
730
731
|
self.assertEqual(result.remote, None)
|
|
731
732
|
|
|
733
|
+
def test_get_status_wan_macaddr_empty(self) -> None:
|
|
734
|
+
response_status = '''
|
|
735
|
+
{
|
|
736
|
+
"success": true,
|
|
737
|
+
"data": {
|
|
738
|
+
"lan_macaddr": "06:e6:97:9e:23:f5",
|
|
739
|
+
"wan_macaddr": "",
|
|
740
|
+
"wan_ipv4_ipaddr": "0.0.0.0",
|
|
741
|
+
"wan_ipv4_gateway": "0.0.0.0"
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
'''
|
|
745
|
+
response_stats = '''
|
|
746
|
+
{
|
|
747
|
+
"data": [],
|
|
748
|
+
"timeout": false,
|
|
749
|
+
"success": true,
|
|
750
|
+
"operator": "load"
|
|
751
|
+
}
|
|
752
|
+
'''
|
|
753
|
+
|
|
754
|
+
class TPLinkRouterTest(TplinkRouter):
|
|
755
|
+
def request(self, path: str, data: str,
|
|
756
|
+
ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
|
|
757
|
+
if path == 'admin/status?form=all&operation=read':
|
|
758
|
+
return loads(response_status)['data']
|
|
759
|
+
elif path == 'admin/wireless?form=statistics':
|
|
760
|
+
return loads(response_stats)['data']
|
|
761
|
+
raise ClientException()
|
|
762
|
+
|
|
763
|
+
client = TPLinkRouterTest('', '')
|
|
764
|
+
result = client.get_status()
|
|
765
|
+
|
|
766
|
+
self.assertIsInstance(result, Status)
|
|
767
|
+
self.assertEqual(result.wan_macaddr, None)
|
|
768
|
+
self.assertEqual(result.wan_ipv4_addr, '0.0.0.0')
|
|
769
|
+
self.assertEqual(result.wan_ipv4_gateway, '0.0.0.0')
|
|
770
|
+
self.assertEqual(result.lan_macaddr, '06-E6-97-9E-23-F5')
|
|
771
|
+
|
|
772
|
+
def test_vpn_status(self) -> None:
|
|
773
|
+
response_openvpn_read = """
|
|
774
|
+
{
|
|
775
|
+
"enabled": "on",
|
|
776
|
+
"proto": "udp",
|
|
777
|
+
"access": "home",
|
|
778
|
+
"cert_exist": true,
|
|
779
|
+
"mask": "255.255.255.0",
|
|
780
|
+
"port": "1194",
|
|
781
|
+
"serverip": "10.8.0.0"
|
|
782
|
+
}
|
|
783
|
+
"""
|
|
784
|
+
|
|
785
|
+
response_pptp_read = """
|
|
786
|
+
{
|
|
787
|
+
"enabled": "off",
|
|
788
|
+
"unencrypted_access": "on",
|
|
789
|
+
"samba_access": "on",
|
|
790
|
+
"netbios_pass": "on",
|
|
791
|
+
"remoteip": "10.0.0.11-20"
|
|
792
|
+
}
|
|
793
|
+
"""
|
|
794
|
+
|
|
795
|
+
respone_vpnconn_openvpn = """[
|
|
796
|
+
{"username": "admin", "remote_ip": "192.168.0.200", "ipaddr": "10.0.0.11",
|
|
797
|
+
"extra": "7450", "vpntype": "openvpn", "key": "7450"},
|
|
798
|
+
{"username": "admin", "remote_ip": "192.168.0.200", "ipaddr": "10.0.0.11",
|
|
799
|
+
"extra": "7450", "vpntype": "openvpn", "key": "7450"}
|
|
800
|
+
]"""
|
|
801
|
+
|
|
802
|
+
respone_vpnconn_pptpvpn = """[
|
|
803
|
+
{"username": "admin", "remote_ip": "192.168.0.200", "ipaddr": "10.0.0.11",
|
|
804
|
+
"extra": "7450", "vpntype": "pptp", "key": "7450"},
|
|
805
|
+
{"username": "admin", "remote_ip": "192.168.0.200", "ipaddr": "10.0.0.11",
|
|
806
|
+
"extra": "7450", "vpntype": "pptp", "key": "7450"},
|
|
807
|
+
{"username": "admin", "remote_ip": "192.168.0.200", "ipaddr": "10.0.0.11",
|
|
808
|
+
"extra": "7450", "vpntype": "pptp", "key": "7450"}
|
|
809
|
+
]"""
|
|
810
|
+
|
|
811
|
+
class TPLinkRouterTest(TplinkRouter):
|
|
812
|
+
def request(
|
|
813
|
+
self,
|
|
814
|
+
path: str,
|
|
815
|
+
data: str,
|
|
816
|
+
ignore_response: bool = False,
|
|
817
|
+
ignore_errors: bool = False,
|
|
818
|
+
) -> dict | None:
|
|
819
|
+
if path == "admin/openvpn?form=config":
|
|
820
|
+
return loads(response_openvpn_read)
|
|
821
|
+
if path == "admin/pptpd?form=config":
|
|
822
|
+
return loads(response_pptp_read)
|
|
823
|
+
if path == "admin/vpnconn?form=config" and data == "operation=list&vpntype=openvpn":
|
|
824
|
+
return loads(respone_vpnconn_openvpn)
|
|
825
|
+
if path == "admin/vpnconn?form=config" and data == "operation=list&vpntype=pptp":
|
|
826
|
+
return loads(respone_vpnconn_pptpvpn)
|
|
827
|
+
raise ClientException()
|
|
828
|
+
|
|
829
|
+
client = TPLinkRouterTest("", "")
|
|
830
|
+
|
|
831
|
+
vpn_status = client.get_vpn_status()
|
|
832
|
+
self.assertTrue(vpn_status.openvpn_enable)
|
|
833
|
+
self.assertFalse(vpn_status.pptpvpn_enable)
|
|
834
|
+
self.assertEqual(vpn_status.openvpn_clients_total, 2)
|
|
835
|
+
self.assertEqual(vpn_status.pptpvpn_clients_total, 3)
|
|
836
|
+
|
|
837
|
+
def test_set_vpn(self) -> None:
|
|
838
|
+
response_openvpn_read = """
|
|
839
|
+
{
|
|
840
|
+
"enabled": "on",
|
|
841
|
+
"proto": "udp",
|
|
842
|
+
"access": "home",
|
|
843
|
+
"cert_exist": true,
|
|
844
|
+
"mask": "255.255.255.0",
|
|
845
|
+
"port": "1194",
|
|
846
|
+
"serverip": "10.8.0.0"
|
|
847
|
+
}
|
|
848
|
+
"""
|
|
849
|
+
|
|
850
|
+
class TPLinkRouterTest(TplinkRouter):
|
|
851
|
+
def request(
|
|
852
|
+
self,
|
|
853
|
+
path: str,
|
|
854
|
+
data: str,
|
|
855
|
+
ignore_response: bool = False,
|
|
856
|
+
ignore_errors: bool = False,
|
|
857
|
+
) -> dict | None:
|
|
858
|
+
if path == "admin/openvpn?form=config" and data == "operation=read":
|
|
859
|
+
return loads(response_openvpn_read)
|
|
860
|
+
self.captured_path = path
|
|
861
|
+
self.captured_data = data
|
|
862
|
+
|
|
863
|
+
client = TPLinkRouterTest("", "")
|
|
864
|
+
client.set_vpn(VPN.OPEN_VPN, True)
|
|
865
|
+
|
|
866
|
+
expected_data = (
|
|
867
|
+
"operation=write&enabled=on"
|
|
868
|
+
"&proto=udp&access=home&cert_exist=True&mask=255.255.255.0&port=1194&serverip=10.8.0.0"
|
|
869
|
+
)
|
|
870
|
+
self.assertEqual(client.captured_path, 'admin/openvpn?form=config')
|
|
871
|
+
self.assertEqual(client.captured_data, expected_data)
|
|
872
|
+
|
|
732
873
|
|
|
733
874
|
if __name__ == '__main__':
|
|
734
875
|
main()
|
test/test_client_wdr.py
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
from unittest import main, TestCase
|
|
2
|
+
from ipaddress import IPv4Address
|
|
3
|
+
from macaddress import EUI48
|
|
4
|
+
from tplinkrouterc6u.common.dataclass import Firmware, Status
|
|
5
|
+
from tplinkrouterc6u.common.dataclass import IPv4Status, IPv4Reservation, IPv4DHCPLease
|
|
6
|
+
from tplinkrouterc6u import ClientError
|
|
7
|
+
from tplinkrouterc6u.client.wdr import TplinkWDRRouter
|
|
8
|
+
|
|
9
|
+
_NETWAN = (
|
|
10
|
+
'<SCRIPT language="javascript" type="text/javascript">\nvar wanTypeDetectInfoArray = '
|
|
11
|
+
+ "new Array(\n1, 0, 4500, \n0,0 );\n</SCRIPT>\n"
|
|
12
|
+
+ '<SCRIPT language="javascript" type="text/javascript">\nvar dhcpInf = new Array(\n1,\n'
|
|
13
|
+
+ '0,\n1,\n0,\n0,\n0,\n0,\n0,\n"",\n"",\n0,\n0,\n"",\n"192.168.0.129",\n"255.255.255.0",\n'
|
|
14
|
+
+ '"192.168.0.1",\n1,\n0,\n1500,\n0,\n"8.8.8.8",\n1,\n"8.8.4.4",\n0,\n0,\n0,\n"TL-WDR3600",\n0,0 );\n</SCRIPT>\n'
|
|
15
|
+
+ '<SCRIPT language="javascript" type="text/javascript">\nvar wantypeinfo = new Array(\n6,\n0,\n'
|
|
16
|
+
+ '"WanDynamicIpCfgRpm.htm",\n1,\n"WanStaticIpCfgRpm.htm",\n'
|
|
17
|
+
+ '2,\n"PPPoECfgRpm.htm",\n5,\n"BPACfgRpm.htm",\n6,\n"L2TPCfgRpm.htm",\n7,\n"PPTPCfgRpm.htm",\n0,0 );\n</SCRIPT>'
|
|
18
|
+
)
|
|
19
|
+
_NETLAN = (
|
|
20
|
+
'<SCRIPT language="javascript" type="text/javascript">\nvar lanPara = new Array(\n"C4-6E-1F-41-67-C0",\n'
|
|
21
|
+
+ '"192.168.1.254",\n2,\n"255.255.255.0",\n1,\n0,0 );\n</SCRIPT>'
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
_W24STA = (
|
|
25
|
+
'<SCRIPT language="javascript" type="text/javascript">\nvar wlanHostPara = new Array(\n1, 1, 8, 5000, 4,\n'
|
|
26
|
+
+ '0,0);\n</SCRIPT>\n<SCRIPT language="javascript" type="text/javascript">\nvar hostList = new Array(\n'
|
|
27
|
+
+ '"D0-BD-53-57-3E-4A", 1, 170893827, 0,\n"08-16-AC-03-E2-FA", 1, 873409583, 0,\n"F8-F1-E8-CD-0A-CF", 1, '
|
|
28
|
+
+ '240958643, 0,\n"ED-49-92-1A-1D-D7", 1, 358743698, 0,\n"0E-50-99-5D-9A-D5", 1, 572346959, 0,\n0,0 );\n</SCRIPT>'
|
|
29
|
+
)
|
|
30
|
+
_W50STA = (
|
|
31
|
+
'<SCRIPT language="javascript" type="text/javascript">\nvar wlanHostPara = new Array(\n1, 1, 8, 5000, 4,\n'
|
|
32
|
+
+ '0,0 );\n</SCRIPT>\n<SCRIPT language="javascript" type="text/javascript">\nvar hostList = new Array(\n'
|
|
33
|
+
+ '"50-A6-FC-6D-EB-D3", 1, 708938274, 0,\n"6A-D0-5F-2A-FA-2D", 1, 287340958, 0,\n"DA-69-2D-59-B3-FA", 1'
|
|
34
|
+
+ ", 540958641, 0,\n0,0 );\n</SCRIPT>"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
_WLANGUEST = (
|
|
38
|
+
'<SCRIPT language="javascript" type="text/javascript">\nvar guestNetworkBandwidthInf = '
|
|
39
|
+
+ "new Array(\n"
|
|
40
|
+
+ '0,\n1000000,\n1000000,\n1024,\n1024,\n1,\n0,0);\n</SCRIPT>\n<SCRIPT language="javascript" '
|
|
41
|
+
+ 'type="text/javascript">'
|
|
42
|
+
+ '\nvar guestNetAccTime2gInf = new Array(\n1,\n1,\n0,\n0,\n0,\n1,\n0,\n0,\n0,\n0,\n0,\n0,\n0,\n1,\n"",\n"",\n'
|
|
43
|
+
+ "0,0 );"
|
|
44
|
+
+ '\n</SCRIPT>\n<SCRIPT language="javascript" type="text/javascript">\nvar guestNetAccTime5gInf = new Array(\n'
|
|
45
|
+
+ '1,\n0,\n0,\n0,\n0,\n1,\n0,\n0,\n0,\n0,\n0,\n0,\n0,\n1,\n"",\n"",\n0,0 );\n</SCRIPT>\n'
|
|
46
|
+
+ '<SCRIPT language="javascript" type="text/javascript">\nvar guestNetworkInf = '
|
|
47
|
+
+ 'new Array(\n1, 1, 1, 0, "Pegasus", '
|
|
48
|
+
+ '"Pegasus", 1, 1, 3, 3, "333", "333", 0, 0, "p4ssw0rd", "p4ssw0rd", '
|
|
49
|
+
+ "0, 0, 0, 0, 3, 3, 1, 1, 5, 8, 0, \n0,0 );\n"
|
|
50
|
+
+ "</SCRIPT>"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
_DHCPCFG = (
|
|
54
|
+
'<SCRIPT language="javascript" type="text/javascript">\nvar DHCPPara = new Array(\n1,\n"192.168.1.129",\n'
|
|
55
|
+
+ '"192.168.1.192",\n120,\n"192.168.1.254",\n"internal.lan",\n"8.8.8.8",\n"8.8.4.4",\n0,\n0,0 );\n</SCRIPT>'
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
_DHCPLEASES = (
|
|
59
|
+
'<SCRIPT language="javascript" type="text/javascript">var DHCPDynList = new Array(\n"aliquam",'
|
|
60
|
+
+ '"A9-A8-2B-F7-9F-5D","192.168.1.123","Permanent",\n"pharetra","B3-A5-1E-C3-92-A9","192.168.1.163","Permanent",\n'
|
|
61
|
+
+ '"ligula","71-34-47-FD-DE-84","192.168.1.165","Permanent",\n"vulputate","46-5F-5F-27-23-9F","192.168.1.103",'
|
|
62
|
+
+ '"Permanent",\n"amet","86-9F-53-91-04-2B","192.168.1.72","Permanent",\n"volutpat","FA-5C-6F-87-A3-5A",'
|
|
63
|
+
+ '"192.168.1.43",'
|
|
64
|
+
+ '"Permanent",\n"eget","C4-ED-6C-B6-F6-B9","192.168.1.112","Permanent",\n"ante","FF-C1-A3-93-C8-E6",'
|
|
65
|
+
+ '"192.168.1.38",'
|
|
66
|
+
+ '"Permanent",\n"pellentesque","E3-5E-59-2E-CF-AD","192.168.1.148","Permanent",\n"metus","AE-15-51-37-0E-9E",'
|
|
67
|
+
+ '"192.168.1.178","Permanent",\n0,0 );\n</SCRIPT>\n<SCRIPT language="javascript" type="text/javascript">\n'
|
|
68
|
+
+ "var DHCPDynPara = new Array(\n10,\n4,\n0,0 );\n</SCRIPT>"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
_DHCPRESERVES = (
|
|
72
|
+
'<SCRIPT language="javascript" type="text/javascript">\nvar dhcpList = new Array(\n"9B-FA-04-D8-AB-8D",'
|
|
73
|
+
+ '"192.168.1.56",1,\n"EE-7C-6B-B6-05-2F","192.168.1.51",1,\n"09-51-B3-0B-92-01","192.168.1.21",1,\n'
|
|
74
|
+
+ '"49-6F-72-CD-68-5D","192.168.1.25",1,\n"DF-24-38-C1-FE-BB","192.168.1.51",1,\n"1A-08-6C-52-31-3D",'
|
|
75
|
+
+ '"192.168.1.22",1,\n"DE-E4-DF-9A-AD-0D","192.168.1.17",1,\n"DF-F2-CB-FE-46-15","192.168.1.26",1,\n'
|
|
76
|
+
+ '0,0 )\n</SCRIPT>\n<SCRIPT language="javascript" type="text/javascript">var DHCPStaticPara = '
|
|
77
|
+
+ "new Array(\n1,\n1,\n8,\n1,\n8,\n0,0 );\n</SCRIPT>"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
ABSTRACT_STATUS = (
|
|
81
|
+
'<SCRIPT language="javascript" type="text/javascript">\nvar statusPara = new Array(\n1,\n1,\n1,\n'
|
|
82
|
+
+ '22,\n20000,\n1468171,\n"3.13.34 Build 130909 Rel.53148n ",\n"WDR3600 v1 00000000",\n6732336,\n0, 0);\n'
|
|
83
|
+
+ '</SCRIPT>\n'
|
|
84
|
+
+ '<SCRIPT language="javascript" type="text/javascript">\nvar lanPara = new Array(\n"C4-6E-1F-41-67-C0", '
|
|
85
|
+
+ '"192.168.1.254", "255.255.255.0",\n0, 0);\n</SCRIPT>\n<SCRIPT language="javascript" type="text/javascript">\n'
|
|
86
|
+
+ 'var wlanPara = new Array(\n1,\n"testSSID24",\n15,\n5,\n"C4-6E-1F-41-67-BF",\n"192.168.1.254",\n2,\n8,\n71,\n6,\n'
|
|
87
|
+
+ '6,\n0, 0);\n</SCRIPT>\n<SCRIPT language="javascript" type="text/javascript">\nvar wlan5GPara = new Array(\n1,\n'
|
|
88
|
+
+ '"testSSID",\n15,\n8,\n"C4-6E-1F-41-67-C0",\n"192.168.1.254",\n2,\n8,\n83,\n36,\n6,\n0, 0);\n</SCRIPT>\n'
|
|
89
|
+
+ '<SCRIPT language="javascript" type="text/javascript">\nvar statistList = '
|
|
90
|
+
+ "new Array(\n1129349328, 3900411475, 200068023, 165562287,\n0, 0);\n</SCRIPT>\n"
|
|
91
|
+
+ '<SCRIPT language="javascript" type="text/javascript">\nvar wanPara = new Array(\n4, '
|
|
92
|
+
+ '"C4-6E-1F-41-67-C1", "192.168.0.129", 1, "255.255.255.0", 0, 0, "192.168.0.1", 1, 1, 0, '
|
|
93
|
+
+ '"8.8.8.8 , 8.8.4.4", "", 0, 0, "0.0.0.0", "0.0.0.0", "0.0.0.0", "0.0.0.0 , 0.0.0.0", '
|
|
94
|
+
+ "0, 0, 0, 0, 0,\n0, 0);\n</SCRIPT>"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
ABSTRACT_NETWORK = {
|
|
98
|
+
"netWan": _NETWAN,
|
|
99
|
+
"netLan": _NETLAN,
|
|
100
|
+
"w24stations": _W24STA,
|
|
101
|
+
"w50stations": _W50STA,
|
|
102
|
+
"wgsettings": _WLANGUEST,
|
|
103
|
+
"dhcpconfig": _DHCPCFG,
|
|
104
|
+
"dhcplease": _DHCPLEASES,
|
|
105
|
+
"dhcpreserve": _DHCPRESERVES,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class ResponseMock:
|
|
110
|
+
def __init__(self, text: str, status_code=0):
|
|
111
|
+
self.content = text.encode("utf8")
|
|
112
|
+
self.status_code = status_code
|
|
113
|
+
self.headers: dict = {}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class TplinkWDRRouterTest(TplinkWDRRouter):
|
|
117
|
+
response = ""
|
|
118
|
+
|
|
119
|
+
def request(
|
|
120
|
+
self,
|
|
121
|
+
section: str,
|
|
122
|
+
data: str,
|
|
123
|
+
ignore_response: bool = False,
|
|
124
|
+
ignore_errors: bool = False,
|
|
125
|
+
) -> str | dict | None:
|
|
126
|
+
# only a test, so no extra headers
|
|
127
|
+
# Responses
|
|
128
|
+
sections = "summary,status,"
|
|
129
|
+
sections += "netWan,netLan,dualBand,"
|
|
130
|
+
sections += "w24settings,w24wps,w24sec,w24adv,w24stations,"
|
|
131
|
+
sections += "w50settings,w50wps,w50sec,w50adv,w50stations,"
|
|
132
|
+
sections += "wgsettings,wgshare,dhcpconfig,dhcplease,dhcpreserve,"
|
|
133
|
+
sections += "portFwd,sysroute,upnpFwd"
|
|
134
|
+
|
|
135
|
+
section_list = sections.split(",")
|
|
136
|
+
|
|
137
|
+
if ignore_response:
|
|
138
|
+
return None
|
|
139
|
+
elif section == "check":
|
|
140
|
+
resp = ResponseMock("", 200)
|
|
141
|
+
resp.headers["www-authenticate"] = (
|
|
142
|
+
'Basic realm="TP-LINK Wireless Dual Band Gigabit Router WDR3600"'
|
|
143
|
+
)
|
|
144
|
+
return resp
|
|
145
|
+
elif section in section_list:
|
|
146
|
+
if section in ["summary", "status"]:
|
|
147
|
+
return ResponseMock(ABSTRACT_STATUS).content
|
|
148
|
+
elif section in ["w24stations", "w50stations", "dhcpreserve"]:
|
|
149
|
+
return ResponseMock(ABSTRACT_NETWORK[section]).content
|
|
150
|
+
elif section in [
|
|
151
|
+
"netLan",
|
|
152
|
+
"netWan",
|
|
153
|
+
# 'w24stations',
|
|
154
|
+
# 'w50stations',
|
|
155
|
+
"wgsettings",
|
|
156
|
+
"dhcpconfig",
|
|
157
|
+
"dhcplease",
|
|
158
|
+
# 'dhcpreserve',
|
|
159
|
+
]:
|
|
160
|
+
return ResponseMock(ABSTRACT_NETWORK[section]).content
|
|
161
|
+
else:
|
|
162
|
+
return ""
|
|
163
|
+
# raise ClientError (f'Section {section} not allowed')
|
|
164
|
+
|
|
165
|
+
else:
|
|
166
|
+
error = ""
|
|
167
|
+
error = (
|
|
168
|
+
(
|
|
169
|
+
"WDRRouter - {} - Response with error; Request {} - Response {}".format(
|
|
170
|
+
self.__class__.__name__, section, data
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
if not error
|
|
174
|
+
else error
|
|
175
|
+
)
|
|
176
|
+
if self._logger:
|
|
177
|
+
self._logger.debug(error)
|
|
178
|
+
|
|
179
|
+
raise ClientError(error)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class TestTPLinkWDRClient(TestCase):
|
|
183
|
+
|
|
184
|
+
def test_supports(self) -> None:
|
|
185
|
+
client = TplinkWDRRouterTest("", "")
|
|
186
|
+
# client.response = ResponseMock(ABSTRACT_STATUS)
|
|
187
|
+
supports = client.supports()
|
|
188
|
+
self.assertTrue(supports)
|
|
189
|
+
|
|
190
|
+
def test_get_firmware(self) -> None:
|
|
191
|
+
|
|
192
|
+
client = TplinkWDRRouterTest("", "")
|
|
193
|
+
client.response = ResponseMock(ABSTRACT_STATUS)
|
|
194
|
+
firmware = client.get_firmware()
|
|
195
|
+
|
|
196
|
+
self.assertIsInstance(firmware, Firmware)
|
|
197
|
+
self.assertEqual(firmware.hardware_version, "WDR3600 v1 00000000")
|
|
198
|
+
self.assertEqual(firmware.model, "WDR3600")
|
|
199
|
+
self.assertEqual(
|
|
200
|
+
firmware.firmware_version.strip(), "3.13.34 Build 130909 Rel.53148n"
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
def test_get_ipv4(self) -> None:
|
|
204
|
+
|
|
205
|
+
client = TplinkWDRRouterTest("", "")
|
|
206
|
+
ipv4status: IPv4Status = IPv4Status()
|
|
207
|
+
ipv4status = client.get_ipv4_status()
|
|
208
|
+
|
|
209
|
+
self.assertIsInstance(ipv4status, IPv4Status)
|
|
210
|
+
self.assertEqual(ipv4status._wan_macaddr, EUI48("C4-6E-1F-41-67-C1"))
|
|
211
|
+
self.assertEqual(
|
|
212
|
+
IPv4Address(ipv4status.wan_ipv4_ipaddr), IPv4Address("192.168.0.129")
|
|
213
|
+
)
|
|
214
|
+
self.assertEqual(
|
|
215
|
+
IPv4Address(ipv4status.wan_ipv4_gateway), IPv4Address("192.168.0.1")
|
|
216
|
+
)
|
|
217
|
+
self.assertEqual(ipv4status.wan_ipv4_conntype, "Dynamic IP")
|
|
218
|
+
self.assertEqual(
|
|
219
|
+
IPv4Address(ipv4status.wan_ipv4_netmask), IPv4Address("255.255.255.0")
|
|
220
|
+
)
|
|
221
|
+
self.assertEqual(
|
|
222
|
+
IPv4Address(ipv4status.wan_ipv4_pridns), IPv4Address("0.0.0.0")
|
|
223
|
+
)
|
|
224
|
+
self.assertEqual(
|
|
225
|
+
IPv4Address(ipv4status.wan_ipv4_snddns), IPv4Address("0.0.0.0")
|
|
226
|
+
)
|
|
227
|
+
self.assertEqual(ipv4status._lan_macaddr, EUI48("C4-6E-1F-41-67-C0"))
|
|
228
|
+
self.assertEqual(
|
|
229
|
+
IPv4Address(ipv4status.lan_ipv4_ipaddr), IPv4Address("192.168.1.254")
|
|
230
|
+
)
|
|
231
|
+
self.assertEqual(ipv4status.lan_ipv4_dhcp_enable, True)
|
|
232
|
+
self.assertEqual(
|
|
233
|
+
IPv4Address(ipv4status.lan_ipv4_netmask), IPv4Address("255.255.255.0")
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
def test_get_ipv4_reservations(self) -> None:
|
|
237
|
+
client = TplinkWDRRouterTest("", "")
|
|
238
|
+
ipv4_reservations: list[IPv4Reservation] = client.get_ipv4_reservations()
|
|
239
|
+
fRes: IPv4Reservation = ipv4_reservations[0]
|
|
240
|
+
|
|
241
|
+
self.assertIsInstance(fRes, IPv4Reservation)
|
|
242
|
+
self.assertEqual(EUI48(fRes.macaddress), EUI48("9B-FA-04-D8-AB-8D"))
|
|
243
|
+
self.assertEqual(IPv4Address(fRes.ipaddress), IPv4Address("192.168.1.56"))
|
|
244
|
+
self.assertEqual(fRes.enabled, True)
|
|
245
|
+
|
|
246
|
+
def test_get_ipv4_dhcp_leases(self) -> None:
|
|
247
|
+
client = TplinkWDRRouterTest("", "")
|
|
248
|
+
dhcp_leases: list[IPv4DHCPLease] = client.get_ipv4_dhcp_leases()
|
|
249
|
+
|
|
250
|
+
self.assertIsInstance(dhcp_leases[0], IPv4DHCPLease)
|
|
251
|
+
self.assertEqual(dhcp_leases[0].macaddress, EUI48("A9-A8-2B-F7-9F-5D"))
|
|
252
|
+
self.assertEqual(dhcp_leases[0].ipaddress, IPv4Address("192.168.1.123"))
|
|
253
|
+
self.assertEqual(dhcp_leases[0].hostname, "aliquam")
|
|
254
|
+
self.assertEqual(dhcp_leases[0].lease_time, "Permanent")
|
|
255
|
+
|
|
256
|
+
self.assertIsInstance(dhcp_leases[1], IPv4DHCPLease)
|
|
257
|
+
self.assertEqual(dhcp_leases[1].macaddress, EUI48("B3-A5-1E-C3-92-A9"))
|
|
258
|
+
self.assertEqual(dhcp_leases[1].ipaddress, IPv4Address("192.168.1.163"))
|
|
259
|
+
self.assertEqual(dhcp_leases[1].hostname, "pharetra")
|
|
260
|
+
self.assertEqual(dhcp_leases[1].lease_time, "Permanent")
|
|
261
|
+
|
|
262
|
+
def test_get_status(self) -> None:
|
|
263
|
+
client = TplinkWDRRouterTest("", "")
|
|
264
|
+
client.response = ResponseMock(ABSTRACT_STATUS)
|
|
265
|
+
|
|
266
|
+
status = client.get_status()
|
|
267
|
+
|
|
268
|
+
self.assertIsInstance(status, Status)
|
|
269
|
+
self.assertEqual(status.wan_macaddr, "C4-6E-1F-41-67-C1")
|
|
270
|
+
self.assertIsInstance(status.wan_macaddress, EUI48)
|
|
271
|
+
self.assertEqual(status.lan_macaddr, "C4-6E-1F-41-67-C0")
|
|
272
|
+
self.assertIsInstance(status.lan_macaddress, EUI48)
|
|
273
|
+
self.assertEqual(status.wan_ipv4_addr, "192.168.0.129")
|
|
274
|
+
self.assertIsInstance(status.lan_ipv4_address, IPv4Address)
|
|
275
|
+
self.assertEqual(status.lan_ipv4_addr, "192.168.1.254")
|
|
276
|
+
self.assertEqual(status.wan_ipv4_gateway, "192.168.0.1")
|
|
277
|
+
self.assertIsInstance(status.wan_ipv4_address, IPv4Address)
|
|
278
|
+
|
|
279
|
+
self.assertEqual(status.wired_total, 10)
|
|
280
|
+
self.assertEqual(status.wifi_clients_total, 8)
|
|
281
|
+
self.assertEqual(status.guest_clients_total, 0)
|
|
282
|
+
self.assertEqual(status.clients_total, 18)
|
|
283
|
+
|
|
284
|
+
self.assertTrue(status.guest_2g_enable)
|
|
285
|
+
self.assertFalse(status.guest_5g_enable)
|
|
286
|
+
self.assertTrue(status.wifi_2g_enable)
|
|
287
|
+
self.assertTrue(status.wifi_5g_enable)
|
|
288
|
+
self.assertEqual(status.wan_ipv4_uptime, 6732336)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
if __name__ == "__main__":
|
|
292
|
+
main()
|
tplinkrouterc6u/__init__.py
CHANGED
|
@@ -8,6 +8,7 @@ from tplinkrouterc6u.client.c80 import TplinkC80Router
|
|
|
8
8
|
from tplinkrouterc6u.client.c5400x import TplinkC5400XRouter
|
|
9
9
|
from tplinkrouterc6u.client.c1200 import TplinkC1200Router
|
|
10
10
|
from tplinkrouterc6u.client.xdr import TPLinkXDRClient
|
|
11
|
+
from tplinkrouterc6u.client.wdr import TplinkWDRRouter
|
|
11
12
|
from tplinkrouterc6u.provider import TplinkRouterProvider
|
|
12
13
|
from tplinkrouterc6u.common.package_enum import Connection, VPN
|
|
13
14
|
from tplinkrouterc6u.common.dataclass import (
|
tplinkrouterc6u/client/c1200.py
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
from re import search
|
|
2
2
|
from requests import post, Response
|
|
3
|
-
from urllib.parse import urlencode
|
|
4
3
|
from tplinkrouterc6u.common.encryption import EncryptionWrapper
|
|
5
4
|
from tplinkrouterc6u.common.exception import ClientException, AuthorizeError
|
|
6
5
|
from tplinkrouterc6u.client.c5400x import TplinkC5400XRouter
|
|
7
|
-
from tplinkrouterc6u.common.dataclass import VPNStatus
|
|
8
|
-
from tplinkrouterc6u.common.package_enum import VPN
|
|
9
6
|
|
|
10
7
|
|
|
11
8
|
class TplinkC1200Router(TplinkC5400XRouter):
|
|
@@ -103,36 +100,3 @@ class TplinkC1200Router(TplinkC5400XRouter):
|
|
|
103
100
|
@staticmethod
|
|
104
101
|
def _get_login_data(crypted_pwd: str) -> str:
|
|
105
102
|
return 'operation=login&password={}'.format(crypted_pwd)
|
|
106
|
-
|
|
107
|
-
def get_vpn_status(self) -> VPNStatus:
|
|
108
|
-
status = VPNStatus()
|
|
109
|
-
|
|
110
|
-
values = [
|
|
111
|
-
self.request("/admin/openvpn?form=config&operation=read", "operation=read"),
|
|
112
|
-
self.request("/admin/pptpd?form=config&operation=read", "operation=read"),
|
|
113
|
-
self.request("/admin/vpnconn?form=config&operation=list&vpntype=openvpn",
|
|
114
|
-
"operation=list&operation=list&vpntype=openvpn"),
|
|
115
|
-
self.request("/admin/vpnconn?form=config&operation=list&vpntype=pptp",
|
|
116
|
-
"operation=list&operation=list&vpntype=pptp"),
|
|
117
|
-
]
|
|
118
|
-
|
|
119
|
-
status.openvpn_enable = values[0]['enabled'] == 'on'
|
|
120
|
-
status.pptpvpn_enable = values[1]['enabled'] == 'on'
|
|
121
|
-
|
|
122
|
-
if isinstance(values[2], list):
|
|
123
|
-
status.openvpn_clients_total = len(values[2])
|
|
124
|
-
status.pptpvpn_clients_total = len(values[3])
|
|
125
|
-
else:
|
|
126
|
-
status.openvpn_clients_total = 0
|
|
127
|
-
status.pptpvpn_clients_total = 0
|
|
128
|
-
|
|
129
|
-
return status
|
|
130
|
-
|
|
131
|
-
def set_vpn(self, vpn: VPN, enable: bool) -> None:
|
|
132
|
-
path = "/admin/{}?form=config&operation=read".format(vpn.lowercase)
|
|
133
|
-
current_config = self.request(path, "operation=read")
|
|
134
|
-
current_config['enabled'] = "on" if enable else "off"
|
|
135
|
-
data = urlencode(current_config)
|
|
136
|
-
data = "&operation=write&{}".format(data)
|
|
137
|
-
path = "/admin/{}?form=config{}".format(vpn.lowercase, data)
|
|
138
|
-
self.request(path, data)
|
tplinkrouterc6u/client/c6u.py
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
from hashlib import md5
|
|
2
2
|
from re import search
|
|
3
3
|
from json import loads
|
|
4
|
+
from urllib.parse import urlencode
|
|
4
5
|
from requests import post, Response
|
|
5
6
|
from macaddress import EUI48
|
|
6
7
|
from ipaddress import IPv4Address
|
|
7
8
|
from logging import Logger
|
|
8
9
|
from tplinkrouterc6u.common.helper import get_ip, get_mac
|
|
9
10
|
from tplinkrouterc6u.common.encryption import EncryptionWrapper
|
|
10
|
-
from tplinkrouterc6u.common.package_enum import Connection
|
|
11
|
-
from tplinkrouterc6u.common.dataclass import
|
|
11
|
+
from tplinkrouterc6u.common.package_enum import Connection, VPN
|
|
12
|
+
from tplinkrouterc6u.common.dataclass import (
|
|
13
|
+
Firmware,
|
|
14
|
+
Status,
|
|
15
|
+
Device,
|
|
16
|
+
IPv4Reservation,
|
|
17
|
+
IPv4DHCPLease,
|
|
18
|
+
IPv4Status,
|
|
19
|
+
VPNStatus,
|
|
20
|
+
)
|
|
12
21
|
from tplinkrouterc6u.common.exception import ClientException, ClientError
|
|
13
22
|
from tplinkrouterc6u.client_abstract import AbstractRouter
|
|
14
23
|
from abc import abstractmethod
|
|
@@ -231,6 +240,10 @@ class TplinkBaseRouter(AbstractRouter, TplinkRequest):
|
|
|
231
240
|
self._url_firmware = 'admin/firmware?form=upgrade&operation=read'
|
|
232
241
|
self._url_ipv4_reservations = 'admin/dhcps?form=reservation&operation=load'
|
|
233
242
|
self._url_ipv4_dhcp_leases = 'admin/dhcps?form=client&operation=load'
|
|
243
|
+
self._url_openvpn = 'admin/openvpn?form=config&operation=read'
|
|
244
|
+
self._url_pptpd = 'admin/pptpd?form=config&operation=read'
|
|
245
|
+
self._url_vpnconn_openvpn = 'admin/vpnconn?form=config&operation=list&vpntype=openvpn'
|
|
246
|
+
self._url_vpnconn_pptpd = 'admin/vpnconn?form=config&operation=list&vpntype=pptp'
|
|
234
247
|
referer = '{}/webpages/index.html'.format(self.host)
|
|
235
248
|
self._headers_request = {'Referer': referer}
|
|
236
249
|
self._headers_login = {'Referer': referer, 'Content-Type': 'application/x-www-form-urlencoded'}
|
|
@@ -275,7 +288,7 @@ class TplinkBaseRouter(AbstractRouter, TplinkRequest):
|
|
|
275
288
|
data = self.request('admin/status?form=all&operation=read', 'operation=read')
|
|
276
289
|
|
|
277
290
|
status = Status()
|
|
278
|
-
status._wan_macaddr = EUI48(data['wan_macaddr']) if 'wan_macaddr' in data else None
|
|
291
|
+
status._wan_macaddr = EUI48(data['wan_macaddr']) if 'wan_macaddr' in data and data['wan_macaddr'] else None
|
|
279
292
|
status._lan_macaddr = EUI48(data['lan_macaddr'])
|
|
280
293
|
status._wan_ipv4_addr = IPv4Address(data['wan_ipv4_ipaddr']) if 'wan_ipv4_ipaddr' in data else None
|
|
281
294
|
status._lan_ipv4_addr = IPv4Address(data['lan_ipv4_ipaddr']) if 'lan_ipv4_ipaddr' in data else None
|
|
@@ -401,6 +414,36 @@ class TplinkBaseRouter(AbstractRouter, TplinkRequest):
|
|
|
401
414
|
|
|
402
415
|
return dhcp_leases
|
|
403
416
|
|
|
417
|
+
def get_vpn_status(self) -> VPNStatus:
|
|
418
|
+
status = VPNStatus()
|
|
419
|
+
|
|
420
|
+
values = [
|
|
421
|
+
self.request(self._url_openvpn, "operation=read"),
|
|
422
|
+
self.request(self._url_pptpd, "operation=read"),
|
|
423
|
+
self.request(self._url_vpnconn_openvpn, "operation=list&vpntype=openvpn"),
|
|
424
|
+
self.request(self._url_vpnconn_pptpd, "operation=list&vpntype=pptp"),
|
|
425
|
+
]
|
|
426
|
+
|
|
427
|
+
status.openvpn_enable = values[0]['enabled'] == 'on'
|
|
428
|
+
status.pptpvpn_enable = values[1]['enabled'] == 'on'
|
|
429
|
+
|
|
430
|
+
if isinstance(values[2], list):
|
|
431
|
+
status.openvpn_clients_total = len(values[2])
|
|
432
|
+
status.pptpvpn_clients_total = len(values[3])
|
|
433
|
+
else:
|
|
434
|
+
status.openvpn_clients_total = 0
|
|
435
|
+
status.pptpvpn_clients_total = 0
|
|
436
|
+
|
|
437
|
+
return status
|
|
438
|
+
|
|
439
|
+
def set_vpn(self, vpn: VPN, enable: bool) -> None:
|
|
440
|
+
path = self._url_openvpn if VPN.OPEN_VPN == vpn else self._url_pptpd
|
|
441
|
+
current_config = self.request(path, "operation=read")
|
|
442
|
+
current_config['enabled'] = "on" if enable else "off"
|
|
443
|
+
data = urlencode(current_config)
|
|
444
|
+
data = "operation=write&{}".format(data)
|
|
445
|
+
self.request(path, data)
|
|
446
|
+
|
|
404
447
|
@staticmethod
|
|
405
448
|
def _str2bool(v) -> bool | None:
|
|
406
449
|
return str(v).lower() in ("yes", "true", "on") if v is not None else None
|
|
@@ -435,3 +478,7 @@ class TplinkRouter(TplinkEncryption, TplinkBaseRouter):
|
|
|
435
478
|
self._url_firmware = 'admin/firmware?form=upgrade'
|
|
436
479
|
self._url_ipv4_reservations = 'admin/dhcps?form=reservation'
|
|
437
480
|
self._url_ipv4_dhcp_leases = 'admin/dhcps?form=client'
|
|
481
|
+
self._url_openvpn = 'admin/openvpn?form=config'
|
|
482
|
+
self._url_pptpd = 'admin/pptpd?form=config'
|
|
483
|
+
self._url_vpnconn_openvpn = 'admin/vpnconn?form=config'
|
|
484
|
+
self._url_vpnconn_pptpd = 'admin/vpnconn?form=config'
|