Windows support

David Woodhouse dwmw2 at infradead.org
Mon Feb 10 11:28:11 EST 2014


I've now managed to get this actually passing packets, albeit
sporadically.

Nikos, I wonder if GnuTLS should be accepting EWOULDBLOCK on a read from
a non-blocking socket and treating it the same as EAGAIN? See
http://git.infradead.org/users/dwmw2/openconnect.git/commitdiff/b5df97e74b

I've committed the code to find and open the tun device (using the
latest one from OpenVPN, which does actually support tun mode).

What I haven't committed is anything to actually read/write the tun
device. That's in the patch below, but it's only barely function. The
problem is that Windows is crap and you can't just open the tun device,
get a file descriptor for it, and select() on that. We're probably going
to have to do the reads from the tun device in a thread and then wake
the main thread (perhaps via a socketpair).

The alternative is to revamp the whole of the event processing to allow
us to make it work with real Windows events, and I think that's just a
step too far.

So this patch works, except that it keeps blocking on reading from the
tun device when there isn't a packet to be read. I've only tested it
with Legacy IP, not IPv6.

The other issue is that I haven't worked out how to configure the
device. The 'netsh' command lines that vpnc and openvpn attempt to use
are failing here with a confusing 'Element not found' error. I went
through the GUI to *manually* configure the device with the IP addresses
for my test connection, but we need to find a correct fix.

diff --git a/tun.c b/tun.c
index 1fcb19f..5ad0a96 100644
--- a/tun.c
+++ b/tun.c
@@ -723,8 +723,8 @@ int tun_mainloop(struct openconnect_info *vpninfo, int *timeout)
 		prefix_size = sizeof(int);
 #endif
 
-	if (FD_ISSET(vpninfo->tun_fd, &vpninfo->select_rfds)) {
-		while (1) {
+	if (1 || FD_ISSET(vpninfo->tun_fd, &vpninfo->select_rfds)) {
+		while (!work_done) {
 			int len = vpninfo->ip_info.mtu;
 
 			if (!out_pkt) {
@@ -734,8 +734,23 @@ int tun_mainloop(struct openconnect_info *vpninfo, int *timeout)
 					break;
 				}
 			}
-
+#ifdef _WIN32
+			{ DWORD got;
+				printf("reading...\n");
+				if (!ReadFile(vpninfo->tun_fh, out_pkt->data - prefix_size, len + prefix_size, &got, NULL)) {
+					DWORD err = GetLastError();
+					vpn_progress(vpninfo, PRG_ERR,
+					     _("Failed to read from to TAP device: %lx\n"), err);
+					break;
+				}
+				else printf("got %d: %02x %02x %02x %02x %02x %02x %02x %02x\n", got,
+					    out_pkt->data[0], out_pkt->data[1], out_pkt->data[2], out_pkt->data[3],
+					    out_pkt->data[4], out_pkt->data[5], out_pkt->data[6], out_pkt->data[7]);
+				len = got;
+			}
+#else
 			len = read(vpninfo->tun_fd, out_pkt->data - prefix_size, len + prefix_size);
+#endif
 			if (len <= prefix_size)
 				break;
 			out_pkt->len = len - prefix_size;
@@ -794,7 +809,19 @@ int tun_mainloop(struct openconnect_info *vpninfo, int *timeout)
 		}
 #endif
 		vpninfo->incoming_queue = this->next;
+#ifdef _WIN32
+		{
+			DWORD wrote;
 
+			if (!WriteFile(vpninfo->tun_fh, data, len, &wrote, NULL)) {
+				DWORD err = GetLastError();
+
+				vpn_progress(vpninfo, PRG_ERR,
+					     _("Failed to write to TAP device: %lx\n"), err);
+			}
+			else printf("wrote %d\n", wrote);
+		}
+#else
 		if (write(vpninfo->tun_fd, data, len) < 0) {
 			/* Handle death of "script" socket */
 			if (vpninfo->script_tun && errno == ENOTCONN) {
@@ -805,6 +832,7 @@ int tun_mainloop(struct openconnect_info *vpninfo, int *timeout)
 				     _("Failed to write incoming packet: %s\n"),
 				     strerror(errno));
 		}
+#endif
 		free(this);
 	}
 	/* Work is not done if we just got rid of packets off the queue */


-- 
dwmw2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 5745 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/openconnect-devel/attachments/20140210/2674fb05/attachment.bin>


More information about the openconnect-devel mailing list