OpenVPN port to AIX
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
PATCH 1/4 Recognize AIX, define TARGET_AIX
From: Gert Doering <[email protected]...>
force "have_tap_header=yes", as configure won't like AIX headers otherwise (no tun related headers, just <net/if_tap.h>).
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' <net/if.h> pulls in AIX' <net/route.h>, which #defines ROUTE_H, disabling our "route.h"... (and we don't need <net/if.h> on AIX anyway)
--- configure.ac | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
configure.ac +7 -0
@@ -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"
Signature · 1 line
1.6.4
PATCH 2/4 Add tap driver initialization and ifconfig for AIX.
From: Gert Doering <[email protected]...>
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).
--- src/openvpn/tun.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 170 insertions(+), 0 deletions(-)
src/openvpn/tun.c +170 -0
@@ -1194,6 +1194,43 @@ do_ifconfig (struct tuntap *tt,openvpn_execve_check (&argv, 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 (&argv, +"%s %s %s netmask %s mtu %d up" , +IFCONFIG_PATH , + actual, + ifconfig_local, + ifconfig_remote_netmask, + tun_mtu + ); + +argv_msg (M_INFO , &argv); +openvpn_execve_check (&argv, aix_es,S_FATAL ,"AIX ifconfig failed" ); + tt->did_ifconfig = true; + +if ( do_ipv6 ) + { +argv_printf (&argv, +"%s %s inet6 %s/%d" , +IFCONFIG_PATH , + actual, + ifconfig_ipv6_local, + tt->netbits_ipv6 + ); +argv_msg (M_INFO , &argv); +openvpn_execve_check (&argv, 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+<digits>" *only* */ + p = &dev[3 ]; +while (isdigit (*p) ) p++; +if ( *p !='\0' ) +msg (M_FATAL ,"TAP device name must be '--dev tapNNNN'" ); + +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); +argv_printf (&argv,"%s %s create" ,IFCONFIG_PATH , dev); +argv_msg (M_INFO , &argv); +env_set_add ( es,"ODMDIR=/etc/objrepos" ); +openvpn_execve_check (&argv, 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 * tt) +{ +struct gc_arena gc =gc_new (); +struct argv argv; +struct env_set *es =env_set_create (NULL ); + +if (!tt)return ; + +/* persistent devices need IP address unconfig, others need destroyal +*/ +argv_init (&argv); + +if (tt->persistent_if) + { +argv_printf (&argv,"%s %s 0.0.0.0 down" , +IFCONFIG_PATH , tt->actual_name); + } +else + { +argv_printf (&argv,"%s %s destroy" , +IFCONFIG_PATH , tt->actual_name); + } + +close_tun_generic (tt); +argv_msg (M_INFO , &argv); +env_set_add ( es,"ODMDIR=/etc/objrepos" ); +openvpn_execve_check (&argv, es,0 ,"AIX 'destroy tap interface' failed (non-critical)" ); + +free (tt); +env_set_destroy (es); +} + +int +write_tun (struct tuntap * tt,uint8_t *buf,int len) +{ +return write (tt->fd, buf, len); +} + +int +read_tun (struct tuntap * tt,uint8_t *buf,int len) +{ +return read (tt->fd, buf, len); +} +#elif defined(WIN32 )int
Signature · 1 line
1.6.4
PATCH 3/4 implement adding/deleting routes on AIX, for IPv4 and IPv6
From: Gert Doering <[email protected]...>
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(-)
src/openvpn/route.c +60 -0
@@ -1482,6 +1482,17 @@ add_route (struct route_ipv4 *r,argv_msg (D_ROUTE , &argv); status =openvpn_execve_check (&argv, es,0 ,"ERROR: OpenBSD/NetBSD route add command failed" ); +#elif defined(TARGET_AIX ) + + { +int netbits =netmask_to_netbits2 (r->netmask); +argv_printf (&argv,"%s add -net %s/%d %s" , +ROUTE_PATH , + network, netbits, gateway); +argv_msg (D_ROUTE , &argv); + status =openvpn_execve_check (&argv, 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 flaargv_msg (D_ROUTE , &argv); status =openvpn_execve_check (&argv, es,0 ,"ERROR: NetBSD route add -inet6 command failed" ); +#elif defined(TARGET_AIX ) + +argv_printf (&argv,"%s add -inet6 %s/%d %s" , +ROUTE_PATH , + network, r6->netbits, gateway); +argv_msg (D_ROUTE , &argv); + status =openvpn_execve_check (&argv, 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 , &argv);openvpn_execve_check (&argv, 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 (&argv,"%s delete -net %s/%d %s" , +ROUTE_PATH , + network, netbits, gateway); +argv_msg (D_ROUTE , &argv); +openvpn_execve_check (&argv, 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, unsigneargv_msg (D_ROUTE , &argv);openvpn_execve_check (&argv, es,0 ,"ERROR: NetBSD route delete -inet6 command failed" ); +#elif defined(TARGET_AIX ) + +argv_printf (&argv,"%s delete -inet6 %s/%d %s" , +ROUTE_PATH , + network, r6->netbits, gateway); +argv_msg (D_ROUTE , &argv); +openvpn_execve_check (&argv, 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 *netbireturn 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,
Signature · 1 line
1.6.4
PATCH 4/4 Make t_client.sh work on AIX.
From: Gert Doering <[email protected]...>
Teach it how to run ifconfig/route on AIX to have meaningful results.
--- tests/t_client.sh.in | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
tests/t_client.sh.in +6 -0
@@ -134,6 +134,12 @@ get_ifconfig_route() @NETSTAT@ -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$6 }' return ;; + AIX) + echo "-- AIX --" + @IFCONFIG@ -a | egrep "(flags=|inet)" + @NETSTAT@ -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$6 }' + return + ;; esac echo "get_ifconfig_route(): no idea how to get info on your OS. FAIL." >&2
Signature · 1 line
1.6.4
Re: [Openvpn-devel] [PATCH 4/4] Make t_client.sh work on AIX.
Am 10.06.14 16:04, schrieb Gert Doering:
Quoted 4 lines
From: Gert Doering <[email protected]...>
Teach it how to run ifconfig/route on AIX to have meaningful results.
ACK on the basis of "cannot test, but looks sane and does not touch other platforms"
Arne
[Openvpn-devel] [PATCH applied] Re: Make t_client.sh work on AIX.
In reply to Gert DoeringYour patch has been applied to the master branch.
commit a637016ea3a6b49e3c792ca335f50eb32a182093
Author: Gert Doering Date: Tue Jun 10 16:04:33 2014 +0200
Make t_client.sh work on AIX.
Signed-off-by: Gert Doering <[email protected]...>
Acked-by: Arne Schwabe <[email protected]...>
Message-Id: <[email protected]...>
URL: http://article.gmane.org/gmane.network.openvpn.devel/8786
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
Re: [Openvpn-devel] [PATCH 3/4] implement adding/deleting routes on AIX, for IPv4 and IPv6
In reply to Gert DoeringAm 10.06.14 16:04, schrieb Gert Doering:
Quoted 8 lines
From: Gert Doering <[email protected]...>
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())
ACK on the basis of "cannot test, but looks sane and does not touch other platforms"
Arne
[Openvpn-devel] [PATCH applied] Re: implement adding/deleting routes on AIX, for IPv4 and IPv6
In reply to Gert DoeringYour patch has been applied to the master branch.
(A followup patch will have to come, making use of count_netmask_bits(), and drop the netmask_to_netbits2() helper again)
commit b4b92ae5dca218325dfbe16992922716ea83e261
Author: Gert Doering Date: Tue Jun 10 16:04:32 2014 +0200
implement adding/deleting routes on AIX, for IPv4 and IPv6
Acked-by: Arne Schwabe <[email protected]...>
Message-Id: <[email protected]...>
URL: http://article.gmane.org/gmane.network.openvpn.devel/8785
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
Re: [Openvpn-devel] [PATCH 2/4] Add tap driver initialization and ifconfig for AIX.
In reply to Gert DoeringAm 10.06.14 16:04, schrieb Gert Doering:
Quoted 10 lines
From: Gert Doering <[email protected]...>
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).
ACK on the basis of "cannot test, but looks sane and does not touch other platforms"
Arne
[Openvpn-devel] [PATCH applied] Re: Add tap driver initialization and ifconfig for AIX.
In reply to Gert DoeringYour patch has been applied to the master branch.
commit 7e1e7b46701214f7886af6b408d6954a6621be46
Author: Gert Doering Date: Tue Jun 10 16:04:31 2014 +0200
Add tap driver initialization and ifconfig for AIX.
Signed-off-by: Gert Doering <[email protected]...>
Acked-by: Arne Schwabe <[email protected]...>
Message-Id: <[email protected]...>
URL: http://article.gmane.org/gmane.network.openvpn.devel/8788
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
Re: [Openvpn-devel] [PATCH 1/4] Recognize AIX, define TARGET_AIX
In reply to Gert DoeringAm 10.06.14 16:04, schrieb Gert Doering:
Quoted 5 lines
From: Gert Doering <[email protected]...>
force "have_tap_header=yes", as configure won't like AIX headers otherwise (no tun related headers, just <
net/if_tap.h>).
Quoted 8 lines
force ROUTE to be "
/usr/sbin/route" - not executable by non-root users, so configure testing for executables will not find itforce "ac_cv_header_net_if_h=no", because AIX' <
net/if.h> pulls in AIX' <net/route.h>, which #definesROUTE_H, disabling our "route.h"... (and we don't need <net/if.h> on AIX anyway)
ACK on the basis of "cannot test, but looks sane and does not touch other platforms"
Arne
[Openvpn-devel] [PATCH applied] Re: Recognize AIX, define TARGET_AIX
In reply to Gert DoeringYour patch has been applied to the master branch.
commit 42f13dc03c12805b994ea67fe77c9cb9dd55c10d
Author: Gert Doering Date: Tue Jun 10 16:04:30 2014 +0200
Recognize AIX, define TARGET_AIX
Signed-off-by: Gert Doering <[email protected]...>
Acked-by: Arne Schwabe <[email protected]...>
Message-Id: <[email protected]...>
URL: http://article.gmane.org/gmane.network.openvpn.devel/8787
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering