1 /*
2  * Copyright (c)2019 ZeroTier, Inc.
3  *
4  * Use of this software is governed by the Business Source License included
5  * in the LICENSE.TXT file in the project's root directory.
6  *
7  * Change Date: 2025-01-01
8  *
9  * On the date above, in accordance with the Business Source License, use
10  * of this software will be governed by version 2.0 of the Apache License.
11  */
12 /****/
13 
14 #ifndef ZT_WINDOWSETHERNETTAP_HPP
15 #define ZT_WINDOWSETHERNETTAP_HPP
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 
20 #include <ifdef.h>
21 
22 #include <string>
23 #include <queue>
24 #include <stdexcept>
25 
26 #include "../node/Constants.hpp"
27 #include "../node/Mutex.hpp"
28 #include "../node/MulticastGroup.hpp"
29 #include "../node/InetAddress.hpp"
30 #include "../osdep/Thread.hpp"
31 #include "EthernetTap.hpp"
32 
33 namespace ZeroTier {
34 
35 class WindowsEthernetTap : public EthernetTap
36 {
37 public:
38 	/**
39 	 * Installs a new instance of the ZT tap driver
40 	 *
41 	 * @param pathToInf Path to zttap driver .inf file
42 	 * @param deviceInstanceId Buffer to fill with device instance ID on success (and if SetupDiGetDeviceInstanceIdA succeeds, which it should)
43 	 * @return Empty string on success, otherwise an error message
44 	 */
45 	static std::string addNewPersistentTapDevice(const char *pathToInf,std::string &deviceInstanceId);
46 
47 	/**
48 	 * Uninstalls all persistent tap devices that have legacy drivers
49 	 *
50 	 * @return Empty string on success, otherwise an error message
51 	 */
52 	static std::string destroyAllLegacyPersistentTapDevices();
53 
54 	/**
55 	 * Uninstalls all persistent tap devices on the system
56 	 *
57 	 * @return Empty string on success, otherwise an error message
58 	 */
59 	static std::string destroyAllPersistentTapDevices();
60 
61 	/**
62 	 * Uninstalls a specific persistent tap device by instance ID
63 	 *
64 	 * @param instanceId Device instance ID
65 	 * @return Empty string on success, otherwise an error message
66 	 */
67 	static std::string deletePersistentTapDevice(const char *instanceId);
68 
69 	/**
70 	 * Disable a persistent tap device by instance ID
71 	 *
72 	 * @param instanceId Device instance ID
73 	 * @param enabled Enable device?
74 	 * @return True if device was found and disabled
75 	 */
76 	static bool setPersistentTapDeviceState(const char *instanceId,bool enabled);
77 
78 	WindowsEthernetTap(
79 		const char *hp,
80 		const MAC &mac,
81 		unsigned int mtu,
82 		unsigned int metric,
83 		uint64_t nwid,
84 		const char *friendlyName,
85 		void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
86 		void *arg);
87 
88 	virtual ~WindowsEthernetTap();
89 
90 	virtual void setEnabled(bool en);
91 	virtual bool enabled() const;
92 	virtual bool addIp(const InetAddress &ip);
93 	virtual bool removeIp(const InetAddress &ip);
94 	virtual std::vector<InetAddress> ips() const;
95 	virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
96 	virtual std::string deviceName() const;
97 	virtual void setFriendlyName(const char *friendlyName);
98 	virtual std::string friendlyName() const;
99 	virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
100 	virtual void setMtu(unsigned int mtu);
101 	virtual void setDns(const char* domain, const std::vector<InetAddress> &servers);
102 
luid() const103 	inline const NET_LUID &luid() const { return _deviceLuid; }
guid() const104 	inline const GUID &guid() const { return _deviceGuid; }
instanceId() const105 	inline const std::string &instanceId() const { return _deviceInstanceId; }
106 	NET_IFINDEX interfaceIndex() const;
107 
108 	void threadMain()
109 		throw();
110 
isInitialized() const111 	bool isInitialized() const { return _initialized; };
112 
113 private:
114 	NET_IFINDEX _getDeviceIndex(); // throws on failure
115 	std::vector<std::string> _getRegistryIPv4Value(const char *regKey);
116 	void _setRegistryIPv4Value(const char *regKey,const std::vector<std::string> &value);
117 	void _syncIps();
118 
119 	void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
120 	void *_arg;
121 	MAC _mac;
122 	uint64_t _nwid;
123 	volatile unsigned int _mtu;
124 	Thread _thread;
125 
126 	volatile HANDLE _tap;
127 	HANDLE _injectSemaphore;
128 
129 	GUID _deviceGuid;
130 	NET_LUID _deviceLuid;
131 	std::string _netCfgInstanceId;
132 	std::string _deviceInstanceId;
133 	std::string _mySubkeyName;
134 	std::string _friendlyName;
135 	Mutex _friendlyName_m;
136 
137 	std::vector<InetAddress> _assignedIps; // IPs assigned with addIp
138 	Mutex _assignedIps_m;
139 
140 	std::vector<MulticastGroup> _multicastGroups;
141 
142 	struct _InjectPending
143 	{
144 		unsigned int len;
145 		char data[ZT_MAX_MTU + 32];
146 	};
147 	std::queue<_InjectPending> _injectPending;
148 	Mutex _injectPending_m;
149 
150 	std::string _pathToHelpers;
151 
152 	volatile bool _run;
153 	volatile bool _initialized;
154 	volatile bool _enabled;
155 };
156 
157 } // namespace ZeroTier
158 
159 #endif
160