tapwin32-funcs.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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. #include <stddef.h>
  30. #include <stdint.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <misc/debug.h>
  34. #include <misc/ipaddr.h>
  35. #include <misc/maxalign.h>
  36. #include <misc/strdup.h>
  37. #include "wintap-common.h"
  38. #include <tuntap/tapwin32-funcs.h>
  39. static int split_spec (char *name, char *sep, char **out_fields[], int num_fields)
  40. {
  41. ASSERT(num_fields > 0)
  42. ASSERT(strlen(sep) > 0)
  43. size_t seplen = strlen(sep);
  44. int i = 0;
  45. while (i < num_fields - 1) {
  46. char *s = strstr(name, sep);
  47. if (!s) {
  48. DEBUG("missing separator number %d", (i + 1));
  49. goto fail;
  50. }
  51. if (!(*out_fields[i] = b_strdup_bin(name, s - name))) {
  52. DEBUG("b_strdup_bin failed");
  53. goto fail;
  54. }
  55. name = s + seplen;
  56. i++;
  57. }
  58. if (!(*out_fields[i] = b_strdup(name))) {
  59. DEBUG("b_strdup_bin failed");
  60. goto fail;
  61. }
  62. return 1;
  63. fail:
  64. while (i-- > 0) {
  65. free(*out_fields[i]);
  66. }
  67. return 0;
  68. }
  69. int tapwin32_parse_tap_spec (char *name, char **out_component_id, char **out_human_name)
  70. {
  71. char **out_fields[2];
  72. out_fields[0] = out_component_id;
  73. out_fields[1] = out_human_name;
  74. return split_spec(name, ":", out_fields, 2);
  75. }
  76. int tapwin32_parse_tun_spec (char *name, char **out_component_id, char **out_human_name, uint32_t out_addrs[3])
  77. {
  78. char *addr_strs[3];
  79. char **out_fields[5];
  80. out_fields[0] = out_component_id;
  81. out_fields[1] = out_human_name;
  82. out_fields[2] = &addr_strs[0];
  83. out_fields[3] = &addr_strs[1];
  84. out_fields[4] = &addr_strs[2];
  85. if (!split_spec(name, ":", out_fields, 5)) {
  86. goto fail0;
  87. }
  88. for (int i = 0; i < 3; i++) {
  89. if (!ipaddr_parse_ipv4_addr(addr_strs[i], &out_addrs[i])) {
  90. goto fail1;
  91. }
  92. }
  93. free(addr_strs[0]);
  94. free(addr_strs[1]);
  95. free(addr_strs[2]);
  96. return 1;
  97. fail1:
  98. free(*out_component_id);
  99. free(*out_human_name);
  100. free(addr_strs[0]);
  101. free(addr_strs[1]);
  102. free(addr_strs[2]);
  103. fail0:
  104. return 0;
  105. }
  106. int tapwin32_find_device (char *device_component_id, char *device_name, char (*device_path)[TAPWIN32_MAX_REG_SIZE])
  107. {
  108. // open adapter key
  109. // used to find all devices with the given ComponentId
  110. HKEY adapter_key;
  111. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADAPTER_KEY, 0, KEY_READ, &adapter_key) != ERROR_SUCCESS) {
  112. DEBUG("Error opening adapter key");
  113. return 0;
  114. }
  115. char net_cfg_instance_id[TAPWIN32_MAX_REG_SIZE];
  116. int found = 0;
  117. int pres;
  118. DWORD i;
  119. for (i = 0;; i++) {
  120. DWORD len;
  121. DWORD type;
  122. char key_name[TAPWIN32_MAX_REG_SIZE];
  123. len = sizeof(key_name);
  124. if (RegEnumKeyEx(adapter_key, i, key_name, &len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
  125. break;
  126. }
  127. char unit_string[TAPWIN32_MAX_REG_SIZE];
  128. pres = _snprintf(unit_string, sizeof(unit_string), "%s\\%s", ADAPTER_KEY, key_name);
  129. if (pres < 0 || pres == sizeof(unit_string)) {
  130. continue;
  131. }
  132. HKEY unit_key;
  133. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit_string, 0, KEY_READ, &unit_key) != ERROR_SUCCESS) {
  134. continue;
  135. }
  136. char component_id[TAPWIN32_MAX_REG_SIZE];
  137. len = sizeof(component_id);
  138. if (RegQueryValueEx(unit_key, "ComponentId", NULL, &type, (LPBYTE)component_id, &len) != ERROR_SUCCESS || type != REG_SZ) {
  139. ASSERT_FORCE(RegCloseKey(unit_key) == ERROR_SUCCESS)
  140. continue;
  141. }
  142. len = sizeof(net_cfg_instance_id);
  143. if (RegQueryValueEx(unit_key, "NetCfgInstanceId", NULL, &type, (LPBYTE)net_cfg_instance_id, &len) != ERROR_SUCCESS || type != REG_SZ) {
  144. ASSERT_FORCE(RegCloseKey(unit_key) == ERROR_SUCCESS)
  145. continue;
  146. }
  147. RegCloseKey(unit_key);
  148. // check if ComponentId matches
  149. if (!strcmp(component_id, device_component_id)) {
  150. // if no name was given, use the first device with the given ComponentId
  151. if (!device_name) {
  152. found = 1;
  153. break;
  154. }
  155. // open connection key
  156. char conn_string[TAPWIN32_MAX_REG_SIZE];
  157. pres = _snprintf(conn_string, sizeof(conn_string), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, net_cfg_instance_id);
  158. if (pres < 0 || pres == sizeof(conn_string)) {
  159. continue;
  160. }
  161. HKEY conn_key;
  162. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, conn_string, 0, KEY_READ, &conn_key) != ERROR_SUCCESS) {
  163. continue;
  164. }
  165. // read name
  166. char name[TAPWIN32_MAX_REG_SIZE];
  167. len = sizeof(name);
  168. if (RegQueryValueEx(conn_key, "Name", NULL, &type, (LPBYTE)name, &len) != ERROR_SUCCESS || type != REG_SZ) {
  169. ASSERT_FORCE(RegCloseKey(conn_key) == ERROR_SUCCESS)
  170. continue;
  171. }
  172. ASSERT_FORCE(RegCloseKey(conn_key) == ERROR_SUCCESS)
  173. // check name
  174. if (!strcmp(name, device_name)) {
  175. found = 1;
  176. break;
  177. }
  178. }
  179. }
  180. ASSERT_FORCE(RegCloseKey(adapter_key) == ERROR_SUCCESS)
  181. if (!found) {
  182. return 0;
  183. }
  184. pres = _snprintf(*device_path, sizeof(*device_path), "\\\\.\\Global\\%s.tap", net_cfg_instance_id);
  185. if (pres < 0 || pres == sizeof(*device_path)) {
  186. return 0;
  187. }
  188. return 1;
  189. }