Updates in net branch coded 6 months ago.

Mostly concerning checksuming, and cleanups

git-svn-id: svn://kolibrios.org@1473 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2010-05-28 20:47:32 +00:00
parent 9ca8f38b9e
commit c59969f41c
7 changed files with 520 additions and 266 deletions

View File

@ -113,85 +113,110 @@ IPv4_init:
; ;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
align 4 align 4
IPv4_handler: ; TODO: clean up this mess IPv4_handler: ; TODO: implement handler for IP options
; for instance, there should be only one piece of code wich make the jump to an underlying protocol, and not two..
; TODO2: add code for IPv4 sockets (raw sockets) ; TODO2: add code for IPv4 sockets (raw sockets)
DEBUGF 1,"IP_Handler - start\n" DEBUGF 1,"IP_Handler - start\n"
push edx ebx
; save checksum, and clear it in original packet ;-------------------------------------------
mov di , [edx + IPv4_Packet.HeaderChecksum] ; Check if the packet still has time to live
mov word [edx + IPv4_Packet.HeaderChecksum], 0
; Re-calculate checksum
movzx ecx, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field
and ecx, 0x0000000F ;
shl cx , 2 ;
mov esi, edx
xor edx, edx
call checksum_1
call checksum_2
; now compare the two..
cmp dx, di
pop ebx edx
jne .dump ; if checksum isn't valid then dump packet
DEBUGF 1,"IPv4 Checksum is correct\n",di
mov eax, [edx + IPv4_Packet.DestinationAddress]
mov edi, BROADCAST
mov ecx, MAX_IP+1
repnz scasd
jz .ip_ok
not eax
test eax, 127 shl 24 ; 127.x.x.x
jz .ip_ok
; TODO: we need to check for broadcasts (other then 255.255.255.255)
jmp .dump
.ip_ok:
call ETH_struc2dev ; TODO: make this work on other protocols too!
inc [IP_PACKETS_RX+4*edi]
DEBUGF 1,"packet comes from %u.%u.%u.%u\n",\
[edx + IPv4_Packet.SourceAddress]:1,[edx + IPv4_Packet.SourceAddress + 1]:1,[edx + IPv4_Packet.SourceAddress + 2]:1,[edx + IPv4_Packet.SourceAddress + 3]:1
mov al , [edx + IPv4_Packet.VersionAndIHL]
and al , 0x0f ; get IHL(header length)
cmp al , 0x05 ; IHL!= 5*4(20 bytes)
jnz .dump ; TODO: dont dump packets wich have optional fiels !!! /!\
cmp byte [edx + IPv4_Packet.TimeToLive], 0 cmp byte [edx + IPv4_Packet.TimeToLive], 0
je .dump je .dump
movzx eax, word [edx + IPv4_Packet.FlagsAndFragmentOffset] ;--------------------------------------
xchg al , ah ; First, check if IP packet has options
test ax , 1 shl 13 ; Is 'more fragments' flag set ? movzx eax, [edx + IPv4_Packet.VersionAndIHL]
jnz .yes_fragments ; If so, we definately have a fragmented packet and al , 0x0f ; get IHL(header length)
cmp al , 0x05 ; IHL!= 5*4(20 bytes)
jnz .has_options
test ax , 0x1fff ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
jnz .last_fragment
.handle_it: ; We reach here if packet hasnt been fragmented, or when it already has been re-constructed ;-------------------------------
; Now, re-calcualte the checksum
; Re-calculate checksum
push edx ebx
mov esi, edx
call checksum_ip_header
pop ebx edx
; now see if it was correct
cmp [edx + IPv4_Packet.HeaderChecksum], 0
jne .dump ; if checksum isn't valid then dump packet
DEBUGF 1,"IPv4 Checksum is correct\n"
;-------------------------------------------------------
; Time to find out what interface this packet belongs to
; Therefore we will scan the current list of IP's
mov eax, [edx + IPv4_Packet.DestinationAddress]
mov edi, BROADCAST
mov ecx, MAX_IP+1
.find_ip_loop:
cmp eax, dword [edi]
jz .ip_ok
add edi, 4
dec ecx
jnz .find_ip_loop
; it was not on the list, perhaps it's a loopback ?
not eax
test eax, 127 shl 24 ; 127.x.x.x
jz .ip_ok
; TODO: we need to check for broadcasts (other then 255.255.255.255)
DEBUGF 2,"Destination address does not match!\n"
jmp .dump
;---------------------------------------------------
; Now we can update stats and find the device number
.ip_ok:
call ETH_struc2dev ; TODO: make this work on other protocols too!
inc [IP_PACKETS_RX+4*edi]
DEBUGF 1,"Packet comes from %u.%u.%u.%u\n",\
[edx + IPv4_Packet.SourceAddress]:1,[edx + IPv4_Packet.SourceAddress + 1]:1,[edx + IPv4_Packet.SourceAddress + 2]:1,[edx + IPv4_Packet.SourceAddress + 3]:1
;----------------------------------
; Check if the packet is fragmented
test [edx + IPv4_Packet.FlagsAndFragmentOffset], 1 shl 5 ; Is 'more fragments' flag set ?
jnz .has_fragments ; If so, we definately have a fragmented packet
test [edx + IPv4_Packet.FlagsAndFragmentOffset], 0xff1f ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
jnz .is_last_fragment
;-------------------------------------------------------------------
; No, it's just a regular IP packet, pass it to the higher protocols
.handle_it: ; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
movzx eax, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field movzx eax, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field
and eax, 0x0000000F ; and eax, 0x0000000F ;
shl eax, 2 ; shl eax, 2 ;
movzx ecx, word [edx + IPv4_Packet.TotalLength] ; Calculate length of encapsulated Packet movzx ecx, word [edx + IPv4_Packet.TotalLength] ; Calculate length of encapsulated Packet
xchg cl , ch ; xchg cl , ch ;
sub ecx, eax ; sub ecx, eax ;
add eax, edx add eax, edx
push eax push eax
mov esi, [edx + IPv4_Packet.SourceAddress] ; These values might be of interest to the higher protocols
mov edi, [edx + IPv4_Packet.DestinationAddress] ;
mov al , [edx + IPv4_Packet.Protocol] mov al , [edx + IPv4_Packet.Protocol]
mov esi, [edx + IPv4_Packet.SourceAddress]
mov edi, [edx + IPv4_Packet.DestinationAddress]
pop edx ; Offset to data (tcp/udp/icmp/.. Packet) pop edx ; Offset to data (tcp/udp/icmp/.. Packet)
cmp al , IP_PROTO_TCP cmp al , IP_PROTO_TCP
@ -203,35 +228,79 @@ IPv4_handler: ; TODO: clean up this mess
cmp al , IP_PROTO_ICMP cmp al , IP_PROTO_ICMP
je ICMP_handler je ICMP_handler
DEBUGF 1,"unknown protocol: %u\n",al DEBUGF 2,"unknown Internet protocol: %u\n", al
.dump: .dump:
DEBUGF 1,"IP_Handler - done\n" DEBUGF 2,"IP_Handler - dumping\n"
; inc [dumped_rx_count] ; inc [dumped_rx_count]
call kernel_free call kernel_free
add esp, 4 ; pop (balance stack) add esp, 4 ; pop (balance stack)
ret ret
.yes_fragments: ;---------------------------
; Fragmented packet handler
.has_fragments:
movzx eax, [edx + IPv4_Packet.FlagsAndFragmentOffset]
xchg al , ah
shl ax , 3 shl ax , 3
DEBUGF 1,"Fragmented packet, offset:%u, id:%x\n", ax, [edx + IPv4_Packet.Identification]:4 DEBUGF 1,"Fragmented packet, offset:%u, id:%x\n", ax, [edx + IPv4_Packet.Identification]:4
test ax , ax ; Is this the first packet of the fragment? test ax , ax ; Is this the first packet of the fragment?
jnz .not_first_fragment jz .is_first_fragment
;-------------------------------------------------------
; We have a fragmented IP packet, but it's not the first
DEBUGF 1,"Middle fragmented packet received!\n"
call IPv4_find_fragment_slot
cmp esi, -1
je .dump
mov word [esi + FRAGMENT_slot.ttl], 15 ; Reset the ttl
mov esi, [esi + FRAGMENT_slot.ptr]
or edi, -1
.find_last_entry: ; The following routine will try to find the last entry
cmp edi, [esi + FRAGMENT_entry.PrevPtr]
jne .destroy_slot ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
mov edi, esi
mov esi, [esi + FRAGMENT_entry.NextPtr]
cmp esi, -1
jne .find_last_entry
; We found the last entry (pointer is now in edi)
; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
pop eax ; pointer to packet
mov [edi + FRAGMENT_entry.NextPtr], eax ; update pointer of previous entry to the new entry
mov [eax + FRAGMENT_entry.NextPtr], -1
mov [eax + FRAGMENT_entry.PrevPtr], edi
mov [eax + FRAGMENT_entry.Owner], ebx
add esp, 4
ret
;------------------------------------
; We have received the first fragment
.is_first_fragment:
DEBUGF 1,"First fragmented packet received!\n" DEBUGF 1,"First fragmented packet received!\n"
; try to locate a free slot.. ; try to locate a free slot..
mov ecx, MAX_FRAGMENTS mov ecx, MAX_FRAGMENTS
mov esi, FRAGMENT_LIST mov esi, FRAGMENT_LIST
.find_free_slot: .find_free_slot:
cmp word [esi + FRAGMENT_slot.ttl], 0 cmp word [esi + FRAGMENT_slot.ttl], 0
je .found_free_slot je .found_free_slot
add esi, FRAGMENT_slot.size add esi, FRAGMENT_slot.size
loop .find_free_slot loop .find_free_slot
jmp .dump ; If no free slot was found, dump the packet jmp .dump ; If no free slot was found, dump the packet
.found_free_slot: ; We found a free slot, let's fill in the FRAGMENT_slot structure .found_free_slot: ; We found a free slot, let's fill in the FRAGMENT_slot structure
mov word [esi + FRAGMENT_slot.ttl], 15 ; RFC recommends 15 secs as ttl mov word [esi + FRAGMENT_slot.ttl], 15 ; RFC recommends 15 secs as ttl
mov ax , word [edx + IPv4_Packet.Identification] mov ax , word [edx + IPv4_Packet.Identification]
mov word [esi + FRAGMENT_slot.id], ax mov word [esi + FRAGMENT_slot.id], ax
@ -250,51 +319,24 @@ IPv4_handler: ; TODO: clean up this mess
ret ret
;-----------------------------------
; We have received the last fragment
.not_first_fragment: .is_last_fragment:
DEBUGF 1,"Middle fragmented packet received!\n"
call .find_fragment_slot
cmp esi, -1
je .dump
mov word [esi + FRAGMENT_slot.ttl], 15 ; Reset the ttl
mov esi, [esi + FRAGMENT_slot.ptr]
or edi, -1
.find_last_entry: ; The following routine will try to find the last entry
cmp edi, [esi + FRAGMENT_entry.PrevPtr]
jne .destroy_slot ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
mov edi, esi
mov esi, [esi + FRAGMENT_entry.NextPtr]
cmp esi, -1
jne .find_last_entry
; We found the last entry (pointer is noww in edi)
; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
pop eax ; pointer to packet
mov [edi + FRAGMENT_entry.NextPtr], eax ; update pointer of previous entry to the new entry
mov [eax + FRAGMENT_entry.NextPtr], -1
mov [eax + FRAGMENT_entry.PrevPtr], edi
mov [eax + FRAGMENT_entry.Owner], ebx
add esp, 4
ret
.last_fragment:
DEBUGF 1,"Last fragmented packet received!\n" DEBUGF 1,"Last fragmented packet received!\n"
call .find_fragment_slot
call IPv4_find_fragment_slot
cmp esi, -1 cmp esi, -1
je .dump je .dump
mov esi, [esi + FRAGMENT_slot.ptr] ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer mov esi, [esi + FRAGMENT_slot.ptr] ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
push esi push esi
xor eax, eax ; xor eax, eax
or edi, -1 or edi, -1
.count_bytes:
.count_bytes:
cmp [esi + FRAGMENT_entry.PrevPtr], edi cmp [esi + FRAGMENT_entry.PrevPtr], edi
jne .destroy_slot_pop ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!) jne .destroy_slot_pop ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
mov cx, word [esi + FRAGMENT_entry.Data + IPv4_Packet.TotalLength] ; Add total length mov cx, word [esi + FRAGMENT_entry.Data + IPv4_Packet.TotalLength] ; Add total length
xchg cl, ch xchg cl, ch
DEBUGF 1,"Packet size: %u\n", cx DEBUGF 1,"Packet size: %u\n", cx
@ -339,9 +381,9 @@ IPv4_handler: ; TODO: clean up this mess
je .destroy_slot_pop ; If we dont have enough space to allocate the buffer, discard all packets in slot je .destroy_slot_pop ; If we dont have enough space to allocate the buffer, discard all packets in slot
mov edx, [esp+4] ; Get pointer to first fragment entry back in edx mov edx, [esp+4] ; Get pointer to first fragment entry back in edx
.rebuild_packet_loop: .rebuild_packet_loop:
movzx ecx, word [edx + FRAGMENT_entry.Data + IPv4_Packet.FlagsAndFragmentOffset] ; Calculate the fragment offset movzx ecx, word [edx + FRAGMENT_entry.Data + IPv4_Packet.FlagsAndFragmentOffset] ; Calculate the fragment offset
xchg cl , ch ; intel byte order xchg cl , ch ; intel byte order
shl cx , 3 ; multiply by 8 and clear first 3 bits shl cx , 3 ; multiply by 8 and clear first 3 bits
DEBUGF 1,"Fragment offset: %u\n", cx DEBUGF 1,"Fragment offset: %u\n", cx
@ -358,7 +400,7 @@ IPv4_handler: ; TODO: clean up this mess
je .first_fragment je .first_fragment
sub cx, bx ; If not, dont copy the header sub cx, bx ; If not, dont copy the header
add esi, ebx ; add esi, ebx ;
.first_fragment: .first_fragment:
push cx ; First copy dword-wise, then byte-wise push cx ; First copy dword-wise, then byte-wise
shr cx, 2 ; shr cx, 2 ;
@ -369,6 +411,7 @@ IPv4_handler: ; TODO: clean up this mess
push eax push eax
push edx ; Push pointer to fragment onto stack push edx ; Push pointer to fragment onto stack
mov ebx, [edx + FRAGMENT_entry.Owner] ; we need to remeber the owner, in case this is the last packet
mov edx, [edx + FRAGMENT_entry.NextPtr] ; Set edx to the next pointer mov edx, [edx + FRAGMENT_entry.NextPtr] ; Set edx to the next pointer
call kernel_free ; free the previous fragment buffer (this uses the value from stack) call kernel_free ; free the previous fragment buffer (this uses the value from stack)
pop eax pop eax
@ -381,46 +424,19 @@ IPv4_handler: ; TODO: clean up this mess
mov word [edx + IPv4_Packet.TotalLength], cx mov word [edx + IPv4_Packet.TotalLength], cx
add esp, 8 add esp, 8
xchg cl, ch ; This prints the IP packet to the debug board (usefull when using serial output debug..) xchg cl, ch ;
push ecx ;;;;
push eax ;;;; push ecx ;;;;
; mov esi, edx ; push eax ;;;;
; mov esi, edx ; This prints the IP packet to the debug board (usefull when using serial output debug..)
; ; ; ;
; @@: ; ; @@: ;
; lodsb ; ; lodsb ;
; DEBUGF 1,"%x ", eax:2 ; ; DEBUGF 1,"%x ", eax:2 ;
; loop @r ; ; loop @r ;
movzx eax, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field jmp .handle_it ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
and ax, 0x000F ;
shl ax, 2 ;
sub ecx, eax
add eax, edx
push eax
mov al , [edx + IPv4_Packet.Protocol]
mov esi, [edx + IPv4_Packet.SourceAddress]
mov edi, [edx + IPv4_Packet.DestinationAddress]
pop edx ; Offset to data (tcp/udp/icmp/.. Packet)
cmp al , IP_PROTO_TCP
je TCP_handler
cmp al , IP_PROTO_UDP
je UDP_handler
cmp al , IP_PROTO_ICMP
je ICMP_handler_fragments
DEBUGF 1,"IP_Handler - unknown protocol:%u\n",al
call kernel_free
add esp, 8 ; pop (balance stack)
ret
.destroy_slot_pop: .destroy_slot_pop:
add esp, 4 add esp, 4
@ -431,6 +447,18 @@ IPv4_handler: ; TODO: clean up this mess
;-----------------------------------
; The IP packet has some options
.has_options:
jmp .dump
;----------------------------------------------------------------- ;-----------------------------------------------------------------
; ;
; find fragment slot ; find fragment slot
@ -439,8 +467,8 @@ IPv4_handler: ; TODO: clean up this mess
; OUT: pointer to slot in edi, -1 on error ; OUT: pointer to slot in edi, -1 on error
; ;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
align 4
.find_fragment_slot: IPv4_find_fragment_slot:
push eax ebx ecx edx push eax ebx ecx edx
mov ax , word [edx + IPv4_Packet.Identification] mov ax , word [edx + IPv4_Packet.Identification]
@ -458,7 +486,7 @@ IPv4_handler: ; TODO: clean up this mess
.try_next: .try_next:
add esi, FRAGMENT_slot.size add esi, FRAGMENT_slot.size
loop .find_slot loop .find_slot
; pop edx ebx ; pop edx ebx
or esi, -1 or esi, -1
; ret ; ret
@ -581,15 +609,10 @@ IPv4_create_packet:
pop ecx pop ecx
mov [edi + IPv4_Packet.DestinationAddress], ecx mov [edi + IPv4_Packet.DestinationAddress], ecx
push eax ebx edx push eax edx esi
; calculate checksum
xor edx, edx
mov esi, edi mov esi, edi
mov ecx, IPv4_Packet.DataOrOptional call checksum_ip_header
call checksum_1 pop esi edx eax ecx
call checksum_2
mov [edi + IPv4_Packet.HeaderChecksum], dx
pop edx ebx eax ecx
add edi, IPv4_Packet.DataOrOptional add edi, IPv4_Packet.DataOrOptional
DEBUGF 1,"IPv4 Packet for device %x created successfully\n", ebx DEBUGF 1,"IPv4 Packet for device %x created successfully\n", ebx
@ -644,7 +667,7 @@ IPv4_dest_to_dev:
.found_it: .found_it:
shr edi, 2 shr edi, 2
DEBUGF 1,"%u\n",edi DEBUGF 1,"%u\n",edi
ret ret
@ -705,59 +728,59 @@ IPv4_API:
dec bl dec bl
jz .write_gateway ; 9 jz .write_gateway ; 9
.error: .error:
mov eax, -1 mov eax, -1
ret ret
.packets_tx: .packets_tx:
add eax, IP_PACKETS_TX add eax, IP_PACKETS_TX
mov eax, [eax] mov eax, [eax]
ret ret
.packets_rx: .packets_rx:
add eax, IP_PACKETS_RX add eax, IP_PACKETS_RX
mov eax, [eax] mov eax, [eax]
ret ret
.read_ip: .read_ip:
add eax, IP_LIST add eax, IP_LIST
mov eax, [eax] mov eax, [eax]
ret ret
.write_ip: .write_ip:
add eax, IP_LIST add eax, IP_LIST
mov [eax], ecx mov [eax], ecx
xor eax, eax xor eax, eax
ret ret
.read_dns: .read_dns:
add eax, DNS_LIST add eax, DNS_LIST
mov eax, [eax] mov eax, [eax]
ret ret
.write_dns: .write_dns:
add eax, DNS_LIST add eax, DNS_LIST
mov [eax], ecx mov [eax], ecx
xor eax, eax xor eax, eax
ret ret
.read_subnet: .read_subnet:
add eax, SUBNET_LIST add eax, SUBNET_LIST
mov eax, [eax] mov eax, [eax]
ret ret
.write_subnet: .write_subnet:
add eax, SUBNET_LIST add eax, SUBNET_LIST
mov [eax], ecx mov [eax], ecx
xor eax, eax xor eax, eax
ret ret
.read_gateway: .read_gateway:
add eax, GATEWAY_LIST add eax, GATEWAY_LIST
mov eax, [eax] mov eax, [eax]
ret ret
.write_gateway: .write_gateway:
add eax, GATEWAY_LIST add eax, GATEWAY_LIST
mov [eax], ecx mov [eax], ecx
xor eax, eax xor eax, eax

View File

@ -153,7 +153,7 @@ end if
.error: .error:
or eax, -1 or eax, -1
DEBUGF 1,"- fail\n" DEBUGF 2,"Adding ETH device failed\n"
ret ret
@ -219,50 +219,56 @@ end if
align 4 align 4
ETH_receiver: ETH_receiver:
DEBUGF 1,"ETH_Receiver: " ; DEBUGF 1,"ETH_Receiver: "
push ebx ; push ebx
mov esi, esp ; mov esi, esp
add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail ; add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail
DEBUGF 1,"Queued packet successfully\n" ; DEBUGF 1,"Queued packet successfully\n"
add esp, 4*3 ; add esp, 4*3
ret
.fail:
DEBUGF 1,"ETH_IN_QUEUE is full!\n"
add esp, 4
call kernel_free
add esp, 4
ret
;-----------------------------------------------------------------
; ;
; ETH_Handler: ; ret
; ;
; Handles all queued eth packets (called from kernel's main_loop) ; .fail:
; DEBUGF 1,"ETH_IN_QUEUE is full!\n"
; add esp, 4
; call kernel_free
; add esp, 4
; ;
; IN: / ; ret
; OUT: /
; ;
;----------------------------------------------------------------- ;
align 4 ;
ETH_handler: ;;-----------------------------------------------------------------
;;
;; ETH_Handler:
;;
;; Handles all queued eth packets (called from kernel's main_loop)
;;
;; IN: /
;; OUT: /
;;
;;-----------------------------------------------------------------
;align 4
;ETH_handler:
;
; get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
;
; push ETH_handler
;
; lodsd
; mov ebx, eax
; lodsd
; mov ecx, eax
; lodsd
; xchg eax, ecx
; push ecx
; push eax
get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
push ETH_handler ;-----------------------------
mov eax, [esp]
lodsd mov ecx, [esp+4]
mov ebx, eax ;-----------------------------
lodsd
mov ecx, eax
lodsd
xchg eax, ecx
push ecx
push eax
DEBUGF 1,"ETH_Handler - size: %u\n", ecx DEBUGF 1,"ETH_Handler - size: %u\n", ecx
cmp ecx, 60 ; check packet length cmp ecx, 60 ; check packet length
@ -278,10 +284,10 @@ ETH_handler:
cmp ax, ETHER_ARP cmp ax, ETHER_ARP
je ARP_handler je ARP_handler
DEBUGF 1,"Unknown ethernet packet type %x\n", ax DEBUGF 2,"Unknown ethernet packet type %x\n", ax
.dump: .dump:
DEBUGF 1,"Dumping packet\n" DEBUGF 2,"ETH_Handler - dumping\n"
call kernel_free call kernel_free
add esp, 4 add esp, 4
@ -290,6 +296,12 @@ ETH_handler:
align 4
ETH_handler:
ret
;----------------------------------------------------------------- ;-----------------------------------------------------------------
; ;
; ETH_sender: ; ETH_sender:
@ -366,24 +378,29 @@ end if
;----------------------------------------------------------------- ;-----------------------------------------------------------------
align 4 align 4
ETH_struc2dev: ETH_struc2dev:
push eax ecx push ecx
mov eax, ebx
mov ecx, MAX_ETH_DEVICES mov ecx, MAX_ETH_DEVICES
mov edi, ETH_DRV_LIST mov edi, ETH_DRV_LIST
repne scasd
jnz .error
sub edi, ETH_DRV_LIST+4 .loop:
cmp ebx, [edi]
jz .found
add edi, 4
dec ecx
jnz .loop
or edi, -1
pop ecx
ret
.found:
sub edi, ETH_DRV_LIST
shr edi, 2 shr edi, 2
pop ecx eax pop ecx
ret
.error:
or edi, -1
pop ecx eax
ret ret
@ -408,7 +425,7 @@ ETH_struc2dev:
align 4 align 4
ETH_create_packet: ETH_create_packet:
DEBUGF 1,"Creating Ethernet Packet (size=%u): \n", ecx DEBUGF 1,"Creating Ethernet Packet (size=%u): \n", ecx
cmp ecx, 1500 cmp ecx, 1500
jg .exit jg .exit
@ -448,17 +465,17 @@ ETH_create_packet:
mov edx, 46 + ETH_FRAME.Data mov edx, 46 + ETH_FRAME.Data
.continue: .continue:
DEBUGF 1,"done: %x size:%u device:%x\n", eax, edx, ebx DEBUGF 1,"done: %x size:%u device:%x\n", eax, edx, ebx
ret ret
.pop_exit: .pop_exit:
DEBUGF 1,"Out of ram space!!\n" DEBUGF 2,"Out of ram space!!\n"
add esp, 18 add esp, 18
or edi,-1 or edi,-1
ret ret
.exit: .exit:
DEBUGF 1,"Packet too large!\n" DEBUGF 2,"Packet too large!\n"
or edi, -1 or edi, -1
ret ret

View File

@ -146,10 +146,14 @@ ICMP_init:
align 4 align 4
ICMP_handler: ;TODO: works only on pure ethernet right now ! ICMP_handler: ;TODO: works only on pure ethernet right now !
DEBUGF 1,"ICMP_Handler - start\n" DEBUGF 1,"ICMP_Handler - buf:%x size:%x dev:%x, size:%x, buf:%x\n", [esp], [esp+4], ebx, ecx, edx
cmp byte [edx + ICMP_Packet.Type], ICMP_ECHO ; Is this an echo request? cmp byte [edx + ICMP_Packet.Type], ICMP_ECHO ; Is this an echo request?
jne .check_sockets jne .check_sockets
;;; TODO: check checksum!
DEBUGF 1,"ICMP_Handler - is echo request, through device:%x\n", ebx
mov byte [edx + ICMP_Packet.Type], ICMP_ECHOREPLY ; Change Packet type to reply mov byte [edx + ICMP_Packet.Type], ICMP_ECHOREPLY ; Change Packet type to reply
mov word [edx + ICMP_Packet.Checksum], 0 ; Set checksum to 0, needed to calculate new checksum mov word [edx + ICMP_Packet.Checksum], 0 ; Set checksum to 0, needed to calculate new checksum

View File

@ -16,8 +16,8 @@
$Revision$ $Revision$
struct SOCKET_head struct SOCKET_head
.PrevPtr dd ? ; pointer to previous socket in list
.NextPtr dd ? ; pointer to next socket in list .NextPtr dd ? ; pointer to next socket in list
.PrevPtr dd ? ; pointer to previous socket in list
.Number dd ? ; socket number (unique within single process) .Number dd ? ; socket number (unique within single process)
.PID dd ? ; application process id .PID dd ? ; application process id
.Domain dd ? ; INET/UNIX/.. .Domain dd ? ; INET/UNIX/..
@ -935,7 +935,7 @@ socket_check_port:
align 4 align 4
socket_internal_receiver: socket_internal_receiver:
DEBUGF 1,"Internal socket receiver: buffer %x, offset: %x size=%u socket: %x\n", esi, edi, ecx, eax DEBUGF 1,"Internal socket receiver: buffer %x, offset: %x size=%u socket: %x\n", esi, edi, ecx, eax
push edi ; offset push edi ; offset
push ecx ; size push ecx ; size
@ -969,7 +969,7 @@ notify_network_event:
ret ret
.full: .full:
DEBUGF 1,"Socket %x is full!\n",eax DEBUGF 2,"Socket %x is full!\n",eax
mov [eax + SOCKET_head.lock], 0 mov [eax + SOCKET_head.lock], 0
call kernel_free call kernel_free
add esp, 8 add esp, 8

View File

@ -19,18 +19,21 @@
$Revision$ $Revision$
__DEBUG_LEVEL_OLD__ equ __DEBUG_LEVEL__
__DEBUG_LEVEL__ equ 1 ; this sets the debug level for network part of kernel
uglobal uglobal
last_1sTick db ? last_1sTick db ?
last_1hsTick dd ? last_1hsTick dd ?
endg endg
MAX_NET_DEVICES equ 16 MAX_NET_DEVICES equ 16
QUEUE_BEFORE_SENDING equ 1 ; 1 or 0 (enable or disable) currently only affects ethernet QUEUE_BEFORE_SENDING equ 0 ; 1 or 0 (enable or disable) currently only affects ethernet
MIN_EPHEMERAL_PORT equ 49152 MIN_EPHEMERAL_PORT equ 49152
MAX_EPHEMERAL_PORT equ 61000 MAX_EPHEMERAL_PORT equ 61000
ETHER equ 1337 ; TODO: find another value for this (how does it work in posix ?) ETHER equ 1337 ; TODO: find another value for this (how does it work in posix ?)
ETHER_ARP equ 0x0608 ETHER_ARP equ 0x0608
AF_UNSPEC equ 0 AF_UNSPEC equ 0
@ -207,35 +210,230 @@ end if
; ;
; This is the first of two functions needed to calculate the TCP checksum. ; This is the first of two functions needed to calculate the TCP checksum.
; ;
; IN: edx = start offeset for semi-checksum ; IN: edx = start offset for semi-checksum
; esi = pointer to data ; esi = pointer to data
; ecx = data size ; ecx = data size
; OUT: edx = semi-checksum ; OUT: edx = semi-checksum
; ;
;
; Code was optimized by diamond
;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
align 4 align 4
checksum_1: checksum_1:
xor eax, eax
shr ecx, 1 shr ecx, 1
pushf pushf
.loop: jz .no_2
lodsw
xchg al, ah
add edx, eax
loop .loop
shr ecx, 1
pushf
jz .no_4
shr ecx, 1
pushf
jz .no_8
.loop:
add dl, [esi+1]
adc dh, [esi+0]
adc dl, [esi+3]
adc dh, [esi+2]
adc dl, [esi+5]
adc dh, [esi+4]
adc dl, [esi+7]
adc dh, [esi+6]
adc edx, 0
add esi, 8
dec ecx
jnz .loop
adc edx, 0
.no_8:
popf
jnc .no_4
add dl, [esi+1]
adc dh, [esi+0]
adc dl, [esi+3]
adc dh, [esi+2]
adc edx, 0
add esi, 4
.no_4:
popf
jnc .no_2
add dl, [esi+1]
adc dh, [esi+0]
adc edx, 0
inc ecx
inc ecx
.no_2:
popf popf
jnc .end jnc .end
add dh, [esi] add dh, [esi+0]
adc edx, 0
.end:
ret
;IN: 12 bytes of pseudoheader pushed onto the stack
; edx = start offset
;
; OUT: pseudochecksum in edx
align 4
checksum_pseudoheader:
add dl, [esp+5]
adc dh, [esp+4]
adc dl, [esp+7]
adc dh, [esp+6]
adc dl, [esp+9]
adc dh, [esp+8]
adc dl, [esp+11]
adc dh, [esp+10]
adc dl, [esp+13]
adc dh, [esp+12]
adc dl, [esp+15]
adc dh, [esp+14]
adc edx,0
ret 12
align 4
checksum_ip_header:
; This is the fast procedure to create or check a IP header without options
;
; To create a new checksum, the checksum field must be set to 0 before computation
;
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
xor edx, edx
add dl, [esi+1]
adc dh, [esi+0]
adc dl, [esi+3]
adc dh, [esi+2]
adc dl, [esi+5]
adc dh, [esi+4]
adc dl, [esi+7]
adc dh, [esi+6]
adc dl, [esi+9]
adc dh, [esi+8]
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
adc dl, [esi+13]
adc dh, [esi+12]
adc dl, [esi+15]
adc dh, [esi+14]
adc dl, [esi+17]
adc dh, [esi+16]
adc dl, [esi+19]
adc dh, [esi+18]
adc edx, 0 adc edx, 0
.end: call checksum_2
neg word [esi+10] ; zero will stay zero so we jsut get the checksum
add word [esi+10], dx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
ret ret
align 4
checksum_udp:
; This is the fast procedure to create or check a IP header without options
;
; To create a new checksum, the checksum field must be set to 0 before computation
;
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
xor edx, edx
add dl, [esi+1]
adc dh, [esi+0]
adc dl, [esi+3]
adc dh, [esi+2]
adc dl, [esi+5]
adc dh, [esi+4]
adc dl, [esi+7]
adc dh, [esi+6]
adc dl, [esi+9]
adc dh, [esi+8]
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
adc dl, [esi+13]
adc dh, [esi+12]
adc dl, [esi+15]
adc dh, [esi+14]
adc dl, [esi+17]
adc dh, [esi+16]
adc dl, [esi+19]
adc dh, [esi+18]
adc edx, 0
call checksum_2
neg word [esi+10] ; zero will stay zero so we jsut get the checksum
add word [esi+10], dx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
ret
;----------------------------------------------------------------- ;-----------------------------------------------------------------
; ;
; checksum_2 ; checksum_2
@ -400,3 +598,6 @@ sys_protocols:
.return: .return:
mov [esp+28+4], eax mov [esp+28+4], eax
ret ret
__DEBUG_LEVEL__ equ __DEBUG_LEVEL_OLD__

View File

@ -139,10 +139,8 @@ TCP_decrease_socket_ttls:
; scan through all the sockets, decrementing active timers ; scan through all the sockets, decrementing active timers
mov ebx, net_sockets mov ebx, net_sockets
cmp [ebx + SOCKET_head.NextPtr], 0 cmp [ebx + SOCKET_head.NextPtr], 0
je .exit je .exit
.next_socket: .next_socket:
mov ebx, [ebx + SOCKET_head.NextPtr] mov ebx, [ebx + SOCKET_head.NextPtr]
or ebx, ebx or ebx, ebx

View File

@ -74,35 +74,37 @@ UDP_init:
align 4 align 4
UDP_handler: UDP_handler:
DEBUGF 1,"UDP_Handler\n" DEBUGF 1,"UDP_Handler\n"
cmp [edx + UDP_Packet.Checksum], 0
jz .no_checksum
; First validate, checksum: ; First validate, checksum:
pusha pusha
rol cx, 8
push cx push cx
rol cx, 8 rol word [esp], 8
push word IP_PROTO_UDP shl 8 push word IP_PROTO_UDP shl 8
push edi push edi
push esi push esi
mov di, [edx + UDP_Packet.Checksum] mov di, [edx + UDP_Packet.Checksum]
mov [edx + UDP_Packet.Checksum], 0 mov [edx + UDP_Packet.Checksum], 0
mov esi, edx mov esi, edx
xor edx, edx xor edx, edx
call checksum_1 call checksum_1
mov ecx, 12 call checksum_pseudoheader
mov esi, esp
call checksum_1
add esp, 12
call checksum_2 call checksum_2
cmp di, dx cmp di, dx
popa popa
jne .dump jne .checksum_mismatch ;dump
DEBUGF 1,"UDP Checksum is correct\n"
.no_checksum:
DEBUGF 1,"UDP Checksum is correct\n"
; Look for a socket where ; Look for a socket where
; IP Packet UDP Destination Port = local Port ; IP Packet UDP Destination Port = local Port
@ -110,7 +112,7 @@ UDP_handler:
mov eax, net_sockets mov eax, net_sockets
.try_more: .try_more:
mov bx , [edx + UDP_Packet.DestinationPort] ; get the local port from the IP Packet's UDP header mov si , [edx + UDP_Packet.DestinationPort] ; get the local port from the IP Packet's UDP header
.next_socket: .next_socket:
mov eax, [eax + SOCKET_head.NextPtr] mov eax, [eax + SOCKET_head.NextPtr]
or eax, eax or eax, eax
@ -119,10 +121,10 @@ UDP_handler:
jne .next_socket jne .next_socket
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
jne .next_socket jne .next_socket
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], si
jne .next_socket jne .next_socket
DEBUGF 1,"found socket with matching domain, type and localport\n" DEBUGF 1,"found socket with matching domain, type and localport\n"
; For dhcp, we must allow any remote server to respond. ; For dhcp, we must allow any remote server to respond.
; I will accept the first incoming response to be the one ; I will accept the first incoming response to be the one
@ -131,28 +133,30 @@ UDP_handler:
cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0xffffffff cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0xffffffff
je .ok1 je .ok1
mov ebx, [esp] mov esi, [esp]
mov ebx, [ebx + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet FIXME mov esi, [ebx + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet FIXME
cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi
jne .try_more ; Quit if the source IP is not valid, check for more sockets with this IP/PORT combination jne .try_more ; Quit if the source IP is not valid, check for more sockets with this IP/PORT combination
DEBUGF 1,"Remote Ip matches\n" DEBUGF 1,"Remote Ip matches\n"
.ok1: .ok1:
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket], 0 cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket], 0
jz .updateport jz .updateport
mov bx, [edx + UDP_Packet.SourcePort] mov si, [edx + UDP_Packet.SourcePort]
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], si
jne .dump jne .dump
push ebx
lea ebx, [eax + SOCKET_head.lock] lea ebx, [eax + SOCKET_head.lock]
call wait_mutex call wait_mutex
pop ebx
.ok2: .ok2:
DEBUGF 1,"Found valid UDP packet for socket %x\n", eax DEBUGF 1,"Found valid UDP packet for socket %x\n", eax
lea esi, [edx + UDP_Packet.Data] lea esi, [edx + UDP_Packet.Data]
movzx ecx, [edx + UDP_Packet.Length] movzx ecx, [edx + UDP_Packet.Length]
rol cx , 8 rol cx , 8
@ -170,20 +174,33 @@ UDP_handler:
.updateport: .updateport:
push ebx
lea ebx, [eax + SOCKET_head.lock] lea ebx, [eax + SOCKET_head.lock]
call wait_mutex call wait_mutex
pop ebx
mov bx, [edx + UDP_Packet.SourcePort] mov si, [edx + UDP_Packet.SourcePort]
DEBUGF 1,"Changing remote port to: %x\n", bx DEBUGF 1,"Changing remote port to: %x\n", si
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], si
inc [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket] inc [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket]
jmp .ok2 jmp .ok2
.checksum_mismatch:
DEBUGF 2,"UDP_Handler - checksum mismatch\n"
mov esi, [esp]
mov ecx, [esp + 4]
@@: ;
lodsb ;
DEBUGF 2,"%x ", eax:2 ;
loop @r ;
.dump: .dump:
DEBUGF 1,"Dumping UDP packet\n"
call kernel_free call kernel_free
add esp, 4 ; pop (balance stack) add esp, 4 ; pop (balance stack)
DEBUGF 2,"UDP_Handler - dumping\n"
ret ret
@ -210,15 +227,12 @@ UDP_socket_send:
mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP] mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP] mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
DEBUGF 1,"Create UDP Packet (size=%u)\n",ecx DEBUGF 1,"Create UDP Packet (size=%u)\n",ecx
mov di , IP_PROTO_UDP mov di , IP_PROTO_UDP
sub esp, 8 ; reserve some place in stack for later sub esp, 8 ; reserve some place in stack for later
; Create a part of the pseudoheader in stack,
; Create a part pseudoheader in stack,
push dword IP_PROTO_UDP shl 8 push dword IP_PROTO_UDP shl 8
add ecx, UDP_Packet.Data add ecx, UDP_Packet.Data
; TODO: fill in: dx = fragment id ; TODO: fill in: dx = fragment id
@ -257,17 +271,14 @@ UDP_socket_send:
; Checksum for pseudoheader ; Checksum for pseudoheader
pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options.. pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options..
pushd [edi-8] ; source address pushd [edi-8] ; source address
mov ecx, 12 call checksum_pseudoheader
mov esi, esp
call checksum_1
add esp, 12 ; remove the pseudoheader from stack
; Now create the final checksum and store it in UDP header ; Now create the final checksum and store it in UDP header
call checksum_2 call checksum_2
mov [edi + UDP_Packet.Checksum], dx mov [edi + UDP_Packet.Checksum], dx
inc [UDP_PACKETS_TX] inc [UDP_PACKETS_TX]
DEBUGF 1,"Sending UDP Packet to device %x\n", ebx ; DEBUGF 1,"Sending UDP Packet to device %x\n", ebx ;
jmp ETH_sender ; jmp ETH_sender ;
.fail: .fail: