Daynaport device can be configured with interface list (issue #202)

This commit is contained in:
Uwe Seimet
2021-08-24 20:05:16 +02:00
parent e336e726cb
commit 106d2d50d1
10 changed files with 92 additions and 70 deletions

View File

@@ -26,7 +26,7 @@
#include "ctapdriver.h" #include "ctapdriver.h"
#include "log.h" #include "log.h"
#include "exceptions.h" #include "exceptions.h"
#include <string> #include <sstream>
using namespace std; using namespace std;
@@ -35,9 +35,14 @@ using namespace std;
// Constructor // Constructor
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
CTapDriver::CTapDriver() CTapDriver::CTapDriver(const string& interfaces)
{ {
LOGTRACE("%s",__PRETTY_FUNCTION__); stringstream s(interfaces);
string interface;
while (getline(s, interface, ',')) {
this->interfaces.push_back(interface);
}
// Initialization // Initialization
m_bTxValid = FALSE; m_bTxValid = FALSE;
m_hTAP = -1; m_hTAP = -1;
@@ -88,7 +93,7 @@ static BOOL ip_link(int fd, const char* ifname, BOOL up) {
return TRUE; return TRUE;
} }
static bool is_interface_up(const char *interface) { static bool is_interface_up(const string& interface) {
string file = "/sys/class/net/"; string file = "/sys/class/net/";
file += interface; file += interface;
file += "/carrier"; file += "/carrier";
@@ -150,24 +155,31 @@ BOOL CTapDriver::Init()
return FALSE; return FALSE;
} }
// Check if the bridge is already created // Check if the bridge has already been created
if (access("/sys/class/net/rascsi_bridge", F_OK) != 0) { if (access("/sys/class/net/rascsi_bridge", F_OK) != 0) {
LOGINFO("rascsi_bridge is not yet available"); LOGINFO("rascsi_bridge is not yet available");
LOGINFO("Checking whether to create bridge for interface eth0 or wlan0"); LOGTRACE("Checking which interface is available for creating the bridge");
const char *interface = NULL; string interface;
if (is_interface_up("eth0")) { for (auto it = interfaces.begin(); it != interfaces.end(); ++it) {
interface = "eth0"; if (is_interface_up(*it)) {
LOGTRACE(string("Interface " + (*it) + " is up").c_str());
interface = *it;
break;
}
else {
LOGTRACE(string("Interface " + (*it) + " is not up").c_str());
}
} }
else if (is_interface_up("wlan0")) {
interface = "wlan0"; if (interface.empty()) {
} LOGERROR("No interface is up, not creating bridge");
if (!interface) {
LOGERROR("Neither interface eth0 nor wlan0 is up, not creating bridge");
return FALSE; return FALSE;
} }
LOGINFO("Creating rascsi_bridge for interface %s...", interface); LOGINFO("Creating rascsi_bridge for interface %s", interface.c_str());
LOGDEBUG("brctl addbr rascsi_bridge"); LOGDEBUG("brctl addbr rascsi_bridge");
if ((ret = ioctl(br_socket_fd, SIOCBRADDBR, "rascsi_bridge")) < 0) { if ((ret = ioctl(br_socket_fd, SIOCBRADDBR, "rascsi_bridge")) < 0) {
LOGERROR("Error: can't ioctl SIOCBRADDBR. Errno: %d %s", errno, strerror(errno)); LOGERROR("Error: can't ioctl SIOCBRADDBR. Errno: %d %s", errno, strerror(errno));
@@ -176,16 +188,17 @@ BOOL CTapDriver::Init()
close(br_socket_fd); close(br_socket_fd);
return FALSE; return FALSE;
} }
if (strcmp(interface, "wlan0")) {
LOGDEBUG("brctl addif rascsi_bridge %s", interface); if (interface == "eth0") {
if (!br_setif(br_socket_fd, "rascsi_bridge", interface, TRUE)) { LOGDEBUG("brctl addif rascsi_bridge %s", interface.c_str());
if (!br_setif(br_socket_fd, "rascsi_bridge", interface.c_str(), TRUE)) {
close(m_hTAP); close(m_hTAP);
close(ip_fd); close(ip_fd);
close(br_socket_fd); close(br_socket_fd);
return FALSE; return FALSE;
} }
} }
if (!strcmp(interface, "wlan0")) { else {
LOGDEBUG("ip address add 10.10.20.1/24 dev rascsi_bridge"); LOGDEBUG("ip address add 10.10.20.1/24 dev rascsi_bridge");
struct ifreq ifr_a; struct ifreq ifr_a;
ifr_a.ifr_addr.sa_family = AF_INET; ifr_a.ifr_addr.sa_family = AF_INET;

View File

@@ -18,6 +18,8 @@
#include <pcap/pcap.h> #include <pcap/pcap.h>
#include "filepath.h" #include "filepath.h"
#include <vector>
#include <string>
#ifndef ETH_FRAME_LEN #ifndef ETH_FRAME_LEN
#define ETH_FRAME_LEN 1514 #define ETH_FRAME_LEN 1514
@@ -32,8 +34,8 @@ class CTapDriver
{ {
public: public:
// Basic Functionality // Basic Functionality
CTapDriver(); // Constructor CTapDriver(const std::string&); // Constructor
BOOL Init(); // Initilization BOOL Init(); // Initialization
void OpenDump(const Filepath& path); void OpenDump(const Filepath& path);
// Capture packets // Capture packets
void Cleanup(); // Cleanup void Cleanup(); // Cleanup
@@ -55,6 +57,8 @@ private:
pcap_t *m_pcap; pcap_t *m_pcap;
pcap_dumper_t *m_pcap_dumper; pcap_dumper_t *m_pcap_dumper;
// Prioritized comma-separated list of interfaces to create the bridge for
std::vector<std::string> interfaces;
}; };
#endif // ctapdriver_h #endif // ctapdriver_h

View File

@@ -92,7 +92,7 @@ public:
virtual ~Device() {}; virtual ~Device() {};
// Override for device specific initializations, to be called after all device properties have been set // Override for device specific initializations, to be called after all device properties have been set
virtual void Init() {}; virtual void Init(const string&) {};
virtual bool Dispatch(SCSIDEV *) = 0; virtual bool Dispatch(SCSIDEV *) = 0;

View File

@@ -77,11 +77,11 @@ SCSIDaynaPort::~SCSIDaynaPort()
} }
} }
void SCSIDaynaPort::Init() void SCSIDaynaPort::Init(const string& interfaces)
{ {
#ifdef __linux__ #ifdef __linux__
// TAP Driver Generation // TAP Driver Generation
m_tap = new CTapDriver(); m_tap = new CTapDriver(!interfaces.empty() ? interfaces : "eth0,wlan0");
m_bTapEnable = m_tap->Init(); m_bTapEnable = m_tap->Init();
if(!m_bTapEnable){ if(!m_bTapEnable){
LOGERROR("Unable to open the TAP interface"); LOGERROR("Unable to open the TAP interface");
@@ -115,8 +115,6 @@ void SCSIDaynaPort::Init()
void SCSIDaynaPort::Open(const Filepath& path) void SCSIDaynaPort::Open(const Filepath& path)
{ {
LOGTRACE("SCSIDaynaPort Open");
m_tap->OpenDump(path); m_tap->OpenDump(path);
} }

View File

@@ -33,6 +33,7 @@
#include "disk.h" #include "disk.h"
#include "ctapdriver.h" #include "ctapdriver.h"
#include <map> #include <map>
#include <string>
//=========================================================================== //===========================================================================
// //
@@ -60,7 +61,7 @@ public:
SCSIDaynaPort(); SCSIDaynaPort();
~SCSIDaynaPort(); ~SCSIDaynaPort();
void Init() override; void Init(const string&) override;
void Open(const Filepath& path); void Open(const Filepath& path);
// Capture packets // Capture packets

View File

@@ -21,6 +21,8 @@
#include "ctapdriver.h" #include "ctapdriver.h"
#include "cfilesystem.h" #include "cfilesystem.h"
using namespace std;
//=========================================================================== //===========================================================================
// //
// SCSI Host Bridge // SCSI Host Bridge
@@ -76,11 +78,11 @@ SCSIBR::~SCSIBR()
} }
} }
void SCSIBR::Init() void SCSIBR::Init(const string&)
{ {
#ifdef __linux__ #ifdef __linux__
// TAP Driver Generation // TAP Driver Generation
tap = new CTapDriver(); tap = new CTapDriver("");
m_bTapEnable = tap->Init(); m_bTapEnable = tap->Init();
// Generate MAC Address // Generate MAC Address

View File

@@ -20,6 +20,7 @@
#include "xm6.h" #include "xm6.h"
#include "os.h" #include "os.h"
#include "disk.h" #include "disk.h"
#include <string>
//=========================================================================== //===========================================================================
// //
@@ -49,7 +50,7 @@ public:
SCSIBR(); SCSIBR();
~SCSIBR(); ~SCSIBR();
void Init() override; void Init(const string&) override;
bool Dispatch(SCSIDEV *) override; bool Dispatch(SCSIDEV *) override;

View File

@@ -592,14 +592,13 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm
const int id = pbDevice.id(); const int id = pbDevice.id();
const int unit = pbDevice.unit(); const int unit = pbDevice.unit();
const string filename = pbDevice.file();
PbDeviceType type = pbDevice.type(); PbDeviceType type = pbDevice.type();
bool all = params == "all"; bool all = params == "all";
ostringstream s; ostringstream s;
s << (dryRun ? "Validating: " : "Executing: "); s << (dryRun ? "Validating: " : "Executing: ");
s << "cmd=" << PbOperation_Name(cmd) << ", id=" << id << ", unit=" << unit << ", type=" << PbDeviceType_Name(type) s << "cmd=" << PbOperation_Name(cmd) << ", id=" << id << ", unit=" << unit << ", type=" << PbDeviceType_Name(type)
<< ", filename='" << filename << "', vendor='" << pbDevice.vendor() << ", params='" << pbDevice.params() << "', vendor='" << pbDevice.vendor()
<< ", product='" << pbDevice.product() << "', revision='" << pbDevice.revision() << "'" << ", product='" << pbDevice.product() << "', revision='" << pbDevice.revision() << "'"
<< "', block size=" << pbDevice.block_size() << ", params='" << params << "'"; << "', block size=" << pbDevice.block_size() << ", params='" << params << "'";
LOGINFO("%s", s.str().c_str()); LOGINFO("%s", s.str().c_str());
@@ -628,6 +627,7 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm
return ReturnStatus(fd, false, error); return ReturnStatus(fd, false, error);
} }
string filename = pbDevice.params();
string ext; string ext;
int len = filename.length(); int len = filename.length();
if (len > 4 && filename[len - 4] == '.') { if (len > 4 && filename[len - 4] == '.') {
@@ -736,7 +736,7 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm
} }
// Initialize everything that would have caused issues when being initialized during the dry run // Initialize everything that would have caused issues when being initialized during the dry run
device->Init(); device->Init(pbDevice.params());
// Replace with the newly created unit // Replace with the newly created unit
map[id * UnitNum + unit] = device; map[id * UnitNum + unit] = device;
@@ -819,39 +819,42 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm
} }
switch (cmd) { switch (cmd) {
case INSERT: case INSERT: {
if (!pbDevice.vendor().empty() || !pbDevice.product().empty() || !pbDevice.revision().empty()) { if (!pbDevice.vendor().empty() || !pbDevice.product().empty() || !pbDevice.revision().empty()) {
return ReturnStatus(fd, false, "Device name cannot be changed"); return ReturnStatus(fd, false, "Device name cannot be changed");
}
if (filename.empty()) {
return ReturnStatus(fd, false, "Missing filename");
}
if (dryRun) {
return true;
}
filepath.SetPath(filename.c_str());
LOGINFO("Insert file '%s' requested into %s ID: %d unit: %d", filename.c_str(), device->GetType().c_str(), id, unit);
try {
fileSupport->Open(filepath);
}
catch(const io_exception& e) {
if (!default_image_folder.empty()) {
// If the file does not exist search for it in the default image folder
string default_file = default_image_folder + "/" + filename;
filepath.SetPath(default_file.c_str());
try {
fileSupport->Open(filepath);
}
catch(const io_exception&) {
return ReturnStatus(fd, false, "Tried to open an invalid file '" + filename + "': " + e.getmsg());
}
} }
else {
return ReturnStatus(fd, false, "No default image folder"); string filename = pbDevice.params();
if (filename.empty()) {
return ReturnStatus(fd, false, "Missing filename");
}
if (dryRun) {
return true;
}
filepath.SetPath(filename.c_str());
LOGINFO("Insert file '%s' requested into %s ID: %d unit: %d", filename.c_str(), device->GetType().c_str(), id, unit);
try {
fileSupport->Open(filepath);
}
catch(const io_exception& e) {
if (!default_image_folder.empty()) {
// If the file does not exist search for it in the default image folder
string default_file = default_image_folder + "/" + filename;
filepath.SetPath(default_file.c_str());
try {
fileSupport->Open(filepath);
}
catch(const io_exception&) {
return ReturnStatus(fd, false, "Tried to open an invalid file '" + filename + "': " + e.getmsg());
}
}
else {
return ReturnStatus(fd, false, "No default image folder");
}
} }
} }
break; break;
@@ -1030,7 +1033,7 @@ bool ParseArgument(int argc, char* argv[], int& port)
device->set_unit(unit); device->set_unit(unit);
device->set_type(type); device->set_type(type);
device->set_block_size(block_size); device->set_block_size(block_size);
device->set_file(optarg); device->set_params(optarg);
size_t separatorPos = name.find(':'); size_t separatorPos = name.find(':');
if (separatorPos != string::npos) { if (separatorPos != string::npos) {

View File

@@ -61,10 +61,10 @@ message PbDeviceDefinition {
int32 id = 1; int32 id = 1;
int32 unit = 2; int32 unit = 2;
PbDeviceType type = 3; PbDeviceType type = 3;
// Optional device specific parameter, e.g. the name of an image file
string params = 4;
// The optional SCSI hard disk drive block size in bytes per sector, must be 512, 1024, 2048 or 4096 // The optional SCSI hard disk drive block size in bytes per sector, must be 512, 1024, 2048 or 4096
int32 block_size = 4; int32 block_size = 5;
// The optional name of the image file
string file = 5;
// The device name components // The device name components
string vendor = 6; string vendor = 6;
string product = 7; string product = 7;

View File

@@ -360,7 +360,7 @@ int main(int argc, char* argv[])
break; break;
case 'f': case 'f':
device->set_file(optarg); device->set_params(optarg);
break; break;
case 't': case 't':