diff options
| -rw-r--r-- | icsopenvpn.iml | 2 | ||||
| -rw-r--r-- | openvpn/config.h | 2 | ||||
| -rw-r--r-- | openvpn/configure.ac | 6 | ||||
| -rw-r--r-- | openvpn/doc/openvpn.8 | 10 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ps.c | 3 | ||||
| -rw-r--r-- | openvpn/src/openvpn/route.c | 140 | ||||
| -rw-r--r-- | openvpn/src/openvpn/route.h | 10 | ||||
| -rw-r--r-- | openvpn/src/openvpn/socket.c | 3 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl_polarssl.c | 13 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl_verify_polarssl.c | 2 | ||||
| -rw-r--r-- | openvpn/src/openvpn/syshead.h | 7 | ||||
| -rw-r--r-- | openvpn/src/openvpn/tun.c | 6 | ||||
| -rw-r--r-- | openvpn/src/openvpn/win32.c | 2 | ||||
| -rwxr-xr-x | res/values/strings.xml | 5 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/VpnProfile.java | 4 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/core/ConfigParser.java | 2 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/core/NetworkSpace.java | 244 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/core/OpenVpnManagementThread.java | 12 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/core/OpenVpnService.java | 109 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/core/VpnStatus.java | 7 | 
20 files changed, 402 insertions, 187 deletions
| diff --git a/icsopenvpn.iml b/icsopenvpn.iml index 62aab261..866601d3 100644 --- a/icsopenvpn.iml +++ b/icsopenvpn.iml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="UTF-8"?> -<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4"> +<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">    <component name="FacetManager">      <facet type="android" name="Android">        <configuration> diff --git a/openvpn/config.h b/openvpn/config.h index d281d33d..993a46f1 100644 --- a/openvpn/config.h +++ b/openvpn/config.h @@ -450,7 +450,7 @@  #define PACKAGE_NAME "OpenVPN"  /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "OpenVPN 2.4-icsopenvpn64" +#define PACKAGE_STRING "OpenVPN 2.4-icsopenvpn"  /* Define to the one symbol short name of this package. */  #define PACKAGE_TARNAME "openvpn" diff --git a/openvpn/configure.ac b/openvpn/configure.ac index 636d4e25..380dcdbb 100644 --- a/openvpn/configure.ac +++ b/openvpn/configure.ac @@ -501,6 +501,12 @@ AC_CHECK_TYPE(  	[[${SOCKET_INCLUDES}]]  )  AC_CHECK_TYPE( +        [sa_family_t], +        [AC_DEFINE([HAVE_SA_FAMILY_T], [1], [sa_family_t, needed to hold AF_* info])], +        , +        [[${SOCKET_INCLUDES}]] +) +AC_CHECK_TYPE(  	[struct sockaddr_in6],  	,  	[AC_MSG_ERROR([struct sockaddr_in6 not found, needed for ipv6 transport support.])], diff --git a/openvpn/doc/openvpn.8 b/openvpn/doc/openvpn.8 index 0235c2c8..9eebf93e 100644 --- a/openvpn/doc/openvpn.8 +++ b/openvpn/doc/openvpn.8 @@ -2097,6 +2097,16 @@ In many cases, the  parameter can point to an empty directory, however  complications can result when scripts or restarts  are executed after the chroot operation. + +Note: if OpenVPN is built using the PolarSSL SSL +library, +.B \-\-chroot +will only work if a /dev/urandom device node is available +inside the chroot directory +.B dir. +This is due to the way PolarSSL works (it wants to open +/dev/urandom every time randomness is needed, not just once +at startup) and nothing OpenVPN can influence.  .\"*********************************************************  .TP  .B \-\-setcon context diff --git a/openvpn/src/openvpn/ps.c b/openvpn/src/openvpn/ps.c index b22653b4..901a094f 100644 --- a/openvpn/src/openvpn/ps.c +++ b/openvpn/src/openvpn/ps.c @@ -340,7 +340,8 @@ journal_add (const char *journal_dir, struct proxy_connection *pc, struct proxy_        fd = platform_open (jfn, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);        if (fd != -1)  	{ -	  write(fd, f, strlen(f)); +	  if (write(fd, f, strlen(f)) != strlen(f)) +	    msg(M_WARN, "PORT SHARE: writing to journal file (%s) failed", jfn);  	  close (fd);  	  cp->jfn = jfn;  	} diff --git a/openvpn/src/openvpn/route.c b/openvpn/src/openvpn/route.c index 81ffa876..fa8221d4 100644 --- a/openvpn/src/openvpn/route.c +++ b/openvpn/src/openvpn/route.c @@ -49,7 +49,7 @@  #define METRIC_NOT_USED ((DWORD)-1)  #endif -static void delete_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es); +static void delete_route (struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es);  static void get_bypass_addresses (struct route_bypass *rb, const unsigned int flags); @@ -150,7 +150,7 @@ struct route_list *  new_route_list (const int max_routes, struct gc_arena *a)  {    struct route_list *ret; -  ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_list, struct route, max_routes, a); +  ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_list, struct route_ipv4, max_routes, a);    ret->capacity = max_routes;    return ret;  } @@ -165,7 +165,7 @@ new_route_ipv6_list (const int max_routes, struct gc_arena *a)  }  static const char * -route_string (const struct route *r, struct gc_arena *gc) +route_string (const struct route_ipv4 *r, struct gc_arena *gc)  {    struct buffer out = alloc_buf_gc (256, gc);    buf_printf (&out, "ROUTE network %s netmask %s gateway %s", @@ -267,7 +267,7 @@ is_special_addr (const char *addr_str)  }  static bool -init_route (struct route *r, +init_route (struct route_ipv4 *r,  	    struct addrinfo **network_list,  	    const struct route_option *ro,  	    const struct route_list *rl) @@ -484,7 +484,7 @@ void  clear_route_list (struct route_list *rl)  {    const int capacity = rl->capacity; -  const size_t rl_size = array_mult_safe (sizeof(struct route), capacity, sizeof(struct route_list)); +  const size_t rl_size = array_mult_safe (sizeof(struct route_ipv4), capacity, sizeof(struct route_list));    memset(rl, 0, rl_size);    rl->capacity = capacity;  } @@ -519,7 +519,7 @@ add_block_local_item (struct route_list *rl,        && rl->rgi.gateway.netmask < 0xFFFFFFFF        && (rl->n)+2 <= rl->capacity)      { -      struct route r; +      struct route_ipv4 r;        unsigned int l2;        /* split a route into two smaller blocking routes, and direct them to target */ @@ -649,7 +649,7 @@ init_route_list (struct route_list *rl,      for (i = 0; i < opt->n; ++i)        {          struct addrinfo* netlist; -	struct route r; +	struct route_ipv4 r;  	if (!init_route (&r,  			 &netlist, @@ -760,7 +760,7 @@ add_route3 (in_addr_t network,  	    const struct route_gateway_info *rgi,  	    const struct env_set *es)  { -  struct route r; +  struct route_ipv4 r;    CLEAR (r);    r.flags = RT_DEFINED;    r.network = network; @@ -778,7 +778,7 @@ del_route3 (in_addr_t network,  	    const struct route_gateway_info *rgi,  	    const struct env_set *es)  { -  struct route r; +  struct route_ipv4 r;    CLEAR (r);    r.flags = RT_DEFINED|RT_ADDED;    r.network = network; @@ -1028,7 +1028,7 @@ add_routes (struct route_list *rl, struct route_ipv6_list *rl6, const struct tun        for (i = 0; i < rl->n; ++i)  	{ -	  struct route *r = &rl->routes[i]; +	  struct route_ipv4 *r = &rl->routes[i];  	  check_subnet_conflict (r->network, r->netmask, "route");  	  if (flags & ROUTE_DELETE_FIRST)  	    delete_route (r, tt, flags, &rl->rgi, es); @@ -1060,7 +1060,7 @@ delete_routes (struct route_list *rl, struct route_ipv6_list *rl6,        int i;        for (i = rl->n - 1; i >= 0; --i)  	{ -	  struct route * r = &rl->routes[i]; +	  struct route_ipv4 * r = &rl->routes[i];  	  delete_route (r, tt, flags, &rl->rgi, es);  	}        rl->iflags &= ~RL_ROUTES_ADDED; @@ -1154,7 +1154,7 @@ print_default_gateway(const int msglevel, const struct route_gateway_info *rgi)  #endif  static void -print_route (const struct route *r, int level) +print_route (const struct route_ipv4 *r, int level)  {    struct gc_arena gc = gc_new ();    if (r->flags & RT_DEFINED) @@ -1171,7 +1171,7 @@ print_routes (const struct route_list *rl, int level)  }  static void -setenv_route (struct env_set *es, const struct route *r, int i) +setenv_route (struct env_set *es, const struct route_ipv4 *r, int i)  {    struct gc_arena gc = gc_new ();    if (r->flags & RT_DEFINED) @@ -1288,7 +1288,7 @@ is_on_link (const int is_local_route, const unsigned int flags, const struct rou  }  void -add_route (struct route *r, +add_route (struct route_ipv4 *r,  	   const struct tuntap *tt,  	   unsigned int flags,  	   const struct route_gateway_info *rgi, /* may be NULL */ @@ -1344,9 +1344,12 @@ add_route (struct route *r,    status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route add command failed");  #elif defined (TARGET_ANDROID) -  struct buffer out = alloc_buf_gc (64, &gc); +  struct buffer out = alloc_buf_gc (128, &gc); -  buf_printf (&out, "%s %s", network, netmask); +  if (rgi) +    buf_printf (&out, "%s %s %s dev %s", network, netmask, gateway, rgi->iface); +  else +    buf_printf (&out, "%s %s %s", network, netmask, gateway);    management_android_control (management, "ROUTE", buf_bptr(&out));  #elif defined (WIN32) @@ -1626,7 +1629,7 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla  #elif defined (TARGET_ANDROID)      struct buffer out = alloc_buf_gc (64, &gc); -    buf_printf (&out, "%s/%d", network, r6->netbits); +    buf_printf (&out, "%s/%d %s", network, r6->netbits, device);      management_android_control (management, "ROUTE6", buf_bptr(&out)); @@ -1741,7 +1744,7 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla  }  static void -delete_route (struct route *r, +delete_route (struct route_ipv4 *r,  	      const struct tuntap *tt,  	      unsigned int flags,  	      const struct route_gateway_info *rgi, @@ -2246,7 +2249,7 @@ get_default_gateway (struct route_gateway_info *rgi)  }  static DWORD -windows_route_find_if_index (const struct route *r, const struct tuntap *tt) +windows_route_find_if_index (const struct route_ipv4 *r, const struct tuntap *tt)  {    struct gc_arena gc = gc_new ();    DWORD ret = TUN_ADAPTER_INDEX_INVALID; @@ -2291,7 +2294,7 @@ windows_route_find_if_index (const struct route *r, const struct tuntap *tt)  }  bool -add_route_ipapi (const struct route *r, const struct tuntap *tt, DWORD adapter_index) +add_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt, DWORD adapter_index)  {    struct gc_arena gc = gc_new ();    bool ret = false; @@ -2365,7 +2368,7 @@ add_route_ipapi (const struct route *r, const struct tuntap *tt, DWORD adapter_i  }  bool -del_route_ipapi (const struct route *r, const struct tuntap *tt) +del_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt)  {    struct gc_arena gc = gc_new ();    bool ret = false; @@ -2611,53 +2614,7 @@ get_default_gateway (struct route_gateway_info *rgi)  #include <sys/types.h>  #include <sys/socket.h>  #include <netinet/in.h> - -/* all of this is taken from <net/route.h> in FreeBSD */ -#define RTA_DST     0x1 -#define RTA_GATEWAY 0x2 -#define RTA_NETMASK 0x4 - -#define RTM_GET     0x4 -#define RTM_VERSION 5 - -#define RTF_UP      0x1 -#define RTF_GATEWAY 0x2 - -/* - * These numbers are used by reliable protocols for determining - * retransmission behavior and are included in the routing structure. - */ -struct rt_metrics { -        u_long  rmx_locks;      /* Kernel must leave these values alone */ -        u_long  rmx_mtu;        /* MTU for this path */ -        u_long  rmx_hopcount;   /* max hops expected */ -        u_long  rmx_expire;     /* lifetime for route, e.g. redirect */ -        u_long  rmx_recvpipe;   /* inbound delay-bandwidth product */ -        u_long  rmx_sendpipe;   /* outbound delay-bandwidth product */ -        u_long  rmx_ssthresh;   /* outbound gateway buffer limit */ -        u_long  rmx_rtt;        /* estimated round trip time */ -        u_long  rmx_rttvar;     /* estimated rtt variance */ -        u_long  rmx_pksent;     /* packets sent using this route */ -        u_long  rmx_filler[4];  /* will be used for T/TCP later */ -}; - -/* - * Structures for routing messages. - */ -struct rt_msghdr { -        u_short rtm_msglen;     /* to skip over non-understood messages */ -        u_char  rtm_version;    /* future binary compatibility */ -        u_char  rtm_type;       /* message type */ -        u_short rtm_index;      /* index for associated ifp */ -        int     rtm_flags;      /* flags, incl. kern & message, e.g. DONE */ -        int     rtm_addrs;      /* bitmask identifying sockaddrs in msg */ -        pid_t   rtm_pid;        /* identify sender */ -        int     rtm_seq;        /* for sender to identify action */ -        int     rtm_errno;      /* why failed */ -        int     rtm_use;        /* from rtentry */ -        u_long  rtm_inits;      /* which metrics we are initializing */ -        struct  rt_metrics rtm_rmx; /* metrics themselves */ -}; +#include <net/route.h>  struct {    struct rt_msghdr m_rtm; @@ -2976,52 +2933,7 @@ get_default_gateway (struct route_gateway_info *rgi)  #include <sys/types.h>  #include <sys/socket.h>  #include <netinet/in.h> - -/* all of this is taken from <net/route.h> in OpenBSD 3.6 */ -#define RTA_DST		0x1	/* destination sockaddr present */ -#define RTA_GATEWAY	0x2	/* gateway sockaddr present */ -#define RTA_NETMASK	0x4	/* netmask sockaddr present */ - -#define RTM_GET		0x4	/* Report Metrics */ - -#define RTM_VERSION	3	/* Up the ante and ignore older versions */ - -#define	RTF_UP		0x1		/* route usable */ -#define	RTF_GATEWAY	0x2		/* destination is a gateway */ - -/* - * Huge version for userland compatibility. - */ -struct rt_metrics { -	u_long	rmx_locks;	/* Kernel must leave these values alone */ -	u_long	rmx_mtu;	/* MTU for this path */ -	u_long	rmx_hopcount;	/* max hops expected */ -	u_long	rmx_expire;	/* lifetime for route, e.g. redirect */ -	u_long	rmx_recvpipe;	/* inbound delay-bandwidth product */ -	u_long	rmx_sendpipe;	/* outbound delay-bandwidth product */ -	u_long	rmx_ssthresh;	/* outbound gateway buffer limit */ -	u_long	rmx_rtt;	/* estimated round trip time */ -	u_long	rmx_rttvar;	/* estimated rtt variance */ -	u_long	rmx_pksent;	/* packets sent using this route */ -}; - -/* - * Structures for routing messages. - */ -struct rt_msghdr { -	u_short	rtm_msglen;	/* to skip over non-understood messages */ -	u_char	rtm_version;	/* future binary compatibility */ -	u_char	rtm_type;	/* message type */ -	u_short	rtm_index;	/* index for associated ifp */ -	int	rtm_flags;	/* flags, incl. kern & message, e.g. DONE */ -	int	rtm_addrs;	/* bitmask identifying sockaddrs in msg */ -	pid_t	rtm_pid;	/* identify sender */ -	int	rtm_seq;	/* for sender to identify action */ -	int	rtm_errno;	/* why failed */ -	int	rtm_use;	/* from rtentry */ -	u_long	rtm_inits;	/* which metrics we are initializing */ -	struct	rt_metrics rtm_rmx; /* metrics themselves */ -}; +#include <net/route.h>  struct {    struct rt_msghdr m_rtm; diff --git a/openvpn/src/openvpn/route.h b/openvpn/src/openvpn/route.h index a40de32f..fe9b4616 100644 --- a/openvpn/src/openvpn/route.h +++ b/openvpn/src/openvpn/route.h @@ -110,7 +110,7 @@ struct route_ipv6_option_list {    struct route_ipv6_option routes_ipv6[EMPTY_ARRAY_SIZE];  }; -struct route { +struct route_ipv4 {  # define RT_DEFINED        (1<<0)  # define RT_ADDED          (1<<1)  # define RT_METRIC_DEFINED (1<<2) @@ -190,7 +190,7 @@ struct route_list {    unsigned int flags;     /* RG_x flags */    int capacity;    int n; -  struct route routes[EMPTY_ARRAY_SIZE]; +  struct route_ipv4 routes[EMPTY_ARRAY_SIZE];  };  #if P2MP @@ -223,7 +223,7 @@ struct route_ipv6_list *new_route_ipv6_list (const int max_routes, struct gc_are  void add_route_ipv6 (struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);  void delete_route_ipv6 (const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es); -void add_route (struct route *r, +void add_route (struct route_ipv4 *r,  		const struct tuntap *tt,  		unsigned int flags,  		const struct route_gateway_info *rgi, @@ -301,8 +301,8 @@ void print_routes (const struct route_list *rl, int level);  void show_routes (int msglev);  bool test_routes (const struct route_list *rl, const struct tuntap *tt); -bool add_route_ipapi (const struct route *r, const struct tuntap *tt, DWORD adapter_index); -bool del_route_ipapi (const struct route *r, const struct tuntap *tt); +bool add_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt, DWORD adapter_index); +bool del_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt);  #else  static inline bool test_routes (const struct route_list *rl, const struct tuntap *tt) { return true; } diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c index 716512df..97f67563 100644 --- a/openvpn/src/openvpn/socket.c +++ b/openvpn/src/openvpn/socket.c @@ -1981,7 +1981,8 @@ link_socket_init_phase2 (struct link_socket *sock,  #endif  	}  #ifdef TARGET_ANDROID -      protect_fd_nonlocal (sock->sd, &sock->info.lsa->actual.dest.addr.sa); +      if (sock->sd != -1) +	protect_fd_nonlocal (sock->sd, &sock->info.lsa->actual.dest.addr.sa);  #endif        if (sig_info && sig_info->signal_received)  	goto done; diff --git a/openvpn/src/openvpn/ssl_polarssl.c b/openvpn/src/openvpn/ssl_polarssl.c index 47fb62a5..9dc4e879 100644 --- a/openvpn/src/openvpn/ssl_polarssl.c +++ b/openvpn/src/openvpn/ssl_polarssl.c @@ -49,6 +49,7 @@  #include <polarssl/havege.h>  #include "ssl_verify_polarssl.h" +#include <polarssl/error.h>  #include <polarssl/pem.h>  void @@ -284,7 +285,7 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file,  	  pem_password_callback(passbuf, 512, 0, NULL);  	  status = x509parse_key(ctx->priv_key,  	      priv_key_file_inline, strlen(priv_key_file_inline), -	      passbuf, strlen(passbuf)); +	      (unsigned char *) passbuf, strlen(passbuf));  	}      }    else @@ -481,7 +482,8 @@ void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,    if (ca_file && !strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline)      { -      if (0 != x509parse_crt(ctx->ca_chain, ca_file_inline, strlen(ca_file_inline))) +      if (0 != x509parse_crt(ctx->ca_chain, (unsigned char *) ca_file_inline, +          strlen(ca_file_inline)))  	msg (M_FATAL, "Cannot load inline CA certificates");      }    else @@ -501,8 +503,9 @@ tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file    if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_file_inline)      { -      if (0 != x509parse_crt(ctx->crt_chain, extra_certs_file_inline, -	  strlen(extra_certs_file_inline))) +      if (0 != x509parse_crt(ctx->crt_chain, +          (unsigned char *) extra_certs_file_inline, +          strlen(extra_certs_file_inline)))          msg (M_FATAL, "Cannot load inline extra-certs file");      }    else @@ -625,7 +628,7 @@ static void my_debug( void *ctx, int level, const char *str )  void tls_ctx_personalise_random(struct tls_root_ctx *ctx)  {    static char old_sha256_hash[32] = {0}; -  char sha256_hash[32] = {0}; +  unsigned char sha256_hash[32] = {0};    ctr_drbg_context *cd_ctx = rand_ctx_get();    if (NULL != ctx->crt_chain) diff --git a/openvpn/src/openvpn/ssl_verify_polarssl.c b/openvpn/src/openvpn/ssl_verify_polarssl.c index 5db4f027..e5ccd904 100644 --- a/openvpn/src/openvpn/ssl_verify_polarssl.c +++ b/openvpn/src/openvpn/ssl_verify_polarssl.c @@ -125,8 +125,6 @@ x509_get_username (char *cn, int cn_len,  char *  x509_get_serial (x509_cert *cert, struct gc_arena *gc)  { -  int ret = 0; -  int i = 0;    char *buf = NULL;    size_t len = cert->serial.len * 3 + 1; diff --git a/openvpn/src/openvpn/syshead.h b/openvpn/src/openvpn/syshead.h index ab6fa01f..4050d548 100644 --- a/openvpn/src/openvpn/syshead.h +++ b/openvpn/src/openvpn/syshead.h @@ -426,6 +426,13 @@  #endif  /* + * Define type sa_family_t if it isn't defined in the socket headers + */ +#ifndef HAVE_SA_FAMILY_T +typedef unsigned short sa_family_t; +#endif + +/*   * Disable ESEC   */  #if 0 diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c index 6460a369..4df271d5 100644 --- a/openvpn/src/openvpn/tun.c +++ b/openvpn/src/openvpn/tun.c @@ -909,7 +909,7 @@ do_ifconfig (struct tuntap *tt,        if (!tun && tt->topology == TOP_SUBNET)  	{  	  /* Add a network route for the local tun interface */ -	  struct route r; +	  struct route_ipv4 r;  	  CLEAR (r);        	  r.flags = RT_DEFINED | RT_METRIC_DEFINED;  	  r.network = tt->local & tt->remote_netmask; @@ -1106,7 +1106,7 @@ do_ifconfig (struct tuntap *tt,        /* Add a network route for the local tun interface */        if (!tun && tt->topology == TOP_SUBNET)  	{ -	  struct route r; +	  struct route_ipv4 r;  	  CLEAR (r);  	  r.flags = RT_DEFINED;  	  r.network = tt->local & tt->remote_netmask; @@ -1172,7 +1172,7 @@ do_ifconfig (struct tuntap *tt,  	/* Add a network route for the local tun interface */        if (!tun && tt->topology == TOP_SUBNET)          { -          struct route r; +          struct route_ipv4 r;            CLEAR (r);            r.flags = RT_DEFINED;            r.network = tt->local & tt->remote_netmask; diff --git a/openvpn/src/openvpn/win32.c b/openvpn/src/openvpn/win32.c index f35c96be..7c89a5a9 100644 --- a/openvpn/src/openvpn/win32.c +++ b/openvpn/src/openvpn/win32.c @@ -517,7 +517,7 @@ win32_signal_get (struct win32_signal *ws)        if (ret)  	{  	  siginfo_static.signal_received = ret; -	  siginfo_static.hard = true; +	  siginfo_static.source = SIG_SOURCE_HARD;  	}      }    return ret; diff --git a/res/values/strings.xml b/res/values/strings.xml index 792a5f89..34721515 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -97,8 +97,9 @@      <string name="last_openvpn_tun_config">Opening tun interface:</string>      <string name="local_ip_info">Local IPv4: %1$s/%2$d IPv6: %3$s MTU: %4$d</string>      <string name="dns_server_info">DNS Server: %1$s, Domain: %2$s</string> -    <string name="routes_info">Routes: %s</string> -    <string name="routes_info6">Routes IPv6: %s</string> +    <string name="routes_info_incl">Routes: %1$s %2$s</string> +    <string name="routes_info_excl">Routes excluded: %1$s %2$s</string> +    <string name="routes_debug">VpnService routes installed: %1$s %2$s</string>      <string name="ip_not_cidr">Got interface information %1$s and %2$s, assuming second address is peer address of remote. Using /32 netmask for local IP. Mode given by OpenVPN is \"%3$s\".</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> diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java index d580829d..b016fb64 100644 --- a/src/de/blinkt/openvpn/VpnProfile.java +++ b/src/de/blinkt/openvpn/VpnProfile.java @@ -305,10 +305,10 @@ public class VpnProfile implements Serializable {          String routes = "";          int numroutes = 0;          if (mUseDefaultRoute) -            routes += "route 0.0.0.0 0.0.0.0\n"; +            routes += "route 0.0.0.0 0.0.0.0 vpn_gateway\n";          else              for (String route : getCustomRoutes()) { -                routes += "route " + route + "\n"; +                routes += "route " + route + "vpn_gateway\n";                  numroutes++;              } diff --git a/src/de/blinkt/openvpn/core/ConfigParser.java b/src/de/blinkt/openvpn/core/ConfigParser.java index 103c208b..895f048e 100644 --- a/src/de/blinkt/openvpn/core/ConfigParser.java +++ b/src/de/blinkt/openvpn/core/ConfigParser.java @@ -12,7 +12,7 @@ import java.util.Vector;  //! Openvpn Config FIle Parser, probably not 100% accurate but close enough -// And rember, this is valid :) +// And remember, this is valid :)  // --<foo>  // bar  // </foo> diff --git a/src/de/blinkt/openvpn/core/NetworkSpace.java b/src/de/blinkt/openvpn/core/NetworkSpace.java new file mode 100644 index 00000000..3701c43d --- /dev/null +++ b/src/de/blinkt/openvpn/core/NetworkSpace.java @@ -0,0 +1,244 @@ +package de.blinkt.openvpn.core; + +import android.text.TextUtils; + +import java.math.BigInteger; +import java.net.Inet6Address; +import java.util.*; + +public class NetworkSpace { + + +    static class ipAddress implements Comparable<ipAddress> { +        private BigInteger netAddress; +        public int networkMask; +        private boolean included; +        private boolean isV4; + + +        @Override +        public int compareTo(ipAddress another) { +            int comp = getFirstAddress().compareTo(another.getFirstAddress()); +            if (comp != 0) +                return comp; + +            // bigger mask means smaller address block +            if (networkMask > another.networkMask) +                return -1; +            else if (another.networkMask == networkMask) +                return 0; +            else +                return 1; + + +        } + +        public ipAddress(CIDRIP ip, boolean include) { +            included = include; +            netAddress = BigInteger.valueOf(ip.getInt()); +            networkMask = ip.len; +            isV4 = true; +        } + +        public ipAddress(Inet6Address address, int mask, boolean include) { +            networkMask = mask; +            included = include; + +            int s = 128; + +            netAddress = BigInteger.ZERO; +            for (byte b : address.getAddress()) { +                s -= 16; +                netAddress = netAddress.add(BigInteger.valueOf(b).shiftLeft(s)); +            } +        } + +        public BigInteger getLastAddress() { +            return getMaskedAddress(true); +        } + + +        public BigInteger getFirstAddress() { +            return getMaskedAddress(false); +        } + + +        private BigInteger getMaskedAddress(boolean one) { +            BigInteger numAddress = netAddress; + +            int numBits; +            if (isV4) { +                numBits = 32 - networkMask; +            } else { +                numBits = 128 - networkMask; +            } + +            for (int i = 0; i < numBits; i++) { +                if (one) +                    numAddress = numAddress.setBit(i); +                else +                    numAddress = numAddress.clearBit(i); +            } +            return numAddress; +        } + + +        @Override +        public String toString() { +            //String in = included ? "+" : "-"; +            if (isV4) +                return String.format("%s/%d", getIPv4Address(), networkMask); +            else +                return String.format("%s/%d", getIPv6Address(), networkMask); +        } + +        ipAddress(BigInteger baseAddress, int mask, boolean included, boolean isV4) { +            this.netAddress = baseAddress; +            this.networkMask = mask; +            this.included = included; +            this.isV4 = isV4; +        } + + +        public ipAddress[] split() { +            ipAddress firsthalf = new ipAddress(getFirstAddress(), networkMask + 1, included, isV4); +            ipAddress secondhalf = new ipAddress(firsthalf.getLastAddress().add(BigInteger.ONE), networkMask + 1, included, isV4); +            assert secondhalf.getLastAddress().equals(getLastAddress()); +            return new ipAddress[]{firsthalf, secondhalf}; +        } + +        String getIPv4Address() { +            assert (isV4); +            assert (netAddress.longValue() <= 0xffffffffl); +            assert (netAddress.longValue() >= 0); +            long ip = netAddress.longValue(); +            return String.format("%d.%d.%d.%d", (ip >> 24) % 256, (ip >> 16) % 256, (ip >> 8) % 256, ip % 256); +        } + +        String getIPv6Address() { +            assert (!isV4); +            BigInteger r = netAddress; +            if (r.longValue() == 0) +                return "::"; + +            Vector<String> parts = new Vector<String>(); +            while (r.compareTo(BigInteger.ZERO) == 1) { +                parts.add(0, String.format("%x", r.mod(BigInteger.valueOf(256)).longValue())); +                r = r.shiftRight(16); +            } + +            return TextUtils.join(":", parts); +        } + +        public boolean containsNet(ipAddress network) { +            return getFirstAddress().compareTo(network.getFirstAddress()) != 1 && +                    getLastAddress().compareTo(network.getLastAddress()) != -1; +        } +    } + + +    TreeSet<ipAddress> ipAddresses = new TreeSet<ipAddress>(); + + +    public Collection<ipAddress> getNetworks(boolean included) { +        Vector<ipAddress> ips = new Vector<ipAddress>(); +        for (ipAddress ip : ipAddresses) { +            if (ip.included == included) +                ips.add(ip); +        } +        return ips; +    } + +    public void clear() { +        ipAddresses.clear(); +    } + + +    void addIP(CIDRIP cidrIp, boolean include) { + +        ipAddresses.add(new ipAddress(cidrIp, include)); +    } + +    void addIPv6(Inet6Address address, int mask, boolean included) { +        ipAddresses.add(new ipAddress(address, mask, included)); +    } + +    TreeSet<ipAddress> generateIPList() { +        TreeSet<ipAddress> ipsSorted = new TreeSet<ipAddress>(ipAddresses); +        Iterator<ipAddress> it = ipsSorted.iterator(); + +        ipAddress currentNet = null; +        if (it.hasNext()) +            currentNet = it.next(); +        while (it.hasNext()) { +            // Check if it and the next of it are compatbile +            ipAddress nextNet = it.next(); + +            assert currentNet != null; +            if (currentNet.getLastAddress().compareTo(nextNet.getFirstAddress()) == -1) { +                // Everything good, no overlapping nothing to do +                currentNet = nextNet; +            } else { +                // This network is smaller or equal to the next but has the same base address +                if (currentNet.getFirstAddress().equals(nextNet.getFirstAddress()) && currentNet.networkMask >= nextNet.networkMask) { +                    if (currentNet.included == nextNet.included) { +                        ipsSorted.remove(currentNet); +                    } else { + +                        // our currentnet is included in next and nextnet needs to be split +                        ipsSorted.remove(nextNet); +                        ipAddress[] newNets = nextNet.split(); + +                        if (newNets[0].getLastAddress().equals(currentNet.getLastAddress())) { +                            assert (newNets[0].networkMask == currentNet.networkMask); +                            // Don't add the lower half that would conflict with currentNet +                        } else { +                            ipsSorted.add(newNets[0]); +                        } + +                        ipsSorted.add(newNets[1]); +                    } +                } else { +                    assert (currentNet.networkMask < nextNet.networkMask); +                    assert (nextNet.getFirstAddress().compareTo(currentNet.getFirstAddress()) == 1); +                    // This network is bigger than the next and last ip of current >= next +                    assert (currentNet.getLastAddress().compareTo(nextNet.getLastAddress()) != -1); + +                    if (currentNet.included == nextNet.included) { +                        ipsSorted.remove(nextNet); +                    } else { +                        ipsSorted.remove(currentNet); +                        ipAddress[] newNets = currentNet.split(); + +                        ipsSorted.add(newNets[0]); + +                        if (newNets[1].networkMask == nextNet.networkMask) { +                            assert (newNets[1].getFirstAddress().equals(nextNet.getFirstAddress())); +                            assert (newNets[1].getLastAddress().equals(currentNet.getLastAddress())); +                        } else { +                            ipsSorted.add(newNets[1]); +                        } +                    } +                } +                // Reset iterator +                it = ipsSorted.iterator(); +                currentNet = it.next(); +            } + +        } + +        return ipsSorted; +    } + +    Collection<ipAddress> getPositiveIPList() { +        TreeSet<ipAddress> ipsSorted = generateIPList(); + +        Vector<ipAddress> ips = new Vector<ipAddress>(); +        for (ipAddress ia : ipsSorted) { +            if (ia.included) +                ips.add(ia); +        } +        return ips; +    } + +} diff --git a/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java index 2fa407ca..5fa70cc8 100644 --- a/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -379,9 +379,17 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {  			mOpenVPNService.setDomain(extra);
  		} else if (needed.equals("ROUTE")) {
  			String[] routeparts = extra.split(" ");
 -			mOpenVPNService.addRoute(routeparts[0], routeparts[1]);
 +
 +            if(routeparts.length>3) {
 +                assert(routeparts[3].equals("dev"));
 +                mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], routeparts[4]);
 +            }  else {
 +                mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], null);
 +            }
 +
  		} else if (needed.equals("ROUTE6")) {
 -			mOpenVPNService.addRoutev6(extra);
 +            String[] routeparts = extra.split(" ");
 +			mOpenVPNService.addRoutev6(routeparts[0],routeparts[1]);
  		} else if (needed.equals("IFCONFIG")) {
  			String[] ifconfigparts = extra.split(" ");
  			int mtu = Integer.parseInt(ifconfigparts[2]);
 diff --git a/src/de/blinkt/openvpn/core/OpenVpnService.java b/src/de/blinkt/openvpn/core/OpenVpnService.java index 3de701b1..e485ee73 100644 --- a/src/de/blinkt/openvpn/core/OpenVpnService.java +++ b/src/de/blinkt/openvpn/core/OpenVpnService.java @@ -25,10 +25,15 @@ import de.blinkt.openvpn.core.VpnStatus.StateListener;  import java.lang.reflect.InvocationTargetException;  import java.lang.reflect.Method; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException;  import java.util.HashMap;  import java.util.Locale;  import java.util.Vector; +import static de.blinkt.openvpn.core.NetworkSpace.*;  import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.*;  public class OpenVpnService extends VpnService implements StateListener, Callback, ByteCountListener { @@ -41,8 +46,8 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac      private static final int OPENVPN_STATUS = 1;      private static boolean mNotificationAlwaysVisible = false;      private final Vector<String> mDnslist = new Vector<String>(); -    private final Vector<CIDRIP> mRoutes = new Vector<CIDRIP>(); -    private final Vector<String> mRoutesv6 = new Vector<String>(); +    private final NetworkSpace mRoutes = new NetworkSpace(); +    private final NetworkSpace mRoutesv6 = new NetworkSpace();      private final IBinder mBinder = new LocalBinder();      private Thread mProcessThread = null;      private VpnProfile mProfile; @@ -255,8 +260,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac          mDeviceStateReceiver = null;      } -    public void userPause (boolean shouldBePaused) -    { +    public void userPause(boolean shouldBePaused) {          if (mDeviceStateReceiver != null)              mDeviceStateReceiver.userPause(shouldBePaused);      } @@ -349,7 +353,6 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac          } -          Runnable processThread;          if (mOvpn3) { @@ -396,21 +399,21 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac      } -    private String getTunConfigString() -    { +    private String getTunConfigString() {          // The format of the string is not important, only that          // two identical configurations produce the same result -        String cfg="TUNCFG UNQIUE STRING ips:"; - -        if (mLocalIP!=null) -            cfg+=mLocalIP.toString(); -        if (mLocalIPv6!=null) -            cfg+=mLocalIPv6.toString(); - -        cfg+= "routes: " + TextUtils.join("|",mRoutes) + TextUtils.join("|",mRoutesv6); -        cfg+= "dns: " + TextUtils.join("|",mDnslist); -        cfg+= "domain: " + mDomain; -        cfg+= "mtu: " + mMtu; +        String cfg = "TUNCFG UNQIUE STRING ips:"; + +        if (mLocalIP != null) +            cfg += mLocalIP.toString(); +        if (mLocalIPv6 != null) +            cfg += mLocalIPv6.toString(); + +        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); +        cfg += "domain: " + mDomain; +        cfg += "mtu: " + mMtu;          return cfg;      } @@ -455,20 +458,19 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac          builder.setMtu(mMtu); -        for (CIDRIP route : mRoutes) { +        for (NetworkSpace.ipAddress route : mRoutes.getPositiveIPList()) {              try { -                builder.addRoute(route.mIp, route.len); +                builder.addRoute(route.getIPv4Address(), route.networkMask);              } catch (IllegalArgumentException ia) {                  VpnStatus.logError(getString(R.string.route_rejected) + route + " " + ia.getLocalizedMessage());              }          } -        for (String v6route : mRoutesv6) { +        for (NetworkSpace.ipAddress route6 : mRoutesv6.getPositiveIPList()) {              try { -                String[] v6parts = v6route.split("/"); -                builder.addRoute(v6parts[0], Integer.parseInt(v6parts[1])); +                builder.addRoute(route6.getIPv6Address(), route6.networkMask);              } catch (IllegalArgumentException ia) { -                VpnStatus.logError(getString(R.string.route_rejected) + v6route + " " + ia.getLocalizedMessage()); +                VpnStatus.logError(getString(R.string.route_rejected) + route6 + " " + ia.getLocalizedMessage());              }          } @@ -477,9 +479,10 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac          VpnStatus.logInfo(R.string.last_openvpn_tun_config);          VpnStatus.logInfo(R.string.local_ip_info, mLocalIP.mIp, mLocalIP.len, mLocalIPv6, mMtu); -        VpnStatus.logInfo(R.string.dns_server_info, joinString(mDnslist), mDomain); -        VpnStatus.logInfo(R.string.routes_info, joinString(mRoutes)); -        VpnStatus.logInfo(R.string.routes_info6, joinString(mRoutesv6)); +        VpnStatus.logInfo(R.string.dns_server_info, TextUtils.join(", ", mDnslist), mDomain); +        VpnStatus.logInfo(R.string.routes_info_incl, TextUtils.join(", ", mRoutes.getNetworks(true)), TextUtils.join(", ", mRoutesv6.getNetworks(true))); +        VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(", ", mRoutes.getNetworks(false)),TextUtils.join(", ", mRoutesv6.getNetworks(false))); +        VpnStatus.logDebug(R.string.routes_debug, TextUtils.join(", ", mRoutes.getPositiveIPList()), TextUtils.join(", ", mRoutesv6.getPositiveIPList()));          String session = mProfile.mName;          if (mLocalIP != null && mLocalIPv6 != null) @@ -518,18 +521,6 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac      } -    // 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);      } @@ -540,8 +531,17 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac          }      } -    public void addRoute(String dest, String mask) { +    public void addRoute(String dest, String mask, String gateway, String device) {          CIDRIP route = new CIDRIP(dest, mask); +        boolean include = isAndroidTunDevice(device); + +        NetworkSpace.ipAddress gatewayIP = new NetworkSpace.ipAddress(new CIDRIP(gateway, 32),false); + +        NetworkSpace.ipAddress localNet = new NetworkSpace.ipAddress(mLocalIP,true); +        if (localNet.containsNet(gatewayIP)) +            include =true; + +          if (route.len == 32 && !mask.equals("255.255.255.255")) {              VpnStatus.logWarning(R.string.route_not_cidr, dest, mask);          } @@ -549,11 +549,30 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac          if (route.normalise())              VpnStatus.logWarning(R.string.route_not_netip, dest, route.len, route.mIp); -        mRoutes.add(route); +        mRoutes.addIP(route, include); +    } + +    public void addRoutev6(String network, String device) { +        String[] v6parts = network.split("/"); +        boolean included = isAndroidTunDevice(device); + +        // Tun is opened after ROUTE6, no device name may be present + +        try { +            Inet6Address ip = (Inet6Address) InetAddress.getAllByName(v6parts[0])[0]; +            int mask = Integer.parseInt(v6parts[1]); +            mRoutesv6.addIPv6(ip, mask, included); + +        } catch (UnknownHostException e) { +            VpnStatus.logException(e); +        } + +      } -    public void addRoutev6(String extra) { -        mRoutesv6.add(extra); +    private boolean isAndroidTunDevice(String device) { +        return device!=null && +                (device.startsWith("tun") || "(null)".equals(device) || "vpnservice-tun".equals(device));      }      public void setMtu(int mtu) { @@ -657,9 +676,9 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac      public String getTunReopenStatus() {          String currentConfiguration = getTunConfigString(); -        if(currentConfiguration.equals(mLastTunCfg)) +        if (currentConfiguration.equals(mLastTunCfg))              return "NOACTION"; -        else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) +        else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)              return "OPEN_AFTER_CLOSE";          else              return "OPEN_BEFORE_CLOSE"; diff --git a/src/de/blinkt/openvpn/core/VpnStatus.java b/src/de/blinkt/openvpn/core/VpnStatus.java index f2953240..d146aef8 100644 --- a/src/de/blinkt/openvpn/core/VpnStatus.java +++ b/src/de/blinkt/openvpn/core/VpnStatus.java @@ -479,7 +479,12 @@ public class VpnStatus {  		newLogItem(new LogItem(LogLevel.INFO, resourceId, args));  	} -	private synchronized static void newLogItem(LogItem logItem) { +    public static void logDebug(int resourceId, Object... args) { +        newLogItem(new LogItem(LogLevel.DEBUG, resourceId, args)); +    } + + +    private synchronized static void newLogItem(LogItem logItem) {  		logbuffer.addLast(logItem);  		if(logbuffer.size()>MAXLOGENTRIES)  			logbuffer.removeFirst(); | 
