@ -12,11 +12,15 @@
* WHATSOEVER RESULTING FROM LOSS OF USE , DATA OR PROFITS , WHETHER IN AN
* ACTION OF CONTRACT , NEGLIGENCE OR OTHER TORTIOUS ACTION , ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE .
*
* solaris port of libtuntap ( c ) 2019 rick v
* all rights reserved , see LICENSE in top - level folder ( . . / . . / LICENSE )
*/
# include <sys/types.h>
# include <sys/ioctl.h>
# include <sys/socket.h>
# include <sys/sockio.h>
# include <arpa/inet.h>
# include <net/if.h>
@ -24,13 +28,22 @@
# include <net/if_types.h>
# include <netinet/if_ether.h>
# include <netinet/in.h>
# include <netinet/in_systm.h>
# include <netinet/ip.h>
# include <netinet/tcp.h>
# include <fcntl.h>
# include <stdint.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <strings.h>
# include <stropts.h>
# include <unistd.h>
# include <ctype.h>
# include <stdbool.h>
# include <errno.h>
# include <alloca.h>
# include "tuntap.h"
@ -39,59 +52,270 @@
static int
tuntap_sys_create_dev ( struct device * dev , int tun )
{
return - 1 ;
int if_fd , ip_muxid , ppa = - 1 ;
struct lifreq lifr ;
struct ifreq ifr ;
const char * ptr = NULL ;
struct strioctl strioc_ppa ;
/* improved generic TUN/TAP driver from
* http : //www.whiteboard.ne.jp/~admin2/tuntap/
* has IPv6 support . Most open - source variants of
* Solaris already have this driver in their package
* repos , Oracle Solaris users need to compile / load
* manually .
*/
explicit_bzero ( & lifr , sizeof lifr ) ;
if ( ( dev - > ip_fd = open ( " /dev/udp " , O_RDWR , 0 ) ) < 0 )
{
tuntap_log ( TUNTAP_LOG_ERR , " Can't open /dev/udp " ) ;
return - 1 ;
}
if ( ( dev - > tun_fd = open ( " /dev/tun " , O_RDWR , 0 ) ) < 0 )
{
tuntap_log ( TUNTAP_LOG_ERR , " Can't open /dev/tun " ) ;
return - 1 ;
}
/* get unit number */
if ( * dev - > if_name )
{
ptr = dev - > if_name ;
while ( * ptr & & ! isdigit ( ( int ) * ptr ) )
{
ptr + + ;
}
ppa = atoi ( ptr ) ;
}
/* Assign a new PPA and get its unit number. */
strioc_ppa . ic_cmd = TUNNEWPPA ;
strioc_ppa . ic_timout = 0 ;
strioc_ppa . ic_len = sizeof ( ppa ) ;
strioc_ppa . ic_dp = ( char * ) & ppa ;
if ( * ptr = = ' \0 ' ) /* no number given, try dynamic */
{
bool found_one = false ;
while ( ! found_one & & ppa < 64 )
{
int new_ppa = ioctl ( dev - > tun_fd , I_STR , & strioc_ppa ) ;
if ( new_ppa > = 0 )
{
char * msg = alloca ( 512 ) ;
sprintf ( msg , " got dynamic interface tun%i " , new_ppa ) ;
tuntap_log ( TUNTAP_LOG_INFO , msg ) ;
ppa = new_ppa ;
found_one = true ;
break ;
}
if ( errno ! = EEXIST )
{
tuntap_log ( TUNTAP_LOG_ERR , " unexpected error trying to find free tun interface " ) ;
return - 1 ;
}
ppa + + ;
}
if ( ! found_one )
{
tuntap_log ( TUNTAP_LOG_ERR , " could not find free tun interface, give up. " ) ;
return - 1 ;
}
}
else /* try this particular one */
{
if ( ( ppa = ioctl ( dev - > tun_fd , I_STR , & strioc_ppa ) ) < 0 )
{
char * msg = alloca ( 512 ) ;
sprintf ( msg , " Can't assign PPA for new interface (tun%i) " , ppa ) ;
tuntap_log ( TUNTAP_LOG_ERR , msg ) ;
return - 1 ;
}
}
if ( ( if_fd = open ( " /dev/tun " , O_RDWR , 0 ) ) < 0 )
{
tuntap_log ( TUNTAP_LOG_ERR , " Can't open /dev/tun (2) " ) ;
return - 1 ;
}
if ( ioctl ( if_fd , I_PUSH , " ip " ) < 0 )
{
tuntap_log ( TUNTAP_LOG_ERR , " Can't push IP module " ) ;
return - 1 ;
}
/* Assign ppa according to the unit number returned by tun device */
if ( ioctl ( if_fd , IF_UNITSEL , ( char * ) & ppa ) < 0 )
{
char * msg = alloca ( 512 ) ;
sprintf ( msg , " Can't set PPA %i " , ppa ) ;
tuntap_log ( TUNTAP_LOG_ERR , msg ) ;
return - 1 ;
}
snprintf ( dev - > internal_name , IF_NAMESIZE , " %s%d " , " tun " , ppa ) ;
if ( ( ip_muxid = ioctl ( dev - > ip_fd , I_PLINK , if_fd ) ) < 0 )
{
tuntap_log ( TUNTAP_LOG_ERR , " Can't link tun device to IP " ) ;
return - 1 ;
}
explicit_bzero ( & lifr , sizeof lifr ) ;
explicit_bzero ( & ifr , sizeof ifr ) ;
memcpy ( lifr . lifr_name , dev - > internal_name , sizeof ( lifr . lifr_name ) ) ;
lifr . lifr_ip_muxid = ip_muxid ;
if ( ioctl ( dev - > ip_fd , SIOCSLIFMUXID , & lifr ) < 0 )
{
ioctl ( dev - > ip_fd , I_PUNLINK , ip_muxid ) ;
tuntap_log ( TUNTAP_LOG_ERR , " Can't set multiplexor id " ) ;
return - 1 ;
}
fcntl ( dev - > tun_fd , F_SETFL , O_NONBLOCK ) ;
fcntl ( dev - > tun_fd , F_SETFD , FD_CLOEXEC ) ;
fcntl ( dev - > ip_fd , F_SETFD , FD_CLOEXEC ) ;
char * msg = alloca ( 512 ) ;
sprintf ( msg , " TUN device %s opened as %s " , dev - > if_name , dev - > internal_name ) ;
tuntap_log ( TUNTAP_LOG_INFO , msg ) ;
( void ) memcpy ( ifr . ifr_name , dev - > internal_name , sizeof dev - > internal_name ) ;
/* Get the interface default values */
if ( ioctl ( dev - > ctrl_sock , SIOCGIFFLAGS , & ifr ) = = - 1 )
{
tuntap_log ( TUNTAP_LOG_ERR , " Can't get interface values " ) ;
return - 1 ;
}
/* Save flags for tuntap_{up, down} */
dev - > flags = ifr . ifr_flags ;
return 0 ;
}
int
tuntap_sys_start ( struct device * dev , int mode , int tun )
tuntap_sys_start ( struct device * dev , int mode , int tun )
{
return - 1 ;
/* Forces automatic selection of device instance
* in tuntap_sys_create_dev ( ) .
* This also clears the specified interface name .
*/
if ( tun = = TUNTAP_ID_ANY )
memset ( & dev - > if_name , ' \0 ' , sizeof dev - > if_name ) ;
if ( mode = = TUNTAP_MODE_TUNNEL )
{
return tuntap_sys_create_dev ( dev , tun ) ;
}
else
return - 1 ;
/* NOTREACHED */
}
void
tuntap_sys_destroy ( struct device * dev )
{
return /*-1*/ ;
}
struct lifreq ifr ;
int
tuntap_sys_set_hwaddr ( struct device * dev , struct ether_addr * eth_addr )
{
return - 1 ;
explicit_bzero ( & ifr , sizeof ifr ) ;
strncpy ( ifr . lifr_name , dev - > internal_name , sizeof ( ifr . lifr_name ) ) ;
if ( ioctl ( dev - > ip_fd , SIOCGLIFFLAGS , & ifr ) < 0 )
{
tuntap_log ( TUNTAP_LOG_WARN , " Can't get iface flags " ) ;
}
if ( ioctl ( dev - > ip_fd , SIOCGLIFMUXID , & ifr ) < 0 )
{
tuntap_log ( TUNTAP_LOG_WARN , " Can't get multiplexor id " ) ;
}
/* we don't support TAP, and i think jaff stripped out TAP code a while
* back . . .
*/
if ( ioctl ( dev - > ip_fd , I_PUNLINK , ifr . lifr_ip_muxid ) < 0 )
{
tuntap_log ( TUNTAP_LOG_WARN , " Can't unlink interface(ip) " ) ;
}
close ( dev - > ip_fd ) ;
dev - > ip_fd = - 1 ;
}
int
tuntap_sys_set_ipv4 ( struct device * dev , t_tun_in_addr * s4 , uint32_t imask )
tuntap_sys_set_ipv4 ( struct device * dev , t_tun_in_addr * s4 , uint32_t bits)
{
return - 1 ;
struct lifreq ifr ;
struct sockaddr_in mask ;
( void ) memset ( & ifr , ' \0 ' , sizeof ifr ) ;
( void ) memcpy ( ifr . lifr_name , dev - > internal_name , sizeof dev - > internal_name ) ;
/* Set the IP address first */
( void ) memcpy ( & ( ( ( struct sockaddr_in * ) & ifr . lifr_addr ) - > sin_addr ) , s4 ,
sizeof ( struct in_addr ) ) ;
ifr . lifr_addr . ss_family = AF_INET ;
if ( ioctl ( dev - > ctrl_sock , SIOCSLIFADDR , & ifr ) = = - 1 )
{
tuntap_log ( TUNTAP_LOG_ERR , " Can't set IP address " ) ;
return - 1 ;
}
/* Reinit the struct ifr */
( void ) memset ( & ifr . lifr_addr , ' \0 ' , sizeof ifr . lifr_addr ) ;
/* Then set the netmask */
( void ) memset ( & mask , ' \0 ' , sizeof mask ) ;
mask . sin_family = AF_INET ;
mask . sin_addr . s_addr = bits ;
( void ) memcpy ( & ifr . lifr_addr , & mask , sizeof mask ) ;
if ( ioctl ( dev - > ctrl_sock , SIOCSLIFNETMASK , & ifr ) = = - 1 )
{
tuntap_log ( TUNTAP_LOG_ERR , " Can't set netmask " ) ;
return - 1 ;
}
return 0 ;
}
int
tuntap_sys_set_ipv6 ( struct device * dev , t_tun_in6_addr * s6 , uint32_t imask )
{
return - 1 ;
( void ) dev ;
( void ) s6 ;
( void ) imask ;
tuntap_log ( TUNTAP_LOG_NOTICE , " IPv6 is configured manually, this is currently unsupported " ) ;
return - 1 ;
}
int
tuntap_sys_set_ifname ( struct device * dev , const char * ifname , size_t len ) {
struct ifreq ifr ;
( void ) strncpy ( ifr . ifr_name , dev - > if_name , IF_NAMESIZE ) ;
( void ) strncpy ( ifr . ifr_newname , ifname , len ) ;
if ( ioctl ( dev - > ctrl_sock , SIOCSIFNAME , & ifr ) = = - 1 ) {
perror ( NULL ) ;
tuntap_log ( TUNTAP_LOG_ERR , " Can't set interface name " ) ;
return - 1 ;
}
return 0 ;
tuntap_sys_set_ifname ( struct device * dev , const char * ifname , size_t len )
{
/* Not quite sure if solaris SIOCSLIFNAME work the same way as on Linux,
* given the correct parameters .
*/
( void ) dev ;
( void ) ifname ;
( void ) len ;
tuntap_log ( TUNTAP_LOG_NOTICE ,
" Your system does not support tuntap_set_ifname() " ) ;
return - 1 ;
}
int
tuntap_sys_set_descr ( struct device * dev , const char * descr , size_t len )
{
( void ) dev ;
( void ) descr ;
( void ) len ;
return - 1 ;
}
( void ) dev ;
( void ) descr ;
( void ) len ;
tuntap_log ( TUNTAP_LOG_NOTICE ,
" Your system does not support tuntap_set_descr() " ) ;
return - 1 ;
}