195 lines
4.5 KiB
C++
195 lines
4.5 KiB
C++
/* Linux TUN device Test Port for Eclipse Titan
|
|
* (C) 2017 by Harald Welte <laforge@gnumonks.org>
|
|
* Licensed under Eclipse Public License - v1.0 or GPLv2, at your choice */
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <linux/if.h>
|
|
#include <linux/if_tun.h>
|
|
|
|
#include "TunDevice_PT.hh"
|
|
#include "TunDevice_PortType.hh"
|
|
#include "TunDevice_Types.hh"
|
|
|
|
namespace TunDevice__PortType {
|
|
|
|
/* private helper to open the device */
|
|
void TunDevice__PT_PROVIDER::open_device(void)
|
|
{
|
|
struct ifreq ifr;
|
|
int fd, err;
|
|
|
|
log("%s: entering", __func__);
|
|
|
|
if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
|
|
TTCN_error("Unable to open /dev/net/tun");
|
|
return;
|
|
}
|
|
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
|
|
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
|
|
if (tun_data.dev)
|
|
strncpy(ifr.ifr_name, tun_data.dev, IFNAMSIZ);
|
|
if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0) {
|
|
TTCN_error("Unable to issue TUNSETIFF ioctl() for '%s'", ifr.ifr_name);
|
|
close(fd);
|
|
return;
|
|
}
|
|
|
|
log("%s: Successfully opened TUN device", __func__);
|
|
if (!tun_data.dev)
|
|
tun_data.dev = strdup(ifr.ifr_name);
|
|
else
|
|
strcpy(tun_data.dev, ifr.ifr_name);
|
|
tun_data.fd = fd;
|
|
Handler_Add_Fd_Read(fd);
|
|
}
|
|
|
|
/* private helper to closethe device */
|
|
void TunDevice__PT_PROVIDER::close_device(void)
|
|
{
|
|
if (tun_data.fd != -1) {
|
|
close(tun_data.fd);
|
|
tun_data.fd = -1;
|
|
}
|
|
}
|
|
|
|
/* private log helper */
|
|
void TunDevice__PT_PROVIDER::log(const char *fmt, ...)
|
|
{
|
|
if (debugging) {
|
|
TTCN_Logger::begin_event(TTCN_DEBUG);
|
|
TTCN_Logger::log_event("Tun test port (%s): ", get_name());
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
TTCN_Logger::log_event_va_list(fmt, args);
|
|
va_end(args);
|
|
TTCN_Logger::end_event();
|
|
}
|
|
}
|
|
|
|
/* private log helper */
|
|
void TunDevice__PT_PROVIDER::logHex(const char *prompt, const OCTETSTRING& msg)
|
|
{
|
|
if (debugging) {
|
|
TTCN_Logger::begin_event(TTCN_DEBUG);
|
|
TTCN_Logger::log_event("Size: %d,\nMSG: ", msg.lengthof());
|
|
|
|
for (int i = 0; i < msg.lengthof(); i++)
|
|
TTCN_Logger::log_event(" %02x", ((const unsigned char *)msg)[i]);
|
|
TTCN_Logger::log_event("\n");
|
|
TTCN_Logger::end_event();
|
|
}
|
|
}
|
|
|
|
/* constructor */
|
|
TunDevice__PT_PROVIDER::TunDevice__PT_PROVIDER(const char *par_port_name)
|
|
: PORT(par_port_name)
|
|
{
|
|
tun_data.fd = -1;
|
|
tun_data.dev = NULL;
|
|
debugging = false;
|
|
}
|
|
|
|
/* destructor */
|
|
TunDevice__PT_PROVIDER::~TunDevice__PT_PROVIDER()
|
|
{
|
|
close_device();
|
|
free(tun_data.dev);
|
|
tun_data.dev = NULL;
|
|
}
|
|
|
|
/* setting a port parameter via config file */
|
|
void TunDevice__PT_PROVIDER::set_parameter(const char *parameter_name, const char *parameter_value)
|
|
{
|
|
//printf("%s(%s, %s)\n", __func__, parameter_name, parameter_value);
|
|
if (!strcmp(parameter_name, "device_name"))
|
|
tun_data.dev = strdup(parameter_value);
|
|
if (!strcmp(parameter_name, "debugging"))
|
|
debugging = true;
|
|
}
|
|
|
|
/*void TunDevice__PT_PROVIDER::Handle_Fd_Event(int fd, boolean is_readable,
|
|
boolean is_writable, boolean is_error) {}*/
|
|
|
|
void TunDevice__PT_PROVIDER::Handle_Fd_Event_Error(int fd)
|
|
{
|
|
}
|
|
|
|
void TunDevice__PT_PROVIDER::Handle_Fd_Event_Writable(int fd)
|
|
{
|
|
}
|
|
|
|
/* function called if FD becomes readable: pull packet from chardev */
|
|
void TunDevice__PT_PROVIDER::Handle_Fd_Event_Readable(int fd)
|
|
{
|
|
uint8_t msg[0xffff];
|
|
int rc;
|
|
|
|
log("entering %s", __func__);
|
|
|
|
rc = read(tun_data.fd, msg, sizeof(msg));
|
|
if (rc < 0) {
|
|
TTCN_error("reading from tun");
|
|
return;
|
|
}
|
|
TunDevice__Types::Tun__recv recv;
|
|
recv.msg() = OCTETSTRING(rc, msg);
|
|
|
|
logHex("receveid data: ", recv.msg());
|
|
incoming_message(recv);
|
|
}
|
|
|
|
/*void TunDevice__PT_PROVIDER::Handle_Timeout(double time_since_last_call) {}*/
|
|
|
|
/* user map's to our test port -> open */
|
|
void TunDevice__PT_PROVIDER::user_map(const char *system_port)
|
|
{
|
|
open_device();
|
|
}
|
|
|
|
/* user unmap's our test port -> close */
|
|
void TunDevice__PT_PROVIDER::user_unmap(const char *system_port)
|
|
{
|
|
close_device();
|
|
}
|
|
|
|
/* user calls 'start' on given port */
|
|
void TunDevice__PT_PROVIDER::user_start()
|
|
{
|
|
}
|
|
|
|
/* user calls 'stop' on given port */
|
|
void TunDevice__PT_PROVIDER::user_stop()
|
|
{
|
|
}
|
|
|
|
/* user wants to send something through the port */
|
|
void TunDevice__PT_PROVIDER::outgoing_send(const TunDevice__Types::Tun__send& send_par)
|
|
{
|
|
int rc;
|
|
|
|
log("entering %s", __func__);
|
|
logHex("sending data: ", send_par.msg());
|
|
|
|
rc = write(tun_data.fd, (const char*)(const unsigned char*)send_par.msg(),
|
|
send_par.msg().lengthof());
|
|
if (rc < 0) {
|
|
TTCN_error("writing to tun");
|
|
return;
|
|
}
|
|
log("Nr of bytes sent = %d", rc);
|
|
log("leaving %s", __func__);
|
|
}
|
|
|
|
} /* end of namespace */
|
|
|