rawnet - replace ugly transmit/receive functions with read/write.

This commit is contained in:
Kelvin Sherlock 2018-12-30 15:53:54 -05:00
parent 5884e751bc
commit 41b01509ad
7 changed files with 247 additions and 221 deletions

View File

@ -3,17 +3,19 @@ if(WIN32)
set(rawnetarch rawnetarch_win32.c)
elseif(APPLE)
set(rawnetarch rawnetarch_darwin.c)
#set(rawnetarch rawnetarch_unix.c)
elseif(UNIX)
set(rawnetarch rawnetarch_unix.c)
endif()
add_library(rawnet cs8900.c rawnet.c rawnetsupp.c ${rawnetarch})
add_library(rawnet cs8900.c rawnet.c rawnetsupp.c rawnetarch.c ${rawnetarch})
target_compile_definitions(rawnet PUBLIC HAVE_RAWNET)
target_compile_definitions(rawnet PRIVATE CS8900_DEBUG CS8900_DEBUG_STORE CS8900_DEBUG_LOAD)
target_compile_definitions(rawnet PRIVATE CS8900_DEBUG RAWNET_DEBUG_FRAMES)
if(WIN32)
elseif(APPLE)
#target_link_libraries(rawnet PRIVATE pcap)
target_link_libraries(rawnet PRIVATE "-framework vmnet")
elseif(UNIX)
target_link_libraries(rawnet PRIVATE pcap)

144
src/rawnet/rawnetarch.c Normal file
View File

@ -0,0 +1,144 @@
/** \file rawnetarch.c
* \brief raw ethernet interface, architecture-dependant stuff
*
* \author Bas Wassink <b.wassink@ziggo.nl
*/
/*
* This file is part of VICE, the Versatile Commodore Emulator.
* See README for copyright notice.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA.
*
*/
#include "rawnetarch.h"
#include "rawnetsupp.h"
#include <assert.h>
#ifdef HAVE_RAWNET
/* backward compatibility junk */
/** \brief Transmit a frame
*
* \param[in] force Delete waiting frames in transmit buffer
* \param[in] onecoll Terminate after just one collision
* \param[in] inhibit_crc Do not append CRC to the transmission
* \param[in] tx_pad_dis Disable padding to 60 Bytes
* \param[in] txlength Frame length
* \param[in] txframe Pointer to the frame to be transmitted
*/
void rawnet_arch_transmit(int force, int onecoll, int inhibit_crc,
int tx_pad_dis, int txlength, uint8_t *txframe)
{
int ok;
#ifdef RAWNET_DEBUG_ARCH
log_message(rawnet_arch_log,
"rawnet_arch_transmit() called, with: force = %s, onecoll = %s, "
"inhibit_crc=%s, tx_pad_dis=%s, txlength=%u",
force ? "TRUE" : "FALSE",
onecoll ? "TRUE" : "FALSE",
inhibit_crc ? "TRUE" : "FALSE",
tx_pad_dis ? "TRUE" : "FALSE",
txlength);
#endif
ok = rawnet_arch_write(txframe, txlength);
if (ok < 0) {
log_message(rawnet_arch_log, "WARNING! Could not send packet!");
}
}
/**
* \brief Check if a frame was received
*
* This function checks if there was a frame received. If so, it returns 1,
* else 0.
*
* If there was no frame, none of the parameters is changed!
*
* If there was a frame, the following actions are done:
*
* - at maximum \a plen byte are transferred into the buffer given by \a pbuffer
* - \a plen gets the length of the received frame, EVEN if this is more
* than has been copied to \a pbuffer!
* - if the dest. address was accepted by the hash filter, \a phashed is set,
* else cleared.
* - if the dest. address was accepted by the hash filter, \a phash_index is
* set to the number of the rule leading to the acceptance
* - if the receive was ok (good CRC and valid length), \a *prx_ok is set, else
* cleared.
* - if the dest. address was accepted because it's exactly our MAC address
* (set by rawnet_arch_set_mac()), \a pcorrect_mac is set, else cleared.
* - if the dest. address was accepted since it was a broadcast address,
* \a pbroadcast is set, else cleared.
* - if the received frame had a crc error, \a pcrc_error is set, else cleared
*
* \param[out] buffer where to store a frame
* \param[in,out] plen IN: maximum length of frame to copy;
* OUT: length of received frame OUT
* can be bigger than IN if received frame was
* longer than supplied buffer
* \param[out] phashed set if the dest. address is accepted by the
* hash filter
* \param[out] phash_index hash table index if hashed == TRUE
* \param[out] prx_ok set if good CRC and valid length
* \param[out] pcorrect_mac set if dest. address is exactly our IA
* \param[out[ pbroadcast set if dest. address is a broadcast address
* \param[out] pcrc_error set if received frame had a CRC error
*/
int rawnet_arch_receive(uint8_t *pbuffer, int *plen, int *phashed,
int *phash_index, int *prx_ok, int *pcorrect_mac, int *pbroadcast,
int *pcrc_error)
{
int ok;
#ifdef RAWNET_DEBUG_ARCH
log_message(rawnet_arch_log,
"rawnet_arch_receive() called, with *plen=%u.",
*plen);
#endif
assert((*plen & 1) == 0);
ok = rawnet_arch_read(pbuffer, *plen);
if (ok < 0) return 0;
if (ok & 1) ++ok;
*plen = ok;
*phashed =
*phash_index =
*pbroadcast =
*pcorrect_mac =
*pcrc_error = 0;
/* this frame has been received correctly */
*prx_ok = 1;
return 1;
}
#endif /* ifdef HAVE_RAWNET */

View File

@ -66,6 +66,9 @@ extern int rawnet_arch_enumadapter_close(void);
extern char *rawnet_arch_get_standard_interface(void);
extern int rawnet_arch_read(void *buffer, int length);
extern int rawnet_arch_write(const void *buffer, int length);
extern int rawnet_arch_get_mtu(void);
extern int rawnet_arch_get_mac(uint8_t mac[6]);

View File

@ -347,52 +347,7 @@ static void fix_outgoing_packet(uint8_t *packet, unsigned size, const uint8_t re
}
void rawnet_arch_transmit(int force, int onecoll, int inhibit_crc, int tx_pad_dis, int txlength, uint8_t *txframe) {
int count = 1;
vmnet_return_t st;
struct vmpktdesc v;
struct iovec iov;
if (txlength == 0) return;
if (txlength > interface_packet_size) {
log_message(rawnet_arch_log, "packet is too big: %d", txlength);
return;
}
if (txlength < 12) {
log_message(rawnet_arch_log, "packet is too small: %d", txlength);
return;
}
/* copy the buffer and fix the source mac address. */
memcpy(interface_buffer, txframe, txlength);
fix_outgoing_packet(interface_buffer, txlength, interface_mac, interface_fake_mac);
iov.iov_base = interface_buffer;
iov.iov_len = txlength;
v.vm_pkt_size = txlength;
v.vm_pkt_iov = &iov;
v.vm_pkt_iovcnt = 1;
v.vm_flags = 0;
fprintf(stderr, "\nrawnet_arch_transmit: %u\n", (unsigned)iov.iov_len);
rawnet_hexdump(interface_buffer, v.vm_pkt_size);
st = vmnet_write(interface, &v, &count);
if (st != VMNET_SUCCESS) {
log_message(rawnet_arch_log, "vmnet_write failed!");
}
return;
}
int rawnet_arch_receive(uint8_t *pbuffer, int *plen, int *phashed, int *phash_index, int *prx_ok, int *pcorrect_mac, int *pbroadcast, int *pcrc_error) {
int rawnet_arch_read(void *buffer, int nbyte) {
int count = 1;
int xfer;
@ -410,8 +365,8 @@ int rawnet_arch_receive(uint8_t *pbuffer, int *plen, int *phashed, int *phash_in
st = vmnet_read(interface, &v, &count);
if (st != VMNET_SUCCESS) {
log_message(rawnet_arch_log, "vmnet_write failed!");
return 0;
log_message(rawnet_arch_log, "vmnet_read failed!");
return -1;
}
if (count < 1) {
@ -427,40 +382,54 @@ int rawnet_arch_receive(uint8_t *pbuffer, int *plen, int *phashed, int *phash_in
}
xfer = v.vm_pkt_size;
if (xfer > *plen) xfer = *plen;
memcpy(pbuffer, interface_buffer, xfer);
memcpy(buffer, interface_buffer, xfer);
xfer = v.vm_pkt_size;
if (xfer & 0x01) ++xfer; /* ??? */
*plen = xfer; /* actual frame size */
*phashed =
*phash_index =
*pbroadcast =
*pcorrect_mac =
*pcrc_error = 0;
*prx_ok = 1;
#if 0
*pcorrect_mac = memcmp(interface_buffer, interface_mac, 6) == 0;
*pbroadcast = memcmp(interface_buffer, broadcast_mac, 6) == 0;
#endif
/* vmnet won't send promiscuous packets */
#if 0
hashreg = (~crc32_buf(interface_buffer, 6) >> 26) & 0x3f;
if (hash_mask[hashreg >= 32] & (1 << (hashreg & 0x1F))) {
*phashed = 1;
*phash_index = hashreg;
} else {
*phashed = 0;
*phash_index = 0;
}
#endif
return 1;
return xfer;
}
int rawnet_arch_write(const void *buffer, int nbyte) {
int count = 1;
vmnet_return_t st;
struct vmpktdesc v;
struct iovec iov;
if (nbyte <= 0) return 0;
if (nbyte > interface_packet_size) {
log_message(rawnet_arch_log, "packet is too big: %d", nbyte);
return -1;
}
/* copy the buffer and fix the source mac address. */
memcpy(interface_buffer, buffer, nbyte);
fix_outgoing_packet(interface_buffer, nbyte, interface_mac, interface_fake_mac);
iov.iov_base = interface_buffer;
iov.iov_len = nbyte;
v.vm_pkt_size = nbyte;
v.vm_pkt_iov = &iov;
v.vm_pkt_iovcnt = 1;
v.vm_flags = 0;
fprintf(stderr, "\nrawnet_arch_transmit: %u\n", (unsigned)iov.iov_len);
rawnet_hexdump(interface_buffer, v.vm_pkt_size);
st = vmnet_write(interface, &v, &count);
if (st != VMNET_SUCCESS) {
log_message(rawnet_arch_log, "vmnet_write failed!");
return -1;
}
return nbyte;
}
static unsigned adapter_index = 0;
int rawnet_arch_enumadapter_open(void) {
adapter_index = 0;

View File

@ -142,23 +142,12 @@ void rawnet_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver) {
/* NOP */
}
void rawnet_arch_transmit(int force, int onecoll, int inhibit_crc, int tx_pad_dis, int txlength, uint8_t *txframe) {
ssize_t ok = write(interface_fd, txframe, txlength);
int rawnet_arch_read(void *buffer, int nbyte) {
return read(interface_fd, buffer, nbyte);
}
int rawnet_arch_receive(uint8_t *pbuffer, int *plen, int *phashed, int *phash_index, int *prx_ok, int *pcorrect_mac, int *pbroadcast, int *pcrc_error) {
int count = *plen;
ssize_t ok = read(interface_fd, pbuffer, count);
if (ok < 0) return 0;
if (ok & 0x01) ++ok; /* ??? */
*plen = ok;
*prx_ok = 1;
*phashed = *pcorrect_mac = *pbroadcast = *pcrc_error = 0;
return 1;
int rawnet_arch_write(const void *buffer, int nbyte) {
return write(interface_fd, buffer, nbyte);
}

View File

@ -388,30 +388,25 @@ static int rawnet_arch_receive_frame(rawnet_pcap_internal_t *pinternal)
return ret;
}
int rawnet_arch_read(void *buffer, int nbyte) {
/** \brief Transmit a frame
*
* \param[in] force Delete waiting frames in transmit buffer
* \param[in] onecoll Terminate after just one collision
* \param[in] inhibit_crc Do not append CRC to the transmission
* \param[in] tx_pad_dis Disable padding to 60 Bytes
* \param[in] txlength Frame length
* \param[in] txframe Pointer to the frame to be transmitted
*/
void rawnet_arch_transmit(int force, int onecoll, int inhibit_crc,
int tx_pad_dis, int txlength, uint8_t *txframe)
{
int len;
#ifdef RAWNET_DEBUG_ARCH
log_message(rawnet_arch_log,
"rawnet_arch_transmit() called, with: force = %s, onecoll = %s, "
"inhibit_crc=%s, tx_pad_dis=%s, txlength=%u",
force ? "TRUE" : "FALSE",
onecoll ? "TRUE" : "FALSE",
inhibit_crc ? "TRUE" : "FALSE",
tx_pad_dis ? "TRUE" : "FALSE",
txlength);
#endif
rawnet_pcap_internal_t internal = { nbyte, (uint8_t *)buffer };
len = rawnet_arch_receive_frame(&internal);
if (len <= 0) return len;
#ifdef RAWNET_DEBUG_PKTDUMP
debug_output("Received frame: ", internal.buffer, internal.len);
#endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
return len;
}
int rawnet_arch_write(const void *buffer, int nbyte) {
#ifdef RAWNET_DEBUG_PKTDUMP
debug_output("Transmit frame: ", txframe, txlength);
@ -419,97 +414,12 @@ void rawnet_arch_transmit(int force, int onecoll, int inhibit_crc,
if (pcap_sendpacket(rawnet_pcap_fp, txframe, txlength) < 0) {
log_message(rawnet_arch_log, "WARNING! Could not send packet!");
return -1;
}
return nbyte;
}
/**
* \brief Check if a frame was received
*
* This function checks if there was a frame received. If so, it returns 1,
* else 0.
*
* If there was no frame, none of the parameters is changed!
*
* If there was a frame, the following actions are done:
*
* - at maximum \a plen byte are transferred into the buffer given by \a pbuffer
* - \a plen gets the length of the received frame, EVEN if this is more
* than has been copied to \a pbuffer!
* - if the dest. address was accepted by the hash filter, \a phashed is set,
* else cleared.
* - if the dest. address was accepted by the hash filter, \a phash_index is
* set to the number of the rule leading to the acceptance
* - if the receive was ok (good CRC and valid length), \a *prx_ok is set, else
* cleared.
* - if the dest. address was accepted because it's exactly our MAC address
* (set by rawnet_arch_set_mac()), \a pcorrect_mac is set, else cleared.
* - if the dest. address was accepted since it was a broadcast address,
* \a pbroadcast is set, else cleared.
* - if the received frame had a crc error, \a pcrc_error is set, else cleared
*
* \param[out] buffer where to store a frame
* \param[in,out] plen IN: maximum length of frame to copy;
* OUT: length of received frame OUT
* can be bigger than IN if received frame was
* longer than supplied buffer
* \param[out] phashed set if the dest. address is accepted by the
* hash filter
* \param[out] phash_index hash table index if hashed == TRUE
* \param[out] prx_ok set if good CRC and valid length
* \param[out] pcorrect_mac set if dest. address is exactly our IA
* \param[out[ pbroadcast set if dest. address is a broadcast address
* \param[out] pcrc_error set if received frame had a CRC error
*/
int rawnet_arch_receive(uint8_t *pbuffer, int *plen, int *phashed,
int *phash_index, int *prx_ok, int *pcorrect_mac, int *pbroadcast,
int *pcrc_error)
{
int len;
rawnet_pcap_internal_t internal = { *plen, pbuffer };
#ifdef RAWNET_DEBUG_ARCH
log_message(rawnet_arch_log,
"rawnet_arch_receive() called, with *plen=%u.",
*plen);
#endif
assert((*plen & 1) == 0);
len = rawnet_arch_receive_frame(&internal);
if (len != -1) {
#ifdef RAWNET_DEBUG_PKTDUMP
debug_output("Received frame: ", internal.buffer, internal.len);
#endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
if (len & 1) {
++len;
}
*plen = len;
/* we don't decide if this frame fits the needs;
* by setting all zero, we let tfe.c do the work
* for us
*/
*phashed =
*phash_index =
*pbroadcast =
*pcorrect_mac =
*pcrc_error = 0;
/* this frame has been received correctly */
*prx_ok = 1;
return 1;
}
return 0;
}
/** \brief Find default device on which to capture
*

View File

@ -438,23 +438,29 @@ static int rawnet_arch_receive_frame(Ethernet_PCAP_internal_t *pinternal)
return ret;
}
/* int force - FORCE: Delete waiting frames in transmit buffer */
/* int onecoll - ONECOLL: Terminate after just one collision */
/* int inhibit_crc - INHIBITCRC: Do not append CRC to the transmission */
/* int tx_pad_dis - TXPADDIS: Disable padding to 60 Bytes */
/* int txlength - Frame length */
/* uint8_t *txframe - Pointer to the frame to be transmitted */
void rawnet_arch_transmit(int force, int onecoll, int inhibit_crc, int tx_pad_dis, int txlength, uint8_t *txframe)
{
#ifdef RAWNET_DEBUG_ARCH
log_message(rawnet_arch_log, "rawnet_arch_transmit() called, with: force = %s, onecoll = %s, inhibit_crc=%s, tx_pad_dis=%s, txlength=%u",
force ? "TRUE" : "FALSE",
onecoll ? "TRUE" : "FALSE",
inhibit_crc ? "TRUE" : "FALSE",
tx_pad_dis ? "TRUE" : "FALSE",
txlength);
#endif
int rawnet_arch_read(void *buffer, int nbyte) {
int len;
Ethernet_PCAP_internal_t internal;
internal.len = nbyte;
internal.buffer = (uint8_t *)buffer;
len = rawnet_arch_receive_frame(&internal);
if (len <= 0) return len;
#ifdef RAWNET_DEBUG_PKTDUMP
debug_output("Received frame: ", internal.buffer, internal.len);
#endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
return len;
}
int rawnet_arch_write(const void *buffer, int nbyte) {
#ifdef RAWNET_DEBUG_PKTDUMP
debug_output("Transmit frame: ", txframe, txlength);
@ -462,9 +468,12 @@ void rawnet_arch_transmit(int force, int onecoll, int inhibit_crc, int tx_pad_di
if ((*p_pcap_sendpacket)(EthernetPcapFP, txframe, txlength) == -1) {
log_message(rawnet_arch_log, "WARNING! Could not send packet!");
return -1;
}
return nbyte;
}
/*
rawnet_arch_receive()