include libtuntap

pull/3/head
Ryan Tharp 6 years ago
parent 15df397cd3
commit e41ad35c9f

@ -0,0 +1,137 @@
# libtuntap CMakeLists.txt
# ========================
project(libtuntap)
cmake_minimum_required(VERSION 2.8)
# CMake global options
# --------------------
option(ENABLE_REGRESS "Enable the regression tests" OFF)
option(ENABLE_CXX "Enable the C++ wrapper library" OFF)
option(ENABLE_PYTHON "Enable the Python wrapper library" OFF)
if(ENABLE_PYTHON AND NOT ENABLE_CXX)
set(ENABLE_CXX ON)
message(WARNING "ENABLE_CXX also set to ON")
endif()
# CMake Configuration
# -------------------
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
set(CMAKE_INSTALL_PREFIX "/usr/local/")
set(${CMAKE_SYSTEM_NAME} True)
# Global CPP definitions
# ----------------------
add_definitions(-D${CMAKE_SYSTEM_NAME})
# Portable source files
# ---------------------
set(SOURCES_LIST
tuntap.c
tuntap_log.c
)
# OS families specific things
# ---------------------------
if(UNIX)
# Unix specific include directories
# ---------------------------------
include_directories(
"${CMAKE_CURRENT_SOURCE_DIR}"
/usr/include/
/usr/local/include
)
# Unix specific definitions
# -------------------------
add_definitions(-DUnix)
# Unix specific source files
# --------------------------
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix.c )
endif(UNIX)
if(Windows)
# Windows specific definitions
# ----------------------------
add_definitions(-DWindows)
# Windows specific source files
# -----------------------------
set(SOURCES_LIST ${SOURCES_LIST} tuntap-windows.c )
endif(Windows)
# OS specific things
# ------------------
if(UNIX)
if(Linux)
set(CMAKE_INSTALL_PREFIX "/usr/")
add_definitions(-D_GNU_SOURCE)
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix-linux.c)
elseif (OpenBSD)
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix-openbsd.c)
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix-bsd.c)
elseif (NetBSD)
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix-netbsd.c)
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix-bsd.c)
elseif (FreeBSD)
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix-freebsd.c)
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix-bsd.c)
elseif (Darwin)
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix-darwin.c)
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix-bsd.c)
elseif (DragonFly)
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix-freebsd.c)
set(SOURCES_LIST ${SOURCES_LIST} tuntap-unix-bsd.c)
else()
message(FATAL_ERROR "Your operating system is not supported yet")
endif()
endif(UNIX)
# Library definition
# ------------------
add_library(tuntap SHARED ${SOURCES_LIST} tuntap.h)
set_target_properties(tuntap PROPERTIES VERSION 2.1)
add_library(tuntap-static STATIC ${SOURCES_LIST})
set_target_properties(tuntap-static PROPERTIES OUTPUT_NAME "tuntap")
if(UNIX)
set_target_properties(tuntap-static PROPERTIES PREFIX "lib")
endif(UNIX)
if(Windows)
target_link_libraries(tuntap Ws2_32.lib)
target_link_libraries(tuntap-static Ws2_32.lib)
endif(Windows)
# C++ Binding definition
# ----------------------
if(ENABLE_CXX)
include(bindings/cpp/CMakeLists.txt)
endif(ENABLE_CXX)
# Python Binding definition
# -------------------------
if(ENABLE_PYTHON)
include(bindings/python/CMakeLists.txt)
endif (ENABLE_PYTHON)
# Install rules
# -------------
if(UNIX)
install(TARGETS tuntap DESTINATION lib)
install(TARGETS tuntap-static DESTINATION lib)
install(FILES tuntap.h DESTINATION include)
target_include_directories(tuntap INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
endif(UNIX)
include(CMakeLists.txt.local OPTIONAL)
# Tests rules
# -----------
if (ENABLE_REGRESS)
include(regress/CMakeLists.txt)
endif (ENABLE_REGRESS)

@ -0,0 +1,377 @@
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.9
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/local/bin/cmake
# The command to remove a file.
RM = /usr/local/bin/cmake -E remove -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /Users/rtharp/Sites/llarp/vendor/libtuntap-master
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /Users/rtharp/Sites/llarp/vendor/libtuntap-master
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target install/local
install/local: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
/usr/local/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
.PHONY : install/local
# Special rule for the target install/local
install/local/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
/usr/local/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
.PHONY : install/local/fast
# Special rule for the target install/strip
install/strip: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
/usr/local/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
.PHONY : install/strip
# Special rule for the target install/strip
install/strip/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
/usr/local/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
.PHONY : install/strip/fast
# Special rule for the target install
install: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
/usr/local/bin/cmake -P cmake_install.cmake
.PHONY : install
# Special rule for the target install
install/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
/usr/local/bin/cmake -P cmake_install.cmake
.PHONY : install/fast
# Special rule for the target list_install_components
list_install_components:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\""
.PHONY : list_install_components
# Special rule for the target list_install_components
list_install_components/fast: list_install_components
.PHONY : list_install_components/fast
# Special rule for the target rebuild_cache
rebuild_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
/usr/local/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# Special rule for the target edit_cache
edit_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
/usr/local/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start /Users/rtharp/Sites/llarp/vendor/libtuntap-master/CMakeFiles /Users/rtharp/Sites/llarp/vendor/libtuntap-master/CMakeFiles/progress.marks
$(MAKE) -f CMakeFiles/Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start /Users/rtharp/Sites/llarp/vendor/libtuntap-master/CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) -f CMakeFiles/Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named tuntap-static
# Build rule for target.
tuntap-static: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 tuntap-static
.PHONY : tuntap-static
# fast build rule for target.
tuntap-static/fast:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/build
.PHONY : tuntap-static/fast
#=============================================================================
# Target rules for targets named tuntap
# Build rule for target.
tuntap: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 tuntap
.PHONY : tuntap
# fast build rule for target.
tuntap/fast:
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/build
.PHONY : tuntap/fast
tuntap-unix-bsd.o: tuntap-unix-bsd.c.o
.PHONY : tuntap-unix-bsd.o
# target to build an object file
tuntap-unix-bsd.c.o:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap-unix-bsd.c.o
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap-unix-bsd.c.o
.PHONY : tuntap-unix-bsd.c.o
tuntap-unix-bsd.i: tuntap-unix-bsd.c.i
.PHONY : tuntap-unix-bsd.i
# target to preprocess a source file
tuntap-unix-bsd.c.i:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap-unix-bsd.c.i
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap-unix-bsd.c.i
.PHONY : tuntap-unix-bsd.c.i
tuntap-unix-bsd.s: tuntap-unix-bsd.c.s
.PHONY : tuntap-unix-bsd.s
# target to generate assembly for a file
tuntap-unix-bsd.c.s:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap-unix-bsd.c.s
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap-unix-bsd.c.s
.PHONY : tuntap-unix-bsd.c.s
tuntap-unix-darwin.o: tuntap-unix-darwin.c.o
.PHONY : tuntap-unix-darwin.o
# target to build an object file
tuntap-unix-darwin.c.o:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap-unix-darwin.c.o
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap-unix-darwin.c.o
.PHONY : tuntap-unix-darwin.c.o
tuntap-unix-darwin.i: tuntap-unix-darwin.c.i
.PHONY : tuntap-unix-darwin.i
# target to preprocess a source file
tuntap-unix-darwin.c.i:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap-unix-darwin.c.i
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap-unix-darwin.c.i
.PHONY : tuntap-unix-darwin.c.i
tuntap-unix-darwin.s: tuntap-unix-darwin.c.s
.PHONY : tuntap-unix-darwin.s
# target to generate assembly for a file
tuntap-unix-darwin.c.s:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap-unix-darwin.c.s
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap-unix-darwin.c.s
.PHONY : tuntap-unix-darwin.c.s
tuntap-unix.o: tuntap-unix.c.o
.PHONY : tuntap-unix.o
# target to build an object file
tuntap-unix.c.o:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap-unix.c.o
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap-unix.c.o
.PHONY : tuntap-unix.c.o
tuntap-unix.i: tuntap-unix.c.i
.PHONY : tuntap-unix.i
# target to preprocess a source file
tuntap-unix.c.i:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap-unix.c.i
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap-unix.c.i
.PHONY : tuntap-unix.c.i
tuntap-unix.s: tuntap-unix.c.s
.PHONY : tuntap-unix.s
# target to generate assembly for a file
tuntap-unix.c.s:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap-unix.c.s
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap-unix.c.s
.PHONY : tuntap-unix.c.s
tuntap.o: tuntap.c.o
.PHONY : tuntap.o
# target to build an object file
tuntap.c.o:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap.c.o
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap.c.o
.PHONY : tuntap.c.o
tuntap.i: tuntap.c.i
.PHONY : tuntap.i
# target to preprocess a source file
tuntap.c.i:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap.c.i
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap.c.i
.PHONY : tuntap.c.i
tuntap.s: tuntap.c.s
.PHONY : tuntap.s
# target to generate assembly for a file
tuntap.c.s:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap.c.s
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap.c.s
.PHONY : tuntap.c.s
tuntap_log.o: tuntap_log.c.o
.PHONY : tuntap_log.o
# target to build an object file
tuntap_log.c.o:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap_log.c.o
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap_log.c.o
.PHONY : tuntap_log.c.o
tuntap_log.i: tuntap_log.c.i
.PHONY : tuntap_log.i
# target to preprocess a source file
tuntap_log.c.i:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap_log.c.i
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap_log.c.i
.PHONY : tuntap_log.c.i
tuntap_log.s: tuntap_log.c.s
.PHONY : tuntap_log.s
# target to generate assembly for a file
tuntap_log.c.s:
$(MAKE) -f CMakeFiles/tuntap-static.dir/build.make CMakeFiles/tuntap-static.dir/tuntap_log.c.s
$(MAKE) -f CMakeFiles/tuntap.dir/build.make CMakeFiles/tuntap.dir/tuntap_log.c.s
.PHONY : tuntap_log.c.s
# Help Target
help:
@echo "The following are some of the valid targets for this Makefile:"
@echo "... all (the default if no target is provided)"
@echo "... clean"
@echo "... depend"
@echo "... install/local"
@echo "... install/strip"
@echo "... install"
@echo "... list_install_components"
@echo "... tuntap-static"
@echo "... rebuild_cache"
@echo "... edit_cache"
@echo "... tuntap"
@echo "... tuntap-unix-bsd.o"
@echo "... tuntap-unix-bsd.i"
@echo "... tuntap-unix-bsd.s"
@echo "... tuntap-unix-darwin.o"
@echo "... tuntap-unix-darwin.i"
@echo "... tuntap-unix-darwin.s"
@echo "... tuntap-unix.o"
@echo "... tuntap-unix.i"
@echo "... tuntap-unix.s"
@echo "... tuntap.o"
@echo "... tuntap.i"
@echo "... tuntap.s"
@echo "... tuntap_log.o"
@echo "... tuntap_log.i"
@echo "... tuntap_log.s"
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
.PHONY : cmake_check_build_system

@ -0,0 +1,53 @@
libtuntap
=========
Description
-----------
libtuntap is a library for configuring TUN or TAP devices in a portable manner.
TUN and TAP are virtual networking devices which allow userland applications
to receive packets sent to it. The userland applications can also send their
own packets to the devices and they will be forwarded to the kernel.
This is useful for developping tunnels, private networks or virtualisation
systems.
Supported Features
------------------
* Creation of TUN _and_ TAP devices;
* Autodetection of available TUN or TAP devices;
* Setting and getting the MAC address of the device;
* Setting and getting the MTU of the device;
* Setting the status of the device (up/down);
* Setting the IPv4 address and netmask of the device;
* Setting the persistence mode of the device;
* Setting the name of the device (Linux only);
* Setting the description of the device (OpenBSD and FreeBSD only).
Supported Systems
-----------------
* OpenBSD;
* Linux;
* NetBSD;
* Darwin.
Current Porting Efforts
-----------------------
* Windows;
* FreeBSD.
In the future
-------------
* AIX;
* Solaris.
License
-------
All the code is licensed under the ISC License.
It's free, not GPLed !

@ -0,0 +1,17 @@
# TODO
- [ ] Create a system of automatic testing with VMs
- [X] OpenBSD vm
- [X] Debian vm
- [ ] Import some patches from dev branch in master
- [ ] tuntap_get_descr() is not implemented in master
- [X] Test on OpenBSD (not working)
- [ ] Fix tuntap-unix-openbsd.c
- [ ] Test on NetBSD
- [ ] Test on FreeBSD
- [ ] Test on Darwin
- [X] Test on Debian (working)
- [ ] Fix shell scripts based tests test35 and test36
- [ ] Test on FreeBSD
- [ ] Test on Windows
- [ ] Move away from cmake?

@ -0,0 +1,7 @@
libtuntap bindings
==================
libtuntap supports bindings in C++ and Python, thanks to Fabien Pichot
(@drepdash on Github). This is a work in progress.
Support for more languages is planned.

@ -0,0 +1,24 @@
# libtuntap C++ binding CMakeLists.txt
# ====================================
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/bindings/cpp
)
add_library(tuntap++ SHARED
${CMAKE_CURRENT_SOURCE_DIR}/bindings/cpp/tuntap++.cc
${CMAKE_CURRENT_SOURCE_DIR}/bindings/cpp/tuntap++.hh
)
set_target_properties(tuntap++ PROPERTIES VERSION 2.1)
add_library(tuntap++-static STATIC
${CMAKE_CURRENT_SOURCE_DIR}/bindings/cpp/tuntap++.cc
${CMAKE_CURRENT_SOURCE_DIR}/bindings/cpp/tuntap++.hh
)
set_target_properties(tuntap++-static PROPERTIES OUTPUT_NAME "tuntap++")
target_link_libraries(tuntap++ tuntap)
target_link_libraries(tuntap++-static tuntap)
target_include_directories(tuntap++ INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/bindings/cpp)

@ -0,0 +1,176 @@
#include "tuntap++.hh"
#include <iostream>
#include <string>
#include <algorithm>
namespace tuntap {
tun::tun()
: _dev{tuntap_init()}
{
tuntap_start(_dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY);
}
tun::~tun()
{
tuntap_destroy(_dev);
}
tun::tun(tun &&t)
: _dev(nullptr)
{
std::swap(t._dev, this->_dev);
}
void
tun::release()
{
tuntap_release(_dev);
}
std::string
tun::name() const
{
return tuntap_get_ifname(_dev);
}
void
tun::name(std::string const &s)
{
tuntap_set_ifname(_dev, s.c_str());
}
t_tun
tun::native_handle() const
{
return TUNTAP_GET_FD(this->_dev);
}
void
tun::up()
{
tuntap_up(_dev);
}
void
tun::down()
{
tuntap_down(_dev);
}
int
tun::mtu() const
{
return tuntap_get_mtu(_dev);
}
void
tun::mtu(int m)
{
tuntap_set_mtu(_dev, m);
}
void
tun::ip(std::string const &s, int netmask)
{
tuntap_set_ip(_dev, s.c_str(), netmask);
}
void
tun::nonblocking(bool b)
{
tuntap_set_nonblocking(_dev, int(b));
}
tap::tap()
: _dev{tuntap_init()}
{
tuntap_start(_dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY);
}
tap::~tap()
{
tuntap_destroy(_dev);
}
tap::tap(tap &&t)
: _dev(nullptr)
{
std::swap(t._dev, this->_dev);
}
void
tap::release()
{
tuntap_release(_dev);
}
std::string
tap::name() const
{
return tuntap_get_ifname(_dev);
}
void
tap::name(std::string const &s)
{
tuntap_set_ifname(_dev, s.c_str());
}
std::string
tap::hwaddr() const
{
return tuntap_get_hwaddr(_dev);
}
void
tap::hwaddr(std::string const &s)
{
tuntap_set_hwaddr(_dev, s.c_str());
}
t_tun
tap::native_handle() const
{
return TUNTAP_GET_FD(this->_dev);
}
void
tap::up()
{
tuntap_up(_dev);
}
void
tap::down()
{
tuntap_down(_dev);
}
int
tap::mtu() const
{
return tuntap_get_mtu(_dev);
}
void
tap::mtu(int m)
{
tuntap_set_mtu(_dev, m);
}
void
tap::ip(std::string const &s, int netmask)
{
tuntap_set_ip(_dev, s.c_str(), netmask);
}
void
tap::nonblocking(bool b)
{
tuntap_set_nonblocking(_dev, int(b));
}
} /* tuntap */

@ -0,0 +1,72 @@
#pragma once
#ifndef LIBTUNTAP_ALY0MA60
#define LIBTUNTAP_ALY0MA60
#include <string>
#include <tuntap.h>
namespace tuntap {
class tun
{
public:
tun();
~tun();
tun(tun const &) = delete;
tun & operator = (tun const &) = delete;
tun(tun &&);
// Properties
std::string name() const;
void name(std::string const &);
int mtu() const ;
void mtu(int);
t_tun native_handle() const;
// Network
void up();
void down();
void ip(std::string const &presentation, int netmask);
// System
void release();
void nonblocking(bool);
private:
struct device* _dev;
};
class tap
{
public:
tap();
~tap();
tap(tap const &) = delete;
tap & operator = (tap const &) = delete;
tap(tap &&);
// Properties
std::string name() const;
void name(std::string const &);
std::string hwaddr() const;
void hwaddr(std::string const &);
int mtu() const;
void mtu(int);
t_tun native_handle() const;
// Network
void up();
void down();
void ip(std::string const &presentation, int netmask);
// System
void release();
void nonblocking(bool);
private:
struct device* _dev;
};
} /* tuntap */
#endif /* end of include guard: LIBTUNTAP_ALY0MA60 */

@ -0,0 +1,32 @@
# libtuntap python binding CMakeLists.txt
# =======================================
find_package(PythonLibs)
find_package(Boost COMPONENTS system thread python)
if(${PYTHONLIBS_FOUND} AND ${Boost_FOUND})
include_directories(${PYTHON_INCLUDE_PATH})
include_directories(${Boost_INCLUDE_PATH})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bindings/cpp)
add_library(python-tuntap SHARED
${CMAKE_CURRENT_SOURCE_DIR}/bindings/python/pytuntap.cc
)
target_link_libraries(python-tuntap
${PYTHON_LIBRARIES}
${Boost_LIBRARIES}
tuntap++
)
add_custom_command(TARGET python-tuntap POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${PROJECT_SOURCE_DIR}/bindings/python/__init__.py"
"${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/bindings/python/pytuntap"
)
set_target_properties(python-tuntap PROPERTIES OUTPUT_NAME "_pytuntap")
set_target_properties(python-tuntap PROPERTIES PREFIX "")
set_target_properties(python-tuntap
PROPERTIES LIBRARY_OUTPUT_DIRECTORY
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/bindings/python/pytuntap
)
endif()

@ -0,0 +1,24 @@
from _pytuntap import *
import io
class TunTapFileIO(io.FileIO):
def __init__(self, tuntap):
super(TunTapFileIO, self).__init__(tuntap.native_handle, 'rb+')
def read(self, size):
return memoryview(bytearray(super(TunTapFileIO, self).read(size)))
def readinto():
raise NotImplementedError
def readall():
raise NotImplementedError
def writelines():
raise NotImplementedError
def _file(self):
return TunTapFileIO(self)
Tap.file = _file
Tun.file = _file

@ -0,0 +1,44 @@
#include "tuntap++.hh"
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(_pytuntap)
{
using namespace tuntap;
using namespace boost::python;
std::string (tap::*tap_get_name)() const = &tap::name;
void (tap::*tap_set_name)(std::string const &) = &tap::name;
std::string (tap::*tap_get_hwaddr)() const = &tap::hwaddr;
void (tap::*tap_set_hwaddr)(std::string const &) = &tap::hwaddr;
int (tap::*tap_get_mtu)() const = &tap::mtu;
void (tap::*tap_set_mtu)(int) = &tap::mtu;
std::string (tun::*tun_get_name)() const = &tun::name;
void (tun::*tun_set_name)(std::string const &) = &tun::name;
int (tun::*tun_get_mtu)() const = &tun::mtu;
void (tun::*tun_set_mtu)(int) = &tun::mtu;
def("tuntap_version", tuntap_version);
class_<tun, boost::noncopyable>("Tun", init<>())
.def("release", &tun::release)
.def("up", &tun::up)
.def("down", &tun::down)
.def("ip", &tun::ip)
.def("nonblocking", &tun::nonblocking)
.add_property("name", tun_get_name, tun_set_name)
.add_property("mtu", tun_get_mtu, tun_set_mtu)
.add_property("native_handle", &tun::native_handle)
;
class_<tap, boost::noncopyable>("Tap", init<>())
.def("release", &tap::release)
.def("up", &tap::up)
.def("down", &tap::down)
.def("ip", &tap::ip)
.def("nonblocking", &tap::nonblocking)
.add_property("name", tap_get_name, tap_set_name)
.add_property("hwaddr", tap_set_hwaddr, tap_set_hwaddr)
.add_property("mtu", tap_set_mtu, tap_set_mtu)
.add_property("native_handle", &tap::native_handle)
;
}

@ -0,0 +1,327 @@
API
===
Types
=====
struct device
-------------
The `struct device` is an opaque structure containing internal parameter, like the device name, device flags, device file descriptor, etc. You should not access them.
The structure size may vary from an operating system to an other, you should not rely on it.
t_tuntap_log
------------
typedef void (*t_tuntap_log)(int level, const char *msg);
This type is a pointer to a log function. It allows to override the default behaviour, which is printing every messages on the error output prefixed with its error level.
Error levels are described later, they are macros in the form `TUNTAP_LOG_*`.
t_tun
-----
The `t_tun` type map the file descriptor type of a given operating system.
Typically it's an `int` on UNIXes and a `HANDLE` on Windows.
Macros
======
There is two type of macros, the libtuntap ones, and the "portable" ones. The laters are here to help portable parts of the code to rely on meaningful names, not hard-coded magic values.
libtuntap macros
----------------
TUNTAP_ID_MAX
-------------
`TUNTAP_ID_MAX` is the maximal device unit giveable as the third parameter of `tuntap_start()`.
TUNTAP_ID_ANY
-------------
`TUNTAP_ID_ANY` is the wild-card device unit giveable as the third parameter of `tuntap_start()`.
TUNTAP_MODE_ETHERNET
--------------------
`TUNTAP_MODE_ETHERNET` is the tap-mode giveable as the second parameter of `tuntap_start()`.
TUNTAP_MODE_TUNNEL
------------------
`TUNTAP_MODE_TUNNEL` is the tun-mode giveable as the second parameter of `tuntap_start()`.
TUNTAP_MODE_PERSIST
-------------------
`TUNTAP_MODE_PERSIST` is the persistence flag giveable OR'ed with the second parameter of `tuntap_start()`.
This flag is optional and should be used with either `TUNTAP_MODE_TUNNEL` or `TUNTAP_MODE_ETHERNET`.
TUNTAP_LOG_ERR
--------------
`TUNTAP_LOG_ERR` describes an error message.
TUNTAP_LOG_WARN
---------------
`TUNTAP_LOG_WARN` describes a warning message.
TUNTAP_LOG_INFO
---------------
`TUNTAP_LOG_INFO` describes an informational message.
TUNTAP_LOG_NOTICE
-----------------
`TUNTAP_LOG_NOTICE` describes a message which is not really an error nor a warning. It is mostly used to warn about unimplemented or unavailable part of the libtuntap.
TUNTAP_LOG_DEBUG
----------------
`TUNTAP_LOG_DEBUG` describes a debug messages. You should see one only if your are using the git HEAD.
TUNTAP_LOG_NONE
---------------
`TUNTAP_LOG_NONE` describes other things. It is only used by `tuntap_log_hexdump()` and `tuntap_log_chksum()`.
Portable macros
---------------
ETHER_ADDR_LEN
--------------
`ETHER_ADDR_LEN` is a value dictated by [[http://www.ieee802.org/3/|IEEE 802.3]] standard.
On Linux systems its value is mapped on `ETH_ALEN` one.
IF_NAMESIZE
-----------
`IF_NAMESIZE` gives the maximal length of an interface name.
On BSD systems its value is mapped on `IFNAMSIZ` one.
IF_DESCRSIZE
------------
`IF_DESCSIZE` gives the maximal length of an interface description.
TUNFD_INVALID_VALUE
-------------------
`TUNFD_INVALID_VALUE` is the invalid value of the t_tun type.
On UNIXes systems its value is `-1`.
On Windows systems its value is `INVALID_HANDLE_VALUE`.
Functions
=========
tuntap_init
-----------
struct device *tuntap_init(void);
This function will allocate and initialise a `struct device`.
tuntap_version
--------------
int tuntap_version(void);
This function returns the version number of libtuntap.
You can extract the major and the minor like this:
int version = tuntap_version();
int major = version >> 8;
int minor = version & major;
Note that this version number is not the same as the shared library version.
tuntap_destroy
--------------
void tuntap_destroy(struct device *dev);
This function will free allocated memory, close file descriptors and destroy the interface.
=== tuntap_release
void tuntap_release(struct device *dev);
This function will free allocated memory and close file descriptors. leaving the interface.
=== tuntap_start
int tuntap_start(struct device dev*, int mode, int unit);
This function will configure the device with the mode `mode` and the optional device unit `unit`.
The `mode` parameter should be either `TUNTAP_MODE_ETHERNET` or `TUNTAP_MODE_TUNNEL` eventually ORed with `TUNTAP_MODE_PERSIST`.
The `unit` parameter should always be less than `TUNTAP_ID_MAX` and greater than 0. If you don't need a particular value, you should use `TUNTAP_ID_ANY`, which is a sort of wild-card device unit. With this parameter, the kernel will pick the next available device.
The term "device unit" is also known as PPA, for Physical Point of Attachment, in Solaris documentation.
Examples:
tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY)
tuntap_start(dev, TUNTAP_MODE_TUNNEL, 2)
tuntap_start(dev, TUNTAP_MODE_TUNNEL | TUNTAP_MODE_PERSIST, TUNTAP_ID_ANY)
tuntap_get_ifname
-----------------
char *tuntap_get_ifname(struct device *dev);
This function fetch and return the name of the interface described by `dev`.
tuntap_set_ifname
-----------------
int tuntap_set_ifname(struct device *dev, const char *ifname);
This function replaces the name of the interface described by `dev` with the given name `ifname`.
It returns -1 on error.
Compatibility: Linux.
tuntap_get_hwaddr
-----------------
char *tuntap_get_hwaddr(struct device *dev);
This function fetch and returns the link-layer address (MAC) of the interface described by `dev`.
The returned string come from a statically allocated buffer, ans thus should be saved if needed for later use.
tuntap_set_hwaddr
-----------------
int tuntap_set_hwaddr(struct device *dev, const char *mac_addr);
This function replaces the link-layer address of the interface described by `dev` with the given address `mac_addr`.
It returns -1 on error.
tuntap_set_descr
----------------
int tuntap_set_descr(struct device *dev, const char *desc);
This function replaces the description of the interface described by `dev` with the given string `desc`.
Compatibility: OpenBSD, FreeBSD.
tuntap_up
---------
int tuntap_up(struct device *dev);
This function set interface to the UP state, just like `ifconfig eth0 up` would do.
tuntap_down
-----------
int tuntap_down(struct device *dev);
This function set interface to the DOWN state, just like `ifconfig eth0 down` would do.
tuntap_get_mtu
--------------
int tuntap_get_mtu(struct device *dev);
This function fetch and returns the Maximum Transfer Unit (MTU) of the interface described by `dev`.
tuntap_set_mtu
--------------
int tuntap_set_mtu(struct device *dev, int mtu);
This function replaces the MTU of the interface described by `dev` with the given value `mtu`.
tuntap_set_ip
-------------
int tuntap_set_ip(struct device *dev, const char *, int ip_addr);
This function replaces the IP address of the interface described by `dev` with the given address `ip_addr`.
tuntap_read
-----------
int tuntap_read(struct device *dev, void *buf, size_t buf_len);
This function will read one packet from the interface descibed by `dev` and will store it in the buffer `buf` of size `buf_len`. This value can be retrieved with a call to `tuntap_get_readable()`.
tuntap_write
------------
int tuntap_write(struct device *dev, void *buf, size_t buf_len);
This function will write the packet stored in the buffer `buf` of size `buf_len` to the interface descibed by `dev`.
tuntap_get_readable
-------------------
int tuntap_get_readable(struct device *dev);
This function will return the size of the next packet waiting in the buffer queue of the interface described by `dev`.
On Linux this function is the same as `tuntap_get_mtu()`, because the ioctl call `FIONREAD` is not supported on caracter devices.
tuntap_set_nonblocking
----------------------
int tuntap_set_nonblocking(struct device *dev, int set);
This function will set the socket of the interface described by `dev` to a non-blocking state.
tuntap_set_debug
----------------
int tuntap_set_debug(struct device *dev, int set);
This function will enable or disable the debug mode of the interface described by `dev`, depending of the value of `set`.
If `set` is 0, it will disable debug, and if it is 1 it will enable it.
The debug mode will add more output regarding the interface on the console.
This functionality depend on your operating system. It is enable by default on FreeBSD and NetBSD, but you might have to recompile your tun and tap drivers on Linux and OpenBSD to enable it.
tuntap_log_set_cb
-----------------
void tuntap_log_set_cb(t_tuntap_log cb);
This function allow to set an external printing function, in order to erase the default behaviour.
tuntap_log_hexdump
------------------
void tuntap_log_hexdump(void *, size_t);
This function is actualy not documented.
tuntap_log_chksum
-----------------
void tuntap_log_chksum(void *, int);
This function is actualy not documented.
TUNTAP_GET_FD
-------------
int TUNTAP_GET_FD(struct device *dev)
This macro will return the socket of the interface described by `dev`.

Binary file not shown.

@ -0,0 +1 @@
libtuntap.2.1.dylib

@ -0,0 +1,100 @@
# libtuntap regression tests CMakeLists.txt
# =========================================
cmake_minimum_required(VERSION 2.8)
enable_testing()
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
# C based tests
# -------------
file(GLOB ALL_C_TESTS regress/test*.c)
foreach(SOURCE_FILE ${ALL_C_TESTS})
string(REPLACE ".c" "" PATH_WO_SUFFIX ${SOURCE_FILE})
string(REPLACE ${CMAKE_CURRENT_SOURCE_DIR}/ ""
TEST_SRC_PATH ${SOURCE_FILE})
string(REPLACE ${CMAKE_CURRENT_SOURCE_DIR}/regress/ ""
TEST_NAME ${PATH_WO_SUFFIX})
add_executable(${TEST_NAME} ${TEST_SRC_PATH})
target_link_libraries(${TEST_NAME} tuntap)
add_test(${TEST_NAME} ${EXECUTABLE_OUTPUT_PATH}/${TEST_NAME})
endforeach(SOURCE_FILE)
# Shell based tests
# -----------------
file(GLOB ALL_SH_TESTS regress/test*.sh)
foreach(SOURCE_FILE ${ALL_SH_TESTS})
string(REPLACE ".sh" "" PATH_WO_SUFFIX ${SOURCE_FILE})
string(REPLACE ${CMAKE_CURRENT_SOURCE_DIR}/ ""
TEST_SRC_PATH ${SOURCE_FILE})
string(REPLACE ${CMAKE_CURRENT_SOURCE_DIR}/regress/ ""
TEST_NAME ${PATH_WO_SUFFIX})
string(REPLACE ".sh" ".c" HELPER_SRC_PATH ${TEST_SRC_PATH})
string(REPLACE "test" "helper" HELPER_SRC_PATH ${HELPER_SRC_PATH})
string(REPLACE "test" "helper" HELPER_NAME ${TEST_NAME})
# XXX: Do it conditionaly
add_executable(${HELPER_NAME} ${HELPER_SRC_PATH})
target_link_libraries(${HELPER_NAME} tuntap)
# XXX: This is cancerous
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME})
file(COPY ${TEST_SRC_PATH}
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
FILE_PERMISSIONS OWNER_READ OWNER_EXECUTE
)
file(RENAME ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.sh
${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME})
add_test(${TEST_NAME} ${EXECUTABLE_OUTPUT_PATH}/${TEST_NAME})
endforeach(SOURCE_FILE)
# "Will fail" tests
# -----------------
# Only NetBSD, FreeBSD and DragonFlyBSD have the debug mode compiled by default
if(NOT NetBSD AND NOT FreeBSD AND NOT DragonFly)
set_tests_properties(test39 PROPERTIES WILL_FAIL true)
set_tests_properties(test40 PROPERTIES WILL_FAIL true)
endif()
# Only Linux has a tuntap_set_ifname() implemented
if(NOT Linux)
set_tests_properties(test41 PROPERTIES WILL_FAIL true)
endif()
# Only FreeBSD and OpenBSD have a tuntap_set_descr() implemented
if(NOT FreeBSD AND NOT OpenBSD)
set_tests_properties(test44 PROPERTIES WILL_FAIL true)
set_tests_properties(test46 PROPERTIES WILL_FAIL true)
endif()
# Windows work-in-progress (tap)
if (Windows)
set_tests_properties(test05 PROPERTIES WILL_FAIL true)
set_tests_properties(test07 PROPERTIES WILL_FAIL true)
set_tests_properties(test09 PROPERTIES WILL_FAIL true)
set_tests_properties(test39 PROPERTIES WILL_FAIL true)
set_tests_properties(test41 PROPERTIES WILL_FAIL true)
set_tests_properties(test44 PROPERTIES WILL_FAIL true)
endif()
# Windows work-in-progress (tun)
if (Windows)
set_tests_properties(test02 PROPERTIES WILL_FAIL true)
set_tests_properties(test04 PROPERTIES WILL_FAIL true)
set_tests_properties(test06 PROPERTIES WILL_FAIL true)
set_tests_properties(test08 PROPERTIES WILL_FAIL true)
set_tests_properties(test10 PROPERTIES WILL_FAIL true)
set_tests_properties(test12 PROPERTIES WILL_FAIL true)
set_tests_properties(test14 PROPERTIES WILL_FAIL true)
set_tests_properties(test18 PROPERTIES WILL_FAIL true)
set_tests_properties(test22 PROPERTIES WILL_FAIL true)
set_tests_properties(test24 PROPERTIES WILL_FAIL true)
set_tests_properties(test26 PROPERTIES WILL_FAIL true)
set_tests_properties(test40 PROPERTIES WILL_FAIL true)
endif()

@ -0,0 +1,50 @@
Regression Testing
==================
test01: Create a tapN device
test02: Create a tunN device
test03: Create a tap0 device
test04: Create a tun0 device
test05: Create a tapN device and set its mtu to 1400
test06: Create a tunN device and set its mtu to 1400
test07: Create a tapN device and set its MAC address to 54:1a:13:ef:b6:b5
test08: Create a tunN device and set its MAC address to 54:1a:13:ef:b6:b5
test09: Create a tapN device and set its MAC address to random
test10: Create a tunN device and set its MAC address to random
test11: Create a tapN device and turn it up
test12: Create a tunN device and turn it up
test13: Create a tapN device, turn it up and set its IPv4 address
test14: Create a tunN device, turn it up and set its IPv4 address
#test15: Create a tapN device, turn it up and set its IPv6 address
#test16: Create a tunN device, turn it up and set its IPv6 address
test17: Create a tapN device, set its IPv4 address and turn it up
test18: Create a tunN device, set its IPv4 address and turn it up
#test19: Create a tapN device, set its IPv6 address and turn it up
#test20: Create a tunN device, set its IPv6 address and turn it up
test21: Create a tapN device and set its IP address to NULL
test22: Create a tunN device and set its IP address to NULL
test23: Create a tapN device and set its netmask to a negative value
test24: Create a tunN device and set its netmask to a negative value
test25: Create a tapN device and set its IP address to a dumb value
test26: Create a tunN device and set its IP address to a dumb value
#test27: Create a tapN device and set its netmask to a dumb value
#test28: Create a tunN device and set its netmask to a dumb value
test29: Double create a tapN device
test30: Create a device with a wrong type
test31: Create a device with a wrong number
test32: Create a tapN device and check its pre-existing MAC address
test33: Create a tap0 persistent device and destroy it
test34: Create a tun0 persistent device and destroy it
test35: Create a tap0 persistent device and release it
test36: Create a tun1 persistent device and release it
test37: Set a log callback and generate an error
test38: Set a log callback and generate all possible error levels
test39: Enable debug for a tap device
test40: Enable debug for a tun device
test41: Set a new name to an interface
test42: Set a NULL name to an interface
test43: Set a name of more than IF_NAMESIZE to an interface
test44: Set a description to an interface
test45: Set a NULL description to an interface
test46: Set a description to an interface and check it

@ -0,0 +1,26 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET|TUNTAP_MODE_PERSIST
, 0) == -1)
ret = 1;
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,26 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL|TUNTAP_MODE_PERSIST, 0)
== -1)
ret = 1;
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,26 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET|TUNTAP_MODE_PERSIST
, 0) == -1)
ret = 1;
tuntap_release(dev);
return ret;
}

@ -0,0 +1,25 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL|TUNTAP_MODE_PERSIST, 1) == -1)
ret = 1;
tuntap_release(dev);
return ret;
}

@ -0,0 +1,25 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1)
ret = 1;
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,25 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1)
ret = 1;
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,25 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, 0) == -1)
ret = 1;
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,25 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, 0) == -1)
ret = 1;
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,39 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
int mtu;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY)
== -1) {
ret = 1;
goto clean;
}
if (tuntap_set_mtu(dev, 1400) == -1) {
ret = 1;
goto clean;
}
mtu = tuntap_get_mtu(dev);
if (mtu != 1400)
ret = 1;
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,39 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
int mtu;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1) {
ret = 1;
goto clean;
}
if (tuntap_set_mtu(dev, 1400) == -1) {
ret = 1;
goto clean;
}
mtu = tuntap_get_mtu(dev);
if (mtu != 1400) {
ret = 1;
}
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,42 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
# define strcasecmp(x, y) _stricmp((x), (y))
#else
# include <strings.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
char *hwaddr;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY)
== -1) {
ret = 1;
goto clean;
}
if (tuntap_set_hwaddr(dev, "54:1a:13:ef:b6:b5") == -1) {
ret = 1;
goto clean;
}
hwaddr = tuntap_get_hwaddr(dev);
if (strcasecmp(hwaddr, "54:1a:13:ef:b6:b5") != 0)
ret = 1;
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,31 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
/* This test SHOULD fail, it's normal */
int
main(void) {
int ret;
struct device *dev;
ret = 1;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1)
goto clean;
if (tuntap_set_hwaddr(dev, "54:1a:13:ef:b6:b5") == -1)
ret = 0;
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,33 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY)
== -1) {
ret = 1;
goto clean;
}
if (tuntap_set_hwaddr(dev, "random") == -1) {
ret = 1;
}
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,33 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
/* This test SHOULD fail, it's normal */
int
main(void) {
int ret;
struct device *dev;
ret = 1;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1) {
goto clean;
}
if (tuntap_set_hwaddr(dev, "random") == -1) {
ret = 0;
}
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,32 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY)
== -1) {
ret = 1;
goto clean;
}
if (tuntap_up(dev) == -1)
ret = 1;
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,31 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1) {
ret = 1;
goto clean;
}
if (tuntap_up(dev) == -1)
ret = 1;
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,43 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
/*
* This test seems to pass on Windows, but it's not true.
* tuntap_up() should be call _after_ tuntap_set_ip(), as in test17.c
*
* Fuck.
*/
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1) {
ret = 1;
goto clean;
}
if (tuntap_up(dev) == -1) {
ret = 1;
goto clean;
}
if (tuntap_set_ip(dev, "1.2.3.4", 24) == -1) {
ret = 1;
}
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,32 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1) {
return 1;
}
if (tuntap_up(dev) == -1) {
return 1;
}
if (tuntap_set_ip(dev, "1.2.3.4", 24) == -1) {
return 1;
}
tuntap_destroy(dev);
return 0;
}

@ -0,0 +1,32 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1) {
return 1;
}
if (tuntap_set_ip(dev, "1.2.3.4", 24) == -1) {
return 1;
}
if (tuntap_up(dev) == -1) {
return 1;
}
tuntap_destroy(dev);
return 0;
}

@ -0,0 +1,32 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1) {
return 1;
}
if (tuntap_set_ip(dev, "1.2.3.4", 24) == -1) {
return 1;
}
if (tuntap_up(dev) == -1) {
return 1;
}
tuntap_destroy(dev);
return 0;
}

@ -0,0 +1,28 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1) {
return 1;
}
if (tuntap_set_ip(dev, NULL, 24) == -1) {
tuntap_destroy(dev);
return 0;
}
return 1;
}

@ -0,0 +1,28 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1) {
return 1;
}
if (tuntap_set_ip(dev, NULL, 24) == -1) {
tuntap_destroy(dev);
return 0;
}
return 1;
}

@ -0,0 +1,28 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1) {
return 1;
}
if (tuntap_set_ip(dev, "1.2.3.4", -2) == -1) {
tuntap_destroy(dev);
return 0;
}
return 1;
}

@ -0,0 +1,28 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1) {
return 1;
}
if (tuntap_set_ip(dev, "1.2.3.4", -2) == -1) {
tuntap_destroy(dev);
return 0;
}
return 1;
}

@ -0,0 +1,28 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1) {
return 1;
}
if (tuntap_set_ip(dev, "Chipot", 24) == -1) {
tuntap_destroy(dev);
return 0;
}
return 1;
}

@ -0,0 +1,28 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1) {
return 1;
}
if (tuntap_set_ip(dev, "Chipot", 24) == -1) {
tuntap_destroy(dev);
return 0;
}
return 1;
}

@ -0,0 +1,28 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1) {
return 1;
}
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1) {
tuntap_destroy(dev);
return 0;
}
return 1;
}

@ -0,0 +1,24 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, 42, TUNTAP_ID_ANY) == -1) {
tuntap_destroy(dev);
return 0;
}
return 1;
}

@ -0,0 +1,24 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
struct device *dev;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, -1) == -1) {
tuntap_destroy(dev);
return 0;
}
return 1;
}

@ -0,0 +1,37 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
char *hwaddr;
ret = 1;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1) {
goto clean;
}
hwaddr = tuntap_get_hwaddr(dev);
(void)fprintf(stderr, "%s\n", hwaddr);
if (strcmp(hwaddr, "0:0:0:0:0:0") == 0)
goto clean;
if (strcmp(hwaddr, "00:00:00:00:00:00") == 0)
goto clean;
ret = 0;
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,40 @@
#!/bin/sh
# test33: Create a tap0 persistent device and destroy it
TEST="`pwd`/helper33"
SYSTEM=`uname`
# There is no tap driver on OpenBSD
if [ "$SYSTEM" = "OpenBSD" ]; then
TARGET='tun0'
TYPE='tap'
else
TARGET='tap0'
TYPE='tap'
fi
if [ "$SYSTEM" = "Linux" ]; then
IFDEL="ip tuntap del $TARGET mode $TYPE"
else
IFDEL="ifconfig $TARGET destroy"
fi
OK=0
$TEST && OK=1
# If the $TEST was a success, check if the interface still exist
if [ $OK -eq 1 ]; then
ifconfig $TARGET > /dev/null && OK=2
else
exit 1
fi
# The $TARGET still exists, clean it and return failure
if [ $OK -eq 2 ]; then
$IFDEL
exit 1
fi
# Everything went fine
exit 0

@ -0,0 +1,32 @@
#!/bin/sh
# test34: Create a tun0 persistent device and destroy it
TEST="`pwd`/helper34"
SYSTEM=`uname`
TARGET='tun0'
TYPE='tun'
if [ "$SYSTEM" = "Linux" ]; then
IFDEL="ip tuntap del $TARGET mode $TYPE"
else
IFDEL="ifconfig $TARGET destroy"
fi
OK=0
$TEST && OK=1
# The $TEST is successful
if [ $OK -eq 1 ]; then
ifconfig $TARGET && OK=2
else
exit 1
fi
# The $TARGET still exists
if [ $OK -eq 2 ]; then
$IFDEL
exit 1
fi
exit 0

@ -0,0 +1,40 @@
#!/bin/sh
# test35: Create a tap0 persistent device and release it
TEST="`pwd`/helper35"
SYSTEM=`uname`
# There is no tap driver on OpenBSD
if [ "$SYSTEM" = "OpenBSD" ]; then
TARGET='tun0'
TYPE='tap'
else
TARGET='tap0'
TYPE='tap'
fi
if [ "$SYSTEM" = "Linux" ]; then
IFDEL="ip tuntap del $TARGET mode $TYPE"
else
IFDEL="ifconfig $TARGET destroy"
fi
OK=0
$TEST && OK=1
# The $TEST is successful
if [ $OK -eq 1 ]; then
ifconfig $TARGET && OK=2
else
exit 1
fi
# The $TARGET still exists
if [ $OK -eq 2 ]; then
$IFDEL
exit 0
else
exit 1
fi

@ -0,0 +1,32 @@
#!/bin/sh
# test36: Create a tun1 persistent device and release it
TEST="`pwd`/helper36"
SYSTEM=`uname`
TARGET='tun1'
TYPE='tun'
if [ "$SYSTEM" = "Linux" ]; then
IFDEL="ip tuntap del $TARGET mode $TYPE"
else
IFDEL="ifconfig $TARGET destroy"
fi
OK=0
$TEST && OK=1
# If the $TEST was a success, check if the interface still exist
if [ $OK -eq 1 ]; then
ifconfig $TARGET && OK=2
else
exit 1
fi
# The $TARGET still exists, clean it and exit success
if [ $OK -eq 2 ]; then
$IFDEL
exit 0
fi
exit 1

@ -0,0 +1,35 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int exit_value;
void
test_cb(int level, const char *errmsg) {
(void)level;
(void)errmsg;
fprintf(stderr, "successfully set a callback\n");
exit_value = 0;
}
int
main(void) {
struct device *dev;
exit_value = 1;
dev = tuntap_init();
tuntap_log_set_cb(test_cb);
tuntap_start(dev, 0, -1);
tuntap_destroy(dev);
return exit_value;
}

@ -0,0 +1,60 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int debug, info, notice, warn, err;
void
test_cb(int level, const char *errmsg) {
const char *prefix = NULL;
switch (level) {
case TUNTAP_LOG_DEBUG:
prefix = "debug";
debug = 1;
break;
case TUNTAP_LOG_INFO:
prefix = "info";
info = 1;
break;
case TUNTAP_LOG_NOTICE:
prefix = "notice";
notice = 1;
break;
case TUNTAP_LOG_WARN:
prefix = "warn";
warn = 1;
break;
case TUNTAP_LOG_ERR:
prefix = "err";
err = 1;
break;
default:
/* NOTREACHED */
break;
}
(void)fprintf(stderr, "%s: %s\n", prefix, errmsg);
}
int
main(void) {
tuntap_log_set_cb(test_cb);
tuntap_log(TUNTAP_LOG_DEBUG, "debug message");
tuntap_log(TUNTAP_LOG_INFO, "info message");
tuntap_log(TUNTAP_LOG_NOTICE, "notice message");
tuntap_log(TUNTAP_LOG_WARN, "warn message");
tuntap_log(TUNTAP_LOG_ERR, "err message");
if (debug + info + notice + warn + err != 5)
return -1;
return 0;
}

@ -0,0 +1,33 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1) {
ret = 1;
goto clean;
}
if (tuntap_set_debug(dev, 1) == -1) {
ret = 1;
goto clean;
}
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,33 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1) {
ret = 1;
goto clean;
}
if (tuntap_set_debug(dev, 1) == -1) {
ret = 1;
goto clean;
}
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,29 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1)
ret = 1;
if (tuntap_set_ifname(dev, "jelly0") == -1) {
ret = 1;
}
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,29 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 1;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1)
ret = 1;
if (tuntap_set_ifname(dev, NULL) == -1) {
ret = 0;
}
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,29 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 1;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1)
ret = 1;
if (tuntap_set_ifname(dev, "abcdefghijklmnopqrstuvwxyz0") == -1) {
ret = 0;
}
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,30 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
const char *s = "This tap interface is here for testing purpose";
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1)
ret = 1;
if (tuntap_set_descr(dev, s) == -1) {
ret = 1;
}
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,29 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
ret = 1;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1)
ret = 1;
if (tuntap_set_descr(dev, NULL) == -1) {
ret = 0;
}
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,45 @@
/* Public domain - Tristan Le Guern <tleguern@bouledef.eu> */
#include <sys/types.h>
#include <stdio.h>
#if defined Windows
# include <windows.h>
#endif
#include <string.h>
#include "tuntap.h"
int
main(void) {
int ret;
struct device *dev;
const char *s = "This tap interface is here for testing purpose";
char *check_s;
ret = 0;
dev = tuntap_init();
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) == -1) {
ret = 1;
goto clean;
}
if (tuntap_set_descr(dev, s) == -1) {
ret = 1;
goto clean;
}
if ((check_s = tuntap_get_descr(dev)) == NULL) {
ret = 1;
goto clean;
}
if (strcmp(s, check_s) != 0) {
ret = 1;
}
clean:
tuntap_destroy(dev);
return ret;
}

@ -0,0 +1,93 @@
/*
* Copyright (c) 2012 Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_tun.h>
#include <net/if_types.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tuntap.h"
static int
tuntap_sys_create_dev(struct device *dev, int tun) {
return -1;
}
int
tuntap_sys_start(struct device *dev, int mode, int tun) {
return -1;
}
void
tuntap_sys_destroy(struct device *dev) {
return;
}
int
tuntap_sys_set_hwaddr(struct device *dev, struct ether_addr *eth_addr) {
return -1;
}
int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s4, uint32_t bits) {
(void)dev;
(void)s4;
(void)bits;
return -1;
}
int
tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s6, uint32_t bits) {
(void)dev;
(void)s6;
(void)bits;
tuntap_log(TUNTAP_LOG_INFO, "IPv6 is not implemented on your system");
return -1;
}
int
tuntap_sys_set_ifname(struct device *dev, const char *ifname, size_t len) {
(void)dev;
(void)ifname;
(void)len;
tuntap_log(TUNTAP_LOG_ERR,
"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;
tuntap_log(TUNTAP_LOG_ERR,
"Your system does not support tuntap_set_descr()");
return -1;
}

@ -0,0 +1,45 @@
/*
* Copyright (c) 2012 Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <string.h>
#include "tuntap.h"
int
tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s6, uint32_t bits) {
(void)dev;
(void)s6;
(void)bits;
tuntap_log(TUNTAP_LOG_NOTICE, "IPv6 is not implemented on your system");
return -1;
}
int
tuntap_sys_set_ifname(struct device *dev, const char *ifname, size_t len) {
(void)dev;
(void)ifname;
(void)len;
tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_ifname()");
return -1;
}

@ -0,0 +1,223 @@
/*
* Copyright (c) 2012 Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_types.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tuntap.h"
static int
tuntap_sys_create_dev(struct device *dev, int tun) {
return -1;
}
int
tuntap_sys_start(struct device *dev, int mode, int tun) {
struct ifreq ifr;
struct ifaddrs *ifa;
char name[MAXPATHLEN];
int fd;
char *type;
fd = -1;
/* Force creation of the driver if needed or let it resilient */
if (mode & TUNTAP_MODE_PERSIST) {
mode &= ~TUNTAP_MODE_PERSIST;
/* TODO: Call tuntap_sys_create_dev() */
}
/* Set the mode: tun or tap */
if (mode == TUNTAP_MODE_ETHERNET) {
type = "tap";
ifr.ifr_flags |= IFF_LINK0;
}
else if (mode == TUNTAP_MODE_TUNNEL) {
type = "tun";
ifr.ifr_flags &= ~IFF_LINK0;
}
else {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'");
return -1;
}
/* Try to use the given driver or loop throught the avaible ones */
if (tun < TUNTAP_ID_MAX) {
(void)snprintf(name, sizeof name, "/dev/%s%i", type, tun);
fd = open(name, O_RDWR);
} else if (tun == TUNTAP_ID_ANY) {
for (tun = 0; tun < TUNTAP_ID_MAX; ++tun) {
(void)memset(name, '\0', sizeof name);
(void)snprintf(name, sizeof name, "/dev/%s%i",
type, tun);
if ((fd = open(name, O_RDWR)) > 0)
break;
}
} else {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'tun'");
return -1;
}
switch (fd) {
case -1:
tuntap_log(TUNTAP_LOG_ERR, "Permission denied");
return -1;
case 256:
tuntap_log(TUNTAP_LOG_ERR, "Can't find a tun entry");
return -1;
default:
/* NOTREACHED */
break;
}
/* Set the interface name */
(void)memset(&ifr, '\0', sizeof ifr);
(void)snprintf(ifr.ifr_name, sizeof ifr.ifr_name, "%s%i", type, tun);
/* And save it */
(void)strlcpy(dev->if_name, ifr.ifr_name, sizeof dev->if_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;
}
/* Set our modifications */
if (ioctl(dev->ctrl_sock, SIOCSIFFLAGS, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set interface values");
return -1;
}
/* Save flags for tuntap_{up, down} */
dev->flags = ifr.ifr_flags;
/* Save pre-existing MAC address */
if (mode == TUNTAP_MODE_ETHERNET && getifaddrs(&ifa) == 0) {
struct ifaddrs *pifa;
for (pifa = ifa; pifa != NULL; pifa = pifa->ifa_next) {
if (strcmp(pifa->ifa_name, dev->if_name) == 0) {
struct ether_addr eth_addr;
/*
* The MAC address is from 10 to 15.
*
* And yes, I know, the buffer is supposed
* to have a size of 14 bytes.
*/
(void)memcpy(dev->hwaddr,
pifa->ifa_addr->sa_data + 10,
ETHER_ADDR_LEN);
(void)memset(&eth_addr.ether_addr_octet, 0,
ETHER_ADDR_LEN);
(void)memcpy(&eth_addr.ether_addr_octet,
pifa->ifa_addr->sa_data + 10,
ETHER_ADDR_LEN);
break;
}
}
if (pifa == NULL)
tuntap_log(TUNTAP_LOG_WARN,
"Can't get link-layer address");
freeifaddrs(ifa);
}
return fd;
}
void
tuntap_sys_destroy(struct device *dev) {
(void)dev;
}
int
tuntap_sys_set_hwaddr(struct device *dev, struct ether_addr *eth_addr) {
struct ifreq ifr;
(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof ifr.ifr_name);
ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
ifr.ifr_addr.sa_family = AF_LINK;
(void)memcpy(ifr.ifr_addr.sa_data, eth_addr, ETHER_ADDR_LEN);
if (ioctl(dev->ctrl_sock, SIOCSIFLLADDR, &ifr) < 0) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set link-layer address");
return -1;
}
return 0;
}
int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s4, uint32_t bits) {
struct ifaliasreq ifa;
struct ifreq ifr;
struct sockaddr_in addr;
struct sockaddr_in mask;
(void)memset(&ifa, '\0', sizeof ifa);
(void)strlcpy(ifa.ifra_name, dev->if_name, sizeof ifa.ifra_name);
(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof ifr.ifr_name);
/* Delete previously assigned address */
(void)ioctl(dev->ctrl_sock, SIOCDIFADDR, &ifr);
/*
* Fill-in the destination address and netmask,
* but don't care of the broadcast address
*/
(void)memset(&addr, '\0', sizeof addr);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = s4->s_addr;
addr.sin_len = sizeof addr;
(void)memcpy(&ifa.ifra_addr, &addr, sizeof addr);
(void)memset(&mask, '\0', sizeof mask);
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = bits;
mask.sin_len = sizeof mask;
(void)memcpy(&ifa.ifra_mask, &mask, sizeof ifa.ifra_mask);
/* Simpler than calling SIOCSIFADDR and/or SIOCSIFBRDADDR */
if (ioctl(dev->ctrl_sock, SIOCSIFADDR, &ifa) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set IP/netmask");
return -1;
}
return 0;
}
int
tuntap_sys_set_descr(struct device *dev, const char *descr, size_t len) {
tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_descr()");
return -1;
}

@ -0,0 +1,285 @@
/*
* Copyright (c) 2012 Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Copyright (c) 2016 Mahdi Mokhtari <mokhi64@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/param.h> /* For MAXPATHLEN */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#if defined FreeBSD
# include <net/if_tun.h>
#elif defined DragonFly
# include <net/tun/if_tun.h>
#endif
#include <net/if_types.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tuntap.h"
int
tuntap_sys_start(struct device *dev, int mode, int tun) {
int fd;
int persist;
char *ifname;
char name[MAXPATHLEN];
struct ifaddrs *ifa;
struct ifreq ifr;
/* Get the persistence bit */
if (mode & TUNTAP_MODE_PERSIST) {
mode &= ~TUNTAP_MODE_PERSIST;
persist = 1;
} else {
persist = 0;
}
/* Set the mode: tun or tap */
if (mode == TUNTAP_MODE_ETHERNET) {
ifname = "tap";
} else if (mode == TUNTAP_MODE_TUNNEL) {
ifname = "tun";
} else {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'");
return -1;
}
dev->mode = mode;
/* Try to use the given driver or loop throught the avaible ones */
fd = -1;
if (tun < TUNTAP_ID_MAX) {
(void)snprintf(name, sizeof(name), "/dev/%s%i", ifname, tun);
fd = open(name, O_RDWR);
} else if (tun == TUNTAP_ID_ANY) {
for (tun = 0; tun < TUNTAP_ID_MAX; ++tun) {
(void)memset(name, 0, sizeof(name));
(void)snprintf(name, sizeof(name), "/dev/%s%i",
ifname, tun);
if ((fd = open(name, O_RDWR)) > 0)
break;
}
} else {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'tun'");
return -1;
}
switch (fd) {
case -1:
tuntap_log(TUNTAP_LOG_ERR, "Permission denied");
return -1;
case 256:
tuntap_log(TUNTAP_LOG_ERR, "Can't find a tun entry");
return -1;
default:
/* NOTREACHED */
break;
}
/* Set the interface name */
(void)memset(&ifr, 0, sizeof(ifr));
(void)snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%i", ifname, tun);
/* And save it */
(void)strlcpy(dev->if_name, ifr.ifr_name, sizeof(dev->if_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;
/* Save pre-existing MAC address */
if (mode == TUNTAP_MODE_ETHERNET && getifaddrs(&ifa) == 0) {
struct ifaddrs *pifa;
for (pifa = ifa; pifa != NULL; pifa = pifa->ifa_next) {
if (strcmp(pifa->ifa_name, dev->if_name) == 0) {
struct ether_addr eth_addr;
/*
* The MAC address is from 10 to 15.
*
* And yes, I know, the buffer is supposed
* to have a size of 14 bytes.
*/
(void)memcpy(dev->hwaddr,
pifa->ifa_addr->sa_data + 10,
ETHER_ADDR_LEN);
(void)memset(&eth_addr.octet, 0,
ETHER_ADDR_LEN);
(void)memcpy(&eth_addr.octet,
pifa->ifa_addr->sa_data + 10,
ETHER_ADDR_LEN);
break;
}
}
if (pifa == NULL)
tuntap_log(TUNTAP_LOG_WARN,
"Can't get link-layer address");
freeifaddrs(ifa);
}
return fd;
}
void
tuntap_sys_destroy(struct device *dev) {
return;
}
int
tuntap_sys_set_hwaddr(struct device *dev, struct ether_addr *eth_addr) {
struct ifreq ifr;
(void)memset(&ifr, 0, sizeof(ifr));
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof(ifr.ifr_name));
ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
ifr.ifr_addr.sa_family = AF_LINK;
(void)memcpy(ifr.ifr_addr.sa_data, eth_addr, ETHER_ADDR_LEN);
if (ioctl(dev->ctrl_sock, SIOCSIFLLADDR, &ifr) < 0) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set link-layer address");
return -1;
}
return 0;
}
int
tuntap_sys_set_ipv4_tap(struct device *dev, t_tun_in_addr *s4, uint32_t bits) {
struct ifaliasreq ifrq;
struct sockaddr_in mask;
struct sockaddr_in addr;
(void)memset(&ifrq, 0, sizeof(ifrq));
(void)strlcpy(ifrq.ifra_name, dev->if_name, sizeof(ifr.ifr_name));
/* Delete previously assigned address */
(void)ioctl(dev->ctrl_sock, SIOCDIFADDR, &ifrq);
/* Set the address */
(void)memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = s4->s_addr;
addr.sin_len = sizeof(addr);
(void)memcpy(&ifrq.ifra_addr, &addr, sizeof(addr));
/* Then set the netmask */
(void)memset(&mask, 0, sizeof(mask));
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = bits;
mask.sin_len = sizeof(mask);
(void)memcpy(&ifrq.ifra_addr, &mask, sizeof(ifrq.ifra_mask));
if (ioctl(dev->ctrl_sock, SIOCAIFADDR, &ifrq) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set IP address/netmask");
return -1;
}
return 0;
}
int
tuntap_sys_set_ipv4_tun(struct device *dev, t_tun_in_addr *s4, t_tun_in_addr *s4dest, uint32_t bits) {
struct ifaliasreq ifrq;
struct sockaddr_in mask;
struct sockaddr_in saddr;
struct sockaddr_in daddr;
(void)memset(&ifrq, 0, sizeof(ifrq));
(void)memcpy(ifrq.ifra_name, dev->if_name, sizeof(ifrq.ifra_name));
/* Delete previously assigned address */
(void)ioctl(dev->ctrl_sock, SIOCDIFADDR, &ifrq);
/* Set the address */
(void)memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = s4->s_addr;
saddr.sin_len = sizeof(saddr);
(void)memcpy(&ifrq.ifra_addr, &saddr, sizeof(saddr));
(void)memset(&daddr, 0, sizeof(daddr));
daddr.sin_family = AF_INET;
daddr.sin_addr.s_addr = s4dest->s_addr;
daddr.sin_len = sizeof(daddr);
(void)memcpy(&ifrq.ifra_broadaddr, &daddr, sizeof(daddr));
/* Then set the netmask */
(void)memset(&mask, 0, sizeof(mask));
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = bits;
mask.sin_len = sizeof(mask);
(void)memcpy(&ifrq.ifra_addr, &mask, sizeof(ifrq.ifra_mask));
if (ioctl(dev->ctrl_sock, SIOCAIFADDR, &ifrq) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set IP address");
return -1;
}
return 0;
}
int
tuntap_sys_set_descr(struct device *dev, const char *descr, size_t len) {
#if defined FreeBSD
struct ifreq ifr;
struct ifreq_buffer ifrbuf;
(void)memset(&ifr, 0, sizeof(ifr));
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof(ifr.ifr_name));
ifrbuf.buffer = (void *)descr;
ifrbuf.length = len;
ifr.ifr_buffer = ifrbuf;
if (ioctl(dev->ctrl_sock, SIOCSIFDESCR, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR,
"Can't set the interface description");
return -1;
}
return 0;
#elif defined DragonFly
tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_descr()");
return -1;
#endif
}

@ -0,0 +1,221 @@
/*
* Copyright (c) 2012 Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <netinet/if_ether.h>
#include <net/if_arp.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tuntap.h"
int
tuntap_sys_start(struct device *dev, int mode, int tun) {
int fd;
int persist;
char *ifname;
struct ifreq ifr;
/* Get the persistence bit */
if (mode & TUNTAP_MODE_PERSIST) {
mode &= ~TUNTAP_MODE_PERSIST;
persist = 1;
} else {
persist = 0;
}
/* Set the mode: tun or tap */
(void)memset(&ifr, '\0', sizeof ifr);
if (mode == TUNTAP_MODE_ETHERNET) {
ifr.ifr_flags = IFF_TAP;
ifname = "tap%i";
} else if (mode == TUNTAP_MODE_TUNNEL) {
ifr.ifr_flags = IFF_TUN;
ifname = "tun%i";
} else {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'");
return -1;
}
ifr.ifr_flags |= IFF_NO_PI;
if (tun < 0) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'tun'");
return -1;
}
/* Open the clonable interface */
fd = -1;
if ((fd = open("/dev/net/tun", O_RDWR)) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't open /dev/net/tun");
return -1;
}
/* Set the interface name, if any */
if (tun != TUNTAP_ID_ANY) {
if (fd > TUNTAP_ID_MAX) {
return -1;
}
(void)snprintf(ifr.ifr_name, sizeof ifr.ifr_name,
ifname, tun);
/* Save interface name *after* SIOCGIFFLAGS */
}
/* Configure the interface */
if (ioctl(fd, TUNSETIFF, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set interface name");
return -1;
}
/* Set it persistent if needed */
if (persist == 1) {
if (ioctl(fd, TUNSETPERSIST, 1) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set persistent");
return -1;
}
}
/* 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;
/* Save interface name */
(void)memcpy(dev->if_name, ifr.ifr_name, sizeof ifr.ifr_name);
/* Save pre-existing MAC address */
if (mode == TUNTAP_MODE_ETHERNET) {
struct ifreq ifr_hw;
(void)memcpy(ifr_hw.ifr_name, dev->if_name,
sizeof(dev->if_name));
if (ioctl(fd, SIOCGIFHWADDR, &ifr_hw) == -1) {
tuntap_log(TUNTAP_LOG_WARN,
"Can't get link-layer address");
return fd;
}
(void)memcpy(dev->hwaddr, ifr_hw.ifr_hwaddr.sa_data, ETH_ALEN);
}
return fd;
}
void
tuntap_sys_destroy(struct device *dev) {
if (ioctl(dev->tun_fd, TUNSETPERSIST, 0) == -1) {
tuntap_log(TUNTAP_LOG_WARN, "Can't destroy the interface");
}
}
int
tuntap_sys_set_hwaddr(struct device *dev, struct ether_addr *eth_addr) {
struct ifreq ifr;
(void)memset(&ifr, '\0', sizeof ifr);
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
(void)memcpy(ifr.ifr_hwaddr.sa_data, eth_addr->ether_addr_octet, 6);
/* Linux has a special flag for setting the MAC address */
if (ioctl(dev->ctrl_sock, SIOCSIFHWADDR, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set link-layer address");
return -1;
}
return 0;
}
int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s4, uint32_t bits) {
struct ifreq ifr;
struct sockaddr_in mask;
(void)memset(&ifr, '\0', sizeof ifr);
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
/* Set the IP address first */
(void)memcpy(&(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr),
s4, sizeof(struct in_addr));
ifr.ifr_addr.sa_family = AF_INET;
if (ioctl(dev->ctrl_sock, SIOCSIFADDR, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set IP address");
return -1;
}
/* Reinit the struct ifr */
(void)memset(&ifr.ifr_addr, '\0', sizeof ifr.ifr_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.ifr_netmask, &mask, sizeof ifr.ifr_netmask);
if (ioctl(dev->ctrl_sock, SIOCSIFNETMASK, &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 bits) {
(void)dev;
(void)s6;
(void)bits;
tuntap_log(TUNTAP_LOG_NOTICE, "IPv6 is not implemented on your system");
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;
}
int
tuntap_sys_set_descr(struct device *dev, const char *descr, size_t len) {
(void)dev;
(void)descr;
(void)len;
tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_descr()");
return -1;
}

@ -0,0 +1,300 @@
/*
* Copyright (c) 2012 Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/sockio.h>
#include <sys/socket.h>
#include <sys/param.h> /* For MAXPATHLEN */
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/if_tun.h>
#include <net/if_tap.h>
#include <netinet/if_ether.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tuntap.h"
static int
tuntap_sys_create_dev(struct device *dev, int mode, int tun) {
struct ifreq ifr;
char *name;
if (mode == TUNTAP_MODE_ETHERNET)
name = "tap%i";
else
name = "tun%i";
/* At this point 'tun' can't be TUNTAP_ID_ANY */
(void)memset(&ifr, '\0', sizeof ifr);
(void)snprintf(ifr.ifr_name, IF_NAMESIZE, name, tun);
if (ioctl(dev->ctrl_sock, SIOCIFCREATE, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set persistent");
return -1;
}
return 0;
}
/*
* NetBSD support auto-clonning, but only for tap device.
* To access /dev/tapN we have to create it before.
*/
static int
tuntap_sys_start_tap(struct device *dev, int tun) {
int fd;
struct ifreq ifr;
struct ifaddrs *ifa;
char name[IF_NAMESIZE + 5]; /* For /dev/IFNAMSIZ */
fd = -1;
(void)memset(&ifr, '\0', sizeof ifr);
(void)memset(name, '\0', sizeof name);
/* Set the device path to open */
if (tun < TUNTAP_ID_MAX) {
/* Create the wanted device */
tuntap_sys_create_dev(dev, TUNTAP_MODE_ETHERNET, tun);
(void)snprintf(name, sizeof name, "/dev/tap%i", tun);
} else if (tun == TUNTAP_ID_ANY) {
/* Or use autocloning */
(void)memcpy(name, "/dev/tap", 8);
} else {
return -1;
}
if ((fd = open(name, O_RDWR)) == -1) {
char buf[11 + MAXPATHLEN];
(void)memset(buf, 0, sizeof buf);
snprintf(buf, sizeof buf, "Can't open %s", name);
tuntap_log(TUNTAP_LOG_DEBUG, buf);
return -1;
}
/* Get the interface name */
if (ioctl(fd, TAPGIFNAME, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't get interface name");
return -1;
}
(void)strlcpy(dev->if_name, ifr.ifr_name, sizeof dev->if_name);
/* Get the interface default values */
if (ioctl(fd, 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;
/* Save pre-existing MAC address */
if (getifaddrs(&ifa) == 0) {
struct ifaddrs *pifa;
for (pifa = ifa; pifa != NULL; pifa = pifa->ifa_next) {
if (strcmp(pifa->ifa_name, dev->if_name) == 0) {
struct ether_addr eth_addr;
/*
* The MAC address is from 10 to 15.
*
* And yes, I know, the buffer is supposed
* to have a size of 14 bytes.
*/
(void)memcpy(dev->hwaddr,
pifa->ifa_addr->sa_data + 10,
ETHER_ADDR_LEN);
(void)memset(&eth_addr.ether_addr_octet, 0,
ETHER_ADDR_LEN);
(void)memcpy(&eth_addr.ether_addr_octet,
pifa->ifa_addr->sa_data + 10,
ETHER_ADDR_LEN);
break;
}
}
if (pifa == NULL)
tuntap_log(TUNTAP_LOG_WARN,
"Can't get link-layer address");
freeifaddrs(ifa);
}
return fd;
}
static int
tuntap_sys_start_tun(struct device *dev, int tun) {
struct ifreq ifr;
char name[MAXPATHLEN];
int fd;
/*
* Try to use the given driver, or loop throught the avaible ones
*/
fd = -1;
if (tun < TUNTAP_ID_MAX) {
(void)snprintf(name, sizeof name, "/dev/tun%i", tun);
fd = open(name, O_RDWR);
} else if (tun == TUNTAP_ID_ANY) {
for (tun = 0; tun < TUNTAP_ID_MAX; ++tun) {
(void)memset(name, '\0', sizeof name);
(void)snprintf(name, sizeof name, "/dev/tun%i", tun);
if ((fd = open(name, O_RDWR)) > 0)
break;
}
} else {
return -1;
}
switch (fd) {
case -1:
tuntap_log(TUNTAP_LOG_ERR, "Permission denied");
return -1;
case 256:
tuntap_log(TUNTAP_LOG_ERR, "Can't find a tun entry");
return -1;
default:
/* NOTREACHED */
break;
}
/* Set the interface name */
(void)memset(&ifr, '\0', sizeof ifr);
(void)snprintf(ifr.ifr_name, sizeof ifr.ifr_name, "tun%i", tun);
/* And save it */
(void)strlcpy(dev->if_name, ifr.ifr_name, sizeof dev->if_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 fd;
}
int
tuntap_sys_start(struct device *dev, int mode, int tun) {
int fd;
/* Force creation of the driver if needed or let it resilient */
if (mode & TUNTAP_MODE_PERSIST) {
mode &= ~TUNTAP_MODE_PERSIST;
if (tuntap_sys_create_dev(dev, mode, tun) == -1)
return -1;
}
/* tun and tap devices are not created in the same way */
if (mode == TUNTAP_MODE_ETHERNET) {
fd = tuntap_sys_start_tap(dev, tun);
}
else if (mode == TUNTAP_MODE_TUNNEL) {
fd = tuntap_sys_start_tun(dev, tun);
}
else {
return -1;
}
return fd;
}
void
tuntap_sys_destroy(struct device *dev) {
struct ifreq ifr;
(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof ifr.ifr_name);
if (ioctl(dev->ctrl_sock, SIOCIFDESTROY, &ifr) == -1)
tuntap_log(TUNTAP_LOG_WARN, "Can't destroy the interface");
}
int
tuntap_sys_set_hwaddr(struct device *dev, struct ether_addr *eth_addr) {
struct ifaliasreq ifra;
(void)memset(&ifra, 0, sizeof ifra);
(void)memcpy(ifra.ifra_name, dev->if_name, sizeof dev->if_name);
ifra.ifra_addr.sa_len = ETHER_ADDR_LEN;
ifra.ifra_addr.sa_family = AF_LINK;
(void)memcpy(ifra.ifra_addr.sa_data, eth_addr, ETHER_ADDR_LEN);
if (ioctl(dev->ctrl_sock, SIOCSIFPHYADDR, &ifra) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set link-layer address");
return -1;
}
return 0;
}
int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s, uint32_t bits) {
struct ifaliasreq ifa;
struct ifreq ifr;
struct sockaddr_in mask;
struct sockaddr_in addr;
(void)memset(&ifa, '\0', sizeof ifa);
(void)strlcpy(ifa.ifra_name, dev->if_name, sizeof ifa.ifra_name);
(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof ifr.ifr_name);
/* Delete previously assigned address */
(void)ioctl(dev->ctrl_sock, SIOCDIFADDR, &ifr);
/*
* Fill-in the destination address and netmask,
* but don't care of the broadcast address
*/
(void)memset(&addr, '\0', sizeof addr);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = s->s_addr;
addr.sin_len = sizeof addr;
(void)memcpy(&ifa.ifra_addr, &addr, sizeof addr);
(void)memset(&mask, '\0', sizeof mask);
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = bits;
mask.sin_len = sizeof mask;
(void)memcpy(&ifa.ifra_mask, &mask, sizeof ifa.ifra_mask);
/* Simpler than calling SIOCSIFADDR and/or SIOCSIFBRDADDR */
if (ioctl(dev->ctrl_sock, SIOCAIFADDR, &ifa) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set IP/netmask");
return -1;
}
return 0;
}
int
tuntap_sys_set_descr(struct device *dev, const char *descr, size_t len) {
tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_descr()");
return -1;
}

@ -0,0 +1,228 @@
/*
* Copyright (c) 2012 Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/param.h> /* For MAXPATHLEN */
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_tun.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet6/in6_var.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tuntap.h"
static int
tuntap_sys_create_dev(struct device *dev, int tun) {
struct ifreq ifr;
/* At this point 'tun' can't be TUNTAP_ID_ANY */
(void)memset(&ifr, '\0', sizeof ifr);
(void)snprintf(ifr.ifr_name, IF_NAMESIZE, "tun%i", tun);
if (ioctl(dev->ctrl_sock, SIOCIFCREATE, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set persistent");
return -1;
}
return 0;
}
int
tuntap_sys_start(struct device *dev, int mode, int tun) {
int fd;
char name[MAXPATHLEN];
struct ifreq ifr;
/* Get the persistence bit */
if (mode & TUNTAP_MODE_PERSIST) {
mode &= ~TUNTAP_MODE_PERSIST;
/* And force the creation of the driver, if needed */
if (tuntap_sys_create_dev(dev, tun) == -1)
return -1;
}
/* Try to use the given driver or loop throught the avaible ones */
fd = -1;
if (tun < TUNTAP_ID_MAX) {
(void)snprintf(name, sizeof name, "/dev/tun%i", tun);
fd = open(name, O_RDWR);
} else if (tun == TUNTAP_ID_ANY) {
for (tun = 0; tun < TUNTAP_ID_MAX; ++tun) {
(void)memset(name, '\0', sizeof name);
(void)snprintf(name, sizeof name, "/dev/tun%i", tun);
if ((fd = open(name, O_RDWR)) > 0)
break;
}
} else {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'tun'");
return -1;
}
switch (fd) {
case -1:
tuntap_log(TUNTAP_LOG_ERR, "Permission denied");
return -1;
case 256:
tuntap_log(TUNTAP_LOG_ERR, "Can't find a tun entry");
return -1;
default:
/* NOTREACHED */
break;
}
/* Set the interface name */
(void)memset(&ifr, '\0', sizeof ifr);
(void)snprintf(ifr.ifr_name, sizeof ifr.ifr_name, "tun%i", tun);
/* And save it */
(void)strlcpy(dev->if_name, ifr.ifr_name, sizeof dev->if_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;
}
/* Set the mode: tun or tap */
if (mode == TUNTAP_MODE_ETHERNET) {
ifr.ifr_flags |= IFF_LINK0;
}
else if (mode == TUNTAP_MODE_TUNNEL) {
ifr.ifr_flags &= ~IFF_LINK0;
}
else {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'");
return -1;
}
/* Set back our modifications */
if (ioctl(dev->ctrl_sock, SIOCSIFFLAGS, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set interface values");
return -1;
}
/* Save flags for tuntap_{up, down} */
dev->flags = ifr.ifr_flags;
/* Save pre-existing MAC address */
if (mode == TUNTAP_MODE_ETHERNET) {
struct ether_addr addr;
if (ioctl(fd, SIOCGIFADDR, &addr) == -1) {
tuntap_log(TUNTAP_LOG_WARN,
"Can't get link-layer address");
return fd;
}
(void)memcpy(dev->hwaddr, &addr, ETHER_ADDR_LEN);
}
return fd;
}
void
tuntap_sys_destroy(struct device *dev) {
struct ifreq ifr;
(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof ifr.ifr_name);
if (ioctl(dev->ctrl_sock, SIOCIFDESTROY, &ifr) == -1)
tuntap_log(TUNTAP_LOG_WARN, "Can't destroy the interface");
}
int
tuntap_sys_set_hwaddr(struct device *dev, struct ether_addr *eth_addr) {
struct ifreq ifr;
(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof ifr.ifr_name);
ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
ifr.ifr_addr.sa_family = AF_LINK;
(void)memcpy(ifr.ifr_addr.sa_data, eth_addr, ETHER_ADDR_LEN);
if (ioctl(dev->ctrl_sock, SIOCSIFLLADDR, (caddr_t)&ifr) < 0) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set link-layer address");
return -1;
}
return 0;
}
int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s4, uint32_t bits) {
struct ifaliasreq ifa;
struct ifreq ifr;
struct sockaddr_in mask;
struct sockaddr_in addr;
(void)memset(&ifa, '\0', sizeof ifa);
(void)strlcpy(ifa.ifra_name, dev->if_name, sizeof ifa.ifra_name);
(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof ifr.ifr_name);
/* Delete previously assigned address */
(void)ioctl(dev->ctrl_sock, SIOCDIFADDR, &ifr);
/*
* Fill-in the destination address and netmask,
* but don't care of the broadcast address
*/
(void)memset(&addr, '\0', sizeof addr);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = s4->s_addr;
addr.sin_len = sizeof addr;
(void)memcpy(&ifa.ifra_addr, &addr, sizeof addr);
(void)memset(&mask, '\0', sizeof mask);
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = bits;
mask.sin_len = sizeof mask;
(void)memcpy(&ifa.ifra_mask, &mask, sizeof mask);
/* Simpler than calling SIOCSIFADDR and/or SIOCSIFBRDADDR */
if (ioctl(dev->ctrl_sock, SIOCAIFADDR, &ifa) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set IP/netmask");
return -1;
}
return 0;
}
int
tuntap_sys_set_descr(struct device *dev, const char *descr, size_t len) {
struct ifreq ifr;
(void)len;
(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof ifr.ifr_name);
ifr.ifr_data = (void *)descr;
if (ioctl(dev->ctrl_sock, SIOCSIFDESCR, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR,
"Can't set the interface description");
return -1;
}
return 0;
}

@ -0,0 +1,82 @@
/*
* Copyright (c) 2012 Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_tun.h>
#include <net/if_types.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tuntap.h"
static int
tuntap_sys_create_dev(struct device *dev, int tun) {
return -1;
}
int
tuntap_sys_start(struct device *dev, int mode, int tun) {
return -1;
}
void
tuntap_sys_destroy(struct device *dev) {
return -1;
}
int
tuntap_sys_set_hwaddr(struct device *dev, struct ether_addr *eth_addr) {
return -1;
}
int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s4, uint32_t imask) {
return -1;
}
int
tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s6, uint32_t imask) {
return -1;
}
int
tuntap_sys_set_ifname(struct device *dev, const char *ifname, size_t len) {
(void)dev;
(void)ifname;
(void)len;
return -1;
}
int
tuntap_sys_set_descr(struct device *dev, const char *descr, size_t len) {
(void)dev;
(void)descr;
(void)len;
return -1;
}

@ -0,0 +1,360 @@
/*
* Copyright (c) 2012 Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Copyright (c) 2016 Mahdi Mokhtari <mokhi64@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#if defined Linux
# include <netinet/ether.h>
# include <linux/if_tun.h>
#else
# include <net/if.h>
# if defined DragonFly
# include <net/tun/if_tun.h>
# elif !defined Darwin
# include <net/if_tun.h>
# endif
# include <netinet/in.h>
# include <netinet/if_ether.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tuntap.h"
int
tuntap_start(struct device *dev, int mode, int tun) {
int sock;
int fd;
fd = sock = -1;
/* Don't re-initialise a previously started device */
if (dev->tun_fd != -1) {
tuntap_log(TUNTAP_LOG_ERR, "Device is already started");
return -1;
}
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
goto clean;
}
dev->ctrl_sock = sock;
if (mode & TUNTAP_MODE_PERSIST && tun == TUNTAP_ID_ANY) {
goto clean; /* XXX: Explain why */
}
fd = tuntap_sys_start(dev, mode, tun);
if (fd == -1) {
goto clean;
}
dev->tun_fd = fd;
tuntap_set_debug(dev, 0);
return 0;
clean:
if (fd != -1) {
(void)close(fd);
}
if (sock != -1) {
(void)close(sock);
}
return -1;
}
void
tuntap_release(struct device *dev) {
(void)close(dev->tun_fd);
(void)close(dev->ctrl_sock);
free(dev);
}
int
tuntap_set_descr(struct device *dev, const char *descr) {
size_t len;
if (descr == NULL) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'descr'");
return -1;
}
len = strlen(descr);
if (len > IF_DESCRSIZE) {
/* The value will be troncated */
tuntap_log(TUNTAP_LOG_WARN, "Parameter 'descr' is too long");
}
if (tuntap_sys_set_descr(dev, descr, len) == -1) {
return -1;
}
return 0;
}
int
tuntap_set_ifname(struct device *dev, const char *ifname) {
size_t len;
if (ifname == NULL) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'ifname'");
return -1;
}
len = strlen(ifname);
if (len > IF_NAMESIZE) {
tuntap_log(TUNTAP_LOG_ERR, "Parameter 'ifname' is too long");
return -1;
}
if (tuntap_sys_set_ifname(dev, ifname, len) == -1) {
return -1;
}
(void)memset(dev->if_name, 0, IF_NAMESIZE);
(void)strncpy(dev->if_name, ifname, len);
return 0;
}
char *
tuntap_get_hwaddr(struct device *dev) {
struct ether_addr eth_attr;
(void)memcpy(&eth_attr, dev->hwaddr, sizeof dev->hwaddr);
return ether_ntoa(&eth_attr);
}
int
tuntap_set_hwaddr(struct device *dev, const char *hwaddr) {
struct ether_addr *eth_addr, eth_rand;
if (strcmp(hwaddr, "random") == 0) {
unsigned int i;
unsigned char *ptr;
i = 0;
ptr = (unsigned char *)&eth_rand;
srandom((unsigned int)time(NULL));
for (; i < sizeof eth_rand; ++i) {
*ptr = (unsigned char)random();
ptr++;
}
ptr = (unsigned char *)&eth_rand;
*ptr &= 0xfc;
eth_addr = &eth_rand;
} else {
eth_addr = ether_aton(hwaddr);
if (eth_addr == NULL) {
return -1;
}
}
(void)memcpy(dev->hwaddr, eth_addr, ETHER_ADDR_LEN);
if (tuntap_sys_set_hwaddr(dev, eth_addr) == -1)
return -1;
return 0;
}
int
tuntap_up(struct device *dev) {
struct ifreq ifr;
(void)memset(&ifr, '\0', sizeof ifr);
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
ifr.ifr_flags = (short int)dev->flags;
ifr.ifr_flags |= IFF_UP;
if (ioctl(dev->ctrl_sock, SIOCSIFFLAGS, &ifr) == -1) {
return -1;
}
dev->flags = ifr.ifr_flags;
return 0;
}
int
tuntap_down(struct device *dev) {
struct ifreq ifr;
(void)memset(&ifr, '\0', sizeof ifr);
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
ifr.ifr_flags = (short)dev->flags;
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(dev->ctrl_sock, SIOCSIFFLAGS, &ifr) == -1) {
return -1;
}
dev->flags = ifr.ifr_flags;
return 0;
}
int
tuntap_get_mtu(struct device *dev) {
struct ifreq ifr;
/* Only accept started device */
if (dev->tun_fd == -1) {
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
}
(void)memset(&ifr, '\0', sizeof ifr);
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
if (ioctl(dev->ctrl_sock, SIOCGIFMTU, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't get MTU");
return -1;
}
return ifr.ifr_mtu;
}
int
tuntap_set_mtu(struct device *dev, int mtu) {
struct ifreq ifr;
/* Only accept started device */
if (dev->tun_fd == -1) {
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
}
(void)memset(&ifr, '\0', sizeof ifr);
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
ifr.ifr_mtu = mtu;
if (ioctl(dev->ctrl_sock, SIOCSIFMTU, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set MTU");
return -1;
}
return 0;
}
int
tuntap_read(struct device *dev, void *buf, size_t size) {
int n;
/* Only accept started device */
if (dev->tun_fd == -1) {
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
}
n = read(dev->tun_fd, buf, size);
if (n == -1) {
tuntap_log(TUNTAP_LOG_WARN, "Can't to read from device");
return -1;
}
return n;
}
int
tuntap_write(struct device *dev, void *buf, size_t size) {
int n;
/* Only accept started device */
if (dev->tun_fd == -1) {
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
}
n = write(dev->tun_fd, buf, size);
if (n == -1) {
tuntap_log(TUNTAP_LOG_WARN, "Can't write to device");
return -1;
}
return n;
}
int
tuntap_get_readable(struct device *dev) {
int n;
n = 0;
if (ioctl(dev->tun_fd, FIONREAD, &n) == -1) {
tuntap_log(TUNTAP_LOG_INFO, "Your system does not support"
" FIONREAD, fallback to MTU");
return tuntap_get_mtu(dev);
}
return n;
}
int
tuntap_set_nonblocking(struct device *dev, int set) {
if (ioctl(dev->tun_fd, FIONBIO, &set) == -1) {
switch(set) {
case 0:
tuntap_log(TUNTAP_LOG_ERR, "Can't unset nonblocking");
break;
case 1:
tuntap_log(TUNTAP_LOG_ERR, "Can't set nonblocking");
break;
default:
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'set'");
}
return -1;
}
return 0;
}
int
tuntap_set_debug(struct device *dev, int set) {
/* Only accept started device */
if (dev->tun_fd == -1) {
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
}
#if !defined Darwin
if (ioctl(dev->tun_fd, TUNSDEBUG, &set) == -1) {
switch(set) {
case 0:
tuntap_log(TUNTAP_LOG_WARN, "Can't unset debug");
break;
case 1:
tuntap_log(TUNTAP_LOG_WARN, "Can't set debug");
break;
default:
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'set'");
}
return -1;
}
return 0;
#else
tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_debug()");
return -1;
#endif
}

@ -0,0 +1,373 @@
/*
* Copyright (c) 2012 Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <strsafe.h>
#include "tuntap.h"
/* From OpenVPN tap driver, common.h */
#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED)
#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED)
#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED)
#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED)
#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_TUN TAP_CONTROL_CODE (10, METHOD_BUFFERED)
/* Windows registry crap */
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
#define NETWORK_ADAPTERS "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
/* From OpenVPN tap driver, proto.h */
typedef unsigned long IPADDR;
/* This one is from Fabien Pichot, in the tNETacle source code */
static LPWSTR
formated_error(LPWSTR pMessage, DWORD m, ...) {
LPWSTR pBuffer = NULL;
va_list args = NULL;
va_start(args, pMessage);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER,
pMessage,
m,
0,
(LPSTR)&pBuffer,
0,
&args);
va_end(args);
return pBuffer;
}
/* TODO: Rework to be more generic and allow arbitrary key modification (MTU and stuff) */
static char *
reg_query(char *key_name) {
HKEY adapters, adapter;
DWORD i, ret, len;
char *deviceid = NULL;
DWORD sub_keys = 0;
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(key_name), 0, KEY_READ, &adapters);
if (ret != ERROR_SUCCESS) {
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", ret));
return NULL;
}
ret = RegQueryInfoKey(adapters, NULL, NULL, NULL, &sub_keys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (ret != ERROR_SUCCESS) {
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", ret));
return NULL;
}
if (sub_keys <= 0) {
tuntap_log(TUNTAP_LOG_DEBUG, "Wrong registry key");
return NULL;
}
/* Walk througt all adapters */
for (i = 0; i < sub_keys; i++) {
char new_key[MAX_KEY_LENGTH];
char data[256];
TCHAR key[MAX_KEY_LENGTH];
DWORD keylen = MAX_KEY_LENGTH;
/* Get the adapter key name */
ret = RegEnumKeyEx(adapters, i, key, &keylen, NULL, NULL, NULL, NULL);
if (ret != ERROR_SUCCESS) {
continue;
}
/* Append it to NETWORK_ADAPTERS and open it */
snprintf(new_key, sizeof new_key, "%s\\%s", key_name, key);
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(new_key), 0, KEY_READ, &adapter);
if (ret != ERROR_SUCCESS) {
continue;
}
/* Check its values */
len = sizeof data;
ret = RegQueryValueEx(adapter, "ComponentId", NULL, NULL, (LPBYTE)data, &len);
if (ret != ERROR_SUCCESS) {
/* This value doesn't exist in this adaptater tree */
goto clean;
}
/* If its a tap adapter, its all good */
if (strncmp(data, "tap", 3) == 0) {
DWORD type;
len = sizeof data;
ret = RegQueryValueEx(adapter, "NetCfgInstanceId", NULL, &type, (LPBYTE)data, &len);
if (ret != ERROR_SUCCESS) {
tuntap_log(TUNTAP_LOG_INFO, (const char *)formated_error(L"%1", ret));
goto clean;
}
deviceid = strdup(data);
break;
}
clean:
RegCloseKey(adapter);
}
RegCloseKey(adapters);
return deviceid;
}
void
tuntap_sys_destroy(struct device *dev) {
(void)dev;
return;
}
int
tuntap_start(struct device *dev, int mode, int tun) {
HANDLE tun_fd;
char *deviceid;
char buf[60];
/* Don't re-initialise a previously started device */
if (dev->tun_fd != TUNFD_INVALID_VALUE) {
return -1;
}
/* Shift the persistence bit */
if (mode & TUNTAP_MODE_PERSIST) {
mode &= ~TUNTAP_MODE_PERSIST;
}
if (mode == TUNTAP_MODE_TUNNEL) {
tuntap_log(TUNTAP_LOG_NOTICE, "Layer 3 tunneling is not implemented");
return -1;
}
else if (mode != TUNTAP_MODE_ETHERNET) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'");
return -1;
}
deviceid = reg_query(NETWORK_ADAPTERS);
snprintf(buf, sizeof buf, "\\\\.\\Global\\%s.tap", deviceid);
tun_fd = CreateFile(buf, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED, 0);
if (tun_fd == TUNFD_INVALID_VALUE) {
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
dev->tun_fd = tun_fd;
return 0;
}
void
tuntap_release(struct device *dev) {
(void)CloseHandle(dev->tun_fd);
free(dev);
}
char *
tuntap_get_hwaddr(struct device *dev) {
static unsigned char hwaddr[ETHER_ADDR_LEN];
DWORD len;
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_GET_MAC, &hwaddr, sizeof(hwaddr), &hwaddr, sizeof(hwaddr), &len, NULL) == 0) {
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return NULL;
} else {
char buf[128];
(void)_snprintf_s(buf, sizeof buf, sizeof buf, "MAC address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
hwaddr[0],hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]);
tuntap_log(TUNTAP_LOG_DEBUG, buf);
}
return (char *)hwaddr;
}
int
tuntap_set_hwaddr(struct device *dev, const char *hwaddr) {
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_hwaddr()");
return -1;
}
static int
tuntap_sys_set_updown(struct device *dev, ULONG flag) {
DWORD len;
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_SET_MEDIA_STATUS, &flag, sizeof(flag), &flag, sizeof(flag), &len, NULL) == 0) {
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
} else {
char buf[32];
(void)_snprintf_s(buf, sizeof buf, sizeof buf, "Status: %s", flag ? "Up" : "Down");
tuntap_log(TUNTAP_LOG_DEBUG, buf);
return 0;
}
}
int
tuntap_up(struct device *dev) {
ULONG flag;
flag = 1;
return tuntap_sys_set_updown(dev, flag);
}
int
tuntap_down(struct device *dev) {
ULONG flag;
flag = 0;
return tuntap_sys_set_updown(dev, flag);
}
int
tuntap_get_mtu(struct device *dev) {
ULONG mtu;
DWORD len;
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_GET_MTU, &mtu, sizeof(mtu), &mtu, sizeof(mtu), &len, NULL) == 0) {
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
return 0;
}
int
tuntap_set_mtu(struct device *dev, int mtu) {
(void)dev;
(void)mtu;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_mtu()");
return -1;
}
int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s, uint32_t mask) {
IPADDR psock[4];
DWORD len;
/* Address + Netmask */
psock[0] = s->S_un.S_addr;
psock[1] = mask;
/* DHCP server address (We don't want it) */
psock[2] = 0;
/* DHCP lease time */
psock[3] = 0;
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_CONFIG_DHCP_MASQ, &psock, sizeof(psock), &psock, sizeof(psock), &len, NULL) == 0) {
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
return 0;
}
int
tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s, uint32_t mask) {
(void)dev;
(void)s;
(void)mask;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_sys_set_ipv6()");
return -1;
}
int
tuntap_read(struct device *dev, void *buf, size_t size) {
DWORD len;
if (ReadFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0) {
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
return 0;
}
int
tuntap_write(struct device *dev, void *buf, size_t size) {
DWORD len;
if (WriteFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0) {
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
return 0;
}
int
tuntap_get_readable(struct device *dev) {
(void)dev;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_get_readable()");
return -1;
}
int
tuntap_set_nonblocking(struct device *dev, int set) {
(void)dev;
(void)set;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_nonblocking()");
return -1;
}
int
tuntap_set_debug(struct device *dev, int set) {
(void)dev;
(void)set;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_debug()");
return -1;
}
int
tuntap_set_descr(struct device *dev, const char *descr) {
(void)dev;
(void)descr;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_descr()");
return -1;
}
int
tuntap_set_ifname(struct device *dev, const char *name) {
/* TODO: Check Windows API to know how to rename an interface */
(void)dev;
(void)name;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_ifname()");
return -1;
}

@ -0,0 +1,223 @@
/*
* Copyright (c) 2012 Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Copyright (c) 2016 Mahdi Mokhtari <mokhi64@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#if defined Windows
# include <winsock2.h>
# include <ws2tcpip.h>
#else
# include <netinet/in.h>
# include <arpa/inet.h>
#endif
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "tuntap.h"
struct device *
tuntap_init(void) {
struct device *dev = NULL;
if ((dev = (struct device *)malloc(sizeof(*dev))) == NULL)
return NULL;
(void)memset(dev->if_name, '\0', sizeof(dev->if_name));
(void)memset(dev->hwaddr, '\0', sizeof(dev->hwaddr));
dev->tun_fd = TUNFD_INVALID_VALUE;
dev->ctrl_sock = -1;
dev->flags = 0;
tuntap_log = tuntap_log_default;
return dev;
}
void
tuntap_destroy(struct device *dev) {
tuntap_sys_destroy(dev);
tuntap_release(dev);
}
char *
tuntap_get_ifname(struct device *dev) {
return dev->if_name;
}
int
tuntap_version(void) {
return TUNTAP_VERSION;
}
#if !defined(FreeBSD)
int
tuntap_set_ip_old(struct device *dev, const char *addr, int netmask) {
t_tun_in_addr baddr4;
t_tun_in6_addr baddr6;
uint32_t mask;
int errval;
/* Only accept started device */
if (dev->tun_fd == TUNFD_INVALID_VALUE) {
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
}
if (addr == NULL) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'addr'");
return -1;
}
if (netmask < 0 || netmask > 128) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'netmask'");
return -1;
}
/* Netmask */
mask = ~0;
mask = ~(mask >> netmask);
mask = htonl(mask);
/*
* Destination address parsing: we try IPv4 first and fall back to
* IPv6 if inet_pton return 0
*/
(void)memset(&baddr4, '\0', sizeof(baddr4));
(void)memset(&baddr6, '\0', sizeof(baddr6));
errval = inet_pton(AF_INET, addr, &(baddr4));
if (errval == 1) {
return tuntap_sys_set_ipv4(dev, &baddr4, mask);
} else if (errval == 0) {
if (inet_pton(AF_INET6, addr, &(baddr6)) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameters");
return -1;
}
return tuntap_sys_set_ipv6(dev, &baddr6, mask);
} else if (errval == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameters");
return -1;
}
/* NOTREACHED */
return -1;
}
#endif
int
tuntap_set_ip(struct device *dev, ...)
{
va_list vl;
char *saddr;
char *daddr;
int netmask;
t_tun_in_addr sbaddr4;
t_tun_in_addr dbaddr4;
t_tun_in6_addr sbaddr6;
t_tun_in6_addr dbaddr6;
uint32_t mask;
int errval;
saddr = daddr = NULL;
netmask = -1;
va_start(vl, dev);
saddr = va_arg(vl, char *);
netmask = va_arg(vl, int);
#if defined(FreeBSD)
if (dev->mode == TUNTAP_MODE_TUNNEL)
daddr = va_arg(vl, char *);
#endif
va_end(vl);
/* Only accept started device */
if (dev->tun_fd == TUNFD_INVALID_VALUE) {
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
}
if (saddr == NULL) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'saddr'");
return -1;
}
if (netmask < 0 || netmask > 128) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'netmask'");
return -1;
}
/* Netmask */
mask = ~0;
mask = ~(mask >> netmask);
mask = htonl(mask);
/*
* Destination address parsing: we try IPv4 first and fall back to
* IPv6 if inet_pton return 0
*/
(void)memset(&sbaddr4, 0, sizeof(sbaddr4));
(void)memset(&sbaddr6, 0, sizeof(sbaddr6));
errval = inet_pton(AF_INET, saddr, &(sbaddr4));
if (errval == 1) {
#if defined(FreeBSD)
#define tuntap_sys_set_ipv4 tuntap_sys_set_ipv4_tap
if (dev->mode == TUNTAP_MODE_TUNNEL) {
if (daddr == NULL) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'daddr'");
return -1;
}
(void)memset(&dbaddr4, 0, sizeof(dbaddr4));
(void)inet_pton(AF_INET, daddr, &(dbaddr4));
return tuntap_sys_set_ipv4_tun(dev, &sbaddr4, &dbaddr4, mask);
} else
#endif
{
return tuntap_sys_set_ipv4(dev, &sbaddr4, mask);
}
} else if (errval == 0) {
#if !defined(FreeBSD) /* No IPV6 tests YET */
if (inet_pton(AF_INET6, saddr, &(sbaddr6)) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameters");
return -1;
}
return tuntap_sys_set_ipv6(dev, &sbaddr6, mask);
} else if (errval == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameters");
return -1;
#endif
}
/* NOTREACHED */
return -1;
}

@ -0,0 +1,213 @@
/*
* Copyright (c) 2012 Tristan Le Guern <leguern AT medu DOT se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Copyright (c) 2016 Mahdi Mokhtari <mokhi64@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* 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.
*/
#include <sys/types.h>
#if defined Windows
# include <In6addr.h>
#else /* Unix */
# include <sys/socket.h>
#endif
#if !defined Windows /* Unix :) */
# if defined Linux
# include <linux/if.h>
# else
# include <net/if.h>
# endif
# include <netinet/in.h>
# include <netinet/if_ether.h>
#endif
#include <stdint.h>
#ifndef LIBTUNTAP_H_
# define LIBTUNTAP_H_
/*
* Uniformize macros
* - ETHER_ADDR_LEN: Magic number from IEEE 802.3
* - IF_NAMESIZE: Length of interface external name
* - IF_DESCRSIZE: Length of interface description
* - TUNSDEBUG: ioctl flag to enable the debug mode of a tun device
* - TUNFD_INVALID_VALUE: Invalid value for tun_fd
*/
# if defined ETH_ALEN /* Linux */
# define ETHER_ADDR_LEN ETH_ALEN
# elif defined Windows
# define ETHER_ADDR_LEN 6
# endif
# if defined IFNAMSIZ && !defined IF_NAMESIZE
# define IF_NAMESIZE IFNAMSIZ /* Historical BSD name */
# elif !defined IF_NAMESIZE
# define IF_NAMESIZE 16
# endif
# define IF_DESCRSIZE 50 /* XXX: Tests needed on NetBSD and OpenBSD */
# if defined TUNSETDEBUG
# define TUNSDEBUG TUNSETDEBUG
# endif
# if defined Windows
# define TUNFD_INVALID_VALUE INVALID_HANDLE_VALUE
# else /* Unix */
# define TUNFD_INVALID_VALUE -1
# endif
/*
* Uniformize types
* - t_tun: tun device file descriptor
* - t_tun_in_addr: struct in_addr/IN_ADDR
* - t_tun_in6_addr: struct in6_addr/IN6_ADDR
*/
# if defined Windows
typedef HANDLE t_tun;
typedef IN_ADDR t_tun_in_addr;
typedef IN6_ADDR t_tun_in6_addr;
# else /* Unix */
typedef int t_tun;
typedef struct in_addr t_tun_in_addr;
typedef struct in6_addr t_tun_in6_addr;
# endif
/*
* Windows helpers
*/
# if defined Windows
# define snprintf(x, y, z, ...) _snprintf_s((x), (y), (y), (z), __VA_ARGS__);
# define strncat(x, y, z) strncat_s((x), _countof(x), (y), (z));
# define strdup(x) _strdup(x)
# endif
# define TUNTAP_ID_MAX 256
# define TUNTAP_ID_ANY 257
# define TUNTAP_MODE_ETHERNET 0x0001
# define TUNTAP_MODE_TUNNEL 0x0002
# define TUNTAP_MODE_PERSIST 0x0004
# define TUNTAP_LOG_NONE 0x0000
# define TUNTAP_LOG_DEBUG 0x0001
# define TUNTAP_LOG_INFO 0x0002
# define TUNTAP_LOG_NOTICE 0x0004
# define TUNTAP_LOG_WARN 0x0008
# define TUNTAP_LOG_ERR 0x0016
/* Versioning: 0xMMmm, with 'M' for major and 'm' for minor */
# define TUNTAP_VERSION_MAJOR 0
# define TUNTAP_VERSION_MINOR 3
# define TUNTAP_VERSION ((TUNTAP_VERSION_MAJOR<<8)|TUNTAP_VERSION_MINOR)
# define TUNTAP_GET_FD(x) (x)->tun_fd
/* Handle Windows symbols export */
# if defined Windows
# if defined(tuntap_EXPORTS) /* CMake generated goo */
# define TUNTAP_EXPORT __declspec(dllexport)
# else
# define TUNTAP_EXPORT __declspec(dllimport)
# endif
# else /* Unix */
# define TUNTAP_EXPORT
# endif
# ifdef __cplusplus
extern "C" {
# endif
struct device {
t_tun tun_fd;
int ctrl_sock;
int flags; /* ifr.ifr_flags on Unix */
unsigned char hwaddr[ETHER_ADDR_LEN];
char if_name[IF_NAMESIZE];
#if defined(FreeBSD)
int mode;
#endif
};
/* User definable log callback */
typedef void (*t_tuntap_log)(int, const char *);
TUNTAP_EXPORT t_tuntap_log tuntap_log;
/* Portable "public" functions */
TUNTAP_EXPORT struct device *tuntap_init(void);
TUNTAP_EXPORT int tuntap_version(void);
TUNTAP_EXPORT void tuntap_destroy(struct device *);
TUNTAP_EXPORT void tuntap_release(struct device *);
TUNTAP_EXPORT int tuntap_start(struct device *, int, int);
TUNTAP_EXPORT char *tuntap_get_ifname(struct device *);
TUNTAP_EXPORT int tuntap_set_ifname(struct device *, const char *);
TUNTAP_EXPORT char *tuntap_get_hwaddr(struct device *);
TUNTAP_EXPORT int tuntap_set_hwaddr(struct device *, const char *);
TUNTAP_EXPORT int tuntap_set_descr(struct device *, const char *);
TUNTAP_EXPORT int tuntap_up(struct device *);
TUNTAP_EXPORT int tuntap_down(struct device *);
TUNTAP_EXPORT int tuntap_get_mtu(struct device *);
TUNTAP_EXPORT int tuntap_set_mtu(struct device *, int);
/*
* It's impossible to set single IP for `tun` devices on FreeBSD .
* FreeBSD's `tun` interface needs 2 IP addresses.
* So a new (and backward compatible) version of tuntap_set_ip() is implemented.
*/
TUNTAP_EXPORT int tuntap_set_ip(struct device *, ...);
//TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char *, int);
/*TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char *, int);*/
TUNTAP_EXPORT int tuntap_read(struct device *, void *, size_t);
TUNTAP_EXPORT int tuntap_write(struct device *, void *, size_t);
TUNTAP_EXPORT int tuntap_get_readable(struct device *);
TUNTAP_EXPORT int tuntap_set_nonblocking(struct device *dev, int);
TUNTAP_EXPORT int tuntap_set_debug(struct device *dev, int);
/* Logging functions */
TUNTAP_EXPORT void tuntap_log_set_cb(t_tuntap_log cb);
void tuntap_log_default(int, const char *);
void tuntap_log_hexdump(void *, size_t);
void tuntap_log_chksum(void *, int);
/* OS specific functions */
int tuntap_sys_start(struct device *, int, int);
void tuntap_sys_destroy(struct device *);
int tuntap_sys_set_hwaddr(struct device *, struct ether_addr *);
int tuntap_sys_set_ipv4(struct device *, t_tun_in_addr *, uint32_t);
#if defined(FreeBSD)
int tuntap_sys_set_ipv4_tap(struct device *, t_tun_in_addr *, uint32_t);
int tuntap_sys_set_ipv4_tun(struct device *dev, t_tun_in_addr *s4, t_tun_in_addr *s4dest, uint32_t bits);
#endif
int tuntap_sys_set_ipv6(struct device *, t_tun_in6_addr *, uint32_t);
int tuntap_sys_set_ifname(struct device *, const char *, size_t);
int tuntap_sys_set_descr(struct device *, const char *, size_t);
# ifdef __cplusplus
}
# endif
#endif

@ -0,0 +1,147 @@
/**
* Copyright (c) 2012, PICHOT Fabien Paul Leonard <pichot.fabienATgmail.com>
* Copyright (c) 2012, Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 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.
**/
#if defined Windows
# include <windows.h>
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>
#include "tuntap.h"
void
tuntap_log_set_cb(t_tuntap_log cb) {
if (cb == NULL)
tuntap_log = tuntap_log_default;
tuntap_log = cb;
}
void
tuntap_log_default(int level, const char *errmsg) {
char *name;
switch(level) {
case TUNTAP_LOG_DEBUG:
name = "Debug";
break;
case TUNTAP_LOG_INFO:
name = "Info";
break;
case TUNTAP_LOG_NOTICE:
name = "Notice";
break;
case TUNTAP_LOG_WARN:
name = "Warning";
break;
case TUNTAP_LOG_ERR:
name = "Error";
break;
case TUNTAP_LOG_NONE:
default:
name = NULL;
break;
}
if (name == NULL) {
(void)fprintf(stderr, "%s\n", errmsg);
} else {
(void)fprintf(stderr, "%s: %s\n", name, errmsg);
}
}
void
tuntap_log_hexdump(void *data, size_t size) {
unsigned char *p = (unsigned char *)data;
unsigned int c;
size_t n;
char bytestr[4] = {0};
char addrstr[10] = {0};
char hexstr[16 * 3 + 5] = {0};
char charstr[16 * 1 + 5] = {0};
char buf[1024];
for (n = 1; n <= size; n++) {
if (n % 16 == 1) {
/* store address for this line */
snprintf(addrstr, sizeof(addrstr), "%.4lx",
((uintptr_t)p - (uintptr_t)data) );
}
c = *p;
if (isalnum(c) == 0) {
c = '.';
}
/* store hex str (for left side) */
snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
/* store char str (for right side) */
snprintf(bytestr, sizeof(bytestr), "%c", c);
strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
if (n % 16 == 0) {
/* line completed */
(void)memset(buf, 0, sizeof buf);
(void)snprintf(buf, sizeof buf,
"[%4.4s] %-50.50s %s", addrstr, hexstr, charstr);
tuntap_log(TUNTAP_LOG_NONE, buf);
hexstr[0] = 0;
charstr[0] = 0;
} else if (n % 8 == 0) {
/* half line: add whitespaces */
strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1);
strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
}
p++; /* next byte */
}
/* print the rest of the buffer if not empty */
if (strlen(hexstr) > 0) {
(void)memset(buf, 0, sizeof buf);
(void)snprintf(buf, sizeof buf, "[%4.4s] %-50.50s %s",
addrstr, hexstr, charstr);
tuntap_log(TUNTAP_LOG_NONE, buf);
}
}
void
tuntap_log_chksum(void *addr, int count) {
int sum;
short *sptr;
char buf[32];
sum = 0;
sptr = (short *)addr;
while (count > 1)
{
sum = sum + *sptr;
count = count - 2;
sptr++;
}
addr = (char *)sptr;
if (count > 0)
sum = sum + *((char *) addr);
sum = ~sum;
(void)memset(buf, 0, sizeof buf);
(void)snprintf(buf, sizeof buf, "Checksum of this block: %0#4x", sum);
tuntap_log(TUNTAP_LOG_NONE, buf);
}
Loading…
Cancel
Save