1
0
mirror of https://github.com/simh/simh.git synced 2026-01-13 23:35:57 +00:00

ETHER: Latest from 4.x master branch

This commit is contained in:
Mark Pizzolato 2021-01-17 11:19:53 -08:00
parent 79878eb6ed
commit c263d60a86

View File

@ -56,7 +56,7 @@
Supported/Tested Platforms:
Windows(NT,2K,XP,2K3,Vista,Win7) WinPcap V3.0+
Windows(NT,2K,XP,2K3,Vista,Win7) WinPcap-4.1.3 Npcap-V0.9994
Linux libpcap at least 0.9
OpenBSD,FreeBSD,NetBSD libpcap at least 0.9
MAC OS/X libpcap at least 0.9
@ -67,8 +67,11 @@
Compaq Tru64 Unix ??
VMS Alpha/Itanium VMS only, needs VMS libpcap
WinPcap is available from:
WinPcap is no longer developed or supported by was available from:
http://winpcap.polito.it/
Npcap is a complete replacement for systems running Windows7 and later
and is available from:
https://nmap.org/npcap
libpcap for VMS is available from:
http://simh.trailing-edge.com/sources/vms-pcap.zip
libpcap for other Unix platforms is available at:
@ -82,8 +85,9 @@
Current Version: http://www.tcpdump.org/daily/libpcap-current.tar.gz
Released Version: http://www.tcpdump.org/release/
When necessary (see NOTE above about vendor supplied libpcap),
we've gotten the tarball, unpacked, built and installed it with:
When absolutely necessary (see NOTE above about vendor supplied
libpcap), we've gotten the tarball, unpacked, built and installed
it with:
gzip -dc libpcap-current.tar.gz | tar xvf -
cd libpcap-directory-name
./configure
@ -271,7 +275,7 @@
the registry on Windows XP x64
10-Jul-06 RMS Fixed linux conditionalization (from Chaskiel Grundman)
02-Jun-06 JDB Fixed compiler warning for incompatible sscanf parameter
15-Dec-05 DTH Patched eth_host_devices [remove non-ethernet devices]
15-Dec-05 DTH Patched eth_host_pcap_devices [remove non-ethernet devices]
(from Mark Pizzolato and Galen Tackett, 08-Jun-05)
Patched eth_open [tun fix](from Antal Ritter, 06-Oct-05)
30-Nov-05 DTH Added option to regenerate CRC on received packets; some
@ -377,9 +381,8 @@
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
/* Internal routines - forward declarations */
/* Internal routine - forward declaration */
static int _eth_get_system_id (char *buf, size_t buf_size);
static int _eth_devices (int max, ETH_LIST* dev); /* get ethernet devices on host */
/*============================================================================*/
/* OS-independant ethernet routines */
@ -658,88 +661,6 @@ void eth_packet_trace_detail(ETH_DEV* dev, const uint8 *msg, int len, const char
eth_packet_trace_ex(dev, msg, len, txt, 1 , dev->dbit);
}
static const char* _eth_getname(int number, char* name, char *desc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
if ((number < 0) || (count <= number))
return NULL;
if (list[number].eth_api != ETH_API_PCAP) {
sim_printf ("Eth: Pcap capable device not found. You may need to run as root\n");
return NULL;
}
strcpy(name, list[number].name);
strcpy(desc, list[number].desc);
return name;
}
const char* eth_getname_bydesc(const char* desc, char* name, char *ndesc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
int i;
size_t j=strlen(desc);
for (i=0; i<count; i++) {
int found = 1;
size_t k = strlen(list[i].desc);
if (j != k) continue;
for (k=0; k<j; k++)
if (tolower(list[i].desc[k]) != tolower(desc[k]))
found = 0;
if (found == 0) continue;
/* found a case-insensitive description match */
strcpy(name, list[i].name);
strcpy(ndesc, list[i].desc);
return name;
}
/* not found */
return NULL;
}
char* eth_getname_byname(const char* name, char* temp, char *desc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
size_t n;
int i, found;
found = 0;
n = strlen(name);
for (i=0; i<count && !found; i++) {
if ((n == strlen(list[i].name)) &&
(strncasecmp(name, list[i].name, n) == 0)) {
found = 1;
strcpy(temp, list[i].name); /* only case might be different */
strcpy(desc, list[i].desc);
}
}
return (found ? temp : NULL);
}
char* eth_getdesc_byname(char* name, char* temp)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
size_t n;
int i, found;
found = 0;
n = strlen(name);
for (i=0; i<count && !found; i++) {
if ((n == strlen(list[i].name)) &&
(strncasecmp(name, list[i].name, n) == 0)) {
found = 1;
strcpy(temp, list[i].desc);
}
}
return (found ? temp : NULL);
}
void eth_zero(ETH_DEV* dev)
{
/* set all members to NULL OR 0 */
@ -747,74 +668,6 @@ void eth_zero(ETH_DEV* dev)
dev->reflections = -1; /* not established yet */
}
static char* (*p_pcap_lib_version) (void);
static ETH_DEV **eth_open_devices = NULL;
static int eth_open_device_count = 0;
#if defined (USE_NETWORK) || defined (USE_SHARED)
static void _eth_add_to_open_list (ETH_DEV* dev)
{
eth_open_devices = (ETH_DEV**)realloc(eth_open_devices, (eth_open_device_count+1)*sizeof(*eth_open_devices));
eth_open_devices[eth_open_device_count++] = dev;
}
static void _eth_remove_from_open_list (ETH_DEV* dev)
{
int i, j;
for (i=0; i<eth_open_device_count; ++i)
if (eth_open_devices[i] == dev) {
for (j=i+1; j<eth_open_device_count; ++j)
eth_open_devices[j-1] = eth_open_devices[j];
--eth_open_device_count;
break;
}
}
#endif
t_stat eth_show (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int number;
number = _eth_devices(ETH_MAX_DEVICE, list);
fprintf(st, "ETH devices:\n");
if (number == -1)
fprintf(st, " network support not available in simulator\n");
else
if (number == 0)
fprintf(st, " no network devices are available\n");
else {
size_t min, len;
int i;
for (i=0, min=0; i<number; i++)
if ((len = strlen(list[i].name)) > min) min = len;
for (i=0; i<number; i++)
fprintf(st," eth%d\t%-*s (%s)\n", i, (int)min, list[i].name, list[i].desc);
}
if (eth_open_device_count) {
int i;
char desc[ETH_DEV_DESC_MAX], *d;
fprintf(st,"Open ETH Devices:\n");
for (i=0; i<eth_open_device_count; i++) {
d = eth_getdesc_byname(eth_open_devices[i]->name, desc);
if (d)
fprintf(st, " %-7s%s (%s)\n", eth_open_devices[i]->dptr->name, eth_open_devices[i]->dptr->units[0].filename, d);
else
fprintf(st, " %-7s%s\n", eth_open_devices[i]->dptr->name, eth_open_devices[i]->dptr->units[0].filename);
eth_show_dev (st, eth_open_devices[i]);
}
}
return SCPE_OK;
}
t_stat eth_show_devices (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char *desc)
{
return eth_show (st, uptr, val, NULL);
}
t_stat ethq_init(ETH_QUE* que, int max)
{
/* create dynamic queue if it does not exist */
@ -921,6 +774,159 @@ void ethq_insert(ETH_QUE* que, int32 type, ETH_PACK* pack, int32 status)
ethq_insert_data(que, type, pack->oversize ? pack->oversize : pack->msg, pack->used, pack->len, pack->crc_len, NULL, status);
}
t_stat eth_show_devices (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char *desc)
{
return eth_show (st, uptr, val, NULL);
}
#if defined (USE_NETWORK) || defined (USE_SHARED)
/* Internal routine - forward declaration */
static int _eth_devices (int max, ETH_LIST* dev); /* get ethernet devices on host */
static const char* _eth_getname(int number, char* name, char *desc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
if ((number < 0) || (count <= number))
return NULL;
if (list[number].eth_api != ETH_API_PCAP) {
sim_printf ("Eth: Pcap capable device not found. You may need to run as root\n");
return NULL;
}
strcpy(name, list[number].name);
strcpy(desc, list[number].desc);
return name;
}
const char* eth_getname_bydesc(const char* desc, char* name, char *ndesc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
int i;
size_t j=strlen(desc);
for (i=0; i<count; i++) {
int found = 1;
size_t k = strlen(list[i].desc);
if (j != k) continue;
for (k=0; k<j; k++)
if (tolower(list[i].desc[k]) != tolower(desc[k]))
found = 0;
if (found == 0) continue;
/* found a case-insensitive description match */
strcpy(name, list[i].name);
strcpy(ndesc, list[i].desc);
return name;
}
/* not found */
return NULL;
}
char* eth_getname_byname(const char* name, char* temp, char *desc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
size_t n;
int i, found;
found = 0;
n = strlen(name);
for (i=0; i<count && !found; i++) {
if ((n == strlen(list[i].name)) &&
(strncasecmp(name, list[i].name, n) == 0)) {
found = 1;
strcpy(temp, list[i].name); /* only case might be different */
strcpy(desc, list[i].desc);
}
}
return (found ? temp : NULL);
}
char* eth_getdesc_byname(char* name, char* temp)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
size_t n;
int i, found;
found = 0;
n = strlen(name);
for (i=0; i<count && !found; i++) {
if ((n == strlen(list[i].name)) &&
(strncasecmp(name, list[i].name, n) == 0)) {
found = 1;
strcpy(temp, list[i].desc);
}
}
return (found ? temp : NULL);
}
static ETH_DEV **eth_open_devices = NULL;
static int eth_open_device_count = 0;
static char* (*p_pcap_lib_version) (void);
static void _eth_add_to_open_list (ETH_DEV* dev)
{
eth_open_devices = (ETH_DEV**)realloc(eth_open_devices, (eth_open_device_count+1)*sizeof(*eth_open_devices));
eth_open_devices[eth_open_device_count++] = dev;
}
static void _eth_remove_from_open_list (ETH_DEV* dev)
{
int i, j;
for (i=0; i<eth_open_device_count; ++i)
if (eth_open_devices[i] == dev) {
for (j=i+1; j<eth_open_device_count; ++j)
eth_open_devices[j-1] = eth_open_devices[j];
--eth_open_device_count;
break;
}
}
t_stat eth_show (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int number;
number = _eth_devices(ETH_MAX_DEVICE, list);
fprintf(st, "ETH devices:\n");
if (number == -1)
fprintf(st, " network support not available in simulator\n");
else
if (number == 0)
fprintf(st, " no network devices are available\n");
else {
size_t min, len;
int i;
for (i=0, min=0; i<number; i++)
if ((len = strlen(list[i].name)) > min) min = len;
for (i=0; i<number; i++)
fprintf(st," eth%d\t%-*s (%s)\n", i, (int)min, list[i].name, list[i].desc);
}
if (eth_open_device_count) {
int i;
char desc[ETH_DEV_DESC_MAX], *d;
fprintf(st,"Open ETH Devices:\n");
for (i=0; i<eth_open_device_count; i++) {
d = eth_getdesc_byname(eth_open_devices[i]->name, desc);
if (d)
fprintf(st, " %-7s%s (%s)\n", eth_open_devices[i]->dptr->name, eth_open_devices[i]->dptr->units[0].filename, d);
else
fprintf(st, " %-7s%s\n", eth_open_devices[i]->dptr->name, eth_open_devices[i]->dptr->units[0].filename);
eth_show_dev (st, eth_open_devices[i]);
}
}
return SCPE_OK;
}
#endif
/*============================================================================*/
/* Non-implemented versions */
/*============================================================================*/
@ -957,12 +963,16 @@ t_stat eth_filter (ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
ETH_BOOL all_multicast, ETH_BOOL promiscuous, ETH_MULTIHASH* const hash)
{return SCPE_NOFNC;}
int _eth_devices (int max, ETH_LIST* dev)
{return -1;}
const char *eth_version (void)
{return NULL;}
void eth_show_dev (FILE* st, ETH_DEV* dev)
{}
t_stat eth_show (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
{
fprintf(st, "ETH devices:\n");
fprintf(st, " network support not available in simulator\n");
return SCPE_OK;
}
static int _eth_get_system_id (char *buf, size_t buf_size)
{memset (buf, 0, buf_size); return 0;}
t_stat sim_ether_test (DEVICE *dptr)
@ -1015,6 +1025,172 @@ typedef void * pcap_t; /* Pseudo Type to avoid compiler errors */
#define DLT_EN10MB 1 /* Dummy Value to avoid compiler errors */
#endif /* HAVE_PCAP_NETWORK */
/*
The libpcap provided API pcap_findalldevs() on most platforms, will
leverage the getifaddrs() API if it is available in preference to
alternate platform specific methods of determining the interface list.
A limitation of getifaddrs() is that it returns only interfaces which
have associated addresses. This may not include all of the interesting
interfaces that we are interested in since a host may have dedicated
interfaces for a simulator, which is otherwise unused by the host.
One could hand craft the the build of libpcap to specifically use
alternate methods to implement pcap_findalldevs(). However, this can
get tricky, and would then result in a sort of deviant libpcap.
This routine exists to allow platform specific code to validate and/or
extend the set of available interfaces to include any that are not
returned by pcap_findalldevs.
*/
static int eth_host_pcap_devices(int used, int max, ETH_LIST* list)
{
pcap_t* conn = NULL;
int i, j, datalink = 0;
for (i=0; i<used; ++i) {
/* Cull any non-ethernet interface types */
#if defined(HAVE_PCAP_NETWORK)
char errbuf[PCAP_ERRBUF_SIZE];
conn = pcap_open_live(list[i].name, ETH_MAX_PACKET, ETH_PROMISC, PCAP_READ_TIMEOUT, errbuf);
if (NULL != conn)
datalink = pcap_datalink(conn), pcap_close(conn);
list[i].eth_api = ETH_API_PCAP;
if ((NULL == conn) || (datalink != DLT_EN10MB)) {
for (j=i; j<used-1; ++j)
list[j] = list[j+1];
--used;
--i;
}
#endif
} /* for */
#if defined(_WIN32)
/* replace device description with user-defined adapter name (if defined) */
for (i=0; i<used; i++) {
char regkey[2048];
unsigned char regval[2048];
LONG status;
DWORD reglen, regtype;
HKEY reghnd;
/* These registry keys don't seem to exist for all devices, so we simply ignore errors. */
/* Windows XP x64 registry uses wide characters by default,
so we force use of narrow characters by using the 'A'(ANSI) version of RegOpenKeyEx.
This could cause some problems later, if this code is internationalized. Ideally,
the pcap lookup will return wide characters, and we should use them to build a wide
registry key, rather than hardcoding the string as we do here. */
if (list[i].name[strlen( "\\Device\\NPF_" )] == '{') {
sprintf( regkey, "SYSTEM\\CurrentControlSet\\Control\\Network\\"
"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", list[i].name+
strlen( "\\Device\\NPF_" ) );
if ((status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, regkey, 0, KEY_QUERY_VALUE, &reghnd)) != ERROR_SUCCESS)
continue;
reglen = sizeof(regval);
/* look for user-defined adapter name, bail if not found */
/* same comment about Windows XP x64 (above) using RegQueryValueEx */
if ((status = RegQueryValueExA (reghnd, "Name", NULL, &regtype, regval, &reglen)) != ERROR_SUCCESS) {
RegCloseKey (reghnd);
continue;
}
/* make sure value is the right type, bail if not acceptable */
if ((regtype != REG_SZ) || (reglen > sizeof(regval))) {
RegCloseKey (reghnd);
continue;
}
/* registry value seems OK, finish up and replace description */
RegCloseKey (reghnd );
sprintf (list[i].desc, "%s", regval);
}
} /* for */
#endif
return used;
}
static int _eth_devices(int max, ETH_LIST* list)
{
int used = 0;
char errbuf[PCAP_ERRBUF_SIZE] = "";
#ifndef DONT_USE_PCAP_FINDALLDEVS
pcap_if_t* alldevs;
pcap_if_t* dev;
memset(list, 0, max*sizeof(*list));
errbuf[0] = '\0';
/* retrieve the device list */
if (pcap_findalldevs(&alldevs, errbuf) == -1) {
if (errbuf[0])
sim_printf ("Eth: %s\n", errbuf);
}
else {
/* copy device list into the passed structure */
for (used=0, dev=alldevs; dev && (used < max); dev=dev->next, ++used) {
if ((dev->flags & PCAP_IF_LOOPBACK) || (!strcmp("any", dev->name)))
continue;
strlcpy(list[used].name, dev->name, sizeof(list[used].name));
if (dev->description)
strlcpy(list[used].desc, dev->description, sizeof(list[used].desc));
else
strlcpy(list[used].desc, "No description available", sizeof(list[used].desc));
}
/* free device list */
pcap_freealldevs(alldevs);
}
#endif
/* Add any host specific devices and/or validate those already found */
used = eth_host_pcap_devices(used, max, list);
/* If no devices were found and an error message was left in the buffer, display it */
if ((used == 0) && (errbuf[0])) {
sim_printf ("Eth: pcap_findalldevs warning: %s\n", errbuf);
}
#ifdef HAVE_TAP_NETWORK
if (used < max) {
#if defined(__OpenBSD__)
sprintf(list[used].name, "%s", "tap:tunN");
#else
sprintf(list[used].name, "%s", "tap:tapN");
#endif
sprintf(list[used].desc, "%s", "Integrated Tun/Tap support");
list[used].eth_api = ETH_API_TAP;
++used;
}
#endif
#ifdef HAVE_VDE_NETWORK
if (used < max) {
sprintf(list[used].name, "%s", "vde:device{:switch-port-number}");
sprintf(list[used].desc, "%s", "Integrated VDE support");
list[used].eth_api = ETH_API_VDE;
++used;
}
#endif
#ifdef HAVE_SLIRP_NETWORK
if (used < max) {
sprintf(list[used].name, "%s", "nat:{optional-nat-parameters}");
sprintf(list[used].desc, "%s", "Integrated NAT (SLiRP) support");
list[used].eth_api = ETH_API_NAT;
++used;
}
#endif
if (used < max) {
sprintf(list[used].name, "%s", "udp:sourceport:remotehost:remoteport");
sprintf(list[used].desc, "%s", "Integrated UDP bridge support");
list[used].eth_api = ETH_API_UDP;
++used;
}
/* return device count */
return used;
}
#ifdef HAVE_TAP_NETWORK
#if defined(__linux) || defined(__linux__)
#include <sys/ioctl.h>
@ -1672,18 +1848,24 @@ static int _eth_get_system_id (char *buf, size_t buf_size)
static int _eth_get_system_id (char *buf, size_t buf_size)
{
FILE *f;
t_bool popened = FALSE;
memset (buf, 0, buf_size);
if (buf_size < 37)
return -1;
if ((f = fopen ("/etc/machine-id", "r")) == NULL)
if ((f = fopen ("/etc/machine-id", "r")) == NULL) {
f = popen ("hostname", "r");
popened = TRUE;
}
if (f) {
size_t read_size;
read_size = fread (buf, 1, buf_size - 1, f);
buf[read_size] = '\0';
fclose (f);
if (popened)
pclose (f);
else
fclose (f);
}
while ((strlen (buf) > 0) && sim_isspace(buf[strlen (buf) - 1]))
buf[strlen (buf) - 1] = '\0';
@ -1904,7 +2086,7 @@ static void *
_eth_writer(void *arg)
{
ETH_DEV* volatile dev = (ETH_DEV*)arg;
ETH_WRITE_REQUEST *request;
ETH_WRITE_REQUEST *request = NULL;
/* Boost Priority for this I/O thread vs the CPU instruction execution
thread which in general won't be readily yielding the processor when
@ -3436,7 +3618,7 @@ response.msg[15] = (offset >> 8) & 0xFF;
/* send response packet */
eth_write(dev, &response, NULL);
eth_packet_trace(dev, response.msg, response.len, ((function == 1) ? "loopbackreply" : "loopbackforward"));
eth_packet_trace(dev, response.msg, response.len, "loopbackforward");
++dev->loopback_packets_processed;
@ -3883,6 +4065,9 @@ if (dev->dptr->dctrl & dev->dbit) {
sim_debug(dev->dbit, dev->dptr, "Promiscuous\n");
}
}
#ifdef USE_READER_THREAD
pthread_mutex_lock (&dev->self_lock);
#endif
/* Set the desired physical address */
memset(dev->physical_addr, 0, sizeof(ETH_MAC));
dev->loopback_self_sent = 0;
@ -3896,6 +4081,9 @@ for (i = 0; i < addr_count; i++) {
break;
}
}
#ifdef USE_READER_THREAD
pthread_mutex_unlock (&dev->self_lock);
#endif
/* setup BPF filters and other fields to minimize packet delivery */
eth_bpf_filter (dev, dev->addr_count, dev->filter_address,
@ -3971,171 +4159,6 @@ if (dev->eth_api == ETH_API_PCAP) {
return SCPE_OK;
}
/*
The libpcap provided API pcap_findalldevs() on most platforms, will
leverage the getifaddrs() API if it is available in preference to
alternate platform specific methods of determining the interface list.
A limitation of getifaddrs() is that it returns only interfaces which
have associated addresses. This may not include all of the interesting
interfaces that we are interested in since a host may have dedicated
interfaces for a simulator, which is otherwise unused by the host.
One could hand craft the the build of libpcap to specifically use
alternate methods to implement pcap_findalldevs(). However, this can
get tricky, and would then result in a sort of deviant libpcap.
This routine exists to allow platform specific code to validate and/or
extend the set of available interfaces to include any that are not
returned by pcap_findalldevs.
*/
static int eth_host_devices(int used, int max, ETH_LIST* list)
{
pcap_t* conn = NULL;
int i, j, datalink = 0;
for (i=0; i<used; ++i) {
/* Cull any non-ethernet interface types */
#if defined(HAVE_PCAP_NETWORK)
char errbuf[PCAP_ERRBUF_SIZE];
conn = pcap_open_live(list[i].name, ETH_MAX_PACKET, ETH_PROMISC, PCAP_READ_TIMEOUT, errbuf);
if (NULL != conn)
datalink = pcap_datalink(conn), pcap_close(conn);
list[i].eth_api = ETH_API_PCAP;
#endif
if ((NULL == conn) || (datalink != DLT_EN10MB)) {
for (j=i; j<used-1; ++j)
list[j] = list[j+1];
--used;
--i;
}
} /* for */
#if defined(_WIN32)
/* replace device description with user-defined adapter name (if defined) */
for (i=0; i<used; i++) {
char regkey[2048];
unsigned char regval[2048];
LONG status;
DWORD reglen, regtype;
HKEY reghnd;
/* These registry keys don't seem to exist for all devices, so we simply ignore errors. */
/* Windows XP x64 registry uses wide characters by default,
so we force use of narrow characters by using the 'A'(ANSI) version of RegOpenKeyEx.
This could cause some problems later, if this code is internationalized. Ideally,
the pcap lookup will return wide characters, and we should use them to build a wide
registry key, rather than hardcoding the string as we do here. */
if (list[i].name[strlen( "\\Device\\NPF_" )] == '{') {
sprintf( regkey, "SYSTEM\\CurrentControlSet\\Control\\Network\\"
"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", list[i].name+
strlen( "\\Device\\NPF_" ) );
if ((status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, regkey, 0, KEY_QUERY_VALUE, &reghnd)) != ERROR_SUCCESS)
continue;
reglen = sizeof(regval);
/* look for user-defined adapter name, bail if not found */
/* same comment about Windows XP x64 (above) using RegQueryValueEx */
if ((status = RegQueryValueExA (reghnd, "Name", NULL, &regtype, regval, &reglen)) != ERROR_SUCCESS) {
RegCloseKey (reghnd);
continue;
}
/* make sure value is the right type, bail if not acceptable */
if ((regtype != REG_SZ) || (reglen > sizeof(regval))) {
RegCloseKey (reghnd);
continue;
}
/* registry value seems OK, finish up and replace description */
RegCloseKey (reghnd );
sprintf (list[i].desc, "%s", regval);
}
} /* for */
#endif
#ifdef HAVE_TAP_NETWORK
if (used < max) {
#if defined(__OpenBSD__)
sprintf(list[used].name, "%s", "tap:tunN");
#else
sprintf(list[used].name, "%s", "tap:tapN");
#endif
sprintf(list[used].desc, "%s", "Integrated Tun/Tap support");
list[used].eth_api = ETH_API_TAP;
++used;
}
#endif
#ifdef HAVE_VDE_NETWORK
if (used < max) {
sprintf(list[used].name, "%s", "vde:device{:switch-port-number}");
sprintf(list[used].desc, "%s", "Integrated VDE support");
list[used].eth_api = ETH_API_VDE;
++used;
}
#endif
#ifdef HAVE_SLIRP_NETWORK
if (used < max) {
sprintf(list[used].name, "%s", "nat:{optional-nat-parameters}");
sprintf(list[used].desc, "%s", "Integrated NAT (SLiRP) support");
list[used].eth_api = ETH_API_NAT;
++used;
}
#endif
if (used < max) {
sprintf(list[used].name, "%s", "udp:sourceport:remotehost:remoteport");
sprintf(list[used].desc, "%s", "Integrated UDP bridge support");
list[used].eth_api = ETH_API_UDP;
++used;
}
return used;
}
static int _eth_devices(int max, ETH_LIST* list)
{
int i = 0;
char errbuf[PCAP_ERRBUF_SIZE] = "";
#ifndef DONT_USE_PCAP_FINDALLDEVS
pcap_if_t* alldevs;
pcap_if_t* dev;
memset(list, 0, max*sizeof(*list));
errbuf[0] = '\0';
/* retrieve the device list */
if (pcap_findalldevs(&alldevs, errbuf) == -1) {
if (errbuf[0])
sim_printf ("Eth: %s\n", errbuf);
}
else {
/* copy device list into the passed structure */
for (i=0, dev=alldevs; dev && (i < max); dev=dev->next, ++i) {
if ((dev->flags & PCAP_IF_LOOPBACK) || (!strcmp("any", dev->name))) continue;
strlcpy(list[i].name, dev->name, sizeof(list[i].name));
if (dev->description)
strlcpy(list[i].desc, dev->description, sizeof(list[i].desc));
else
strlcpy(list[i].desc, "No description available", sizeof(list[i].desc));
}
/* free device list */
pcap_freealldevs(alldevs);
}
#endif
/* Add any host specific devices and/or validate those already found */
i = eth_host_devices(i, max, list);
/* If no devices were found and an error message was left in the buffer, display it */
if ((i == 0) && (errbuf[0])) {
sim_printf ("Eth: pcap_findalldevs warning: %s\n", errbuf);
}
/* return device count */
return i;
}
void eth_show_dev (FILE *st, ETH_DEV* dev)
{
fprintf(st, "Ethernet Device:\n");
@ -4262,7 +4285,6 @@ ETH_MAC filter_address[3] = {
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
};
int addr_count;
ETH_MAC physical_addr = {0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
ETH_MAC host_nic_phy_hw_addr = {0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
ETH_MAC *host_phy_addr_list[2] = {&host_nic_phy_hw_addr, NULL};
int host_phy_addr_listindex;