diff options
| -rw-r--r-- | main/jni/Android.mk | 3 | ||||
| -rw-r--r-- | main/jni/jniglue.c | 3 | ||||
| -rw-r--r-- | main/jni/jniglue.h | 9 | ||||
| -rw-r--r-- | main/jni/scan_ifs.c | 109 | ||||
| -rw-r--r-- | main/src/main/java/de/blinkt/openvpn/VpnProfile.java | 5 | ||||
| -rw-r--r-- | main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java | 28 | 
6 files changed, 150 insertions, 7 deletions
| diff --git a/main/jni/Android.mk b/main/jni/Android.mk index 90074b0f..df8cbb34 100644 --- a/main/jni/Android.mk +++ b/main/jni/Android.mk @@ -49,8 +49,9 @@ LOCAL_PATH := $(JNI_DIR)  # The only real JNI library  include $(CLEAR_VARS)  LOCAL_LDLIBS := -llog  -lz +LOCAL_CFLAGS = --std=c99  LOCAL_C_INCLUDES := openssl/include openssl/crypto openssl  -LOCAL_SRC_FILES:= jniglue.c jbcrypto.cpp +LOCAL_SRC_FILES:= jniglue.c jbcrypto.cpp scan_ifs.c  LOCAL_MODULE = opvpnutil  LOCAL_SHARED_LIBRARIES :=  libcrypto  include $(BUILD_SHARED_LIBRARY) diff --git a/main/jni/jniglue.c b/main/jni/jniglue.c index 36ad8fe7..d446f78c 100644 --- a/main/jni/jniglue.c +++ b/main/jni/jniglue.c @@ -1,7 +1,8 @@  #include <jni.h>  #include <android/log.h>  #include <stdlib.h> -#include <setjmp.h> +#include <unistd.h> +  #include "jniglue.h" diff --git a/main/jni/jniglue.h b/main/jni/jniglue.h index a86d52da..8f813b64 100644 --- a/main/jni/jniglue.h +++ b/main/jni/jniglue.h @@ -10,3 +10,12 @@  #define xcopenvpn_jniglue_h  void android_openvpn_log(int level,const char* prefix,const char* prefix_sep,const char* m1);  #endif + +#ifdef __cplusplus +extern "C" { +#endif +    int jniThrowException(JNIEnv* env, const char* className, const char* msg); + +#ifdef __cplusplus +} +#endif diff --git a/main/jni/scan_ifs.c b/main/jni/scan_ifs.c new file mode 100644 index 00000000..e0024c54 --- /dev/null +++ b/main/jni/scan_ifs.c @@ -0,0 +1,109 @@ +#include <jni.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> +#include <netinet/in.h> +#include <sys/ioctl.h> +#include <linux/if.h> +#include <android/log.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> + +#include "jniglue.h" + +jobjectArray Java_de_blinkt_openvpn_core_NativeUtils_getIfconfig(JNIEnv* env) +{ + +	int sd; +    if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { +        __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "Opening socket for intface get failed"); +        //jniThrowException(env, "java/lang/IllegalArgumentException", "Opening socket for intface get failed"); +        return NULL; +    } + +    struct ifreq ifs[23]; + +    struct ifconf ifc;   +    ifc.ifc_req = ifs; +    ifc.ifc_len = sizeof (ifs); + +    if (ioctl (sd, SIOCGIFCONF, &ifc) < 0) { +        __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "IOCTL for intface get failed"); +        //jniThrowException(env, "java/lang/IllegalArgumentException", "IOTCL socket for intface get failed"); +        return NULL; +    } +     + +     + +    char buf[NI_MAXHOST]; +     +    int ji=0; +     +    /* +    jtmp = (*env)->NewStringUTF(env, "HALLO WELT"); +    (*env)->SetObjectArrayElement(env, ret, ji++, jtmp); +    */ + +    size_t num_intf=ifc.ifc_len / sizeof(struct ifreq); +    jobjectArray ret= (jobjectArray) (*env)->NewObjectArray(env, num_intf*3,(*env)->FindClass(env, "java/lang/String"), NULL); + +    for (struct ifreq* ifr = ifc.ifc_req; ifr <   ifs + num_intf; ifr++) { +         +        if (ifr->ifr_addr.sa_family != AF_INET)  { +            __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "NOT AF_INET: %s", ifr->ifr_name); +            continue; +        } +         +        /* get interface addr, prefilled by SIOGIFCONF */ +         +        int err; +        if (err=getnameinfo(&ifr->ifr_addr, sizeof(struct sockaddr_in), buf, NI_MAXHOST, NULL, 0, +                                NI_NUMERICHOST) !=0) { +            __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "getnameinfo failed for  %s: %s", ifr->ifr_name,  gai_strerror(err)); +            continue; +        } +        jstring jaddr = (*env)->NewStringUTF(env, buf); +        jstring jname = (*env)->NewStringUTF(env, ifr->ifr_name); +             + +        struct ifreq ifreq; +        strncpy (ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name)); + +        /* interface is up */ +        if (ioctl (sd, SIOCGIFFLAGS, &ifreq) < 0) { +            __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "SIOCGIFFLAGS failed for %s: %s", ifr->ifr_name, strerror(errno)); +            continue; +        } +         +        if (!(ifreq.ifr_flags & IFF_UP)) { +            __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "IFF_UP failed for %s", ifr->ifr_name); +            continue; +        } + +        /* interface netmask */ +        if (ioctl (sd, SIOCGIFNETMASK, &ifreq) < 0) { +            __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "SIOCIFNETMASK failed for %s: %s", ifr->ifr_name, strerror(errno)); +            continue; +        } +        +        if (err=getnameinfo(&ifreq.ifr_netmask, sizeof(struct sockaddr_in), buf, NI_MAXHOST, NULL, 0, +                                NI_NUMERICHOST) !=0) { +            __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "getnameinfo failed for  %s: %s", ifr->ifr_name,  gai_strerror(err)); +            continue; +        } +        jstring jnetmask = (*env)->NewStringUTF(env, buf); +         +        (*env)->SetObjectArrayElement(env, ret, ji++, jname); +        (*env)->SetObjectArrayElement(env, ret, ji++, jaddr); +        (*env)->SetObjectArrayElement(env, ret, ji++, jnetmask); +    } +    if (sd >= 0) +        close (sd); +     +    return ret; +} + diff --git a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java index 4b483b8f..c8cf7ac8 100644 --- a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -398,11 +398,6 @@ public class VpnProfile implements Serializable {              }          } -        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT && !mAllowLocalLAN) -            cfg+="redirect-private block-local\n"; -        else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && mAllowLocalLAN) -            cfg+="redirect-private unblock-local\n"; -          if (mUseDefaultRoutev6)              cfg += "route-ipv6 ::/0\n"; diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java index be803392..037be5f2 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -471,6 +471,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          if (mLocalIPv6 != null)              cfg += mLocalIPv6; + +          cfg += "routes: " + TextUtils.join("|", mRoutes.getNetworks(true)) + TextUtils.join("|", mRoutesv6.getNetworks(true));          cfg += "excl. routes:" + TextUtils.join("|", mRoutes.getNetworks(false)) + TextUtils.join("|", mRoutesv6.getNetworks(false));          cfg += "dns: " + TextUtils.join("|", mDnslist); @@ -487,6 +489,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          VpnStatus.logInfo(R.string.last_openvpn_tun_config); +        addLocalNetworksToRoutes();          if (mLocalIP == null && mLocalIPv6 == null) {              VpnStatus.logError(getString(R.string.opentun_no_ipaddr)); @@ -602,6 +605,31 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac      } +    private void addLocalNetworksToRoutes() { +        // Add local network interfaces +        String[] localRoutes = NativeUtils.getIfconfig(); + +            // The format of mLocalRoutes is kind of broken because I don't really like JNI +            for (int i=0; i < localRoutes.length; i+=3){ +                String intf = localRoutes[i]; +                String ipAddr = localRoutes[i+1]; +                String netMask = localRoutes[i+2]; + +                if (intf == null || intf.equals("lo") || +                        intf.startsWith("tun") || intf.startsWith("rmnet")) +                    continue; + +                if (ipAddr.equals(mLocalIP.mIp)) +                    continue; + +                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT && !mProfile.mAllowLocalLAN) { +                    mRoutes.addIP(new CIDRIP(ipAddr,netMask), true); +                } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && mProfile.mAllowLocalLAN) +                    mRoutes.addIP(new CIDRIP(ipAddr,netMask), false); +            } +    } + +      @TargetApi(Build.VERSION_CODES.LOLLIPOP)      private void setAllowedVpnPackages(Builder builder) {          for (String pkg : mProfile.mAllowedAppsVpn) { | 
