forked from KolibriOS/kolibrios
Net-branch:
Fixed Bugs in checksum, introduced in #1473 Checksum for IP/UDP/TCP is now very fast. git-svn-id: svn://kolibrios.org@1482 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
049d796e81
commit
34c194bda4
@ -140,7 +140,7 @@ IPv4_handler: ; TODO: implement handler for IP options
|
|||||||
; Re-calculate checksum
|
; Re-calculate checksum
|
||||||
push edx ebx
|
push edx ebx
|
||||||
mov esi, edx
|
mov esi, edx
|
||||||
call checksum_ip_header
|
call IPv4_checksum
|
||||||
pop ebx edx
|
pop ebx edx
|
||||||
|
|
||||||
; now see if it was correct
|
; now see if it was correct
|
||||||
@ -611,7 +611,7 @@ IPv4_create_packet:
|
|||||||
|
|
||||||
push eax edx esi
|
push eax edx esi
|
||||||
mov esi, edi
|
mov esi, edi
|
||||||
call checksum_ip_header
|
call IPv4_checksum
|
||||||
pop esi edx eax ecx
|
pop esi edx eax ecx
|
||||||
add edi, IPv4_Packet.DataOrOptional
|
add edi, IPv4_Packet.DataOrOptional
|
||||||
|
|
||||||
@ -632,6 +632,58 @@ IPv4_create_packet:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
align 4
|
||||||
|
IPv4_checksum:
|
||||||
|
|
||||||
|
; 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 just get the checksum
|
||||||
|
add word [esi+10], dx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;---------------------------------------------------------------------------
|
;---------------------------------------------------------------------------
|
||||||
;
|
;
|
||||||
|
@ -208,7 +208,7 @@ end if
|
|||||||
;
|
;
|
||||||
; checksum_1
|
; checksum_1
|
||||||
;
|
;
|
||||||
; This is the first of two functions needed to calculate the TCP checksum.
|
; This is the first of two functions needed to calculate a checksum.
|
||||||
;
|
;
|
||||||
; IN: edx = start offset for semi-checksum
|
; IN: edx = start offset for semi-checksum
|
||||||
; esi = pointer to data
|
; esi = pointer to data
|
||||||
@ -289,151 +289,6 @@ checksum_1:
|
|||||||
.end:
|
.end:
|
||||||
ret
|
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
|
|
||||||
|
|
||||||
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
|
; checksum_2
|
||||||
@ -451,9 +306,10 @@ checksum_2:
|
|||||||
shr ecx, 16
|
shr ecx, 16
|
||||||
and edx, 0xffff
|
and edx, 0xffff
|
||||||
add edx, ecx
|
add edx, ecx
|
||||||
mov eax, edx
|
|
||||||
shr eax, 16
|
mov ecx, edx
|
||||||
add edx, eax
|
shr ecx, 16
|
||||||
|
add edx, ecx
|
||||||
|
|
||||||
not dx
|
not dx
|
||||||
jnz .not_zero
|
jnz .not_zero
|
||||||
|
@ -67,43 +67,32 @@ UDP_init:
|
|||||||
; size of buffer in [esp+4]
|
; size of buffer in [esp+4]
|
||||||
; pointer to device struct in ebx
|
; pointer to device struct in ebx
|
||||||
; UDP Packet size in ecx
|
; UDP Packet size in ecx
|
||||||
; pointer to UDP Packet data in edx
|
; pointer to UDP Packet in edx
|
||||||
; OUT: /
|
; OUT: /
|
||||||
;
|
;
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
align 4
|
align 4
|
||||||
UDP_handler:
|
UDP_handler:
|
||||||
|
|
||||||
DEBUGF 1,"UDP_Handler\n"
|
DEBUGF 1,"UDP_Handler, checksum:%x\n", [edx+UDP_Packet.Checksum]:4
|
||||||
|
|
||||||
|
; First validate, checksum:
|
||||||
cmp [edx + UDP_Packet.Checksum], 0
|
cmp [edx + UDP_Packet.Checksum], 0
|
||||||
jz .no_checksum
|
jz .no_checksum
|
||||||
; First validate, checksum:
|
|
||||||
|
|
||||||
pusha
|
push ecx edx
|
||||||
|
|
||||||
push cx
|
|
||||||
rol word [esp], 8
|
|
||||||
push word IP_PROTO_UDP shl 8
|
|
||||||
push edi
|
|
||||||
push esi
|
push esi
|
||||||
|
push edi
|
||||||
mov di, [edx + UDP_Packet.Checksum]
|
|
||||||
mov [edx + UDP_Packet.Checksum], 0
|
|
||||||
|
|
||||||
mov esi, edx
|
mov esi, edx
|
||||||
xor edx, edx
|
call UDP_checksum
|
||||||
call checksum_1
|
|
||||||
call checksum_pseudoheader
|
|
||||||
call checksum_2
|
|
||||||
|
|
||||||
cmp di, dx
|
pop edx ecx
|
||||||
popa
|
|
||||||
jne .checksum_mismatch ;dump
|
|
||||||
|
|
||||||
|
cmp [edx + UDP_Packet.Checksum], 0
|
||||||
|
jnz .checksum_mismatch
|
||||||
|
|
||||||
.no_checksum:
|
.no_checksum:
|
||||||
|
|
||||||
DEBUGF 1,"UDP Checksum is correct\n"
|
DEBUGF 1,"UDP Checksum is correct\n"
|
||||||
|
|
||||||
; Look for a socket where
|
; Look for a socket where
|
||||||
@ -190,12 +179,11 @@ UDP_handler:
|
|||||||
|
|
||||||
DEBUGF 2,"UDP_Handler - checksum mismatch\n"
|
DEBUGF 2,"UDP_Handler - checksum mismatch\n"
|
||||||
|
|
||||||
mov esi, [esp]
|
; mov esi, edx
|
||||||
mov ecx, [esp + 4]
|
; @@: ;
|
||||||
@@: ;
|
; lodsb ;
|
||||||
lodsb ;
|
; DEBUGF 2,"%x ", eax:2 ;
|
||||||
DEBUGF 2,"%x ", eax:2 ;
|
; loop @r ;
|
||||||
loop @r ;
|
|
||||||
|
|
||||||
.dump:
|
.dump:
|
||||||
call kernel_free
|
call kernel_free
|
||||||
@ -230,9 +218,7 @@ UDP_socket_send:
|
|||||||
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 ; Data ptr and data size will be placed here
|
||||||
; Create a part of the pseudoheader in stack,
|
|
||||||
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
|
||||||
@ -242,12 +228,11 @@ UDP_socket_send:
|
|||||||
cmp edi, -1
|
cmp edi, -1
|
||||||
je .fail
|
je .fail
|
||||||
|
|
||||||
mov [esp + 8 + 4], eax ; pointer to buffer start
|
mov [esp + 8], eax ; pointer to buffer start
|
||||||
mov [esp + 8 + 4 + 4], edx ; buffer size
|
mov [esp + 8 + 4], edx ; buffer size
|
||||||
|
|
||||||
rol cx, 8
|
rol cx, 8
|
||||||
mov [edi + UDP_Packet.Length], cx
|
mov [edi + UDP_Packet.Length], cx
|
||||||
mov [esp + 8 + 2], cx
|
|
||||||
ror cx, 8
|
ror cx, 8
|
||||||
|
|
||||||
pop esi
|
pop esi
|
||||||
@ -264,22 +249,16 @@ UDP_socket_send:
|
|||||||
pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers
|
pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers
|
||||||
mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum
|
mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum
|
||||||
|
|
||||||
; Checksum for UDP header + data
|
; Checksum
|
||||||
xor edx, edx
|
|
||||||
mov esi, edi
|
mov esi, edi
|
||||||
call checksum_1
|
|
||||||
; 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
|
||||||
call checksum_pseudoheader
|
call UDP_checksum
|
||||||
; Now create the final checksum and store it in UDP header
|
|
||||||
call checksum_2
|
|
||||||
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:
|
||||||
; todo: queue the packet
|
; todo: queue the packet
|
||||||
@ -289,6 +268,73 @@ UDP_socket_send:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; checksum_udp
|
||||||
|
;
|
||||||
|
; This is the fast procedure to create or check a UDP header
|
||||||
|
; - 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
|
||||||
|
;
|
||||||
|
; IN: push source ip
|
||||||
|
; push dest ip
|
||||||
|
; esi = packet ptr
|
||||||
|
;
|
||||||
|
; OUT: checksum is filled in in packet! (but also in dx)
|
||||||
|
;
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
align 4
|
||||||
|
UDP_checksum:
|
||||||
|
|
||||||
|
; Pseudoheader
|
||||||
|
mov edx, IP_PROTO_UDP ; NO shl 8 here ! (it took me ages to figure this one out)
|
||||||
|
|
||||||
|
add dl, [esp+1+4]
|
||||||
|
adc dh, [esp+0+4]
|
||||||
|
adc dl, [esp+3+4]
|
||||||
|
adc dh, [esp+2+4]
|
||||||
|
|
||||||
|
adc dl, [esp+1+8]
|
||||||
|
adc dh, [esp+0+8]
|
||||||
|
adc dl, [esp+3+8]
|
||||||
|
adc dh, [esp+2+8]
|
||||||
|
|
||||||
|
adc dl, byte[esi+UDP_Packet.Length+1]
|
||||||
|
adc dh, byte[esi+UDP_Packet.Length+0]
|
||||||
|
|
||||||
|
; Done with pseudoheader, now do real header
|
||||||
|
adc dl, byte[esi+UDP_Packet.SourcePort+1]
|
||||||
|
adc dh, byte[esi+UDP_Packet.SourcePort+0]
|
||||||
|
|
||||||
|
adc dl, byte[esi+UDP_Packet.DestinationPort+1]
|
||||||
|
adc dh, byte[esi+UDP_Packet.DestinationPort+0]
|
||||||
|
|
||||||
|
adc dl, byte[esi+UDP_Packet.Length+1]
|
||||||
|
adc dh, byte[esi+UDP_Packet.Length+0]
|
||||||
|
|
||||||
|
adc edx, 0
|
||||||
|
|
||||||
|
; Done with header, now do data
|
||||||
|
push esi
|
||||||
|
movzx ecx, [esi+UDP_Packet.Length]
|
||||||
|
rol cx , 8
|
||||||
|
sub cx , UDP_Packet.Data
|
||||||
|
add esi, UDP_Packet.Data
|
||||||
|
|
||||||
|
call checksum_1
|
||||||
|
call checksum_2
|
||||||
|
pop esi
|
||||||
|
|
||||||
|
neg [esi+UDP_Packet.Checksum] ; zero will stay zero so we just get the checksum
|
||||||
|
add [esi+UDP_Packet.Checksum], dx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
|
||||||
|
|
||||||
|
ret 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;---------------------------------------------------------------------------
|
;---------------------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; UDP_API
|
; UDP_API
|
||||||
|
Loading…
Reference in New Issue
Block a user