1 /**********************************************************
2 SixXS - Automatic IPv6 Connectivity Configuration Utility
3 ***********************************************************
4 Copyright 2003-2005 SixXS - http://www.sixxs.net
5 ***********************************************************
6 common/tun.c - Tunnel Device Handling
7 ***********************************************************
9 $Id: tun.c,v 1.14 2007-01-11 00:29:18 jeroen Exp $
10 $Date: 2007-01-11 00:29:18 $
11 **********************************************************/
16 /* The tun/tap device HANDLE */
21 * HAS_IFHEAD -> Tunnel Device produces packets with a tun_pi in the front
22 * NEED_IFHEAD -> Tunnel Device produces packets with a tun_pi in the front, but it is not active per default
26 HANDLE device_handle
= INVALID_HANDLE_VALUE
;
27 #define ETH_P_IPV6 0x86dd
31 uint8_t ether_dhost
[ETH_ALEN
]; /* destination eth addr */
32 uint8_t ether_shost
[ETH_ALEN
]; /* source ether addr */
33 uint16_t ether_type
; /* packet type ID field */
36 /* Tap device constants which we use */
37 #define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
38 #define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE(2, METHOD_BUFFERED)
39 #define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE(5, METHOD_BUFFERED)
40 #define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE(6, METHOD_BUFFERED)
41 #define TAP_REGISTRY_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
42 #define TAP_ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
43 #define TAP_DEVICE_DIR "\\\\.\\Global\\"
44 #define TAP_WIN32_MIN_MAJOR 8
45 #define TAP_WIN32_MIN_MINOR 1
46 #define TAP_COMPONENT_ID1 "tap0801" /* Original Tun/Tap driver ID */
47 #define TAP_COMPONENT_ID2 "tap0802" /* Windows Vista marked 801 as broken, thus use another ID */
51 void tun_log(int level
, const char *what
, const char *fmt
, ...);
52 void tun_log(int level
, const char *what
, const char *fmt
, ...)
57 /* Clear them just in case */
58 memset(buf
, 0, sizeof(buf
));
60 snprintf(buf
, sizeof(buf
), "[tun-%s] ", what
);
62 /* Print the log message behind it */
64 vsnprintf(buf
+strlen(buf
), sizeof(buf
)-strlen(buf
), fmt
, ap
);
71 static const char reader_name
[] = "tundev->tun";
72 static const char writer_name
[] = "tun->tundev";
75 /* Windows doesn't have writev() but does have WSASend */
76 int writev(SOCKET sock
, const struct iovec
*vector
, DWORD count
)
79 WSASend(sock
, (LPWSABUF
)vector
, count
, &sent
, 0, NULL
, NULL
);
83 uint16_t inchksum(const void *data
, uint32_t length
);
84 uint16_t inchksum(const void *data
, uint32_t length
)
86 register long sum
= 0;
87 register const uint16_t *wrd
= (const uint16_t *)data
;
88 register long slen
= (long)length
;
96 if (slen
> 0) sum
+=*(const uint8_t *)wrd
;
98 while (sum
>> 16) sum
= (sum
& 0xffff) + (sum
>> 16);
100 return (uint16_t)sum
;
103 uint16_t ipv6_checksum(const struct ip6_hdr
*ip6
, uint8_t protocol
, const void *data
, const uint16_t length
);
104 uint16_t ipv6_checksum(const struct ip6_hdr
*ip6
, uint8_t protocol
, const void *data
, const uint16_t length
)
113 register uint32_t chksum
= 0;
115 pseudo
.length
= htons(length
);
118 pseudo
.next
= protocol
;
120 /* IPv6 Source + Dest */
121 chksum
= inchksum(&ip6
->ip6_src
, sizeof(ip6
->ip6_src
) + sizeof(ip6
->ip6_dst
));
122 chksum
+= inchksum(&pseudo
, sizeof(pseudo
));
123 chksum
+= inchksum(data
, length
);
125 /* Wrap in the carries to reduce chksum to 16 bits. */
126 chksum
= (chksum
>> 16) + (chksum
& 0xffff);
127 chksum
+= (chksum
>> 16);
129 /* Take ones-complement and replace 0 with 0xFFFF. */
130 chksum
= (uint16_t) ~chksum
;
131 if (chksum
== 0UL) chksum
= 0xffffUL
;
132 return (uint16_t)chksum
;
139 * Needs to be started in a separate thread
140 * This gets done by tun_start()
144 void *tun_reader(void *arg
);
145 void *tun_reader(void *arg
)
147 DWORD WINAPI
tun_reader(LPVOID arg
);
148 DWORD WINAPI
tun_reader(LPVOID arg
)
151 unsigned char buf
[2048];
153 /* The function that actually does something with the buffer */
154 struct tun_reader
*tun
= (struct tun_reader
*)arg
;
158 OVERLAPPED overlapped
;
159 unsigned int errcount
= 0;
164 struct icmp6_hdr icmp
;
165 struct nd_neighbor_solicit sol
;
166 } *solic
= (struct nd_sol
*)&buf
[sizeof(struct ether
)];
171 struct icmp6_hdr icmp
;
172 struct nd_neighbor_advert adv
;
175 /* Create an event for overlapped results */
176 overlapped
.hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
185 n
= read(tun_fd
, buf
, sizeof(buf
));
188 /* Only report issues when the tunnel is actually up and running */
189 if (g_aiccu
->tunrunning
) tun_log(LOG_ERR
, reader_name
, "Read error on Tun Device: %s (%d)\n", strerror(errno
), errno
);
193 #if defined(NEED_IFHEAD) || defined(HAS_IFHEAD)
194 /* get the tun_pi struct out of there */
195 memmove(&buf
, &buf
[4], n
-4);
199 tun
->function((char *)buf
, (unsigned int)n
);
201 overlapped
.Offset
= 0;
202 overlapped
.OffsetHigh
= 0;
204 memset(buf
,0,sizeof(buf
));
205 n
= ReadFile(device_handle
, buf
, sizeof(buf
), &lenin
, &overlapped
);
208 while (!n
&& GetLastError() == ERROR_IO_PENDING
)
210 if (WaitForSingleObject(overlapped
.hEvent
, 20000) == WAIT_OBJECT_0
)
212 n
= GetOverlappedResult(device_handle
, &overlapped
, &lenin
, FALSE
);
218 tun_log(LOG_ERR
, reader_name
, "Error reading from device: %u, %s (%d)\n", GetLastError(), strerror(errno
), errno
);
220 if (errcount
> 10) break;
225 /* Check for neighbour discovery packets (ICMPv6, ND_SOL, hop=255)
226 * (XXX: doesn't check for a chain, but ND is usually without)
228 if ( solic
->ip
.ip6_ctlun
.ip6_un1
.ip6_un1_nxt
== IPPROTO_ICMPV6
&&
229 solic
->icmp
.icmp6_type
== ND_NEIGHBOR_SOLICIT
&&
230 solic
->ip
.ip6_ctlun
.ip6_un1
.ip6_un1_hlim
== 255)
232 /* Ignore unspecified ND's as they are used for DAD */
233 if (IN6_IS_ADDR_UNSPECIFIED(&solic
->ip
.ip6_src
)) continue;
235 /* Create our reply */
236 memset(&advert
, 0, sizeof(advert
));
237 advert
.ip
.ip6_ctlun
.ip6_un2_vfc
= 6 << 4;
238 advert
.ip
.ip6_ctlun
.ip6_un1
.ip6_un1_flow
= solic
->ip
.ip6_ctlun
.ip6_un1
.ip6_un1_flow
;
239 advert
.ip
.ip6_ctlun
.ip6_un1
.ip6_un1_plen
= htons(sizeof(advert
.icmp
) + sizeof(advert
.adv
));
240 advert
.ip
.ip6_ctlun
.ip6_un1
.ip6_un1_nxt
= IPPROTO_ICMPV6
;
241 advert
.ip
.ip6_ctlun
.ip6_un1
.ip6_un1_hlim
= 255;
244 memcpy(&advert
.ip
.ip6_src
, &solic
->sol
.nd_ns_target
, sizeof(advert
.ip
.ip6_src
));
245 memcpy(&advert
.ip
.ip6_dst
, &solic
->ip
.ip6_src
, sizeof(advert
.ip
.ip6_dst
));
247 /* ICMP Neighbour Advertisement */
248 advert
.icmp
.icmp6_type
= ND_NEIGHBOR_ADVERT
;
249 advert
.icmp
.icmp6_code
= 0;
250 advert
.icmp
.icmp6_dataun
.icmp6_un_data8
[0] = 0xe0;
251 memcpy(&advert
.adv
.nd_na_target
, &solic
->sol
.nd_ns_target
, sizeof(advert
.adv
.nd_na_target
));
252 /* Fake MAC address */
253 advert
.adv
.nd_no_type
= 2;
254 advert
.adv
.nd_no_len
= 1;
255 advert
.adv
.nd_no_mac
[0] = 0x00;
256 advert
.adv
.nd_no_mac
[1] = 0xff;
257 advert
.adv
.nd_no_mac
[2] = 0x25;
258 advert
.adv
.nd_no_mac
[3] = 0x02;
259 advert
.adv
.nd_no_mac
[4] = 0x19;
260 advert
.adv
.nd_no_mac
[5] = 0x78;
262 /* ICMP has a checksum */
263 advert
.icmp
.icmp6_cksum
= ipv6_checksum(&advert
.ip
, IPPROTO_ICMPV6
, (uint8_t *)&advert
.icmp
, sizeof(advert
.icmp
) + sizeof(advert
.adv
));
265 /* We'll need to answer this back to the TAP device */
266 tun_write((char *)&advert
, (unsigned int)sizeof(advert
));
269 tun
->function((char *)&buf
[sizeof(struct ether
)], (unsigned int)lenin
- sizeof(struct ether
));
273 D(dolog(LOG_DEBUG
, "TUN Reader stopping\n"));
282 void tun_write(char *buf
, unsigned int length
)
289 memset(&pi
, 0, sizeof(pi
));
291 pi
.proto
= htons(ETH_P_IPV6
);
293 dat
[0].iov_base
= &pi
;
294 dat
[0].iov_len
= sizeof(pi
);
295 dat
[1].iov_base
= buf
;
296 dat
[1].iov_len
= length
;
298 length
+= sizeof(pi
);
300 /* Forward the packet to the kernel */
301 c
= writev(tun_fd
, dat
, 2);
303 #else /* *BSD/Darwin */
305 uint32_t type
= htonl(AF_INET6
);
308 dat
[0].iov_base
= (void *)&type
;
309 dat
[0].iov_len
= sizeof(type
);
310 dat
[1].iov_base
= buf
;
311 dat
[1].iov_len
= length
;
313 length
+= sizeof(type
);
315 /* Forward the packet to the kernel */
316 c
= writev(tun_fd
, dat
, 2);
322 tun_log(LOG_ERR
, writer_name
, "Error while writing to TUN: %u != %u\n", c
, length
);
327 OVERLAPPED overlapped
;
328 unsigned char mbuf
[4096];
330 struct ether
*eth
= (struct ether
*)mbuf
;
332 /* Sent the packet outbound */
333 overlapped
.Offset
= 0;
334 overlapped
.OffsetHigh
= 0;
335 overlapped
.hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
337 memset(mbuf
,0,sizeof(mbuf
));
338 eth
->ether_dhost
[0] = htons(0x3333);
339 eth
->ether_dhost
[1] = htons(0xff00);
340 eth
->ether_dhost
[2] = htons(0x0002);
341 eth
->ether_shost
[0] = htons(0x00ff);
342 eth
->ether_shost
[1] = htons(0x5342);
343 eth
->ether_shost
[2] = htons(0x2768);
344 eth
->ether_type
= htons(ETH_P_IPV6
);
345 memcpy(&mbuf
[sizeof(*eth
)],buf
,length
);
347 n
= WriteFile(device_handle
, mbuf
, sizeof(*eth
)+length
, &lenout
, &overlapped
);
348 if (!n
&& GetLastError() == ERROR_IO_PENDING
)
350 WaitForSingleObject(overlapped
.hEvent
, INFINITE
);
351 n
= GetOverlappedResult(device_handle
, &overlapped
, &lenout
, FALSE
);
356 tun_log(LOG_ERR
, writer_name
, "Error writing to device: %u, %s (%d)\n", GetLastError(), strerror(errno
), errno
);
366 struct tap_reg
*next
;
373 struct panel_reg
*next
;
376 /* Get a working tunnel adapter */
377 struct tap_reg
*get_tap_reg(void)
382 struct tap_reg
*first
= NULL
;
383 struct tap_reg
*last
= NULL
;
386 status
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, TAP_ADAPTER_KEY
, 0, KEY_READ
, &adapter_key
);
387 if (status
!= ERROR_SUCCESS
)
389 dolog(LOG_ERR
, "Error opening registry key: %s\n", TAP_ADAPTER_KEY
);
396 char unit_string
[256];
398 char component_id_string
[] = "ComponentId";
399 char component_id
[256];
400 char net_cfg_instance_id_string
[] = "NetCfgInstanceId";
401 char net_cfg_instance_id
[256];
404 len
= sizeof(enum_name
);
405 status
= RegEnumKeyEx(adapter_key
, i
, enum_name
, &len
, NULL
, NULL
, NULL
, NULL
);
406 if (status
== ERROR_NO_MORE_ITEMS
) break;
407 else if (status
!= ERROR_SUCCESS
)
409 dolog(LOG_ERR
, "Error enumerating registry subkeys of key: %s (t0)\n", TAP_ADAPTER_KEY
);
413 snprintf(unit_string
, sizeof(unit_string
), "%s\\%s", TAP_ADAPTER_KEY
, enum_name
);
414 status
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, unit_string
, 0, KEY_READ
, &unit_key
);
415 if (status
!= ERROR_SUCCESS
)
417 dolog(LOG_WARNING
, "Error opening registry key: %s (t1)\n", unit_string
);
421 len
= sizeof(component_id
);
422 status
= RegQueryValueEx(unit_key
, component_id_string
, NULL
, &data_type
, (LPBYTE
)component_id
, &len
);
423 if (status
!= ERROR_SUCCESS
|| data_type
!= REG_SZ
)
425 dolog(LOG_WARNING
, "Error opening registry key: %s\\%s (t2)\n", unit_string
, component_id_string
);
429 len
= sizeof(net_cfg_instance_id
);
430 status
= RegQueryValueEx(unit_key
, net_cfg_instance_id_string
, NULL
, &data_type
, (LPBYTE
)net_cfg_instance_id
, &len
);
431 if (status
== ERROR_SUCCESS
&& data_type
== REG_SZ
)
433 if ( strcmp(component_id
, TAP_COMPONENT_ID1
) == 0 ||
434 strcmp(component_id
, TAP_COMPONENT_ID2
) == 0)
436 struct tap_reg
*reg
= (struct tap_reg
*)malloc(sizeof(*reg
));
437 memset(reg
, 0, sizeof(*reg
));
438 reg
->guid
= strdup(net_cfg_instance_id
);
440 if (!first
) first
= reg
;
441 if (last
) last
->next
= reg
;
447 RegCloseKey(unit_key
);
452 RegCloseKey(adapter_key
);
456 void free_tap_reg(struct tap_reg
*tap_reg
)
458 struct tap_reg
*tr
, *tr1
;
460 for (tr
= tap_reg
; tr
!= NULL
; tr
= tr1
)
468 void free_panel_reg(struct panel_reg
*panel_reg
)
470 struct panel_reg
*pr
, *pr1
;
472 for (pr
= panel_reg
; pr
!= NULL
; pr
= pr1
)
482 /* Collect GUID's and names of all the Connections that are available */
483 struct panel_reg
*get_panel_reg(void)
486 HKEY network_connections_key
;
488 struct panel_reg
*first
= NULL
;
489 struct panel_reg
*last
= NULL
;
492 status
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, TAP_REGISTRY_KEY
, 0, KEY_READ
, &network_connections_key
);
494 if (status
!= ERROR_SUCCESS
)
496 dolog(LOG_ERR
, "Error opening registry key: %s (p0)\n", TAP_REGISTRY_KEY
);
503 char connection_string
[256];
507 const char name_string
[] = "Name";
509 len
= sizeof(enum_name
);
510 status
= RegEnumKeyEx(network_connections_key
, i
, enum_name
, &len
, NULL
, NULL
, NULL
, NULL
);
511 if (status
== ERROR_NO_MORE_ITEMS
) break;
512 else if (status
!= ERROR_SUCCESS
)
514 dolog(LOG_ERR
, "Error enumerating registry subkeys of key: %s (p1)\n", TAP_REGISTRY_KEY
);
520 if (enum_name
[0] != '{') continue;
522 snprintf(connection_string
, sizeof(connection_string
), "%s\\%s\\Connection", TAP_REGISTRY_KEY
, enum_name
);
524 status
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, connection_string
, 0, KEY_READ
, &connection_key
);
525 if (status
!= ERROR_SUCCESS
)
527 dolog(LOG_WARNING
, "Error opening registry key: %s (p2)\n", connection_string
);
531 len
= sizeof(name_data
);
532 status
= RegQueryValueEx(connection_key
, name_string
, NULL
, &name_type
, (LPBYTE
)name_data
, &len
);
534 if (status
!= ERROR_SUCCESS
|| name_type
!= REG_SZ
)
536 dolog(LOG_WARNING
, "Error opening registry key: %s\\%s\\%s (p3)\n", TAP_REGISTRY_KEY
, (LPBYTE
)connection_string
, name_string
);
540 struct panel_reg
*reg
= (struct panel_reg
*)malloc(sizeof(*reg
));
541 memset(reg
, 0, sizeof(*reg
));
542 reg
->name
= strdup(name_data
);
543 reg
->guid
= strdup(enum_name
);
545 /* link into return list */
546 if (!first
) first
= reg
;
547 if (last
) last
->next
= reg
;
551 RegCloseKey(connection_key
);
555 RegCloseKey(network_connections_key
);
560 void tun_list_tap_adapters(void)
563 struct tap_reg
*tap_reg
= get_tap_reg(), *tr
, *tr1
;
564 struct panel_reg
*panel_reg
= get_panel_reg(), *pr
;
566 dolog(LOG_INFO
, "Available TAP-WIN32 adapters [name, GUID]:\n");
568 /* loop through each TAP-Win32 adapter registry entry */
569 for (tr
= tap_reg
; tr
!= NULL
; tr
= tr
->next
)
573 /* loop through each network connections entry in the control panel */
574 for (pr
= panel_reg
; pr
!= NULL
; pr
= pr
->next
)
576 if (strcmp(tr
->guid
, pr
->guid
) == 0)
578 dolog(LOG_INFO
, "'%s' %s\n", pr
->name
, tr
->guid
);
585 dolog(LOG_WARNING
, "*** Adapter with GUID %s has %u links from the Network Connections control panel, it should only be 1\n", tr
->guid
, links
);
589 dolog(LOG_WARNING
, "[NULL] %s\n", tr
->guid
);
590 dolog(LOG_WARNING
, "*** Adapter with GUID %s doesn't have a link from the control panel\n", tr
->guid
);
593 /* check for TAP-Win32 adapter duplicated GUIDs */
594 for (tr1
= tap_reg
; tr1
!= NULL
; tr1
= tr1
->next
)
596 if (tr
!= tr1
&& strcmp(tr
->guid
, tr1
->guid
) == 0)
598 dolog(LOG_WARNING
, "*** Duplicate Adapter GUID %s\n", tr
->guid
);
603 free_tap_reg(tap_reg
);
604 free_panel_reg(panel_reg
);
607 bool tun_fixup_adapters(void)
609 int links
, count
= 0, found
= 0;
610 struct tap_reg
*tap_reg
= get_tap_reg(), *tr
= NULL
, *tr1
= NULL
;
611 struct panel_reg
*panel_reg
= get_panel_reg(), *pr
= NULL
, *first
= NULL
, *prf
= NULL
;
614 /* loop through each TAP-Win32 adapter registry entry */
615 for (tr
= tap_reg
; tr
!= NULL
; tr
= tr
->next
)
620 /* loop through each network connections entry in the control panel */
621 for (pr
= panel_reg
; pr
!= NULL
; pr
= pr
->next
)
623 if (strcmp(tr
->guid
, pr
->guid
) == 0)
628 /* Is this the one wanted by the user? */
629 if (strcasecmp(g_aiccu
->ipv6_interface
, pr
->name
) == 0) found
++;
635 dolog(LOG_WARNING
, "*** Adapter with GUID %s has %u links from the Network Connections control panel, it should only be 1\n", tr
->guid
, links
);
640 dolog(LOG_WARNING
, "[NULL] %s\n", tr
->guid
);
641 dolog(LOG_WARNING
, "*** Adapter with GUID %s doesn't have a link from the control panel\n", tr
->guid
);
645 /* check for TAP-Win32 adapter duplicated GUIDs */
646 for (tr1
= tap_reg
; tr1
!= NULL
; tr1
= tr1
->next
)
648 if (tr
!= tr1
&& strcmp(tr
->guid
, tr1
->guid
) == 0)
650 dolog(LOG_WARNING
, "*** Duplicate Adapter GUID %s\n", tr
->guid
);
664 /* When the user didn't configure us correctly and we find a single TAP interface, just rename it */
665 if (found
== 0 && count
== 1 && first
)
667 dolog(LOG_INFO
, "Renaming adapter '%s' to '%s' and using it\n", first
->name
, g_aiccu
->ipv6_interface
);
668 aiccu_win32_rename_adapter(first
->name
);
671 else if (found
== 1 && count
== 1)
673 D(dolog(LOG_DEBUG
, "Using configured interface %s\n", g_aiccu
->ipv6_interface
));
679 dolog(LOG_WARNING
, "Found = %u, Count = %u\n", found
, count
);
682 free_tap_reg(tap_reg
);
683 free_panel_reg(panel_reg
);
690 bool tun_start(struct tun_reader
*tun
)
697 /* Create a new tap device */
698 tun_fd
= open("/dev/net/tun", O_RDWR
);
701 tun_log(LOG_ERR
, "start", "Couldn't open device %s: %s (%d)\n", "/dev/net/tun", strerror(errno
), errno
);
705 memset(&ifr
, 0, sizeof(ifr
));
706 /* Request a TUN device */
707 ifr
.ifr_flags
= IFF_TUN
;
708 /* Set the interface name */
709 strncpy(ifr
.ifr_name
, g_aiccu
->ipv6_interface
, sizeof(ifr
.ifr_name
));
711 if (ioctl(tun_fd
, TUNSETIFF
, &ifr
))
713 tun_log(LOG_ERR
, "start", "Couldn't set interface name to %s: %s (%d)\n",
714 g_aiccu
->ipv6_interface
, strerror(errno
), errno
);
718 #else /* *BSD/Darwin */
722 int mode
= IFF_MULTICAST
| IFF_POINTOPOINT
;
724 /* Try the configured interface */
725 tun_log(LOG_DEBUG
, "start", "Trying Configured TUN/TAP interface %s...\n", g_aiccu
->ipv6_interface
);
726 snprintf(buf
, sizeof(buf
), "/dev/%s", g_aiccu
->ipv6_interface
);
727 tun_fd
= open(buf
, O_RDWR
);
730 /* Fall back to trying all /dev/tun* devices */
731 for (i
= 0; i
< 256; ++i
)
733 snprintf(buf
, sizeof(buf
), "/dev/tun%u", i
);
734 tun_log(LOG_DEBUG
, "start", "Trying TUN/TAP interface %s...\n", &buf
[8]);
735 tun_fd
= open(buf
, O_RDWR
);
738 /* Copy over the name of the interface so that configging goes okay */
739 if (g_aiccu
->ipv6_interface
) free(g_aiccu
->ipv6_interface
);
740 snprintf(buf
, sizeof(buf
), "tun%u", i
);
741 g_aiccu
->ipv6_interface
= strdup(buf
);
749 tun_log(LOG_ERR
, "start", "Couldn't open device %s or /dev/tun*: %s (%d)\n", g_aiccu
->ipv6_interface
, strerror(errno
), errno
);
753 tun_log(LOG_DEBUG
, "start", "Using TUN/TAP interface %s\n", g_aiccu
->ipv6_interface
);
758 tun_log(LOG_DEBUG
, "start", "Setting TUNSIFMODE for %s\n", g_aiccu
->ipv6_interface
);
759 if (ioctl(tun_fd
, TUNSIFMODE
, &mode
, sizeof(mode
)) == -1)
761 tun_log(LOG_ERR
, "start", "Couldn't set interface %s's TUNSIFMODE to MULTICAST|POINTOPOINT: %s (%d)\n",
762 g_aiccu
->ipv6_interface
, strerror(errno
), errno
);
772 tun_log(LOG_DEBUG
, "start", "Setting TUNSIFHEAD for %s\n", g_aiccu
->ipv6_interface
);
774 if (ioctl(tun_fd
, TUNSIFHEAD
, &mode
, sizeof(mode
)) == -1)
776 tun_log(LOG_ERR
, "start", "Couldn't set interface %s's TUNSIFHEAD to enabled: %s (%d)\n",
777 g_aiccu
->ipv6_interface
, strerror(errno
), errno
);
794 char adapterid
[1024];
798 if (!tun_fixup_adapters())
800 tun_log(LOG_ERR
, "start", "TAP-Win32 Adapter not configured properly...\n");
804 /* Open registry and look for network adapters */
805 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
, TAP_REGISTRY_KEY
, 0, KEY_READ
, &key
))
807 tun_log(LOG_ERR
, "start", "Could not open the networking registry key\n");
811 for (i
= 0; device_handle
== INVALID_HANDLE_VALUE
; i
++)
813 len
= sizeof(adapterid
);
814 if (RegEnumKeyEx(key
, i
, adapterid
, &len
, 0, 0, 0, NULL
)) break;
816 snprintf(tapname
, sizeof(tapname
), TAP_DEVICE_DIR
"%s.tap", adapterid
);
817 tun_log(LOG_DEBUG
, "start", "Trying %s\n", tapname
);
818 device_handle
= CreateFile(tapname
, GENERIC_WRITE
| GENERIC_READ
, 0, 0, OPEN_EXISTING
, FILE_ATTRIBUTE_SYSTEM
| FILE_FLAG_OVERLAPPED
, 0);
820 if (device_handle
!= INVALID_HANDLE_VALUE
)
822 unsigned long status
, info
[3] = {0,0,0};
824 /* get driver version info */
825 if (DeviceIoControl(device_handle
, TAP_IOCTL_GET_VERSION
, &info
, sizeof(info
), &info
, sizeof(info
), &len
, NULL
))
827 D(tun_log(LOG_DEBUG
, "start", "TAP-Win32 Driver Version %d.%d %s", (int)info
[0], (int)info
[1], info
[2] ? "(DEBUG)" : ""));
830 if (!(info
[0] > TAP_WIN32_MIN_MAJOR
|| (info
[0] == TAP_WIN32_MIN_MAJOR
&& info
[1] >= TAP_WIN32_MIN_MINOR
)))
832 tun_log(LOG_ERR
, "start", "A TAP-Win32 driver is required that is at least version %d.%d -- If you recently upgraded your Tap32 driver, a reboot is probably required at this point to get Windows to see the new driver.", TAP_WIN32_MIN_MAJOR
, TAP_WIN32_MIN_MINOR
);
833 CloseHandle(device_handle
);
834 device_handle
= INVALID_HANDLE_VALUE
;
838 /* Note: we use TAP mode on Windows, not TUN */
840 /* Try to mark the device as 'up */
842 DeviceIoControl(device_handle
, TAP_IOCTL_SET_MEDIA_STATUS
, &status
, sizeof(status
), &status
, sizeof(status
), &len
, NULL
);
848 if (device_handle
== INVALID_HANDLE_VALUE
)
850 tun_log(LOG_ERR
, "start", "No working Tap device found!\n");
856 /* Launch a thread for reader */
858 pthread_create(&thread
, NULL
, tun_reader
, (void *)tun
);
860 h
= CreateThread(NULL
, 0, (LPTHREAD_START_ROUTINE
)tun_reader
, tun
, 0, &pID
);
863 /* We now return, the real tunneling tool can call tun_write() when it wants */