mirror of
https://github.com/LIV2/WinUAE.git
synced 2025-12-06 00:12:52 +00:00
294 lines
6.0 KiB
C++
294 lines
6.0 KiB
C++
|
|
#include "sysconfig.h"
|
|
#include "sysdeps.h"
|
|
|
|
#include "ethernet.h"
|
|
#ifdef _WIN32
|
|
#include "win32_uaenet.h"
|
|
#endif
|
|
#include "threaddep/thread.h"
|
|
#include "options.h"
|
|
#include "traps.h"
|
|
#include "sana2.h"
|
|
#include "uae/slirp.h"
|
|
#include "gui.h"
|
|
#include "rommgr.h"
|
|
|
|
#ifndef HAVE_INET_ATON
|
|
static int inet_aton(const char *cp, struct in_addr *ia)
|
|
{
|
|
uint32_t addr = inet_addr(cp);
|
|
if (addr == 0xffffffff)
|
|
return 0;
|
|
ia->s_addr = addr;
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
struct ethernet_data
|
|
{
|
|
ethernet_gotfunc *gotfunc;
|
|
ethernet_getfunc *getfunc;
|
|
void *userdata;
|
|
};
|
|
|
|
#define SLIRP_PORT_OFFSET 0
|
|
|
|
static const int slirp_ports[] = { 21, 22, 23, 80, 0 };
|
|
|
|
static struct ethernet_data *slirp_data;
|
|
static bool slirp_inited;
|
|
uae_sem_t slirp_sem1, slirp_sem2;
|
|
static int netmode;
|
|
|
|
static struct netdriverdata slirpd =
|
|
{
|
|
UAENET_SLIRP,
|
|
_T("slirp"), _T("SLIRP User Mode NAT"),
|
|
1500,
|
|
{ 0x00, 0x00, 0x00, 50, 51, 52 },
|
|
{ 0x00, 0x00, 0x00, 50, 51, 52 },
|
|
1
|
|
};
|
|
static struct netdriverdata slirpd2 =
|
|
{
|
|
UAENET_SLIRP_INBOUND,
|
|
_T("slirp_inbound"), _T("SLIRP + Open ports (21-23,80)"),
|
|
1500,
|
|
{ 0x00, 0x00, 0x00, 50, 51, 52 },
|
|
{ 0x00, 0x00, 0x00, 50, 51, 52 },
|
|
1
|
|
};
|
|
|
|
void slirp_output (const uint8_t *pkt, int pkt_len)
|
|
{
|
|
if (!slirp_data)
|
|
return;
|
|
gui_flicker_led(LED_NET, 0, gui_data.net | 1);
|
|
uae_sem_wait (&slirp_sem1);
|
|
slirp_data->gotfunc (slirp_data->userdata, pkt, pkt_len);
|
|
uae_sem_post (&slirp_sem1);
|
|
}
|
|
|
|
void ethernet_trigger (struct netdriverdata *ndd, void *vsd)
|
|
{
|
|
if (!ndd)
|
|
return;
|
|
gui_flicker_led(LED_NET, 0, gui_data.net | 2);
|
|
switch (ndd->type)
|
|
{
|
|
case UAENET_SLIRP:
|
|
case UAENET_SLIRP_INBOUND:
|
|
{
|
|
struct ethernet_data *ed = (struct ethernet_data*)vsd;
|
|
if (slirp_data) {
|
|
uae_u8 pkt[4000];
|
|
int len = sizeof pkt;
|
|
int v;
|
|
uae_sem_wait (&slirp_sem1);
|
|
v = slirp_data->getfunc(ed->userdata, pkt, &len);
|
|
uae_sem_post (&slirp_sem1);
|
|
if (v) {
|
|
uae_sem_wait (&slirp_sem2);
|
|
uae_slirp_input(pkt, len);
|
|
uae_sem_post (&slirp_sem2);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
#ifdef WITH_UAENET_PCAP
|
|
case UAENET_PCAP:
|
|
uaenet_trigger (vsd);
|
|
return;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
int ethernet_open (struct netdriverdata *ndd, void *vsd, void *user, ethernet_gotfunc *gotfunc, ethernet_getfunc *getfunc, int promiscuous, const uae_u8 *mac)
|
|
{
|
|
switch (ndd->type)
|
|
{
|
|
case UAENET_SLIRP:
|
|
case UAENET_SLIRP_INBOUND:
|
|
{
|
|
struct ethernet_data *ed = (struct ethernet_data*)vsd;
|
|
ed->gotfunc = gotfunc;
|
|
ed->getfunc = getfunc;
|
|
ed->userdata = user;
|
|
slirp_data = ed;
|
|
uae_sem_init (&slirp_sem1, 0, 1);
|
|
uae_sem_init (&slirp_sem2, 0, 1);
|
|
uae_slirp_init();
|
|
for (int i = 0; i < MAX_SLIRP_REDIRS; i++) {
|
|
struct slirp_redir *sr = &currprefs.slirp_redirs[i];
|
|
if (sr->proto) {
|
|
struct in_addr a;
|
|
if (sr->srcport == 0) {
|
|
inet_aton("10.0.2.15", &a);
|
|
uae_slirp_redir (0, sr->dstport, a, sr->dstport);
|
|
} else {
|
|
#ifdef HAVE_STRUCT_IN_ADDR_S_UN
|
|
a.S_un.S_addr = sr->addr;
|
|
#else
|
|
a.s_addr = sr->addr;
|
|
#endif
|
|
uae_slirp_redir (sr->proto == 1 ? 0 : 1, sr->dstport, a, sr->srcport);
|
|
}
|
|
}
|
|
}
|
|
if (ndd->type == UAENET_SLIRP_INBOUND) {
|
|
struct in_addr a;
|
|
inet_aton("10.0.2.15", &a);
|
|
for (int i = 0; slirp_ports[i]; i++) {
|
|
int port = slirp_ports[i];
|
|
int j;
|
|
for (j = 0; j < MAX_SLIRP_REDIRS; j++) {
|
|
struct slirp_redir *sr = &currprefs.slirp_redirs[j];
|
|
if (sr->proto && sr->dstport == port)
|
|
break;
|
|
}
|
|
if (j == MAX_SLIRP_REDIRS)
|
|
uae_slirp_redir (0, port + SLIRP_PORT_OFFSET, a, port);
|
|
}
|
|
}
|
|
netmode = ndd->type;
|
|
uae_slirp_start ();
|
|
}
|
|
return 1;
|
|
#ifdef WITH_UAENET_PCAP
|
|
case UAENET_PCAP:
|
|
if (uaenet_open (vsd, ndd, user, gotfunc, getfunc, promiscuous, mac)) {
|
|
netmode = ndd->type;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
#endif
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ethernet_close (struct netdriverdata *ndd, void *vsd)
|
|
{
|
|
if (!ndd)
|
|
return;
|
|
switch (ndd->type)
|
|
{
|
|
case UAENET_SLIRP:
|
|
case UAENET_SLIRP_INBOUND:
|
|
if (slirp_data) {
|
|
slirp_data = NULL;
|
|
uae_slirp_end ();
|
|
uae_slirp_cleanup ();
|
|
uae_sem_destroy (&slirp_sem1);
|
|
uae_sem_destroy (&slirp_sem2);
|
|
}
|
|
return;
|
|
#ifdef WITH_UAENET_PCAP
|
|
case UAENET_PCAP:
|
|
return uaenet_close (vsd);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void ethernet_enumerate_free (void)
|
|
{
|
|
#ifdef WITH_UAENET_PCAP
|
|
uaenet_enumerate_free ();
|
|
#endif
|
|
}
|
|
|
|
bool ethernet_enumerate (struct netdriverdata **nddp, int romtype)
|
|
{
|
|
int j;
|
|
struct netdriverdata *nd;
|
|
const TCHAR *name = NULL;
|
|
|
|
if (romtype) {
|
|
struct romconfig *rc = get_device_romconfig(&currprefs, romtype, 0);
|
|
name = ethernet_getselectionname(rc ? rc->device_settings : 0);
|
|
}
|
|
|
|
gui_flicker_led(LED_NET, 0, 0);
|
|
if (name) {
|
|
netmode = 0;
|
|
*nddp = NULL;
|
|
if (!_tcsicmp (slirpd.name, name))
|
|
*nddp = &slirpd;
|
|
if (!_tcsicmp (slirpd2.name, name))
|
|
*nddp = &slirpd2;
|
|
#ifdef WITH_UAENET_PCAP
|
|
if (*nddp == NULL)
|
|
*nddp = uaenet_enumerate (name);
|
|
#endif
|
|
if (*nddp) {
|
|
netmode = (*nddp)->type;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
j = 0;
|
|
nddp[j++] = &slirpd;
|
|
nddp[j++] = &slirpd2;
|
|
#ifdef WITH_UAENET_PCAP
|
|
nd = uaenet_enumerate (NULL);
|
|
if (nd) {
|
|
int last = MAX_TOTAL_NET_DEVICES - 1 - j;
|
|
for (int i = 0; i < last; i++) {
|
|
if (nd[i].active)
|
|
nddp[j++] = &nd[i];
|
|
}
|
|
}
|
|
#endif
|
|
nddp[j] = NULL;
|
|
return true;
|
|
}
|
|
|
|
void ethernet_close_driver (struct netdriverdata *ndd)
|
|
{
|
|
switch (ndd->type)
|
|
{
|
|
case UAENET_SLIRP:
|
|
case UAENET_SLIRP_INBOUND:
|
|
return;
|
|
#ifdef WITH_UAENET_PCAP
|
|
case UAENET_PCAP:
|
|
return uaenet_close_driver (ndd);
|
|
#endif
|
|
}
|
|
netmode = 0;
|
|
}
|
|
|
|
int ethernet_getdatalenght (struct netdriverdata *ndd)
|
|
{
|
|
switch (ndd->type)
|
|
{
|
|
case UAENET_SLIRP:
|
|
case UAENET_SLIRP_INBOUND:
|
|
return sizeof (struct ethernet_data);
|
|
#ifdef WITH_UAENET_PCAP
|
|
case UAENET_PCAP:
|
|
return uaenet_getdatalenght ();
|
|
#endif
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool ethernet_getmac(uae_u8 *m, const TCHAR *mac)
|
|
{
|
|
if (!mac)
|
|
return false;
|
|
if (_tcslen(mac) != 3 * 5 + 2)
|
|
return false;
|
|
for (int i = 0; i < 6; i++) {
|
|
TCHAR *endptr;
|
|
if (mac[0] == 0 || mac[1] == 0)
|
|
return false;
|
|
if (i < 5 && (mac[2] != '.' && mac[2] != ':'))
|
|
return false;
|
|
uae_u8 v = (uae_u8)_tcstol(mac, &endptr, 16);
|
|
mac += 3;
|
|
m[i] = v;
|
|
}
|
|
return true;
|
|
}
|