From c59969f41c6c777bf53ff9ce9b397727879c3b06 Mon Sep 17 00:00:00 2001 From: hidnplayr Date: Fri, 28 May 2010 20:47:32 +0000 Subject: [PATCH] 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 --- kernel/branches/net/network/IPv4.inc | 341 ++++++++++++----------- kernel/branches/net/network/ethernet.inc | 129 +++++---- kernel/branches/net/network/icmp.inc | 6 +- kernel/branches/net/network/socket.inc | 6 +- kernel/branches/net/network/stack.inc | 223 ++++++++++++++- kernel/branches/net/network/tcp.inc | 2 - kernel/branches/net/network/udp.inc | 79 +++--- 7 files changed, 520 insertions(+), 266 deletions(-) diff --git a/kernel/branches/net/network/IPv4.inc b/kernel/branches/net/network/IPv4.inc index 759f78a1f9..d28171513b 100644 --- a/kernel/branches/net/network/IPv4.inc +++ b/kernel/branches/net/network/IPv4.inc @@ -113,85 +113,110 @@ IPv4_init: ; ;----------------------------------------------------------------- align 4 -IPv4_handler: ; TODO: clean up this mess - ; for instance, there should be only one piece of code wich make the jump to an underlying protocol, and not two.. +IPv4_handler: ; TODO: implement handler for IP options ; TODO2: add code for IPv4 sockets (raw sockets) DEBUGF 1,"IP_Handler - start\n" - push edx ebx - ; save checksum, and clear it in original packet - mov di , [edx + IPv4_Packet.HeaderChecksum] - 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 !!! /!\ +;------------------------------------------- +; Check if the packet still has time to live cmp byte [edx + IPv4_Packet.TimeToLive], 0 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 ? - jnz .yes_fragments ; If so, we definately have a fragmented packet + movzx eax, [edx + IPv4_Packet.VersionAndIHL] + 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 and eax, 0x0000000F ; shl eax, 2 ; - movzx ecx, word [edx + IPv4_Packet.TotalLength] ; Calculate length of encapsulated Packet xchg cl , ch ; sub ecx, eax ; add eax, edx 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 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 @@ -203,35 +228,79 @@ IPv4_handler: ; TODO: clean up this mess cmp al , IP_PROTO_ICMP je ICMP_handler - DEBUGF 1,"unknown protocol: %u\n",al + DEBUGF 2,"unknown Internet protocol: %u\n", al .dump: - DEBUGF 1,"IP_Handler - done\n" + DEBUGF 2,"IP_Handler - dumping\n" ; inc [dumped_rx_count] call kernel_free add esp, 4 ; pop (balance stack) ret - .yes_fragments: +;--------------------------- +; Fragmented packet handler + + + .has_fragments: + movzx eax, [edx + IPv4_Packet.FlagsAndFragmentOffset] + xchg al , ah shl ax , 3 + 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? - 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" ; try to locate a free slot.. mov ecx, MAX_FRAGMENTS mov esi, FRAGMENT_LIST - .find_free_slot: + .find_free_slot: cmp word [esi + FRAGMENT_slot.ttl], 0 je .found_free_slot add esi, FRAGMENT_slot.size loop .find_free_slot 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 ax , word [edx + IPv4_Packet.Identification] mov word [esi + FRAGMENT_slot.id], ax @@ -250,51 +319,24 @@ IPv4_handler: ; TODO: clean up this mess ret +;----------------------------------- +; We have received the last fragment - .not_first_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: + .is_last_fragment: DEBUGF 1,"Last fragmented packet received!\n" - call .find_fragment_slot + + call IPv4_find_fragment_slot cmp esi, -1 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 push esi - xor eax, eax ; + xor eax, eax or edi, -1 - .count_bytes: + + .count_bytes: 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 xchg cl, ch 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 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 - xchg cl , ch ; intel byte order + xchg cl , ch ; intel byte order shl cx , 3 ; multiply by 8 and clear first 3 bits DEBUGF 1,"Fragment offset: %u\n", cx @@ -358,7 +400,7 @@ IPv4_handler: ; TODO: clean up this mess je .first_fragment sub cx, bx ; If not, dont copy the header add esi, ebx ; - .first_fragment: + .first_fragment: push cx ; First copy dword-wise, then byte-wise shr cx, 2 ; @@ -369,6 +411,7 @@ IPv4_handler: ; TODO: clean up this mess push eax 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 call kernel_free ; free the previous fragment buffer (this uses the value from stack) pop eax @@ -381,46 +424,19 @@ IPv4_handler: ; TODO: clean up this mess mov word [edx + IPv4_Packet.TotalLength], cx add esp, 8 - xchg cl, ch ; This prints the IP packet to the debug board (usefull when using serial output debug..) - push ecx ;;;; - push eax ;;;; -; mov esi, edx ; + xchg cl, ch ; + + push ecx ;;;; + push eax ;;;; + +; mov esi, edx ; This prints the IP packet to the debug board (usefull when using serial output debug..) ; ; ; @@: ; ; lodsb ; ; DEBUGF 1,"%x ", eax:2 ; ; loop @r ; - movzx eax, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field - 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 - + jmp .handle_it ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr .destroy_slot_pop: 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 @@ -439,8 +467,8 @@ IPv4_handler: ; TODO: clean up this mess ; OUT: pointer to slot in edi, -1 on error ; ;----------------------------------------------------------------- - - .find_fragment_slot: +align 4 +IPv4_find_fragment_slot: push eax ebx ecx edx mov ax , word [edx + IPv4_Packet.Identification] @@ -458,7 +486,7 @@ IPv4_handler: ; TODO: clean up this mess .try_next: add esi, FRAGMENT_slot.size loop .find_slot - ; pop edx ebx +; pop edx ebx or esi, -1 ; ret @@ -581,15 +609,10 @@ IPv4_create_packet: pop ecx mov [edi + IPv4_Packet.DestinationAddress], ecx - push eax ebx edx - ; calculate checksum - xor edx, edx + push eax edx esi mov esi, edi - mov ecx, IPv4_Packet.DataOrOptional - call checksum_1 - call checksum_2 - mov [edi + IPv4_Packet.HeaderChecksum], dx - pop edx ebx eax ecx + call checksum_ip_header + pop esi edx eax ecx add edi, IPv4_Packet.DataOrOptional DEBUGF 1,"IPv4 Packet for device %x created successfully\n", ebx @@ -644,7 +667,7 @@ IPv4_dest_to_dev: .found_it: shr edi, 2 - DEBUGF 1,"%u\n",edi + DEBUGF 1,"%u\n",edi ret @@ -705,59 +728,59 @@ IPv4_API: dec bl jz .write_gateway ; 9 -.error: + .error: mov eax, -1 ret -.packets_tx: + .packets_tx: add eax, IP_PACKETS_TX mov eax, [eax] ret -.packets_rx: + .packets_rx: add eax, IP_PACKETS_RX mov eax, [eax] ret -.read_ip: + .read_ip: add eax, IP_LIST mov eax, [eax] ret -.write_ip: + .write_ip: add eax, IP_LIST mov [eax], ecx xor eax, eax ret -.read_dns: + .read_dns: add eax, DNS_LIST mov eax, [eax] ret -.write_dns: + .write_dns: add eax, DNS_LIST mov [eax], ecx xor eax, eax ret -.read_subnet: + .read_subnet: add eax, SUBNET_LIST mov eax, [eax] ret -.write_subnet: + .write_subnet: add eax, SUBNET_LIST mov [eax], ecx xor eax, eax ret -.read_gateway: + .read_gateway: add eax, GATEWAY_LIST mov eax, [eax] ret -.write_gateway: + .write_gateway: add eax, GATEWAY_LIST mov [eax], ecx xor eax, eax diff --git a/kernel/branches/net/network/ethernet.inc b/kernel/branches/net/network/ethernet.inc index 616decb60b..60b0b0f6cc 100644 --- a/kernel/branches/net/network/ethernet.inc +++ b/kernel/branches/net/network/ethernet.inc @@ -153,7 +153,7 @@ end if .error: or eax, -1 - DEBUGF 1,"- fail\n" + DEBUGF 2,"Adding ETH device failed\n" ret @@ -219,50 +219,56 @@ end if align 4 ETH_receiver: - DEBUGF 1,"ETH_Receiver: " - push ebx - mov esi, esp - add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail - DEBUGF 1,"Queued packet successfully\n" - add esp, 4*3 - - ret - - .fail: - DEBUGF 1,"ETH_IN_QUEUE is full!\n" - add esp, 4 - call kernel_free - add esp, 4 - - ret - - - -;----------------------------------------------------------------- +; DEBUGF 1,"ETH_Receiver: " +; push ebx +; mov esi, esp +; add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail +; DEBUGF 1,"Queued packet successfully\n" +; add esp, 4*3 ; -; 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: / -; OUT: / +; ret ; -;----------------------------------------------------------------- -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 - - lodsd - mov ebx, eax - lodsd - mov ecx, eax - lodsd - xchg eax, ecx - push ecx - push eax +;----------------------------- + mov eax, [esp] + mov ecx, [esp+4] +;----------------------------- DEBUGF 1,"ETH_Handler - size: %u\n", ecx cmp ecx, 60 ; check packet length @@ -278,10 +284,10 @@ ETH_handler: cmp ax, ETHER_ARP je ARP_handler - DEBUGF 1,"Unknown ethernet packet type %x\n", ax + DEBUGF 2,"Unknown ethernet packet type %x\n", ax .dump: - DEBUGF 1,"Dumping packet\n" + DEBUGF 2,"ETH_Handler - dumping\n" call kernel_free add esp, 4 @@ -290,6 +296,12 @@ ETH_handler: + +align 4 +ETH_handler: +ret + + ;----------------------------------------------------------------- ; ; ETH_sender: @@ -366,24 +378,29 @@ end if ;----------------------------------------------------------------- align 4 ETH_struc2dev: - push eax ecx + push ecx - mov eax, ebx mov ecx, MAX_ETH_DEVICES 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 - pop ecx eax - ret - .error: - or edi, -1 - pop ecx eax - + pop ecx ret @@ -408,7 +425,7 @@ ETH_struc2dev: align 4 ETH_create_packet: - DEBUGF 1,"Creating Ethernet Packet (size=%u): \n", ecx + DEBUGF 1,"Creating Ethernet Packet (size=%u): \n", ecx cmp ecx, 1500 jg .exit @@ -448,17 +465,17 @@ ETH_create_packet: mov edx, 46 + ETH_FRAME.Data .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 .pop_exit: - DEBUGF 1,"Out of ram space!!\n" + DEBUGF 2,"Out of ram space!!\n" add esp, 18 or edi,-1 ret .exit: - DEBUGF 1,"Packet too large!\n" + DEBUGF 2,"Packet too large!\n" or edi, -1 ret diff --git a/kernel/branches/net/network/icmp.inc b/kernel/branches/net/network/icmp.inc index e89130abab..78ed39bd0a 100644 --- a/kernel/branches/net/network/icmp.inc +++ b/kernel/branches/net/network/icmp.inc @@ -146,10 +146,14 @@ ICMP_init: align 4 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? 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 word [edx + ICMP_Packet.Checksum], 0 ; Set checksum to 0, needed to calculate new checksum diff --git a/kernel/branches/net/network/socket.inc b/kernel/branches/net/network/socket.inc index decdb4e3d5..88914db64e 100644 --- a/kernel/branches/net/network/socket.inc +++ b/kernel/branches/net/network/socket.inc @@ -16,8 +16,8 @@ $Revision$ struct SOCKET_head - .PrevPtr dd ? ; pointer to previous 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) .PID dd ? ; application process id .Domain dd ? ; INET/UNIX/.. @@ -935,7 +935,7 @@ socket_check_port: align 4 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 ecx ; size @@ -969,7 +969,7 @@ notify_network_event: ret .full: - DEBUGF 1,"Socket %x is full!\n",eax + DEBUGF 2,"Socket %x is full!\n",eax mov [eax + SOCKET_head.lock], 0 call kernel_free add esp, 8 diff --git a/kernel/branches/net/network/stack.inc b/kernel/branches/net/network/stack.inc index 3c7ff46034..59b93240d9 100644 --- a/kernel/branches/net/network/stack.inc +++ b/kernel/branches/net/network/stack.inc @@ -19,18 +19,21 @@ $Revision$ +__DEBUG_LEVEL_OLD__ equ __DEBUG_LEVEL__ +__DEBUG_LEVEL__ equ 1 ; this sets the debug level for network part of kernel + uglobal last_1sTick db ? last_1hsTick dd ? endg 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 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 AF_UNSPEC equ 0 @@ -207,35 +210,230 @@ end if ; ; 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 ; ecx = data size ; OUT: edx = semi-checksum ; +; +; Code was optimized by diamond +; ;----------------------------------------------------------------- align 4 checksum_1: - xor eax, eax shr ecx, 1 pushf -.loop: - lodsw - xchg al, ah - add edx, eax - loop .loop + jz .no_2 + 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 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 -.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 + + + + + + +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 @@ -400,3 +598,6 @@ sys_protocols: .return: mov [esp+28+4], eax ret + + +__DEBUG_LEVEL__ equ __DEBUG_LEVEL_OLD__ \ No newline at end of file diff --git a/kernel/branches/net/network/tcp.inc b/kernel/branches/net/network/tcp.inc index 4896b757cb..f762d4d3fd 100644 --- a/kernel/branches/net/network/tcp.inc +++ b/kernel/branches/net/network/tcp.inc @@ -139,10 +139,8 @@ TCP_decrease_socket_ttls: ; scan through all the sockets, decrementing active timers mov ebx, net_sockets - cmp [ebx + SOCKET_head.NextPtr], 0 je .exit - .next_socket: mov ebx, [ebx + SOCKET_head.NextPtr] or ebx, ebx diff --git a/kernel/branches/net/network/udp.inc b/kernel/branches/net/network/udp.inc index 0462359dc1..1a63868dbb 100644 --- a/kernel/branches/net/network/udp.inc +++ b/kernel/branches/net/network/udp.inc @@ -74,35 +74,37 @@ UDP_init: align 4 UDP_handler: - DEBUGF 1,"UDP_Handler\n" + DEBUGF 1,"UDP_Handler\n" + + cmp [edx + UDP_Packet.Checksum], 0 + jz .no_checksum ; First validate, checksum: pusha - rol cx, 8 push cx - rol cx, 8 + rol word [esp], 8 push word IP_PROTO_UDP shl 8 push edi push esi mov di, [edx + UDP_Packet.Checksum] - mov [edx + UDP_Packet.Checksum], 0 + mov [edx + UDP_Packet.Checksum], 0 mov esi, edx xor edx, edx call checksum_1 - mov ecx, 12 - mov esi, esp - call checksum_1 - add esp, 12 + call checksum_pseudoheader call checksum_2 cmp di, dx 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 ; IP Packet UDP Destination Port = local Port @@ -110,7 +112,7 @@ UDP_handler: mov eax, net_sockets .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: mov eax, [eax + SOCKET_head.NextPtr] or eax, eax @@ -119,10 +121,10 @@ UDP_handler: jne .next_socket cmp [eax + SOCKET_head.Type], IP_PROTO_UDP 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 - 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. ; 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 je .ok1 - mov ebx, [esp] - mov ebx, [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 + mov esi, [esp] + 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], esi 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: cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket], 0 jz .updateport - mov bx, [edx + UDP_Packet.SourcePort] - cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx + mov si, [edx + UDP_Packet.SourcePort] + cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], si jne .dump + push ebx lea ebx, [eax + SOCKET_head.lock] call wait_mutex + pop ebx .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] movzx ecx, [edx + UDP_Packet.Length] rol cx , 8 @@ -170,20 +174,33 @@ UDP_handler: .updateport: + push ebx lea ebx, [eax + SOCKET_head.lock] call wait_mutex + pop ebx - mov bx, [edx + UDP_Packet.SourcePort] - DEBUGF 1,"Changing remote port to: %x\n", bx - mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx + mov si, [edx + UDP_Packet.SourcePort] + DEBUGF 1,"Changing remote port to: %x\n", si + mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], si inc [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket] 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: - DEBUGF 1,"Dumping UDP packet\n" call kernel_free add esp, 4 ; pop (balance stack) + DEBUGF 2,"UDP_Handler - dumping\n" ret @@ -210,15 +227,12 @@ UDP_socket_send: mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP] 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 - sub esp, 8 ; reserve some place in stack for later - -; Create a part pseudoheader in stack, + ; Create a part of the pseudoheader in stack, push dword IP_PROTO_UDP shl 8 - add ecx, UDP_Packet.Data ; TODO: fill in: dx = fragment id @@ -257,17 +271,14 @@ UDP_socket_send: ; Checksum for pseudoheader pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options.. pushd [edi-8] ; source address - mov ecx, 12 - mov esi, esp - call checksum_1 - add esp, 12 ; remove the pseudoheader from stack + call checksum_pseudoheader ; Now create the final checksum and store it in UDP header call checksum_2 mov [edi + UDP_Packet.Checksum], dx 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 ; .fail: