2005-09-26 07:28:27 +02:00
/*
* 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 .
*
2010-04-28 18:31:36 +02:00
* Copyright ( C ) 2002 - 2010 OpenVPN Technologies , Inc . < sales @ openvpn . net >
2005-09-26 07:28:27 +02:00
*
* 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
*/
# include "syshead.h"
# include "forward.h"
# include "helper.h"
# include "pool.h"
# include "push.h"
# include "memdbg.h"
# if P2MP_SERVER
static const char *
print_netmask ( int netbits , struct gc_arena * gc )
{
struct buffer out = alloc_buf_gc ( 128 , gc ) ;
const in_addr_t netmask = netbits_to_netmask ( netbits ) ;
buf_printf ( & out , " %s (/%d) " , print_in_addr_t ( netmask , 0 , gc ) , netbits ) ;
return BSTR ( & out ) ;
}
static const char *
print_opt_route_gateway ( const in_addr_t route_gateway , struct gc_arena * gc )
{
struct buffer out = alloc_buf_gc ( 128 , gc ) ;
ASSERT ( route_gateway ) ;
buf_printf ( & out , " route-gateway %s " , print_in_addr_t ( route_gateway , 0 , gc ) ) ;
return BSTR ( & out ) ;
}
2008-08-02 10:02:53 +02:00
static const char *
print_opt_route_gateway_dhcp ( struct gc_arena * gc )
{
struct buffer out = alloc_buf_gc ( 32 , gc ) ;
buf_printf ( & out , " route-gateway dhcp " ) ;
return BSTR ( & out ) ;
}
2005-09-26 07:28:27 +02:00
static const char *
print_opt_route ( const in_addr_t network , const in_addr_t netmask , struct gc_arena * gc )
{
struct buffer out = alloc_buf_gc ( 128 , gc ) ;
ASSERT ( network ) ;
if ( netmask )
buf_printf ( & out , " route %s %s " ,
print_in_addr_t ( network , 0 , gc ) ,
print_in_addr_t ( netmask , 0 , gc ) ) ;
else
buf_printf ( & out , " route %s " ,
print_in_addr_t ( network , 0 , gc ) ) ;
return BSTR ( & out ) ;
}
2005-09-26 09:40:02 +02:00
static const char *
print_opt_topology ( const int topology , struct gc_arena * gc )
{
struct buffer out = alloc_buf_gc ( 128 , gc ) ;
buf_printf ( & out , " topology %s " , print_topology ( topology ) ) ;
return BSTR ( & out ) ;
}
2005-09-26 07:28:27 +02:00
static const char *
print_str_int ( const char * str , const int i , struct gc_arena * gc )
{
struct buffer out = alloc_buf_gc ( 128 , gc ) ;
buf_printf ( & out , " %s %d " , str , i ) ;
return BSTR ( & out ) ;
}
2008-11-18 06:15:22 +01:00
static const char *
print_str ( const char * str , struct gc_arena * gc )
{
struct buffer out = alloc_buf_gc ( 128 , gc ) ;
buf_printf ( & out , " %s " , str ) ;
return BSTR ( & out ) ;
}
2005-09-26 07:28:27 +02:00
static void
helper_add_route ( const in_addr_t network , const in_addr_t netmask , struct options * o )
{
rol_check_alloc ( o ) ;
add_route_to_option_list ( o - > routes ,
print_in_addr_t ( network , 0 , & o - > gc ) ,
print_in_addr_t ( netmask , 0 , & o - > gc ) ,
NULL ,
NULL ) ;
}
static void
verify_common_subnet ( const char * opt , const in_addr_t a , const in_addr_t b , const in_addr_t subnet )
{
struct gc_arena gc = gc_new ( ) ;
if ( ( a & subnet ) ! = ( b & subnet ) )
msg ( M_USAGE , " %s IP addresses %s and %s are not in the same %s subnet " ,
opt ,
print_in_addr_t ( a , 0 , & gc ) ,
print_in_addr_t ( b , 0 , & gc ) ,
print_in_addr_t ( subnet , 0 , & gc ) ) ;
gc_free ( & gc ) ;
}
# endif
/*
* Process server , server - bridge , and client helper
* directives after the parameters themselves have been
* parsed and placed in struct options .
*/
void
helper_client_server ( struct options * o )
{
struct gc_arena gc = gc_new ( ) ;
# if P2MP
# if P2MP_SERVER
/*
*
* HELPER DIRECTIVE :
*
* server 10.8 .0 .0 255.255 .255 .0
*
* EXPANDS TO :
*
* mode server
* tls - server
2005-09-26 09:40:02 +02:00
* push " topology [topology] "
2005-09-26 07:28:27 +02:00
*
2005-09-26 09:40:02 +02:00
* if tun AND ( topology = = net30 OR topology = = p2p ) :
* ifconfig 10.8 .0 .1 10.8 .0 .2
* if ! nopool :
* ifconfig - pool 10.8 .0 .4 10.8 .0 .251
2005-09-26 07:28:27 +02:00
* route 10.8 .0 .0 255.255 .255 .0
* if client - to - client :
* push " route 10.8.0.0 255.255.255.0 "
2005-09-26 09:40:02 +02:00
* else if topology = = net30 :
2005-09-26 07:28:27 +02:00
* push " route 10.8.0.1 "
*
2005-09-26 09:40:02 +02:00
* if tap OR ( tun AND topology = = subnet ) :
2005-09-26 07:28:27 +02:00
* ifconfig 10.8 .0 .1 255.255 .255 .0
2005-09-26 09:40:02 +02:00
* if ! nopool :
* ifconfig - pool 10.8 .0 .2 10.8 .0 .254 255.255 .255 .0
2005-09-26 07:28:27 +02:00
* push " route-gateway 10.8.0.1 "
*/
/*
* Get tun / tap / null device type
*/
const int dev = dev_type_enum ( o - > dev , o - > dev_type ) ;
2005-09-26 09:40:02 +02:00
const int topology = o - > topology ;
2005-09-26 07:28:27 +02:00
if ( o - > server_defined )
{
int netbits = - 2 ;
bool status = false ;
if ( o - > client )
msg ( M_USAGE , " --server and --client cannot be used together " ) ;
2008-08-02 10:02:53 +02:00
if ( o - > server_bridge_defined | | o - > server_bridge_proxy_dhcp )
2005-09-26 07:28:27 +02:00
msg ( M_USAGE , " --server and --server-bridge cannot be used together " ) ;
if ( o - > shared_secret_file )
msg ( M_USAGE , " --server and --secret cannot be used together (you must use SSL/TLS keys) " ) ;
2008-11-03 14:07:33 +01:00
if ( ! ( o - > server_flags & SF_NOPOOL ) & & o - > ifconfig_pool_defined )
2005-09-26 07:28:27 +02:00
msg ( M_USAGE , " --server already defines an ifconfig-pool, so you can't also specify --ifconfig-pool explicitly " ) ;
if ( ! ( dev = = DEV_TYPE_TAP | | dev = = DEV_TYPE_TUN ) )
msg ( M_USAGE , " --server directive only makes sense with --dev tun or --dev tap " ) ;
status = netmask_to_netbits ( o - > server_network , o - > server_netmask , & netbits ) ;
if ( ! status )
msg ( M_USAGE , " --server directive network/netmask combination is invalid " ) ;
if ( netbits < 0 )
msg ( M_USAGE , " --server directive netmask is invalid " ) ;
if ( netbits < IFCONFIG_POOL_MIN_NETBITS )
msg ( M_USAGE , " --server directive netmask allows for too many host addresses (subnet must be %s or higher) " ,
print_netmask ( IFCONFIG_POOL_MIN_NETBITS , & gc ) ) ;
if ( dev = = DEV_TYPE_TUN )
{
int pool_end_reserve = 4 ;
if ( netbits > 29 )
msg ( M_USAGE , " --server directive when used with --dev tun must define a subnet of %s or lower " ,
print_netmask ( 29 , & gc ) ) ;
if ( netbits = = 29 )
pool_end_reserve = 0 ;
o - > mode = MODE_SERVER ;
o - > tls_server = true ;
2005-09-26 09:40:02 +02:00
if ( topology = = TOP_NET30 | | topology = = TOP_P2P )
{
o - > ifconfig_local = print_in_addr_t ( o - > server_network + 1 , 0 , & o - > gc ) ;
o - > ifconfig_remote_netmask = print_in_addr_t ( o - > server_network + 2 , 0 , & o - > gc ) ;
if ( ! ( o - > server_flags & SF_NOPOOL ) )
{
o - > ifconfig_pool_defined = true ;
o - > ifconfig_pool_start = o - > server_network + 4 ;
o - > ifconfig_pool_end = ( o - > server_network | ~ o - > server_netmask ) - pool_end_reserve ;
2005-12-14 02:09:11 +01:00
ifconfig_pool_verify_range ( M_USAGE , o - > ifconfig_pool_start , o - > ifconfig_pool_end ) ;
2005-09-26 09:40:02 +02:00
}
helper_add_route ( o - > server_network , o - > server_netmask , o ) ;
if ( o - > enable_c2c )
push_option ( o , print_opt_route ( o - > server_network , o - > server_netmask , & o - > gc ) , M_USAGE ) ;
else if ( topology = = TOP_NET30 )
push_option ( o , print_opt_route ( o - > server_network + 1 , 0 , & o - > gc ) , M_USAGE ) ;
}
else if ( topology = = TOP_SUBNET )
{
o - > ifconfig_local = print_in_addr_t ( o - > server_network + 1 , 0 , & o - > gc ) ;
o - > ifconfig_remote_netmask = print_in_addr_t ( o - > server_netmask , 0 , & o - > gc ) ;
if ( ! ( o - > server_flags & SF_NOPOOL ) )
{
o - > ifconfig_pool_defined = true ;
o - > ifconfig_pool_start = o - > server_network + 2 ;
o - > ifconfig_pool_end = ( o - > server_network | ~ o - > server_netmask ) - 2 ;
2005-12-14 02:09:11 +01:00
ifconfig_pool_verify_range ( M_USAGE , o - > ifconfig_pool_start , o - > ifconfig_pool_end ) ;
2005-09-26 09:40:02 +02:00
}
2008-11-03 14:07:33 +01:00
o - > ifconfig_pool_netmask = o - > server_netmask ;
2005-09-26 09:40:02 +02:00
push_option ( o , print_opt_route_gateway ( o - > server_network + 1 , & o - > gc ) , M_USAGE ) ;
}
else
ASSERT ( 0 ) ;
push_option ( o , print_opt_topology ( topology , & o - > gc ) , M_USAGE ) ;
2005-09-26 07:28:27 +02:00
}
else if ( dev = = DEV_TYPE_TAP )
{
2005-11-04 01:05:02 +01:00
if ( netbits > 30 )
2005-09-26 07:28:27 +02:00
msg ( M_USAGE , " --server directive when used with --dev tap must define a subnet of %s or lower " ,
print_netmask ( 30 , & gc ) ) ;
o - > mode = MODE_SERVER ;
o - > tls_server = true ;
o - > ifconfig_local = print_in_addr_t ( o - > server_network + 1 , 0 , & o - > gc ) ;
o - > ifconfig_remote_netmask = print_in_addr_t ( o - > server_netmask , 0 , & o - > gc ) ;
2005-09-26 09:40:02 +02:00
if ( ! ( o - > server_flags & SF_NOPOOL ) )
{
o - > ifconfig_pool_defined = true ;
o - > ifconfig_pool_start = o - > server_network + 2 ;
o - > ifconfig_pool_end = ( o - > server_network | ~ o - > server_netmask ) - 1 ;
2005-12-14 02:09:11 +01:00
ifconfig_pool_verify_range ( M_USAGE , o - > ifconfig_pool_start , o - > ifconfig_pool_end ) ;
2005-09-26 09:40:02 +02:00
}
2008-11-03 14:07:33 +01:00
o - > ifconfig_pool_netmask = o - > server_netmask ;
2005-09-26 09:40:02 +02:00
2005-09-26 07:28:27 +02:00
push_option ( o , print_opt_route_gateway ( o - > server_network + 1 , & o - > gc ) , M_USAGE ) ;
}
else
{
ASSERT ( 0 ) ;
}
2005-09-26 09:40:02 +02:00
/* set push-ifconfig-constraint directive */
if ( ( dev = = DEV_TYPE_TAP | | topology = = TOP_SUBNET ) )
{
o - > push_ifconfig_constraint_defined = true ;
o - > push_ifconfig_constraint_network = o - > server_network ;
o - > push_ifconfig_constraint_netmask = o - > server_netmask ;
}
2005-09-26 07:28:27 +02:00
}
/*
* HELPER DIRECTIVE :
*
* server - bridge 10.8 .0 .4 255.255 .255 .0 10.8 .0 .128 10.8 .0 .254
*
* EXPANDS TO :
*
* mode server
* tls - server
*
* ifconfig - pool 10.8 .0 .128 10.8 .0 .254 255.255 .255 .0
* push " route-gateway 10.8.0.4 "
2008-08-02 10:02:53 +02:00
*
* OR
*
* server - bridge
*
* EXPANDS TO :
*
* mode server
* tls - server
*
2008-11-20 22:02:10 +01:00
* if ! nogw :
* push " route-gateway dhcp "
2005-09-26 07:28:27 +02:00
*/
2008-08-02 10:02:53 +02:00
else if ( o - > server_bridge_defined | o - > server_bridge_proxy_dhcp )
2005-09-26 07:28:27 +02:00
{
if ( o - > client )
msg ( M_USAGE , " --server-bridge and --client cannot be used together " ) ;
2008-11-03 14:07:33 +01:00
if ( ! ( o - > server_flags & SF_NOPOOL ) & & o - > ifconfig_pool_defined )
2005-09-26 07:28:27 +02:00
msg ( M_USAGE , " --server-bridge already defines an ifconfig-pool, so you can't also specify --ifconfig-pool explicitly " ) ;
if ( o - > shared_secret_file )
msg ( M_USAGE , " --server-bridge and --secret cannot be used together (you must use SSL/TLS keys) " ) ;
if ( dev ! = DEV_TYPE_TAP )
msg ( M_USAGE , " --server-bridge directive only makes sense with --dev tap " ) ;
2008-08-02 10:02:53 +02:00
if ( o - > server_bridge_defined )
{
verify_common_subnet ( " --server-bridge " , o - > server_bridge_ip , o - > server_bridge_pool_start , o - > server_bridge_netmask ) ;
verify_common_subnet ( " --server-bridge " , o - > server_bridge_pool_start , o - > server_bridge_pool_end , o - > server_bridge_netmask ) ;
verify_common_subnet ( " --server-bridge " , o - > server_bridge_ip , o - > server_bridge_pool_end , o - > server_bridge_netmask ) ;
}
2005-09-26 07:28:27 +02:00
o - > mode = MODE_SERVER ;
o - > tls_server = true ;
2008-08-02 10:02:53 +02:00
if ( o - > server_bridge_defined )
{
o - > ifconfig_pool_defined = true ;
o - > ifconfig_pool_start = o - > server_bridge_pool_start ;
o - > ifconfig_pool_end = o - > server_bridge_pool_end ;
ifconfig_pool_verify_range ( M_USAGE , o - > ifconfig_pool_start , o - > ifconfig_pool_end ) ;
o - > ifconfig_pool_netmask = o - > server_bridge_netmask ;
push_option ( o , print_opt_route_gateway ( o - > server_bridge_ip , & o - > gc ) , M_USAGE ) ;
}
2008-11-20 22:02:10 +01:00
else if ( o - > server_bridge_proxy_dhcp & & ! ( o - > server_flags & SF_NO_PUSH_ROUTE_GATEWAY ) )
2008-08-02 10:02:53 +02:00
{
push_option ( o , print_opt_route_gateway_dhcp ( & o - > gc ) , M_USAGE ) ;
}
2005-09-26 07:28:27 +02:00
}
else
# endif /* P2MP_SERVER */
/*
* HELPER DIRECTIVE :
*
* client
*
* EXPANDS TO :
*
* pull
* tls - client
*/
if ( o - > client )
{
if ( o - > key_method ! = 2 )
msg ( M_USAGE , " --client requires --key-method 2 " ) ;
o - > pull = true ;
o - > tls_client = true ;
}
# endif /* P2MP */
gc_free ( & gc ) ;
}
/*
*
* HELPER DIRECTIVE :
*
* keepalive 10 60
*
* EXPANDS TO :
*
* if mode server :
* ping 10
* ping - restart 120
* push " ping 10 "
* push " ping-restart 60 "
* else
* ping 10
* ping - restart 60
*/
void
helper_keepalive ( struct options * o )
{
if ( o - > keepalive_ping | | o - > keepalive_timeout )
{
/*
* Sanity checks .
*/
if ( o - > keepalive_ping < = 0 | | o - > keepalive_timeout < = 0 )
msg ( M_USAGE , " --keepalive parameters must be > 0 " ) ;
if ( o - > keepalive_ping * 2 > o - > keepalive_timeout )
msg ( M_USAGE , " the second parameter to --keepalive (restart timeout=%d) must be at least twice the value of the first parameter (ping interval=%d). A ratio of 1:5 or 1:6 would be even better. Recommended setting is --keepalive 10 60. " ,
o - > keepalive_timeout ,
o - > keepalive_ping ) ;
if ( o - > ping_send_timeout | | o - > ping_rec_timeout )
msg ( M_USAGE , " --keepalive conflicts with --ping, --ping-exit, or --ping-restart. If you use --keepalive, you don't need any of the other --ping directives. " ) ;
/*
* Expand .
*/
if ( o - > mode = = MODE_POINT_TO_POINT )
{
o - > ping_rec_timeout_action = PING_RESTART ;
o - > ping_send_timeout = o - > keepalive_ping ;
o - > ping_rec_timeout = o - > keepalive_timeout ;
}
# if P2MP_SERVER
else if ( o - > mode = = MODE_SERVER )
{
o - > ping_rec_timeout_action = PING_RESTART ;
o - > ping_send_timeout = o - > keepalive_ping ;
o - > ping_rec_timeout = o - > keepalive_timeout * 2 ;
push_option ( o , print_str_int ( " ping " , o - > keepalive_ping , & o - > gc ) , M_USAGE ) ;
push_option ( o , print_str_int ( " ping-restart " , o - > keepalive_timeout , & o - > gc ) , M_USAGE ) ;
}
# endif
else
{
ASSERT ( 0 ) ;
}
}
}
2008-11-18 06:15:22 +01:00
/*
*
* HELPER DIRECTIVE :
*
* tcp - nodelay
*
* EXPANDS TO :
*
* if mode server :
* socket - flags TCP_NODELAY
* push " socket-flags TCP_NODELAY "
*/
void
helper_tcp_nodelay ( struct options * o )
{
# if P2MP_SERVER
if ( o - > server_flags & SF_TCP_NODELAY_HELPER )
{
if ( o - > mode = = MODE_SERVER )
{
o - > sockflags | = SF_TCP_NODELAY ;
push_option ( o , print_str ( " socket-flags TCP_NODELAY " , & o - > gc ) , M_USAGE ) ;
}
else
{
ASSERT ( 0 ) ;
}
}
# endif
}