mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-10-14 02:17:36 +08:00
ethernet_pcap: Move NE2000 pcap code to PcapEthernetConnection
This change separates the pcap code out of the NE2000 code to its own EthernetConnection backend, and modifies the NE2000 to use the EthernetConnection abstraction.
This commit is contained in:
@@ -1,9 +1,5 @@
|
||||
#include "config.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#define HAVE_REMOTE
|
||||
#endif
|
||||
|
||||
#include "dosbox.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -51,34 +47,11 @@
|
||||
|
||||
#include "ne2000.h"
|
||||
|
||||
#include "ethernet.h"
|
||||
EthernetConnection* ethernet = nullptr;
|
||||
|
||||
static void NE2000_TX_Event(Bitu val);
|
||||
|
||||
#ifdef C_PCAP
|
||||
|
||||
#include "pcap.h"
|
||||
// Handle to WinPCap device
|
||||
pcap_t *adhandle = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
// DLL loading
|
||||
#define pcap_sendpacket(A,B,C) PacketSendPacket(A,B,C)
|
||||
#define pcap_close(A) PacketClose(A)
|
||||
#define pcap_freealldevs(A) PacketFreealldevs(A)
|
||||
#define pcap_open(A,B,C,D,E,F) PacketOpen(A,B,C,D,E,F)
|
||||
#define pcap_next_ex(A,B,C) PacketNextEx(A,B,C)
|
||||
#define pcap_findalldevs_ex(A,B,C,D) PacketFindALlDevsEx(A,B,C,D)
|
||||
|
||||
int (*PacketSendPacket)(pcap_t *, const u_char *, int) = 0;
|
||||
void (*PacketClose)(pcap_t *) = 0;
|
||||
void (*PacketFreealldevs)(pcap_if_t *) = 0;
|
||||
pcap_t* (*PacketOpen)(char const *,int,int,int,struct pcap_rmtauth *,char *) = 0;
|
||||
int (*PacketNextEx)(pcap_t *, struct pcap_pkthdr **, const u_char **) = 0;
|
||||
int (*PacketFindALlDevsEx)(char *, struct pcap_rmtauth *, pcap_if_t **, char *) = 0;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//Never completely fill the ne2k ring so that we never
|
||||
// hit the unclear completely full buffer condition.
|
||||
#define BX_NE2K_NEVER_FULL_RING (1)
|
||||
@@ -304,9 +277,7 @@ bx_ne2k_c::write_cr(uint32_t value)
|
||||
// Send the packet to the system driver
|
||||
/* TODO: Transmit packet */
|
||||
//BX_NE2K_THIS ethdev->sendpkt(& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - BX_NE2K_MEMSTART], BX_NE2K_THIS s.tx_bytes);
|
||||
#ifdef C_PCAP
|
||||
pcap_sendpacket(adhandle,&s.mem[s.tx_page_start*256 - BX_NE2K_MEMSTART], s.tx_bytes);
|
||||
#endif
|
||||
ethernet->SendPacket(&s.mem[s.tx_page_start*256 - BX_NE2K_MEMSTART], s.tx_bytes);
|
||||
// some more debug
|
||||
if (BX_NE2K_THIS s.tx_timer_active) {
|
||||
BX_PANIC(("CR write, tx timer still active"));
|
||||
@@ -1473,25 +1444,15 @@ static void NE2000_TX_Event(Bitu val) {
|
||||
}
|
||||
|
||||
static void NE2000_Poller(void) {
|
||||
#ifdef C_PCAP
|
||||
int res;
|
||||
struct pcap_pkthdr *header;
|
||||
u_char *pkt_data;
|
||||
//#if 0
|
||||
while((res = pcap_next_ex( adhandle, &header, (const u_char **)&pkt_data)) > 0) {
|
||||
ethernet->GetPackets([](const uint8_t* packet, int len) {
|
||||
//LOG_MSG("NE2000: Received %d bytes", header->len);
|
||||
|
||||
|
||||
// don't receive in loopback modes
|
||||
if((theNE2kDevice->s.DCR.loop == 0) || (theNE2kDevice->s.TCR.loop_cntl != 0))
|
||||
return;
|
||||
theNE2kDevice->rx_frame(pkt_data, header->len);
|
||||
}
|
||||
//#endif
|
||||
#endif
|
||||
theNE2kDevice->rx_frame(packet, len);
|
||||
});
|
||||
}
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
extern std::string niclist;
|
||||
|
||||
@@ -1516,67 +1477,12 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef C_PCAP
|
||||
LOG_MSG("pcap support not enabled, disabling ne2000");
|
||||
load_success = false;
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef C_PCAP
|
||||
#ifdef WIN32
|
||||
/*
|
||||
int (*PacketSendPacket)(pcap_t *, const u_char *, int);
|
||||
void (*PacketClose)(pcap_t *);
|
||||
void (*PacketFreealldevs)(pcap_if_t *);
|
||||
pcap_t* (*PacketOpen)(char const *,int,int,int,struct pcap_rmtauth *,char *);
|
||||
int (*PacketNextEx)(pcap_t *, struct pcap_pkthdr **, const u_char **);
|
||||
int (*PacketFindALlDevsEx)(char *, struct pcap_rmtauth *, pcap_if_t **, char *);
|
||||
*/
|
||||
// init the library
|
||||
HINSTANCE pcapinst;
|
||||
pcapinst = LoadLibrary("WPCAP.DLL");
|
||||
if(pcapinst==NULL) {
|
||||
niclist = "WinPcap has to be installed for the NE2000 to work.";
|
||||
LOG_MSG(niclist.c_str());
|
||||
ethernet = OpenEthernetConnection("pcap");
|
||||
if(!ethernet)
|
||||
{
|
||||
load_success = false;
|
||||
return;
|
||||
}
|
||||
FARPROC psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_sendpacket");
|
||||
if(!PacketSendPacket) PacketSendPacket =
|
||||
(int (__cdecl *)(pcap_t *,const u_char *,int))psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_close");
|
||||
if(!PacketClose) PacketClose =
|
||||
(void (__cdecl *)(pcap_t *)) psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_freealldevs");
|
||||
if(!PacketFreealldevs) PacketFreealldevs =
|
||||
(void (__cdecl *)(pcap_if_t *)) psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_open");
|
||||
if(!PacketOpen) PacketOpen =
|
||||
(pcap_t* (__cdecl *)(char const *,int,int,int,struct pcap_rmtauth *,char *)) psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_next_ex");
|
||||
if(!PacketNextEx) PacketNextEx =
|
||||
(int (__cdecl *)(pcap_t *, struct pcap_pkthdr **, const u_char **)) psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_findalldevs_ex");
|
||||
if(!PacketFindALlDevsEx) PacketFindALlDevsEx =
|
||||
(int (__cdecl *)(char *, struct pcap_rmtauth *, pcap_if_t **, char *)) psp;
|
||||
|
||||
if(PacketFindALlDevsEx==0 || PacketNextEx==0 || PacketOpen==0 ||
|
||||
PacketFreealldevs==0 || PacketClose==0 || PacketSendPacket==0) {
|
||||
niclist = "Incorrect or non-functional WinPcap version.";
|
||||
LOG_MSG(niclist.c_str());
|
||||
load_success = false;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// get irq and base
|
||||
Bitu irq = (Bitu)section->Get_int("nicirq");
|
||||
@@ -1605,120 +1511,6 @@ public:
|
||||
mac[4]=macint[4]; mac[5]=macint[5];
|
||||
}
|
||||
|
||||
#ifdef C_PCAP
|
||||
// find out which pcap device to use
|
||||
const char* realnicstring=section->Get_string("realnic");
|
||||
pcap_if_t *alldevs;
|
||||
pcap_if_t *currentdev = NULL;
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
unsigned int userdev;
|
||||
#ifdef WIN32
|
||||
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
|
||||
#else
|
||||
if (pcap_findalldevs(&alldevs, errbuf) == -1)
|
||||
#endif
|
||||
{
|
||||
niclist = "Cannot enumerate network interfaces: "+std::string(errbuf);
|
||||
LOG_MSG("%s", niclist.c_str());
|
||||
load_success = false;
|
||||
return;
|
||||
}
|
||||
{
|
||||
Bitu i = 0;
|
||||
niclist = "Network Interface List\n-------------------------------------------------------------\n";
|
||||
for(currentdev=alldevs; currentdev!=NULL; currentdev=currentdev->next) {
|
||||
const char* desc = "no description";
|
||||
if(currentdev->description) desc=currentdev->description;
|
||||
i++;
|
||||
niclist+=(i<10?"0":"")+std::to_string(i)+" "+currentdev->name+"\n ("+desc+")\n";
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(realnicstring,"list")) {
|
||||
// print list and quit
|
||||
std::istringstream in(("\n"+niclist+"\n").c_str());
|
||||
if (in) for (std::string line; std::getline(in, line); )
|
||||
LOG_MSG("%s", line.c_str());
|
||||
pcap_freealldevs(alldevs);
|
||||
load_success = false;
|
||||
return;
|
||||
} else if(1==sscanf(realnicstring,"%u",&userdev)) {
|
||||
// user passed us a number
|
||||
Bitu i = 0;
|
||||
currentdev=alldevs;
|
||||
while(currentdev!=NULL) {
|
||||
i++;
|
||||
if(i==userdev) break;
|
||||
else currentdev=currentdev->next;
|
||||
}
|
||||
} else {
|
||||
// user might have passed a piece of name
|
||||
for(currentdev=alldevs; currentdev!=NULL; currentdev=currentdev->next) {
|
||||
if(strstr(currentdev->name,realnicstring)) {
|
||||
break;
|
||||
}else if(currentdev->description!=NULL &&
|
||||
strstr(currentdev->description,realnicstring)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(currentdev==NULL) {
|
||||
LOG_MSG("Unable to find network interface - check realnic parameter\n");
|
||||
load_success = false;
|
||||
pcap_freealldevs(alldevs);
|
||||
return;
|
||||
}
|
||||
// print out which interface we are going to use
|
||||
const char* desc = "no description";
|
||||
if(currentdev->description) desc=currentdev->description;
|
||||
LOG_MSG("Using Network interface:\n%s\n(%s)\n",currentdev->name,desc);
|
||||
|
||||
const char *timeoutstr = section->Get_string("pcaptimeout");
|
||||
char *end;
|
||||
int timeout = -1;
|
||||
if (!strlen(timeoutstr)||timeoutstr[0]!='-'&&!isdigit(timeoutstr[0])) { // Default timeout values
|
||||
#ifdef WIN32
|
||||
timeout = -1; // For Windows, use -1 which appears to be specific to WinPCap and means "non-blocking mode"
|
||||
#else
|
||||
timeout = 3000; // For other platforms, use 3000ms as the timeout which should work for platforms like macOS
|
||||
#endif
|
||||
} else
|
||||
timeout = strtoul(timeoutstr,&end,10);
|
||||
// attempt to open it
|
||||
#ifdef WIN32
|
||||
if ( (adhandle= pcap_open(
|
||||
currentdev->name, // name of the device
|
||||
65536, // portion of the packet to capture
|
||||
// 65536 = whole packet
|
||||
PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode
|
||||
timeout, // read timeout
|
||||
NULL, // authentication on the remote machine
|
||||
errbuf // error buffer
|
||||
) ) == NULL)
|
||||
#else
|
||||
/*pcap_t *pcap_open_live(const char *device, int snaplen,
|
||||
int promisc, int to_ms, char *errbuf)*/
|
||||
if ( (adhandle= pcap_open_live(
|
||||
currentdev->name, // name of the device
|
||||
65536, // portion of the packet to capture
|
||||
// 65536 = whole packet
|
||||
true, // promiscuous mode
|
||||
timeout, // read timeout
|
||||
errbuf // error buffer
|
||||
) ) == NULL)
|
||||
|
||||
#endif
|
||||
{
|
||||
LOG_MSG("\nUnable to open the interface: %s.", errbuf);
|
||||
pcap_freealldevs(alldevs);
|
||||
load_success = false;
|
||||
return;
|
||||
}
|
||||
pcap_freealldevs(alldevs);
|
||||
#ifndef WIN32
|
||||
pcap_setnonblock(adhandle,1,errbuf);
|
||||
#endif
|
||||
#endif
|
||||
// create the bochs NIC class
|
||||
theNE2kDevice = new bx_ne2k_c ();
|
||||
memcpy(theNE2kDevice->s.physaddr, mac, 6);
|
||||
@@ -1739,10 +1531,8 @@ public:
|
||||
}
|
||||
|
||||
~NE2K() {
|
||||
#ifdef C_PCAP
|
||||
if(adhandle) pcap_close(adhandle);
|
||||
adhandle=0;
|
||||
#endif
|
||||
if(ethernet != 0) delete ethernet;
|
||||
ethernet=0;
|
||||
if(theNE2kDevice != 0) delete theNE2kDevice;
|
||||
theNE2kDevice=0;
|
||||
TIMER_DelTickHandler(NE2000_Poller);
|
||||
|
@@ -3,4 +3,4 @@ AM_CPPFLAGS = -I$(top_srcdir)/include "-DRESDIR=\"$(resdir)\""
|
||||
resdir = $(datarootdir)/dosbox-x
|
||||
|
||||
noinst_LIBRARIES = libmisc.a
|
||||
libmisc_a_SOURCES = cross.cpp ethernet.cpp messages.cpp programs.cpp setup.cpp support.cpp regionalloctracking.cpp savestates.cpp shiftjis.cpp iconvpp.cpp
|
||||
libmisc_a_SOURCES = cross.cpp ethernet.cpp ethernet_pcap.cpp messages.cpp programs.cpp setup.cpp support.cpp regionalloctracking.cpp savestates.cpp shiftjis.cpp iconvpp.cpp
|
||||
|
@@ -17,10 +17,31 @@
|
||||
*/
|
||||
|
||||
#include "ethernet.h"
|
||||
#include "ethernet_pcap.h"
|
||||
#include <cstring>
|
||||
#include "dosbox.h"
|
||||
|
||||
EthernetConnection* OpenEthernetConnection(const std::string& backend)
|
||||
{
|
||||
// We currently have no backends, so return nothing at the moment.
|
||||
(void)backend;
|
||||
return nullptr;
|
||||
EthernetConnection* conn = nullptr;
|
||||
#ifdef C_PCAP
|
||||
if (backend == "pcap")
|
||||
{
|
||||
conn = ((EthernetConnection*)new PcapEthernetConnection);
|
||||
}
|
||||
#endif
|
||||
if (!conn)
|
||||
{
|
||||
LOG_MSG("ETHERNET: Unknown ethernet backend: %s", backend.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
if (conn->Initialize())
|
||||
{
|
||||
return conn;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete conn;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
237
src/misc/ethernet_pcap.cpp
Normal file
237
src/misc/ethernet_pcap.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if C_PCAP
|
||||
|
||||
#include "ethernet_pcap.h"
|
||||
#include "dosbox.h"
|
||||
#include "support.h" /* strcasecmp */
|
||||
#include <cstring>
|
||||
|
||||
extern std::string niclist;
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// DLL loading
|
||||
#define pcap_sendpacket(A,B,C) PacketSendPacket(A,B,C)
|
||||
#define pcap_close(A) PacketClose(A)
|
||||
#define pcap_freealldevs(A) PacketFreealldevs(A)
|
||||
#define pcap_open(A,B,C,D,E,F) PacketOpen(A,B,C,D,E,F)
|
||||
#define pcap_next_ex(A,B,C) PacketNextEx(A,B,C)
|
||||
#define pcap_findalldevs_ex(A,B,C,D) PacketFindALlDevsEx(A,B,C,D)
|
||||
|
||||
int (*PacketSendPacket)(pcap_t *, const u_char *, int) = 0;
|
||||
void (*PacketClose)(pcap_t *) = 0;
|
||||
void (*PacketFreealldevs)(pcap_if_t *) = 0;
|
||||
pcap_t* (*PacketOpen)(char const *,int,int,int,struct pcap_rmtauth *,char *) = 0;
|
||||
int (*PacketNextEx)(pcap_t *, struct pcap_pkthdr **, const u_char **) = 0;
|
||||
int (*PacketFindALlDevsEx)(char *, struct pcap_rmtauth *, pcap_if_t **, char *) = 0;
|
||||
|
||||
#endif
|
||||
|
||||
PcapEthernetConnection::PcapEthernetConnection()
|
||||
: EthernetConnection()
|
||||
{
|
||||
}
|
||||
|
||||
PcapEthernetConnection::~PcapEthernetConnection()
|
||||
{
|
||||
if(adhandle) pcap_close(adhandle);
|
||||
}
|
||||
|
||||
bool PcapEthernetConnection::Initialize()
|
||||
{
|
||||
/* TODO: grab from config */
|
||||
const char* realnicstring = "list";
|
||||
|
||||
#ifdef WIN32
|
||||
// init the library
|
||||
HINSTANCE pcapinst;
|
||||
pcapinst = LoadLibrary("WPCAP.DLL");
|
||||
if(pcapinst==NULL) {
|
||||
niclist = "WinPcap has to be installed for the NE2000 to work.";
|
||||
LOG_MSG(niclist.c_str());
|
||||
return false;
|
||||
}
|
||||
FARPROC psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_sendpacket");
|
||||
if(!PacketSendPacket) PacketSendPacket =
|
||||
(int (__cdecl *)(pcap_t *,const u_char *,int))psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_close");
|
||||
if(!PacketClose) PacketClose =
|
||||
(void (__cdecl *)(pcap_t *)) psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_freealldevs");
|
||||
if(!PacketFreealldevs) PacketFreealldevs =
|
||||
(void (__cdecl *)(pcap_if_t *)) psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_open");
|
||||
if(!PacketOpen) PacketOpen =
|
||||
(pcap_t* (__cdecl *)(char const *,int,int,int,struct pcap_rmtauth *,char *)) psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_next_ex");
|
||||
if(!PacketNextEx) PacketNextEx =
|
||||
(int (__cdecl *)(pcap_t *, struct pcap_pkthdr **, const u_char **)) psp;
|
||||
|
||||
psp = GetProcAddress(pcapinst,"pcap_findalldevs_ex");
|
||||
if(!PacketFindALlDevsEx) PacketFindALlDevsEx =
|
||||
(int (__cdecl *)(char *, struct pcap_rmtauth *, pcap_if_t **, char *)) psp;
|
||||
|
||||
if(PacketFindALlDevsEx==0 || PacketNextEx==0 || PacketOpen==0 ||
|
||||
PacketFreealldevs==0 || PacketClose==0 || PacketSendPacket==0) {
|
||||
niclist = "Incorrect or non-functional WinPcap version.";
|
||||
LOG_MSG(niclist.c_str());
|
||||
pcapinst = NULL;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// find out which pcap device to use
|
||||
pcap_if_t *alldevs;
|
||||
pcap_if_t *currentdev = NULL;
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
unsigned int userdev;
|
||||
#ifdef WIN32
|
||||
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
|
||||
#else
|
||||
if (pcap_findalldevs(&alldevs, errbuf) == -1)
|
||||
#endif
|
||||
{
|
||||
niclist = "Cannot enumerate network interfaces: "+std::string(errbuf);
|
||||
LOG_MSG("%s", niclist.c_str());
|
||||
return false;
|
||||
}
|
||||
{
|
||||
Bitu i = 0;
|
||||
niclist = "Network Interface List\n-------------------------------------------------------------\n";
|
||||
for(currentdev=alldevs; currentdev!=NULL; currentdev=currentdev->next) {
|
||||
const char* desc = "no description";
|
||||
if(currentdev->description) desc=currentdev->description;
|
||||
i++;
|
||||
niclist+=(i<10?"0":"")+std::to_string(i)+" "+currentdev->name+"\n ("+desc+")\n";
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(realnicstring,"list")) {
|
||||
// print list and quit
|
||||
std::istringstream in(("\n"+niclist+"\n").c_str());
|
||||
if (in) for (std::string line; std::getline(in, line); )
|
||||
LOG_MSG("%s", line.c_str());
|
||||
pcap_freealldevs(alldevs);
|
||||
return false;
|
||||
} else if(1==sscanf(realnicstring,"%u",&userdev)) {
|
||||
// user passed us a number
|
||||
Bitu i = 0;
|
||||
currentdev=alldevs;
|
||||
while(currentdev!=NULL) {
|
||||
i++;
|
||||
if(i==userdev) break;
|
||||
else currentdev=currentdev->next;
|
||||
}
|
||||
} else {
|
||||
// user might have passed a piece of name
|
||||
for(currentdev=alldevs; currentdev!=NULL; currentdev=currentdev->next) {
|
||||
if(strstr(currentdev->name,realnicstring)) {
|
||||
break;
|
||||
}else if(currentdev->description!=NULL &&
|
||||
strstr(currentdev->description,realnicstring)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(currentdev==NULL) {
|
||||
LOG_MSG("Unable to find network interface - check realnic parameter\n");
|
||||
pcap_freealldevs(alldevs);
|
||||
return false;
|
||||
}
|
||||
// print out which interface we are going to use
|
||||
const char* desc = "no description";
|
||||
if(currentdev->description) desc=currentdev->description;
|
||||
LOG_MSG("Using Network interface:\n%s\n(%s)\n",currentdev->name,desc);
|
||||
|
||||
const char *timeoutstr = section->Get_string("pcaptimeout");
|
||||
char *end;
|
||||
int timeout = -1;
|
||||
if (!strlen(timeoutstr)||timeoutstr[0]!='-'&&!isdigit(timeoutstr[0])) { // Default timeout values
|
||||
#ifdef WIN32
|
||||
timeout = -1; // For Windows, use -1 which appears to be specific to WinPCap and means "non-blocking mode"
|
||||
#else
|
||||
timeout = 3000; // For other platforms, use 3000ms as the timeout which should work for platforms like macOS
|
||||
#endif
|
||||
} else
|
||||
timeout = strtoul(timeoutstr,&end,10);
|
||||
// attempt to open it
|
||||
#ifdef WIN32
|
||||
if ( (adhandle= pcap_open(
|
||||
currentdev->name, // name of the device
|
||||
65536, // portion of the packet to capture
|
||||
// 65536 = whole packet
|
||||
PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode
|
||||
timeout, // read timeout
|
||||
NULL, // authentication on the remote machine
|
||||
errbuf // error buffer
|
||||
) ) == NULL)
|
||||
#else
|
||||
/*pcap_t *pcap_open_live(const char *device, int snaplen,
|
||||
int promisc, int to_ms, char *errbuf)*/
|
||||
if ( (adhandle= pcap_open_live(
|
||||
currentdev->name, // name of the device
|
||||
65536, // portion of the packet to capture
|
||||
// 65536 = whole packet
|
||||
true, // promiscuous mode
|
||||
timeout, // read timeout
|
||||
errbuf // error buffer
|
||||
) ) == NULL)
|
||||
|
||||
#endif
|
||||
{
|
||||
LOG_MSG("\nUnable to open the interface: %s.", errbuf);
|
||||
pcap_freealldevs(alldevs);
|
||||
return false;
|
||||
}
|
||||
pcap_freealldevs(alldevs);
|
||||
#ifndef WIN32
|
||||
pcap_setnonblock(adhandle,1,errbuf);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void PcapEthernetConnection::SendPacket(const uint8_t* packet, int len)
|
||||
{
|
||||
pcap_sendpacket(adhandle, packet, len);
|
||||
}
|
||||
|
||||
void PcapEthernetConnection::GetPackets(std::function<void(const uint8_t*, int)> callback)
|
||||
{
|
||||
int res;
|
||||
struct pcap_pkthdr *header;
|
||||
u_char *pkt_data;
|
||||
//#if 0
|
||||
while((res = pcap_next_ex( adhandle, &header, (const u_char **)&pkt_data)) > 0) {
|
||||
callback(pkt_data, header->len);
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
|
||||
#endif
|
55
src/misc/ethernet_pcap.h
Normal file
55
src/misc/ethernet_pcap.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef DOSBOX_ETHERNET_PCAP_H
|
||||
#define DOSBOX_ETHERNET_PCAP_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if C_PCAP
|
||||
|
||||
#include "ethernet.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define HAVE_REMOTE
|
||||
#endif
|
||||
|
||||
#include "support.h" /* Prevents snprintf conflict with pcap on Windows */
|
||||
#include "pcap.h"
|
||||
|
||||
/** A PCAP-based Ethernet connection
|
||||
* This backend uses a physical Ethernet device. All types of traffic
|
||||
* such as IPX, TCP, NetBIOS work over this interface.
|
||||
* This requires libpcap or WinPcap to be installed and your selected
|
||||
* network interface to support promiscious operation.
|
||||
*/
|
||||
class PcapEthernetConnection : public EthernetConnection {
|
||||
public:
|
||||
PcapEthernetConnection();
|
||||
~PcapEthernetConnection();
|
||||
bool Initialize();
|
||||
void SendPacket(const uint8_t* packet, int len);
|
||||
void GetPackets(std::function<void(const uint8_t*, int)> callback);
|
||||
|
||||
private:
|
||||
pcap_t* adhandle = 0; /*!< The pcap handle used for this device */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -1297,6 +1297,7 @@ copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</C
|
||||
<ClCompile Include="..\src\misc\cross.cpp" />
|
||||
<ClCompile Include="..\src\misc\ethernet.cpp" />
|
||||
<ClCompile Include="..\src\misc\messages.cpp" />
|
||||
<ClCompile Include="..\src\misc\ethernet_pcap.cpp" />
|
||||
<ClCompile Include="..\src\misc\programs.cpp" />
|
||||
<ClCompile Include="..\src\ints\qcow2_disk.cpp" />
|
||||
<ClCompile Include="..\src\misc\regionalloctracking.cpp" />
|
||||
@@ -1638,6 +1639,7 @@ copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</C
|
||||
<ClInclude Include="..\src\libs\mt32\TVA.h" />
|
||||
<ClInclude Include="..\src\libs\mt32\TVF.h" />
|
||||
<ClInclude Include="..\src\libs\mt32\TVP.h" />
|
||||
<ClInclude Include="..\src\misc\ethernet_pcap.h" />
|
||||
<ClInclude Include="..\src\output\direct3d\d3d_components.h" />
|
||||
<ClInclude Include="..\src\output\direct3d\direct3d.h" />
|
||||
<ClInclude Include="..\src\output\direct3d\hq2x_d3d.h" />
|
||||
@@ -1656,4 +1658,4 @@ copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</C
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@@ -618,6 +618,9 @@
|
||||
<ClCompile Include="..\src\misc\messages.cpp">
|
||||
<Filter>Sources\misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\misc\ethernet_pcap.cpp">
|
||||
<Filter>Sources\misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\misc\regionalloctracking.cpp">
|
||||
<Filter>Sources\misc</Filter>
|
||||
</ClCompile>
|
||||
@@ -1787,6 +1790,9 @@
|
||||
<ClInclude Include="..\src\libs\mt32\sha1\sha1.h">
|
||||
<Filter>Sources\libs\mt32\sha1</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\misc\ethernet_pcap.h">
|
||||
<Filter>Sources\misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\hardware\reSID\envelope.h">
|
||||
<Filter>Sources\hardware\reSID</Filter>
|
||||
</ClInclude>
|
||||
@@ -2411,4 +2417,4 @@
|
||||
<Filter>Sources</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
Reference in New Issue
Block a user