mirror of
https://github.com/open-simh/simh.git
synced 2026-02-01 14:32:35 +00:00
ETH_MAC indirection erratum
Pervasive misuse of "ETH_MAC *" (a pointer to an ETH_MAC, aka a 6
element unsigned char array) when a simple "ETH_MAC" is correct. The
best example of this was eth_mac_fmt() in sim_ether.c with the following
prototype:
t_stat eth_mac_fmt (ETH_MAC* const mac, char* strmac)
The first parameter is a pointer to an array of 6 unsigned characters,
whereas it really just wants to be a pointer to the first element of the
array:
t_stat eth_mac_scan (const ETH_MAC mac, char* strmac)
The "ETH_MAC *" indirection error also results in subtle memcpy() and
memcmp() issues, e.g.:
void network_func(DEVICE *dev, ETH_MAC *mac)
{
ETH_MAC other_mac;
/* ...code... */
/* memcpy() bug: */
memcpy(other_mac, mac, sizeof(ETH_MAC));
/* or worse: */
memcpy(mac, other_mac, sizeof(ETH_MAC));
}
eth_copy_mac() and eth_mac_cmp() replace calls to memcpy() and memcmp()
that copy or compare Ethernet MAC addresses. These are type-enforcing
functions, i.e., the parameters are ETH_MAC-s, to avoid the subtle
memcpy() and memcmp() bugs.
This fix solves at least one Heisenbug in _eth_close() while free()-ing
write request buffers (and possibly other Heisenbugs.)
This commit is contained in:
committed by
Paul Koning
parent
73e5df3928
commit
c20b391eea
52
sim_ether.h
52
sim_ether.h
@@ -341,22 +341,22 @@ t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet, /* write synchronous pac
|
||||
int eth_read (ETH_DEV* dev, ETH_PACK* packet, /* read single packet; */
|
||||
ETH_PCALLBACK routine); /* callback when done*/
|
||||
t_stat eth_filter (ETH_DEV* dev, int addr_count, /* set filter on incoming packets */
|
||||
ETH_MAC* const addresses,
|
||||
const ETH_MAC addresses[],
|
||||
ETH_BOOL all_multicast,
|
||||
ETH_BOOL promiscuous);
|
||||
t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, /* set filter on incoming packets with hash */
|
||||
ETH_MAC* const addresses,
|
||||
const ETH_MAC addresses[],
|
||||
ETH_BOOL all_multicast,
|
||||
ETH_BOOL promiscuous,
|
||||
ETH_MULTIHASH* const hash); /* AUTODIN II based 8 byte imperfect hash */
|
||||
t_stat eth_filter_hash_ex (ETH_DEV* dev, int addr_count,/* set filter on incoming packets with hash */
|
||||
ETH_MAC* const addresses,
|
||||
const ETH_MAC addresses[],
|
||||
ETH_BOOL all_multicast,
|
||||
ETH_BOOL promiscuous,
|
||||
ETH_BOOL match_broadcast,
|
||||
ETH_MULTIHASH* const hash); /* AUTODIN II based 8 byte imperfect hash */
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev,
|
||||
ETH_MAC* const address);
|
||||
const ETH_MAC address);
|
||||
const char *eth_version (void); /* Version of dynamically loaded library (pcap) */
|
||||
void eth_setcrc (ETH_DEV* dev, int need_crc); /* enable/disable CRC mode */
|
||||
t_stat eth_set_async (ETH_DEV* dev, int latency); /* set read behavior to be async */
|
||||
@@ -373,9 +373,9 @@ t_stat eth_show_devices (FILE* st, DEVICE *dptr, /* show ethernet devices
|
||||
int eth_devices (int max, ETH_LIST* dev, ETH_BOOL framers); /* get ethernet devices on host */
|
||||
void eth_show_dev (FILE*st, ETH_DEV* dev); /* show ethernet device state */
|
||||
|
||||
void eth_mac_fmt (ETH_MAC* const add, char* buffer); /* format ethernet mac address */
|
||||
t_stat eth_mac_scan (ETH_MAC* mac, const char* strmac); /* scan string for mac, put in mac */
|
||||
t_stat eth_mac_scan_ex (ETH_MAC* mac, /* scan string for mac, put in mac */
|
||||
void eth_mac_fmt (const ETH_MAC add, char* buffer); /* format ethernet mac address */
|
||||
t_stat eth_mac_scan (ETH_MAC mac, const char* strmac); /* scan string for mac, put in mac */
|
||||
t_stat eth_mac_scan_ex (ETH_MAC mac, /* scan string for mac, put in mac */
|
||||
const char* strmac, UNIT *uptr);/* for specified unit */
|
||||
|
||||
t_stat ethq_init (ETH_QUE* que, int max); /* initialize FIFO queue */
|
||||
@@ -390,6 +390,44 @@ t_stat ethq_destroy(ETH_QUE* que); /* release FIFO queue */
|
||||
const char *eth_capabilities(void);
|
||||
t_stat sim_ether_test (DEVICE *dptr, const char *cptr); /* unit test routine */
|
||||
|
||||
/* Well-known Ethernet MAC addresses:
|
||||
*
|
||||
* eth_mac_any: All zeroes/any address
|
||||
* eth_mac_bcast: All ones broadcast.
|
||||
*/
|
||||
extern const ETH_MAC eth_mac_any;
|
||||
extern const ETH_MAC eth_mac_bcast;
|
||||
|
||||
/* Type-enforcing MAC address copy function.
|
||||
*
|
||||
* This inline helps to prevent the following situation:
|
||||
*
|
||||
* void network_func(DEVICE *dev, ETH_MAC *mac)
|
||||
* {
|
||||
* ETH_MAC other_mac;
|
||||
*
|
||||
* ...
|
||||
* memcpy(other_mac, mac, sizeof(ETH_MAC));
|
||||
* }
|
||||
*
|
||||
* The compiler will happily accept the memcpy() as valid because src and dst are
|
||||
* converted to "void *". This is a subtle bug -- mac is a pointer to an ETH_MAC
|
||||
* and memcpy will copy from somewhere other than the first byte of the source MAC
|
||||
* address.
|
||||
*/
|
||||
static inline void eth_copy_mac(ETH_MAC dst, const ETH_MAC src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(ETH_MAC));
|
||||
}
|
||||
|
||||
/* Type-enforcing MAC comparison function. Helps to avoid subtle memcmp() issues
|
||||
* (see above).
|
||||
*/
|
||||
static inline int eth_mac_cmp(const ETH_MAC a, const ETH_MAC b)
|
||||
{
|
||||
return memcmp(a, b, sizeof(ETH_MAC));
|
||||
}
|
||||
|
||||
#if !defined(SIM_TEST_INIT) /* Need stubs for test APIs */
|
||||
#define SIM_TEST_INIT
|
||||
#define SIM_TEST(xxx)
|
||||
|
||||
Reference in New Issue
Block a user