mirror of https://github.com/PCSX2/pcsx2.git
DEV9: Move most of the pcap methods into PCAPAdapter
Also includes the following changes; pcap_io_running checks replaced with assets in send/recv pcap_io_running checks replaces checks on hpcap being non null. Don't cast header->len from unsigned to signed when checking for jumbo frames Log dropping jumbo frames Free pcap filter code Check return value of GetMACAddress() and handle appropriately.
This commit is contained in:
parent
42511ce8d8
commit
3028998a43
|
@ -30,7 +30,6 @@
|
||||||
#include "DEV9.h"
|
#include "DEV9.h"
|
||||||
#include "AdapterUtils.h"
|
#include "AdapterUtils.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "DEV9/PacketReader/MAC_Address.h"
|
|
||||||
#ifndef PCAP_NETMASK_UNKNOWN
|
#ifndef PCAP_NETMASK_UNKNOWN
|
||||||
#define PCAP_NETMASK_UNKNOWN 0xffffffff
|
#define PCAP_NETMASK_UNKNOWN 0xffffffff
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,103 +38,8 @@
|
||||||
#define PCAPPREFIX "\\Device\\NPF_"
|
#define PCAPPREFIX "\\Device\\NPF_"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pcap_t* adhandle;
|
using namespace PacketReader;
|
||||||
pcap_dumper_t* dump_pcap = nullptr;
|
using namespace PacketReader::IP;
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
|
||||||
|
|
||||||
int pcap_io_running = 0;
|
|
||||||
bool pcap_io_switched;
|
|
||||||
bool pcap_io_blocking;
|
|
||||||
|
|
||||||
extern u8 eeprom[];
|
|
||||||
|
|
||||||
char namebuff[256];
|
|
||||||
|
|
||||||
ip_address ps2_ip;
|
|
||||||
mac_address ps2_mac;
|
|
||||||
mac_address host_mac;
|
|
||||||
|
|
||||||
int pcap_io_init(const std::string& adapter, bool switched, mac_address virtual_mac)
|
|
||||||
{
|
|
||||||
struct bpf_program fp;
|
|
||||||
char filter[1024] = "ether broadcast or ether dst ";
|
|
||||||
int dlt;
|
|
||||||
char* dlt_name;
|
|
||||||
Console.WriteLn("DEV9: Opening adapter '%s'...", adapter.c_str());
|
|
||||||
|
|
||||||
pcap_io_switched = switched;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
std::string pcapAdapter = PCAPPREFIX + adapter;
|
|
||||||
#else
|
|
||||||
std::string pcapAdapter = adapter;
|
|
||||||
#endif
|
|
||||||
/* Open the adapter */
|
|
||||||
if ((adhandle = pcap_open_live(pcapAdapter.c_str(), // name of the device
|
|
||||||
65536, // portion of the packet to capture.
|
|
||||||
// 65536 grants that the whole packet will be captured on all the MACs.
|
|
||||||
switched ? 1 : 0,
|
|
||||||
1, // read timeout
|
|
||||||
errbuf // error buffer
|
|
||||||
)) == NULL)
|
|
||||||
{
|
|
||||||
Console.Error("DEV9: %s", errbuf);
|
|
||||||
Console.Error("DEV9: Unable to open the adapter. %s is not supported by pcap", adapter.c_str());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (switched)
|
|
||||||
{
|
|
||||||
char virtual_mac_str[18];
|
|
||||||
sprintf(virtual_mac_str, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", virtual_mac.bytes[0], virtual_mac.bytes[1], virtual_mac.bytes[2], virtual_mac.bytes[3], virtual_mac.bytes[4], virtual_mac.bytes[5]);
|
|
||||||
strcat(filter, virtual_mac_str);
|
|
||||||
// fprintf(stderr, "Trying pcap filter: %s\n", filter);
|
|
||||||
|
|
||||||
if (pcap_compile(adhandle, &fp, filter, 1, PCAP_NETMASK_UNKNOWN) == -1)
|
|
||||||
{
|
|
||||||
Console.Error("DEV9: Error calling pcap_compile: %s", pcap_geterr(adhandle));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pcap_setfilter(adhandle, &fp) == -1)
|
|
||||||
{
|
|
||||||
Console.Error("DEV9: Error setting filter: %s", pcap_geterr(adhandle));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pcap_setnonblock(adhandle, 1, errbuf) == -1)
|
|
||||||
{
|
|
||||||
Console.Error("DEV9: Error setting non-blocking: %s", pcap_geterr(adhandle));
|
|
||||||
Console.Error("DEV9: Continuing in blocking mode");
|
|
||||||
pcap_io_blocking = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pcap_io_blocking = false;
|
|
||||||
|
|
||||||
dlt = pcap_datalink(adhandle);
|
|
||||||
dlt_name = (char*)pcap_datalink_val_to_name(dlt);
|
|
||||||
|
|
||||||
Console.Error("DEV9: Device uses DLT %d: %s", dlt, dlt_name);
|
|
||||||
switch (dlt)
|
|
||||||
{
|
|
||||||
case DLT_EN10MB:
|
|
||||||
//case DLT_IEEE802_11:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Console.Error("ERROR: Unsupported DataLink Type (%d): %s", dlt, dlt_name);
|
|
||||||
pcap_close(adhandle);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
const std::string plfile(s_strLogPath + "/pkt_log.pcap");
|
|
||||||
dump_pcap = pcap_dump_open(adhandle, plfile.c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pcap_io_running = 1;
|
|
||||||
Console.WriteLn("DEV9: Adapter Ok.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
int gettimeofday(struct timeval* tv, void* tz)
|
int gettimeofday(struct timeval* tv, void* tz)
|
||||||
|
@ -149,94 +53,6 @@ int gettimeofday(struct timeval* tv, void* tz)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int pcap_io_send(void* packet, int plen)
|
|
||||||
{
|
|
||||||
if (pcap_io_running <= 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!pcap_io_switched)
|
|
||||||
{
|
|
||||||
if (((ethernet_header*)packet)->protocol == 0x0008) //IP
|
|
||||||
{
|
|
||||||
ps2_ip = ((ip_header*)((u8*)packet + sizeof(ethernet_header)))->src;
|
|
||||||
}
|
|
||||||
if (((ethernet_header*)packet)->protocol == 0x0608) //ARP
|
|
||||||
{
|
|
||||||
ps2_ip = ((arp_packet*)((u8*)packet + sizeof(ethernet_header)))->p_src;
|
|
||||||
((arp_packet*)((u8*)packet + sizeof(ethernet_header)))->h_src = host_mac;
|
|
||||||
}
|
|
||||||
((ethernet_header*)packet)->src = host_mac;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dump_pcap)
|
|
||||||
{
|
|
||||||
static struct pcap_pkthdr ph;
|
|
||||||
gettimeofday(&ph.ts, NULL);
|
|
||||||
ph.caplen = plen;
|
|
||||||
ph.len = plen;
|
|
||||||
pcap_dump((u_char*)dump_pcap, &ph, (u_char*)packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pcap_sendpacket(adhandle, (u_char*)packet, plen);
|
|
||||||
}
|
|
||||||
|
|
||||||
int pcap_io_recv(void* packet, int max_len)
|
|
||||||
{
|
|
||||||
static struct pcap_pkthdr* header;
|
|
||||||
static const u_char* pkt_data1;
|
|
||||||
|
|
||||||
if (pcap_io_running <= 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if ((pcap_next_ex(adhandle, &header, &pkt_data1)) > 0)
|
|
||||||
{
|
|
||||||
if ((int)header->len > max_len)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
memcpy(packet, pkt_data1, header->len);
|
|
||||||
|
|
||||||
if (!pcap_io_switched)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
if (((ethernet_header*)packet)->protocol == 0x0008)
|
|
||||||
{
|
|
||||||
ip_header* iph = ((ip_header*)((u8*)packet + sizeof(ethernet_header)));
|
|
||||||
if (ip_compare(iph->dst, ps2_ip) == 0)
|
|
||||||
{
|
|
||||||
((ethernet_header*)packet)->dst = ps2_mac;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (((ethernet_header*)packet)->protocol == 0x0608)
|
|
||||||
{
|
|
||||||
arp_packet* aph = ((arp_packet*)((u8*)packet + sizeof(ethernet_header)));
|
|
||||||
if (ip_compare(aph->p_dst, ps2_ip) == 0)
|
|
||||||
{
|
|
||||||
((ethernet_header*)packet)->dst = ps2_mac;
|
|
||||||
((arp_packet*)((u8*)packet + sizeof(ethernet_header)))->h_dst = ps2_mac;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dump_pcap)
|
|
||||||
pcap_dump((u_char*)dump_pcap, header, (u_char*)packet);
|
|
||||||
|
|
||||||
return header->len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pcap_io_close()
|
|
||||||
{
|
|
||||||
if (dump_pcap)
|
|
||||||
pcap_dump_close(dump_pcap);
|
|
||||||
if (adhandle)
|
|
||||||
pcap_close(adhandle);
|
|
||||||
pcap_io_running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PCAPAdapter::PCAPAdapter()
|
PCAPAdapter::PCAPAdapter()
|
||||||
: NetAdapter()
|
: NetAdapter()
|
||||||
{
|
{
|
||||||
|
@ -247,44 +63,64 @@ PCAPAdapter::PCAPAdapter()
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AdapterUtils::Adapter adapter;
|
#ifdef _WIN32
|
||||||
AdapterUtils::AdapterBuffer buffer;
|
std::string pcapAdapter = PCAPPREFIX + EmuConfig.DEV9.EthDevice;
|
||||||
if (AdapterUtils::GetAdapter(EmuConfig.DEV9.EthDevice, &adapter, &buffer))
|
#else
|
||||||
{
|
std::string pcapAdapter = EmuConfig.DEV9.EthDevice;
|
||||||
std::optional<PacketReader::MAC_Address> adMAC = AdapterUtils::GetAdapterMAC(&adapter);
|
#endif
|
||||||
if (adMAC.has_value())
|
|
||||||
{
|
|
||||||
mac_address hostMAC = *(mac_address*)&adMAC.value();
|
|
||||||
mac_address newMAC;
|
|
||||||
memcpy(&newMAC, &ps2MAC, 6);
|
|
||||||
|
|
||||||
//Lets take the hosts last 2 bytes to make it unique on Xlink
|
switched = EmuConfig.DEV9.EthApi == Pcsx2Config::DEV9Options::NetApi::PCAP_Switched;
|
||||||
newMAC.bytes[5] = hostMAC.bytes[4];
|
|
||||||
newMAC.bytes[4] = hostMAC.bytes[5];
|
|
||||||
|
|
||||||
SetMACAddress((PacketReader::MAC_Address*)&newMAC);
|
if (!InitPCAP(pcapAdapter, switched))
|
||||||
host_mac = hostMAC;
|
|
||||||
ps2_mac = newMAC; //Needed outside of this class
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.Error("DEV9: Failed to get MAC address for adapter");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.Error("DEV9: Failed to get adapter information");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pcap_io_init(EmuConfig.DEV9.EthDevice, EmuConfig.DEV9.EthApi == Pcsx2Config::DEV9Options::NetApi::PCAP_Switched, ps2_mac) == -1)
|
|
||||||
{
|
{
|
||||||
Console.Error("DEV9: Can't open Device '%s'", EmuConfig.DEV9.EthDevice.c_str());
|
Console.Error("DEV9: Can't open Device '%s'", EmuConfig.DEV9.EthDevice.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitInternalServer(&adapter);
|
AdapterUtils::Adapter adapter;
|
||||||
|
AdapterUtils::AdapterBuffer buffer;
|
||||||
|
std::optional<MAC_Address> adMAC = std::nullopt;
|
||||||
|
const bool foundAdapter = AdapterUtils::GetAdapter(EmuConfig.DEV9.EthDevice, &adapter, &buffer);
|
||||||
|
if (foundAdapter)
|
||||||
|
adMAC = AdapterUtils::GetAdapterMAC(&adapter);
|
||||||
|
else
|
||||||
|
Console.Error("DEV9: Failed to get adapter information");
|
||||||
|
|
||||||
|
if (adMAC.has_value())
|
||||||
|
{
|
||||||
|
hostMAC = adMAC.value();
|
||||||
|
MAC_Address newMAC = ps2MAC;
|
||||||
|
|
||||||
|
//Lets take the hosts last 2 bytes to make it unique on Xlink
|
||||||
|
newMAC.bytes[5] = hostMAC.bytes[4];
|
||||||
|
newMAC.bytes[4] = hostMAC.bytes[5];
|
||||||
|
|
||||||
|
SetMACAddress(&newMAC);
|
||||||
|
}
|
||||||
|
else if (switched)
|
||||||
|
Console.Error("DEV9: Failed to get MAC address for adapter, proceeding with hardcoded MAC address");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.Error("DEV9: Failed to get MAC address for adapter");
|
||||||
|
pcap_close(hpcap);
|
||||||
|
hpcap = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switched && !SetMACSwitchedFilter(ps2MAC))
|
||||||
|
{
|
||||||
|
pcap_close(hpcap);
|
||||||
|
hpcap = nullptr;
|
||||||
|
Console.Error("DEV9: Can't open Device '%s'", EmuConfig.DEV9.EthDevice.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundAdapter)
|
||||||
|
InitInternalServer(&adapter);
|
||||||
|
else
|
||||||
|
InitInternalServer(nullptr);
|
||||||
|
|
||||||
|
InitPCAPDumper();
|
||||||
}
|
}
|
||||||
AdapterOptions PCAPAdapter::GetAdapterOptions()
|
AdapterOptions PCAPAdapter::GetAdapterOptions()
|
||||||
{
|
{
|
||||||
|
@ -292,21 +128,46 @@ AdapterOptions PCAPAdapter::GetAdapterOptions()
|
||||||
}
|
}
|
||||||
bool PCAPAdapter::blocks()
|
bool PCAPAdapter::blocks()
|
||||||
{
|
{
|
||||||
pxAssert(pcap_io_running);
|
pxAssert(hpcap);
|
||||||
return pcap_io_blocking;
|
return blocking;
|
||||||
}
|
}
|
||||||
bool PCAPAdapter::isInitialised()
|
bool PCAPAdapter::isInitialised()
|
||||||
{
|
{
|
||||||
return !!pcap_io_running;
|
return hpcap != nullptr;
|
||||||
}
|
}
|
||||||
//gets a packet.rv :true success
|
//gets a packet.rv :true success
|
||||||
bool PCAPAdapter::recv(NetPacket* pkt)
|
bool PCAPAdapter::recv(NetPacket* pkt)
|
||||||
{
|
{
|
||||||
if (!pcap_io_blocking && NetAdapter::recv(pkt))
|
pxAssert(hpcap);
|
||||||
|
|
||||||
|
if (!blocking && NetAdapter::recv(pkt))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
int size = pcap_io_recv(pkt->buffer, sizeof(pkt->buffer));
|
pcap_pkthdr* header;
|
||||||
if (size > 0 && VerifyPkt(pkt, size))
|
const u_char* pkt_data;
|
||||||
|
|
||||||
|
if (pcap_next_ex(hpcap, &header, &pkt_data) > 0)
|
||||||
|
{
|
||||||
|
if (header->len > sizeof(pkt->buffer))
|
||||||
|
{
|
||||||
|
Console.Error("DEV9: Dropped jumbo frame of size: %u", header->len);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pxAssert(header->len == header->caplen);
|
||||||
|
|
||||||
|
memcpy(pkt->buffer, pkt_data, header->len);
|
||||||
|
|
||||||
|
if (!switched)
|
||||||
|
SetMACBridgedRecv(pkt);
|
||||||
|
|
||||||
|
if (hpcap_dumper)
|
||||||
|
pcap_dump((u_char*)hpcap_dumper, header, pkt_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (VerifyPkt(pkt, header->len))
|
||||||
{
|
{
|
||||||
InspectRecv(pkt);
|
InspectRecv(pkt);
|
||||||
return true;
|
return true;
|
||||||
|
@ -317,18 +178,29 @@ bool PCAPAdapter::recv(NetPacket* pkt)
|
||||||
//sends the packet .rv :true success
|
//sends the packet .rv :true success
|
||||||
bool PCAPAdapter::send(NetPacket* pkt)
|
bool PCAPAdapter::send(NetPacket* pkt)
|
||||||
{
|
{
|
||||||
|
pxAssert(hpcap);
|
||||||
|
|
||||||
InspectSend(pkt);
|
InspectSend(pkt);
|
||||||
if (NetAdapter::send(pkt))
|
if (NetAdapter::send(pkt))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (pcap_io_send(pkt->buffer, pkt->size))
|
if (hpcap_dumper)
|
||||||
{
|
{
|
||||||
|
pcap_pkthdr ph;
|
||||||
|
gettimeofday(&ph.ts, NULL);
|
||||||
|
ph.caplen = pkt->size;
|
||||||
|
ph.len = pkt->size;
|
||||||
|
pcap_dump((u_char*)hpcap_dumper, &ph, (u_char*)pkt->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: loopback broadcast packets to host pc in switched mode.
|
||||||
|
if (!switched)
|
||||||
|
SetMACBridgedSend(pkt);
|
||||||
|
|
||||||
|
if (pcap_sendpacket(hpcap, (u_char*)pkt->buffer, pkt->size))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PCAPAdapter::reloadSettings()
|
void PCAPAdapter::reloadSettings()
|
||||||
|
@ -343,7 +215,16 @@ void PCAPAdapter::reloadSettings()
|
||||||
|
|
||||||
PCAPAdapter::~PCAPAdapter()
|
PCAPAdapter::~PCAPAdapter()
|
||||||
{
|
{
|
||||||
pcap_io_close();
|
if (hpcap_dumper)
|
||||||
|
{
|
||||||
|
pcap_dump_close(hpcap_dumper);
|
||||||
|
hpcap_dumper = nullptr;
|
||||||
|
}
|
||||||
|
if (hpcap)
|
||||||
|
{
|
||||||
|
pcap_close(hpcap);
|
||||||
|
hpcap = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AdapterEntry> PCAPAdapter::GetAdapters()
|
std::vector<AdapterEntry> PCAPAdapter::GetAdapters()
|
||||||
|
@ -355,6 +236,7 @@ std::vector<AdapterEntry> PCAPAdapter::GetAdapters()
|
||||||
return nic;
|
return nic;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
pcap_if_t* alldevs;
|
pcap_if_t* alldevs;
|
||||||
pcap_if_t* d;
|
pcap_if_t* d;
|
||||||
|
|
||||||
|
@ -410,3 +292,127 @@ std::vector<AdapterEntry> PCAPAdapter::GetAdapters()
|
||||||
|
|
||||||
return nic;
|
return nic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Opens device for capture and sets non-blocking.
|
||||||
|
bool PCAPAdapter::InitPCAP(const std::string& adapter, bool promiscuous)
|
||||||
|
{
|
||||||
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
|
Console.WriteLn("DEV9: Opening adapter '%s'...", adapter.c_str());
|
||||||
|
|
||||||
|
// Open the adapter.
|
||||||
|
if ((hpcap = pcap_open_live(adapter.c_str(), // Name of the device.
|
||||||
|
65536, // portion of the packet to capture.
|
||||||
|
// 65536 grants that the whole packet will be captured on all the MACs.
|
||||||
|
promiscuous ? 1 : 0,
|
||||||
|
1, // Read timeout.
|
||||||
|
errbuf // Error buffer.
|
||||||
|
)) == nullptr)
|
||||||
|
{
|
||||||
|
Console.Error("DEV9: %s", errbuf);
|
||||||
|
Console.Error("DEV9: Unable to open the adapter. %s is not supported by pcap", adapter.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcap_setnonblock(hpcap, 1, errbuf) == -1)
|
||||||
|
{
|
||||||
|
Console.Error("DEV9: Error setting non-blocking: %s", pcap_geterr(hpcap));
|
||||||
|
Console.Error("DEV9: Continuing in blocking mode");
|
||||||
|
blocking = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
blocking = false;
|
||||||
|
|
||||||
|
// Validate.
|
||||||
|
const int dlt = pcap_datalink(hpcap);
|
||||||
|
const char* dlt_name = pcap_datalink_val_to_name(dlt);
|
||||||
|
|
||||||
|
Console.Error("DEV9: Device uses DLT %d: %s", dlt, dlt_name);
|
||||||
|
switch (dlt)
|
||||||
|
{
|
||||||
|
case DLT_EN10MB:
|
||||||
|
//case DLT_IEEE802_11:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.Error("ERROR: Unsupported DataLink Type (%d): %s", dlt, dlt_name);
|
||||||
|
pcap_close(hpcap);
|
||||||
|
hpcap = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLn("DEV9: Adapter Ok.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCAPAdapter::InitPCAPDumper()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
const std::string plfile(s_strLogPath + "/pkt_log.pcap");
|
||||||
|
hpcap_dumper = pcap_dump_open(hpcap, plfile.c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PCAPAdapter::SetMACSwitchedFilter(MAC_Address mac)
|
||||||
|
{
|
||||||
|
bpf_program fp;
|
||||||
|
char filter[1024] = "ether broadcast or ether dst ";
|
||||||
|
|
||||||
|
char virtual_mac_str[18];
|
||||||
|
sprintf(virtual_mac_str, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", mac.bytes[0], mac.bytes[1], mac.bytes[2], mac.bytes[3], mac.bytes[4], mac.bytes[5]);
|
||||||
|
strcat(filter, virtual_mac_str);
|
||||||
|
|
||||||
|
if (pcap_compile(hpcap, &fp, filter, 1, PCAP_NETMASK_UNKNOWN) == -1)
|
||||||
|
{
|
||||||
|
Console.Error("DEV9: Error calling pcap_compile: %s", pcap_geterr(hpcap));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setFilterRet;
|
||||||
|
if ((setFilterRet = pcap_setfilter(hpcap, &fp)) == -1)
|
||||||
|
Console.Error("DEV9: Error setting filter: %s", pcap_geterr(hpcap));
|
||||||
|
|
||||||
|
pcap_freecode(&fp);
|
||||||
|
return setFilterRet != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCAPAdapter::SetMACBridgedRecv(NetPacket* pkt)
|
||||||
|
{
|
||||||
|
ethernet_header* eth = (ethernet_header*)pkt->buffer;
|
||||||
|
if (eth->protocol == 0x0008) // IP
|
||||||
|
{
|
||||||
|
// Compare DEST IP in IP with the PS2's IP, if they match, change DEST MAC to ps2MAC.
|
||||||
|
const ip_header* iph = ((ip_header*)(pkt->buffer + sizeof(ethernet_header)));
|
||||||
|
|
||||||
|
if (*(IP_Address*)&iph->dst == ps2IP)
|
||||||
|
eth->dst = *(mac_address*)&ps2MAC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eth->protocol == 0x0608) // ARP
|
||||||
|
{
|
||||||
|
// Compare DEST IP in ARP with the PS2's IP, if they match, DEST MAC to ps2MAC on both ARP and ETH Packet headers.
|
||||||
|
arp_packet* aph = ((arp_packet*)(pkt->buffer + sizeof(ethernet_header)));
|
||||||
|
|
||||||
|
if (*(IP_Address*)&aph->p_dst == ps2IP)
|
||||||
|
{
|
||||||
|
eth->dst = *(mac_address*)&ps2MAC;
|
||||||
|
((arp_packet*)(pkt->buffer + sizeof(ethernet_header)))->h_dst = *(mac_address*)&ps2MAC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCAPAdapter::SetMACBridgedSend(NetPacket* pkt)
|
||||||
|
{
|
||||||
|
ethernet_header* eth = (ethernet_header*)pkt->buffer;
|
||||||
|
if (eth->protocol == 0x0008) // IP
|
||||||
|
{
|
||||||
|
const ip_address ps2_ip = ((ip_header*)((u8*)pkt->buffer + sizeof(ethernet_header)))->src;
|
||||||
|
ps2IP = *(IP_Address*)&ps2_ip;
|
||||||
|
}
|
||||||
|
if (eth->protocol == 0x0608) // ARP
|
||||||
|
{
|
||||||
|
const ip_address ps2_ip = ((arp_packet*)((u8*)pkt->buffer + sizeof(ethernet_header)))->p_src;
|
||||||
|
ps2IP = *(IP_Address*)&ps2_ip;
|
||||||
|
|
||||||
|
((arp_packet*)(pkt->buffer + sizeof(ethernet_header)))->h_src = *(mac_address*)&hostMAC;
|
||||||
|
}
|
||||||
|
eth->src = *(mac_address*)&hostMAC;
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "pcap.h"
|
#include "pcap.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include "PacketReader/MAC_Address.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -173,6 +174,16 @@ void unload_pcap();
|
||||||
|
|
||||||
class PCAPAdapter : public NetAdapter
|
class PCAPAdapter : public NetAdapter
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
pcap_t* hpcap = nullptr;
|
||||||
|
pcap_dumper_t* hpcap_dumper = nullptr;
|
||||||
|
|
||||||
|
bool switched;
|
||||||
|
bool blocking;
|
||||||
|
|
||||||
|
PacketReader::IP::IP_Address ps2IP{};
|
||||||
|
PacketReader::MAC_Address hostMAC;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PCAPAdapter();
|
PCAPAdapter();
|
||||||
virtual bool blocks();
|
virtual bool blocks();
|
||||||
|
@ -185,4 +196,12 @@ public:
|
||||||
virtual ~PCAPAdapter();
|
virtual ~PCAPAdapter();
|
||||||
static std::vector<AdapterEntry> GetAdapters();
|
static std::vector<AdapterEntry> GetAdapters();
|
||||||
static AdapterOptions GetAdapterOptions();
|
static AdapterOptions GetAdapterOptions();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool InitPCAP(const std::string& adapter, bool promiscuous);
|
||||||
|
void InitPCAPDumper();
|
||||||
|
bool SetMACSwitchedFilter(PacketReader::MAC_Address mac);
|
||||||
|
|
||||||
|
void SetMACBridgedRecv(NetPacket* pkt);
|
||||||
|
void SetMACBridgedSend(NetPacket* pkt);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue