Commented DHCP code.
git-svn-id: https://spexeah.com:8443/svn/Asuro@1046 6dbc8c32-bb84-406f-8558-d1cf31a0ab0c
This commit is contained in:
parent
03f7d618cb
commit
5e4308ab2d
@ -47,6 +47,7 @@ var
|
|||||||
i : uint8;
|
i : uint8;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{ Null the entire configuration ready for a new DISCOVER or REQUEST }
|
||||||
if configuration <> nil then begin
|
if configuration <> nil then begin
|
||||||
Configuration^.Transaction:= 0;
|
Configuration^.Transaction:= 0;
|
||||||
for i:=0 to 255 do begin
|
for i:=0 to 255 do begin
|
||||||
@ -64,6 +65,7 @@ var
|
|||||||
MAC : puint8;
|
MAC : puint8;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{ Create a basic header with most values nulled, Hardware type & length is prefilled for ethernet }
|
||||||
tracer.push_trace('dhcp.newHeader');
|
tracer.push_trace('dhcp.newHeader');
|
||||||
result:= PDHCPHeader(kalloc(sizeof(TDHCPHeader)));
|
result:= PDHCPHeader(kalloc(sizeof(TDHCPHeader)));
|
||||||
result^.Message_Type:= $01;
|
result^.Message_Type:= $01;
|
||||||
@ -91,6 +93,7 @@ var
|
|||||||
Option : PDHCPOption;
|
Option : PDHCPOption;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{ Add an option to the Options linkedlist, copy data[size] to the Option }
|
||||||
tracer.push_trace('dhcp.newOption');
|
tracer.push_trace('dhcp.newOption');
|
||||||
Option:= PDHCPOption(LL_Add(PLinkedListBase(DHCPOptions)));
|
Option:= PDHCPOption(LL_Add(PLinkedListBase(DHCPOptions)));
|
||||||
Option^.Opcode:= Opcode;
|
Option^.Opcode:= Opcode;
|
||||||
@ -110,6 +113,7 @@ var
|
|||||||
Option : PDHCPOption;
|
Option : PDHCPOption;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{ Remove an option from the linkedlsit }
|
||||||
tracer.push_trace('dhcp.deleteOptions');
|
tracer.push_trace('dhcp.deleteOptions');
|
||||||
Option:= PDHCPOption(LL_Get(PLinkedListBase(DHCPOptions), idx));
|
Option:= PDHCPOption(LL_Get(PLinkedListBase(DHCPOptions), idx));
|
||||||
if Option <> nil then begin
|
if Option <> nil then begin
|
||||||
@ -122,18 +126,21 @@ end;
|
|||||||
|
|
||||||
function getOption(DHCPOptions : PDHCPOptions; idx : uint32) : PDHCPOption;
|
function getOption(DHCPOptions : PDHCPOptions; idx : uint32) : PDHCPOption;
|
||||||
begin
|
begin
|
||||||
|
{ Get an option by index from the linkedlist }
|
||||||
tracer.push_trace('dhcp.getOption');
|
tracer.push_trace('dhcp.getOption');
|
||||||
getOption:= PDHCPOption(LL_Get(PLinkedListBase(DHCPOptions),idx));
|
getOption:= PDHCPOption(LL_Get(PLinkedListBase(DHCPOptions),idx));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function newOptions : PDHCPOptions;
|
function newOptions : PDHCPOptions;
|
||||||
begin
|
begin
|
||||||
|
{ Create a new Options LinkedList }
|
||||||
tracer.push_trace('dhcp.newOptions');
|
tracer.push_trace('dhcp.newOptions');
|
||||||
newOptions:= PDHCPOptions(LL_New(sizeof(TDHCPOption)));
|
newOptions:= PDHCPOptions(LL_New(sizeof(TDHCPOption)));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure freeOptions(Options : PDHCPOptions);
|
procedure freeOptions(Options : PDHCPOptions);
|
||||||
begin
|
begin
|
||||||
|
{ Free all options and free their underlying data buffers }
|
||||||
tracer.push_trace('dhcp.freeOptions');
|
tracer.push_trace('dhcp.freeOptions');
|
||||||
if Options <> nil then begin
|
if Options <> nil then begin
|
||||||
while LL_Size(PLinkedListBase(Options)) > 0 do begin
|
while LL_Size(PLinkedListBase(Options)) > 0 do begin
|
||||||
@ -145,6 +152,7 @@ end;
|
|||||||
|
|
||||||
function getOptionsCount(Options : PDHCPOptions) : uint32;
|
function getOptionsCount(Options : PDHCPOptions) : uint32;
|
||||||
begin
|
begin
|
||||||
|
{ Get the number of options in the linkedlist }
|
||||||
tracer.push_trace('dhcp.getOptionsCount');
|
tracer.push_trace('dhcp.getOptionsCount');
|
||||||
getOptionsCount:= LL_Size(PLinkedListBase(Options));
|
getOptionsCount:= LL_Size(PLinkedListBase(Options));
|
||||||
end;
|
end;
|
||||||
@ -156,11 +164,19 @@ var
|
|||||||
OptionsSize : uint16;
|
OptionsSize : uint16;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{
|
||||||
|
Get the size of all options in the linkedlist
|
||||||
|
1 byte for the opcode
|
||||||
|
1 byte for the length
|
||||||
|
n bytes (specified by length) for the data
|
||||||
|
total = foreach(element):(sizeof(opcode)+sizeof(length)+length)
|
||||||
|
}
|
||||||
tracer.push_trace('dhcp.calculateOptionsSize');
|
tracer.push_trace('dhcp.calculateOptionsSize');
|
||||||
OptionsSize := 0;
|
OptionsSize := 0;
|
||||||
for i:=0 to getOptionsCount(Options)-1 do begin
|
for i:=0 to getOptionsCount(Options)-1 do begin
|
||||||
Option:= PDHCPOption(LL_Get(PLinkedListBase(Options),i));
|
Option:= PDHCPOption(LL_Get(PLinkedListBase(Options),i));
|
||||||
case Option^.Opcode of
|
case Option^.Opcode of
|
||||||
|
{ PAD & END_VENDOR_OPTIONS are special cases as they are 1 byte in length with no size byte }
|
||||||
PAD,END_VENDOR_OPTIONS : inc(OptionsSize,1);
|
PAD,END_VENDOR_OPTIONS : inc(OptionsSize,1);
|
||||||
else inc(OptionsSize, 2 + Option^.Size);
|
else inc(OptionsSize, 2 + Option^.Size);
|
||||||
end;
|
end;
|
||||||
@ -173,6 +189,7 @@ var
|
|||||||
Value : uint16;
|
Value : uint16;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{ Get the value from an Option as an endian corrected (if applicable) uint16 }
|
||||||
tracer.push_trace('dhcp.getEndianCorrectValue16');
|
tracer.push_trace('dhcp.getEndianCorrectValue16');
|
||||||
Value:= PuInt16(Option^.Value)^;
|
Value:= PuInt16(Option^.Value)^;
|
||||||
if Option^.Reverse_Endian then
|
if Option^.Reverse_Endian then
|
||||||
@ -185,6 +202,7 @@ function getEndianCorrectValue32(Option : PDHCPOption) : uint32;
|
|||||||
var
|
var
|
||||||
Value : uint32;
|
Value : uint32;
|
||||||
begin
|
begin
|
||||||
|
{ Get the value from an Option as an endian corrected (if applicable) uint32 }
|
||||||
tracer.push_trace('dhcp.getEndianCorrectValue32');
|
tracer.push_trace('dhcp.getEndianCorrectValue32');
|
||||||
Value:= puint32(Option^.Value)^;
|
Value:= puint32(Option^.Value)^;
|
||||||
if Option^.Reverse_Endian then
|
if Option^.Reverse_Endian then
|
||||||
@ -197,6 +215,7 @@ function readOption8(Option : PDHCPOption) : uint8;
|
|||||||
var
|
var
|
||||||
read8 : puint8;
|
read8 : puint8;
|
||||||
begin
|
begin
|
||||||
|
{ Read the option data as an 8-bit value }
|
||||||
read8:= puint8(Option^.Value);
|
read8:= puint8(Option^.Value);
|
||||||
readOption8:= read8^;
|
readOption8:= read8^;
|
||||||
end;
|
end;
|
||||||
@ -205,6 +224,7 @@ function readOption16(Option : PDHCPOption) : uint16;
|
|||||||
var
|
var
|
||||||
read16 : puint16;
|
read16 : puint16;
|
||||||
begin
|
begin
|
||||||
|
{ Read the option data as an 16-bit value }
|
||||||
read16:= puint16(Option^.Value);
|
read16:= puint16(Option^.Value);
|
||||||
readOption16:= read16^;
|
readOption16:= read16^;
|
||||||
end;
|
end;
|
||||||
@ -213,6 +233,7 @@ function readOption32(Option : PDHCPOption) : uint32;
|
|||||||
var
|
var
|
||||||
read32 : puint32;
|
read32 : puint32;
|
||||||
begin
|
begin
|
||||||
|
{ Read the option data as an 32-bit value }
|
||||||
read32:= puint32(Option^.Value);
|
read32:= puint32(Option^.Value);
|
||||||
readOption32:= read32^;
|
readOption32:= read32^;
|
||||||
end;
|
end;
|
||||||
@ -223,6 +244,7 @@ var
|
|||||||
i : uint16;
|
i : uint16;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{ Search the linked list for a given OpCode and return if found, nil if not. }
|
||||||
getOptionByOpcode:= nil;
|
getOptionByOpcode:= nil;
|
||||||
for i:=0 to getOptionsCount(Options)-1 do begin
|
for i:=0 to getOptionsCount(Options)-1 do begin
|
||||||
Option:= getOption(Options, i);
|
Option:= getOption(Options, i);
|
||||||
@ -248,30 +270,35 @@ var
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
tracer.push_trace('dhcp.writeOptions');
|
tracer.push_trace('dhcp.writeOptions');
|
||||||
|
|
||||||
|
{ Make room in our new packet buffer for the header + options }
|
||||||
OptionsSize := calculateOptionsSize(Options);
|
OptionsSize := calculateOptionsSize(Options);
|
||||||
TotalSize:= OptionsSize + SizeOf(TDHCPHeader);
|
TotalSize:= OptionsSize + SizeOf(TDHCPHeader);
|
||||||
NewBuffer:= kalloc(TotalSize);
|
NewBuffer:= kalloc(TotalSize);
|
||||||
|
|
||||||
//Copy over Header
|
{ Copy the header }
|
||||||
NewHeader:= PDHCPHeader(NewBuffer);
|
NewHeader:= PDHCPHeader(NewBuffer);
|
||||||
memcpy(uint32(Header), uint32(NewHeader), sizeof(TDHCPHeader));
|
memcpy(uint32(Header), uint32(NewHeader), sizeof(TDHCPHeader));
|
||||||
|
|
||||||
//Write all options
|
{ Write Options }
|
||||||
buffer:= puint8(NewBuffer);
|
buffer:= puint8(NewBuffer);
|
||||||
inc(buffer, SizeOf(TDHCPHeader));
|
inc(buffer, SizeOf(TDHCPHeader));
|
||||||
for i:=0 to getOptionsCount(Options)-1 do begin
|
for i:=0 to getOptionsCount(Options)-1 do begin
|
||||||
Option:= getOption(Options, i);
|
Option:= getOption(Options, i);
|
||||||
case Option^.Opcode of
|
case Option^.Opcode of
|
||||||
|
{ PAD & END_VENDOR_OPTIONS have a length of 0 & no length byte }
|
||||||
PAD,END_VENDOR_OPTIONS:begin
|
PAD,END_VENDOR_OPTIONS:begin
|
||||||
buffer^:= Ord(Option^.Opcode);
|
buffer^:= Ord(Option^.Opcode);
|
||||||
inc(buffer);
|
inc(buffer);
|
||||||
end;
|
end;
|
||||||
|
{ Everything else follows the format: uint8(OpCode)->uint8(Length)->variable(Data) }
|
||||||
else begin
|
else begin
|
||||||
buffer^:= Ord(Option^.OpCode);
|
buffer^:= Ord(Option^.OpCode);
|
||||||
inc(buffer);
|
inc(buffer);
|
||||||
buffer^:= Option^.Size;
|
buffer^:= Option^.Size;
|
||||||
inc(buffer);
|
inc(buffer);
|
||||||
case Option^.Size of
|
case Option^.Size of
|
||||||
|
{ Try to read and write using a 16bit or 32bit pointer for speed, else do a memcpy }
|
||||||
2:begin
|
2:begin
|
||||||
read16:= puint16(buffer);
|
read16:= puint16(buffer);
|
||||||
read16^:= getEndianCorrectValue16(Option);
|
read16^:= getEndianCorrectValue16(Option);
|
||||||
@ -288,6 +315,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
{ Return the new packet size a pointer to the packet (Header) }
|
||||||
newLength^:= TotalSize;
|
newLength^:= TotalSize;
|
||||||
writeOptions:= PDHCPHeader(NewBuffer);
|
writeOptions:= PDHCPHeader(NewBuffer);
|
||||||
end;
|
end;
|
||||||
@ -374,6 +402,7 @@ end;
|
|||||||
procedure processPacket_NAK(Header : PDHCPHeader; Options : PDHCPOptions);
|
procedure processPacket_NAK(Header : PDHCPHeader; Options : PDHCPOptions);
|
||||||
begin
|
begin
|
||||||
console.outputln('DHCP', 'Process NAK.');
|
console.outputln('DHCP', 'Process NAK.');
|
||||||
|
{ Server provided a NAK, NULL configuration ready for next DISCOVER/Request }
|
||||||
nullConfiguration();
|
nullConfiguration();
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -446,23 +475,25 @@ begin
|
|||||||
if Header^.Transaction_ID = Configuration^.Transaction then begin
|
if Header^.Transaction_ID = Configuration^.Transaction then begin
|
||||||
console.outputln('DHCP', 'XID Match');
|
console.outputln('DHCP', 'XID Match');
|
||||||
|
|
||||||
|
{ Create a new header to the use in our DHCP REQUEST packet }
|
||||||
SendHeader:= createHeader();
|
SendHeader:= createHeader();
|
||||||
CopyIPv4(puint8(@Header^.Your_IP[0]), puint8(@SendHeader^.Client_IP[0]));
|
CopyIPv4(puint8(@Header^.Your_IP[0]), puint8(@SendHeader^.Client_IP[0]));
|
||||||
CopyIPv4(puint8(@Header^.Server_IP[0]), puint8(@SendHeader^.Server_IP[0]));
|
CopyIPv4(puint8(@Header^.Server_IP[0]), puint8(@SendHeader^.Server_IP[0]));
|
||||||
processHeader(SendHeader);
|
processHeader(SendHeader);
|
||||||
|
|
||||||
|
{ Setup Options }
|
||||||
SendOptions:= newOptions();
|
SendOptions:= newOptions();
|
||||||
|
{ Create a message type option and assign it the value REQUEST }
|
||||||
SendMsgType:= ord(TDHCPMessageType.REQUEST);
|
SendMsgType:= ord(TDHCPMessageType.REQUEST);
|
||||||
|
|
||||||
NewOption(SendOptions, TDHCPOpCode.DHCP_MESSAGE_TYPE, void(@SendMsgType), 1, false);
|
NewOption(SendOptions, TDHCPOpCode.DHCP_MESSAGE_TYPE, void(@SendMsgType), 1, false);
|
||||||
|
{ Create a Requested IP option and assign it the value from the OFFER packet header }
|
||||||
NewOption(SendOptions, TDHCPOpCode.REQUESTED_IP_ADDRESS, void(@SendHeader^.Client_IP[0]), 4, false);
|
NewOption(SendOptions, TDHCPOpCode.REQUESTED_IP_ADDRESS, void(@SendHeader^.Client_IP[0]), 4, false);
|
||||||
|
{ Create a Server Identifier Option and assign it the value from the OFFER packet options }
|
||||||
Option:= getOptionByOpcode(Options, TDHCPOpCode.SERVER_IDENTIFIER);
|
Option:= getOptionByOpcode(Options, TDHCPOpCode.SERVER_IDENTIFIER);
|
||||||
if Option <> nil then begin
|
if Option <> nil then begin
|
||||||
NewOption(SendOptions, TDHCPOpCode.SERVER_IDENTIFIER, void(@Option^.Value[0]), 4, false);
|
NewOption(SendOptions, TDHCPOpCode.SERVER_IDENTIFIER, void(@Option^.Value[0]), 4, false);
|
||||||
end;
|
end;
|
||||||
|
{ Create a Parameter Request List, Request the following: Netmask, Gateway, DNS Name & DNS Server }
|
||||||
RequestParams[0]:= Ord(TDHCPOpCode.SUBNET_MASK);
|
RequestParams[0]:= Ord(TDHCPOpCode.SUBNET_MASK);
|
||||||
RequestParams[1]:= Ord(TDHCPOpCode.ROUTER);
|
RequestParams[1]:= Ord(TDHCPOpCode.ROUTER);
|
||||||
RequestParams[2]:= Ord(TDHCPOpCode.DOMAIN_NAME);
|
RequestParams[2]:= Ord(TDHCPOpCode.DOMAIN_NAME);
|
||||||
@ -470,9 +501,10 @@ begin
|
|||||||
NewOption(SendOptions, TDHCPOpCode.PARAMETER_REQUEST_LIST, void(@RequestParams[0]), 4, false);
|
NewOption(SendOptions, TDHCPOpCode.PARAMETER_REQUEST_LIST, void(@RequestParams[0]), 4, false);
|
||||||
NewOption(SendOptions, TDHCPOpCode.END_VENDOR_OPTIONS, nil, 0, false);
|
NewOption(SendOptions, TDHCPOpCode.END_VENDOR_OPTIONS, nil, 0, false);
|
||||||
|
|
||||||
|
{ Write the options to the header }
|
||||||
NewSendHeader:= writeOptions(SendHeader, SendOptions, @NewHeaderSize);
|
NewSendHeader:= writeOptions(SendHeader, SendOptions, @NewHeaderSize);
|
||||||
|
|
||||||
{ Setup Packet Context (IPv4 & ETH2) }
|
{ Setup Packet Context (IPv4 & ETH2) & Copy in the correct details }
|
||||||
MAC:= getMAC();
|
MAC:= getMAC();
|
||||||
packetCtx:= PPacketContext(Kalloc(sizeof(TPacketContext)));
|
packetCtx:= PPacketContext(Kalloc(sizeof(TPacketContext)));
|
||||||
packetCtx^.TTL:= 128;
|
packetCtx^.TTL:= 128;
|
||||||
@ -481,15 +513,16 @@ begin
|
|||||||
copyIPv4(@NULL_IP[0], @packetCtx^.IP.Source[0]);
|
copyIPv4(@NULL_IP[0], @packetCtx^.IP.Source[0]);
|
||||||
copyIPv4(@BROADCAST_IP[0], @packetCtx^.IP.Destination[0]);
|
copyIPv4(@BROADCAST_IP[0], @packetCtx^.IP.Destination[0]);
|
||||||
|
|
||||||
{ Setup UDPContext (UDP) }
|
{ Setup UDPContext (UDP) & copy in the correct details }
|
||||||
sendCtx:= PUDPSendContext(Kalloc(sizeof(TUDPSendContext)));
|
sendCtx:= PUDPSendContext(Kalloc(sizeof(TUDPSendContext)));
|
||||||
sendCtx^.DstPort:= 67;
|
sendCtx^.DstPort:= 67;
|
||||||
sendCtx^.context:= packetCtx;
|
sendCtx^.context:= packetCtx;
|
||||||
sendCtx^.socket:= Socket;
|
sendCtx^.socket:= Socket;
|
||||||
|
|
||||||
{ Send }
|
{ Send the packet }
|
||||||
udp.send(void(NewSendHeader), NewHeaderSize, sendCtx);
|
udp.send(void(NewSendHeader), NewHeaderSize, sendCtx);
|
||||||
|
|
||||||
|
{ Free everything we allocated }
|
||||||
freeOptions(SendOptions);
|
freeOptions(SendOptions);
|
||||||
kfree(void(NewSendHeader));
|
kfree(void(NewSendHeader));
|
||||||
kfree(void(SendHeader));
|
kfree(void(SendHeader));
|
||||||
@ -528,8 +561,9 @@ begin
|
|||||||
{ Check the message type is client specific }
|
{ Check the message type is client specific }
|
||||||
If Header^.Message_Type = $02 then begin
|
If Header^.Message_Type = $02 then begin
|
||||||
Outputln('DHCP','Packet is a client packet.');
|
Outputln('DHCP','Packet is a client packet.');
|
||||||
Outputln('DHCP','Searching for message type in Options');
|
|
||||||
{ Iterate options to find DHCP_MESSAGE_TYPE }
|
{ Iterate options to find DHCP_MESSAGE_TYPE }
|
||||||
|
Outputln('DHCP','Searching for message type in Options');
|
||||||
for i:=0 to getOptionsCount(Options)-1 do begin
|
for i:=0 to getOptionsCount(Options)-1 do begin
|
||||||
Option:= getOption(Options, i);
|
Option:= getOption(Options, i);
|
||||||
if Option^.Opcode = DHCP_MESSAGE_TYPE then begin
|
if Option^.Opcode = DHCP_MESSAGE_TYPE then begin
|
||||||
@ -539,6 +573,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Outputln('DHCP','Done searching for message type in Options');
|
Outputln('DHCP','Done searching for message type in Options');
|
||||||
|
|
||||||
{ Did we successfully get the DHCP_MESSAGE_TYPE option? }
|
{ Did we successfully get the DHCP_MESSAGE_TYPE option? }
|
||||||
if Option <> nil then begin
|
if Option <> nil then begin
|
||||||
Outputln('DHCP','Found message type option.');
|
Outputln('DHCP','Found message type option.');
|
||||||
@ -562,7 +597,6 @@ begin
|
|||||||
Outputln('DHCP', 'Packet is not addressed to us.');
|
Outputln('DHCP', 'Packet is not addressed to us.');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
freeOptions(Options);
|
freeOptions(Options);
|
||||||
tracer.push_trace('dhcp.processPacket.exit');
|
tracer.push_trace('dhcp.processPacket.exit');
|
||||||
end;
|
end;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user