complete DHCP. ARP for the DHCP server. feed in proper DNS settings.

This commit is contained in:
Arisotura 2019-02-23 18:50:58 +01:00
parent 93d51b0cbc
commit c135670b9c
1 changed files with 105 additions and 16 deletions

View File

@ -74,6 +74,7 @@ int NumAdapters = 0;
void* PCapLib = NULL;
pcap_t* PCapAdapter = NULL;
AdapterData* PCapAdapterData;
u8 PCapPacketBuffer[2048];
int PCapPacketLen;
@ -249,13 +250,14 @@ bool Init()
#endif // __WIN32__
// open pcap device
dev = (pcap_if_t*)Adapters[0].Internal;
PCapAdapterData = &Adapters[0];
for (int i = 0; i < NumAdapters; i++)
{
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);
if (!PCapAdapter)
{
@ -336,7 +338,8 @@ zarp=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* out = &resp[0];
@ -359,7 +362,14 @@ zarp=transid;
*out++ = 0x11; // protocol (UDP)
*(u16*)out = 0; out += 2; // checksum
*(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
u8* udpheader = out;
@ -388,7 +398,7 @@ zarp=transid;
// DHCP options
*out++ = 53; *out++ = 1;
*out++ = 2; // DHCP type: offer
*out++ = (type==1) ? 2 : 5; // DHCP type: offer/ack
*out++ = 1; *out++ = 4;
*(u32*)out = htonl(0xFFFFFF00); out += 4; // subnet mask
*out++ = 3; *out++ = 4;
@ -397,8 +407,22 @@ zarp=transid;
*(u32*)out = htonl(442030); out += 4; // lease time
*out++ = 54; *out++ = 4;
*(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;
memset(out, 0, 20); out += 20;
@ -454,22 +478,87 @@ zarp=transid;
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)
{
if (ntohs(*(u16*)&data[0xC]) != 0x0800) // IPv4
return false;
u16 ethertype = ntohs(*(u16*)&data[0xC]);
u8 protocol = data[0x17];
if (protocol == 0x11) // UDP
if (ethertype == 0x0800) // IPv4
{
u16 srcport = ntohs(*(u16*)&data[0x22]);
u16 dstport = ntohs(*(u16*)&data[0x24]);
if (srcport == 68 && dstport == 67) // DHCP
u8 protocol = data[0x17];
if (protocol == 0x11) // UDP
{
printf("LANMAGIC: DHCP packet\n");
return HandleDHCPFrame(data, len);
u16 srcport = ntohs(*(u16*)&data[0x22]);
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;
}