1 /* IPSec VPN client compatible with Cisco equipment.
2 Copyright (C) 2007 Maurice Massar
3 Copyright (C) 2007 Paolo Zarpellon <paolo.zarpellon@gmail.com> (Cygwin support)
5 based on VTun - Virtual Tunnel over TCP/IP network.
6 Copyright (C) 1998-2000 Maxim Krasnyansky <max_mk@yahoo.com>
7 VTun has been derived from VPPP package by Maxim Krasnyansky.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
26 #include <sys/ioctl.h>
29 #include <sys/socket.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <sys/sockio.h>
41 #include <netinet/in.h>
42 #include <netinet/in_systm.h>
43 #include <netinet/ip.h>
44 #include <netinet/tcp.h>
47 #if defined(__CYGWIN__)
49 #include <w32api/windef.h>
50 #include <w32api/winbase.h>
51 #include <w32api/winnt.h>
52 #include <w32api/winioctl.h>
53 #include <w32api/iphlpapi.h>
54 #include <w32api/iptypes.h>
55 #include <w32api/winreg.h>
56 #include <sys/cygwin.h>
59 #if defined(__DragonFly__)
60 #include <net/tun/if_tun.h>
61 #elif defined(__linux__)
62 #include <linux/if_tun.h>
63 #elif defined(__APPLE__)
64 /* no header for tun */
65 #elif defined(__CYGWIN__)
66 #include "tap-win32.h"
68 #include <net/if_tun.h>
73 #if !defined(HAVE_VASPRINTF) || !defined(HAVE_ASPRINTF) || !defined(HAVE_ERROR)
78 extern char **environ
;
79 static int ip_fd
= -1, muxid
;
82 #if defined(__CYGWIN__)
84 * Overlapped structures for asynchronous read and write
86 static OVERLAPPED overlap_read
, overlap_write
;
89 SEARCH_IF_GUID_FROM_NAME
,
90 SEARCH_IF_NAME_FROM_GUID
95 * Allocate TUN/TAP device, returns opened fd.
96 * Stores dev name in the first arg(must be large enough).
99 int tun_open(char *dev
, enum if_mode_enum mode
)
101 int tun_fd
, if_fd
, ppa
= -1;
107 while (*ptr
&& !isdigit((int)*ptr
))
112 if ((ip_fd
= open("/dev/ip", O_RDWR
, 0)) < 0) {
113 logmsg(LOG_ERR
, "Can't open /dev/ip");
117 if ((tun_fd
= open(((mode
== IF_MODE_TUN
) ? "/dev/tun" : "/dev/tap"), O_RDWR
, 0)) < 0) {
118 logmsg(LOG_ERR
, "Can't open /dev/tun");
122 /* Assign a new PPA and get its unit number. */
123 if ((ppa
= ioctl(tun_fd
, TUNNEWPPA
, ppa
)) < 0) {
124 logmsg(LOG_ERR
, "Can't assign new interface");
128 if ((if_fd
= open(((mode
== IF_MODE_TUN
) ? "/dev/tun" : "/dev/tap"), O_RDWR
, 0)) < 0) {
129 logmsg(LOG_ERR
, "Can't open /dev/tun (2)");
132 if (ioctl(if_fd
, I_PUSH
, "ip") < 0) {
133 logmsg(LOG_ERR
, "Can't push IP module");
137 /* Assign ppa according to the unit number returned by tun device */
138 if (ioctl(if_fd
, IF_UNITSEL
, (char *)&ppa
) < 0 && errno
!= EEXIST
) {
139 logmsg(LOG_ERR
, "Can't set PPA %d", ppa
);
142 if ((muxid
= ioctl(ip_fd
, I_PLINK
, if_fd
)) < 0) {
143 logmsg(LOG_ERR
, "Can't link TUN device to IP");
148 snprintf(dev
, IFNAMSIZ
, "%s%d", ((mode
== IF_MODE_TUN
) ? "tun" : "tap"), ppa
);
150 memset(&ifr
, 0, sizeof(ifr
));
151 strcpy(ifr
.ifr_name
, dev
);
152 ifr
.ifr_ip_muxid
= muxid
;
154 if (ioctl(ip_fd
, SIOCSIFMUXID
, &ifr
) < 0) {
155 ioctl(ip_fd
, I_PUNLINK
, muxid
);
156 logmsg(LOG_ERR
, "Can't set multiplexor id");
162 #elif defined(__CYGWIN__)
164 * Get interface guid/name from registry
166 static char *search_if(char *value
, char *key
, search_if_en type
)
175 char conn_string
[512];
179 if (!value
|| !key
) {
183 status
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
184 NETWORK_CONNECTIONS_KEY
,
189 if (status
!= ERROR_SUCCESS
) {
190 printf("Error opening registry key: %s\n", NETWORK_CONNECTIONS_KEY
);
196 status
= RegEnumKeyEx(net_conn_key
, i
++, guid
, &len
,
197 NULL
, NULL
, NULL
, NULL
);
198 if (status
== ERROR_NO_MORE_ITEMS
) {
200 } else if (status
!= ERROR_SUCCESS
) {
203 snprintf(conn_string
, sizeof(conn_string
),
204 "%s\\%s\\Connection",
205 NETWORK_CONNECTIONS_KEY
, guid
);
206 status
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
211 if (status
!= ERROR_SUCCESS
) {
214 len
= sizeof(ifname
);
215 status
= RegQueryValueEx(conn_key
, "Name", NULL
,
216 &value_type
, ifname
, &len
);
217 if (status
!= ERROR_SUCCESS
|| value_type
!= REG_SZ
) {
218 RegCloseKey(conn_key
);
223 case SEARCH_IF_GUID_FROM_NAME
:
224 if (!strcmp(key
, ifname
)) {
229 case SEARCH_IF_NAME_FROM_GUID
:
230 if (!strcmp(key
, guid
)) {
231 strcpy(value
, ifname
);
238 RegCloseKey(conn_key
);
240 RegCloseKey(net_conn_key
);
250 * Open the TUN/TAP device with the provided guid
252 static int open_tun_device (char *guid
, char *dev
, enum if_mode_enum mode
)
255 ULONG len
, status
, info
[3];
256 char device_path
[512];
258 printf("Device: %s\n", dev
);
260 if (mode
== IF_MODE_TUN
) {
261 printf("TUN mode is not supported\n");
266 * Let's try to open Windows TAP-Win32 adapter
268 snprintf(device_path
, sizeof(device_path
), "%s%s%s",
269 USERMODEDEVICEDIR
, guid
, TAPSUFFIX
);
271 handle
= CreateFile(device_path
,
272 GENERIC_READ
| GENERIC_WRITE
,
273 0, /* Don't let other processes share or open
274 the resource until the handle's been closed */
277 FILE_ATTRIBUTE_SYSTEM
| FILE_FLAG_OVERLAPPED
,
280 if (handle
== INVALID_HANDLE_VALUE
) {
285 * get driver version info
287 memset(info
, 0, sizeof(info
));
288 if (DeviceIoControl(handle
, TAP_IOCTL_GET_VERSION
,
290 &info
, sizeof(info
), &len
, NULL
)) {
291 printf("TAP-Win32 Driver Version %d.%d %s\n",
294 (info
[2] ? "(DEBUG)" : ""));
298 * Set driver media status to 'connected'
301 if (!DeviceIoControl(handle
, TAP_IOCTL_SET_MEDIA_STATUS
,
302 &status
, sizeof(status
),
303 &status
, sizeof(status
), &len
, NULL
)) {
304 printf("WARNING: The TAP-Win32 driver rejected a "
305 "TAP_IOCTL_SET_MEDIA_STATUS DeviceIoControl call.\n");
309 * Initialize overlapped structures
311 overlap_read
.hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
312 overlap_write
.hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
313 if (!overlap_read
.hEvent
|| !overlap_write
.hEvent
) {
320 return cygwin_attach_handle_to_fd(NULL
, -1, handle
, 1, GENERIC_READ
| GENERIC_WRITE
);
324 * Allocate TUN device, returns opened fd.
325 * Stores dev name in the first arg (must be large enough).
327 int tun_open (char *dev
, enum if_mode_enum mode
)
334 char unit_string
[512];
346 * Device name has been provided. Open such device.
349 if (!search_if(guid
, dev
, SEARCH_IF_GUID_FROM_NAME
)) {
352 return open_tun_device(guid
, dev
, mode
);
356 * Device name has non been specified. Look for one available!
359 status
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
364 if (status
!= ERROR_SUCCESS
) {
365 printf("Error opening registry key: %s", ADAPTER_KEY
);
370 len
= sizeof(enum_name
);
371 status
= RegEnumKeyEx(adapter_key
, i
++,
373 NULL
, NULL
, NULL
, NULL
);
374 if (status
== ERROR_NO_MORE_ITEMS
) {
376 } else if (status
!= ERROR_SUCCESS
) {
379 snprintf(unit_string
, sizeof(unit_string
), "%s\\%s",
380 ADAPTER_KEY
, enum_name
);
381 status
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
386 if (status
!= ERROR_SUCCESS
) {
389 len
= sizeof(comp_id
);
390 status
= RegQueryValueEx(unit_key
,
392 &value_type
, comp_id
, &len
);
393 if (status
!= ERROR_SUCCESS
|| value_type
!= REG_SZ
) {
394 RegCloseKey(unit_key
);
398 status
= RegQueryValueEx(unit_key
,
399 "NetCfgInstanceId", NULL
,
400 &value_type
, guid
, &len
);
401 if (status
!= ERROR_SUCCESS
|| value_type
!= REG_SZ
) {
402 RegCloseKey(unit_key
);
407 while (TAP_COMPONENT_ID
[j
]) {
408 if (!strcmp(comp_id
, TAP_COMPONENT_ID
[j
])) {
413 if (!TAP_COMPONENT_ID
[j
]) {
414 RegCloseKey(unit_key
);
419 * Let's try to open this device
421 search_if(dev
, guid
, SEARCH_IF_NAME_FROM_GUID
);
422 fd
= open_tun_device(guid
, dev
, mode
);
427 RegCloseKey(unit_key
);
429 RegCloseKey(adapter_key
);
433 #elif defined(IFF_TUN)
434 int tun_open(char *dev
, enum if_mode_enum mode
)
439 if ((fd
= open("/dev/net/tun", O_RDWR
)) < 0) {
441 "can't open /dev/net/tun, check that it is either device char 10 200 or (with DevFS) a symlink to ../misc/net/tun (not misc/net/tun)");
445 memset(&ifr
, 0, sizeof(ifr
));
446 ifr
.ifr_flags
= ((mode
== IF_MODE_TUN
) ? IFF_TUN
: IFF_TAP
) | IFF_NO_PI
;
448 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
450 if ((err
= ioctl(fd
, TUNSETIFF
, (void *)&ifr
)) < 0) {
454 strcpy(dev
, ifr
.ifr_name
);
458 int tun_open(char *dev
, enum if_mode_enum mode
)
464 if (strncmp(dev
, ((mode
== IF_MODE_TUN
) ? "tun" : "tap"), 3))
466 "error: arbitrary naming tunnel interface is not supported in this version\n");
467 snprintf(tunname
, sizeof(tunname
), "/dev/%s", dev
);
468 return open(tunname
, O_RDWR
);
471 for (i
= 0; i
< 255; i
++) {
472 snprintf(tunname
, sizeof(tunname
), "/dev/%s%d",
473 ((mode
== IF_MODE_TUN
) ? "tun" : "tap"), i
);
475 if ((fd
= open(tunname
, O_RDWR
)) > 0) {
476 snprintf(dev
, IFNAMSIZ
, "%s%d",
477 ((mode
== IF_MODE_TUN
) ? "tun" : "tap"), i
);
483 #endif /* New driver support */
489 int tun_close(int fd
, char *dev
)
493 memset(&ifr
, 0, sizeof(ifr
));
494 strcpy(ifr
.ifr_name
, dev
);
495 if (ioctl(ip_fd
, SIOCGIFFLAGS
, &ifr
) < 0) {
496 logmsg(LOG_ERR
, "Can't get iface flags");
500 if (ioctl(ip_fd
, I_PUNLINK
, muxid
) < 0) {
501 logmsg(LOG_ERR
, "Can't unlink interface");
510 #elif defined(__CYGWIN__)
511 int tun_close(int fd
, char *dev
)
513 dev
= NULL
; /* unused */
514 return CloseHandle((HANDLE
) get_osfhandle(fd
));
517 int tun_close(int fd
, char *dev
)
519 dev
= NULL
; /*unused */
526 int tun_write(int fd
, unsigned char *buf
, int len
)
531 return putmsg(fd
, NULL
, &sbuf
, 0) >= 0 ? sbuf
.len
: -1;
534 int tun_read(int fd
, unsigned char *buf
, int len
)
541 return getmsg(fd
, NULL
, &sbuf
, &f
) >= 0 ? sbuf
.len
: -1;
543 #elif defined(__CYGWIN__)
544 int tun_read(int fd
, unsigned char *buf
, int len
)
548 ResetEvent(overlap_read
.hEvent
);
549 if (ReadFile((HANDLE
) get_osfhandle(fd
), buf
, len
, &read_size
, &overlap_read
)) {
552 switch (GetLastError()) {
553 case ERROR_IO_PENDING
:
554 WaitForSingleObject(overlap_read
.hEvent
, INFINITE
);
555 GetOverlappedResult((HANDLE
) get_osfhandle(fd
), &overlap_read
, &read_size
, FALSE
);
565 int tun_write(int fd
, unsigned char *buf
, int len
)
569 ResetEvent(overlap_write
.hEvent
);
570 if (WriteFile((HANDLE
) get_osfhandle(fd
),
577 switch (GetLastError()) {
578 case ERROR_IO_PENDING
:
579 WaitForSingleObject(overlap_write
.hEvent
, INFINITE
);
580 GetOverlappedResult((HANDLE
) get_osfhandle(fd
), &overlap_write
,
590 #elif defined(NEW_TUN)
597 u_char data
[MAX_MRU
];
600 /* Read/write frames from TUN device */
601 int tun_write(int fd
, unsigned char *buf
, int len
)
606 if (len
> (int)sizeof(tun
.data
))
609 memcpy(tun
.data
, buf
, len
);
610 tun
.header
.family
= htonl(AF_INET
);
611 len
+= (sizeof(tun
) - sizeof(tun
.data
));
614 return write(fd
, data
, len
) - (sizeof(tun
) - sizeof(tun
.data
));
617 int tun_read(int fd
, unsigned char *buf
, int len
)
626 pack
= read(fd
, data
, sz
);
630 pack
-= sz
- sizeof(tun
.data
);
632 pack
= len
; /* truncate packet */
634 memcpy(buf
, tun
.data
, pack
);
641 int tun_write(int fd
, unsigned char *buf
, int len
)
643 return write(fd
, buf
, len
);
646 int tun_read(int fd
, unsigned char *buf
, int len
)
648 return read(fd
, buf
, len
);
656 int tun_get_hwaddr(int fd
, char *dev
, uint8_t *hwaddr
)
658 #if defined(__CYGWIN__)
661 dev
= NULL
; /* unused */
662 if (!DeviceIoControl((HANDLE
) get_osfhandle(fd
), TAP_IOCTL_GET_MAC
,
663 hwaddr
, ETH_ALEN
, hwaddr
, ETH_ALEN
, &len
, NULL
)) {
664 printf("Cannot get HW address\n");
669 #elif defined(SIOCGIFHWADDR)
672 /* Use a new socket fd! */
673 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
677 memset(&ifr
, 0, sizeof(struct ifreq
));
678 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
680 if (ioctl(fd
, SIOCGIFHWADDR
, &ifr
) < 0) {
684 memcpy(hwaddr
, &ifr
.ifr_hwaddr
.sa_data
, ETH_ALEN
);
688 /* todo: implement using SIOCGLIFADDR */
697 /***********************************************************************/
698 /* other support functions */
700 #ifndef HAVE_VASPRINTF
701 int vasprintf(char **strp
, const char *fmt
, va_list ap
)
706 ret
= vsnprintf(NULL
, 0, fmt
, ap
);
707 strbuf
= (char *)malloc(ret
+ 1);
708 if (strbuf
== NULL
) {
712 vsnprintf(strbuf
, ret
+ 1, fmt
, ap
);
718 #ifndef HAVE_ASPRINTF
719 int asprintf(char **strp
, const char *fmt
, ...)
725 ret
= vasprintf(strp
, fmt
, ap
);
733 void error(int status
, int errornum
, const char *fmt
, ...)
739 vasprintf(&buf2
, fmt
, ap
);
741 fprintf(stderr
, "%s", buf2
);
743 fprintf(stderr
, ": %s\n", strerror(errornum
));
745 fprintf(stderr
, "\n");
754 int getline(char **line
, size_t * length
, FILE * stream
)
760 tmpline
= fgetln(stream
, &len
);
764 fgets(tmpline
, sizeof(tmpline
), stream
);
765 len
= strlen(tmpline
);
770 *line
= malloc(len
+ 1);
773 if (*length
< len
+ 1) {
774 *line
= realloc(*line
, len
+ 1);
779 memcpy(*line
, tmpline
, len
);
785 #ifndef HAVE_UNSETENV
786 int unsetenv(const char *name
)
791 for (i
= 0; environ
[i
]; i
++)
792 if (!strncmp(name
, environ
[i
], len
))
793 if (environ
[i
][len
] == '=')
796 for (; environ
[i
] && environ
[i
+ 1]; i
++)
797 environ
[i
] = environ
[i
+ 1];
804 int setenv(const char *name
, const char *value
, int overwrite
)
810 if (getenv(name
) != NULL
)
813 newenv
= malloc(strlen(name
) + 1 + strlen(value
) + 1);
818 strcat(newenv
, name
);
820 strcat(newenv
, value
);
822 ret
= putenv(newenv
);