netfilter-titan/testproject/TunDevice_PT.cc

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 */