mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-24 14:49:53 -06:00
complete DHCP. ARP for the DHCP server. feed in proper DNS settings.
This commit is contained in:
@ -74,6 +74,7 @@ int NumAdapters = 0;
|
|||||||
|
|
||||||
void* PCapLib = NULL;
|
void* PCapLib = NULL;
|
||||||
pcap_t* PCapAdapter = NULL;
|
pcap_t* PCapAdapter = NULL;
|
||||||
|
AdapterData* PCapAdapterData;
|
||||||
|
|
||||||
u8 PCapPacketBuffer[2048];
|
u8 PCapPacketBuffer[2048];
|
||||||
int PCapPacketLen;
|
int PCapPacketLen;
|
||||||
@ -249,13 +250,14 @@ bool Init()
|
|||||||
#endif // __WIN32__
|
#endif // __WIN32__
|
||||||
|
|
||||||
// open pcap device
|
// open pcap device
|
||||||
dev = (pcap_if_t*)Adapters[0].Internal;
|
PCapAdapterData = &Adapters[0];
|
||||||
for (int i = 0; i < NumAdapters; i++)
|
for (int i = 0; i < NumAdapters; i++)
|
||||||
{
|
{
|
||||||
if (!strncmp(Adapters[i].DeviceName, Config::LANDevice, 128))
|
if (!strncmp(Adapters[i].DeviceName, Config::LANDevice, 128))
|
||||||
dev = (pcap_if_t*)Adapters[i].Internal;
|
PCapAdapterData = &Adapters[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev = (pcap_if_t*)PCapAdapterData->Internal;
|
||||||
PCapAdapter = pcap_open_live(dev->name, 2048, PCAP_OPENFLAG_PROMISCUOUS, 1, errbuf);
|
PCapAdapter = pcap_open_live(dev->name, 2048, PCAP_OPENFLAG_PROMISCUOUS, 1, errbuf);
|
||||||
if (!PCapAdapter)
|
if (!PCapAdapter)
|
||||||
{
|
{
|
||||||
@ -336,7 +338,8 @@ zarp=transid;
|
|||||||
|
|
||||||
printf("DHCP: frame type %d, transid %08X\n", type, transid);
|
printf("DHCP: frame type %d, transid %08X\n", type, transid);
|
||||||
|
|
||||||
if (type == 1) // discover
|
if (type == 1 || // discover
|
||||||
|
type == 3) // request
|
||||||
{
|
{
|
||||||
u8 resp[512];
|
u8 resp[512];
|
||||||
u8* out = &resp[0];
|
u8* out = &resp[0];
|
||||||
@ -359,7 +362,14 @@ zarp=transid;
|
|||||||
*out++ = 0x11; // protocol (UDP)
|
*out++ = 0x11; // protocol (UDP)
|
||||||
*(u16*)out = 0; out += 2; // checksum
|
*(u16*)out = 0; out += 2; // checksum
|
||||||
*(u32*)out = htonl(serverip); out += 4; // source IP
|
*(u32*)out = htonl(serverip); out += 4; // source IP
|
||||||
*(u32*)out = htonl(0xFFFFFFFF); out += 4; // destination IP
|
if (type == 1)
|
||||||
|
{
|
||||||
|
*(u32*)out = htonl(0xFFFFFFFF); out += 4; // destination IP
|
||||||
|
}
|
||||||
|
else if (type == 3)
|
||||||
|
{
|
||||||
|
*(u32*)out = htonl(clientip); out += 4; // destination IP
|
||||||
|
}
|
||||||
|
|
||||||
// UDP
|
// UDP
|
||||||
u8* udpheader = out;
|
u8* udpheader = out;
|
||||||
@ -388,7 +398,7 @@ zarp=transid;
|
|||||||
|
|
||||||
// DHCP options
|
// DHCP options
|
||||||
*out++ = 53; *out++ = 1;
|
*out++ = 53; *out++ = 1;
|
||||||
*out++ = 2; // DHCP type: offer
|
*out++ = (type==1) ? 2 : 5; // DHCP type: offer/ack
|
||||||
*out++ = 1; *out++ = 4;
|
*out++ = 1; *out++ = 4;
|
||||||
*(u32*)out = htonl(0xFFFFFF00); out += 4; // subnet mask
|
*(u32*)out = htonl(0xFFFFFF00); out += 4; // subnet mask
|
||||||
*out++ = 3; *out++ = 4;
|
*out++ = 3; *out++ = 4;
|
||||||
@ -397,8 +407,22 @@ zarp=transid;
|
|||||||
*(u32*)out = htonl(442030); out += 4; // lease time
|
*(u32*)out = htonl(442030); out += 4; // lease time
|
||||||
*out++ = 54; *out++ = 4;
|
*out++ = 54; *out++ = 4;
|
||||||
*(u32*)out = htonl(serverip); out += 4; // DHCP server
|
*(u32*)out = htonl(serverip); out += 4; // DHCP server
|
||||||
*out++ = 6; *out++ = 4;
|
|
||||||
*(u32*)out = htonl(0x08080808); out += 4; // DNS (TODO!!)
|
u8 numdns = 0;
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (*(u32*)&PCapAdapterData->DNS[i][0] != 0)
|
||||||
|
numdns++;
|
||||||
|
}
|
||||||
|
*out++ = 6; *out++ = 4*numdns;
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
u32 dnsip = *(u32*)&PCapAdapterData->DNS[i][0];
|
||||||
|
if (dnsip != 0)
|
||||||
|
{
|
||||||
|
*(u32*)out = htonl(dnsip); out += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*out++ = 0xFF;
|
*out++ = 0xFF;
|
||||||
memset(out, 0, 20); out += 20;
|
memset(out, 0, 20); out += 20;
|
||||||
@ -454,22 +478,87 @@ zarp=transid;
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HandleARPFrame(u8* data, int len)
|
||||||
|
{
|
||||||
|
const u32 serverip = 0x0A404001;
|
||||||
|
const u32 clientip = 0x0A404010;
|
||||||
|
|
||||||
|
u16 protocol = ntohs(*(u16*)&data[0x10]);
|
||||||
|
if (protocol != 0x0800) return false;
|
||||||
|
|
||||||
|
u16 op = ntohs(*(u16*)&data[0x14]);
|
||||||
|
u32 targetip = ntohl(*(u32*)&data[0x26]);
|
||||||
|
|
||||||
|
if (op == 1 && targetip == serverip)
|
||||||
|
{
|
||||||
|
// opcode 1=req 2=reply
|
||||||
|
// sender MAC
|
||||||
|
// sender IP
|
||||||
|
// target MAC
|
||||||
|
// target IP
|
||||||
|
|
||||||
|
u8 resp[64];
|
||||||
|
u8* out = &resp[0];
|
||||||
|
|
||||||
|
// ethernet
|
||||||
|
memcpy(out, &data[6], 6); out += 6;
|
||||||
|
*out++ = 0x00; *out++ = 0xAB; *out++ = 0x33;
|
||||||
|
*out++ = 0x28; *out++ = 0x99; *out++ = 0x44;
|
||||||
|
*(u16*)out = htons(0x0806); out += 2;
|
||||||
|
|
||||||
|
// ARP
|
||||||
|
*(u16*)out = htons(0x0001); out += 2; // hardware type
|
||||||
|
*(u16*)out = htons(0x0800); out += 2; // protocol
|
||||||
|
*out++ = 6; // MAC address size
|
||||||
|
*out++ = 4; // IP address size
|
||||||
|
*(u16*)out = htons(0x0002); out += 2; // opcode
|
||||||
|
*out++ = 0x00; *out++ = 0xAB; *out++ = 0x33;
|
||||||
|
*out++ = 0x28; *out++ = 0x99; *out++ = 0x44;
|
||||||
|
*(u32*)out = htonl(targetip); out += 4;
|
||||||
|
memcpy(out, &data[0x16], 6+4); out += 6+4;
|
||||||
|
|
||||||
|
u32 framelen = (u32)(out - &resp[0]);
|
||||||
|
|
||||||
|
// TODO: if there is already a packet queued, this will overwrite it
|
||||||
|
// that being said, this will only happen during DHCP setup, so probably
|
||||||
|
// not a big deal
|
||||||
|
|
||||||
|
PCapPacketLen = framelen;
|
||||||
|
memcpy(PCapPacketBuffer, resp, PCapPacketLen);
|
||||||
|
PCapRXNum = 1;
|
||||||
|
|
||||||
|
// also broadcast them to the network
|
||||||
|
pcap_sendpacket(PCapAdapter, data, len);
|
||||||
|
pcap_sendpacket(PCapAdapter, resp, framelen);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool HandlePacket(u8* data, int len)
|
bool HandlePacket(u8* data, int len)
|
||||||
{
|
{
|
||||||
if (ntohs(*(u16*)&data[0xC]) != 0x0800) // IPv4
|
u16 ethertype = ntohs(*(u16*)&data[0xC]);
|
||||||
return false;
|
|
||||||
|
|
||||||
u8 protocol = data[0x17];
|
if (ethertype == 0x0800) // IPv4
|
||||||
if (protocol == 0x11) // UDP
|
|
||||||
{
|
{
|
||||||
u16 srcport = ntohs(*(u16*)&data[0x22]);
|
u8 protocol = data[0x17];
|
||||||
u16 dstport = ntohs(*(u16*)&data[0x24]);
|
if (protocol == 0x11) // UDP
|
||||||
if (srcport == 68 && dstport == 67) // DHCP
|
|
||||||
{
|
{
|
||||||
printf("LANMAGIC: DHCP packet\n");
|
u16 srcport = ntohs(*(u16*)&data[0x22]);
|
||||||
return HandleDHCPFrame(data, len);
|
u16 dstport = ntohs(*(u16*)&data[0x24]);
|
||||||
|
if (srcport == 68 && dstport == 67) // DHCP
|
||||||
|
{
|
||||||
|
printf("LANMAGIC: DHCP packet\n");
|
||||||
|
return HandleDHCPFrame(data, len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ethertype == 0x0806) // ARP
|
||||||
|
{
|
||||||
|
return HandleARPFrame(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user