Uthernet II: implement getMACAddress for libslirp.

Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
Andrea Odetti 2022-03-20 16:35:44 +00:00
parent b5ec2343fb
commit a4bdf7ec53
4 changed files with 38 additions and 15 deletions

View file

@ -77,15 +77,13 @@ namespace
return sum;
}
uint16_t checksum(const void *addr, int count, int start_sum)
uint16_t checksum(const void *addr, int count)
{
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
* Taken from https://tools.ietf.org/html/rfc1071
*/
uint32_t sum = start_sum;
sum += sum_every_16bits(addr, count);
uint32_t sum = sum_every_16bits(addr, count);
/* Fold 32-bit sum to 16 bits */
while (sum >> 16)
@ -97,7 +95,7 @@ namespace
}
std::vector<uint8_t> createETH2Frame(const std::vector<uint8_t> &data,
const MACAddress * sourceMac, const MACAddress *destinationMac,
const MACAddress *sourceMac, const MACAddress *destinationMac,
const uint8_t ttl, const uint8_t tos, const uint8_t protocol,
const uint32_t sourceAddress, const uint32_t destinationAddress)
{
@ -119,7 +117,7 @@ std::vector<uint8_t> createETH2Frame(const std::vector<uint8_t> &data,
ip4header->proto = protocol;
ip4header->sourceAddress = sourceAddress;
ip4header->destinationAddress = destinationAddress;
ip4header->checksum = checksum(ip4header, sizeof(IP4Header), 0);
ip4header->checksum = checksum(ip4header, sizeof(IP4Header));
memcpy(frame.data() + sizeof(ETH2Frame) + sizeof(IP4Header), data.data(), data.size());

View file

@ -677,7 +677,7 @@ void Uthernet2::sendDataIPRaw(const size_t i, std::vector<uint8_t> &payload)
const MACAddress * sourceMac = reinterpret_cast<const MACAddress *>(myMemory.data() + W5100_SHAR0);
const MACAddress * destinationMac;
GetMACAddress(destination, destinationMac);
getMACAddress(destination, destinationMac);
std::vector<uint8_t> packet = createETH2Frame(payload, sourceMac, destinationMac, ttl, tos, protocol, source, destination);
@ -1293,7 +1293,7 @@ void Uthernet2::InitializeIO(LPBYTE pCxRomPeripheral)
RegisterIoHandler(m_slot, u2_C0, u2_C0, nullptr, nullptr, this, nullptr);
}
void Uthernet2::GetMACAddress(const uint32_t address, const MACAddress * & mac)
void Uthernet2::getMACAddress(const uint32_t address, const MACAddress * & mac)
{
const auto it = myARPTable.find(address);
if (it != myARPTable.end())
@ -1303,12 +1303,31 @@ void Uthernet2::GetMACAddress(const uint32_t address, const MACAddress * & mac)
else
{
MACAddress & macAddr = myARPTable[address];
memset(macAddr.address, 0xFF, sizeof(macAddr.address));
const uint32_t source = readAddress(myMemory.data() + W5100_SIPR0);
// need to handle the case of the W5100 self address unknown to Windows
if (address != INADDR_BROADCAST)
if (address == source)
{
myNetworkBackend->getMACAddress(address, macAddr);
const uint8_t * sourceMac = myMemory.data() + W5100_SHAR0;
memcpy(macAddr.address, sourceMac, sizeof(macAddr.address));
}
else
{
memset(macAddr.address, 0xFF, sizeof(macAddr.address)); // fallback to broadcast
if (address != INADDR_BROADCAST)
{
const uint32_t subnet = readAddress(myMemory.data() + W5100_SUBR0);
if ((address & subnet) == (source & subnet))
{
// same network: send ARP request
myNetworkBackend->getMACAddress(address, macAddr);
}
else
{
const uint32_t gateway = readAddress(myMemory.data() + W5100_GAR0);
// different network: go via gateway
myNetworkBackend->getMACAddress(gateway, macAddr);
}
}
}
mac = &macAddr;
}

View file

@ -81,7 +81,7 @@ private:
std::map<uint32_t, MACAddress> myARPTable;
void GetMACAddress(const uint32_t address, const MACAddress * & mac);
void getMACAddress(const uint32_t address, const MACAddress * & mac);
void setSocketModeRegister(const size_t i, const uint16_t address, const uint8_t value);
void setTXSizes(const uint16_t address, uint8_t value);

View file

@ -202,9 +202,15 @@ bool SlirpBackend::isValid()
return true;
}
void SlirpBackend::getMACAddress(const uint32_t /* address */, MACAddress & /* mac */)
void SlirpBackend::getMACAddress(const uint32_t address, MACAddress & mac)
{
// not needed for libslirp
// a bit of a hack, I've found out that slirp uses
/* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
// https://gitlab.freedesktop.org/slirp/libslirp/-/blob/bf917b89d64f57d9302aba4b2f027ea68fb78c13/src/slirp.c#L78
mac.address[0] = 0x52;
mac.address[1] = 0x55;
uint32_t * ptr = reinterpret_cast<uint32_t *>(mac.address + 2);
*ptr = address;
}
#endif