diff options
-rw-r--r-- | AndroidManifest.xml | 4 | ||||
-rw-r--r-- | res/layout/basic_settings.xml | 1 | ||||
-rw-r--r-- | res/layout/vpn_list_item.xml | 2 | ||||
-rw-r--r-- | res/menu/logmenu.xml | 19 | ||||
-rw-r--r-- | res/menu/vpn_context.xml | 3 | ||||
-rw-r--r-- | res/values/strings.xml | 12 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/LaunchVPN.java | 5 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/LogWindow.java | 7 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVPN.java | 141 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVPNThread.java | 2 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVpnManagementThread.java | 14 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVpnService.java | 73 |
12 files changed, 194 insertions, 89 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index fe250a8..75fe58d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -17,8 +17,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.blinkt.openvpn" - android:versionCode="15" - android:versionName="0.4.7" > + android:versionCode="16" + android:versionName="0.4.8" > <uses-permission android:name="android.permission.INTERNET" /> diff --git a/res/layout/basic_settings.xml b/res/layout/basic_settings.xml index e19ec14..6d4b8cc 100644 --- a/res/layout/basic_settings.xml +++ b/res/layout/basic_settings.xml @@ -168,7 +168,6 @@ android:layout_marginLeft="8dip" android:layout_marginRight="8dip" android:hint="@string/pw_query_hint" - android:inputType="textPassword" /> </LinearLayout> diff --git a/res/layout/vpn_list_item.xml b/res/layout/vpn_list_item.xml index 75da3cf..16d7d5b 100644 --- a/res/layout/vpn_list_item.xml +++ b/res/layout/vpn_list_item.xml @@ -23,7 +23,7 @@ <LinearLayout android:id="@+id/vpn_list_item_left" - android:layout_width="wrap_content" + android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="?android:attr/selectableItemBackground" diff --git a/res/menu/logmenu.xml b/res/menu/logmenu.xml index 80331c5..b8fd286 100644 --- a/res/menu/logmenu.xml +++ b/res/menu/logmenu.xml @@ -5,13 +5,18 @@ android:id="@+id/clearlog"
android:icon="@drawable/ic_menu_trash_holo_light"
android:showAsAction="ifRoom|withText"
- android:title="@string/clear_log"/>
-
- <item android:id="@+id/cancel"
+ android:title="@string/clear_log"
+ android:titleCondensed="@string/clear"/>
+ <item
+ android:id="@+id/cancel"
android:icon="@android:drawable/ic_menu_close_clear_cancel"
android:showAsAction="ifRoom|withText"
android:title="@string/cancel_connection"
- />
-
-
-</menu>
\ No newline at end of file + android:titleCondensed="@string/cancel"/>
+ <item
+ android:id="@+id/info"
+ android:icon="@android:drawable/ic_menu_info_details"
+ android:showAsAction="ifRoom|withText"
+ android:title="@string/show_connection_details"
+ android:titleCondensed="@string/info"/>
+
</menu>
\ No newline at end of file diff --git a/res/menu/vpn_context.xml b/res/menu/vpn_context.xml index 477c6a8..239f157 100644 --- a/res/menu/vpn_context.xml +++ b/res/menu/vpn_context.xml @@ -18,9 +18,8 @@ <!-- <item android:id="@+id/connect_vpn" android:alphabeticShortcut="c" - android: android:icon="@android:drawable/ic_media_play" - android:showAsAction="withText|ifRoom" + android:showAsAction="ifRoom|withText" android:title="@string/connect"/> --> </menu>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 53483b8..cf8cc5c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -115,7 +115,6 @@ <string name="custom_config_title">Enable Custom Options</string> <string name="custom_config_summary">Specify custom options. Use with care!</string> <string name="route_rejected">Route rejected by Android</string> - <string formatted="false" name="ip_not_cidr">Cannot make sense of %s and %s as IP and CIDR netmask, assuming second address is peer address of remote. Using /32 netmask for local IP.</string> <string name="cancel_connection">Disconnect</string> <string name="clear_log">clear log</string> <string name="title_cancel">Cancel Confirmation</string> @@ -156,4 +155,15 @@ <string name="tun_error_helpful">" On some custom ICS images the permission on /dev/tun might be wrong, or the tun module might be missing completly"</string> <string name="tun_open_error">Opening tun interface failed badly.</string> <string name="error">"Error: "</string> + <string name="clear">Clear</string> + <string name="info">info</string> + <string name="show_connection_details">Show connection details</string> + <string name="last_openvpn_tun_config">Last interface configuration from Openvpn:</string> + <string name="local_ip_info">Local IP: %1$s/%2$d</string> + <string name="dns_server_info">DNS Server: %s</string> + <string name="dns_domain_info">DNS Domain: %s</string> + <string name="routes_info">Routes: %s</string> + <string name="ip_not_cidr">Cannot make sense of %1$s and %2$s as local IP with CIDR netmask, assuming second address is peer address of remote. Using /32 netmask for local IP.</string> + <string name="route_not_cidr">Cannot make sense of %1$s and %2$s as IP route with CIDR netmask, using /32 as netmask.</string> + <string name="route_not_netip">Corrected route %1$s/%2$s to %3$s/%2$s</string> </resources> diff --git a/src/de/blinkt/openvpn/LaunchVPN.java b/src/de/blinkt/openvpn/LaunchVPN.java index d74834c..2e25f7a 100644 --- a/src/de/blinkt/openvpn/LaunchVPN.java +++ b/src/de/blinkt/openvpn/LaunchVPN.java @@ -29,6 +29,8 @@ import android.content.Intent; import android.net.VpnService; import android.os.Bundle; import android.os.Parcelable; +import android.text.InputType; +import android.text.method.PasswordTransformationMethod; import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.AdapterView; @@ -207,7 +209,8 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { final EditText entry = new EditText(this); entry.setSingleLine(); - entry.setInputType(EditorInfo.TYPE_TEXT_VARIATION_PASSWORD); + entry.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); + entry.setTransformationMethod(new PasswordTransformationMethod()); AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setTitle("Need " + type); diff --git a/src/de/blinkt/openvpn/LogWindow.java b/src/de/blinkt/openvpn/LogWindow.java index 001dbf1..65e8c66 100644 --- a/src/de/blinkt/openvpn/LogWindow.java +++ b/src/de/blinkt/openvpn/LogWindow.java @@ -23,6 +23,8 @@ import android.widget.TextView; import de.blinkt.openvpn.OpenVPN.LogListener; public class LogWindow extends ListActivity { + private String[] mBconfig=null; + class LogWindowListAdapter implements ListAdapter,LogListener, Callback { @@ -36,6 +38,7 @@ public class LogWindow extends ListActivity { private Vector<DataSetObserver> observers=new Vector<DataSetObserver>(); + public LogWindowListAdapter() { initLogBuffer(); @@ -159,7 +162,6 @@ public class LogWindow extends ListActivity { OpenVPN.logMessage(0,"","Log cleared."); mHandler.sendEmptyMessage(MESSAGE_CLEARLOG); } - } @@ -185,6 +187,9 @@ public class LogWindow extends ListActivity { builder.setNegativeButton(android.R.string.no, null); builder.show(); return true; + } else if(item.getItemId()==R.id.info) { + if(mBconfig==null) + OpenVPN.triggerLogBuilderConfig(); } return super.onOptionsItemSelected(item); diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java index daa2971..a5f60da 100644 --- a/src/de/blinkt/openvpn/OpenVPN.java +++ b/src/de/blinkt/openvpn/OpenVPN.java @@ -10,77 +10,79 @@ public class OpenVPN { private static final int MAXLOGENTRIES = 500; public static native int startOpenVPNThread(); public static native int startOpenVPNThreadArgs(String argv[]); - private static final String TAG = "OpenVpn"; + private static final String TAG = "OpenVpn"; + - public static LinkedList<String> logbuffer = new LinkedList<String>(); private static int counter=0; private static Vector<LogListener> logListener=new Vector<OpenVPN.LogListener>(); - + private static String[] mBconfig=null; + public interface LogListener { void newLog(String logmessage); } - static { - System.loadLibrary("crypto"); - System.loadLibrary("ssl"); - System.loadLibrary("lzo"); - System.loadLibrary("openvpn"); - } - - static void addRoute(String dest,String mask, String gw) { - Log.i("openvpn" ,"Got Routing information " + dest + " " + mask + " " + gw ); - mOpenVpnService.addRoute(dest,mask); - } - - synchronized static void logMessage(int level,String prefix, String message) - { - logbuffer.addLast(prefix + " " + message); - if(logbuffer.size()>MAXLOGENTRIES) - logbuffer.removeFirst(); - - // The garbage collector does not collect the String from native - // but kills me for logging 100 messages with too many references :( - // Force GC how and then to kill loose ends - if(counter++ % 50==0) - System.gc(); - - for (LogListener ll : logListener) { + static { + System.loadLibrary("crypto"); + System.loadLibrary("ssl"); + System.loadLibrary("lzo"); + System.loadLibrary("openvpn"); + } + + static void addRoute(String dest,String mask, String gw) { + Log.i("openvpn" ,"Got Routing information " + dest + " " + mask + " " + gw ); + mOpenVpnService.addRoute(dest,mask); + } + + synchronized static void logMessage(int level,String prefix, String message) + { + logbuffer.addLast(prefix + " " + message); + if(logbuffer.size()>MAXLOGENTRIES) + logbuffer.removeFirst(); + + // The garbage collector does not collect the String from native + // but kills me for logging 100 messages with too many references :( + // Force GC how and then to kill loose ends + if(counter++ % 50==0) { + System.gc(); + } + + for (LogListener ll : logListener) { ll.newLog(prefix + " " + message); } - - } - - synchronized static void clearLog() { - logbuffer.clear(); - } - - synchronized static void addLogListener(LogListener ll){ - logListener.add(ll); - } - - synchronized static void removeLogListener(LogListener ll) { - logListener.remove(ll); - } - - - static void addInterfaceInfo(int mtu, String local, String netmask) - { - Log.i("openvpn","Got interface info M" + mtu + " L: " + local + "NM: " + netmask); - mOpenVpnService.setLocalIP(local,netmask); - } - - static void addDns(String dns) { - Log.i("openvpn","Got DNS Server: " + dns); - mOpenVpnService.addDNS(dns); - } - - - static void addDomain(String domain) { - Log.i("openvpn","Got DNS Domain: " + domain); - mOpenVpnService.setDomain(domain); - } + + } + + synchronized static void clearLog() { + logbuffer.clear(); + } + + synchronized static void addLogListener(LogListener ll){ + logListener.add(ll); + } + + synchronized static void removeLogListener(LogListener ll) { + logListener.remove(ll); + } + + + static void addInterfaceInfo(int mtu, String local, String netmask) + { + Log.i("openvpn","Got interface info M" + mtu + " L: " + local + "NM: " + netmask); + mOpenVpnService.setLocalIP(local,netmask); + } + + static void addDns(String dns) { + Log.i("openvpn","Got DNS Server: " + dns); + mOpenVpnService.addDNS(dns); + } + + + static void addDomain(String domain) { + Log.i("openvpn","Got DNS Domain: " + domain); + mOpenVpnService.setDomain(domain); + } public static void setCallback(OpenVpnService openVpnService) { @@ -96,19 +98,32 @@ public class OpenVPN { Log.e("openvpn","Error protecting socket "+ sockfd); return p; } - + public static int openTunDevice() { Log.d(TAG,"Opening tun device"); return mOpenVpnService.openTun(); } //! Dummy method being called to force loading of JNI Libraries public static void foo() { } - + synchronized public static String[] getlogbuffer() { - + // The stoned way of java to return an array from a vector // brought to you by eclipse auto complete return (String[]) logbuffer.toArray(new String[logbuffer.size()]); } + public static void logBuilderConfig(String[] bconfig) { + mBconfig =bconfig; + } + public static void triggerLogBuilderConfig() { + if(mBconfig==null) { + logMessage(0, "", "No active interface"); + } else { + for (String item : mBconfig) { + logMessage(0, "", item); + } + } + + } } diff --git a/src/de/blinkt/openvpn/OpenVPNThread.java b/src/de/blinkt/openvpn/OpenVPNThread.java index 124179e..a5b3e5e 100644 --- a/src/de/blinkt/openvpn/OpenVPNThread.java +++ b/src/de/blinkt/openvpn/OpenVPNThread.java @@ -55,6 +55,8 @@ public class OpenVPNThread implements Runnable { mService.getHandler().sendEmptyMessage(R.string.disconnected);
+ // Not a good place to do it, but will do
+ OpenVPN.logBuilderConfig(null);
Log.i(TAG, "Exiting");
}
}
diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java index f05f58d..2421b28 100644 --- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java +++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java @@ -105,13 +105,14 @@ private static Vector<OpenVpnManagementThread> active=new Vector<OpenVpnManageme else if (cmd.equals("PASSWORD")) {
processPWCommand(argument);
} else if (cmd.equals("HOLD")) {
- managmentCommand("hold release\n");
+ managmentCommand("hold release\nlog on\n");
} else if (cmd.equals("PROTECT-FD")) {
protectFD(argument);
}
+ Log.i(TAG, "Got unrecognized command" + command);
+ } else {
+ Log.i(TAG, "Got unrecognized line from managment" + command);
}
- Log.i(TAG, "Got unrecognized command" + command);
-
}
@@ -158,10 +159,13 @@ private static Vector<OpenVpnManagementThread> active=new Vector<OpenVpnManageme }
- public static void stopOpenVPN() {
+ public static boolean stopOpenVPN() {
+ boolean sendCMD=false;
for (OpenVpnManagementThread mt: active){
mt.managmentCommand("signal SIGINT\n");
- }
+ sendCMD=true;
+ }
+ return sendCMD;
}
}
diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java index 076fe7b..b4ae411 100644 --- a/src/de/blinkt/openvpn/OpenVpnService.java +++ b/src/de/blinkt/openvpn/OpenVpnService.java @@ -17,8 +17,11 @@ package de.blinkt.openvpn; import java.io.IOException; +import java.lang.reflect.Array; import java.util.Vector; +import de.blinkt.openvpn.OpenVpnService.CIDRIP; + import android.app.PendingIntent; import android.content.Intent; import android.net.LocalSocket; @@ -83,11 +86,30 @@ public class OpenVpnService extends VpnService implements Handler.Callback { public String toString() { return String.format("%s/%d",mIp,len); } + + public boolean normalise(){ + long ip=0; + + String[] ipt = mIp.split("\\."); + + ip += Long.parseLong(ipt[0])<< 24; + ip += Integer.parseInt(ipt[1])<< 16; + ip += Integer.parseInt(ipt[2])<< 8; + ip += Integer.parseInt(ipt[3]); + + long newip = ip & (0xffffffffl << (32 -len)); + if (newip != ip){ + mIp = String.format("%d.%d.%d.%d", (newip & 0xff000000) >> 24,(newip & 0xff0000) >> 16, (newip & 0xff00) >> 8 ,newip & 0xff); + return true; + } else { + return false; + } + } } @Override public void onRevoke() { - mSocketManager.managmentCommand("signal SIGINT\n"); + OpenVpnManagementThread.stopOpenVPN(); mServiceThread=null; stopSelf(); }; @@ -128,8 +150,12 @@ public class OpenVpnService extends VpnService implements Handler.Callback { } // Stop the previous session by interrupting the thread. - if (mSocketManager != null) { - mSocketManager.managmentCommand("signal SIGINT\n"); + if(OpenVpnManagementThread.stopOpenVPN()){ + // an old was asked to exit, wait 2s + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + } } if (mServiceThread!=null) { @@ -210,13 +236,25 @@ public class OpenVpnService extends VpnService implements Handler.Callback { if(mDomain!=null) builder.addSearchDomain(mDomain); - + String bconfig[] = new String[5]; + + bconfig[0]= getString(R.string.last_openvpn_tun_config); + bconfig[1] = String.format(getString(R.string.local_ip_info,mLocalIP.mIp,mLocalIP.len)); + 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))); + + + OpenVPN.logBuilderConfig(bconfig); + mDnslist.clear(); mRoutes.clear(); builder.setSession(mProfile.mName + " - " + mLocalIP); + + // Let the configure Button show the Log Intent intent = new Intent(getBaseContext(),LogWindow.class); PendingIntent startLW = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0); @@ -233,6 +271,23 @@ public class OpenVpnService extends VpnService implements Handler.Callback { } + + // Ugly, but java has no such method + private <T> String joinString(Vector<T> vec) { + String ret = ""; + if(vec.size() > 0); + ret = vec.get(0).toString(); + for(int i=1;i < vec.size();i++) { + ret = ret + ", " + vec.get(i).toString(); + } + return ret; + } + + + + + + public void addDNS(String dns) { mDnslist.add(dns); } @@ -246,7 +301,15 @@ public class OpenVpnService extends VpnService implements Handler.Callback { public void addRoute(String dest, String mask) { - mRoutes.add(new CIDRIP(dest, mask)); + CIDRIP route = new CIDRIP(dest, mask); + if(route.len == 32 && !mask.equals("255.255.255.255")) { + OpenVPN.logMessage(0, "", String.format(getString(R.string.route_not_cidr,dest,mask))); + } + + if(route.normalise()) + OpenVPN.logMessage(0, "", String.format(getString(R.string.route_not_netip,dest,route.len,route.mIp))); + + mRoutes.add(route); } |