diff --git a/src/driver/net/include/nettypes.pas b/src/driver/net/include/nettypes.pas index bc1897b6..7e6c724b 100644 --- a/src/driver/net/include/nettypes.pas +++ b/src/driver/net/include/nettypes.pas @@ -200,8 +200,8 @@ type Bootp_Flags : uint16; Client_IP : TIPv4Address; Your_IP : TIPv4Address; - Server_IP : TIPV4Header; - Relay_Agent_IP : TIPV4Header; + Server_IP : TIPv4Address; + Relay_Agent_IP : TIPv4Address; Client_MAC : TMACAddress; Padding : Array[0..9] of uint8; Server_Hostname : Array[0..63] of uint8; diff --git a/src/driver/net/l5/dhcp.pas b/src/driver/net/l5/dhcp.pas index 2b7c3ef2..4fbb8a4b 100644 --- a/src/driver/net/l5/dhcp.pas +++ b/src/driver/net/l5/dhcp.pas @@ -5,7 +5,7 @@ interface uses lmemorymanager, console, nettypes, netutils, udp, netlog, net, - util, rand, lists, tracer; + util, rand, lists, tracer, ipv4; type TDHCPOptions = PLinkedListBase; @@ -32,13 +32,18 @@ var Socket : PUDPBindContext; FlipExclude : PFlipExclude; -procedure newOption(DHCPOptions : PDHCPOptions; Opcode : TDHCPOpCode; Data : void; Length : uint32; SwapEndian : Boolean); +function newHeader : PDHCPHeader; +begin + tracer.push_trace('dhcp.newHeader'); + newHeader:= PDHCPHeader(kalloc(sizeof(TDHCPHeader))); +end; + +function newOption(DHCPOptions : PDHCPOptions; Opcode : TDHCPOpCode; Data : void; Length : uint32; SwapEndian : Boolean) : PDHCPOption; var Option : PDHCPOption; - read32 : puint32; - read16 : puint16; begin + tracer.push_trace('dhcp.newOption'); Option:= PDHCPOption(LL_Add(PLinkedListBase(DHCPOptions))); Option^.Opcode:= Opcode; Option^.Size:= Length; @@ -46,21 +51,10 @@ begin if Length > 0 then begin Option^.Value:= kalloc(Length); memcpy(uint32(Data), uint32(Option^.Value), Length); - if Length = 2 then begin - if SwapEndian then begin - read16:= puint16(Option^.Value); - read16^:= switchendian16(read16^); - end; - end; - if Length = 4 then begin - if SwapEndian then begin - read32:= puint32(Option^.Value); - read32^:= switchendian32(read32^); - end; - end; end else begin Option^.Value:= nil; end; + newOption:= Option; end; procedure deleteOption(DHCPOptions : PDHCPOptions; idx : uint32); @@ -68,6 +62,7 @@ var Option : PDHCPOption; begin + tracer.push_trace('dhcp.deleteOptions'); Option:= PDHCPOption(LL_Get(PLinkedListBase(DHCPOptions), idx)); if Option <> nil then begin if Option^.Value <> nil then begin @@ -77,13 +72,21 @@ begin end; end; +function getOption(DHCPOptions : PDHCPOptions; idx : uint32) : PDHCPOption; +begin + tracer.push_trace('dhcp.getOption'); + getOption:= PDHCPOption(LL_Get(PLinkedListBase(DHCPOptions),idx)); +end; + function newOptions : PDHCPOptions; begin + tracer.push_trace('dhcp.newOptions'); newOptions:= PDHCPOptions(LL_New(sizeof(TDHCPOption))); end; procedure freeOptions(Options : PDHCPOptions); begin + tracer.push_trace('dhcp.freeOptions'); if Options <> nil then begin while LL_Size(PLinkedListBase(Options)) > 0 do begin deleteOption(Options, 0); @@ -92,27 +95,132 @@ begin end; end; -function writeOptions(Header : PDHCPHeader; Options : PDHCPOptions; newLength : puint16) : PDHCPHeader; +function getOptionsCount(Options : PDHCPOptions) : uint32; begin + tracer.push_trace('dhcp.getOptionsCount'); + getOptionsCount:= LL_Size(PLinkedListBase(Options)); +end; +function calculateOptionsSize(Options : PDHCPOptions) : uint16; +var + i : uint32; + Option : PDHCPOption; + OptionsSize : uint16; + +begin + tracer.push_trace('dhcp.calculateOptionsSize'); + OptionsSize := 0; + for i:=0 to getOptionsCount(Options)-1 do begin + Option:= PDHCPOption(LL_Get(PLinkedListBase(Options),i)); + case Option^.Opcode of + PAD,END_VENDOR_OPTIONS : inc(OptionsSize,1); + else inc(OptionsSize, 2 + Option^.Size); + end; + end; + calculateOptionsSize:= OptionsSize; end; +function getEndianCorrectValue16(Option : PDHCPOption) : uint16; +var + Value : uint16; + +begin + tracer.push_trace('dhcp.getEndianCorrectValue16'); + Value:= PuInt16(Option^.Value)^; + if Option^.Reverse_Endian then + getEndianCorrectValue16:= switchendian16(Value) + else + getEndianCorrectValue16:= Value; +end; + +function getEndianCorrectValue32(Option : PDHCPOption) : uint32; +var + Value : uint32; +begin + tracer.push_trace('dhcp.getEndianCorrectValue32'); + Value:= puint32(Option^.Value)^; + if Option^.Reverse_Endian then + getEndianCorrectValue32:= switchendian32(Value) + else + getEndianCorrectValue32:= Value; +end; + +function writeOptions(Header : PDHCPHeader; Options : PDHCPOptions; newLength : puint16) : PDHCPHeader; +var + OptionsSize : uint16; + TotalSize : uint16; + NewBuffer : void; + NewHeader : PDHCPHeader; + buffer : puint8; + read8 : puint8; + read16 : puint16; + read32 : puint32; + Option : PDHCPOption; + i : uint32; + +begin + tracer.push_trace('dhcp.writeOptions'); + OptionsSize := calculateOptionsSize(Options); + TotalSize:= OptionsSize + SizeOf(TDHCPHeader); + NewBuffer:= kalloc(TotalSize); + + //Copy over Header + NewHeader:= PDHCPHeader(buffer); + memcpy(uint32(Header), uint32(NewHeader), sizeof(TDHCPHeader)); + + //Write all options + buffer:= puint8(NewBuffer); + inc(buffer, SizeOf(TDHCPHeader)); + for i:=0 to getOptionsCount(Options)-1 do begin + Option:= getOption(Options, i); + case Option^.Opcode of + PAD,END_VENDOR_OPTIONS:begin + buffer^:= Ord(Option^.Opcode); + inc(buffer); + end; + else begin + buffer^:= Ord(Option^.OpCode); + inc(buffer); + buffer^:= Option^.Size; + inc(buffer); + case Option^.Size of + 2:begin + read16:= puint16(buffer); + read16^:= getEndianCorrectValue16(Option); + end; + 4:begin + read32:= puint32(buffer); + read32^:= getEndianCorrectValue32(Option); + end; + else begin + memcpy(uint32(Option^.Value), uint32(buffer), Option^.Size); + end; + end; + inc(buffer, Option^.Size); + end; + end; + end; + newLength^:= TotalSize; + writeOptions:= PDHCPHeader(NewBuffer); +end; + + procedure readOptions(DHCPOptions : PDHCPOptions; p_data : void; p_len : uint16); var headerSize : uint32; - buffer : puint8; - bufferEnd : puint8; bufferStart : puint8; - HaveOp : boolean; HaveLen : boolean; - Opcode : TDHCPOpCode; Length : uint8; + read32 : puint32; + read16 : puint16; + Option : PDHCPOption; begin + tracer.push_trace('dhcp.register'); HeaderSize:= sizeOf(TDHCPHeader); bufferEnd:= puint8(uint32(p_data) + p_len); bufferStart:= puint8(uint32(p_data) + headerSize); @@ -121,7 +229,19 @@ begin HaveLen:= false; while (uint32(buffer) < uint32(bufferEnd)) do begin if HaveLen then begin - newOption(DHCPOptions, Opcode, void(buffer), Length, not FlipExclude^[ord(Opcode)]); + Option:= newOption(DHCPOptions, Opcode, void(buffer), Length, not FlipExclude^[ord(Opcode)]); + if Length = 2 then begin + if Option^.Reverse_Endian then begin + read16:= puint16(Option^.Value); + read16^:= switchendian16(read16^); + end; + end; + if Length = 4 then begin + if Option^.Reverse_Endian then begin + read32:= puint32(Option^.Value); + read32^:= switchendian32(read32^); + end; + end; inc(buffer, Length); HaveOp:= false; HaveLen:= false; @@ -132,11 +252,7 @@ begin end else begin Opcode:= TDHCPOpCode(buffer^); case opcode of - PAD:begin - Length:= 0; - haveLen:= true; - end; - END_VENDOR_OPTIONS:begin + PAD,END_VENDOR_OPTIONS:begin Length:= 0; haveLen:= true; end; @@ -148,12 +264,55 @@ begin end; procedure processPacket(p_data : void; p_len : uint16; context : PUDPPacketContext); -begin +var + Header : PDHCPHeader; + Options : PDHCPOptions; +begin + tracer.push_trace('dhcp.processPacket'); + Header:= PDHCPHeader(p_data); + Options:= newOptions; + readOptions(Options, p_data, p_len); end; procedure DHCPDiscover(); +var + Header : PDHCPHeader; + NewHeader : PDHCPHeader; + HeaderSize : Puint32; + Options : PDHCPOptions; + MsgType : uint8; + begin + tracer.push_trace('dhcp.DHCPDiscover'); + Header:= newHeader; + Options:= newOptions; + XID:= rand32(); + + //Setup header + Header^.Message_Type:= $01; + Header^.Hardware_Type:= $01; + Header^.Hardware_Address_Length:= $06; + Header^.Hops:= $00; + Header^.Transaction_ID:= switchendian32(XID); + Header^.Seconds_Elapsed:= $0000; + CopyIPv4(@NULL_IP[0], @Header^.Client_IP[0]); + CopyIPv4(@NULL_IP[0], @Header^.Your_IP[0]); + CopyIPv4(@NULL_IP[0], @Header^.Server_IP[0]); + CopyIPv4(@NULL_IP[0], @Header^.Relay_Agent_IP[0]); + CopyMAC(@getMAC[0], @Header^.Client_MAC[0]); + memset(uint32(@Header^.Padding[0]), 0, 10); + memset(uint32(@Header^.Server_Hostname[0]), 0, 64); + memset(uint32(@Header^.Boot_File[0]), 0, 128); + memcpy(uint32(@DHCP_MAGIC[0]), uint32(@Header^.Magic_Cookie[0]), 4); + + //Setup options + MsgType:= Ord(TDHCPMessageType.DISCOVER); + newOption(Options, DHCP_MESSAGE_TYPE, void(@MsgType), 1, false); + + NewOption(Options, END_VENDOR_OPTIONS, nil, 0, false); + + getIPv4Config^.UP:= true; end; @@ -232,6 +391,7 @@ begin tueOK:console.outputln('DHCP', 'Successfully bound port 68.'); else console.outputln('DHCP', 'Failed to bind port 68.'); end; + DHCPDiscover; console.outputln('DHCP', 'Register end.'); end; diff --git a/src/include/system.pas b/src/include/system.pas index 8b3f856f..0a2d980a 100644 --- a/src/include/system.pas +++ b/src/include/system.pas @@ -54,6 +54,10 @@ type Void = ^uInt32; HWND = uint32; + yord = uInt8; + xord = uInt8; + zord = uInt16; + //Alternate Types UBit1 = 0..(1 shl 01) - 1; UBit2 = 0..(1 shl 02) - 1;