From 048094fa587dbb0bef8ce1443936528e3912eb2e Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Sun, 13 May 2012 22:51:52 +0200 Subject: Implement the required ipv6 changes. GUI part is still incomplete --- openvpn/src/openvpn/route.c | 9 +++++ openvpn/src/openvpn/tun.c | 44 +++++++++++++++++----- res/menu/import_menu.xml | 2 +- res/values/strings.xml | 6 ++- src/de/blinkt/openvpn/ConfigParser.java | 8 +++- src/de/blinkt/openvpn/OpenVpnManagementThread.java | 5 +++ src/de/blinkt/openvpn/OpenVpnService.java | 40 ++++++++++++++++++-- 7 files changed, 97 insertions(+), 17 deletions(-) diff --git a/openvpn/src/openvpn/route.c b/openvpn/src/openvpn/route.c index 99674e29..7c02d6f5 100644 --- a/openvpn/src/openvpn/route.c +++ b/openvpn/src/openvpn/route.c @@ -1608,6 +1608,15 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla argv_msg (D_ROUTE, &argv); status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 add command failed"); +#elif defined (TARGET_ANDROID) + struct user_pass up; + struct buffer out = alloc_buf_gc (64, &gc); + + buf_printf (&out, "%s/%d", network, r6->netbits); + + strcpy(up.username, buf_bptr(&out)); + management_query_user_pass(management, &up , "ROUTE6", GET_USER_PASS_NEED_OK,(void*) 0); + #elif defined (WIN32) /* netsh interface ipv6 add route 2001:db8::/32 MyTunDevice */ diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c index 158cd61b..ab83d7b8 100644 --- a/openvpn/src/openvpn/tun.c +++ b/openvpn/src/openvpn/tun.c @@ -771,14 +771,22 @@ do_ifconfig (struct tuntap *tt, #endif /*ENABLE_IPROUTE*/ #elif defined(TARGET_ANDROID) + + if (do_ipv6) { + struct user_pass up6; + struct buffer out6 = alloc_buf_gc (64, &gc); + buf_printf (&out6, "%s/%d", ifconfig_ipv6_local,tt->netbits_ipv6); + strcpy(up6.username, buf_bptr(&out6)); + management_query_user_pass(management, &up6 , "IFCONFIG6", GET_USER_PASS_NEED_OK,(void*) 0); + } + struct user_pass up; struct buffer out = alloc_buf_gc (64, &gc); - buf_printf (&out, "%s %s %d", ifconfig_local, ifconfig_remote_netmask, tun_mtu); - strcpy(up.username, buf_bptr(&out)); management_query_user_pass(management, &up , "IFCONFIG", GET_USER_PASS_NEED_OK,(void*) 0); - + + #elif defined(TARGET_SOLARIS) @@ -1377,8 +1385,6 @@ close_tun_generic (struct tuntap *tt) #endif -#if defined(TARGET_LINUX) || defined(TARGET_ANDROID) - #if defined (TARGET_ANDROID) void open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt) @@ -1409,8 +1415,29 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu gc_free (&gc); } -#else +void +close_tun (struct tuntap *tt) +{ + if (tt) + { + close_tun_generic (tt); + free (tt); + } +} +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(TARGET_LINUX) #ifdef HAVE_LINUX_IF_TUN_H /* New driver support */ #ifndef HAVE_LINUX_SOCKIOS_H @@ -1455,7 +1482,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu if (!tt->ipv6) ifr.ifr_flags = IFF_NO_PI; -#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN) && !defined(TARGET_ANDROID) +#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN) ifr.ifr_flags |= IFF_ONE_QUEUE; #endif @@ -1545,7 +1572,6 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu } #endif /* HAVE_LINUX_IF_TUN_H */ -#endif /* TARGET_ANDROID */ #ifdef ENABLE_FEATURE_TUN_PERSIST @@ -1698,7 +1724,7 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len) ret = readv(tt->fd, vect, 2); return(ret - sizeof(pi)); } - else + else return read (tt->fd, buf, len); } diff --git a/res/menu/import_menu.xml b/res/menu/import_menu.xml index 27498da3..c29db10e 100644 --- a/res/menu/import_menu.xml +++ b/res/menu/import_menu.xml @@ -6,7 +6,7 @@ android:icon="@android:drawable/ic_menu_save" android:showAsAction="ifRoom|withText" android:title="@string/add_profile" - android:titleCondensed="@string/clear"/> + android:titleCondensed="@string/import_vpn"/> info Show connection details Last interface configuration from Openvpn: - Local IP: %1$s/%2$d MTU: %3$d + Local IPv4: %1$s/%2$d IPv6: %3$s MTU: %4$d DNS Server: %s DNS Domain: %s Routes: %s + Routes Ipv6: %s Got interface information %1$s and %2$s, assuming second address is peer address of remote. Using /32 netmask for local IP. Cannot make sense of %1$s and %2$s as IP route with CIDR netmask, using /32 as netmask. Corrected route %1$s/%2$s to %3$s/%2$s @@ -212,5 +213,6 @@ Please not that the config importer is an experimental feature. Import configuration file Security considerations - "As openvpn is security sensitive a few notes about security are sensible. All data on the sdcard is inherently unsecure. Every app can read it (for example this program requires no special sd card rights). The data of this application can only be read by the application itself. By using the import option for cacert/cert/key in the file dialog the data is stored in the vpn profile. The vpn profiles are only accessable by this application. (Do not forget to delte the copies on the sdcard afterwards). Even though accessible only by this application the data is stil unecrypted. By rooting the telephone or other exploits it may be possible to retrieve the data. Saved passwords are stored in plain text as well. For pkcs12 files it is highly recommended that you import them into the android keystore." + "As openvpn is security sensitive a few notes about security are sensible. All data on the sdcard is inherently unsecure. Every app can read it (for example this program requires no special sd card rights). The data of this application can only be read by the application itself. By using the import option for cacert/cert/key in the file dialog the data is stored in the vpn profile. The vpn profiles are only accessable by this application. (Do not forget to delte the copies on the sdcard afterwards). Even though accessible only by this application the data is stil unecrypted. By rooting the telephone or other exploits it may be possible to retrieve the data. Saved passwords are stored in plain text as well. For pkcs12 files it is highly recommended that you import them into the android keystore." + Import diff --git a/src/de/blinkt/openvpn/ConfigParser.java b/src/de/blinkt/openvpn/ConfigParser.java index 1b37c0a8..5e054c6d 100644 --- a/src/de/blinkt/openvpn/ConfigParser.java +++ b/src/de/blinkt/openvpn/ConfigParser.java @@ -337,7 +337,7 @@ public class ConfigParser { } - Vector> dhcpoptions = getAllOption("dhcp-options", 2, 2); + Vector> dhcpoptions = getAllOption("dhcp-option", 2, 2); if(dhcpoptions!=null) { for(Vector dhcpoption:dhcpoptions) { String type=dhcpoption.get(1); @@ -354,6 +354,12 @@ public class ConfigParser { } } + Vector ifconfig = getOption("ifconfig", 2, 2); + if(ifconfig!=null) { + CIDRIP cidr = new CIDRIP(ifconfig.get(1), ifconfig.get(2)); + np.mIPv4Address=cidr.toString(); + } + if(getOption("remote-random-hostname", 0, 0)!=null) np.mUseRandomHostname=true; diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java index bc2b0e13..ce6f718f 100644 --- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java +++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java @@ -192,10 +192,15 @@ public class OpenVpnManagementThread implements Runnable { } else if (needed.equals("ROUTE")) { String[] routeparts = extra.split(" "); mOpenVPNService.addRoute(routeparts[0], routeparts[1]); + } else if (needed.equals("ROUTE6")) { + mOpenVPNService.addRoutev6(extra); } else if (needed.equals("IFCONFIG")) { String[] ifconfigparts = extra.split(" "); int mtu = Integer.parseInt(ifconfigparts[2]); mOpenVPNService.setLocalIP(ifconfigparts[0], ifconfigparts[1],mtu); + } else if (needed.equals("IFCONFIG6")) { + mOpenVPNService.setLocalIPv6(extra); + } else if (needed.equals("OPENTUN")) { if(sendTunFD(needed,extra)) return; diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java index 8a884fcc..48ab03b6 100644 --- a/src/de/blinkt/openvpn/OpenVpnService.java +++ b/src/de/blinkt/openvpn/OpenVpnService.java @@ -45,6 +45,7 @@ public class OpenVpnService extends VpnService implements Handler.Callback { private String mDomain=null; private Vector mRoutes=new Vector(); + private Vector mRoutesv6=new Vector(); private CIDRIP mLocalIP=null; @@ -52,6 +53,7 @@ public class OpenVpnService extends VpnService implements Handler.Callback { private Thread mSocketManagerThread; private int mMtu; + private String mLocalIPv6=null; @@ -201,12 +203,20 @@ public class OpenVpnService extends VpnService implements Handler.Callback { public ParcelFileDescriptor openTun() { Builder builder = new Builder(); - if(mLocalIP==null) { + if(mLocalIP==null && mLocalIPv6==null) { OpenVPN.logMessage(0, "", getString(R.string.opentun_no_ipaddr)); return null; } - builder.addAddress(mLocalIP.mIp, mLocalIP.len); + if(mLocalIP!=null) { + builder.addAddress(mLocalIP.mIp, mLocalIP.len); + } + + if(mLocalIPv6!=null) { + String[] ipv6parts = mLocalIPv6.split("/"); + builder.addAddress(ipv6parts[0],Integer.parseInt(ipv6parts[1])); + } + for (String dns : mDnslist ) { builder.addDnsServer(dns); @@ -223,16 +233,26 @@ public class OpenVpnService extends VpnService implements Handler.Callback { } } + for(String v6route:mRoutesv6) { + try { + String[] v6parts = v6route.split("/"); + builder.addRoute(v6parts[0],Integer.parseInt(v6parts[1])); + } catch (IllegalArgumentException ia) { + OpenVPN.logMessage(0, "", getString(R.string.route_rejected) + v6route + " " + ia.getLocalizedMessage()); + } + } + if(mDomain!=null) builder.addSearchDomain(mDomain); - String bconfig[] = new String[5]; + String bconfig[] = new String[6]; bconfig[0]= getString(R.string.last_openvpn_tun_config); - bconfig[1] = String.format(getString(R.string.local_ip_info,mLocalIP.mIp,mLocalIP.len,mMtu)); + bconfig[1] = String.format(getString(R.string.local_ip_info,mLocalIP.mIp,mLocalIP.len,mLocalIPv6, mMtu)); bconfig[2] = String.format(getString(R.string.dns_server_info, joinString(mDnslist))); bconfig[3] = String.format(getString(R.string.dns_domain_info, mDomain)); bconfig[4] = String.format(getString(R.string.routes_info, joinString(mRoutes))); + bconfig[5] = String.format(getString(R.string.routes_info6, joinString(mRoutesv6))); builder.setSession(mProfile.mName + " - " + mLocalIP); @@ -242,7 +262,9 @@ public class OpenVpnService extends VpnService implements Handler.Callback { // Reset information mDnslist.clear(); mRoutes.clear(); + mRoutesv6.clear(); mLocalIP=null; + mLocalIPv6=null; // Let the configure Button show the Log Intent intent = new Intent(getBaseContext(),LogWindow.class); @@ -301,6 +323,10 @@ public class OpenVpnService extends VpnService implements Handler.Callback { mRoutes.add(route); } + + public void addRoutev6(String extra) { + mRoutesv6.add(extra); + } public void setLocalIP(String local, String netmask,int mtu) { @@ -313,7 +339,13 @@ public class OpenVpnService extends VpnService implements Handler.Callback { } + public void setLocalIPv6(String ipv6addr) { + mLocalIPv6 = ipv6addr; + } + + public Handler getHandler() { return mHandler; } + } -- cgit v1.2.3