Uthernet II: implement getMACAddress for libslirp.
Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
parent
b5ec2343fb
commit
a4bdf7ec53
4 changed files with 38 additions and 15 deletions
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue