RASCSI/src/raspberrypi/ctapdriver.cpp

209 lines
4.6 KiB
C++

//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Powered by XM6 TypeG Technology.
// Copyright (C) 2016-2020 GIMONS
//
// Imported NetBSD support and some optimisation patch by Rin Okuyama.
//
// [ TAPドライバ ]
//
//---------------------------------------------------------------------------
#include "os.h"
#include "xm6.h"
#include "ctapdriver.h"
//---------------------------------------------------------------------------
//
// コンストラクタ
//
//---------------------------------------------------------------------------
CTapDriver::CTapDriver()
{
// 初期化
m_hTAP = -1;
memset(&m_MacAddr, 0, sizeof(m_MacAddr));
}
//---------------------------------------------------------------------------
//
// 初期化
//
//---------------------------------------------------------------------------
#ifdef __linux__
BOOL FASTCALL CTapDriver::Init()
{
char dev[IFNAMSIZ] = "ras0";
struct ifreq ifr;
int ret;
ASSERT(this);
// TAPデバイス初期化
if ((m_hTAP = open("/dev/net/tun", O_RDWR)) < 0) {
printf("Error: can't open tun\n");
return FALSE;
}
// IFF_NO_PI for no extra packet information
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
if ((ret = ioctl(m_hTAP, TUNSETIFF, (void *)&ifr)) < 0) {
printf("Error: can't ioctl TUNSETIFF\n");
close(m_hTAP);
return FALSE;
}
// MACアドレス取得
ifr.ifr_addr.sa_family = AF_INET;
if ((ret = ioctl(m_hTAP, SIOCGIFHWADDR, &ifr)) < 0) {
printf("Error: can't ioctl SIOCGIFHWADDR\n");
close(m_hTAP);
return FALSE;
}
// MACアドレス保存
memcpy(m_MacAddr, ifr.ifr_hwaddr.sa_data, sizeof(m_MacAddr));
return TRUE;
}
#endif // __linux__
#ifdef __NetBSD__
BOOL FASTCALL CTapDriver::Init()
{
struct ifreq ifr;
struct ifaddrs *ifa, *a;
ASSERT(this);
// TAPデバイス初期化
if ((m_hTAP = open("/dev/tap", O_RDWR)) < 0) {
printf("Error: can't open tap\n");
return FALSE;
}
// デバイス名取得
if (ioctl(m_hTAP, TAPGIFNAME, (void *)&ifr) < 0) {
printf("Error: can't ioctl TAPGIFNAME\n");
close(m_hTAP);
return FALSE;
}
// MACアドレス取得
if (getifaddrs(&ifa) == -1) {
printf("Error: can't getifaddrs\n");
close(m_hTAP);
return FALSE;
}
for (a = ifa; a != NULL; a = a->ifa_next)
if (strcmp(ifr.ifr_name, a->ifa_name) == 0 &&
a->ifa_addr->sa_family == AF_LINK)
break;
if (a == NULL) {
printf("Error: can't get MAC address\n");
close(m_hTAP);
return FALSE;
}
// MACアドレス保存
memcpy(m_MacAddr, LLADDR((struct sockaddr_dl *)a->ifa_addr),
sizeof(m_MacAddr));
freeifaddrs(ifa);
printf("Tap device : %s\n", ifr.ifr_name);
return TRUE;
}
#endif // __NetBSD__
//---------------------------------------------------------------------------
//
// クリーンアップ
//
//---------------------------------------------------------------------------
void FASTCALL CTapDriver::Cleanup()
{
ASSERT(this);
// TAPデバイス解放
if (m_hTAP != -1) {
close(m_hTAP);
m_hTAP = -1;
}
}
//---------------------------------------------------------------------------
//
// MACアドレス取得
//
//---------------------------------------------------------------------------
void FASTCALL CTapDriver::GetMacAddr(BYTE *mac)
{
ASSERT(this);
ASSERT(mac);
memcpy(mac, m_MacAddr, sizeof(m_MacAddr));
}
//---------------------------------------------------------------------------
//
// 受信
//
//---------------------------------------------------------------------------
int FASTCALL CTapDriver::Rx(BYTE *buf)
{
struct pollfd fds;
DWORD dwReceived;
ASSERT(this);
ASSERT(m_hTAP != -1);
// 受信可能なデータがあるか調べる
fds.fd = m_hTAP;
fds.events = POLLIN | POLLERR;
fds.revents = 0;
poll(&fds, 1, 0);
if (!(fds.revents & POLLIN)) {
return 0;
}
// 受信
dwReceived = read(m_hTAP, buf, ETH_FRAME_LEN);
if (dwReceived == (DWORD)-1) {
return 0;
}
// 受信が有効であれば
if (dwReceived > 0) {
// FCSを除く最小フレームサイズ(60バイト)にパディング
if (dwReceived < 60) {
memset(buf + dwReceived, 0, 60 - dwReceived);
dwReceived = 60;
}
// ダミーのFCSを付加する
memset(buf + dwReceived, 0, 4);
dwReceived += 4;
}
// バイト数を返却
return dwReceived;
}
//---------------------------------------------------------------------------
//
// 送信
//
//---------------------------------------------------------------------------
int FASTCALL CTapDriver::Tx(BYTE *buf, int len)
{
ASSERT(this);
ASSERT(m_hTAP != -1);
// 送信開始
return write(m_hTAP, buf, len);
}