diff --git a/src/raspberrypi/devices/ctapdriver.cpp b/src/raspberrypi/devices/ctapdriver.cpp index 0a437462..db95a801 100644 --- a/src/raspberrypi/devices/ctapdriver.cpp +++ b/src/raspberrypi/devices/ctapdriver.cpp @@ -26,7 +26,7 @@ #include "ctapdriver.h" #include "log.h" #include "exceptions.h" -#include +#include using namespace std; @@ -35,9 +35,14 @@ using namespace std; // 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 m_bTxValid = FALSE; m_hTAP = -1; @@ -88,7 +93,7 @@ static BOOL ip_link(int fd, const char* ifname, BOOL up) { return TRUE; } -static bool is_interface_up(const char *interface) { +static bool is_interface_up(const string& interface) { string file = "/sys/class/net/"; file += interface; file += "/carrier"; @@ -150,24 +155,31 @@ BOOL CTapDriver::Init() 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) { LOGINFO("rascsi_bridge is not yet available"); - LOGINFO("Checking whether to create bridge for interface eth0 or wlan0"); - const char *interface = NULL; - if (is_interface_up("eth0")) { - interface = "eth0"; + LOGTRACE("Checking which interface is available for creating the bridge"); + string interface; + for (auto it = interfaces.begin(); it != interfaces.end(); ++it) { + 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) { - LOGERROR("Neither interface eth0 nor wlan0 is up, not creating bridge"); + + if (interface.empty()) { + LOGERROR("No interface is up, not creating bridge"); 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"); if ((ret = ioctl(br_socket_fd, SIOCBRADDBR, "rascsi_bridge")) < 0) { LOGERROR("Error: can't ioctl SIOCBRADDBR. Errno: %d %s", errno, strerror(errno)); @@ -176,16 +188,17 @@ BOOL CTapDriver::Init() close(br_socket_fd); return FALSE; } - if (strcmp(interface, "wlan0")) { - LOGDEBUG("brctl addif rascsi_bridge %s", interface); - if (!br_setif(br_socket_fd, "rascsi_bridge", interface, TRUE)) { + + if (interface == "eth0") { + 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(ip_fd); close(br_socket_fd); return FALSE; } } - if (!strcmp(interface, "wlan0")) { + else { LOGDEBUG("ip address add 10.10.20.1/24 dev rascsi_bridge"); struct ifreq ifr_a; ifr_a.ifr_addr.sa_family = AF_INET; diff --git a/src/raspberrypi/devices/ctapdriver.h b/src/raspberrypi/devices/ctapdriver.h index 61cfeb9c..350f7bfd 100644 --- a/src/raspberrypi/devices/ctapdriver.h +++ b/src/raspberrypi/devices/ctapdriver.h @@ -18,6 +18,8 @@ #include #include "filepath.h" +#include +#include #ifndef ETH_FRAME_LEN #define ETH_FRAME_LEN 1514 @@ -32,8 +34,8 @@ class CTapDriver { public: // Basic Functionality - CTapDriver(); // Constructor - BOOL Init(); // Initilization + CTapDriver(const std::string&); // Constructor + BOOL Init(); // Initialization void OpenDump(const Filepath& path); // Capture packets void Cleanup(); // Cleanup @@ -55,6 +57,8 @@ private: pcap_t *m_pcap; pcap_dumper_t *m_pcap_dumper; + // Prioritized comma-separated list of interfaces to create the bridge for + std::vector interfaces; }; #endif // ctapdriver_h diff --git a/src/raspberrypi/devices/device.h b/src/raspberrypi/devices/device.h index a9ad7322..94da8e69 100644 --- a/src/raspberrypi/devices/device.h +++ b/src/raspberrypi/devices/device.h @@ -92,7 +92,7 @@ public: virtual ~Device() {}; // 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; diff --git a/src/raspberrypi/devices/scsi_daynaport.cpp b/src/raspberrypi/devices/scsi_daynaport.cpp index 6d108834..cbbe9e6a 100644 --- a/src/raspberrypi/devices/scsi_daynaport.cpp +++ b/src/raspberrypi/devices/scsi_daynaport.cpp @@ -77,11 +77,11 @@ SCSIDaynaPort::~SCSIDaynaPort() } } -void SCSIDaynaPort::Init() +void SCSIDaynaPort::Init(const string& interfaces) { #ifdef __linux__ // TAP Driver Generation - m_tap = new CTapDriver(); + m_tap = new CTapDriver(!interfaces.empty() ? interfaces : "eth0,wlan0"); m_bTapEnable = m_tap->Init(); if(!m_bTapEnable){ LOGERROR("Unable to open the TAP interface"); @@ -115,8 +115,6 @@ void SCSIDaynaPort::Init() void SCSIDaynaPort::Open(const Filepath& path) { - LOGTRACE("SCSIDaynaPort Open"); - m_tap->OpenDump(path); } diff --git a/src/raspberrypi/devices/scsi_daynaport.h b/src/raspberrypi/devices/scsi_daynaport.h index 127ce5f5..b77cdc7b 100644 --- a/src/raspberrypi/devices/scsi_daynaport.h +++ b/src/raspberrypi/devices/scsi_daynaport.h @@ -33,6 +33,7 @@ #include "disk.h" #include "ctapdriver.h" #include +#include //=========================================================================== // @@ -60,7 +61,7 @@ public: SCSIDaynaPort(); ~SCSIDaynaPort(); - void Init() override; + void Init(const string&) override; void Open(const Filepath& path); // Capture packets diff --git a/src/raspberrypi/devices/scsi_host_bridge.cpp b/src/raspberrypi/devices/scsi_host_bridge.cpp index 81d9d7a4..a60d52db 100644 --- a/src/raspberrypi/devices/scsi_host_bridge.cpp +++ b/src/raspberrypi/devices/scsi_host_bridge.cpp @@ -21,6 +21,8 @@ #include "ctapdriver.h" #include "cfilesystem.h" +using namespace std; + //=========================================================================== // // SCSI Host Bridge @@ -76,11 +78,11 @@ SCSIBR::~SCSIBR() } } -void SCSIBR::Init() +void SCSIBR::Init(const string&) { #ifdef __linux__ // TAP Driver Generation - tap = new CTapDriver(); + tap = new CTapDriver(""); m_bTapEnable = tap->Init(); // Generate MAC Address diff --git a/src/raspberrypi/devices/scsi_host_bridge.h b/src/raspberrypi/devices/scsi_host_bridge.h index 99922503..e3b0365d 100644 --- a/src/raspberrypi/devices/scsi_host_bridge.h +++ b/src/raspberrypi/devices/scsi_host_bridge.h @@ -20,6 +20,7 @@ #include "xm6.h" #include "os.h" #include "disk.h" +#include //=========================================================================== // @@ -49,7 +50,7 @@ public: SCSIBR(); ~SCSIBR(); - void Init() override; + void Init(const string&) override; bool Dispatch(SCSIDEV *) override; diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index f3264269..5864d24e 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -592,14 +592,13 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm const int id = pbDevice.id(); const int unit = pbDevice.unit(); - const string filename = pbDevice.file(); PbDeviceType type = pbDevice.type(); bool all = params == "all"; ostringstream s; s << (dryRun ? "Validating: " : "Executing: "); 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() << "'" << "', block size=" << pbDevice.block_size() << ", params='" << params << "'"; 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); } + string filename = pbDevice.params(); string ext; int len = filename.length(); 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 - device->Init(); + device->Init(pbDevice.params()); // Replace with the newly created unit map[id * UnitNum + unit] = device; @@ -819,39 +819,42 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm } switch (cmd) { - case INSERT: - if (!pbDevice.vendor().empty() || !pbDevice.product().empty() || !pbDevice.revision().empty()) { - 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()); - } + case INSERT: { + if (!pbDevice.vendor().empty() || !pbDevice.product().empty() || !pbDevice.revision().empty()) { + return ReturnStatus(fd, false, "Device name cannot be changed"); } - 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; @@ -1030,7 +1033,7 @@ bool ParseArgument(int argc, char* argv[], int& port) device->set_unit(unit); device->set_type(type); device->set_block_size(block_size); - device->set_file(optarg); + device->set_params(optarg); size_t separatorPos = name.find(':'); if (separatorPos != string::npos) { diff --git a/src/raspberrypi/rascsi_interface.proto b/src/raspberrypi/rascsi_interface.proto index c2440668..06425001 100644 --- a/src/raspberrypi/rascsi_interface.proto +++ b/src/raspberrypi/rascsi_interface.proto @@ -61,10 +61,10 @@ message PbDeviceDefinition { int32 id = 1; int32 unit = 2; 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 - int32 block_size = 4; - // The optional name of the image file - string file = 5; + int32 block_size = 5; // The device name components string vendor = 6; string product = 7; diff --git a/src/raspberrypi/rasctl.cpp b/src/raspberrypi/rasctl.cpp index cce02f00..993c052c 100644 --- a/src/raspberrypi/rasctl.cpp +++ b/src/raspberrypi/rasctl.cpp @@ -360,7 +360,7 @@ int main(int argc, char* argv[]) break; case 'f': - device->set_file(optarg); + device->set_params(optarg); break; case 't':