Added support for new interfaces syntax (#684)

* Added support for new interfaces syntax

* rasctl output update

* Added operation parameters

* Fixed typo

* Manpage update

* Added deprecation warning

* Moved parser

* Updated parser

* Updated parameter override

* Removed debug code

* Made netmask handling more flexible

* Updated logging

* Logging update

* Logging update

* Comment update

* Removed unused field

* Replaced BOOL by bool

* Moved code

* Logging update

* Removed useless comments

* Added TODZ

* Logging update

* Logging update

* Logging update

* No need to report that an error is an error twice

* Removed duplicate logging

* Updated error handling

* Updated error handling

* Fixed typo

* Removed magic constant

* Fixed 32 bit platform issue

* Signature update

* Fixed message string

* Comment update

* Fixed SCSI command opcode

* Updated StopPrint

* Logging update

* Removed obsolete casts

* Renaming

* Removed duplicate logging

* Updated flushing caches

* Added FlushCache() method

* Reduced visibility

* Reduced visibility

* Reduced visibility

* Code cleanup, removed useless comments

* Removed useless comments

* Updated error handling

* Removed duplicate code

* Manpage update
This commit is contained in:
Uwe Seimet 2022-02-20 18:40:30 +01:00 committed by GitHub
parent 2184992ce7
commit 2beb78727f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 212 additions and 308 deletions

View File

@ -84,7 +84,7 @@ Overrides the default locale for client-faces error messages. The client can ove
.BR \-ID\fIn[:u] " " \fIFILE
n is the SCSI ID number (0-7). u (0-31) is the optional LUN (logical unit). The default LUN is 0.
.IP
FILE is the name of the image file to use for the SCSI device. For devices that do not support an image file (SCBR, SCDP, SCLP, SCHS) the filename may have a special meaning or a dummy name can be provided. For SCBR and SCDP it is an optioinal prioritized list of network interfaces, e.g. "interfaces=eth0,eth1,wlan0". For SCLP it is the print command to be used and a reservation timeout in seconds, e.g. "cmd=lp -oraw:timeout=60".
FILE is the name of the image file to use for the SCSI device. For devices that do not support an image file (SCBR, SCDP, SCLP, SCHS) the filename may have a special meaning or a dummy name can be provided. For SCBR and SCDP it is an optioinal prioritized list of network interfaces, an optional IP address and netmask, e.g. "interfaces=eth0,eth1,wlan0:inet=10.10.20.1/24". For SCLP it is the print command to be used and a reservation timeout in seconds, e.g. "cmd=lp -oraw %f:timeout=60".
.TP
.BR \-HD\fIn[:u] " " \fIFILE
n is the SASI ID number (0-15). The effective SASI ID is calculated as n/2, the effective SASI LUN is calculated is the remainder of n/2. Alternatively the n:u syntax can be used, where ns is the SASI ID (0-7) and u the LUN (0-1).

View File

@ -111,10 +111,10 @@ OPTIONS
For devices that do not support an image file (SCBR, SCDP, SCLP,
SCHS) the filename may have a special meaning or a dummy name
can be provided. For SCBR and SCDP it is an optioinal priori
tized list of network interfaces, e.g. "inter
faces=eth0,eth1,wlan0". For SCLP it is the print command to be
used and a reservation timeout in seconds, e.g. "cmd=lp
-oraw:timeout=60".
tized list of network interfaces, an optional IP address and
netmask, e.g. "interfaces=eth0,eth1,wlan0:inet=10.10.20.1/24".
For SCLP it is the print command to be used and a reservation
timeout in seconds, e.g. "cmd=lp -oraw %f:timeout=60".
-HDn[:u] FILE
n is the SASI ID number (0-15). The effective SASI ID is calcu

View File

@ -70,7 +70,7 @@ public:
ERROR_CODES::asc asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION,
ERROR_CODES::status status = ERROR_CODES::status::CHECK_CONDITION) override;
void ShutDown(rascsi_shutdown_mode shutdown_mode) { this->shutdown_mode = shutdown_mode; }
void ScheduleShutDown(rascsi_shutdown_mode shutdown_mode) { this->shutdown_mode = shutdown_mode; }
int GetInitiatorId() const { return scsi.initiator_id; }
bool IsByteTransfer() const { return scsi.is_byte_transfer; }

View File

@ -20,25 +20,22 @@
#include <sys/ioctl.h>
#include <linux/sockios.h>
#endif
// TODO Try to get rid of zlib, there is only one operation using it
#include <zlib.h> // For crc32()
#include "os.h"
#include "ctapdriver.h"
#include "log.h"
#include "rasutil.h"
#include "exceptions.h"
#include <sstream>
#define BRIDGE_NAME "rascsi_bridge"
using namespace std;
using namespace ras_util;
CTapDriver::CTapDriver(const string& interfaces)
CTapDriver::CTapDriver()
{
stringstream s(interfaces);
string interface;
while (getline(s, interface, ',')) {
this->interfaces.push_back(interface);
}
// Initialization
m_bTxValid = FALSE;
m_hTAP = -1;
memset(&m_MacAddr, 0, sizeof(m_MacAddr));
m_pcap = NULL;
@ -52,28 +49,28 @@ CTapDriver::CTapDriver(const string& interfaces)
//---------------------------------------------------------------------------
#ifdef __linux__
static BOOL br_setif(int br_socket_fd, const char* bridgename, const char* ifname, BOOL add) {
static bool br_setif(int br_socket_fd, const char* bridgename, const char* ifname, bool add) {
struct ifreq ifr;
ifr.ifr_ifindex = if_nametoindex(ifname);
if (ifr.ifr_ifindex == 0) {
LOGERROR("Error: can't if_nametoindex. Errno: %d %s", errno, strerror(errno));
return FALSE;
LOGERROR("Can't if_nametoindex: %s", strerror(errno));
return false;
}
strncpy(ifr.ifr_name, bridgename, IFNAMSIZ);
if (ioctl(br_socket_fd, add ? SIOCBRADDIF : SIOCBRDELIF, &ifr) < 0) {
LOGERROR("Error: can't ioctl %s. Errno: %d %s", add ? "SIOCBRADDIF" : "SIOCBRDELIF", errno, strerror(errno));
return FALSE;
LOGERROR("Can't ioctl %s: %s", add ? "SIOCBRADDIF" : "SIOCBRDELIF", strerror(errno));
return false;
}
return TRUE;
return true;
}
static BOOL ip_link(int fd, const char* ifname, BOOL up) {
static bool ip_link(int fd, const char* ifname, bool up) {
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1); // Need to save room for null terminator
int err = ioctl(fd, SIOCGIFFLAGS, &ifr);
if (err) {
LOGERROR("Error: can't ioctl SIOCGIFFLAGS. Errno: %d %s", errno, strerror(errno));
return FALSE;
LOGERROR("Can't ioctl SIOCGIFFLAGS: %s", strerror(errno));
return false;
}
ifr.ifr_flags &= ~IFF_UP;
if (up) {
@ -81,10 +78,10 @@ static BOOL ip_link(int fd, const char* ifname, BOOL up) {
}
err = ioctl(fd, SIOCSIFFLAGS, &ifr);
if (err) {
LOGERROR("Error: can't ioctl SIOCSIFFLAGS. Errno: %d %s", errno, strerror(errno));
return FALSE;
LOGERROR("Can't ioctl SIOCSIFFLAGS: %s", strerror(errno));
return false;
}
return TRUE;
return true;
}
static bool is_interface_up(const string& interface) {
@ -105,12 +102,33 @@ static bool is_interface_up(const string& interface) {
return status;
}
bool CTapDriver::Init()
bool CTapDriver::Init(const map<string, string>& const_params)
{
map<string, string> params = const_params;
if (params.count("interfaces")) {
LOGWARN("You are using the deprecated 'interfaces' parameter. "
"Provide the interface list and the IP address/netmask with the 'interface' and 'inet' parameters");
// TODO Remove the deprecated syntax in a future version
const string& interfaces = params["interfaces"];
size_t separatorPos = interfaces.find(':');
if (separatorPos != string::npos) {
params["interface"] = interfaces.substr(0, separatorPos);
params["inet"] = interfaces.substr(separatorPos + 1);
}
}
stringstream s(params["interface"]);
string interface;
while (getline(s, interface, ',')) {
this->interfaces.push_back(interface);
}
this->inet = params["inet"];
LOGTRACE("Opening Tap device");
// TAP device initilization
if ((m_hTAP = open("/dev/net/tun", O_RDWR)) < 0) {
LOGERROR("Error: can't open tun. Errno: %d %s", errno, strerror(errno));
LOGERROR("Can't open tun: %s", strerror(errno));
return false;
}
@ -127,17 +145,17 @@ bool CTapDriver::Init()
int ret = ioctl(m_hTAP, TUNSETIFF, (void *)&ifr);
if (ret < 0) {
LOGERROR("Error: can't ioctl TUNSETIFF. Errno: %d %s", errno, strerror(errno));
LOGERROR("Can't ioctl TUNSETIFF: %s", strerror(errno));
close(m_hTAP);
return false;
}
LOGTRACE("return code from ioctl was %d", ret);
LOGTRACE("Return code from ioctl was %d", ret);
int ip_fd = socket(PF_INET, SOCK_DGRAM, 0);
if (ip_fd < 0) {
LOGERROR("Error: can't open ip socket. Errno: %d %s", errno, strerror(errno));
LOGERROR("Can't open ip socket: %s", strerror(errno));
close(m_hTAP);
return false;
@ -145,7 +163,7 @@ bool CTapDriver::Init()
int br_socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
if (br_socket_fd < 0) {
LOGERROR("Error: can't open bridge socket. Errno: %d %s", errno, strerror(errno));
LOGERROR("Can't open bridge socket: %s", strerror(errno));
close(m_hTAP);
close(ip_fd);
@ -153,36 +171,23 @@ bool CTapDriver::Init()
}
// Check if the bridge has already been created
if (access("/sys/class/net/rascsi_bridge", F_OK)) {
LOGINFO("rascsi_bridge is not yet available");
string sys_file = "/sys/class/net/";
sys_file += BRIDGE_NAME;
if (access(sys_file.c_str(), F_OK)) {
LOGINFO("%s is not yet available", BRIDGE_NAME);
LOGTRACE("Checking which interface is available for creating the bridge");
string bridge_interface;
string bridge_ip;
for (const string& iface : interfaces) {
string interface;
size_t separatorPos = iface.find(':');
if (separatorPos != string::npos) {
interface = iface.substr(0, separatorPos);
bridge_ip = iface.substr(separatorPos + 1);
}
else {
interface = iface;
bridge_ip = "10.10.20.1/24";
}
ostringstream msg;
for (const string& interface : interfaces) {
if (is_interface_up(interface)) {
msg << "Interface " << interface << " is up";
LOGTRACE("%s", msg.str().c_str());
LOGTRACE("%s", string("Interface " + interface + " is up").c_str());
bridge_interface = interface;
break;
}
else {
msg << "Interface " << interface << " is not available or is not up";
LOGTRACE("%s", msg.str().c_str());
LOGTRACE("%s", string("Interface " + interface + " is not available or is not up").c_str());
}
}
@ -191,13 +196,13 @@ bool CTapDriver::Init()
return false;
}
LOGINFO("Creating rascsi_bridge for interface %s", bridge_interface.c_str());
LOGINFO("Creating %s for interface %s", BRIDGE_NAME, bridge_interface.c_str());
if (bridge_interface == "eth0") {
LOGDEBUG("brctl addbr rascsi_bridge");
LOGTRACE("brctl addbr %s", BRIDGE_NAME);
if ((ret = ioctl(br_socket_fd, SIOCBRADDBR, "rascsi_bridge")) < 0) {
LOGERROR("Error: can't ioctl SIOCBRADDBR. Errno: %d %s", errno, strerror(errno));
if ((ret = ioctl(br_socket_fd, SIOCBRADDBR, BRIDGE_NAME)) < 0) {
LOGERROR("Can't ioctl SIOCBRADDBR: %s", strerror(errno));
close(m_hTAP);
close(ip_fd);
@ -205,9 +210,9 @@ bool CTapDriver::Init()
return false;
}
LOGDEBUG("brctl addif rascsi_bridge %s", bridge_interface.c_str());
LOGTRACE("brctl addif %s %s", BRIDGE_NAME, bridge_interface.c_str());
if (!br_setif(br_socket_fd, "rascsi_bridge", bridge_interface.c_str(), TRUE)) {
if (!br_setif(br_socket_fd, BRIDGE_NAME, bridge_interface.c_str(), true)) {
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
@ -215,38 +220,34 @@ bool CTapDriver::Init()
}
}
else {
LOGDEBUG("ip address add %s dev rascsi_bridge", bridge_ip.c_str());
string address = bridge_ip;
string address = inet;
string netmask = "255.255.255.0";
size_t separatorPos = bridge_ip.find('/');
size_t separatorPos = inet.find('/');
if (separatorPos != string::npos) {
address = bridge_ip.substr(0, separatorPos);
address = inet.substr(0, separatorPos);
string mask = bridge_ip.substr(separatorPos + 1);
if (mask == "8") {
netmask = "255.0.0.0";
}
else if (mask == "16") {
netmask = "255.255.0.0";
}
else if (mask == "24") {
netmask = "255.255.255.0";
}
else {
LOGERROR("Error: Invalid netmask in %s", bridge_ip.c_str());
int m;
if (!GetAsInt(inet.substr(separatorPos + 1), m) || m < 8 || m > 32) {
LOGERROR("Invalid CIDR netmask notation '%s'", inet.substr(separatorPos + 1).c_str());
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
return false;
}
// long long is required for compatibility with 32 bit platforms
long long mask = pow(2, 32) - (1 << (32 - m));
char buf[16];
sprintf(buf, "%lld.%lld.%lld.%lld", (mask >> 24) & 0xff, (mask >> 16) & 0xff, (mask >> 8) & 0xff,
mask & 0xff);
netmask = buf;
}
LOGDEBUG("brctl addbr rascsi_bridge");
LOGTRACE("brctl addbr %s", BRIDGE_NAME);
if ((ret = ioctl(br_socket_fd, SIOCBRADDBR, "rascsi_bridge")) < 0) {
LOGERROR("Error: can't ioctl SIOCBRADDBR. Errno: %d %s", errno, strerror(errno));
if ((ret = ioctl(br_socket_fd, SIOCBRADDBR, BRIDGE_NAME)) < 0) {
LOGERROR("Can't ioctl SIOCBRADDBR: %s", strerror(errno));
close(m_hTAP);
close(ip_fd);
@ -254,20 +255,36 @@ bool CTapDriver::Init()
return false;
}
LOGDEBUG("ip address add %s dev rascsi_bridge", bridge_ip.c_str());
struct ifreq ifr_a;
ifr_a.ifr_addr.sa_family = AF_INET;
strncpy(ifr_a.ifr_name, "rascsi_bridge", IFNAMSIZ);
strncpy(ifr_a.ifr_name, BRIDGE_NAME, IFNAMSIZ);
struct sockaddr_in* addr = (struct sockaddr_in*)&ifr_a.ifr_addr;
inet_pton(AF_INET, address.c_str(), &addr->sin_addr);
if (inet_pton(AF_INET, address.c_str(), &addr->sin_addr) != 1) {
LOGERROR("Can't convert '%s' into a network address: %s", address.c_str(), strerror(errno));
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
return false;
}
struct ifreq ifr_n;
ifr_n.ifr_addr.sa_family = AF_INET;
strncpy(ifr_n.ifr_name, "rascsi_bridge", IFNAMSIZ);
strncpy(ifr_n.ifr_name, BRIDGE_NAME, IFNAMSIZ);
struct sockaddr_in* mask = (struct sockaddr_in*)&ifr_n.ifr_addr;
inet_pton(AF_INET, netmask.c_str(), &mask->sin_addr);
if (inet_pton(AF_INET, netmask.c_str(), &mask->sin_addr) != 1) {
LOGERROR("Can't convert '%s' into a netmask: %s", netmask.c_str(), strerror(errno));
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
return false;
}
LOGTRACE("ip address add %s dev %s", inet.c_str(), BRIDGE_NAME);
if (ioctl(ip_fd, SIOCSIFADDR, &ifr_a) < 0 || ioctl(ip_fd, SIOCSIFNETMASK, &ifr_n) < 0) {
LOGERROR("Error: can't ioctl SIOCSIFADDR or SIOCSIFNETMASK. Errno: %d %s", errno, strerror(errno));
LOGERROR("Can't ioctl SIOCSIFADDR or SIOCSIFNETMASK: %s", strerror(errno));
close(m_hTAP);
close(ip_fd);
@ -276,9 +293,9 @@ bool CTapDriver::Init()
}
}
LOGDEBUG("ip link set dev rascsi_bridge up");
LOGTRACE("ip link set dev %s up", BRIDGE_NAME);
if (!ip_link(ip_fd, "rascsi_bridge", TRUE)) {
if (!ip_link(ip_fd, BRIDGE_NAME, true)) {
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
@ -287,21 +304,21 @@ bool CTapDriver::Init()
}
else
{
LOGINFO("rascsi_bridge is already available");
LOGINFO("%s is already available", BRIDGE_NAME);
}
LOGDEBUG("ip link set ras0 up");
LOGTRACE("ip link set ras0 up");
if (!ip_link(ip_fd, "ras0", TRUE)) {
if (!ip_link(ip_fd, "ras0", true)) {
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
return false;
}
LOGDEBUG("brctl addif rascsi_bridge ras0");
LOGTRACE("brctl addif %s ras0", BRIDGE_NAME);
if (!br_setif(br_socket_fd, "rascsi_bridge", "ras0", TRUE)) {
if (!br_setif(br_socket_fd, BRIDGE_NAME, "ras0", true)) {
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
@ -313,7 +330,7 @@ bool CTapDriver::Init()
ifr.ifr_addr.sa_family = AF_INET;
if ((ret = ioctl(m_hTAP, SIOCGIFHWADDR, &ifr)) < 0) {
LOGERROR("Error: can't ioctl SIOCGIFHWADDR. Errno: %d %s", errno, strerror(errno));
LOGERROR("Can't ioctl SIOCGIFHWADDR: %s", strerror(errno));
close(m_hTAP);
close(ip_fd);
@ -335,27 +352,27 @@ bool CTapDriver::Init()
#endif // __linux__
#ifdef __NetBSD__
BOOL CTapDriver::Init()
bool CTapDriver::Init(const map<string, string>&)
{
struct ifreq ifr;
struct ifaddrs *ifa, *a;
// TAP Device Initialization
if ((m_hTAP = open("/dev/tap", O_RDWR)) < 0) {
LOGERROR("Error: can't open tap. Errno: %d %s", errno, strerror(errno));
LOGERROR("Can't open tap: %s", strerror(errno));
return false;
}
// Get device name
if (ioctl(m_hTAP, TAPGIFNAME, (void *)&ifr) < 0) {
LOGERROR("Error: can't ioctl TAPGIFNAME. Errno: %d %s", errno, strerror(errno));
LOGERROR("Can't ioctl TAPGIFNAME: %s", strerror(errno));
close(m_hTAP);
return false;
}
// Get MAC address
if (getifaddrs(&ifa) == -1) {
LOGERROR("Error: can't getifaddrs. Errno: %d %s", errno, strerror(errno));
LOGERROR("Can't getifaddrs: %s", strerror(errno));
close(m_hTAP);
return false;
}
@ -364,7 +381,7 @@ BOOL CTapDriver::Init()
a->ifa_addr->sa_family == AF_LINK)
break;
if (a == NULL) {
LOGERROR("Error: can't get MAC addressErrno: %d %s", errno, strerror(errno));
LOGERROR("Can't get MAC address: %s", strerror(errno));
close(m_hTAP);
return false;
}
@ -374,7 +391,7 @@ BOOL CTapDriver::Init()
sizeof(m_MacAddr));
freeifaddrs(ifa);
LOGINFO("Tap device : %s\n", ifr.ifr_name);
LOGINFO("Tap device: %s\n", ifr.ifr_name);
return true;
}
@ -389,26 +406,21 @@ void CTapDriver::OpenDump(const Filepath& path) {
}
m_pcap_dumper = pcap_dump_open(m_pcap, path.GetPath());
if (m_pcap_dumper == NULL) {
LOGERROR("Error: can't open pcap file: %s", pcap_geterr(m_pcap));
LOGERROR("Can't open pcap file: %s", pcap_geterr(m_pcap));
throw io_exception("Can't open pcap file");
}
LOGTRACE("%s Opened %s for dumping", __PRETTY_FUNCTION__, path.GetPath());
}
//---------------------------------------------------------------------------
//
// Cleanup
//
//---------------------------------------------------------------------------
void CTapDriver::Cleanup()
{
int br_socket_fd = -1;
if ((br_socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
LOGERROR("Error: can't open bridge socket. Errno: %d %s", errno, strerror(errno));
LOGERROR("Can't open bridge socket: %s", strerror(errno));
} else {
LOGDEBUG("brctl delif rascsi_bridge ras0");
if (!br_setif(br_socket_fd, "rascsi_bridge", "ras0", FALSE)) {
LOGDEBUG("brctl delif %s ras0", BRIDGE_NAME);
if (!br_setif(br_socket_fd, BRIDGE_NAME, "ras0", false)) {
LOGWARN("Warning: Removing ras0 from the bridge failed.");
LOGWARN("You may need to manually remove the ras0 tap device from the bridge");
}
@ -432,50 +444,29 @@ void CTapDriver::Cleanup()
}
}
//---------------------------------------------------------------------------
//
// Enable
//
//---------------------------------------------------------------------------
bool CTapDriver::Enable(){
int fd = socket(PF_INET, SOCK_DGRAM, 0);
LOGDEBUG("%s: ip link set ras0 up", __PRETTY_FUNCTION__);
bool result = ip_link(fd, "ras0", TRUE);
bool result = ip_link(fd, "ras0", true);
close(fd);
return result;
}
//---------------------------------------------------------------------------
//
// Disable
//
//---------------------------------------------------------------------------
bool CTapDriver::Disable(){
int fd = socket(PF_INET, SOCK_DGRAM, 0);
LOGDEBUG("%s: ip link set ras0 down", __PRETTY_FUNCTION__);
bool result = ip_link(fd, "ras0", FALSE);
bool result = ip_link(fd, "ras0", false);
close(fd);
return result;
}
//---------------------------------------------------------------------------
//
// Flush
//
//---------------------------------------------------------------------------
BOOL CTapDriver::Flush(){
void CTapDriver::Flush(){
LOGTRACE("%s", __PRETTY_FUNCTION__);
while(PendingPackets()){
(void)Rx(m_garbage_buffer);
}
return TRUE;
}
//---------------------------------------------------------------------------
//
// MGet MAC Address
//
//---------------------------------------------------------------------------
void CTapDriver::GetMacAddr(BYTE *mac)
{
ASSERT(mac);
@ -488,7 +479,7 @@ void CTapDriver::GetMacAddr(BYTE *mac)
// Receive
//
//---------------------------------------------------------------------------
BOOL CTapDriver::PendingPackets()
bool CTapDriver::PendingPackets()
{
struct pollfd fds;
@ -501,9 +492,9 @@ BOOL CTapDriver::PendingPackets()
poll(&fds, 1, 0);
LOGTRACE("%s %u revents", __PRETTY_FUNCTION__, fds.revents);
if (!(fds.revents & POLLIN)) {
return FALSE;
return false;
}else {
return TRUE;
return true;
}
}

View File

@ -17,6 +17,7 @@
#include <pcap/pcap.h>
#include "filepath.h"
#include <map>
#include <vector>
#include <string>
@ -24,6 +25,8 @@
#define ETH_FRAME_LEN 1514
#endif
using namespace std;
//===========================================================================
//
// Linux Tap Driver
@ -31,25 +34,31 @@
//===========================================================================
class CTapDriver
{
public:
CTapDriver(const std::string&);
~CTapDriver() {};
private:
friend class SCSIDaynaPort;
friend class SCSIBR;
CTapDriver();
~CTapDriver() {}
bool Init(const map<string, string>&);
public:
bool Init();
void OpenDump(const Filepath& path);
// Capture packets
void Cleanup(); // Cleanup
void GetMacAddr(BYTE *mac); // Get Mac Address
int Rx(BYTE *buf); // Receive
int Tx(const BYTE *buf, int len); // Send
BOOL PendingPackets(); // Check if there are IP packets available
bool PendingPackets(); // Check if there are IP packets available
bool Enable(); // Enable the ras0 interface
bool Disable(); // Disable the ras0 interface
BOOL Flush(); // Purge all of the packets that are waiting to be processed
void Flush(); // Purge all of the packets that are waiting to be processed
private:
BYTE m_MacAddr[6]; // MAC Address
BOOL m_bTxValid; // Send Valid Flag
int m_hTAP; // File handle
BYTE m_garbage_buffer[ETH_FRAME_LEN];
@ -58,6 +67,8 @@ private:
pcap_dumper_t *m_pcap_dumper;
// Prioritized comma-separated list of interfaces to create the bridge for
std::vector<std::string> interfaces;
vector<string> interfaces;
string inet;
};

View File

@ -121,6 +121,15 @@ const string Device::GetParam(const string& key)
return params.find(key) != params.end() ? params[key] : "";
}
void Device::SetParams(const map<string, string>& params)
{
this->params = GetDefaultParams();
for (const auto& param : params) {
this->params[param.first] = param.second;
}
}
void Device::SetStatusCode(int status_code)
{
if (status_code) {

View File

@ -171,7 +171,7 @@ public:
void SupportsParams(bool supports_paams) { this->supports_params = supports_paams; }
const map<string, string> GetParams() const { return params; }
const string GetParam(const string&);
void SetParams(const map<string, string>& params) { this->params = params; }
void SetParams(const map<string, string>&);
const map<string, string> GetDefaultParams() const { return default_params; }
void SetDefaultParams(const map<string, string>& default_params) { this->default_params = default_params; }

View File

@ -51,8 +51,10 @@ DeviceFactory::DeviceFactory()
network_interfaces += network_interface;
}
default_params[SCBR]["interfaces"] = network_interfaces;
default_params[SCDP]["interfaces"] = network_interfaces;
default_params[SCBR]["interface"] = network_interfaces;
default_params[SCBR]["inet"] = "10.10.20.1/24";
default_params[SCDP]["interface"] = network_interfaces;
default_params[SCDP]["inet"] = "10.10.20.1/24";
default_params[SCLP]["cmd"] = "lp -oraw %f";
default_params[SCLP]["timeout"] = "30";

View File

@ -67,9 +67,7 @@ Disk::~Disk()
// Save disk cache
if (IsReady()) {
// Only if ready...
if (disk.dcache) {
disk.dcache->Save();
}
FlushCache();
}
// Clear disk cache
@ -118,6 +116,13 @@ void Disk::Open(const Filepath& path)
SetLocked(false);
}
void Disk::FlushCache()
{
if (disk.dcache) {
disk.dcache->Save();
}
}
void Disk::Rezero(SASIDEV *controller)
{
if (!CheckReady()) {
@ -369,8 +374,7 @@ void Disk::PreventAllowMediumRemoval(SASIDEV *controller)
void Disk::SynchronizeCache10(SASIDEV *controller)
{
// Flush the RaSCSI cache
disk.dcache->Save();
FlushCache();
controller->Status();
}
@ -395,8 +399,7 @@ bool Disk::Eject(bool force)
{
bool status = Device::Eject(force);
if (status) {
// Remove disk cache
disk.dcache->Save();
FlushCache();
delete disk.dcache;
disk.dcache = NULL;
@ -1030,8 +1033,7 @@ bool Disk::StartStop(const DWORD *cdb)
}
if (!start) {
// Flush the cache when stopping
disk.dcache->Save();
FlushCache();
// Look at the eject bit and eject if necessary
if (load) {

View File

@ -132,6 +132,7 @@ public:
void SetBlockCount(uint32_t);
bool CheckBlockAddress(SASIDEV *, access_mode);
bool GetStartAndCount(SASIDEV *, uint64_t&, uint32_t&, access_mode);
void FlushCache();
protected:
int ModeSense6(const DWORD *cdb, BYTE *buf);

View File

@ -43,6 +43,9 @@ public:
DiskTrack();
~DiskTrack();
private:
friend class DiskCache;
void Init(int track, int size, int sectors, BOOL raw = FALSE, off_t imgoff = 0);
bool Load(const Filepath& path);
bool Save(const Filepath& path);

View File

@ -33,6 +33,7 @@
//
#include "controllers/scsidev_ctrl.h"
#include "disk.h"
#include "host_services.h"
using namespace scsi_defs;
@ -67,18 +68,19 @@ void HostServices::StartStopUnit(SCSIDEV *controller)
bool load = ctrl->cmd[4] & 0x02;
if (!start) {
// Delete all other devices. This will also flush any caches.
for (const Device *device : devices) {
if (device != this) {
delete device;
// Flush any caches
for (Device *device : devices) {
Disk *disk = dynamic_cast<Disk *>(device);
if (disk) {
disk->FlushCache();
}
}
if (load) {
((SCSIDEV *)controller)->ShutDown(SCSIDEV::rascsi_shutdown_mode::PI);
controller->ScheduleShutDown(SCSIDEV::rascsi_shutdown_mode::PI);
}
else {
((SCSIDEV *)controller)->ShutDown(SCSIDEV::rascsi_shutdown_mode::RASCSI);
controller->ScheduleShutDown(SCSIDEV::rascsi_shutdown_mode::RASCSI);
}
controller->Status();

View File

@ -66,12 +66,12 @@ bool SCSIDaynaPort::Dispatch(SCSIDEV *controller)
bool SCSIDaynaPort::Init(const map<string, string>& params)
{
SetParams(params.empty() ? GetDefaultParams() : params);
SetParams(params);
#ifdef __linux__
// TAP Driver Generation
m_tap = new CTapDriver(GetParam("interfaces"));
m_bTapEnable = m_tap->Init();
m_tap = new CTapDriver();
m_bTapEnable = m_tap->Init(GetParams());
if(!m_bTapEnable){
LOGERROR("Unable to open the TAP interface");

View File

@ -61,13 +61,12 @@ SCSIBR::~SCSIBR()
bool SCSIBR::Init(const map<string, string>& params)
{
// Use default parameters if no parameters were provided
SetParams(params.empty() ? GetDefaultParams() : params);
SetParams(params);
#ifdef __linux__
// TAP Driver Generation
tap = new CTapDriver(GetParam("interfaces"));
m_bTapEnable = tap->Init();
tap = new CTapDriver();
m_bTapEnable = tap->Init(GetParams());
if (!m_bTapEnable){
LOGERROR("Unable to open the TAP interface");
return false;

View File

@ -29,6 +29,7 @@
// requires that the client uses a printer driver compatible with the respective printer, or that the
// printing service on the Pi is configured to do any necessary conversions, or that the print command
// applies any conversions on the file to be printed (%f) before passing it to the printing service.
// 'enscript' is an example for a conversion tool.
// By attaching different devices/LUNs multiple printers (i.e. different print commands) are possible.
// Note that the print command is not executed by root but with the permissions of the lp user.
//
@ -60,7 +61,7 @@ SCSIPrinter::SCSIPrinter() : PrimaryDevice("SCLP"), ScsiPrinterCommands()
dispatcher.AddCommand(eCmdReserve6, "ReserveUnit", &SCSIPrinter::ReserveUnit);
dispatcher.AddCommand(eCmdRelease6, "ReleaseUnit", &SCSIPrinter::ReleaseUnit);
dispatcher.AddCommand(eCmdWrite6, "Print", &SCSIPrinter::Print);
dispatcher.AddCommand(eCmdReadCapacity10, "SynchronizeBuffer", &SCSIPrinter::SynchronizeBuffer);
dispatcher.AddCommand(eCmdSynchronizeBuffer, "SynchronizeBuffer", &SCSIPrinter::SynchronizeBuffer);
dispatcher.AddCommand(eCmdSendDiag, "SendDiagnostic", &SCSIPrinter::SendDiagnostic);
dispatcher.AddCommand(eCmdStartStop, "StopPrint", &SCSIPrinter::StopPrint);
}
@ -72,8 +73,7 @@ SCSIPrinter::~SCSIPrinter()
bool SCSIPrinter::Init(const map<string, string>& params)
{
// Use default parameters if no parameters were provided
SetParams(params.empty() ? GetDefaultParams() : params);
SetParams(params);
if (GetParam("cmd").find("%f") == string::npos) {
LOGERROR("Missing filename specifier %s", "%f");
@ -169,6 +169,8 @@ void SCSIPrinter::Print(SCSIDEV *controller)
// TODO This device suffers from the statically allocated buffer size,
// see https://github.com/akuker/RASCSI/issues/669
if (length > (uint32_t)controller->DEFAULT_BUFFER_SIZE) {
LOGERROR("Transfer buffer overflow");
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
return;
}
@ -236,7 +238,7 @@ void SCSIPrinter::StopPrint(SCSIDEV *controller)
return;
}
Cleanup();
// Nothing to do, printing has not yet been started
controller->Status();
}

View File

@ -22,15 +22,10 @@ using namespace scsi_defs;
//===========================================================================
//
// CD Track
// CD Track
//
//===========================================================================
//---------------------------------------------------------------------------
//
// Constructor
//
//---------------------------------------------------------------------------
CDTrack::CDTrack(SCSICD *scsicd)
{
ASSERT(scsicd);
@ -49,20 +44,6 @@ CDTrack::CDTrack(SCSICD *scsicd)
raw = false;
}
//---------------------------------------------------------------------------
//
// Destructor
//
//---------------------------------------------------------------------------
CDTrack::~CDTrack()
{
}
//---------------------------------------------------------------------------
//
// Init
//
//---------------------------------------------------------------------------
void CDTrack::Init(int track, DWORD first, DWORD last)
{
ASSERT(!valid);
@ -78,11 +59,6 @@ void CDTrack::Init(int track, DWORD first, DWORD last)
last_lba = last;
}
//---------------------------------------------------------------------------
//
// Set Path
//
//---------------------------------------------------------------------------
void CDTrack::SetPath(bool cdda, const Filepath& path)
{
ASSERT(valid);
@ -94,11 +70,6 @@ void CDTrack::SetPath(bool cdda, const Filepath& path)
imgpath = path;
}
//---------------------------------------------------------------------------
//
// Get Path
//
//---------------------------------------------------------------------------
void CDTrack::GetPath(Filepath& path) const
{
ASSERT(valid);
@ -107,11 +78,6 @@ void CDTrack::GetPath(Filepath& path) const
path = imgpath;
}
//---------------------------------------------------------------------------
//
// Add Index
//
//---------------------------------------------------------------------------
void CDTrack::AddIndex(int index, DWORD lba)
{
ASSERT(valid);
@ -149,11 +115,6 @@ DWORD CDTrack::GetLast() const
return last_lba;
}
//---------------------------------------------------------------------------
//
// Get the number of blocks
//
//---------------------------------------------------------------------------
DWORD CDTrack::GetBlocks() const
{
ASSERT(valid);
@ -163,11 +124,6 @@ DWORD CDTrack::GetBlocks() const
return (DWORD)(last_lba - first_lba + 1);
}
//---------------------------------------------------------------------------
//
// Get track number
//
//---------------------------------------------------------------------------
int CDTrack::GetTrackNo() const
{
ASSERT(valid);
@ -220,11 +176,6 @@ bool CDTrack::IsAudio() const
//
//===========================================================================
//---------------------------------------------------------------------------
//
// Constructor
//
//---------------------------------------------------------------------------
SCSICD::SCSICD() : Disk("SCCD"), ScsiMmcCommands(), FileSupport()
{
// NOT in raw format
@ -245,11 +196,6 @@ SCSICD::SCSICD() : Disk("SCCD"), ScsiMmcCommands(), FileSupport()
dispatcher.AddCommand(eCmdGetEventStatusNotification, "GetEventStatusNotification", &SCSICD::GetEventStatusNotification);
}
//---------------------------------------------------------------------------
//
// Destructor
//
//---------------------------------------------------------------------------
SCSICD::~SCSICD()
{
// Clear track
@ -262,11 +208,6 @@ bool SCSICD::Dispatch(SCSIDEV *controller)
return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller);
}
//---------------------------------------------------------------------------
//
// Open
//
//---------------------------------------------------------------------------
void SCSICD::Open(const Filepath& path)
{
off_t size;
@ -334,21 +275,11 @@ void SCSICD::Open(const Filepath& path)
}
}
//---------------------------------------------------------------------------
//
// Open (CUE)
//
//---------------------------------------------------------------------------
void SCSICD::OpenCue(const Filepath& /*path*/)
{
throw io_exception("Opening CUE CD-ROM files is not supported");
}
//---------------------------------------------------------------------------
//
// Open (ISO)
//
//---------------------------------------------------------------------------
void SCSICD::OpenIso(const Filepath& path)
{
// Open as read-only
@ -419,11 +350,6 @@ void SCSICD::OpenIso(const Filepath& path)
dataindex = 0;
}
//---------------------------------------------------------------------------
//
// Open (Physical)
//
//---------------------------------------------------------------------------
void SCSICD::OpenPhysical(const Filepath& path)
{
// Open as read-only
@ -469,11 +395,6 @@ void SCSICD::ReadToc(SASIDEV *controller)
controller->DataIn();
}
//---------------------------------------------------------------------------
//
// INQUIRY
//
//---------------------------------------------------------------------------
int SCSICD::Inquiry(const DWORD *cdb, BYTE *buf)
{
// EVPD check
@ -535,11 +456,6 @@ int SCSICD::Inquiry(const DWORD *cdb, BYTE *buf)
return size;
}
//---------------------------------------------------------------------------
//
// READ
//
//---------------------------------------------------------------------------
int SCSICD::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
{
ASSERT(buf);
@ -584,11 +500,6 @@ int SCSICD::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
return Disk::Read(cdb, buf, block);
}
//---------------------------------------------------------------------------
//
// READ TOC
//
//---------------------------------------------------------------------------
int SCSICD::ReadToc(const DWORD *cdb, BYTE *buf)
{
ASSERT(cdb);
@ -741,11 +652,6 @@ void SCSICD::LBAtoMSF(DWORD lba, BYTE *msf) const
msf[3] = (BYTE)f;
}
//---------------------------------------------------------------------------
//
// Clear Track
//
//---------------------------------------------------------------------------
void SCSICD::ClearTrack()
{
// delete the track object

View File

@ -10,7 +10,7 @@
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI CD-ROM for Apple Macintosh ]
// [ SCSI CD-ROM ]
//
//---------------------------------------------------------------------------
#pragma once
@ -21,12 +21,6 @@
#include "interfaces/scsi_mmc_commands.h"
#include "interfaces/scsi_primary_commands.h"
//---------------------------------------------------------------------------
//
// Class precedence definition
//
//---------------------------------------------------------------------------
class SCSICD;
//===========================================================================
@ -36,9 +30,14 @@ class SCSICD;
//===========================================================================
class CDTrack
{
public:
private:
friend class SCSICD;
CDTrack(SCSICD *scsicd);
virtual ~CDTrack();
virtual ~CDTrack() {}
public:
void Init(int track, DWORD first, DWORD last);

View File

@ -26,11 +26,6 @@
//
//===========================================================================
//---------------------------------------------------------------------------
//
// Constructor
//
//---------------------------------------------------------------------------
SCSIHD::SCSIHD(bool removable) : Disk(removable ? "SCRM" : "SCHD")
{
}
@ -67,11 +62,6 @@ void SCSIHD::FinalizeSetup(const Filepath &path, off_t size)
FileSupport::SetPath(path);
}
//---------------------------------------------------------------------------
//
// Reset
//
//---------------------------------------------------------------------------
void SCSIHD::Reset()
{
// Unlock and release attention
@ -83,11 +73,6 @@ void SCSIHD::Reset()
SetStatusCode(STATUS_NOERROR);
}
//---------------------------------------------------------------------------
//
// Open
//
//---------------------------------------------------------------------------
void SCSIHD::Open(const Filepath& path)
{
ASSERT(!IsReady());
@ -112,11 +97,6 @@ void SCSIHD::Open(const Filepath& path)
FinalizeSetup(path, size);
}
//---------------------------------------------------------------------------
//
// INQUIRY
//
//---------------------------------------------------------------------------
int SCSIHD::Inquiry(const DWORD *cdb, BYTE *buf)
{
// EVPD check
@ -157,11 +137,6 @@ int SCSIHD::Inquiry(const DWORD *cdb, BYTE *buf)
return size;
}
//---------------------------------------------------------------------------
//
// MODE SELECT
//
//---------------------------------------------------------------------------
bool SCSIHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
{
int size;

View File

@ -41,7 +41,8 @@ enum PbOperation {
// Attach devices and return the new device list (PbDevicesInfo)
// Parameters (depending on the device type):
// "file": The filename relative to the default image folder
// "interfaces": A prioritized comma-separated list of interfaces to create a network bridge for
// "interface": A prioritized comma-separated list of interfaces to create a network bridge for
// "inet": The IP address and netmask for the network bridge
// "cmd": The command to be used for printing, with "%f" as file placeholder
// "timeout": The timeout for printer reservations in seconds
ATTACH = 1;

View File

@ -369,8 +369,9 @@ PbOperationInfo *RascsiResponse::GetOperationInfo(PbResult& result, int depth)
PbOperationMetaData *meta_data = new PbOperationMetaData();
AddOperationParameter(meta_data, "name", "Image file name in case of a mass storage device");
AddOperationParameter(meta_data, "interfaces", "Comma-separated prioritized network interface list");
AddOperationParameter(meta_data, "cmd", "print command for the printer device");
AddOperationParameter(meta_data, "interface", "Comma-separated prioritized network interface list");
AddOperationParameter(meta_data, "inet", "IP address and netmask of the network bridge");
AddOperationParameter(meta_data, "cmd", "Print command for the printer device");
AddOperationParameter(meta_data, "timeout", "Reservation timeout for the printer device in seconds");
CreateOperation(operation_info, meta_data, ATTACH, "Attach device, device-specific parameters are required");

View File

@ -173,13 +173,12 @@ void RasctlDisplay::DisplayDeviceTypesInfo(const PbDeviceTypesInfo& device_types
bool isFirst = true;
for (const auto& param : params) {
if (!isFirst) {
cout << ":";
cout << " ";
}
cout << param.first << "=" << param.second;
cout << param.first << "=" << param.second << endl;
isFirst = false;
}
cout << endl;
}
if (properties.block_sizes_size()) {

View File

@ -184,6 +184,7 @@ namespace scsi_defs {
eCmdSetMcastAddr = 0x0D,
// DaynaPort specific command
eCmdEnableInterface = 0x0E,
eCmdSynchronizeBuffer = 0x10,
eCmdInquiry = 0x12,
eCmdModeSelect6 = 0x15,
eCmdReserve6 = 0x16,