[Openvpn-devel] [PATCH 2/4] Add tap driver initialization and ifconfig for AIX.

2014-06-10 Thread Gert Doering
From: Gert Doering 

AIX is special... ifconfig only works if it can add the data to
the ODM right away, so setup a local enviromnment set that has
"ODMDIR=/etc/objrepos" in it (hard-coded, nobody changes that).

Only --dev tap or --dev tapNN are supported right now.  AIX has no
tun driver (so tun mode would need to dynamically add/remove ethernet
headers to/from AIX).

Signed-off-by: Gert Doering 
---
 src/openvpn/tun.c |  170 +
 1 files changed, 170 insertions(+), 0 deletions(-)

diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index 482f640..25d5473 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -1194,6 +1194,43 @@ do_ifconfig (struct tuntap *tt,
  openvpn_execve_check (, es, S_FATAL, "FreeBSD ifconfig inet6 
failed");
}

+#elif defined(TARGET_AIX)
+  {
+   /* AIX ifconfig will complain if it can't find ODM path in env */
+   struct env_set *aix_es = env_set_create (NULL);
+   env_set_add( aix_es, "ODMDIR=/etc/objrepos" );
+
+   if (tun)
+ msg(M_FATAL, "no tun support on AIX (canthappen)");
+
+   /* example: ifconfig tap0 172.30.1.1 netmask 255.255.254.0 up */
+   argv_printf (,
+"%s %s %s netmask %s mtu %d up",
+   IFCONFIG_PATH,
+   actual,
+   ifconfig_local,
+   ifconfig_remote_netmask,
+   tun_mtu
+   );
+
+   argv_msg (M_INFO, );
+   openvpn_execve_check (, aix_es, S_FATAL, "AIX ifconfig failed");
+   tt->did_ifconfig = true;
+
+   if ( do_ipv6 )
+ {
+   argv_printf (,
+   "%s %s inet6 %s/%d",
+   IFCONFIG_PATH,
+   actual,
+   ifconfig_ipv6_local,
+   tt->netbits_ipv6
+   );
+   argv_msg (M_INFO, );
+   openvpn_execve_check (, aix_es, S_FATAL, "AIX ifconfig inet6 
failed");
+ }
+   env_set_destroy (aix_es);
+  }
 #elif defined (WIN32)
   {
/*
@@ -2825,6 +2862,139 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
 return read (tt->fd, buf, len);
 }

+#elif defined(TARGET_AIX)
+
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, struct 
tuntap *tt)
+{
+  char tunname[256];
+  char dynamic_name[20];
+  const char *p;
+  struct argv argv;
+
+  if (tt->type == DEV_TYPE_NULL)
+{
+  open_null (tt);
+  return;
+}
+
+  if ( tt->type == DEV_TYPE_TUN)
+{
+  msg(M_FATAL, "no support for 'tun' devices on AIX" );
+}
+
+  if ( strncmp( dev, "tap", 3 ) != 0 || dev_node )
+{
+  msg(M_FATAL, "'--dev %s' and/or '--dev-node' not supported on AIX, use 
'--dev tap0', 'tap1', etc.", dev );
+}
+
+  if ( strcmp( dev, "tap" ) == 0 ) /* find first free tap dev */
+{  /* (= no /dev/tapN node) */
+  int i;
+  for (i=0; i<99; i++ )
+   {
+ openvpn_snprintf (tunname, sizeof (tunname), "/dev/tap%d", i);
+ if ( access( tunname, F_OK ) < 0 && errno == ENOENT )
+   { break; }
+   }
+  if ( i >= 99 )
+   msg( M_FATAL, "cannot find unused tap device" );
+
+  openvpn_snprintf( dynamic_name, sizeof(dynamic_name), "tap%d", i );
+  dev = dynamic_name;
+}
+  else /* name given, sanity check */
+{
+  /* ensure that dev name is "tap+" *only* */
+  p = [3];
+  while( isdigit(*p) ) p++;
+  if ( *p != '\0' )
+   msg( M_FATAL, "TAP device name must be '--dev tap'" );
+
+  openvpn_snprintf (tunname, sizeof (tunname), "/dev/%s", dev);
+}
+
+  /* pre-existing device? 
+   */
+  if ( access( tunname, F_OK ) < 0 && errno == ENOENT )
+{
+
+  /* tunnel device must be created with 'ifconfig tapN create'
+   */
+  struct env_set *es = env_set_create (NULL);
+  argv_init ();
+  argv_printf (, "%s %s create", IFCONFIG_PATH, dev);
+  argv_msg (M_INFO, );
+  env_set_add( es, "ODMDIR=/etc/objrepos" );
+  openvpn_execve_check (, es, S_FATAL, "AIX 'create tun interface' 
failed");
+  env_set_destroy (es);
+}
+  else
+{
+  /* we didn't make it, we're not going to break it */
+  tt->persistent_if = TRUE;
+}
+
+  if ((tt->fd = open (tunname, O_RDWR)) < 0)
+{
+  msg (M_ERR, "Cannot open TAP device '%s'", tunname);
+}
+
+  set_nonblock (tt->fd);
+  set_cloexec (tt->fd); /* don't pass fd to scripts */
+  msg (M_INFO, "TUN/TAP device %s opened", tunname);
+
+  /* tt->actual_name is passed to up and down scripts and used as the ifconfig 
dev name */
+  tt->actual_name = string_alloc(dev, NULL);
+}
+
+/* tap devices need to be manually destroyed on AIX
+ */
+void
+close_tun (struct tuntap* 

[Openvpn-devel] [PATCH 1/4] Recognize AIX, define TARGET_AIX

2014-06-10 Thread Gert Doering
From: Gert Doering 

force "have_tap_header=yes", as configure won't like AIX headers otherwise
(no tun related headers, just ).

force ROUTE to be "/usr/sbin/route" - not executable by non-root users, so
configure testing for executables will not find it

force "ac_cv_header_net_if_h=no", because AIX'  pulls in AIX'
, which #defines ROUTE_H, disabling our "route.h"... (and
we don't need  on AIX anyway)

Signed-off-by: Gert Doering 
---
 configure.ac |7 +++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/configure.ac b/configure.ac
index ea35d73..fe278e1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -342,6 +342,13 @@ case "$host" in
AC_DEFINE([TARGET_DRAGONFLY], [1], [Are we running on 
DragonFlyBSD?])
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["D"], [Target prefix])
;;
+   *-aix*)
+   AC_DEFINE([TARGET_AIX], [1], [Are we running AIX?])
+   AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["A"], [Target prefix])
+   ROUTE="/usr/sbin/route"
+   have_tap_header="yes"
+   ac_cv_header_net_if_h="no"  # exists, but breaks things
+   ;;
*)
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["X"], [Target prefix])
have_tap_header="yes"
-- 
1.6.4




[Openvpn-devel] [PATCH 3/4] implement adding/deleting routes on AIX, for IPv4 and IPv6

2014-06-10 Thread Gert Doering
From: Gert Doering 

AIX only has TAP interfaces, so always use gateway address as next hop,
not interface name.

AIX route works much more reliable if passed netbits than netmask - do so
(introducing a new helper function netmask_to_netbits2())
---
 src/openvpn/route.c |   60 +++
 1 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/src/openvpn/route.c b/src/openvpn/route.c
index 5531eda..5428e76 100644
--- a/src/openvpn/route.c
+++ b/src/openvpn/route.c
@@ -1482,6 +1482,17 @@ add_route (struct route_ipv4 *r,
   argv_msg (D_ROUTE, );
   status = openvpn_execve_check (, es, 0, "ERROR: OpenBSD/NetBSD route 
add command failed");

+#elif defined(TARGET_AIX)
+
+  {
+  int netbits = netmask_to_netbits2(r->netmask);
+  argv_printf (, "%s add -net %s/%d %s",
+   ROUTE_PATH,
+   network, netbits, gateway);
+  argv_msg (D_ROUTE, );
+  status = openvpn_execve_check (, es, 0, "ERROR: AIX route add command 
failed");
+  }
+
 #else
   msg (M_FATAL, "Sorry, but I don't know how to do 'route' commands on this 
operating system.  Try putting your routes in a --route-up script");
 #endif
@@ -1701,6 +1712,14 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct 
tuntap *tt, unsigned int fla
   argv_msg (D_ROUTE, );
   status = openvpn_execve_check (, es, 0, "ERROR: NetBSD route add -inet6 
command failed");

+#elif defined(TARGET_AIX)
+
+  argv_printf (, "%s add -inet6 %s/%d %s",
+   ROUTE_PATH,
+   network, r6->netbits, gateway);
+  argv_msg (D_ROUTE, );
+  status = openvpn_execve_check (, es, 0, "ERROR: AIX route add command 
failed");
+
 #else
   msg (M_FATAL, "Sorry, but I don't know how to do 'route ipv6' commands on 
this operating system.  Try putting your routes in a --route-up script");
 #endif
@@ -1859,8 +1878,21 @@ delete_route (struct route_ipv4 *r,

   argv_msg (D_ROUTE, );
   openvpn_execve_check (, es, 0, "ERROR: OpenBSD/NetBSD route delete 
command failed");
+
 #elif defined(TARGET_ANDROID)
   msg (M_NONFATAL, "Sorry, deleting routes on Android is not possible. The 
VpnService API allows routes to be set on connect only.");
+
+#elif defined(TARGET_AIX)
+
+  {
+  int netbits = netmask_to_netbits2(r->netmask);
+  argv_printf (, "%s delete -net %s/%d %s",
+   ROUTE_PATH,
+   network, netbits, gateway);
+  argv_msg (D_ROUTE, );
+  openvpn_execve_check (, es, 0, "ERROR: AIX route delete command 
failed");
+  }
+
 #else
   msg (M_FATAL, "Sorry, but I don't know how to do 'route' commands on this 
operating system.  Try putting your routes in a --route-up script");
 #endif
@@ -2031,6 +2063,14 @@ delete_route_ipv6 (const struct route_ipv6 *r6, const 
struct tuntap *tt, unsigne
   argv_msg (D_ROUTE, );
   openvpn_execve_check (, es, 0, "ERROR: NetBSD route delete -inet6 
command failed");

+#elif defined(TARGET_AIX)
+
+  argv_printf (, "%s delete -inet6 %s/%d %s",
+   ROUTE_PATH,
+   network, r6->netbits, gateway);
+  argv_msg (D_ROUTE, );
+  openvpn_execve_check (, es, 0, "ERROR: AIX route add command failed");
+
 #else
   msg (M_FATAL, "Sorry, but I don't know how to do 'route ipv6' commands on 
this operating system.  Try putting your routes in a --route-down script");
 #endif
@@ -2868,6 +2908,26 @@ netmask_to_netbits (const in_addr_t network, const 
in_addr_t netmask, int *netbi
   return false;
 }

+/* similar to netmask_to_netbits(), but don't mess with base address
+ * etc., just convert to netbits - non-mappable masks are returned as "-1"
+ */
+int netmask_to_netbits2 (in_addr_t netmask)
+{
+  int i;
+  const int addrlen = sizeof (in_addr_t) * 8;
+
+  for (i = 0; i <= addrlen; ++i)
+{
+  in_addr_t mask = netbits_to_netmask (i);
+  if (mask == netmask)
+   {
+ return i;
+   }
+}
+  return -1;
+}
+
+
 /*
  * get_bypass_addresses() is used by the redirect-gateway bypass-x
  * functions to build a route bypass to selected DHCP/DNS servers,
-- 
1.6.4




[Openvpn-devel] OpenVPN port to AIX

2014-06-10 Thread Gert Doering
Hi,

the following four patches port OpenVPN git/master to AIX.  It might not
be the most asked-for platform in the world, but since it finally grew a
tap driver, it can be useful, so here it is :-)

Drawbacks today:
  - AIX has no tun driver, so only --dev tap is supported
  - IPv4 ICMP packets are never fragmented, so t_client fails for IPv4
ping with 3000 bytes (while IPv6 works!)

gert




[Openvpn-devel] Rekey and Defer sample plugin

2014-06-10 Thread Lev Stipakov
Hello,

I'm facing a problem with "defer" sample plugin and rekeying.

I use plugin from
https://github.com/OpenVPN/openvpn/tree/master/sample/sample-plugins/defer.

Relevant part of openvpn config:

> auth-user-pass-optional
> setenv test_deferred_auth 2
> plugin /etc/openvpn/simple.so
> reneg-sec 20

Everything works fine, plugin writes into auth control file in 2 secs
and client got authenticated. When rekeying happends, plugin got
called and writes again to auth control file, however after that
connection breaks.

Part of OpenVPN log:

OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY
DEFER u='' p='' acf='/tmp/openvpn_acf_8ec7b1fb155ede01c8bae22c6e4ad4ea.tmp'
( sleep 2 ; echo AUTH
/tmp/openvpn_acf_8ec7b1fb155ede01c8bae22c6e4ad4ea.tmp 2 ; echo 1
>/tmp/openvpn_acf_8ec7b1fb155ede01c8bae22c6e4ad4ea.tmp ) &
Tue Jun 10 13:25:50 2014 us=851659
588b4d7d-f8ec-4397-8156-43ed232c2dd8/10.64.1.101:1194 PLUGIN_CALL:
POST /etc/openvpn/simple.so/PLUGIN_AUTH_USER_PASS_VERIFY status=2
Tue Jun 10 13:25:50 2014 us=851680
588b4d7d-f8ec-4397-8156-43ed232c2dd8/10.64.1.101:1194 TLS:
Username/Password authentication deferred for username ''
OPENVPN_PLUGIN_TLS_FINAL
Tue Jun 10 13:25:50 2014 us=851695
588b4d7d-f8ec-4397-8156-43ed232c2dd8/10.64.1.101:1194 PLUGIN_CALL:
POST /etc/openvpn/simple.so/PLUGIN_TLS_FINAL status=0
Tue Jun 10 13:25:50 2014 us=851842
588b4d7d-f8ec-4397-8156-43ed232c2dd8/10.64.1.101:1194 Data Channel
Encrypt: Cipher 'BF-CBC' initialized with 128 bit key
Tue Jun 10 13:25:50 2014 us=851850
588b4d7d-f8ec-4397-8156-43ed232c2dd8/10.64.1.101:1194 Data Channel
Encrypt: Using 160 bit message hash 'SHA1' for HMAC authentication
Tue Jun 10 13:25:50 2014 us=851894
588b4d7d-f8ec-4397-8156-43ed232c2dd8/10.64.1.101:1194 Data Channel
Decrypt: Cipher 'BF-CBC' initialized with 128 bit key
Tue Jun 10 13:25:50 2014 us=851902
588b4d7d-f8ec-4397-8156-43ed232c2dd8/10.64.1.101:1194 Data Channel
Decrypt: Using 160 bit message hash 'SHA1' for HMAC authentication
Tue Jun 10 13:25:50 2014 us=853273
588b4d7d-f8ec-4397-8156-43ed232c2dd8/10.64.1.101:1194 Control Channel:
TLSv1, cipher TLSv1/SSLv3 DHE-RSA-AES256-SHA, 2048 bit RSA
Tue Jun 10 13:25:51 2014 us=238477
588b4d7d-f8ec-4397-8156-43ed232c2dd8/10.64.1.101:1194 TLS Error:
local/remote TLS keys are out of sync: [AF_INET]10.64.1.101:1194 [1]

and after that lots of "TLS keys are out of sync".

Is it kind of a bug in OpenVPN/sample plugin or am I missing something
in configuration? Anything can be done (maybe in OpenVPN code) to make
it work?

-- 
-Lev