ETHER: Reorg for warning free build with and without Ethernet support
This commit is contained in:
parent
2f38b5f779
commit
bcaf577d21
1 changed files with 326 additions and 319 deletions
645
sim_ether.c
645
sim_ether.c
|
@ -381,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 */
|
||||
|
@ -662,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 */
|
||||
|
@ -751,74 +668,6 @@ void eth_zero(ETH_DEV* dev)
|
|||
dev->reflections = -1; /* not established yet */
|
||||
}
|
||||
|
||||
static ETH_DEV **eth_open_devices = NULL;
|
||||
static int eth_open_device_count = 0;
|
||||
|
||||
#if defined (USE_NETWORK) || defined (USE_SHARED)
|
||||
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;
|
||||
}
|
||||
}
|
||||
#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 */
|
||||
|
@ -925,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 */
|
||||
/*============================================================================*/
|
||||
|
@ -961,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)
|
||||
|
@ -1009,6 +1015,172 @@ const char *eth_capabilities(void)
|
|||
|
||||
#include <pcap.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
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, ®hnd)) != 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, ®type, regval, ®len)) != 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;
|
||||
}
|
||||
|
||||
#else
|
||||
struct pcap_pkthdr {
|
||||
uint32 caplen; /* length of portion present */
|
||||
|
@ -3987,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, ®hnd)) != 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, ®type, regval, ®len)) != 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");
|
||||
|
|
Loading…
Add table
Reference in a new issue