src/openvpn/route.h
6fbf66fa
 /*
  *  OpenVPN -- An application to securely tunnel IP networks
  *             over a single TCP/UDP port, with support for SSL/TLS-based
  *             session authentication and key exchange,
  *             packet encryption, packet authentication, and
  *             packet compression.
  *
564a2109
  *  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
6fbf66fa
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2
  *  as published by the Free Software Foundation.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program (see the file COPYING included with this
  *  distribution); if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 /*
  * Support routines for adding/deleting network routes.
  */
 
 #ifndef ROUTE_H
 #define ROUTE_H
 
7fb0e07e
 #include "basic.h"
6fbf66fa
 #include "tun.h"
 #include "misc.h"
 
445b192a
 #ifdef _WIN32
6fbf66fa
 /*
  * Windows route methods
  */
6215931b
 #define ROUTE_METHOD_ADAPTIVE  0  /* try IP helper first then route.exe */
 #define ROUTE_METHOD_IPAPI     1  /* use IP helper API */
 #define ROUTE_METHOD_EXE       2  /* use route.exe */
a24dd2e3
 #define ROUTE_METHOD_SERVICE   3  /* use the privileged Windows service */
6215931b
 #define ROUTE_METHOD_MASK      3
6fbf66fa
 #endif
 
 /*
8fc83a2d
  * Route add/delete flags (must stay clear of ROUTE_METHOD bits)
6fbf66fa
  */
8fc83a2d
 #define ROUTE_DELETE_FIRST  (1<<2)
 #define ROUTE_REF_GW        (1<<3)
6fbf66fa
 
3c7f2f55
 struct route_bypass
 {
 # define N_ROUTE_BYPASS 8
   int n_bypass;
   in_addr_t bypass[N_ROUTE_BYPASS];
 };
 
6fbf66fa
 struct route_special_addr
 {
7fb0e07e
   /* bits indicating which members below are defined */
 # define RTSA_REMOTE_ENDPOINT  (1<<0)
 # define RTSA_REMOTE_HOST      (1<<1)
 # define RTSA_DEFAULT_METRIC   (1<<2)
   unsigned int flags;
 
6fbf66fa
   in_addr_t remote_endpoint;
   in_addr_t remote_host;
7fb0e07e
   int remote_host_local;  /* TLA_x value */
3c7f2f55
   struct route_bypass bypass;
40ac3d7a
   int default_metric;
6fbf66fa
 };
 
 struct route_option {
d0085293
   struct route_option *next;
6fbf66fa
   const char *network;
   const char *netmask;
   const char *gateway;
   const char *metric;
 };
 
3c7f2f55
 /* redirect-gateway flags */
 #define RG_ENABLE         (1<<0)
 #define RG_LOCAL          (1<<1)
 #define RG_DEF1           (1<<2)
 #define RG_BYPASS_DHCP    (1<<3)
 #define RG_BYPASS_DNS     (1<<4)
b723833b
 #define RG_REROUTE_GW     (1<<5)
775a6ac2
 #define RG_AUTO_LOCAL     (1<<6)
7fb0e07e
 #define RG_BLOCK_LOCAL    (1<<7)
3c7f2f55
 
6fbf66fa
 struct route_option_list {
7fb0e07e
   unsigned int flags;  /* RG_x flags */
d0085293
   struct route_option *routes;
   struct gc_arena *gc;
6fbf66fa
 };
 
512cda46
 struct route_ipv6_option {
d0085293
   struct route_ipv6_option *next;
512cda46
   const char *prefix;		/* e.g. "2001:db8:1::/64" */
   const char *gateway;		/* e.g. "2001:db8:0::2" */
   const char *metric;		/* e.g. "5" */
 };
 
 struct route_ipv6_option_list {
0ad73859
   unsigned int flags;		/* RG_x flags, see route_option-list */
d0085293
   struct route_ipv6_option *routes_ipv6;
   struct gc_arena *gc;
512cda46
 };
 
b57e005b
 struct route_ipv4 {
7fb0e07e
 # define RT_DEFINED        (1<<0)
 # define RT_ADDED          (1<<1)
 # define RT_METRIC_DEFINED (1<<2)
d0085293
   struct route_ipv4 *next;
7fb0e07e
   unsigned int flags;
6fbf66fa
   const struct route_option *option;
   in_addr_t network;
   in_addr_t netmask;
   in_addr_t gateway;
   int metric;
 };
 
512cda46
 struct route_ipv6 {
d0085293
   struct route_ipv6 *next;
c3ef2d23
   unsigned int flags;				/* RT_ flags, see route_ipv4 */
512cda46
   struct in6_addr network;
1840c852
   unsigned int netbits;
512cda46
   struct in6_addr gateway;
   int metric;
3ddb5643
   /* gateway interface */
445b192a
 # ifdef _WIN32
3ddb5643
   DWORD adapter_index;		/* interface or ~0 if undefined */
 #else
   char * iface;			/* interface name (null terminated) */
 #endif
512cda46
 };
 
 
7fb0e07e
 struct route_gateway_address {
   in_addr_t addr;
   in_addr_t netmask;
 };
 
 struct route_gateway_info {
 # define RGI_ADDR_DEFINED     (1<<0) /* set if gateway.addr defined */
 # define RGI_NETMASK_DEFINED  (1<<1) /* set if gateway.netmask defined */
 # define RGI_HWADDR_DEFINED   (1<<2) /* set if hwaddr is defined */
 # define RGI_IFACE_DEFINED    (1<<3) /* set if iface is defined */
 # define RGI_OVERFLOW         (1<<4) /* set if more interface addresses than will fit in addrs */
8fc83a2d
 # define RGI_ON_LINK          (1<<5)
7fb0e07e
   unsigned int flags;
 
   /* gateway interface */
445b192a
 # ifdef _WIN32
7fb0e07e
   DWORD adapter_index;  /* interface or ~0 if undefined */
 #else
   char iface[16]; /* interface name (null terminated), may be empty */
 #endif
 
   /* gateway interface hardware address */
   uint8_t hwaddr[6];
 
   /* gateway/router address */
   struct route_gateway_address gateway;
 
   /* address/netmask pairs bound to interface */
 # define RGI_N_ADDRESSES 8
   int n_addrs; /* len of addrs, may be 0 */
   struct route_gateway_address addrs[RGI_N_ADDRESSES]; /* local addresses attached to iface */
 };
 
c0da18cd
 struct route_ipv6_gateway_address {
   struct in6_addr addr_ipv6;
   int netbits_ipv6;
 };
 
 struct route_ipv6_gateway_info {
 /* RGI_ flags used as in route_gateway_info */
   unsigned int flags;
 
   /* gateway interface */
445b192a
 # ifdef _WIN32
c0da18cd
   DWORD adapter_index;  /* interface or ~0 if undefined */
 #else
   char iface[16]; /* interface name (null terminated), may be empty */
 #endif
 
   /* gateway interface hardware address */
   uint8_t hwaddr[6];
 
   /* gateway/router address */
   struct route_ipv6_gateway_address gateway;
 
   /* address/netmask pairs bound to interface */
 # define RGI_N_ADDRESSES 8
   int n_addrs; /* len of addrs, may be 0 */
   struct route_ipv6_gateway_address addrs[RGI_N_ADDRESSES]; /* local addresses attached to iface */
 };
 
d02a86d3
 struct route_list {
7fb0e07e
 # define RL_DID_REDIRECT_DEFAULT_GATEWAY (1<<0)
 # define RL_DID_LOCAL                    (1<<1)
 # define RL_ROUTES_ADDED                 (1<<2)
   unsigned int iflags;
 
d02a86d3
   struct route_special_addr spec;
7fb0e07e
   struct route_gateway_info rgi;
   unsigned int flags;     /* RG_x flags */
d0085293
   struct route_ipv4 *routes;
   struct gc_arena gc;
d02a86d3
 };
 
3ddb5643
 struct route_ipv6_list {
   unsigned int iflags;			/* RL_ flags, see route_list */
 
   unsigned int spec_flags;		/* RTSA_ flags, route_special_addr */
   struct in6_addr remote_endpoint_ipv6;	/* inside tun */
   struct in6_addr remote_host_ipv6;	/* --remote address */
   int default_metric;
 
   struct route_ipv6_gateway_info rgi6;
   unsigned int flags;			/* RG_x flags, see route_option_list */
   struct route_ipv6 *routes_ipv6;
   struct gc_arena gc;
 };
 
6fbf66fa
 #if P2MP
 /* internal OpenVPN route */
 struct iroute {
   in_addr_t network;
   int netbits;
   struct iroute *next;
 };
512cda46
 
 struct iroute_ipv6 {
   struct in6_addr network;
   unsigned int netbits;
   struct iroute_ipv6 *next;
 };
6fbf66fa
 #endif
 
d0085293
 struct route_option_list *new_route_option_list (struct gc_arena *a);
 struct route_ipv6_option_list *new_route_ipv6_option_list (struct gc_arena *a);
576dc96c
 
673f583f
 struct route_option_list *clone_route_option_list (const struct route_option_list *src, struct gc_arena *a);
91402236
 struct route_ipv6_option_list *clone_route_ipv6_option_list (const struct route_ipv6_option_list *src, struct gc_arena *a);
d0085293
 void copy_route_option_list (struct route_option_list *dest, const struct route_option_list *src, struct gc_arena *a);
91402236
 void copy_route_ipv6_option_list (struct route_ipv6_option_list *dest,
d0085293
                                   const struct route_ipv6_option_list *src,
                                   struct gc_arena *a);
6fbf66fa
 
512cda46
 void add_route_ipv6 (struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
b55e49bd
 void delete_route_ipv6 (const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
6d5d1010
 
b57e005b
 void add_route (struct route_ipv4 *r,
7fb0e07e
 		const struct tuntap *tt,
 		unsigned int flags,
 		const struct route_gateway_info *rgi,
 		const struct env_set *es);
d02a86d3
 
6fbf66fa
 void add_route_to_option_list (struct route_option_list *l,
 			       const char *network,
 			       const char *netmask,
 			       const char *gateway,
 			       const char *metric);
 
512cda46
 void add_route_ipv6_to_option_list (struct route_ipv6_option_list *l,
 			       const char *prefix,
 			       const char *gateway,
 			       const char *metric);
 
6fbf66fa
 bool init_route_list (struct route_list *rl,
 		      const struct route_option_list *opt,
 		      const char *remote_endpoint,
40ac3d7a
 		      int default_metric,
6fbf66fa
 		      in_addr_t remote_host,
 		      struct env_set *es);
 
512cda46
 bool init_route_ipv6_list (struct route_ipv6_list *rl6,
 		      const struct route_ipv6_option_list *opt6,
 		      const char *remote_endpoint,
 		      int default_metric,
3ddb5643
 		      const struct in6_addr *remote_host,
512cda46
 		      struct env_set *es);
 
7fb0e07e
 void route_list_add_vpn_gateway (struct route_list *rl,
 				 struct env_set *es,
 				 const in_addr_t addr);
03731db3
 
6fbf66fa
 void add_routes (struct route_list *rl,
512cda46
 		 struct route_ipv6_list *rl6,
6fbf66fa
 		 const struct tuntap *tt,
 		 unsigned int flags,
 		 const struct env_set *es);
 
 void delete_routes (struct route_list *rl,
512cda46
 		    struct route_ipv6_list *rl6,
6fbf66fa
 		    const struct tuntap *tt,
 		    unsigned int flags,
 		    const struct env_set *es);
 
 void setenv_routes (struct env_set *es, const struct route_list *rl);
512cda46
 void setenv_routes_ipv6 (struct env_set *es, const struct route_ipv6_list *rl6);
6fbf66fa
 
576dc96c
 
d02a86d3
 
b4073a76
 bool is_special_addr (const char *addr_str);
 
7fb0e07e
 void get_default_gateway (struct route_gateway_info *rgi);
d8a8656f
 void get_default_gateway_ipv6 (struct route_ipv6_gateway_info *rgi,
3ddb5643
 				const struct in6_addr *dest);
d8a8656f
 void print_default_gateway(const int msglevel,
                            const struct route_gateway_info *rgi,
                            const struct route_ipv6_gateway_info *rgi6);
f77c60d3
 
775a6ac2
 /*
  * Test if addr is reachable via a local interface (return ILA_LOCAL),
  * or if it needs to be routed via the default gateway (return
  * ILA_NONLOCAL).  If the current platform doesn't implement this
  * function, return ILA_NOT_IMPLEMENTED.
  */
 #define TLA_NOT_IMPLEMENTED 0
 #define TLA_NONLOCAL        1
 #define TLA_LOCAL           2
7fb0e07e
 int test_local_addr (const in_addr_t addr, const struct route_gateway_info *rgi);
5f31881e
 
6c61d0dd
 #ifndef ENABLE_SMALL
6fbf66fa
 void print_route_options (const struct route_option_list *rol,
 			  int level);
 #endif
 
 void print_routes (const struct route_list *rl, int level);
 
445b192a
 #ifdef _WIN32
6fbf66fa
 
 void show_routes (int msglev);
 bool test_routes (const struct route_list *rl, const struct tuntap *tt);
b57e005b
 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);
6fbf66fa
 
 #else
 static inline bool test_routes (const struct route_list *rl, const struct tuntap *tt) { return true; }
 #endif
 
 bool netmask_to_netbits (const in_addr_t network, const in_addr_t netmask, int *netbits);
ec2fbf37
 int netmask_to_netbits2 (in_addr_t netmask);
6fbf66fa
 
 static inline in_addr_t
 netbits_to_netmask (const int netbits)
 {
   const int addrlen = sizeof (in_addr_t) * 8;
   in_addr_t mask = 0;
   if (netbits > 0 && netbits <= addrlen)
32e576d2
     mask = IPV4_NETMASK_HOST << (addrlen-netbits);
6fbf66fa
   return mask;
 }
 
03731db3
 static inline bool
7fb0e07e
 route_list_vpn_gateway_needed (const struct route_list *rl)
03731db3
 {
   if (!rl)
     return false;
   else
7fb0e07e
     return !(rl->spec.flags & RTSA_REMOTE_ENDPOINT);
 }
 
 static inline int
 route_did_redirect_default_gateway(const struct route_list *rl)
 {
f0257abb
   return rl && BOOL_CAST(rl->iflags & RL_DID_REDIRECT_DEFAULT_GATEWAY);
03731db3
 }
 
6fbf66fa
 #endif