BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file tapwin32-funcs.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #include <stddef.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <string.h>
34  
35 #include <misc/debug.h>
36 #include <misc/ipaddr.h>
37 #include <misc/maxalign.h>
38 #include <misc/strdup.h>
39  
40 #include "wintap-common.h"
41  
42 #include <tuntap/tapwin32-funcs.h>
43  
44 static int split_spec (char *name, char *sep, char **out_fields[], int num_fields)
45 {
46 ASSERT(num_fields > 0)
47 ASSERT(strlen(sep) > 0)
48  
49 size_t seplen = strlen(sep);
50  
51 int i = 0;
52 while (i < num_fields - 1) {
53 char *s = strstr(name, sep);
54 if (!s) {
55 DEBUG("missing separator number %d", (i + 1));
56 goto fail;
57 }
58  
59 if (!(*out_fields[i] = b_strdup_bin(name, s - name))) {
60 DEBUG("b_strdup_bin failed");
61 goto fail;
62 }
63  
64 name = s + seplen;
65 i++;
66 }
67  
68 if (!(*out_fields[i] = b_strdup(name))) {
69 DEBUG("b_strdup_bin failed");
70 goto fail;
71 }
72  
73 return 1;
74  
75 fail:
76 while (i-- > 0) {
77 free(*out_fields[i]);
78 }
79 return 0;
80 }
81  
82 int tapwin32_parse_tap_spec (char *name, char **out_component_id, char **out_human_name)
83 {
84 char **out_fields[2];
85 out_fields[0] = out_component_id;
86 out_fields[1] = out_human_name;
87  
88 return split_spec(name, ":", out_fields, 2);
89 }
90  
91 int tapwin32_parse_tun_spec (char *name, char **out_component_id, char **out_human_name, uint32_t out_addrs[3])
92 {
93 char *addr_strs[3];
94  
95 char **out_fields[5];
96 out_fields[0] = out_component_id;
97 out_fields[1] = out_human_name;
98 out_fields[2] = &addr_strs[0];
99 out_fields[3] = &addr_strs[1];
100 out_fields[4] = &addr_strs[2];
101  
102 if (!split_spec(name, ":", out_fields, 5)) {
103 goto fail0;
104 }
105  
106 for (int i = 0; i < 3; i++) {
107 if (!ipaddr_parse_ipv4_addr(MemRef_MakeCstr(addr_strs[i]), &out_addrs[i])) {
108 goto fail1;
109 }
110 }
111  
112 free(addr_strs[0]);
113 free(addr_strs[1]);
114 free(addr_strs[2]);
115  
116 return 1;
117  
118 fail1:
119 free(*out_component_id);
120 free(*out_human_name);
121 free(addr_strs[0]);
122 free(addr_strs[1]);
123 free(addr_strs[2]);
124 fail0:
125 return 0;
126 }
127  
128 int tapwin32_find_device (char *device_component_id, char *device_name, char (*device_path)[TAPWIN32_MAX_REG_SIZE])
129 {
130 // open adapter key
131 // used to find all devices with the given ComponentId
132 HKEY adapter_key;
133 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADAPTER_KEY, 0, KEY_READ, &adapter_key) != ERROR_SUCCESS) {
134 DEBUG("Error opening adapter key");
135 return 0;
136 }
137  
138 char net_cfg_instance_id[TAPWIN32_MAX_REG_SIZE];
139 int found = 0;
140 int pres;
141  
142 DWORD i;
143 for (i = 0;; i++) {
144 DWORD len;
145 DWORD type;
146  
147 char key_name[TAPWIN32_MAX_REG_SIZE];
148 len = sizeof(key_name);
149 if (RegEnumKeyEx(adapter_key, i, key_name, &len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
150 break;
151 }
152  
153 char unit_string[TAPWIN32_MAX_REG_SIZE];
154 pres = _snprintf(unit_string, sizeof(unit_string), "%s\\%s", ADAPTER_KEY, key_name);
155 if (pres < 0 || pres == sizeof(unit_string)) {
156 continue;
157 }
158 HKEY unit_key;
159 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit_string, 0, KEY_READ, &unit_key) != ERROR_SUCCESS) {
160 continue;
161 }
162  
163 char component_id[TAPWIN32_MAX_REG_SIZE];
164 len = sizeof(component_id);
165 if (RegQueryValueEx(unit_key, "ComponentId", NULL, &type, (LPBYTE)component_id, &len) != ERROR_SUCCESS || type != REG_SZ) {
166 ASSERT_FORCE(RegCloseKey(unit_key) == ERROR_SUCCESS)
167 continue;
168 }
169  
170 len = sizeof(net_cfg_instance_id);
171 if (RegQueryValueEx(unit_key, "NetCfgInstanceId", NULL, &type, (LPBYTE)net_cfg_instance_id, &len) != ERROR_SUCCESS || type != REG_SZ) {
172 ASSERT_FORCE(RegCloseKey(unit_key) == ERROR_SUCCESS)
173 continue;
174 }
175  
176 RegCloseKey(unit_key);
177  
178 // check if ComponentId matches
179 if (!strcmp(component_id, device_component_id)) {
180 // if no name was given, use the first device with the given ComponentId
181 if (!device_name) {
182 found = 1;
183 break;
184 }
185  
186 // open connection key
187 char conn_string[TAPWIN32_MAX_REG_SIZE];
188 pres = _snprintf(conn_string, sizeof(conn_string), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, net_cfg_instance_id);
189 if (pres < 0 || pres == sizeof(conn_string)) {
190 continue;
191 }
192 HKEY conn_key;
193 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, conn_string, 0, KEY_READ, &conn_key) != ERROR_SUCCESS) {
194 continue;
195 }
196  
197 // read name
198 char name[TAPWIN32_MAX_REG_SIZE];
199 len = sizeof(name);
200 if (RegQueryValueEx(conn_key, "Name", NULL, &type, (LPBYTE)name, &len) != ERROR_SUCCESS || type != REG_SZ) {
201 ASSERT_FORCE(RegCloseKey(conn_key) == ERROR_SUCCESS)
202 continue;
203 }
204  
205 ASSERT_FORCE(RegCloseKey(conn_key) == ERROR_SUCCESS)
206  
207 // check name
208 if (!strcmp(name, device_name)) {
209 found = 1;
210 break;
211 }
212 }
213 }
214  
215 ASSERT_FORCE(RegCloseKey(adapter_key) == ERROR_SUCCESS)
216  
217 if (!found) {
218 return 0;
219 }
220  
221 pres = _snprintf(*device_path, sizeof(*device_path), "\\\\.\\Global\\%s.tap", net_cfg_instance_id);
222 if (pres < 0 || pres == sizeof(*device_path)) {
223 return 0;
224 }
225  
226 return 1;
227 }