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.
  *
49979459
  *  Copyright (C) 2002-2018 OpenVPN 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.
  *
caa54ac3
  *  You should have received a copy of the GNU General Public License along
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6fbf66fa
  */
 
 /*
  * 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
 {
81d882d5
 #define N_ROUTE_BYPASS 8
     int n_bypass;
     in_addr_t bypass[N_ROUTE_BYPASS];
3c7f2f55
 };
 
6fbf66fa
 struct route_special_addr
 {
81d882d5
     /* 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;
 
     in_addr_t remote_endpoint;
     in_addr_t remote_host;
     int remote_host_local; /* TLA_x value */
     struct route_bypass bypass;
     int default_metric;
6fbf66fa
 };
 
 struct route_option {
81d882d5
     struct route_option *next;
     const char *network;
     const char *netmask;
     const char *gateway;
     const char *metric;
6fbf66fa
 };
 
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 {
81d882d5
     unsigned int flags; /* RG_x flags */
     struct route_option *routes;
     struct gc_arena *gc;
6fbf66fa
 };
 
512cda46
 struct route_ipv6_option {
81d882d5
     struct route_ipv6_option *next;
     const char *prefix;         /* e.g. "2001:db8:1::/64" */
     const char *gateway;        /* e.g. "2001:db8:0::2" */
     const char *metric;         /* e.g. "5" */
512cda46
 };
 
 struct route_ipv6_option_list {
81d882d5
     unsigned int flags;         /* RG_x flags, see route_option-list */
     struct route_ipv6_option *routes_ipv6;
     struct gc_arena *gc;
512cda46
 };
 
b57e005b
 struct route_ipv4 {
81d882d5
 #define RT_DEFINED        (1<<0)
 #define RT_ADDED          (1<<1)
 #define RT_METRIC_DEFINED (1<<2)
     struct route_ipv4 *next;
     unsigned int flags;
     const struct route_option *option;
     in_addr_t network;
     in_addr_t netmask;
     in_addr_t gateway;
     int metric;
6fbf66fa
 };
 
512cda46
 struct route_ipv6 {
81d882d5
     struct route_ipv6 *next;
     unsigned int flags;                         /* RT_ flags, see route_ipv4 */
     struct in6_addr network;
     unsigned int netbits;
     struct in6_addr gateway;
     int metric;
     /* gateway interface */
 #ifdef _WIN32
     DWORD adapter_index;        /* interface or ~0 if undefined */
3ddb5643
 #else
81d882d5
     char *iface;                /* interface name (null terminated) */
3ddb5643
 #endif
512cda46
 };
 
 
7fb0e07e
 struct route_gateway_address {
81d882d5
     in_addr_t addr;
     in_addr_t netmask;
7fb0e07e
 };
 
 struct route_gateway_info {
81d882d5
 #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 */
 #define RGI_ON_LINK          (1<<5)
     unsigned int flags;
 
     /* gateway interface */
 #ifdef _WIN32
     DWORD adapter_index; /* interface or ~0 if undefined */
7fb0e07e
 #else
81d882d5
     char iface[16]; /* interface name (null terminated), may be empty */
7fb0e07e
 #endif
 
81d882d5
     /* gateway interface hardware address */
     uint8_t hwaddr[6];
7fb0e07e
 
81d882d5
     /* gateway/router address */
     struct route_gateway_address gateway;
7fb0e07e
 
81d882d5
     /* 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 */
7fb0e07e
 };
 
c0da18cd
 struct route_ipv6_gateway_address {
81d882d5
     struct in6_addr addr_ipv6;
     int netbits_ipv6;
c0da18cd
 };
 
 struct route_ipv6_gateway_info {
 /* RGI_ flags used as in route_gateway_info */
81d882d5
     unsigned int flags;
c0da18cd
 
81d882d5
     /* gateway interface */
 #ifdef _WIN32
     DWORD adapter_index; /* interface or ~0 if undefined */
c0da18cd
 #else
81d882d5
     char iface[16]; /* interface name (null terminated), may be empty */
c0da18cd
 #endif
 
81d882d5
     /* gateway interface hardware address */
     uint8_t hwaddr[6];
c0da18cd
 
81d882d5
     /* gateway/router address */
     struct route_ipv6_gateway_address gateway;
c0da18cd
 
81d882d5
     /* 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 */
c0da18cd
 };
 
d02a86d3
 struct route_list {
81d882d5
 #define RL_DID_REDIRECT_DEFAULT_GATEWAY (1<<0)
 #define RL_DID_LOCAL                    (1<<1)
 #define RL_ROUTES_ADDED                 (1<<2)
     unsigned int iflags;
 
     struct route_special_addr spec;
     struct route_gateway_info rgi;
     unsigned int flags;   /* RG_x flags */
     struct route_ipv4 *routes;
     struct gc_arena gc;
d02a86d3
 };
 
3ddb5643
 struct route_ipv6_list {
81d882d5
     unsigned int iflags;                /* RL_ flags, see route_list */
3ddb5643
 
81d882d5
     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;
3ddb5643
 
81d882d5
     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;
3ddb5643
 };
 
6fbf66fa
 #if P2MP
 /* internal OpenVPN route */
 struct iroute {
81d882d5
     in_addr_t network;
     int netbits;
     struct iroute *next;
6fbf66fa
 };
512cda46
 
 struct iroute_ipv6 {
81d882d5
     struct in6_addr network;
     unsigned int netbits;
     struct iroute_ipv6 *next;
512cda46
 };
6fbf66fa
 #endif
 
81d882d5
 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);
 
 struct route_option_list *clone_route_option_list(const struct route_option_list *src, struct gc_arena *a);
 
 struct route_ipv6_option_list *clone_route_ipv6_option_list(const struct route_ipv6_option_list *src, struct gc_arena *a);
 
 void copy_route_option_list(struct route_option_list *dest, const struct route_option_list *src, struct gc_arena *a);
 
 void copy_route_ipv6_option_list(struct route_ipv6_option_list *dest,
                                  const struct route_ipv6_option_list *src,
                                  struct gc_arena *a);
 
 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_ipv4 *r,
                const struct tuntap *tt,
                unsigned int flags,
                const struct route_gateway_info *rgi,
                const struct env_set *es);
 
 void add_route_to_option_list(struct route_option_list *l,
                               const char *network,
                               const char *netmask,
                               const char *gateway,
                               const char *metric);
 
 void add_route_ipv6_to_option_list(struct route_ipv6_option_list *l,
                                    const char *prefix,
                                    const char *gateway,
                                    const char *metric);
 
 bool init_route_list(struct route_list *rl,
                      const struct route_option_list *opt,
                      const char *remote_endpoint,
                      int default_metric,
                      in_addr_t remote_host,
                      struct env_set *es);
 
 bool init_route_ipv6_list(struct route_ipv6_list *rl6,
                           const struct route_ipv6_option_list *opt6,
                           const char *remote_endpoint,
                           int default_metric,
                           const struct in6_addr *remote_host,
                           struct env_set *es);
 
 void route_list_add_vpn_gateway(struct route_list *rl,
                                 struct env_set *es,
                                 const in_addr_t addr);
 
 void add_routes(struct route_list *rl,
                 struct route_ipv6_list *rl6,
                 const struct tuntap *tt,
                 unsigned int flags,
                 const struct env_set *es);
 
 void delete_routes(struct route_list *rl,
                    struct route_ipv6_list *rl6,
                    const struct tuntap *tt,
                    unsigned int flags,
                    const struct env_set *es);
 
 void setenv_routes(struct env_set *es, const struct route_list *rl);
 
 void setenv_routes_ipv6(struct env_set *es, const struct route_ipv6_list *rl6);
 
 
 
 bool is_special_addr(const char *addr_str);
 
 void get_default_gateway(struct route_gateway_info *rgi);
 
 void get_default_gateway_ipv6(struct route_ipv6_gateway_info *rgi,
                               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
81d882d5
 int test_local_addr(const in_addr_t addr, const struct route_gateway_info *rgi);
5f31881e
 
6c61d0dd
 #ifndef ENABLE_SMALL
81d882d5
 void print_route_options(const struct route_option_list *rol,
                          int level);
 
6fbf66fa
 #endif
 
81d882d5
 void print_routes(const struct route_list *rl, int level);
6fbf66fa
 
445b192a
 #ifdef _WIN32
6fbf66fa
 
81d882d5
 void show_routes(int msglev);
6fbf66fa
 
81d882d5
 bool test_routes(const struct route_list *rl, 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  /* ifdef _WIN32 */
 static inline bool
4cd4899e
 test_routes(const struct route_list *rl, const struct tuntap *tt)
 {
81d882d5
     return true;
 }
6fbf66fa
 #endif
 
81d882d5
 bool netmask_to_netbits(const in_addr_t network, const in_addr_t netmask, int *netbits);
 
 int netmask_to_netbits2(in_addr_t netmask);
6fbf66fa
 
 static inline in_addr_t
81d882d5
 netbits_to_netmask(const int netbits)
6fbf66fa
 {
81d882d5
     const int addrlen = sizeof(in_addr_t) * 8;
     in_addr_t mask = 0;
     if (netbits > 0 && netbits <= addrlen)
     {
         mask = IPV4_NETMASK_HOST << (addrlen-netbits);
     }
     return mask;
6fbf66fa
 }
 
03731db3
 static inline bool
81d882d5
 route_list_vpn_gateway_needed(const struct route_list *rl)
03731db3
 {
81d882d5
     if (!rl)
     {
         return false;
     }
     else
     {
         return !(rl->spec.flags & RTSA_REMOTE_ENDPOINT);
     }
7fb0e07e
 }
 
 static inline int
 route_did_redirect_default_gateway(const struct route_list *rl)
 {
81d882d5
     return rl && BOOL_CAST(rl->iflags & RL_DID_REDIRECT_DEFAULT_GATEWAY);
03731db3
 }
 
81d882d5
 #endif /* ifndef ROUTE_H */