Merge pull request #93 from quentinmit/daynaport-pcap

Daynaport improvements
This commit is contained in:
akuker 2021-04-05 11:13:07 -05:00 committed by GitHub
commit 877a7a129c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 182 additions and 105 deletions

View File

@ -41,7 +41,7 @@ function initialChecks() {
}
function installPackages() {
sudo apt-get update && sudo apt install git libspdlog-dev genisoimage python3 python3-venv nginx bridge-utils -y
sudo apt-get update && sudo apt install git libspdlog-dev genisoimage python3 python3-venv nginx libpcap-dev -y
}
# install all dependency packages for RaSCSI Service

View File

@ -75,7 +75,6 @@ SRC_RASCSI = \
gpiobus.cpp \
filepath.cpp \
fileio.cpp\
os.cpp\
rascsi_version.cpp
# os.cpp
# rasctl_command.cpp
@ -152,7 +151,7 @@ ALL: all
docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt $(DOC_DIR)/scsimon_man_page.txt
$(BINDIR)/$(RASCSI): $(OBJ_RASCSI) | $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI) -lpthread -lz
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI) -lpthread -lz -lpcap
$(BINDIR)/$(RASCTL): $(OBJ_RASCTL) | $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCTL)

View File

@ -13,13 +13,18 @@
//
//---------------------------------------------------------------------------
#include <unistd.h>
#ifdef __linux__
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/sockios.h>
#endif
#include <zlib.h> // For crc32()
#include "os.h"
#include "xm6.h"
#include "ctapdriver.h"
#include "log.h"
const char rascsi_bridge_string[] = "rascsi_bridge";
//---------------------------------------------------------------------------
//
@ -32,6 +37,8 @@ CTapDriver::CTapDriver()
// Initialization
m_hTAP = -1;
memset(&m_MacAddr, 0, sizeof(m_MacAddr));
m_pcap = NULL;
m_pcap_dumper = NULL;
}
//---------------------------------------------------------------------------
@ -40,12 +47,48 @@ CTapDriver::CTapDriver()
//
//---------------------------------------------------------------------------
#ifdef __linux__
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;
}
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;
}
return TRUE;
}
static BOOL ip_link(int fd, const char* ifname, BOOL up) {
struct ifreq ifr;
int err;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
err = ioctl(fd, SIOCGIFFLAGS, &ifr);
if (err) {
LOGERROR("Error: can't ioctl SIOCGIFFLAGS. Errno: %d %s", errno, strerror(errno));
return FALSE;
}
ifr.ifr_flags &= ~IFF_UP;
if (up) {
ifr.ifr_flags |= IFF_UP;
}
err = ioctl(fd, SIOCSIFFLAGS, &ifr);
if (err) {
LOGERROR("Error: can't ioctl SIOCSIFFLAGS. Errno: %d %s", errno, strerror(errno));
return FALSE;
}
return TRUE;
}
BOOL FASTCALL CTapDriver::Init()
{
LOGTRACE("%s",__PRETTY_FUNCTION__);
char dev[IFNAMSIZ] = "ras0";
char cmd_output[256] = "";
struct ifreq ifr;
int ret;
@ -72,23 +115,48 @@ BOOL FASTCALL CTapDriver::Init()
}
LOGTRACE("return code from ioctl was %d", ret);
int ip_fd;
if ((ip_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
LOGERROR("Error: can't open ip socket. Errno: %d %s", errno, strerror(errno));
close(m_hTAP);
return FALSE;
}
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));
close(m_hTAP);
close(ip_fd);
return FALSE;
}
LOGTRACE("Going to see if the bridge is created");
ret = run_system_cmd_with_output("brctl show | grep rascsi_bridge", cmd_output, sizeof(cmd_output));
if(ret != EXIT_SUCCESS){
LOGTRACE("Unable to run brctl show command");
}
LOGTRACE("%s brctl show returned %s", __PRETTY_FUNCTION__, cmd_output);
// Check if the bridge is already created
if(strncmp(rascsi_bridge_string, cmd_output, strlen(rascsi_bridge_string)) != 0){
if (access("/sys/class/net/rascsi_bridge", F_OK) != 0) {
LOGINFO("Creating the rascsi_bridge...");
LOGDEBUG("brctl addbr rascsi_bridge");
ret = run_system_cmd("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));
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
return FALSE;
}
LOGDEBUG("brctl addif rascsi_bridge eth0");
ret = run_system_cmd("brctl addif rascsi_bridge eth0");
if (!br_setif(br_socket_fd, "rascsi_bridge", "eth0", TRUE)) {
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
return FALSE;
}
LOGDEBUG("ip link set dev rascsi_bridge up");
ret = run_system_cmd("ip link set dev rascsi_bridge up");
if (!ip_link(ip_fd, "rascsi_bridge", TRUE)) {
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
return FALSE;
}
}
else
{
@ -96,19 +164,29 @@ BOOL FASTCALL CTapDriver::Init()
}
LOGDEBUG("ip link set ras0 up");
ret = run_system_cmd("ip link set ras0 up");
LOGTRACE("return code from ip link set ras0 up was %d", ret);
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");
ret = run_system_cmd("brctl addif rascsi_bridge ras0");
LOGTRACE("return code from brctl addif rascsi_bridge ras0 was %d", ret);
if (!br_setif(br_socket_fd, "rascsi_bridge", "ras0", TRUE)) {
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
return FALSE;
}
// Get MAC address
LOGTRACE("Getting the MAC address");
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));
close(m_hTAP);
close(ip_fd);
close(br_socket_fd);
return FALSE;
}
LOGTRACE("got the mac");
@ -116,6 +194,10 @@ BOOL FASTCALL CTapDriver::Init()
// Save MAC address
memcpy(m_MacAddr, ifr.ifr_hwaddr.sa_data, sizeof(m_MacAddr));
LOGINFO("Tap device %s created", ifr.ifr_name);
close(ip_fd);
close(br_socket_fd);
return TRUE;
}
#endif // __linux__
@ -168,6 +250,22 @@ BOOL FASTCALL CTapDriver::Init()
}
#endif // __NetBSD__
BOOL FASTCALL CTapDriver::OpenDump(const Filepath& path) {
if (m_pcap == NULL) {
m_pcap = pcap_open_dead(DLT_EN10MB, 65535);
}
if (m_pcap_dumper != NULL) {
pcap_dump_close(m_pcap_dumper);
}
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));
return FALSE;
}
LOGTRACE("%s Opened %s for dumping", __PRETTY_FUNCTION__, path.GetPath())
return TRUE;
}
//---------------------------------------------------------------------------
//
// Cleanup
@ -176,13 +274,17 @@ BOOL FASTCALL CTapDriver::Init()
void FASTCALL CTapDriver::Cleanup()
{
ASSERT(this);
int result;
LOGDEBUG("brctl delif rascsi_bridge ras0");
result = run_system_cmd("brctl delif rascsi_bridge ras0");
if(result != EXIT_SUCCESS){
LOGWARN("Warning: The brctl delif command failed.");
LOGWARN("You may need to manually remove the ras0 tap device from the bridge");
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));
} else {
LOGDEBUG("brctl delif rascsi_bridge ras0");
if (!br_setif(br_socket_fd, "rascsi_bridge", "ras0", FALSE)) {
LOGWARN("Warning: Removing ras0 from the bridge failed.");
LOGWARN("You may need to manually remove the ras0 tap device from the bridge");
}
close(br_socket_fd);
}
// Release TAP defice
@ -190,6 +292,14 @@ void FASTCALL CTapDriver::Cleanup()
close(m_hTAP);
m_hTAP = -1;
}
if (m_pcap_dumper != NULL) {
pcap_dump_close(m_pcap_dumper);
m_pcap_dumper = NULL;
}
if (m_pcap != NULL) {
pcap_close(m_pcap);
}
}
//---------------------------------------------------------------------------
@ -198,10 +308,11 @@ void FASTCALL CTapDriver::Cleanup()
//
//---------------------------------------------------------------------------
BOOL FASTCALL CTapDriver::Enable(){
int result;
int fd = socket(PF_INET, SOCK_DGRAM, 0);
LOGDEBUG("%s: ip link set ras0 up", __PRETTY_FUNCTION__);
result = run_system_cmd("ip link set ras0 up");
return (result == EXIT_SUCCESS);
BOOL result = ip_link(fd, "ras0", TRUE);
close(fd);
return result;
}
//---------------------------------------------------------------------------
@ -210,10 +321,11 @@ BOOL FASTCALL CTapDriver::Enable(){
//
//---------------------------------------------------------------------------
BOOL FASTCALL CTapDriver::Disable(){
int result;
int fd = socket(PF_INET, SOCK_DGRAM, 0);
LOGDEBUG("%s: ip link set ras0 down", __PRETTY_FUNCTION__);
result = run_system_cmd("ip link set ras0 down");
return (result == EXIT_SUCCESS);
BOOL result = ip_link(fd, "ras0", FALSE);
close(fd);
return result;
}
//---------------------------------------------------------------------------
@ -314,6 +426,16 @@ int FASTCALL CTapDriver::Rx(BYTE *buf)
dwReceived += 4;
}
if (m_pcap_dumper != NULL) {
struct pcap_pkthdr h = {
.caplen = dwReceived,
.len = dwReceived,
};
gettimeofday(&h.ts, NULL);
pcap_dump((u_char*)m_pcap_dumper, &h, buf);
LOGTRACE("%s Dumped %d byte packet (first byte: %02x last byte: %02x)", __PRETTY_FUNCTION__, (unsigned int)dwReceived, buf[0], buf[dwReceived-1]);
}
// Return the number of bytes
return dwReceived;
}
@ -328,6 +450,16 @@ int FASTCALL CTapDriver::Tx(const BYTE *buf, int len)
ASSERT(this);
ASSERT(m_hTAP != -1);
if (m_pcap_dumper != NULL) {
struct pcap_pkthdr h = {
.caplen = (bpf_u_int32)len,
.len = (bpf_u_int32)len,
};
gettimeofday(&h.ts, NULL);
pcap_dump((u_char*)m_pcap_dumper, &h, buf);
LOGTRACE("%s Dumped %d byte packet (first byte: %02x last byte: %02x)", __PRETTY_FUNCTION__, (unsigned int)h.len, buf[0], buf[h.len-1]);
}
// Start sending
return write(m_hTAP, buf, len);
}

View File

@ -16,6 +16,9 @@
#if !defined(ctapdriver_h)
#define ctapdriver_h
#include <pcap/pcap.h>
#include "filepath.h"
#ifndef ETH_FRAME_LEN
#define ETH_FRAME_LEN 1514
#endif
@ -32,7 +35,9 @@ public:
CTapDriver();
// Constructor
BOOL FASTCALL Init();
// Initilization
// Initialization
BOOL FASTCALL OpenDump(const Filepath& path);
// Capture packets
void FASTCALL Cleanup();
// Cleanup
void FASTCALL GetMacAddr(BYTE *mac);
@ -58,6 +63,9 @@ private:
int m_hTAP;
// File handle
BYTE m_garbage_buffer[ETH_FRAME_LEN];
pcap_t *m_pcap;
pcap_dumper_t *m_pcap_dumper;
};
#endif // ctapdriver_h

View File

@ -106,6 +106,12 @@ SCSIDaynaPort::~SCSIDaynaPort()
}
}
BOOL FASTCALL SCSIDaynaPort::Open(const Filepath& path, BOOL attn)
{
LOGTRACE("SCSIDaynaPort Open");
return m_tap->OpenDump(path);
}
//---------------------------------------------------------------------------
//
// INQUIRY

View File

@ -46,6 +46,8 @@ public:
// Constructor
virtual ~SCSIDaynaPort();
// Destructor
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
// Capture packets
// commands
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buffer, DWORD major, DWORD minor);

View File

@ -1,63 +0,0 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Powered by XM6 TypeG Technology.
// Copyright (C) 2016-2020 GIMONS
// Copyright (C) 2020-2021 akuker
//
// [ OS related definitions ]
//
//---------------------------------------------------------------------------
#include "os.h"
#include "log.h"
#include <sys/wait.h>
//---------------------------------------------------------------------------
//
// Run system command and wait for it to finish
//
//---------------------------------------------------------------------------
int run_system_cmd(const char* command)
{
pid_t pid;
int result;
int status = 0;
pid=fork();
if(pid == 0){
result = system(command);
exit(result);
}
waitpid(pid, &status, 0);
return status;
}
//---------------------------------------------------------------------------
//
// Run system command and save the output to a string
//
//---------------------------------------------------------------------------
int run_system_cmd_with_output(const char* command, char* output_str, size_t max_size)
{
FILE *fp;
char str_buff[1024];
fp = popen(command,"r");
if(fp == NULL)
{
LOGWARN("%s Unable to run command %s", __PRETTY_FUNCTION__, command);
return EXIT_FAILURE;
}
while((fgets(str_buff, sizeof(str_buff), fp) != NULL) && (strlen(output_str) < max_size))
{
strncat(output_str, str_buff, max_size);
}
pclose(fp);
return EXIT_SUCCESS;
}

View File

@ -155,11 +155,4 @@ typedef const char *LPCSTR;
#define xstrcasecmp strcasecmp
#define xstrncasecmp strncasecmp
// Run system command and wait for it to finish
extern int run_system_cmd(const char* command);
// Run system command and wait for it to finish and keep the output
extern int run_system_cmd_with_output(const char* command, char* output_str, size_t max_size);
#endif // os_h

View File

@ -557,7 +557,7 @@ BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file)
}
// drive checks files
if (type <= rasctl_dev_scsi_hd || (type <= rasctl_dev_cd && xstrcasecmp(file, "-") != 0)) {
if (type <= rasctl_dev_scsi_hd || ((type <= rasctl_dev_cd || type == rasctl_dev_daynaport) && xstrcasecmp(file, "-") != 0)) {
// Set the Path
filepath.SetPath(file);