+#else /* WINDOWS32 */
+static void
+get_device(char *device, int device_len)
+{
+ LONG status;
+ HKEY adapter_key;
+ int index;
+
+ index = 0;
+ status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_ADAPTER_KEY, 0, KEY_READ, &adapter_key);
+
+ if (status != ERROR_SUCCESS) {
+ warnx("Error opening registry key " TAP_ADAPTER_KEY );
+ return;
+ }
+
+ while (TRUE) {
+ char name[256];
+ char unit[256];
+ char component[256];
+
+ char cid_string[256] = KEY_COMPONENT_ID;
+ HKEY device_key;
+ DWORD datatype;
+ DWORD len;
+
+ /* Iterate through all adapter of this kind */
+ len = sizeof(name);
+ status = RegEnumKeyEx(adapter_key, index, name, &len, NULL, NULL, NULL, NULL);
+ if (status == ERROR_NO_MORE_ITEMS) {
+ break;
+ } else if (status != ERROR_SUCCESS) {
+ warnx("Error enumerating subkeys of registry key " TAP_ADAPTER_KEY );
+ break;
+ }
+
+ snprintf(unit, sizeof(unit), TAP_ADAPTER_KEY "\\%s", name);
+ status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit, 0, KEY_READ, &device_key);
+ if (status != ERROR_SUCCESS) {
+ warnx("Error opening registry key %s", unit);
+ goto next;
+ }
+
+ /* Check component id */
+ len = sizeof(component);
+ status = RegQueryValueEx(device_key, cid_string, NULL, &datatype, (LPBYTE)component, &len);
+ if (status != ERROR_SUCCESS || datatype != REG_SZ) {
+ goto next;
+ }
+ if (strncmp(TAP_VERSION_ID_0801, component, strlen(TAP_VERSION_ID_0801)) == 0 ||
+ strncmp(TAP_VERSION_ID_0901, component, strlen(TAP_VERSION_ID_0901)) == 0) {
+ /* We found a TAP32 device, get its NetCfgInstanceId */
+ char iid_string[256] = NET_CFG_INST_ID;
+
+ status = RegQueryValueEx(device_key, iid_string, NULL, &datatype, (LPBYTE) device, (DWORD *) &device_len);
+ if (status != ERROR_SUCCESS || datatype != REG_SZ) {
+ warnx("Error reading registry key %s\\%s on TAP device", unit, iid_string);
+ } else {
+ /* Done getting name of TAP device */
+ RegCloseKey(device_key);
+ return;
+ }
+ }
+next:
+ RegCloseKey(device_key);
+ index++;
+ }
+ RegCloseKey(adapter_key);
+}
+
+DWORD WINAPI tun_reader(LPVOID arg)
+{
+ struct tun_data *tun = arg;
+ char buf[64*1024];
+ int len;
+ int res;
+ OVERLAPPED olpd;
+ int sock;
+
+ sock = open_dns(0, INADDR_ANY);
+
+ olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ while(TRUE) {
+ olpd.Offset = 0;
+ olpd.OffsetHigh = 0;
+ res = ReadFile(tun->tun, buf, sizeof(buf), (LPDWORD) &len, &olpd);
+ if (!res) {
+ WaitForSingleObject(olpd.hEvent, INFINITE);
+ res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE);
+ res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
+ sizeof(struct sockaddr_in));
+ }
+ }
+
+ return 0;
+}
+
+int
+open_tun(const char *tun_device)
+{
+ char adapter[256];
+ char tapfile[512];
+ int tunfd;
+ in_addr_t local;
+
+ memset(adapter, 0, sizeof(adapter));
+ get_device(adapter, sizeof(adapter));
+
+ if (strlen(adapter) == 0) {
+ warnx("No TAP adapters found. See README-win32.txt for help.\n");
+ return -1;
+ }
+
+ snprintf(tapfile, sizeof(tapfile), "%s%s.tap", TAP_DEVICE_SPACE, adapter);
+ fprintf(stderr, "Opening device %s\n", tapfile);
+ dev_handle = CreateFile(tapfile, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
+ if (dev_handle == INVALID_HANDLE_VALUE) {
+ return -1;
+ }
+
+ /* TODO get name of interface */
+ strncpy(if_name, "dns", MIN(4, sizeof(if_name)));
+
+ /* Use a UDP connection to forward packets from tun,
+ * so we can still use select() in main code.
+ * A thread does blocking reads on tun device and
+ * sends data as udp to this socket */
+
+ local = htonl(0x7f000001); /* 127.0.0.1 */
+ tunfd = open_dns(55353, local);
+
+ data.tun = dev_handle;
+ memset(&(data.addr), 0, sizeof(data.addr));
+ data.addr.sin_family = AF_INET;
+ data.addr.sin_port = htons(55353);
+ data.addr.sin_addr.s_addr = local;
+ CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL);
+
+ return tunfd;
+}
+#endif