mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-11 23:52:48 +00:00
SCP: Updated to current.
This commit is contained in:
parent
881114ef2b
commit
8e0069a8c2
1
scp.c
1
scp.c
@ -3016,6 +3016,7 @@ while (stat != SCPE_EXIT) { /* in case exit */
|
||||
}
|
||||
else {
|
||||
if (sim_vm_read != NULL) { /* sim routine? */
|
||||
printf ("%s", sim_prompt); /* prompt */
|
||||
cptr = (*sim_vm_read) (cbuf, sizeof(cbuf), stdin);
|
||||
}
|
||||
else
|
||||
|
||||
182
sim_ether.c
182
sim_ether.c
@ -386,25 +386,25 @@ static int _eth_get_system_id (char *buf, size_t buf_size);
|
||||
static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on);
|
||||
|
||||
static const unsigned char framer_oui[3] = { 0xaa, 0x00, 0x03 };
|
||||
const ETH_MAC eth_mac_any = {0, 0, 0, 0, 0, 0};
|
||||
const ETH_MAC eth_mac_bcast = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
/*============================================================================*/
|
||||
/* OS-independent ethernet routines */
|
||||
/*============================================================================*/
|
||||
|
||||
t_stat eth_mac_scan (ETH_MAC* mac, const char* strmac)
|
||||
t_stat eth_mac_scan (ETH_MAC mac, const char* strmac)
|
||||
{
|
||||
return eth_mac_scan_ex (mac, strmac, NULL);
|
||||
}
|
||||
|
||||
t_stat eth_mac_scan_ex (ETH_MAC* mac, const char* strmac, UNIT *uptr)
|
||||
t_stat eth_mac_scan_ex (ETH_MAC mac, const char* strmac, UNIT *uptr)
|
||||
{
|
||||
unsigned int a[6], g[6];
|
||||
FILE *f;
|
||||
char filebuf[64] = "";
|
||||
uint32 i;
|
||||
static const ETH_MAC zeros = {0,0,0,0,0,0};
|
||||
static const ETH_MAC ones = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
ETH_MAC newmac;
|
||||
ETH_MAC newmac = {0, 0, 0, 0, 0, 0};
|
||||
struct {
|
||||
uint32 bits;
|
||||
char system_id[64];
|
||||
@ -470,8 +470,8 @@ t_stat eth_mac_scan_ex (ETH_MAC* mac, const char* strmac, UNIT *uptr)
|
||||
}
|
||||
|
||||
/* final check - mac cannot be broadcast or multicast address */
|
||||
if (!memcmp(newmac, zeros, sizeof(ETH_MAC)) || /* broadcast */
|
||||
!memcmp(newmac, ones, sizeof(ETH_MAC)) || /* broadcast */
|
||||
if (!eth_mac_cmp(newmac, eth_mac_any) || /* broadcast */
|
||||
!eth_mac_cmp(newmac, eth_mac_bcast) || /* broadcast */
|
||||
(newmac[0] & 0x01) /* multicast */
|
||||
)
|
||||
return sim_messagef (SCPE_ARG, "Can't use Broadcast or MultiCast address as interface MAC address\n");
|
||||
@ -482,29 +482,28 @@ t_stat eth_mac_scan_ex (ETH_MAC* mac, const char* strmac, UNIT *uptr)
|
||||
f = fopen (state.file, "w");
|
||||
if (f == NULL)
|
||||
return sim_messagef (SCPE_ARG, "Can't open MAC address configuration file '%s'.\n", state.file);
|
||||
eth_mac_fmt (&newmac, filebuf);
|
||||
eth_mac_fmt (newmac, filebuf);
|
||||
fprintf (f, "%s/48\n", filebuf);
|
||||
fprintf (f, "system-id: %s\n", state.system_id);
|
||||
fprintf (f, "directory: %s\n", state.cwd);
|
||||
fprintf (f, "simulator: %s\n", state.sim);
|
||||
fprintf (f, "device: %s\n", state.uname);
|
||||
fprintf (f, "file: %s\n", state.file);
|
||||
eth_mac_fmt (&state.base_mac, filebuf);
|
||||
eth_mac_fmt (state.base_mac, filebuf);
|
||||
fprintf (f, "base-mac: %s\n", filebuf);
|
||||
fprintf (f, "specified: %d bits\n", state.bits);
|
||||
fprintf (f, "generated: %d bits\n", 48-state.bits);
|
||||
fclose (f);
|
||||
}
|
||||
/* copy into passed mac */
|
||||
memcpy (*mac, newmac, sizeof(ETH_MAC));
|
||||
eth_copy_mac (mac, newmac);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
void eth_mac_fmt(ETH_MAC* const mac, char* buff)
|
||||
void eth_mac_fmt(const ETH_MAC mac, char* buff)
|
||||
{
|
||||
const uint8* m = (const uint8*) mac;
|
||||
const uint8* m = (const uint8 *) mac;
|
||||
sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X", m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||
return;
|
||||
}
|
||||
|
||||
static const uint32 crcTable[256] = {
|
||||
@ -615,8 +614,8 @@ void eth_packet_trace_ex(ETH_DEV* dev, const uint8 *msg, int len, const char* tx
|
||||
char dst[20];
|
||||
const unsigned short* proto = (const unsigned short*) &msg[12];
|
||||
uint32 crc = eth_crc32(0, msg, len);
|
||||
eth_mac_fmt((ETH_MAC*)msg, dst);
|
||||
eth_mac_fmt((ETH_MAC*)(msg+6), src);
|
||||
eth_mac_fmt(msg, dst);
|
||||
eth_mac_fmt(msg + 6, src);
|
||||
sim_debug(reason, dev->dptr, "%s dst: %s src: %s proto: 0x%04X len: %d crc: %X\n",
|
||||
txt, dst, src, ntohs(*proto), len, crc);
|
||||
if (detail) {
|
||||
@ -625,7 +624,7 @@ void eth_packet_trace_ex(ETH_DEV* dev, const uint8 *msg, int len, const char* tx
|
||||
static const char hex[] = "0123456789ABCDEF";
|
||||
|
||||
for (i=same=0; i<len; i += 16) {
|
||||
if ((i > 0) && (0 == memcmp(&msg[i], &msg[i-16], 16))) {
|
||||
if ((i > 0) && (0 == eth_mac_cmp(&msg[i], &msg[i-16]))) {
|
||||
++same;
|
||||
continue;
|
||||
}
|
||||
@ -779,6 +778,8 @@ ethq_insert_data(que, type, pack->oversize ? pack->oversize : pack->msg, pack->u
|
||||
|
||||
t_stat eth_show_devices (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char *desc)
|
||||
{
|
||||
(void) dptr;
|
||||
(void) desc;
|
||||
return eth_show (st, uptr, val, NULL);
|
||||
}
|
||||
|
||||
@ -873,8 +874,11 @@ 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;
|
||||
ETH_DEV **tmp = (ETH_DEV**)realloc(eth_open_devices, (eth_open_device_count+1)*sizeof(*eth_open_devices));
|
||||
if (tmp != NULL) {
|
||||
eth_open_devices = tmp;
|
||||
eth_open_devices[eth_open_device_count++] = dev;
|
||||
}
|
||||
}
|
||||
|
||||
static void _eth_remove_from_open_list (ETH_DEV* dev)
|
||||
@ -895,6 +899,11 @@ t_stat eth_show (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
|
||||
ETH_LIST list[ETH_MAX_DEVICE];
|
||||
int number;
|
||||
|
||||
/* Squelch unused parameters. But do we really need them? */
|
||||
(void) uptr;
|
||||
(void) val;
|
||||
(void) desc;
|
||||
|
||||
number = eth_devices(ETH_MAX_DEVICE, list, FALSE);
|
||||
fprintf(st, "ETH devices:\n");
|
||||
if (number == -1)
|
||||
@ -912,11 +921,11 @@ t_stat eth_show (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
|
||||
}
|
||||
if (eth_open_device_count) {
|
||||
int i;
|
||||
char desc[ETH_DEV_DESC_MAX], *d;
|
||||
char devdesc[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);
|
||||
d = eth_getdesc_byname(eth_open_devices[i]->name, devdesc);
|
||||
if (d)
|
||||
fprintf(st, " %-7s%s (%s)\n", eth_open_devices[i]->dptr->name, eth_open_devices[i]->dptr->units[0].filename, d);
|
||||
else
|
||||
@ -945,8 +954,7 @@ t_stat eth_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const cha
|
||||
fprintf (st, "This simulator was not built with ethernet device support\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev,
|
||||
ETH_MAC* const mac)
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev, const ETH_MAC mac)
|
||||
{return SCPE_NOFNC;}
|
||||
t_stat eth_set_throttle (ETH_DEV* dev, uint32 time, uint32 burst, uint32 delay)
|
||||
{return SCPE_NOFNC;}
|
||||
@ -958,13 +966,13 @@ t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine)
|
||||
{return SCPE_NOFNC;}
|
||||
int eth_read (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine)
|
||||
{return SCPE_NOFNC;}
|
||||
t_stat eth_filter (ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
|
||||
t_stat eth_filter (ETH_DEV* dev, int addr_count, const ETH_MAC addresses[],
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous)
|
||||
{return SCPE_NOFNC;}
|
||||
t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
|
||||
t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, const ETH_MAC addresses[],
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous, ETH_MULTIHASH* const hash)
|
||||
{return SCPE_NOFNC;}
|
||||
t_stat eth_filter_hash_ex(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
|
||||
t_stat eth_filter_hash_ex(ETH_DEV* dev, int addr_count, const ETH_MAC addresses[],
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
ETH_BOOL match_broadcast, ETH_MULTIHASH* const hash)
|
||||
{return SCPE_NOFNC;}
|
||||
@ -2762,7 +2770,7 @@ return (rand() & 0xFF);
|
||||
}
|
||||
|
||||
t_stat eth_check_address_conflict_ex (ETH_DEV* dev,
|
||||
ETH_MAC* const mac,
|
||||
const ETH_MAC mac,
|
||||
int *reflections,
|
||||
t_bool silent)
|
||||
{
|
||||
@ -2779,9 +2787,9 @@ eth_mac_fmt(mac, mac_string);
|
||||
sim_debug(dev->dbit, dev->dptr, "Determining Address Conflict for MAC address: %s\n", mac_string);
|
||||
|
||||
/* 00:00:00:00:00:00 or any address with a multi-cast address is invalid */
|
||||
if ((((*mac)[0] == 0) && ((*mac)[1] == 0) && ((*mac)[2] == 0) &&
|
||||
((*mac)[3] == 0) && ((*mac)[4] == 0) && ((*mac)[5] == 0)) ||
|
||||
((*mac)[0] & 1)) {
|
||||
if (((mac[0] == 0) && (mac[1] == 0) && (mac[2] == 0) &&
|
||||
(mac[3] == 0) && (mac[4] == 0) && (mac[5] == 0)) ||
|
||||
(mac[0] & 1)) {
|
||||
return sim_messagef (SCPE_ARG, "%s: Invalid NIC MAC Address: %s\n", sim_dname(dev->dptr), mac_string);
|
||||
}
|
||||
|
||||
@ -2850,15 +2858,15 @@ memset (&send, 0, sizeof(ETH_PACK));
|
||||
send.len = ETH_MIN_PACKET; /* minimum packet size */
|
||||
for (i=0; i<send.len; i++)
|
||||
send.msg[i] = _eth_rand_byte();
|
||||
memcpy(&send.msg[0], mac, sizeof(ETH_MAC)); /* target address */
|
||||
memcpy(&send.msg[6], mac, sizeof(ETH_MAC)); /* source address */
|
||||
eth_copy_mac(&send.msg[0], mac); /* target address */
|
||||
eth_copy_mac(&send.msg[6], mac); /* source address */
|
||||
send.msg[12] = 0x90; /* loopback packet type */
|
||||
send.msg[13] = 0;
|
||||
send.msg[14] = 0; /* Offset */
|
||||
send.msg[15] = 0;
|
||||
send.msg[16] = 2; /* Forward */
|
||||
send.msg[17] = 0;
|
||||
memcpy(&send.msg[18], mac, sizeof(ETH_MAC)); /* Forward Destination */
|
||||
eth_copy_mac(&send.msg[18], mac); /* Forward Destination */
|
||||
send.msg[24] = 1; /* Reply */
|
||||
send.msg[25] = 0;
|
||||
|
||||
@ -2905,13 +2913,12 @@ if (reflections)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev,
|
||||
ETH_MAC* const mac)
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev, const ETH_MAC mac)
|
||||
{
|
||||
char mac_string[32];
|
||||
|
||||
eth_mac_fmt(mac, mac_string);
|
||||
if (0 == memcmp (mac, dev->host_nic_phy_hw_addr, sizeof *mac))
|
||||
if (0 == eth_mac_cmp (mac, dev->host_nic_phy_hw_addr))
|
||||
return sim_messagef (SCPE_OK, "Sharing the host NIC MAC address %s may cause unexpected behavior\n", mac_string);
|
||||
return eth_check_address_conflict_ex (dev, mac, NULL, FALSE);
|
||||
}
|
||||
@ -2927,7 +2934,7 @@ static ETH_MAC mac = {0xfe,0xff,0xff,0xff,0xff,0xfe};
|
||||
|
||||
sim_debug(dev->dbit, dev->dptr, "Determining Reflections...\n");
|
||||
|
||||
r = eth_check_address_conflict_ex (dev, &mac, &dev->reflections, TRUE);
|
||||
r = eth_check_address_conflict_ex (dev, mac, &dev->reflections, TRUE);
|
||||
if (r != SCPE_OK)
|
||||
return sim_messagef (r, "eth: Error determining reflection count\n");
|
||||
|
||||
@ -3042,8 +3049,8 @@ if ((packet->len >= ETH_MIN_PACKET) && (packet->len <= ETH_MAX_PACKET)) {
|
||||
/* Direct loopback responses to the host physical address since our physical address
|
||||
may not have been learned yet. */
|
||||
if (loopback_self_frame && dev->have_host_nic_phy_addr) {
|
||||
memcpy(&packet->msg[6], dev->host_nic_phy_hw_addr, sizeof(ETH_MAC));
|
||||
memcpy(&packet->msg[18], dev->host_nic_phy_hw_addr, sizeof(ETH_MAC));
|
||||
eth_copy_mac(&packet->msg[6], dev->host_nic_phy_hw_addr);
|
||||
eth_copy_mac(&packet->msg[18], dev->host_nic_phy_hw_addr);
|
||||
eth_packet_trace (dev, packet->msg, packet->len, "writing-fixed");
|
||||
}
|
||||
#ifdef USE_READER_THREAD
|
||||
@ -3123,7 +3130,6 @@ t_stat eth_write(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine)
|
||||
{
|
||||
#ifdef USE_READER_THREAD
|
||||
ETH_WRITE_REQUEST *request;
|
||||
int write_queue_size = 1;
|
||||
|
||||
/* make sure device exists */
|
||||
if ((!dev) || (dev->eth_api == ETH_API_NONE)) return SCPE_UNATT;
|
||||
@ -3135,11 +3141,12 @@ if (packet->len > sizeof (packet->msg)) /* packet oversized? */
|
||||
pthread_mutex_lock (&dev->writer_lock);
|
||||
if (NULL != (request = dev->write_buffers))
|
||||
dev->write_buffers = request->next;
|
||||
pthread_mutex_unlock (&dev->writer_lock);
|
||||
|
||||
if (NULL == request)
|
||||
request = (ETH_WRITE_REQUEST *)malloc(sizeof(*request));
|
||||
|
||||
/* Copy buffer contents */
|
||||
request->next = NULL;
|
||||
request->packet.len = packet->len;
|
||||
request->packet.used = packet->used;
|
||||
request->packet.status = packet->status;
|
||||
@ -3148,25 +3155,21 @@ memcpy(request->packet.msg, packet->msg, packet->len);
|
||||
|
||||
/* Insert buffer at the end of the write list (to make sure that */
|
||||
/* packets make it to the wire in the order they were presented here) */
|
||||
pthread_mutex_lock (&dev->writer_lock);
|
||||
request->next = NULL;
|
||||
if (dev->write_requests) {
|
||||
ETH_WRITE_REQUEST *last_request = dev->write_requests;
|
||||
{
|
||||
int write_queue_size = 1;
|
||||
ETH_WRITE_REQUEST **last_request = &dev->write_requests;
|
||||
|
||||
++write_queue_size;
|
||||
while (last_request->next) {
|
||||
last_request = last_request->next;
|
||||
while (*last_request != NULL) {
|
||||
last_request = &(*last_request)->next;
|
||||
++write_queue_size;
|
||||
}
|
||||
last_request->next = request;
|
||||
*last_request = request;
|
||||
if (write_queue_size > dev->write_queue_peak)
|
||||
dev->write_queue_peak = write_queue_size;
|
||||
}
|
||||
else
|
||||
dev->write_requests = request;
|
||||
if (write_queue_size > dev->write_queue_peak)
|
||||
dev->write_queue_peak = write_queue_size;
|
||||
pthread_mutex_unlock (&dev->writer_lock);
|
||||
|
||||
/* Awaken writer thread to perform actual write */
|
||||
pthread_mutex_unlock (&dev->writer_lock);
|
||||
pthread_cond_signal (&dev->writer_cond);
|
||||
|
||||
/* Return with a status from some prior write */
|
||||
@ -3644,7 +3647,7 @@ if (function != 2) /*forward*/
|
||||
(we may receive others if we're in promiscuous mode, but shouldn't
|
||||
respond to them) */
|
||||
if ((0 == (data[0]&1)) && /* Multicast or Broadcast */
|
||||
(0 != memcmp(dev->filter_address[0], data, sizeof(ETH_MAC))))
|
||||
(0 != eth_mac_cmp(dev->filter_address[0], data)))
|
||||
return 0;
|
||||
|
||||
/* Attempts to forward to multicast or broadcast addresses are explicitly
|
||||
@ -3660,8 +3663,8 @@ sim_debug(dev->dbit, dev->dptr, "_eth_process_loopback()\n");
|
||||
memset(&response, 0, sizeof(response));
|
||||
response.len = len;
|
||||
memcpy(response.msg, data, len);
|
||||
memcpy(&response.msg[0], &response.msg[offset+2], sizeof(ETH_MAC));
|
||||
memcpy(&response.msg[6], dev->filter_address[0], sizeof(ETH_MAC));
|
||||
eth_copy_mac(&response.msg[0], &response.msg[offset+2]);
|
||||
eth_copy_mac(&response.msg[6], dev->filter_address[0]);
|
||||
offset += 8 - 16; /* Account for the Ethernet Header and Offset value in this number */
|
||||
response.msg[14] = offset & 0xFF;
|
||||
response.msg[15] = (offset >> 8) & 0xFF;
|
||||
@ -3692,8 +3695,8 @@ if (LOOPBACK_PHYSICAL_RESPONSE(dev, data)) {
|
||||
host's interface instead of the programmatically set physical address of this pseudo
|
||||
device, we restore parts of the modified packet back as needed */
|
||||
memcpy(datacopy, data, header->len);
|
||||
memcpy(datacopy, dev->physical_addr, sizeof(ETH_MAC));
|
||||
memcpy(datacopy+18, dev->physical_addr, sizeof(ETH_MAC));
|
||||
eth_copy_mac(datacopy, dev->physical_addr);
|
||||
eth_copy_mac(datacopy+18, dev->physical_addr);
|
||||
_eth_callback(info, header, datacopy);
|
||||
free(datacopy);
|
||||
return;
|
||||
@ -3775,7 +3778,7 @@ if (bpf_used ? to_me : (to_me && !from_me)) {
|
||||
#if defined (USE_READER_THREAD)
|
||||
if (1) {
|
||||
int crc_len = 0;
|
||||
uint8 crc_data[4];
|
||||
uint8 crc_data[4] = { 0, 0, 0, 0 };
|
||||
uint32 len = header->len;
|
||||
u_char *moved_data = NULL;
|
||||
|
||||
@ -3959,8 +3962,8 @@ return status;
|
||||
t_stat eth_bpf_filter (ETH_DEV* dev, int addr_count, ETH_MAC* const filter_address,
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
int reflections,
|
||||
ETH_MAC* physical_addr,
|
||||
ETH_MAC* host_nic_phy_hw_addr,
|
||||
ETH_MAC physical_addr,
|
||||
ETH_MAC host_nic_phy_hw_addr,
|
||||
ETH_MULTIHASH* const hash,
|
||||
char *buf)
|
||||
{
|
||||
@ -3976,7 +3979,7 @@ strcpy(buf, "");
|
||||
our simulated interface doesn't want. */
|
||||
if (!promiscuous) {
|
||||
for (i = 0; i < addr_count; i++) {
|
||||
eth_mac_fmt(&filter_address[i], mac);
|
||||
eth_mac_fmt(filter_address[i], mac);
|
||||
if (!strstr(buf, mac)) /* eliminate duplicates */
|
||||
sprintf(&buf[strlen(buf)], "%s(ether dst %s)", (*buf) ? " or " : "((", mac);
|
||||
}
|
||||
@ -4000,7 +4003,7 @@ if ((addr_count > 0) && (reflections > 0)) {
|
||||
buf2 = &buf[strlen(buf)];
|
||||
for (i = 0; i < addr_count; i++) {
|
||||
if (filter_address[i][0] & 0x01) continue; /* skip multicast addresses */
|
||||
eth_mac_fmt(&filter_address[i], mac);
|
||||
eth_mac_fmt(filter_address[i], mac);
|
||||
if (!strstr(buf2, mac)) /* only process each address once */
|
||||
sprintf(&buf2[strlen(buf2)], "%s(ether src %s)", (*buf2) ? " or " : "", mac);
|
||||
}
|
||||
@ -4032,14 +4035,12 @@ if (strlen(buf) > 0)
|
||||
simulated machine. */
|
||||
/* check for physical address in filters */
|
||||
if ((!promiscuous) && (addr_count) && (reflections > 0)) {
|
||||
eth_mac_fmt(&physical_addr[0], mac);
|
||||
eth_mac_fmt(physical_addr, mac);
|
||||
if (strcmp(mac, "00:00:00:00:00:00") != 0) {
|
||||
/* let packets through where dst and src are the same as our physical address */
|
||||
sprintf (&buf[strlen(buf)], " or ((ether dst %s) and (ether src %s))", mac, mac);
|
||||
if (host_nic_phy_hw_addr) {
|
||||
eth_mac_fmt(&host_nic_phy_hw_addr[0], mac);
|
||||
sprintf(&buf[strlen(buf)], " or ((ether dst %s) and (ether proto 0x9000))", mac);
|
||||
}
|
||||
eth_mac_fmt(host_nic_phy_hw_addr, mac);
|
||||
sprintf(&buf[strlen(buf)], " or ((ether dst %s) and (ether proto 0x9000))", mac);
|
||||
}
|
||||
}
|
||||
if ((0 == strlen(buf)) && (!promiscuous)) /* Empty filter means match nothing */
|
||||
@ -4048,7 +4049,7 @@ sim_debug(dev->dbit, dev->dptr, "BPF string is: |%s|\n", buf);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
|
||||
t_stat eth_filter(ETH_DEV* dev, int addr_count, const ETH_MAC addresses[],
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous)
|
||||
{
|
||||
return eth_filter_hash_ex(dev, addr_count, addresses,
|
||||
@ -4056,7 +4057,7 @@ return eth_filter_hash_ex(dev, addr_count, addresses,
|
||||
NULL);
|
||||
}
|
||||
|
||||
t_stat eth_filter_hash(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
|
||||
t_stat eth_filter_hash(ETH_DEV* dev, int addr_count, const ETH_MAC addresses[],
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
ETH_MULTIHASH* const hash)
|
||||
{
|
||||
@ -4065,7 +4066,7 @@ return eth_filter_hash_ex(dev, addr_count, addresses,
|
||||
hash);
|
||||
}
|
||||
|
||||
t_stat eth_filter_hash_ex(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
|
||||
t_stat eth_filter_hash_ex(ETH_DEV* dev, int addr_count, const ETH_MAC addresses[],
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
ETH_BOOL match_broadcast, ETH_MULTIHASH* const hash)
|
||||
{
|
||||
@ -4094,7 +4095,7 @@ if (dev->reflections == -1)
|
||||
|
||||
/* set new filter addresses */
|
||||
for (i = 0; i < addr_count; i++)
|
||||
memcpy(dev->filter_address[i], addresses[i], sizeof(ETH_MAC));
|
||||
eth_copy_mac(dev->filter_address[i], addresses[i]);
|
||||
dev->addr_count = addr_count;
|
||||
if (match_broadcast) {
|
||||
memset(&dev->filter_address[addr_count], 0xFF, sizeof(ETH_MAC));
|
||||
@ -4119,9 +4120,9 @@ if (hash) {
|
||||
if (dev->dptr->dctrl & dev->dbit) {
|
||||
sim_debug(dev->dbit, dev->dptr, "Filter Set\n");
|
||||
for (i = 0; i < addr_count; i++) {
|
||||
char mac[20];
|
||||
eth_mac_fmt(&dev->filter_address[i], mac);
|
||||
sim_debug(dev->dbit, dev->dptr, " Addr[%d]: %s\n", i, mac);
|
||||
char macaddr[20];
|
||||
eth_mac_fmt(dev->filter_address[i], macaddr);
|
||||
sim_debug(dev->dbit, dev->dptr, " Addr[%d]: %s\n", i, macaddr);
|
||||
}
|
||||
if (dev->all_multicast) {
|
||||
sim_debug(dev->dbit, dev->dptr, "All Multicast\n");
|
||||
@ -4140,9 +4141,9 @@ dev->loopback_self_sent = 0;
|
||||
for (i = 0; i < addr_count; i++) {
|
||||
if (dev->filter_address[i][0]&1)
|
||||
continue; /* skip all multicast addresses */
|
||||
eth_mac_fmt(&dev->filter_address[i], mac);
|
||||
eth_mac_fmt(dev->filter_address[i], mac);
|
||||
if (strcmp(mac, "00:00:00:00:00:00") != 0) {
|
||||
memcpy(dev->physical_addr, &dev->filter_address[i], sizeof(ETH_MAC));
|
||||
eth_copy_mac(dev->physical_addr, dev->filter_address[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -4153,8 +4154,8 @@ for (i = 0; i < addr_count; i++) {
|
||||
/* setup BPF filters and other fields to minimize packet delivery */
|
||||
eth_bpf_filter (dev, dev->addr_count, dev->filter_address,
|
||||
dev->all_multicast, dev->promiscuous,
|
||||
dev->reflections, &dev->physical_addr,
|
||||
dev->have_host_nic_phy_addr ? &dev->host_nic_phy_hw_addr: NULL,
|
||||
dev->reflections, dev->physical_addr,
|
||||
dev->host_nic_phy_hw_addr,
|
||||
(dev->hash_filter ? &dev->hash : NULL), buf);
|
||||
|
||||
/* get netmask, which is a required argument for compiling. The value,
|
||||
@ -4178,9 +4179,9 @@ if (dev->eth_api == ETH_API_PCAP) {
|
||||
sim_printf ("Eth: Reflections: %d\n", dev->reflections);
|
||||
sim_printf ("Eth: Filter Set:\n");
|
||||
for (i = 0; i < addr_count; i++) {
|
||||
char mac[20];
|
||||
eth_mac_fmt(&dev->filter_address[i], mac);
|
||||
sim_printf ("Eth: Addr[%d]: %s\n", i, mac);
|
||||
char macaddr[20];
|
||||
eth_mac_fmt(dev->filter_address[i], macaddr);
|
||||
sim_printf ("Eth: Addr[%d]: %s\n", i, macaddr);
|
||||
}
|
||||
if (dev->all_multicast)
|
||||
sim_printf ("Eth: All Multicast\n");
|
||||
@ -4191,7 +4192,7 @@ if (dev->eth_api == ETH_API_PCAP) {
|
||||
dev->hash[0], dev->hash[1], dev->hash[2], dev->hash[3],
|
||||
dev->hash[4], dev->hash[5], dev->hash[6], dev->hash[7]);
|
||||
if (dev->have_host_nic_phy_addr) {
|
||||
eth_mac_fmt(&dev->host_nic_phy_hw_addr, mac);
|
||||
eth_mac_fmt(dev->host_nic_phy_hw_addr, mac);
|
||||
sim_printf ("Eth: host_nic_phy_hw_addr: %s\n", mac);
|
||||
}
|
||||
}
|
||||
@ -4238,7 +4239,7 @@ fprintf(st, " Self Loopbacks Rcvd: %d\n", dev->loopback_self_rcvd_total);
|
||||
if (dev->have_host_nic_phy_addr) {
|
||||
char hw_mac[20];
|
||||
|
||||
eth_mac_fmt(&dev->host_nic_phy_hw_addr, hw_mac);
|
||||
eth_mac_fmt(dev->host_nic_phy_hw_addr, hw_mac);
|
||||
fprintf(st, " Host NIC Address: %s\n", hw_mac);
|
||||
}
|
||||
if (dev->jumbo_dropped)
|
||||
@ -4276,12 +4277,11 @@ if (dev->error_reopen_count)
|
||||
fprintf(st, " Error Reopen Count: %d\n", (int)dev->error_reopen_count);
|
||||
if (1) {
|
||||
int i, count = 0;
|
||||
ETH_MAC zeros = {0, 0, 0, 0, 0, 0};
|
||||
char buffer[20];
|
||||
|
||||
for (i = 0; i < ETH_FILTER_MAX; i++) {
|
||||
if (memcmp(zeros, &dev->filter_address[i], sizeof(ETH_MAC))) {
|
||||
eth_mac_fmt(&dev->filter_address[i], buffer);
|
||||
if (eth_mac_cmp(eth_mac_any, dev->filter_address[i])) {
|
||||
eth_mac_fmt(dev->filter_address[i], buffer);
|
||||
fprintf(st, " MAC Filter[%2d]: %s\n", count++, buffer);
|
||||
}
|
||||
}
|
||||
@ -4386,7 +4386,7 @@ int bpf_compile_skip_count = 0;
|
||||
sim_printf ("Eth: Reflections: %d\n", reflections); \
|
||||
sim_printf ("Eth: Filter Set:\n"); \
|
||||
for (i = 0; i < addr_count; i++) { \
|
||||
eth_mac_fmt(&filter_address[i], mac); \
|
||||
eth_mac_fmt(filter_address[i], mac); \
|
||||
sim_printf ("Eth: Addr[%d]: %s\n", i, mac); \
|
||||
} \
|
||||
if (all_multicast) \
|
||||
@ -4398,7 +4398,7 @@ int bpf_compile_skip_count = 0;
|
||||
(*hash_list[hash_listindex])[0], (*hash_list[hash_listindex])[1], (*hash_list[hash_listindex])[2], (*hash_list[hash_listindex])[3], \
|
||||
(*hash_list[hash_listindex])[4], (*hash_list[hash_listindex])[5], (*hash_list[hash_listindex])[6], (*hash_list[hash_listindex])[7]);\
|
||||
if (host_phy_addr_list[host_phy_addr_listindex]) { \
|
||||
eth_mac_fmt(host_phy_addr_list[host_phy_addr_listindex], mac);\
|
||||
eth_mac_fmt(*host_phy_addr_list[host_phy_addr_listindex], mac);\
|
||||
sim_printf ("Eth: host_nic_phy_hw_addr: %s\n", mac); \
|
||||
} \
|
||||
}
|
||||
@ -4435,8 +4435,8 @@ for (eth_num=0; eth_num<eth_device_count; eth_num++) {
|
||||
++bpf_count;
|
||||
r = eth_bpf_filter (&dev, addr_count, &filter_address[0],
|
||||
all_multicast, promiscuous, reflections,
|
||||
&filter_address[0],
|
||||
host_phy_addr_list[host_phy_addr_listindex],
|
||||
filter_address[0],
|
||||
*host_phy_addr_list[host_phy_addr_listindex],
|
||||
hash_list[hash_listindex],
|
||||
buf);
|
||||
if (r != SCPE_OK) {
|
||||
|
||||
52
sim_ether.h
52
sim_ether.h
@ -340,22 +340,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 */
|
||||
@ -372,9 +372,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 */
|
||||
@ -389,6 +389,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)
|
||||
|
||||
93
sim_fio.c
93
sim_fio.c
@ -127,22 +127,89 @@ if (sim_end || (count == 0) || (size == sizeof (char)))
|
||||
sim_byte_swap_data (bptr, size, count);
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define sim_bswap16 __builtin_bswap16
|
||||
#define sim_bswap32 __builtin_bswap32
|
||||
#define sim_bswap64 __builtin_bswap64
|
||||
|
||||
#define USE_BSWAP_INTRINSIC
|
||||
#elif defined(_MSC_VER)
|
||||
#define sim_bswap16 _byteswap_ushort
|
||||
#define sim_bswap32 _byteswap_ulong
|
||||
#define sim_bswap64 _byteswap_uint64
|
||||
|
||||
#define USE_BSWAP_INTRINSIC
|
||||
#endif
|
||||
|
||||
void sim_byte_swap_data (void *bptr, size_t size, size_t count)
|
||||
{
|
||||
uint32 j;
|
||||
int32 k;
|
||||
unsigned char by, *sptr, *dptr;
|
||||
size_t j;
|
||||
uint8 *sptr = (uint8 *) bptr;
|
||||
|
||||
if (sim_end || (count == 0) || (size == sizeof (char)))
|
||||
return;
|
||||
for (j = 0, dptr = sptr = (unsigned char *) bptr; /* loop on items */
|
||||
j < count; j++) {
|
||||
for (k = (int32)(size - 1); k >= (((int32) size + 1) / 2); k--) {
|
||||
by = *sptr; /* swap end-for-end */
|
||||
*sptr++ = *(dptr + k);
|
||||
*(dptr + k) = by;
|
||||
if (sim_end || (count == 0) || (size == sizeof (char)))
|
||||
return;
|
||||
|
||||
/* Note: Restructured this code so that GCC Link Time Optimization doesn't generate
|
||||
* spurious buffer overwrite messages.
|
||||
*
|
||||
* LTO tries to inline this function where it's used and ends up evaluating the loop.
|
||||
* It's clearly a LTO bug that needs to be worked around as opposed to waiting for a
|
||||
* compiler update (and SIMH can't guarantee that users will maintain updated platforms).
|
||||
*
|
||||
* Output from the compiler looks like:
|
||||
*
|
||||
* 363 | int32 f, u, comp, cyl, sect, surf;
|
||||
* | ^
|
||||
* PDP18B/pdp18b_rp.c:363:13: note: at offset [16, 48] into destination object ‘comp’ of size 4
|
||||
* PDP18B/pdp18b_rp.c:363:13: note: at offset [80, 17179869168] into destination object ‘comp’ of size 4
|
||||
* In function ‘sim_byte_swap_data’,
|
||||
* inlined from ‘sim_byte_swap_data’ at sim_fio.c:130:6,
|
||||
* inlined from ‘sim_buf_swap_data’ at sim_fio.c:127:1,
|
||||
* inlined from ‘sim_fread’ at sim_fio.c:158:1,
|
||||
* inlined from ‘rp_svc’ at PDP18B/pdp18b_rp.c:442:15:
|
||||
* sim_fio.c:142:17: error: writing 4 bytes into a region of size 0 [-Werror=stringop-overflow=]
|
||||
* 142 | *sptr++ = *(dptr + k);
|
||||
*/
|
||||
|
||||
for (j = 0; j < count; j++) { /* loop on items */
|
||||
#if defined(USE_BSWAP_INTRINSIC)
|
||||
switch (size) {
|
||||
case sizeof(uint16):
|
||||
*((uint16 *) sptr) = sim_bswap16 (*((uint16 *) sptr));
|
||||
break;
|
||||
|
||||
case sizeof(uint32):
|
||||
*((uint32 *) sptr) = sim_bswap32 (*((uint32 *) sptr));
|
||||
break;
|
||||
|
||||
case sizeof(t_uint64):
|
||||
*((t_uint64 *) sptr) = sim_bswap64 (*((t_uint64 *) sptr));
|
||||
break;
|
||||
|
||||
default:
|
||||
#endif
|
||||
|
||||
{
|
||||
/* Either there aren't any intrinsics that do byte swapping or
|
||||
* it's not a well known size. */
|
||||
uint8 *dptr;
|
||||
size_t k;
|
||||
const size_t midpoint = (size + 1) / 2;
|
||||
|
||||
dptr = sptr + size - 1;
|
||||
for (k = size - 1; k >= midpoint; k--) {
|
||||
uint8 by = *sptr; /* swap end-for-end */
|
||||
*sptr++ = *dptr;
|
||||
*dptr-- = by;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_BSWAP_INTRINSIC)
|
||||
break;
|
||||
}
|
||||
sptr = dptr = dptr + size; /* next item */
|
||||
#endif
|
||||
|
||||
sptr += size; /* next item */
|
||||
}
|
||||
}
|
||||
|
||||
@ -550,7 +617,7 @@ dwStatus = FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM|
|
||||
Error, // __in DWORD dwMessageId,
|
||||
0, // __in DWORD dwLanguageId,
|
||||
szMsgBuffer, // __out LPTSTR lpBuffer,
|
||||
sizeof (szMsgBuffer) -1, // __in DWORD nSize,
|
||||
sizeof (szMsgBuffer) - 1, // __in DWORD nSize,
|
||||
NULL); // __in_opt va_list *Arguments
|
||||
if (0 == dwStatus)
|
||||
snprintf(szMsgBuffer, sizeof(szMsgBuffer) - 1, "Error Code: 0x%X", Error);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user