From 54e96610452e196195c74a038ec85996b685cb93 Mon Sep 17 00:00:00 2001 From: "Mihail Semenyako (mike.dld)" Date: Wed, 5 Nov 2008 00:42:22 +0000 Subject: [PATCH] Network stack: dynamic sockets list, other small fixes git-svn-id: svn://kolibrios.org@907 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/core/sched.inc | 418 ++-- kernel/trunk/data32.inc | 2 +- .../trunk/network/eth_drv/drivers/rtl8169.inc | 52 +- kernel/trunk/network/eth_drv/ethernet.inc | 14 +- kernel/trunk/network/ip.inc | 124 +- kernel/trunk/network/queue.inc | 39 +- kernel/trunk/network/socket.inc | 1236 ++++++----- kernel/trunk/network/stack.inc | 29 +- kernel/trunk/network/tcp.inc | 1914 ++++++++--------- kernel/trunk/network/udp.inc | 156 +- 10 files changed, 2033 insertions(+), 1951 deletions(-) diff --git a/kernel/trunk/core/sched.inc b/kernel/trunk/core/sched.inc index eafda6b848..83db51f967 100644 --- a/kernel/trunk/core/sched.inc +++ b/kernel/trunk/core/sched.inc @@ -15,93 +15,101 @@ $Revision$ align 32 irq0: - pushad - mov ax, app_data ; - mov ds, ax - mov es, ax + pushad + mov ax, app_data ; + mov ds, ax + mov es, ax - inc dword [timer_ticks] +; cmp dword[CURRENT_TASK], 1 +; jnz @f +; mov eax, [esp + 32] +; cmp eax, idle_loop + 1 +; jz @f +; DEBUGF 1, "K : OOOPS! EAX = 0x%x\n", eax +; @@: - mov eax, [timer_ticks] - call playNote ; <<<--- Speaker driver + inc dword [timer_ticks] - cmp eax,[next_usage_update] - jb .nocounter - add eax,100 - mov [next_usage_update],eax - call updatecputimes + mov eax, [timer_ticks] + call playNote ; <<<--- Speaker driver + + cmp eax,[next_usage_update] + jb .nocounter + add eax,100 + mov [next_usage_update],eax + call updatecputimes .nocounter: - cmp [DONT_SWITCH], byte 1 - jne .change_task + cmp [DONT_SWITCH], byte 1 + jne .change_task - mov al,0x20 ; send End Of Interrupt signal - mov dx,0x20 - out dx,al + mov al,0x20 ; send End Of Interrupt signal + mov dx,0x20 + out dx,al - mov [DONT_SWITCH], byte 0 + mov [DONT_SWITCH], byte 0 - popad - iretd + popad + iretd .change_task: - call update_counters + call update_counters - call find_next_task - mov ecx, eax + call find_next_task + mov ecx, eax - mov al,0x20 ; send End Of Interrupt signal - mov dx,0x20 - out dx,al + mov al,0x20 ; send End Of Interrupt signal + mov dx,0x20 + out dx,al - test ecx, ecx ; if there is only one running process - jnz .return + test ecx, ecx ; if there is only one running process + jnz .return - call do_change_task + call do_change_task .return: - popad + popad ; popfd - iretd + iretd align 4 change_task: - pushfd - cli - pushad + pushfd + cli + pushad - call update_counters + call update_counters if 0 ; \begin{Mario79} - cmp [dma_task_switched], 1 - jne .find_next_task - mov [dma_task_switched], 0 - mov ebx, [dma_process] - cmp [CURRENT_TASK], ebx - je .return - mov edi, [dma_slot_ptr] - mov [CURRENT_TASK], ebx - mov [TASK_BASE], edi - jmp @f + cmp [dma_task_switched], 1 + jne .find_next_task + mov [dma_task_switched], 0 + mov ebx, [dma_process] + cmp [CURRENT_TASK], ebx + je .return + mov edi, [dma_slot_ptr] + mov [CURRENT_TASK], ebx + mov [TASK_BASE], edi + jmp @f .find_next_task: ; \end{Mario79} end if - call find_next_task - test eax, eax ; the same task -> skip switch - jnz .return + call find_next_task + test eax, eax ; the same task -> skip switch + jnz .return @@: - mov [DONT_SWITCH],byte 1 - call do_change_task + mov [DONT_SWITCH],byte 1 + call do_change_task .return: - popad - popfd - ret + popad + popfd + ret uglobal @@ -111,19 +119,19 @@ uglobal .sel dw ? context_counter dd ? ;noname & halyavin next_usage_update dd ? - timer_ticks dd ? - prev_slot dd ? - event_sched dd ? + timer_ticks dd ? + prev_slot dd ? + event_sched dd ? endg update_counters: - mov edi, [TASK_BASE] - mov ebx, [edi+TASKDATA.counter_add] ; time stamp counter add - rdtsc - sub eax, ebx - add eax, [edi+TASKDATA.counter_sum] ; counter sum - mov [edi+TASKDATA.counter_sum], eax + mov edi, [TASK_BASE] + mov ebx, [edi+TASKDATA.counter_add] ; time stamp counter add + rdtsc + sub eax, ebx + add eax, [edi+TASKDATA.counter_sum] ; counter sum + mov [edi+TASKDATA.counter_sum], eax ret @@ -134,65 +142,65 @@ ret ; [0x3000] = ebx and [0x3010] = edi ; corrupts other regs find_next_task: - mov ebx, [CURRENT_TASK] - mov edi, [TASK_BASE] - mov [prev_slot], ebx + mov ebx, [CURRENT_TASK] + mov edi, [TASK_BASE] + mov [prev_slot], ebx .waiting_for_termination: .waiting_for_reuse: .waiting_for_event: .suspended: - cmp ebx, [TASK_COUNT] - jb @f - mov edi, CURRENT_TASK - xor ebx, ebx + cmp ebx, [TASK_COUNT] + jb @f + mov edi, CURRENT_TASK + xor ebx, ebx @@: - add edi,0x20 - inc ebx + add edi,0x20 + inc ebx - mov al, byte [edi+TASKDATA.state] - test al, al - jz .found + mov al, byte [edi+TASKDATA.state] + test al, al + jz .found cmp al, 1 jz .suspended cmp al, 2 jz .suspended - cmp al, 3 - je .waiting_for_termination - cmp al, 4 - je .waiting_for_termination - cmp al, 9 - je .waiting_for_reuse + cmp al, 3 + je .waiting_for_termination + cmp al, 4 + je .waiting_for_termination + cmp al, 9 + je .waiting_for_reuse - mov [CURRENT_TASK],ebx - mov [TASK_BASE],edi + mov [CURRENT_TASK],ebx + mov [TASK_BASE],edi - cmp al, 5 - jne .noevents - call get_event_for_app - test eax, eax - jnz @f - mov eax, ebx - shl eax, 8 - mov eax, [SLOT_BASE + APPDATA.wait_timeout + eax] - cmp eax, [timer_ticks] - jae .waiting_for_event - xor eax, eax + cmp al, 5 + jne .noevents + call get_event_for_app + test eax, eax + jnz @f + mov eax, ebx + shl eax, 8 + mov eax, [SLOT_BASE + APPDATA.wait_timeout + eax] + cmp eax, [timer_ticks] + jae .waiting_for_event + xor eax, eax @@: - mov [event_sched], eax - mov [edi+TASKDATA.state], byte 0 + mov [event_sched], eax + mov [edi+TASKDATA.state], byte 0 .noevents: .found: - mov [CURRENT_TASK],ebx - mov [TASK_BASE],edi - rdtsc ;call _rdtsc - mov [edi+TASKDATA.counter_add],eax + mov [CURRENT_TASK],ebx + mov [TASK_BASE],edi + rdtsc ;call _rdtsc + mov [edi+TASKDATA.counter_add],eax - mov esi, [prev_slot] + mov esi, [prev_slot] xor eax, eax - cmp ebx, esi - sete al + cmp ebx, esi + sete al ret ; param @@ -201,78 +209,78 @@ ret do_change_task: - shl ebx, 8 - add ebx, SLOT_BASE - mov [current_slot], ebx + shl ebx, 8 + add ebx, SLOT_BASE + mov [current_slot], ebx - shl esi, 8 - add esi, SLOT_BASE + shl esi, 8 + add esi, SLOT_BASE - mov [esi+APPDATA.saved_esp], esp - mov esp, [ebx+APPDATA.saved_esp] + mov [esi+APPDATA.saved_esp], esp + mov esp, [ebx+APPDATA.saved_esp] ; set thread io map - mov ecx, [ebx+APPDATA.io_map] - mov edx, [ebx+APPDATA.io_map+4] - mov dword [page_tabs+((tss._io_map_0 and -4096) shr 10)], ecx - mov dword [page_tabs+((tss._io_map_1 and -4096) shr 10)], edx + mov ecx, [ebx+APPDATA.io_map] + mov edx, [ebx+APPDATA.io_map+4] + mov dword [page_tabs+((tss._io_map_0 and -4096) shr 10)], ecx + mov dword [page_tabs+((tss._io_map_1 and -4096) shr 10)], edx - mov eax, [ebx+APPDATA.dir_table] - cmp eax, [esi+APPDATA.dir_table] - je @F - mov cr3, eax + mov eax, [ebx+APPDATA.dir_table] + cmp eax, [esi+APPDATA.dir_table] + je @F + mov cr3, eax @@: - mov eax, [ebx+APPDATA.saved_esp0] - mov [tss._esp0], eax - mov ax, graph_data - mov gs, ax + mov eax, [ebx+APPDATA.saved_esp0] + mov [tss._esp0], eax + mov ax, graph_data + mov gs, ax - mov eax, [CURRENT_TASK] - cmp eax, [fpu_owner] - clts ;clear a task switch flag - je @F - ;and set it again if the owner - mov ecx, cr0 ;of a fpu has changed - or ecx, CR0_TS - mov cr0, ecx + mov eax, [CURRENT_TASK] + cmp eax, [fpu_owner] + clts ;clear a task switch flag + je @F + ;and set it again if the owner + mov ecx, cr0 ;of a fpu has changed + or ecx, CR0_TS + mov cr0, ecx @@: - inc [context_counter] ;noname & halyavin - test [ebx+APPDATA.dbg_state], 1 - jnz @F - ret + inc [context_counter] ;noname & halyavin + test [ebx+APPDATA.dbg_state], 1 + jnz @F + ret @@: - mov eax, [ebx+APPDATA.dbg_regs.dr0] - mov dr0, eax - mov eax, [ebx+APPDATA.dbg_regs.dr1] - mov dr1, eax - mov eax, [ebx+APPDATA.dbg_regs.dr2] - mov dr2, eax - mov eax, [ebx+APPDATA.dbg_regs.dr3] - mov dr3, eax - xor eax, eax - mov dr6, eax - mov eax, [ebx+APPDATA.dbg_regs.dr7] - mov dr7, eax - ret + mov eax, [ebx+APPDATA.dbg_regs.dr0] + mov dr0, eax + mov eax, [ebx+APPDATA.dbg_regs.dr1] + mov dr1, eax + mov eax, [ebx+APPDATA.dbg_regs.dr2] + mov dr2, eax + mov eax, [ebx+APPDATA.dbg_regs.dr3] + mov dr3, eax + xor eax, eax + mov dr6, eax + mov eax, [ebx+APPDATA.dbg_regs.dr7] + mov dr7, eax + ret align 4 updatecputimes: - mov eax,[idleuse] - mov [idleusesec],eax - mov [idleuse],dword 0 - mov ecx, [TASK_COUNT] - mov edi, TASK_DATA + mov eax,[idleuse] + mov [idleusesec],eax + mov [idleuse],dword 0 + mov ecx, [TASK_COUNT] + mov edi, TASK_DATA .newupdate: - mov ebx,[edi+TASKDATA.counter_sum] - mov [edi+TASKDATA.cpu_usage],ebx - mov [edi+TASKDATA.counter_sum],dword 0 - add edi,0x20 - dec ecx - jnz .newupdate + mov ebx,[edi+TASKDATA.counter_sum] + mov [edi+TASKDATA.cpu_usage],ebx + mov [edi+TASKDATA.counter_sum],dword 0 + add edi,0x20 + dec ecx + jnz .newupdate - ret + ret if 0 @@ -282,7 +290,7 @@ struc TIMER .next dd ? .exp_time dd ? .func dd ? - .arg dd ? + .arg dd ? } @@ -293,12 +301,12 @@ struc TIMER -MAX_PROIRITY 0 ; highest, used for kernel tasks -MAX_USER_PRIORITY 0 ; highest priority for user processes -USER_PRIORITY 7 ; default (should correspond to nice 0) -MIN_USER_PRIORITY 14 ; minimum priority for user processes -IDLE_PRIORITY 15 ; lowest, only IDLE process goes here -NR_SCHED_QUEUES 16 ; MUST equal IDLE_PRIORYTY + 1 +MAX_PROIRITY 0 ; highest, used for kernel tasks +MAX_USER_PRIORITY 0 ; highest priority for user processes +USER_PRIORITY 7 ; default (should correspond to nice 0) +MIN_USER_PRIORITY 14 ; minimum priority for user processes +IDLE_PRIORITY 15 ; lowest, only IDLE process goes here +NR_SCHED_QUEUES 16 ; MUST equal IDLE_PRIORYTY + 1 rdy_head rd 16 @@ -306,21 +314,21 @@ rdy_head rd 16 align 4 pick_task: - xor eax, eax + xor eax, eax .pick: - mov ebx, [rdy_head+eax*4] - test ebx, ebx - jz .next + mov ebx, [rdy_head+eax*4] + test ebx, ebx + jz .next - mov [next_task], ebx - test [ebx+flags.billable] - jz @F - mov [bill_task], ebx + mov [next_task], ebx + test [ebx+flags.billable] + jz @F + mov [bill_task], ebx @@: - ret + ret .next: - inc eax - jmp .pick + inc eax + jmp .pick ; param @@ -333,48 +341,48 @@ pick_task: align 4 shed: - cmp [eax+.tics_left], 0 ;signed compare - mov ebx, [eax+.priority] - setg ecx - jg @F + cmp [eax+.tics_left], 0 ;signed compare + mov ebx, [eax+.priority] + setg ecx + jg @F - mov edx, [eax+.tics_quantum] - mov [eax+.ticks_left], edx - cmp ebx, (IDLE_PRIORITY-1) - je @F - inc ebx + mov edx, [eax+.tics_quantum] + mov [eax+.ticks_left], edx + cmp ebx, (IDLE_PRIORITY-1) + je @F + inc ebx @@: - ret + ret ; param ; eax= task align 4 enqueue: - call shed ;eax - cmp [rdy_head+ebx*4],0 - jnz @F + call shed ;eax + cmp [rdy_head+ebx*4],0 + jnz @F - mov [rdy_head+ebx*4], eax - mov [rdy_tail+ebx*4], eax - mov [eax+.next_ready], 0 - jmp .pick + mov [rdy_head+ebx*4], eax + mov [rdy_tail+ebx*4], eax + mov [eax+.next_ready], 0 + jmp .pick @@: - test ecx, ecx - jz .back + test ecx, ecx + jz .back - mov ecx, [rdy_head+ebx*4] - mov [eax+.next_ready], ecx - mov [rdy_head+ebx*4], eax - jmp .pick + mov ecx, [rdy_head+ebx*4] + mov [eax+.next_ready], ecx + mov [rdy_head+ebx*4], eax + jmp .pick .back: - mov ecx, [rdy_tail+ebx*4] - mov [ecx+.next_ready], eax - mov [rdy_tail+ebx*4], eax - mov [eax+.next_ready], 0 + mov ecx, [rdy_tail+ebx*4] + mov [ecx+.next_ready], eax + mov [rdy_tail+ebx*4], eax + mov [eax+.next_ready], 0 .pick: - call pick_proc ;select next task - ret + call pick_proc ;select next task + ret end if diff --git a/kernel/trunk/data32.inc b/kernel/trunk/data32.inc index 541b19007c..bc45e1221c 100644 --- a/kernel/trunk/data32.inc +++ b/kernel/trunk/data32.inc @@ -90,7 +90,7 @@ szHwMouse db 'ATI2D',0 szPS2MDriver db 'PS2MOUSE',0 szCOM_MDriver db 'COM_MOUSE',0 szUSB db 'USB',0 -szAtiHW db '/rd/1/drivers/ati2d.drv',0 +szAtiHW db '/rd/1/drivers/ati2d.drv',0 szSTART db 'START',0 szEXPORTS db 'EXPORTS',0 diff --git a/kernel/trunk/network/eth_drv/drivers/rtl8169.inc b/kernel/trunk/network/eth_drv/drivers/rtl8169.inc index 31e7ba1925..498fd15459 100644 --- a/kernel/trunk/network/eth_drv/drivers/rtl8169.inc +++ b/kernel/trunk/network/eth_drv/drivers/rtl8169.inc @@ -524,20 +524,20 @@ endp ; Also adjust PCI latency timer to a reasonable value, 32. proc adjust_pci_device - DEBUGF 1,"K : adjust_pci_device\n" +; DEBUGF 1,"K : adjust_pci_device\n" stdcall pci_read_config_word,PCI_COMMAND mov bx,ax or bx,PCI_COMMAND_MASTER or PCI_COMMAND_IO cmp ax,bx je @f - DEBUGF 1,"K : adjust_pci_device: The PCI BIOS has not enabled this device!\nK : Updating PCI command %x->%x. pci_bus %x pci_device_fn %x\n",ax,bx,[pci_bus]:2,[pci_dev]:2 +; DEBUGF 1,"K : adjust_pci_device: The PCI BIOS has not enabled this device!\nK : Updating PCI command %x->%x. pci_bus %x pci_device_fn %x\n",ax,bx,[pci_bus]:2,[pci_dev]:2 stdcall pci_write_config_word,PCI_COMMAND,ebx @@: stdcall pci_read_config_byte,PCI_LATENCY_TIMER cmp al,32 jae @f - DEBUGF 1,"K : adjust_pci_device: PCI latency timer (CFLT) is unreasonably low at %d.\nK : Setting to 32 clocks.\n",al +; DEBUGF 1,"K : adjust_pci_device: PCI latency timer (CFLT) is unreasonably low at %d.\nK : Setting to 32 clocks.\n",al stdcall pci_write_config_byte,PCI_LATENCY_TIMER,32 @@: ret @@ -559,7 +559,7 @@ proc pci_bar_start,index:dword stdcall pci_read_config_dword,eax or eax,eax jz .not64 - DEBUGF 1,"K : pci_bar_start: Unhandled 64bit BAR\n" +; DEBUGF 1,"K : pci_bar_start: Unhandled 64bit BAR\n" add esp,4 or eax,-1 ret @@ -572,7 +572,7 @@ endp proc rtl8169_init_board - DEBUGF 1,"K : rtl8169_init_board\n" +; DEBUGF 1,"K : rtl8169_init_board\n" call adjust_pci_device @@ -592,7 +592,7 @@ proc rtl8169_init_board ; identify config method RTL_R32 RTL8169_REG_TxConfig and eax,0x7c800000 - DEBUGF 1,"K : rtl8169_init_board: TxConfig & 0x7c800000 = 0x%x\n",eax +; DEBUGF 1,"K : rtl8169_init_board: TxConfig & 0x7c800000 = 0x%x\n",eax mov esi,mac_info-8 @@: add esi,8 mov ecx,eax @@ -625,9 +625,9 @@ proc rtl8169_init_board jmp .match @@: ; if unknown chip, assume array element #0, original RTL-8169 in this case - DEBUGF 1,"K : rtl8169_init_board: PCI device: unknown chip version, assuming RTL-8169\n" +; DEBUGF 1,"K : rtl8169_init_board: PCI device: unknown chip version, assuming RTL-8169\n" RTL_R32 RTL8169_REG_TxConfig - DEBUGF 1,"K : rtl8169_init_board: PCI device: TxConfig = 0x%x\n",eax +; DEBUGF 1,"K : rtl8169_init_board: PCI device: TxConfig = 0x%x\n",eax mov [rtl8169_tpc.chipset],0 @@ -642,7 +642,7 @@ endp proc rtl8169_hw_PHY_config - DEBUGF 1,"K : rtl8169_hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[rtl8169_tpc.mcfg],[rtl8169_tpc.pcfg] +; DEBUGF 1,"K : rtl8169_hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[rtl8169_tpc.mcfg],[rtl8169_tpc.pcfg] ; DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n", tpc->mcfg, tpc->pcfg); @@ -705,7 +705,7 @@ proc rtl8169_hw_PHY_config jmp .exit .not_2_or_3: ; DBG_PRINT("tpc->mcfg=%d. Discard hw PHY config.\n", tpc->mcfg); - DEBUGF 1,"K : tpc.mcfg=%d, discard hw PHY config\n",[rtl8169_tpc.mcfg] +; DEBUGF 1,"K : tpc.mcfg=%d, discard hw PHY config\n",[rtl8169_tpc.mcfg] .exit: ret endp @@ -716,7 +716,7 @@ endp proc RTL8169_WRITE_GMII_REG,RegAddr:byte,value:dword -;;; DEBUGF 1,"K : RTL8169_WRITE_GMII_REG: 0x%x 0x%x\n",[RegAddr]:2,[value] +;;; DEBUGF 1,"K : RTL8169_WRITE_GMII_REG: 0x%x 0x%x\n",[RegAddr]:2,[value] movzx eax,[RegAddr] shl eax,16 @@ -738,7 +738,7 @@ endp proc RTL8169_READ_GMII_REG,RegAddr:byte -;;; DEBUGF 1,"K : RTL8169_READ_GMII_REG: 0x%x\n",[RegAddr]:2 +;;; DEBUGF 1,"K : RTL8169_READ_GMII_REG: 0x%x\n",[RegAddr]:2 push ecx movzx eax,[RegAddr] @@ -767,7 +767,7 @@ endp proc rtl8169_set_rx_mode - DEBUGF 1,"K : rtl8169_set_rx_mode\n" +; DEBUGF 1,"K : rtl8169_set_rx_mode\n" ; IFF_ALLMULTI ; Too many to filter perfectly -- accept all multicasts @@ -785,7 +785,7 @@ endp proc rtl8169_init_ring - DEBUGF 1,"K : rtl8169_init_ring\n" +; DEBUGF 1,"K : rtl8169_init_ring\n" xor eax,eax mov [rtl8169_tpc.cur_rx],eax @@ -834,7 +834,7 @@ endp proc rtl8169_hw_start - DEBUGF 1,"K : rtl8169_hw_start\n" +; DEBUGF 1,"K : rtl8169_hw_start\n" ; Soft reset the chip RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset @@ -883,10 +883,10 @@ proc rtl8169_hw_start push eax ; shurf 28.09.2008 mov eax, [rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 sub eax, OS_BASE ; shurf 28.09.2008 - RTL_W32 RTL8169_REG_TxDescStartAddr,eax ;[rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 + RTL_W32 RTL8169_REG_TxDescStartAddr,eax ;[rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 mov eax, [rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 sub eax, OS_BASE ; shurf 28.09.2008 - RTL_W32 RTL8169_REG_RxDescStartAddr,eax ;[rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 + RTL_W32 RTL8169_REG_RxDescStartAddr,eax ;[rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 pop eax ; shurf 28.09.2008 RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Lock stdcall udelay,10 @@ -920,7 +920,7 @@ endp ;*************************************************************************** proc rtl8169_probe - DEBUGF 1,"K : rtl8169_probe: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 +; DEBUGF 1,"K : rtl8169_probe: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 call rtl8169_init_board @@ -935,7 +935,7 @@ proc rtl8169_probe inc ebx loop @b - DEBUGF 1,"K : rtl8169_probe: MAC = %x-%x-%x-%x-%x-%x\n",[node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2 +; DEBUGF 1,"K : rtl8169_probe: MAC = %x-%x-%x-%x-%x-%x\n",[node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2 ; Config PHY stdcall rtl8169_hw_PHY_config @@ -995,7 +995,7 @@ endp ;*************************************************************************** proc rtl8169_reset - DEBUGF 1,"K : rtl8169_reset: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 +; DEBUGF 1,"K : rtl8169_reset: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 mov [rtl8169_tpc.TxDescArrays],rtl8169_tx_ring ; Tx Desscriptor needs 256 bytes alignment @@ -1040,7 +1040,7 @@ endp ;*************************************************************************** proc rtl8169_transmit - DEBUGF 1,"K : rtl8169_transmit\n" ;: 0x%x : 0x%x 0x%x 0x%x 0x%x\n",[io_addr]:8,edi,bx,ecx,esi +; DEBUGF 1,"K : rtl8169_transmit\n" ;: 0x%x : 0x%x 0x%x 0x%x 0x%x\n",[io_addr]:8,edi,bx,ecx,esi push ecx edx esi mov eax,MAX_ETH_FRAME_SIZE @@ -1094,7 +1094,7 @@ proc rtl8169_transmit add eax,[rtl8169_tpc.TxDescArray] xchg eax,ebx mov [ebx + rtl8169_TxDesc.buf_addr],eax - sub [ebx + rtl8169_TxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 + sub [ebx + rtl8169_TxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 mov eax,ecx cmp eax,ETH_ZLEN @@ -1118,7 +1118,7 @@ proc rtl8169_transmit jnz @f stdcall udelay,10 loop @b - DEBUGF 1,"K : rtl8169_transmit: TX Time Out\n" +; DEBUGF 1,"K : rtl8169_transmit: TX Time Out\n" @@: ret @@ -1176,7 +1176,7 @@ proc rtl8169_poll add eax,-4 mov [eth_rx_data_len],ax - DEBUGF 1,"K : rtl8169_poll: data length = %u\n",ax +; DEBUGF 1,"K : rtl8169_poll: data length = %u\n",ax push eax mov ecx,eax @@ -1198,10 +1198,10 @@ proc rtl8169_poll @@: mov [ebx + rtl8169_RxDesc.status],eax mov [ebx + rtl8169_RxDesc.buf_addr],edx - sub [ebx + rtl8169_RxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 + sub [ebx + rtl8169_RxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 jmp @f .else: - DEBUGF 1,"K : rtl8169_poll: Rx Error\n" +; DEBUGF 1,"K : rtl8169_poll: Rx Error\n" ; FIXME: shouldn't I reset the status on an error @@: inc [rtl8169_tpc.cur_rx] diff --git a/kernel/trunk/network/eth_drv/ethernet.inc b/kernel/trunk/network/eth_drv/ethernet.inc index c9bd81d5dd..74df50176d 100644 --- a/kernel/trunk/network/eth_drv/ethernet.inc +++ b/kernel/trunk/network/eth_drv/ethernet.inc @@ -204,7 +204,7 @@ dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 dd 0x006610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; nVidia Corporation nForce2 Ethernet Controller dd 0x01c310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x00D610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x00D610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested dd 0x008610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested dd 0x008c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested dd 0x00e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested @@ -353,6 +353,9 @@ endp ; All registers may be destroyed ; ;*************************************************************************** +uglobal + ether_IP_handler_cnt dd ? +endg ether_IP_handler: mov eax, EMPTY_QUEUE call dequeue @@ -376,6 +379,9 @@ ether_IP_handler: cld rep movsd +; inc [ether_IP_handler_cnt] +; DEBUGF 1, "K : ether_IP_handler (%u)\n", [ether_IP_handler_cnt] + ; And finally, place the buffer in the IPRX queue pop ebx mov eax, IPIN_QUEUE @@ -462,16 +468,18 @@ eth_rx: cmp ax, ETHER_ARP je .is_arp ; It is ARP + DEBUGF 1,"K : eth_rx - dumped (%u)\n", ax + inc [dumped_rx_count] jmp .exit ; If not IP or ARP, ignore .is_ip: - DEBUGF 1,"K : eth_rx - IP packet\n" +; DEBUGF 1,"K : eth_rx - IP packet\n" inc dword [ip_rx_count] call ether_IP_handler jmp .exit .is_arp: - DEBUGF 1,"K : eth_rx - ARP packet\n" +; DEBUGF 1,"K : eth_rx - ARP packet\n" ; At this point, the packet is still in the Ether_buffer call arp_handler diff --git a/kernel/trunk/network/ip.inc b/kernel/trunk/network/ip.inc index a57e082bc0..4796d532e8 100644 --- a/kernel/trunk/network/ip.inc +++ b/kernel/trunk/network/ip.inc @@ -16,22 +16,22 @@ $Revision$ ; IP underlying protocols numbers -PROTOCOL_ICMP equ 1 -PROTOCOL_TCP equ 6 -PROTOCOL_UDP equ 17 +PROTOCOL_ICMP equ 1 +PROTOCOL_TCP equ 6 +PROTOCOL_UDP equ 17 struc IP_PACKET -{ .VersionAndIHL db ? ;+00 - Version[0-3 bits] and IHL(header length)[4-7 bits] - .TypeOfService db ? ;+01 - .TotalLength dw ? ;+02 - .Identification dw ? ;+04 - .FlagsAndFragmentOffset dw ? ;+06 - Flags[0-2] and FragmentOffset[3-15] - .TimeToLive db ? ;+08 - .Protocol db ? ;+09 - .HeaderChecksum dw ? ;+10 - .SourceAddress dd ? ;+12 - .DestinationAddress dd ? ;+16 - .DataOrOptional dd ? ;+20 +{ .VersionAndIHL db ? ;+00 - Version[0-3 bits] and IHL(header length)[4-7 bits] + .TypeOfService db ? ;+01 + .TotalLength dw ? ;+02 + .Identification dw ? ;+04 + .FlagsAndFragmentOffset dw ? ;+06 - Flags[0-2] and FragmentOffset[3-15] + .TimeToLive db ? ;+08 + .Protocol db ? ;+09 + .HeaderChecksum dw ? ;+10 + .SourceAddress dd ? ;+12 + .DestinationAddress dd ? ;+16 + .DataOrOptional dd ? ;+20 } virtual at 0 @@ -83,10 +83,14 @@ macro GET_IHL reg, header_addr and reg, 0x0000000F ; IHL keeps number of octets, so we need to << 2 'reg' - shl reg, 2 + shl reg, 2 } +include "tcp.inc" +include "udp.inc" +include "icmp.inc" + ;*************************************************************************** ; Function ; ip_rx @@ -104,7 +108,7 @@ local buffer_number dd ? mov eax, IPIN_QUEUE call dequeue cmp ax, NO_BUFFER - je .exit ; Exit if no buffer available + je .exit ; Exit if no buffer available mov [buffer_number], eax ;save buffer number @@ -114,12 +118,14 @@ local buffer_number dd ? mov ebx, eax ; ebx=pointer to IP_PACKET +; DEBUGF 1, "K : ip_rx - proto: %u\n", [ebx + IP_PACKET.Protocol]:1 + ; Validate the IP checksum mov dx, word[ebx + IP_PACKET.HeaderChecksum] - xchg dh,dl ; Get the checksum in intel format + xchg dh,dl ; Get the checksum in intel format - mov [ebx + IP_PACKET.HeaderChecksum], word 0 ; clear checksum field - need to when - ; recalculating checksum + mov [ebx + IP_PACKET.HeaderChecksum], 0 ; clear checksum field - need to when + ; recalculating checksum ; this needs two data pointers and two size #. ; 2nd pointer can be of length 0 @@ -127,32 +133,51 @@ local buffer_number dd ? stdcall checksum_jb, ebx, ecx ;buf_ptr, buf_size cmp dx, ax +; DEBUGF 1, "K : ip_rx - checksums: %x - %x\n", dx, ax + + jnz .dump.1 ;if CHECKSUM isn't valid then dump packet mov edx, ebx ; EDX (IP-BUFFER POINTER) WILL BE USED FOR *_rx HANDLERS BELOW!!! - jnz .dump ;if CHECKSUM isn't valid then dump packet + +; DEBUGF 1, "K : ip_rx - dest: %x - %x\n", [ebx + IP_PACKET.DestinationAddress], [stack_ip] ; Validate the IP address, if it isn't broadcast mov eax, [stack_ip] cmp dword[ebx + IP_PACKET.DestinationAddress], eax - je @f + je @f ; If the IP address is 255.255.255.255, accept it ; - it is a broadcast packet, which we need for dhcp - cmp dword[ebx + IP_PACKET.DestinationAddress], 0xffffffff - jne .dump + + mov eax, [ebx + IP_PACKET.DestinationAddress] + cmp eax, 0xffffffff + ;je @f + ;mov ecx, [stack_ip] + ;and eax, [subnet_mask] + ;and ecx, [subnet_mask] + ;cmp eax, ecx + ;jne .dump.2 + ;mov eax, [ebx + IP_PACKET.DestinationAddress] + ;or eax, [subnet_mask] + ;cmp eax, 0xffffffff + jne .dump.2 @@: mov al, [ebx + IP_PACKET.VersionAndIHL] and al, 0x0f ;get IHL(header length) cmp al, 0x05 ;if IHL!= 5*4(20 bytes) - jnz .dump ;then dump it +; DEBUGF 1, "K : ip_rx - ihl: %x - 05\n", al + jnz .dump.3 ;then dump it - cmp byte[ebx + IP_PACKET.TimeToLive], byte 0 - je .dump ;if TTL==0 then dump it +; DEBUGF 1, "K : ip_rx - ttl: %x - 00\n", [ebx + IP_PACKET.TimeToLive]:2 - mov ax, word[ebx + IP_PACKET.FlagsAndFragmentOffset] - and ax, 0xFFBF ;get flags - cmp ax, 0 ;if some flags was set then we dump this packet - jnz .dump ;the flags should be used for fragmented packets + cmp [ebx + IP_PACKET.TimeToLive], 0 + je .dump.4 ;if TTL==0 then dump it + + mov ax, [ebx + IP_PACKET.FlagsAndFragmentOffset] + and ax, 0xFFBF ;get flags +; DEBUGF 1, "K : ip_rx - flags: %x - 0000\n", ax + cmp ax, 0 ;if some flags was set then we dump this packet + jnz .dump.5 ;the flags should be used for fragmented packets ; Check the protocol, and call the appropriate handler ; Each handler will re-use or free the queue buffer as appropriate @@ -161,7 +186,7 @@ local buffer_number dd ? cmp al , PROTOCOL_TCP jne .not_tcp - DEBUGF 1,"K : ip_rx - TCP packet\n" +; DEBUGF 1,"K : ip_rx - TCP packet\n" mov eax, dword[buffer_number] call tcp_rx jmp .exit @@ -169,29 +194,48 @@ local buffer_number dd ? .not_tcp: cmp al, PROTOCOL_UDP jne .not_udp - DEBUGF 1,"K : ip_rx - UDP packet\n" +; DEBUGF 1,"K : ip_rx - UDP packet\n" mov eax, dword[buffer_number] call udp_rx jmp .exit .not_udp: - cmp al , PROTOCOL_ICMP - jne .dump ;protocol ain't supported + cmp al, PROTOCOL_ICMP + jne .dump.6 ;protocol ain't supported - DEBUGF 1,"K : ip_rx - ICMP packet\n" +; DEBUGF 1,"K : ip_rx - ICMP packet\n" ;GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx mov eax, dword[buffer_number] stdcall icmp_rx,eax,ebx,ecx ;buffer_number,IPPacketBase,IPHeaderLength jmp .exit -.dump: - ; No protocol handler available, so - ; silently dump the packet, freeing up the queue buffer + .dump.1: + DEBUGF 1, "K : ip_rx - dumped (checksum: 0x%x-0x%x)\n", dx, ax + jmp .dump.x - inc dword [dumped_rx_count] + .dump.2: + DEBUGF 1, "K : ip_rx - dumped (ip: %u.%u.%u.%u)\n", [ebx + IP_PACKET.DestinationAddress + 0]:1, [ebx + IP_PACKET.DestinationAddress + 1]:1, [ebx + IP_PACKET.DestinationAddress + 2]:1, [ebx + IP_PACKET.DestinationAddress + 3]:1 + jmp .dump.x - mov eax, dword[buffer_number] + .dump.3: + DEBUGF 1, "K : ip_rx - dumped (ihl: %u)\n", al + jmp .dump.x + + .dump.4: + DEBUGF 1, "K : ip_rx - dumped (ihl: %u)\n", [ebx + IP_PACKET.TimeToLive] + jmp .dump.x + + .dump.5: + DEBUGF 1, "K : ip_rx - dumped (flags: 0x%x)\n", ax + jmp .dump.x + + .dump.6: + DEBUGF 1, "K : ip_rx - dumped (proto: %u)\n", [ebx + IP_PACKET.Protocol]:1 + + .dump.x: + inc dword[dumped_rx_count] + mov eax, [buffer_number] call freeBuff .exit: diff --git a/kernel/trunk/network/queue.inc b/kernel/trunk/network/queue.inc index 15b458f1a1..5e79761ee6 100644 --- a/kernel/trunk/network/queue.inc +++ b/kernel/trunk/network/queue.inc @@ -43,18 +43,19 @@ $Revision$ ; all other registers preserved ; This always works, so no error returned ;*************************************************************************** +uglobal + freeBuff_cnt dd ? +endg freeBuff: +; inc [freeBuff_cnt] +; DEBUGF 1, "K : freeBuff (%u)\n", [freeBuff_cnt] push ebx push ecx - mov ebx, EMPTY_QUEUE - shl ebx, 1 - add ebx, queues + mov ebx, queues + EMPTY_QUEUE * 2 cli ; Ensure that another process does not interfer - movzx ecx, word [ebx] + mov cx, [ebx] mov [ebx], ax - shl eax, 1 - add eax, queueList - mov [eax], cx + mov [queueList + eax * 2], cx sti pop ecx pop ebx @@ -78,7 +79,7 @@ queueSize: add ebx, queues movzx ecx, word [ebx] cmp cx, NO_BUFFER - je qs_exit + je qs_exit qs_001: inc eax @@ -86,7 +87,7 @@ qs_001: add ecx, queueList movzx ecx, word [ecx] cmp cx, NO_BUFFER - je qs_exit + je qs_exit jmp qs_001 qs_exit: @@ -105,15 +106,20 @@ qs_exit: ; all other registers preserved ; This always works, so no error returned ;*************************************************************************** +uglobal + queue_cnt dd ? +endg queue: +; inc [queue_cnt] +; DEBUGF 1, "K : queue (%u)\n", [queue_cnt] push ebx shl ebx, 1 - add ebx, queueList ; eax now holds address of queue entry + add ebx, queueList ; eax now holds address of queue entry mov [ebx], word NO_BUFFER ; This buffer will be the last cli shl eax, 1 - add eax, queues ; eax now holds address of queue + add eax, queues ; eax now holds address of queue movzx ebx, word [eax] cmp bx, NO_BUFFER @@ -155,18 +161,23 @@ qu_exit: ; all other registers preserved ; ;*************************************************************************** +uglobal + dequeue_cnt dd ? +endg dequeue: push ebx shl eax, 1 - add eax, queues ; eax now holds address of queue + add eax, queues ; eax now holds address of queue mov ebx, eax cli movzx eax, word [eax] cmp ax, NO_BUFFER - je dq_exit + je dq_exit +; inc [dequeue_cnt] +; DEBUGF 1, "K : dequeue (%u)\n", [dequeue_cnt] push eax shl eax, 1 - add eax, queueList ; eax now holds address of queue entry + add eax, queueList ; eax now holds address of queue entry mov ax, [eax] mov [ebx], ax pop eax diff --git a/kernel/trunk/network/socket.inc b/kernel/trunk/network/socket.inc index 9d197ddf99..093f069a5b 100644 --- a/kernel/trunk/network/socket.inc +++ b/kernel/trunk/network/socket.inc @@ -77,21 +77,21 @@ $Revision$ ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; 72| Retransmit queue # NOW WINDOW SIZE TIMER INTEL format| ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; 76| RX offset from -; 76| RX Data | +; 76| RX Data Buffer | ; +-+-+-.......... -+ ; so, define struct struc SOCKET -{ .Status dd ? ;+00 - Status ( of this buffer ) +{ + .Status dd ? ;+00 - Status ( of this buffer ) .PID dd ? ;+04 - Application Process ID - .LocalIP dd ? ;+08 - Local IP Address + .LocalIP dd ? ;+08 - Local IP Address .LocalPort dw ? ;+12 - Local Port - .UnusedL dw ? ;+14 - may be removed in future .RemoteIP dd ? ;+16 - Remote IP Address .RemotePort dw ? ;+20 - Remote Port - .UnusedR dw ? ;+22 - may be removed in future + .OrigRemoteIP dd ? + .OrigRemotePort dw ? .rxDataCount dd ? ;+24 - Rx Data Count .TCBState dd ? ;+28 - TCB STATE .TCBTimer dd ? ;+32 - TCB Timer (seconds) @@ -105,6 +105,8 @@ struc SOCKET .SEG_LEN dd ? ;+64 - Segment length .SEG_WND dd ? ;+68 - Segment window .wndsizeTimer dd ? ;+72 - Retransmit queue # NOW WINDOW SIZE TIMER + .PrevPtr dd ? + .NextPtr dd ? .rxData dd ? ;+76 - receive data buffer here } @@ -113,21 +115,128 @@ virtual at 0 end virtual ; simple macro calcing real memory address of SOCKET struct by socket's -macro Index2RealAddr reg -{ - shl reg, 12 - add reg, sockets -} +;macro Index2RealAddr reg +;{ +; shl reg, 12 +; add reg, sockets +;} ;Constants ; current socket statuses -SOCK_EMPTY equ 0 ; socket not in use -SOCK_OPEN equ 1 ; open issued, but no data sent +SOCK_EMPTY = 0 ; socket not in use +SOCK_OPEN = 1 ; open issued, but no data sent ; TCP opening modes SOCKET_PASSIVE equ 0 SOCKET_ACTIVE equ 1 +proc net_socket_alloc stdcall uses ebx ecx edx edi + stdcall kernel_alloc, SOCKETBUFFSIZE + DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax + or eax, eax + jz .exit + + push eax + mov edi, eax + mov ecx, SOCKETBUFFSIZE / 4 + cld + xor eax, eax + rep stosd + pop eax + + mov ebx, net_sockets + push [ebx + SOCKET.NextPtr] + mov [ebx + SOCKET.NextPtr], eax + mov [eax + SOCKET.PrevPtr], ebx + pop ebx + mov [eax + SOCKET.NextPtr], ebx + or ebx, ebx + jz @f + mov [ebx + SOCKET.PrevPtr], eax + + @@: mov ebx, [TASK_BASE] + mov ebx, [ebx + TASKDATA.pid] + mov [eax + SOCKET.PID], ebx + + .exit: + ret +endp + +proc net_socket_free stdcall uses ebx ecx edx, sock:DWORD + mov eax, [sock] + DEBUGF 1, "K : net_socket_free (0x%x)\n", eax + or eax, eax + jz .error + + mov ebx, net_sockets + mov ecx, [TASK_BASE] + mov ecx, [ecx + TASKDATA.pid] + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .error + cmp ebx, eax + jne .next_socket + ;cmp [ebx + SOCKET.PID], ecx + ;jne .next_socket + + mov ebx, [eax + SOCKET.NextPtr] + mov eax, [eax + SOCKET.PrevPtr] + mov [eax + SOCKET.NextPtr], ebx + or ebx, ebx + jz @f + mov [ebx + SOCKET.PrevPtr], eax + + @@: stdcall kernel_free, [sock] + ret + + .error: + DEBUGF 1, "K : failed\n" + ret +endp + +proc net_socket_num_to_addr stdcall uses ebx ecx, x:DWORD +; FIXME: do real transform + mov eax, [x] + mov ebx, net_sockets + mov ecx, [TASK_BASE] + mov ecx, [ecx + TASKDATA.pid] + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .error + cmp ebx, eax + jne .next_socket + ;cmp [ebx + SOCKET.PID], ecx + ;jne .next_socket + ret + + .error: + xor eax, eax + ret +endp + +proc net_socket_addr_to_num stdcall uses ebx ecx, x:DWORD +; FIXME: do real transform + mov eax, [x] + mov ebx, net_sockets + mov ecx, [TASK_BASE] + mov ecx, [ecx + TASKDATA.pid] + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .error + cmp ebx, eax + jne .next_socket + ;cmp [ebx + SOCKET.PID], ecx + ;jne .next_socket + ret + + .error: + xor eax, eax + ret +endp + ;*************************************************************************** ; Function ; is_localport_unused @@ -140,51 +249,26 @@ SOCKET_ACTIVE equ 1 ; On return, eax = 1 for free, 0 for in use ; ;*************************************************************************** -is_localport_unused: - mov al, bh - mov ah, bl - mov bx, ax +proc is_localport_unused stdcall - mov edx, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS - mov eax, 0 ; Assume the return value is 'in use' + xchg bl, bh -ilu1: - sub edx, SOCKETBUFFSIZE - cmp [edx + sockets + SOCKET.LocalPort], bx - loopnz ilu1 ; Return back if the socket is occupied + xor eax, eax ; Assume the return value is 'free' + inc al + mov edx, net_sockets - jz ilu_exit - inc eax ; return port not in use + .next_socket: + mov edx, [edx + SOCKET.NextPtr] + or edx, edx + jz .exit + cmp [edx + SOCKET.LocalPort], bx + jne .next_socket ; Return back if the port is not occupied -ilu_exit: - ret + dec al ; return 'in use' - - -;*************************************************************************** -; Function -; get_free_socket -; -; Description -; -;*************************************************************************** -get_free_socket: - push ecx - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS - -gfs1: - sub eax, SOCKETBUFFSIZE - cmp [eax + sockets + SOCKET.Status], dword SOCK_EMPTY - loopnz gfs1 ; Return back if the socket is occupied - mov eax, ecx - pop ecx - jz gfs_exit - mov eax, 0xFFFFFFFF - -gfs_exit: - ret + .exit: + ret +endp ;*************************************************************************** @@ -199,36 +283,33 @@ gfs_exit: ; return socket # in eax, -1 if none available ; ;*************************************************************************** -socket_open: - call get_free_socket +proc socket_open stdcall + call net_socket_alloc + or eax, eax + jz .error - cmp eax, 0xFFFFFFFF - jz so_exit + DEBUGF 1, "K : socket_open (0x%x)\n", eax - ; ax holds the socket number that is free. Get real address - push eax - Index2RealAddr eax + push eax - mov [eax + SOCKET.Status], dword SOCK_OPEN + mov [eax + SOCKET.Status], SOCK_OPEN + xchg bh, bl + mov [eax + SOCKET.LocalPort], bx + xchg ch, cl + mov [eax + SOCKET.RemotePort], cx + mov ebx, [stack_ip] + mov [eax + SOCKET.LocalIP], ebx + mov [eax + SOCKET.RemoteIP], edx - xchg bh, bl - mov [eax + SOCKET.LocalPort], bx - xchg ch, cl - mov [eax + SOCKET.RemotePort], cx - - mov ebx, [stack_ip] - mov [eax + SOCKET.LocalIP], ebx - mov [eax + SOCKET.RemoteIP], edx - mov [eax + SOCKET.rxDataCount], dword 0 ; recieved data count - - mov esi, [TASK_BASE] - mov ebx, [esi+TASKDATA.pid] - mov [eax + SOCKET.PID], ebx ; save the process ID - pop eax ; Get the socket number back, so we can return it - -so_exit: - ret + ;pop eax ; Get the socket number back, so we can return it + stdcall net_socket_addr_to_num + ret + .error: + DEBUGF 1, "K : socket_open (fail)\n" + or eax, -1 + ret +endp ;*************************************************************************** @@ -245,92 +326,108 @@ so_exit: ; return socket # in eax, -1 if none available ; ;*************************************************************************** -socket_open_tcp: - call get_free_socket +proc socket_open_tcp stdcall +local sockAddr dd ? - cmp eax, 0xFFFFFFFF - jz so_exit + cmp esi, SOCKET_PASSIVE + jne .skip_port_check - ; ax holds the socket number that is free. Get real address - push eax - Index2RealAddr eax + push ebx + mov eax, ebx + xchg al, ah + mov ebx, net_sockets - mov [sktAddr], eax - mov [eax], dword SOCK_OPEN + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .last_socket + cmp [ebx + SOCKET.TCBState], TCB_LISTEN + jne .next_socket + cmp [ebx + SOCKET.LocalPort], ax + jne .next_socket - ; TODO - check this works! - mov [eax + SOCKET.wndsizeTimer], dword 0 ; Reset the window timer. + xchg al, ah + DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx + pop ebx + jmp .error + + .last_socket: + pop ebx + + .skip_port_check: + call net_socket_alloc + or eax, eax + jz .error + + DEBUGF 1, "K : socket_open_tcp (0x%x)\n", eax + + mov [sockAddr], eax + + ; TODO - check this works! + ;xxx: already 0 (intialized by net_socket_alloc) + ;mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer. xchg bh, bl mov [eax + SOCKET.LocalPort], bx -; mov [eax + 12], byte bh ; Local port ( LS 16 bits ) -; mov [eax + 13], byte bl ; Local port ( LS 16 bits ) - xchg ch, cl mov [eax + SOCKET.RemotePort], cx -; mov [eax + 20], ch ; Remote Port ( LS 16 bits ) -; mov [eax + 21], cl ; Remote Port ( LS 16 bits ) + mov [eax + SOCKET.OrigRemotePort], cx + mov ebx, [stack_ip] + mov [eax + SOCKET.LocalIP], ebx + mov [eax + SOCKET.RemoteIP], edx + mov [eax + SOCKET.OrigRemoteIP], edx - mov ebx, [stack_ip] - mov [eax + SOCKET.LocalIP], ebx - mov [eax + SOCKET.RemoteIP], edx - mov [eax + SOCKET.rxDataCount], dword 0 + mov ebx, TCB_LISTEN + cmp esi, SOCKET_PASSIVE + je @f + mov ebx, TCB_SYN_SENT + @@: mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB - ; Now fill in TCB state - mov ebx, TCB_LISTEN - cmp esi, SOCKET_PASSIVE - jz sot_001 - mov ebx, TCB_SYN_SENT + cmp ebx, TCB_LISTEN + je .exit -sot_001: - mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB + ; Now, if we are in active mode, then we have to send a SYN to the specified remote port + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit - mov esi, [TASK_BASE] - mov ecx, [esi+TASKDATA.pid] - mov [eax + SOCKET.PID], ecx ; save the process ID + push eax - cmp ebx, TCB_LISTEN - je sot_done + mov bl, TH_SYN + xor ecx, ecx + stdcall build_tcp_packet, [sockAddr] - ; Now, if we are in active mode, then we have to send a SYN to the specified remote port - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je sot_done + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE - push eax + .not_local: + ; Send it. + pop ebx + call queue - mov bl, 0x02 ; SYN - mov ecx, 0 + mov esi, [sockAddr] - call buildTCPPacket + ; increment SND.NXT in socket + add esi, SOCKET.SND_NXT + call inc_inet_esi - mov eax, NET1OUT_QUEUE - - mov edx, [stack_ip] - mov ecx, [sktAddr ] - mov ecx, [ecx + 16] - cmp edx, ecx - jne sot_notlocal - mov eax, IPIN_QUEUE - -sot_notlocal: - ; Send it. - pop ebx - call queue - - mov esi, [sktAddr] - - ; increment SND.NXT in socket - add esi, 48 - call inc_inet_esi - -sot_done: - pop eax ; Get the socket number back, so we can return it - -sot_exit: - ret + .exit: + mov ebx, [sockAddr] + mov [ebx + SOCKET.Status], SOCK_OPEN + ;pop eax ; Get the socket number back, so we can return it + stdcall net_socket_addr_to_num, ebx + ret + .error: + DEBUGF 1, "K : socket_open_tcp (fail)\n" + or eax, -1 + ret +endp ;*************************************************************************** @@ -342,24 +439,31 @@ sot_exit: ; returns 0 for ok, -1 for socket not open (fail) ; ;*************************************************************************** -socket_close: - mov eax, 0xFFFFFFFF ; assume this operation will fail.. - cmp ebx, NUM_SOCKETS - jae sc_exit - Index2RealAddr ebx - cmp [ebx + SOCKET.Status], dword SOCK_EMPTY - jz sc_exit +proc socket_close stdcall + DEBUGF 1, "K : socket_close (0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error - ; Clear the socket varaibles - xor eax, eax - mov edi, ebx - mov ecx, SOCKETHEADERSIZE - cld - rep stosb + cmp [eax + SOCKET.Status], dword SOCK_EMPTY + jz .error -sc_exit: - ret + ; Clear the socket varaibles + stdcall net_socket_free, eax +; mov edi, eax +; xor eax, eax +; mov ecx, SOCKETHEADERSIZE +; cld +; rep stosb + xor eax, eax + ret + + .error: + DEBUGF 1, "K : socket_close (fail)\n" + or eax, -1 + ret +endp ;*************************************************************************** @@ -371,110 +475,118 @@ sc_exit: ; returns 0 for ok, -1 for socket not open (fail) ; ;*************************************************************************** -socket_close_tcp: - ; first, remove any resend entries - pusha +proc socket_close_tcp stdcall +local sockAddr dd ? + DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx + ; first, remove any resend entries + pusha - mov esi, resendQ - mov ecx, 0 + mov esi, resendQ + mov ecx, 0 -sct001: - cmp ecx, NUMRESENDENTRIES - je sct003 ; None left - cmp [esi], bl - je sct002 ; found one - inc ecx - add esi, 4 - jmp sct001 + .next_resendq: + cmp ecx, NUMRESENDENTRIES + je .last_resendq ; None left + ;cmp [esi], bl ; XTODO: bl -> ebx + cmp [esi + 4], ebx + je @f ; found one + inc ecx + add esi, 8 + jmp .next_resendq -sct002: + ;@@: mov byte[esi], 0xff ; XTODO: 0xff -> 0 + @@: mov dword[esi + 4], 0 + inc ecx + add esi, 8 + jmp .next_resendq - mov [esi], byte 0xFF - jmp sct001 + .last_resendq: + popa -sct003: - popa + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error - Index2RealAddr ebx - mov [sktAddr], ebx - mov eax, 0xFFFFFFFF ; assume this operation will fail.. - cmp [ebx + SOCKET.Status], dword SOCK_EMPTY - jz sct_exit + mov ebx, eax + mov [sockAddr], eax + cmp [ebx + SOCKET.Status], SOCK_EMPTY + je .error - ; Now construct the response, and queue for sending by IP - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je stl_exit + cmp [ebx + SOCKET.TCBState], TCB_LISTEN ;xxx + je .destroy_tcb ;xxx + cmp [ebx + SOCKET.TCBState], TCB_SYN_SENT ;xxx + je .destroy_tcb ;xxx - push eax + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .error - mov bl, 0x11 ; FIN + ACK - mov ecx, 0 - mov esi, 0 + push eax - call buildTCPPacket +;xxx mov bl, TH_FIN + TH_ACK + mov bl, TH_FIN ;xxx + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] - mov ebx, [sktAddr] + mov ebx, [sockAddr] + ; increament SND.NXT in socket + lea esi, [ebx + SOCKET.SND_NXT] + call inc_inet_esi - ; increament SND.NXT in socket - mov esi, 48 - add esi, ebx - call inc_inet_esi + ; Get the socket state + mov eax, [ebx + SOCKET.TCBState] +;xxx cmp eax, TCB_LISTEN +;xxx je .destroy_tcb +;xxx cmp eax, TCB_SYN_SENT +;xxx je .destroy_tcb + cmp eax, TCB_SYN_RECEIVED + je .fin_wait_1 + cmp eax, TCB_ESTABLISHED + je .fin_wait_1 + ; assume CLOSE WAIT + ; Send a fin, then enter last-ack state + ; TODO: check if it's really a TCB_CLOSE_WAIT + mov [ebx + SOCKET.TCBState], TCB_LAST_ACK + jmp .send - ; Get the socket state - mov eax, [ebx + SOCKET.TCBState] - cmp eax, TCB_LISTEN - je destroyTCB - cmp eax, TCB_SYN_SENT - je destroyTCB - cmp eax, TCB_SYN_RECEIVED - je sct_finwait1 - cmp eax, TCB_ESTABLISHED - je sct_finwait1 + .fin_wait_1: + ; Send a fin, then enter finwait2 state + mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1 - ; assume CLOSE WAIT - ; Send a fin, then enter last-ack state - mov eax, TCB_LAST_ACK - mov [ebx + SOCKET.TCBState], eax - xor eax, eax - jmp sct_send + .send: + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE -sct_finwait1: - ; Send a fin, then enter finwait2 state - mov eax, TCB_FIN_WAIT_1 - mov [ebx + SOCKET.TCBState], eax - xor eax, eax + .not_local: + ; Send it. + pop ebx + call queue + jmp .exit -sct_send: - mov eax, NET1OUT_QUEUE + .destroy_tcb: +;xxx pop eax - mov edx, [stack_ip] - mov ecx, [sktAddr ] - mov ecx, [ecx + 16] - cmp edx, ecx - jne sct_notlocal - mov eax, IPIN_QUEUE + ; Clear the socket variables +;xxx stdcall net_socket_free, [sockAddr] + stdcall net_socket_free, ebx -sct_notlocal: - ; Send it. - pop ebx - call queue - jmp sct_exit - -destroyTCB: - pop eax - ; Clear the socket varaibles - xor eax, eax - mov edi, ebx - mov ecx, SOCKETHEADERSIZE - cld - rep stosb - -sct_exit: - ret + .exit: + xor eax, eax + ret + .error: + DEBUGF 1, "K : socket_close_tcp (fail)\n" + or eax, -1 + ret +endp ;*************************************************************************** @@ -486,12 +598,20 @@ sct_exit: ; returns count in eax. ; ;*************************************************************************** -socket_poll: - Index2RealAddr ebx - mov eax, [ebx + SOCKET.rxDataCount] +proc socket_poll stdcall +; DEBUGF 1, "socket_poll(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error - ret + mov eax, [eax + SOCKET.rxDataCount] + ret + .error: + ;or eax, -1 + xor eax, eax + ret +endp ;*************************************************************************** @@ -503,12 +623,25 @@ socket_poll: ; returns TCB state in eax. ; ;*************************************************************************** -socket_status: - Index2RealAddr ebx - mov eax, [ebx + SOCKET.TCBState] +proc socket_status stdcall +;; DEBUGF 1, "socket_status(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error - ret + mov eax, [eax + SOCKET.TCBState] + ret + .error: + ;or eax, -1 + xor eax, eax + ret +endp + +; Index2RealAddr ebx +; mov eax, [ebx + SOCKET.TCBState] +; +; ret ;*************************************************************************** @@ -520,35 +653,40 @@ socket_status: ; returns # of bytes remaining in eax, data in bl ; ;*************************************************************************** -socket_read: - Index2RealAddr ebx - mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes - mov ecx, 1 - test eax, eax - jz sr2 +proc socket_read stdcall +; DEBUGF 1, "socket_read(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error - dec eax - mov esi, ebx ; esi is address of socket - mov [ebx + SOCKET.rxDataCount], eax ; store new count - ;movzx ebx, byte [ebx + SOCKET.rxData] ; get the byte - movzx ebx, byte [ebx + SOCKETHEADERSIZE] ; get the byte - add esi, SOCKETHEADERSIZE - mov edi, esi - inc esi + mov ebx, eax + mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes + test eax, eax + jz .error - mov ecx, (SOCKETBUFFSIZE - SOCKETHEADERSIZE) / 4 - cld - rep movsd - xor ecx, ecx + dec eax + mov esi, ebx ; esi is address of socket + mov [ebx + SOCKET.rxDataCount], eax ; store new count + ;movzx ebx, byte[ebx + SOCKET.rxData] ; get the byte + movzx ebx, byte[ebx + SOCKETHEADERSIZE] ; get the byte + add esi, SOCKETHEADERSIZE + mov edi, esi + inc esi -sr1: - jmp sor_exit + mov ecx, (SOCKETBUFFSIZE - SOCKETHEADERSIZE) / 4 + lea edi, [ebx + SOCKETHEADERSIZE] + lea esi, [edi + 1] + cld + rep movsd -sr2: - xor bl, bl + ret -sor_exit: - ret + .error: + ;or eax, -1 + xor eax, eax + xor ebx, ebx + ret +endp ;*************************************************************************** @@ -562,61 +700,69 @@ sor_exit: ; returns # of bytes copied in eax ; ;*************************************************************************** -socket_read_packet: - Index2RealAddr ebx ; get real socket address - mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes - test eax, eax ; if count of bytes is zero.. - jz .exit ; exit function (eax will be zero) +proc socket_read_packet stdcall +; DEBUGF 1, "socket_read_packet(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx ; get real socket address + or eax, eax + jz .error - test edx, edx ; if buffer size is zero, copy all data - jz .copyallbytes - cmp edx, eax ; if buffer size is larger then the bytes of data, copy all data - jge .copyallbytes + mov ebx, eax + mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes + test eax, eax ; if count of bytes is zero.. + jz .exit ; exit function (eax will be zero) - sub eax, edx ; store new count (data bytes in buffer - bytes we're about to copy) - mov [ebx + SOCKET.rxDataCount], eax ; - push eax - mov eax, edx ; number of bytes we want to copy must be in eax - call .startcopy ; copy to the application + test edx, edx ; if buffer size is zero, copy all data + jz .copy_all_bytes + cmp edx, eax ; if buffer size is larger then the bytes of data, copy all data + jge .copy_all_bytes - mov esi, ebx ; now we're going to copy the remaining bytes to the beginning - add esi, SOCKETHEADERSIZE ; we dont need to copy the header - mov edi, esi ; edi is where we're going to copy to - add esi, edx ; esi is from where we copy - pop ecx ; count of bytes we have left - push ecx ; push it again so we can re-use it later - shr ecx, 2 ; divide eax by 4 - cld - rep movsd ; copy all full dwords - pop ecx - and ecx, 3 - rep movsb ; copy remaining bytes + sub eax, edx ; store new count (data bytes in buffer - bytes we're about to copy) + mov [ebx + SOCKET.rxDataCount], eax ; + push eax + mov eax, edx ; number of bytes we want to copy must be in eax + call .start_copy ; copy to the application - ret ; at last, exit + mov esi, ebx ; now we're going to copy the remaining bytes to the beginning + add esi, SOCKETHEADERSIZE ; we dont need to copy the header + mov edi, esi ; edi is where we're going to copy to + add esi, edx ; esi is from where we copy + pop ecx ; count of bytes we have left + push ecx ; push it again so we can re-use it later + shr ecx, 2 ; divide eax by 4 + cld + rep movsd ; copy all full dwords + pop ecx + and ecx, 3 + rep movsb ; copy remaining bytes -.copyallbytes: - xor esi, esi - mov [ebx + SOCKET.rxDataCount], esi ; store new count (zero) + .exit: + ret ; at last, exit -.startcopy: - mov edi, ecx ; - ; add edi, std_application_base_address ; get data pointer to buffer in application - - mov esi, ebx ; - add esi, SOCKETHEADERSIZE ; we dont need to copy the header - mov ecx, eax ; eax is count of bytes - push ecx - shr ecx, 2 ; divide eax by 4 - cld ; copy all full dwords - rep movsd ; - pop ecx - and ecx, 3 - rep movsb ; copy the rest bytes - -.exit: - ret ; exit, or go back to shift remaining bytes if any + .error: + ;or eax, -1 + xor eax, eax + ret + .copy_all_bytes: + xor esi, esi + mov [ebx + SOCKET.rxDataCount], esi ; store new count (zero) + call .start_copy + ret + .start_copy: + mov edi, ecx + mov esi, ebx + add esi, SOCKETHEADERSIZE ; we dont need to copy the header + mov ecx, eax ; eax is count of bytes + push ecx + shr ecx, 2 ; divide eax by 4 + cld ; copy all full dwords + rep movsd + pop ecx + and ecx, 3 + rep movsb ; copy the rest bytes + retn ; exit, or go back to shift remaining bytes if any +endp ;*************************************************************************** @@ -631,168 +777,161 @@ socket_read_packet: ; could not queue IP packet ) ; ;*************************************************************************** -socket_write: - Index2RealAddr ebx +proc socket_write stdcall +; DEBUGF 1, "socket_write(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx ; get real socket address + or eax, eax + jz .error - mov eax, 0xFFFFFFFF - ; If the socket is invalid, return with an error code - cmp [ebx], dword SOCK_EMPTY - je sw_exit + mov ebx, eax + ; If the socket is invalid, return with an error code + cmp [ebx + SOCKET.Status], SOCK_EMPTY + je .error - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je sw_exit + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .error - ; Save the queue entry number - push eax + ; Save the queue entry number + push eax - ; save the pointers to the data buffer & size - push edx - push ecx + ; save the pointers to the data buffer & size + push edx + push ecx - ; convert buffer pointer eax to the absolute address - mov ecx, IPBUFFSIZE - mul ecx - add eax, IPbuffs + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs - mov edx, eax + mov edx, eax - ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr + ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr - ; Fill in the IP header ( some data is in the socket descriptor) - mov eax, [ebx + 8] - mov [edx + 12], eax ; source IP - mov eax, [ebx + 16] - mov [edx + 16], eax ; Destination IP + ; Fill in the IP header (some data is in the socket descriptor) + mov eax, [ebx + SOCKET.LocalIP] + mov [edx + IP_PACKET.SourceAddress], eax + mov eax, [ebx + SOCKET.RemoteIP] + mov [edx + IP_PACKET.DestinationAddress], eax - mov al, 0x45 - mov [edx], al ; Version, IHL - xor al, al - mov [edx + 1], al ; Type of service + mov [edx + IP_PACKET.VersionAndIHL], 0x45 + mov [edx + IP_PACKET.TypeOfService], 0 - pop eax ; Get the UDP data length - push eax + pop eax ; Get the UDP data length + push eax - add eax, 20 + 8 ; add IP header and UDP header lengths - mov [edx + 2], ah - mov [edx + 3], al - xor al, al - mov [edx + 4], al - mov [edx + 5], al - mov al, 0x40 - mov [edx + 6], al - xor al, al - mov [edx + 7], al - mov al, 0x20 - mov [edx + 8], al - mov al, 17 - mov [edx + 9], al + add eax, 20 + 8 ; add IP header and UDP header lengths + xchg al, ah + mov [edx + IP_PACKET.TotalLength], ax + xor eax, eax + mov [edx + IP_PACKET.Identification], ax + mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 + mov [edx + IP_PACKET.TimeToLive], 0x20 + mov [edx + IP_PACKET.Protocol], PROTOCOL_UDP - ; Checksum left unfilled - xor ax, ax - mov [edx + 10], ax + ; Checksum left unfilled + mov [edx + IP_PACKET.HeaderChecksum], ax - ; Fill in the UDP header ( some data is in the socket descriptor) - mov ax, [ebx + 12] - mov [edx + 20], ax + ; Fill in the UDP header (some data is in the socket descriptor) + mov ax, [ebx + SOCKET.LocalPort] + mov [edx + 20 + UDP_PACKET.SourcePort], ax - mov ax, [ebx + 20] - mov [edx + 20 + 2], ax + mov ax, [ebx + SOCKET.RemotePort] + mov [edx + 20 + UDP_PACKET.DestinationPort], ax - pop eax - push eax + pop eax + push eax - add eax, 8 - mov [edx + 20 + 4], ah - mov [edx + 20 + 5], al + add eax, 8 + xchg al, ah + mov [edx + 20 + UDP_PACKET.Length], ax - ; Checksum left unfilled - xor ax, ax - mov [edx + 20 + 6], ax + ; Checksum left unfilled + xor eax, eax + mov [edx + 20 + UDP_PACKET.Checksum], ax - pop ecx ; count of bytes to send - mov ebx, ecx ; need the length later - pop eax ; get callers ptr to data to send + pop ecx ; count of bytes to send + mov ebx, ecx ; need the length later + pop eax ; get callers ptr to data to send - ; Get the address of the callers data - mov edi, [TASK_BASE] - add edi, TASKDATA.mem_start - add eax, [edi] - mov esi, eax + ; Get the address of the callers data + mov edi, [TASK_BASE] + add edi, TASKDATA.mem_start + add eax, [edi] + mov esi, eax - mov edi, edx - add edi, 28 - cld - rep movsb ; copy the data across + mov edi, edx + add edi, 28 + cld + rep movsb ; copy the data across - ; we have edx as IPbuffer ptr. - ; Fill in the UDP checksum - ; First, fill in pseudoheader - mov eax, [edx + 12] - mov [pseudoHeader], eax - mov eax, [edx + 16] - mov [pseudoHeader+4], eax - mov ax, 0x1100 ; 0 + protocol - mov [pseudoHeader+8], ax - add ebx, 8 - mov eax, ebx - mov [pseudoHeader+10], ah - mov [pseudoHeader+11], al + ; we have edx as IPbuffer ptr. + ; Fill in the UDP checksum + ; First, fill in pseudoheader + mov eax, [edx + IP_PACKET.SourceAddress] + mov [pseudoHeader], eax + mov eax, [edx + IP_PACKET.DestinationAddress] + mov [pseudoHeader + 4], eax + mov word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0 ; 0 + protocol + add ebx, 8 + mov eax, ebx + xchg al, ah + mov [pseudoHeader + 10], ax - mov eax, pseudoHeader - mov [checkAdd1], eax - mov [checkSize1], word 12 - mov eax, edx - add eax, 20 - mov [checkAdd2], eax - mov eax, ebx - mov [checkSize2], ax ; was eax!! mjh 8/7/02 + mov eax, pseudoHeader + mov [checkAdd1], eax + mov [checkSize1], word 12 + mov eax, edx + add eax, 20 + mov [checkAdd2], eax + mov eax, ebx + mov [checkSize2], ax ; was eax!! mjh 8/7/02 - call checksum + call checksum - ; store it in the UDP checksum ( in the correct order! ) - mov ax, [checkResult] + ; store it in the UDP checksum ( in the correct order! ) + mov ax, [checkResult] - ; If the UDP checksum computes to 0, we must make it 0xffff - ; (0 is reserved for 'not used') - cmp ax, 0 - jne sw_001 - mov ax, 0xffff + ; If the UDP checksum computes to 0, we must make it 0xffff + ; (0 is reserved for 'not used') + test ax, ax + jnz @f + mov ax, 0xffff -sw_001: - mov [edx + 20 + 6], ah - mov [edx + 20 + 7], al + @@: xchg al, ah + mov [edx + 20 + UDP_PACKET.Checksum], ax - ; Fill in the IP header checksum - GET_IHL ecx,edx ; get IP-Header length - stdcall checksum_jb,edx,ecx ; buf_ptr, buf_size + ; Fill in the IP header checksum + GET_IHL ecx,edx ; get IP-Header length + stdcall checksum_jb,edx,ecx ; buf_ptr, buf_size + xchg al, ah + mov [edx + IP_PACKET.HeaderChecksum], ax - mov [edx + 10], ah - mov [edx + 11], al + ; Check destination IP address. + ; If it is the local host IP, route it back to IP_RX - ; Check destination IP address. - ; If it is the local host IP, route it back to IP_RX + pop ebx - pop ebx - mov eax, NET1OUT_QUEUE + mov eax, NET1OUT_QUEUE + mov ecx, [edx + SOCKET.RemoteIP] + mov edx, [stack_ip] + cmp edx, ecx + jne .not_local + mov eax, IPIN_QUEUE - mov ecx, [ edx + 16] - mov edx, [stack_ip] - cmp edx, ecx - jne sw_notlocal - mov eax, IPIN_QUEUE + .not_local: + ; Send it. + call queue -sw_notlocal: - ; Send it. - call queue - - xor eax, eax - -sw_exit: - ret + xor eax, eax + ret + .error: + or eax, -1 + ret +endp ;*************************************************************************** @@ -807,128 +946,131 @@ sw_exit: ; could not queue IP packet ) ; ;*************************************************************************** -socket_write_tcp: - Index2RealAddr ebx +proc socket_write_tcp stdcall +local sockAddr dd ? - mov [sktAddr], ebx +; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error - mov eax, 0xFFFFFFFF - ; If the socket is invalid, return with an error code - cmp [ebx], dword SOCK_EMPTY - je swt_exit + mov ebx, eax + mov [sockAddr], ebx - ; If the sockets window timer is nonzero, do not queue packet - ; TODO - done - cmp [ebx + SOCKET.wndsizeTimer], dword 0 - jne swt_exit + ; If the socket is invalid, return with an error code + cmp [ebx + SOCKET.Status], SOCK_EMPTY + je .error - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je swt_exit + ; If the sockets window timer is nonzero, do not queue packet + ; TODO - done + cmp [ebx + SOCKET.wndsizeTimer], 0 + jne .error - push eax + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .error - mov bl, 0x10 ; ACK + push eax - ; Get the address of the callers data - mov edi, [TASK_BASE] - add edi, TASKDATA.mem_start - add edx, [edi] - mov esi, edx + ; Get the address of the callers data + mov edi, [TASK_BASE] + add edi, TASKDATA.mem_start + add edx, [edi] + mov esi, edx - pop eax - push eax + pop eax + push eax - push ecx - call buildTCPPacket - pop ecx + push ecx + mov bl, TH_ACK + stdcall build_tcp_packet, [sockAddr] + pop ecx - ; Check destination IP address. - ; If it is the local host IP, route it back to IP_RX + ; Check destination IP address. + ; If it is the local host IP, route it back to IP_RX - pop ebx - push ecx - mov eax, NET1OUT_QUEUE + pop ebx + push ecx - mov edx, [stack_ip] - mov ecx, [sktAddr ] - mov ecx, [ecx + 16] - cmp edx, ecx - jne swt_notlocal - mov eax, IPIN_QUEUE + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE -swt_notlocal: - pop ecx + .not_local: + pop ecx + push ebx ; save ipbuffer number - push ebx ; save ipbuffer number + call queue - call queue + mov esi, [sockAddr] - mov esi, [sktAddr] + ; increament SND.NXT in socket + ; Amount to increment by is in ecx + add esi, SOCKET.SND_NXT + call add_inet_esi - ; increament SND.NXT in socket - ; Amount to increment by is in ecx - add esi, 48 - call add_inet_esi + pop ebx - pop ebx + ; Copy the IP buffer to a resend queue + ; If there isn't one, dont worry about it for now + mov esi, resendQ + mov ecx, 0 - ; Copy the IP buffer to a resend queue - ; If there isn't one, dont worry about it for now - mov esi, resendQ - mov ecx, 0 + .next_resendq: + cmp ecx, NUMRESENDENTRIES + je .exit ; None found + ;cmp byte[esi], 0xff ; XTODO: 0xff -> 0 + cmp dword[esi + 4], 0 + je @f ; found one + inc ecx + add esi, 8 + jmp .next_resendq -swt003: - cmp ecx, NUMRESENDENTRIES - je swt001 ; None found - cmp [esi], byte 0xFF - je swt002 ; found one - inc ecx - add esi, 4 - jmp swt003 + @@: push ebx -swt002: - push ebx + ; OK, we have a buffer descriptor ptr in esi. + ; resend entry # in ecx + ; Populate it + ; socket # + ; retries count + ; retry time + ; fill IP buffer associated with this descriptor - ; OK, we have a buffer descriptor ptr in esi. - ; resend entry # in ecx - ; Populate it - ; socket # - ; retries count - ; retry time - ; fill IP buffer associated with this descriptor + stdcall net_socket_addr_to_num, [sockAddr] + ;mov [esi], al ; XTODO: al -> eax + mov [esi + 4], eax + mov byte[esi + 1], TCP_RETRIES + mov word[esi + 2], TCP_TIMEOUT - mov eax, [sktAddr] - sub eax, sockets - shr eax, 12 ; get skt # - mov [esi], al - mov [esi + 1], byte TCP_RETRIES - mov [esi + 2], word TCP_TIMEOUT + inc ecx + ; Now get buffer location, and copy buffer across. argh! more copying,, + mov edi, resendBuffer - IPBUFFSIZE - inc ecx - ; Now get buffer location, and copy buffer across. argh! more copying,, - mov edi, resendBuffer - IPBUFFSIZE -swt002a: - add edi, IPBUFFSIZE - loop swt002a + @@: add edi, IPBUFFSIZE + loop @b - ; we have dest buffer location in edi - pop eax - ; convert source buffer pointer eax to the absolute address - mov ecx, IPBUFFSIZE - mul ecx - add eax, IPbuffs - mov esi, eax + ; we have dest buffer location in edi + pop eax + ; convert source buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + mov esi, eax - ; do copy - mov ecx, IPBUFFSIZE - cld - rep movsb + ; do copy + mov ecx, IPBUFFSIZE + cld + rep movsb -swt001: - xor eax, eax - -swt_exit: - ret + .exit: + xor eax, eax + ret + .error: + or eax, -1 + ret +endp diff --git a/kernel/trunk/network/stack.inc b/kernel/trunk/network/stack.inc index eefc30457a..914cb4248d 100644 --- a/kernel/trunk/network/stack.inc +++ b/kernel/trunk/network/stack.inc @@ -37,7 +37,7 @@ $Revision$ uglobal StackCounters: - dumped_rx_count: dd 0 + dumped_rx_count dd 0 arp_tx_count: dd 0 arp_rx_count: dd 0 ip_rx_count: dd 0 @@ -46,9 +46,9 @@ endg ; socket buffers SOCKETBUFFSIZE equ 4096 ; state + config + buffer. -SOCKETHEADERSIZE equ 76 ; thus 4096 - SOCKETHEADERSIZE bytes data +SOCKETHEADERSIZE equ 76+8+8 ; thus 4096 - SOCKETHEADERSIZE bytes data -NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20 +;NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20 ; IPBUFF status values BUFF_EMPTY equ 0 @@ -59,6 +59,7 @@ BUFF_TX_FULL equ 3 NUM_IPBUFFERS equ 20 ; buffers allocated for TX/RX NUMQUEUES equ 4 + EMPTY_QUEUE equ 0 IPIN_QUEUE equ 1 IPOUT_QUEUE equ 2 @@ -94,7 +95,7 @@ ethernet_active equ stack_data + 9 ; TODO :: empty memory area ; Address of selected socket -sktAddr equ stack_data + 32 +;sktAddr equ stack_data + 32 ; Parameter to checksum routine - data ptr checkAdd1 equ stack_data + 36 ; Parameter to checksum routine - 2nd data ptr @@ -110,8 +111,8 @@ checkResult equ stack_data + 48 pseudoHeader equ stack_data + 50 ; receive and transmit IP buffer allocation -sockets equ stack_data + 62 -Next_free2 equ sockets + (SOCKETBUFFSIZE * NUM_SOCKETS) +;sockets equ stack_data + 62 +Next_free2 equ stack_data + 62;Next_free2 equ sockets + (SOCKETBUFFSIZE * NUM_SOCKETS) ; 1560 byte buffer for rx / tx ethernet packets Ether_buffer equ Next_free2 Next_free3 equ Ether_buffer + 1518 @@ -128,9 +129,15 @@ last_1hsTick equ queueList + ( 2 * NUMQUEUEENTRIES ) ;resendQ equ 0x770000 -resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP +;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP ; XTODO: validate size +resendBuffer equ resendQ + ( 8 * NUMRESENDENTRIES ) ; for TCP +uglobal +net_sockets_mutex dd 0 +net_sockets rd 2 +endg + ; simple macro for memory set operation macro _memset_dw adr,value,amount { @@ -151,9 +158,6 @@ macro _memset_dw adr,value,amount include "queue.inc" include "eth_drv/ethernet.inc" include "ip.inc" -include "icmp.inc" -include "tcp.inc" -include "udp.inc" include "socket.inc" ;*************************************************************************** @@ -171,7 +175,8 @@ include "socket.inc" stack_init: ; Init two address spaces with default values _memset_dw stack_data_start, 0, 0x20000/4 - _memset_dw resendQ, 0xFFFFFFFF, NUMRESENDENTRIES + ;_memset_dw resendQ, 0xFFFFFFFF, NUMRESENDENTRIES ; XTODO: validate size + _memset_dw resendQ, 0xFFFFFFFF, NUMRESENDENTRIES * 2 ; Queries initialization call queueInit @@ -931,13 +936,11 @@ stack_get_packet: pop edx push eax ; save address of IP data - ; Get the address of the callers data mov edi,[TASK_BASE] add edi,TASKDATA.mem_start add edx,[edi] mov edi, edx - pop eax mov ecx, 1500 ; should get the actual number of bytes to write diff --git a/kernel/trunk/network/tcp.inc b/kernel/trunk/network/tcp.inc index 9b88503983..6c108717f3 100644 --- a/kernel/trunk/network/tcp.inc +++ b/kernel/trunk/network/tcp.inc @@ -15,28 +15,36 @@ ;; v0.6 : Added reset handling in the established state ;; ;; Added a timer per socket to allow delays when ;; ;; rx window gets below 1KB ;; +;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision$ ; TCP TCB states -TCB_LISTEN equ 1 -TCB_SYN_SENT equ 2 -TCB_SYN_RECEIVED equ 3 -TCB_ESTABLISHED equ 4 -TCB_FIN_WAIT_1 equ 5 -TCB_FIN_WAIT_2 equ 6 -TCB_CLOSE_WAIT equ 7 -TCB_CLOSING equ 8 -TCB_LAST_ACK equ 9 -TCB_TIME_WAIT equ 10 -TCB_CLOSED equ 11 +TCB_LISTEN equ 1 +TCB_SYN_SENT equ 2 +TCB_SYN_RECEIVED equ 3 +TCB_ESTABLISHED equ 4 +TCB_FIN_WAIT_1 equ 5 +TCB_FIN_WAIT_2 equ 6 +TCB_CLOSE_WAIT equ 7 +TCB_CLOSING equ 8 +TCB_LAST_ACK equ 9 +TCB_TIMED_WAIT equ 10 +TCB_CLOSED equ 11 -TWOMSL equ 10 ; # of secs to wait before closing socket +TH_FIN = 0x01 +TH_SYN = 0x02 +TH_RST = 0x04 +TH_PUSH = 0x08 +TH_ACK = 0x10 +TH_URG = 0x20 -TCP_RETRIES equ 5 ; Number of times to resend a packet -TCP_TIMEOUT equ 10 ; resend if not replied to in x hs +TWOMSL equ 10 ; # of secs to wait before closing socket + +TCP_RETRIES equ 5 ; Number of times to resend a packet +TCP_TIMEOUT equ 10 ; resend if not replied to in x hs ;******************************************************************* ; Interface @@ -73,18 +81,18 @@ TCP_TIMEOUT equ 10 ; resend if not replied to in x struc TCP_PACKET -{ .SourcePort dw ? ;+00 +{ .SourcePort dw ? ;+00 .DestinationPort dw ? ;+02 .SequenceNumber dd ? ;+04 - .AckNumber dd ? ;+08 - .DataOffset db ? ;+12 - DataOffset[0-3 bits] and Reserved[4-7] - .Flags db ? ;+13 - Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN - .Window dw ? ;+14 - .Checksum dw ? ;+16 + .AckNumber dd ? ;+08 + .DataOffset db ? ;+12 - DataOffset[0-3 bits] and Reserved[4-7] + .Flags db ? ;+13 - Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN + .Window dw ? ;+14 + .Checksum dw ? ;+16 .UrgentPointer dw ? ;+18 - .Options rb 3 ;+20 - .Padding db ? ;+23 - .Data db ? ;+24 + .Options rb 3 ;+20 + .Padding db ? ;+23 + .Data db ? ;+24 } virtual at 0 @@ -102,62 +110,50 @@ end virtual ; when the TCB timer expires ; ;*************************************************************************** -tcp_tcb_handler: - ; scan through all the sockets, decrementing active timers - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS +proc tcp_tcb_handler stdcall uses ebx + ; scan through all the sockets, decrementing active timers -tth1: - sub eax, SOCKETBUFFSIZE - cmp [eax + sockets + 32], dword 0 - jne tth2 + mov ebx, net_sockets -tth1a: - cmp [eax + sockets + 72], dword 0 - jne tth4 + cmp [ebx + SOCKET.NextPtr], 0 + je .exit + DEBUGF 1, "K : sockets:\n" - loop tth1 - ret + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .exit -tth2: - ; decrement it, delete socket if TCB timer = 0 & socket in timewait state - pusha - dec dword [eax + sockets + 32] - cmp [eax + sockets + 32], dword 0 - jne tth3 + DEBUGF 1, "K : %x: %x-%x-%x-%u\n", ebx, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] - cmp [eax + sockets + 28], dword TCB_TIME_WAIT - jne tth3 + cmp [ebx + SOCKET.TCBTimer], 0 + jne .decrement_tcb + cmp [ebx + SOCKET.wndsizeTimer], 0 + jne .decrement_wnd + jmp .next_socket - ; OK, delete socket - mov edi, eax - add edi, sockets + .decrement_tcb: + ; decrement it, delete socket if TCB timer = 0 & socket in timewait state + dec [ebx + SOCKET.TCBTimer] + jnz .next_socket - xor eax, eax - mov ecx, SOCKETHEADERSIZE - cld - rep stosb + cmp [ebx + SOCKET.TCBState], TCB_TIMED_WAIT + jne .next_socket -tth3: - popa + push [ebx + SOCKET.PrevPtr] + stdcall net_socket_free, ebx + pop ebx + jmp .next_socket - jmp tth1a + .decrement_wnd: + ; TODO - prove it works! + dec [ebx + SOCKET.wndsizeTimer] + jmp .next_socket - loop tth1 - ret - - ; TODO - prove it works! -tth4: - dec dword [eax + sockets + 72] - loop tth1 - ret - - - - -tth_exit: - ret + .exit: + ret +endp ;*************************************************************************** @@ -169,122 +165,110 @@ tth_exit: ; This is a kernel function, called by stack_handler ; ;*************************************************************************** -tcp_tx_handler: + +proc tcp_tx_handler stdcall ; decrement all resend buffers timers. If they ; expire, queue them for sending, and restart the timer. ; If the retries counter reach 0, delete the entry - mov esi, resendQ - mov ecx, 0 + mov esi, resendQ + mov ecx, 0 -tth001: - cmp ecx, NUMRESENDENTRIES - je tth003 ; None left - cmp [esi], byte 0xFF - jne tth002 ; found one - inc ecx - add esi, 4 - jmp tth001 + .next_resendq: + cmp ecx, NUMRESENDENTRIES + je .exit ; None left + ;cmp [esi], byte 0xFF ; XTODO: 0xff -> 0 + cmp dword[esi + 4], 0 + jne @f ; found one + inc ecx + add esi, 8 + jmp .next_resendq -tth002: - ; we have one. decrement it's timer by 1 - dec word [esi+2] - mov ax, [esi+2] - cmp ax, 0 - je tth002a - inc ecx - add esi, 4 - jmp tth001 ; Timer not zero, so move on + @@: ; we have one. decrement it's timer by 1 + dec word[esi + 2] + jz @f + inc ecx + add esi, 8 + jmp .next_resendq ; Timer not zero, so move on -tth002a: - mov bl, 0xff - ; restart timer, and decrement retries - ; After the first resend, back of on next, by a factor of 5 - mov [esi+2], word TCP_TIMEOUT * 5 - dec byte [esi+1] - mov al, [esi+1] - cmp al, 0 - jne tth004 + @@: + ;mov bl, 0xff ; XTODO: bl -> ebx, 0xff -> 0 + xor ebx, ebx + ; restart timer, and decrement retries + ; After the first resend, back of on next, by a factor of 5 + mov [esi + 2], word TCP_TIMEOUT * 5 + dec byte[esi + 1] + jnz @f - ; retries now 0, so delete from queue - xchg [esi], bl -tth004: + ; retries now 0, so delete from queue + ;xchg [esi], bl ; XTODO: bl -> ebx + xchg [esi + 4], ebx - ; resend packet - pusha + @@: ; resend packet + pushad - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - jne tth004z + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + jne .tth004z - ; TODO - try again in 10ms. - cmp bl, 0xff - jne tth004za - mov [esi], bl + ; TODO - try again in 10ms. + ;cmp bl, 0xff ; XTODO: 0xff -> 0 + test ebx, ebx + jnz @f + ;mov [esi], bl ; XTODO: bl -> ebx + mov [esi + 4], ebx -tth004za: - ; Mark it to expire in 10ms - 1 tick - mov [esi+1], byte 1 - mov [esi+2], word 1 - jmp tth005 + @@: ; Mark it to expire in 10ms - 1 tick + mov byte[esi + 1], 1 + mov word[esi + 2], 1 + jmp .tth005 -tth004z: - ; we have a buffer # in ax + .tth004z: + ; we have a buffer # in ax + push eax ecx + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs - push eax - push ecx - mov ecx, IPBUFFSIZE - mul ecx - add eax, IPbuffs + ; we have the buffer address in eax + mov edi, eax + pop ecx + ; Now get buffer location, and copy buffer across. argh! more copying,, + mov esi, resendBuffer + @@: add esi, IPBUFFSIZE + loop @b - ; we have the buffer address in eax - mov edi, eax - pop ecx - ; get resend data address - inc ecx - ; Now get buffer location, and copy buffer across. argh! more copying,, - mov esi, resendBuffer - IPBUFFSIZE -tth004a: - add esi, IPBUFFSIZE - loop tth004a + ; we have resend buffer location in esi + mov ecx, IPBUFFSIZE - ; we have resend buffer location in esi - mov ecx, IPBUFFSIZE + ; copy data across + push edi + cld + rep movsb + pop edi - ; copy data across - cld - rep movsb + ; queue packet + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + cmp edx, [edi + IP_PACKET.DestinationAddress] + jne .not_local + mov eax, IPIN_QUEUE - ; queue packet + .not_local: + pop ebx + call queue + .tth005: + popad + inc ecx + add esi, 8 + jmp .next_resendq - mov eax, NET1OUT_QUEUE - - mov edx, [stack_ip] - mov ecx, [ edi + 16 ] - cmp edx, ecx - jne tth004b - mov eax, IPIN_QUEUE - -tth004b: - pop ebx - - call queue - - -tth005: - popa - - inc ecx - add esi, 4 - jmp tth001 - -tth003: - ret - - + .exit: + ret +endp ;*************************************************************************** @@ -299,125 +283,165 @@ tth003: ; Free up (or re-use) IP buffer when finished ; ;*************************************************************************** -tcp_rx: - ; The process is as follows. - ; Look for a socket with matching remote IP, remote port, local port - ; if not found, then - ; look for remote IP + local port match ( where sockets remote port = 0) - ; if not found, then - ; look for a socket where local socket port == IP packets remote port - ; where sockets remote port, remote IP = 0 - ; discard if not found - ; Call sockets tcbStateMachine, with pointer to packet. - ; the state machine will not delete the packet, so do that here. - push eax +proc tcp_rx stdcall uses ebx + ; The process is as follows. + ; Look for a socket with matching remote IP, remote port, local port + ; if not found, then + ; look for remote IP + local port match ( where sockets remote port = 0) + ; if not found, then + ; look for a socket where local socket port == IP packets remote port + ; where sockets remote port, remote IP = 0 + ; discard if not found + ; Call sockets tcbStateMachine, with pointer to packet. + ; the state machine will not delete the packet, so do that here. - ; Look for a socket where - ; IP Packet TCP Destination Port = local Port - ; IP Packet SA = Remote IP - ; IP Packet TCP Source Port = remote Port + push eax - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS -ss1: - sub eax, SOCKETBUFFSIZE - movzx ebx, word [edx + 22] ; get the dest. port from the TCP hdr - cmp [eax + sockets + 12], bx ; compare with socket's local port - jnz nxttst1 ; different - try next socket + ; Look for a socket where + ; IP Packet TCP Destination Port = local Port + ; IP Packet SA = Remote IP + ; IP Packet TCP Source Port = remote Port - movzx ebx, word [edx + 20] ; get the source port from the TCP hdr - cmp [eax + sockets + 20], bx ; compare with socket's remote port - jnz nxttst1 ; different - try next socket + mov ebx, net_sockets + .next_socket.1: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .next_socket.1.exit - mov ebx, [edx + 12] ; get the source IP Addr from the IP hdr - cmp [eax + sockets + 16], ebx ; compare with socket's remote IP - jnz nxttst1 ; different - try next socket + cmp [ebx + SOCKET.Status], SOCK_OPEN + jne .next_socket.1 - ; We have a complete match - use this socket - jmp tcprx_001 +; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 -nxttst1: - loop ss1 ; Return back if no match + mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr + cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr + jne .next_socket.1 ; different - try next socket - ; If we got here, there was no match - ; Look for a socket where - ; IP Packet TCP Destination Port = local Port - ; IP Packet SA = Remote IP - ; socket remote Port = 0 +; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS + mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr + cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP + jne .next_socket.1 ; different - try next socket -ss2: - sub eax, SOCKETBUFFSIZE +; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_PACKET.SourcePort]:4, [ebx + SOCKET.RemotePort]:4 - movzx ebx, word [edx + 22] ; get the dest. port from the TCP hdr - cmp [eax + sockets + 12], bx ; compare with socket's local port - jnz nxttst2 ; different - try next socket + mov ax, [edx + 20 + TCP_PACKET.SourcePort] ; get the source port from the TCP hdr + cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port + jne .next_socket.1 ; different - try next socket - mov ebx, [edx + 12] ; get the source IP Addr from the IP hdr - cmp [eax + sockets + 16], ebx ; compare with socket's remote IP - jnz nxttst2 ; different - try next socket + ; We have a complete match - use this socket + jmp .change_state - mov ebx, 0 - cmp [eax + sockets + 20], bx ; only match a remote socket of 0 - jnz nxttst2 ; different - try next socket + .next_socket.1.exit: - ; We have a complete match - use this socket - jmp tcprx_001 + ; If we got here, there was no match + ; Look for a socket where + ; IP Packet TCP Destination Port = local Port + ; IP Packet SA = Remote IP + ; socket remote Port = 0 -nxttst2: - loop ss2 ; Return back if no match + mov ebx, net_sockets - ; If we got here, there was no match - ; Look for a socket where - ; IP Packet TCP Destination Port = local Port - ; socket Remote IP = 0 - ; socket remote Port = 0 + .next_socket.2: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .next_socket.2.exit - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS + cmp [ebx + SOCKET.Status], SOCK_OPEN + jne .next_socket.2 -ss3: - sub eax, SOCKETBUFFSIZE +; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 - movzx ebx, word [edx + 22] ; get destination port from the TCP hdr - cmp [eax + sockets + 12], bx ; compare with socket's local port - jnz nxttst3 ; different - try next socket + mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr + cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port + jne .next_socket.2 ; different - try next socket - mov ebx, 0 - cmp [eax + sockets + 20], bx ; only match a remote socket of 0 - jnz nxttst3 ; different - try next socket +; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] - mov ebx, 0 - cmp [eax + sockets + 16], ebx ; only match a socket remote IP of 0 - jnz nxttst3 ; different - try next socket + mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr + cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP + jne .next_socket.2 ; different - try next socket - ; We have a complete match - use this socket - jmp tcprx_001 +; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 -nxttst3: - loop ss3 ; Return back if no match + cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 + jne .next_socket.2 ; different - try next socket - ; If we got here, we need to reject the packet - inc dword [dumped_rx_count] - jmp tcprx_exit + ; We have a complete match - use this socket + jmp .change_state -tcprx_001: - ; We have a valid socket/TCB, so call the TCB State Machine for that skt. - ; socket is pointed to by [eax + sockets] - ; IP packet is pointed to by [edx] - ; IP buffer number is on stack ( it will be popped at the end) - call tcpStateMachine + .next_socket.2.exit: -tcprx_exit: - pop eax - call freeBuff + ; If we got here, there was no match + ; Look for a socket where + ; IP Packet TCP Destination Port = local Port + ; socket Remote IP = 0 + ; socket remote Port = 0 - ret + mov ebx, net_sockets + .next_socket.3: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .next_socket.3.exit + + cmp [ebx + SOCKET.Status], SOCK_OPEN + jne .next_socket.3 + +; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 + + mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get destination port from the TCP hdr + cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port + jne .next_socket.3 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP] + + cmp [ebx + SOCKET.RemoteIP], 0 ; only match a socket remote IP of 0 + jne .next_socket.3 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 + + cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 + jne .next_socket.3 ; different - try next socket + + ; We have a complete match - use this socket + jmp .change_state + + .next_socket.3.exit: + + ; If we got here, we need to reject the packet + + DEBUGF 1, "K : tcp_rx - dumped\n" + DEBUGF 1, "K : --------: %x-%x-%x (flags: %x)\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [edx + IP_PACKET.SourceAddress], [edx + 20 + TCP_PACKET.SourcePort]:4, [edx + 20 + TCP_PACKET.Flags]:2 +; mov ebx, net_sockets +; +; .next_socket.4: +; mov ebx, [ebx + SOCKET.NextPtr] +; or ebx, ebx +; jz .next_socket.4.exit +; DEBUGF 1, "K : %x: %x-%x-%x-%u\n", ebx, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] +; jne .next_socket.4 +; +; .next_socket.4.exit: + inc [dumped_rx_count] + jmp .exit + + .change_state: + + ; We have a valid socket/TCB, so call the TCB State Machine for that skt. + ; socket is pointed to by ebx + ; IP packet is pointed to by edx + ; IP buffer number is on stack ( it will be popped at the end) + + stdcall tcpStateMachine, ebx + + .exit: + pop eax + call freeBuff + ret +endp ;*************************************************************************** @@ -434,216 +458,166 @@ tcprx_exit: ; Transmit buffer number in eax ; ;*************************************************************************** -buildTCPPacket: - push ecx ; Save data length - ; convert buffer pointer eax to the absolute address - mov ecx, IPBUFFSIZE - mul ecx - add eax, IPbuffs +proc build_tcp_packet stdcall, sockAddr:DWORD + push ecx ; Save data length - mov edx, eax + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs - mov [edx + 33], bl ; TCP flags + mov edx, eax - mov ebx, [sktAddr] + mov [edx + 20 + TCP_PACKET.Flags], bl ; TCP flags - ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr + mov ebx, [sockAddr] - ; Fill in the IP header ( some data is in the socket descriptor) - mov eax, [ebx + 8] - mov [edx + 12], eax ; source IP - mov eax, [ebx + 16] - mov [edx + 16], eax ; Destination IP + ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr - mov al, 0x45 - mov [edx], al ; Version, IHL - xor al, al - mov [edx + 1], al ; Type of service + ; Fill in the IP header ( some data is in the socket descriptor) + mov eax, [ebx + SOCKET.LocalIP] + mov [edx + IP_PACKET.SourceAddress], eax + mov eax, [ebx + SOCKET.RemoteIP] + mov [edx + IP_PACKET.DestinationAddress], eax - pop eax ; Get the TCP data length - push eax + mov [edx + IP_PACKET.VersionAndIHL], 0x45 + mov [edx + IP_PACKET.TypeOfService], 0 - add eax, 20 + 20 ; add IP header and TCP header lengths - mov [edx + 2], ah - mov [edx + 3], al - xor al, al - mov [edx + 4], al - mov [edx + 5], al - mov al, 0x40 - mov [edx + 6], al - xor al, al - mov [edx + 7], al - mov al, 0x20 - mov [edx + 8], al - mov al, 6 ; TCP protocol - mov [edx + 9], al + pop eax ; Get the TCP data length + push eax - ; Checksum left unfilled - xor ax, ax - mov [edx + 10], ax + add eax, 20 + 20 ; add IP header and TCP header lengths + rol ax, 8 + mov [edx + IP_PACKET.TotalLength], ax + mov [edx + IP_PACKET.Identification], 0 + mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 + mov [edx + IP_PACKET.TimeToLive], 0x20 + mov [edx + IP_PACKET.Protocol], PROTOCOL_TCP - ; Fill in the TCP header ( some data is in the socket descriptor) - mov ax, [ebx + 12] - mov [edx + 20], ax ; Local Port + ; Checksum left unfilled + mov [edx + IP_PACKET.HeaderChecksum], 0 - mov ax, [ebx + 20] - mov [edx + 20 + 2], ax ; desitination Port + ; Fill in the TCP header (some data is in the socket descriptor) + mov ax, [ebx + SOCKET.LocalPort] + mov [edx + 20 + TCP_PACKET.SourcePort], ax ; Local Port - ; Checksum left unfilled - xor ax, ax - mov [edx + 20 + 16], ax + mov ax, [ebx + SOCKET.RemotePort] + mov [edx + 20 + TCP_PACKET.DestinationPort], ax ; desitination Port - ; sequence number - mov eax, [ebx + 48] - mov [edx + 20 + 4], eax + ; Checksum left unfilled + mov [edx + 20 + TCP_PACKET.Checksum], 0 - ; ack number - mov eax, [ebx + 56] - mov [edx + 20 + 8], eax + ; sequence number + mov eax, [ebx + SOCKET.SND_NXT] + mov [edx + 20 + TCP_PACKET.SequenceNumber], eax - ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) - ; 768 bytes seems better - mov ax, 0x0003 - mov [edx + 20 + 14], ax + ; ack number + mov eax, [ebx + SOCKET.RCV_NXT] + mov [edx + 20 + TCP_PACKET.AckNumber], eax - ; Urgent pointer (0) - mov ax, 0 - mov [edx + 20 + 18], ax + ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) + ; 768 bytes seems better + mov [edx + 20 + TCP_PACKET.Window], 0x0003 - ; data offset ( 0x50 ) - mov al, 0x50 - mov [edx + 20 + 12], al + ; Urgent pointer (0) + mov [edx + 20 + TCP_PACKET.UrgentPointer], 0 - pop ecx ; count of bytes to send - mov ebx, ecx ; need the length later + ; data offset ( 0x50 ) + mov [edx + 20 + TCP_PACKET.DataOffset], 0x50 - cmp ebx, 0 - jz btp_001 + pop ecx ; count of bytes to send + mov ebx, ecx ; need the length later - mov edi, edx - add edi, 40 - cld - rep movsb ; copy the data across + cmp ebx, 0 + jz @f -btp_001: - ; we have edx as IPbuffer ptr. - ; Fill in the TCP checksum - ; First, fill in pseudoheader - mov eax, [edx + 12] - mov [pseudoHeader], eax - mov eax, [edx + 16] - mov [pseudoHeader+4], eax - mov ax, 0x0600 ; 0 + protocol - mov [pseudoHeader+8], ax - add ebx, 20 - mov eax, ebx - mov [pseudoHeader+10], ah - mov [pseudoHeader+11], al + mov edi, edx + add edi, 40 + cld + rep movsb ; copy the data across - mov eax, pseudoHeader - mov [checkAdd1], eax - mov [checkSize1], word 12 - mov eax, edx - add eax, 20 - mov [checkAdd2], eax - mov eax, ebx - mov [checkSize2], ax + @@: ; we have edx as IPbuffer ptr. + ; Fill in the TCP checksum + ; First, fill in pseudoheader + mov eax, [edx + IP_PACKET.SourceAddress] + mov [pseudoHeader], eax + mov eax, [edx + IP_PACKET.DestinationAddress] + mov [pseudoHeader + 4], eax + mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0 + add ebx, 20 + mov [pseudoHeader + 10], bh + mov [pseudoHeader + 11], bl - call checksum + mov eax, pseudoHeader + mov [checkAdd1], eax + mov word[checkSize1], 12 + mov eax, edx + add eax, 20 + mov [checkAdd2], eax + mov eax, ebx + mov [checkSize2], ax - ; store it in the TCP checksum ( in the correct order! ) - mov ax, [checkResult] + call checksum - mov [edx + 20 + 16], ah - mov [edx + 20 + 17], al + ; store it in the TCP checksum ( in the correct order! ) + mov ax, [checkResult] + rol ax, 8 + mov [edx + 20 + TCP_PACKET.Checksum], ax - ; Fill in the IP header checksum - GET_IHL eax,edx ; get IP-Header length - stdcall checksum_jb,edx,eax ; buf_ptr, buf_size + ; Fill in the IP header checksum + GET_IHL eax, edx ; get IP-Header length + stdcall checksum_jb, edx, eax ; buf_ptr, buf_size + rol ax, 8 + mov [edx + IP_PACKET.HeaderChecksum], ax - mov [edx + 10], ah - mov [edx + 11], al - - ret + ret +endp ; Increments the 32 bit value pointed to by esi in internet order -inc_inet_esi: - push eax - add esi, 3 - mov al, byte[esi] - inc al - mov byte[esi], al - cmp al, 0 - jnz iie_exit - dec esi - mov al, byte[esi] - inc al - mov byte[esi], al - cmp al, 0 - jnz iie_exit - dec esi - mov al, byte[esi] - inc al - mov byte[esi], al - cmp al, 0 - jnz iie_exit - dec esi - mov al, byte[esi] - inc al - mov byte[esi], al - -iie_exit: - pop eax - ret +proc inc_inet_esi stdcall + push eax + mov eax, [esi] + bswap eax + inc eax + bswap eax + mov [esi], eax + pop eax + ret +endp ; Increments the 32 bit value pointed to by esi in internet order ; by the value in ecx -add_inet_esi: - push eax - - mov al, [esi] - shl eax, 8 - inc esi - mov al, [esi] - shl eax, 8 - inc esi - mov al, [esi] - shl eax, 8 - inc esi - mov al, [esi] - add eax, ecx - mov [esi], al - dec esi - shr eax, 8 - mov [esi], al - dec esi - shr eax, 8 - mov [esi], al - dec esi - shr eax, 8 - mov [esi], al - pop eax - ret +proc add_inet_esi stdcall + push eax + mov eax, [esi] + bswap eax + add eax, ecx + bswap eax + mov [esi], eax + pop eax + ret +endp iglobal - TCBStateHandler: - dd stateTCB_LISTEN - dd stateTCB_SYN_SENT - dd stateTCB_SYN_RECEIVED - dd stateTCB_ESTABLISHED - dd stateTCB_FIN_WAIT_1 - dd stateTCB_FIN_WAIT_2 - dd stateTCB_CLOSE_WAIT - dd stateTCB_CLOSING - dd stateTCB_LAST_ACK - dd stateTCB_TIME_WAIT - dd stateTCB_CLOSED + TCBStateHandler dd \ + stateTCB_LISTEN, \ + stateTCB_SYN_SENT, \ + stateTCB_SYN_RECEIVED, \ + stateTCB_ESTABLISHED, \ + stateTCB_FIN_WAIT_1, \ + stateTCB_FIN_WAIT_2, \ + stateTCB_CLOSE_WAIT, \ + stateTCB_CLOSING, \ + stateTCB_LAST_ACK, \ + stateTCB_TIME_WAIT, \ + stateTCB_CLOSED endg + ;*************************************************************************** ; Function ; tcpStateMachine @@ -653,651 +627,553 @@ endg ; This is a kernel function, called by tcp_rx ; ; IP buffer address given in edx -; Socket/TCB address in [eax + sockets] +; Socket/TCB address in ebx ; ; The IP buffer will be released by the caller ;*************************************************************************** -tcpStateMachine: - mov ebx, sockets - add ebx, eax - mov [sktAddr], ebx - - ; as a packet has been received, update the TCB timer - mov ecx, TWOMSL - mov [ebx + 32], ecx - - ; If the received packet has an ACK bit set, - ; remove any packets in the resend queue that this - ; received packet acknowledges - pusha - mov cl, [edx + 33] - and cl, 0x10 - cmp cl, 0x10 - jne tsm001 ; No ACK, so no data yet - - - ; get skt number in al - shr eax, 12 - - ; The ack number is in [edx + 28], inet format - ; skt in al - - mov esi, resendQ - mov ecx, 0 - -t001: - cmp ecx, NUMRESENDENTRIES - je t003 ; None left - cmp [esi], al - je t002 ; found one - inc ecx - add esi, 4 - jmp t001 - -t002: ; Can we delete this buffer? - - ; If yes, goto t004. No, goto t001 - ; Get packet data address - - push ecx - inc ecx - ; Now get buffer location, and copy buffer across. argh! more copying,, - mov edi, resendBuffer - IPBUFFSIZE -t002a: - add edi, IPBUFFSIZE - loop t002a - - ; we have dest buffer location in edi. incoming packet in edx. - ; Get this packets sequence number - ; preserve al, ecx, esi, edx - - mov cl, [edi + 24] - shl ecx, 8 - mov cl, [edi + 25] - shl ecx, 8 - mov cl, [edi + 26] - shl ecx, 8 - mov cl, [edi + 27] - movzx ebx, byte [edi + 3] - mov bh, [edi + 2] - sub ebx, 40 - add ecx, ebx ; ecx is now seq# of last byte +1, intel format - - ; get recievd ack #, in intel format - mov bl, [edx + 28] - shl ebx, 8 - mov bl, [edx + 29] - shl ebx, 8 - mov bl, [edx + 30] - shl ebx, 8 - mov bl, [edx + 31] - - cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que - ; DANGER! need to handle case that we have just - ; passed the 2**32, and wrapped round! - pop ecx - - jae t004 ; if rx > old, delete old - inc ecx - add esi, 4 - jmp t001 - - -t004: - dec dword [arp_rx_count] ; ************ TEST ONLY! - - mov [esi], byte 0xFF - inc ecx - add esi, 4 - jmp t001 - -t003: - -tsm001: - popa - - ; Call handler for given TCB state - mov ebx, [eax + sockets+28] - cmp ebx, TCB_LISTEN - jb tsm_exit - cmp ebx, TCB_CLOSED - ja tsm_exit - - dec ebx - call dword [TCBStateHandler+ebx*4] - -tsm_exit: - ret - - - -stateTCB_LISTEN: - ; In this case, we are expecting a SYN packet - ; For now, if the packet is a SYN, process it, and send a response - ; If not, ignore it - - ; Look at control flags - mov bl, [edx + 33] - and bl, 0x02 - cmp bl, 0x02 - jnz stl_exit - - ; We have a SYN. update the socket with this IP packets details, - ; And send a response - - mov ebx, [edx + 12] ; IP source address - mov [eax + sockets + 16], ebx - mov bx, [edx + 20] ; IP source port - mov [eax + sockets + 20], bx - mov ebx, [edx + 24] ; IRS - mov [eax + sockets + 40], ebx - mov [eax + sockets + 56], ebx - mov esi, sockets - add esi, eax - add esi, 56 - call inc_inet_esi ; RCV.NXT - mov ebx, [eax + sockets + 36] ; ISS - mov [eax + sockets + 48], ebx ; SND.NXT - - ; Now construct the response, and queue for sending by IP - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je stl_exit - - push eax - mov bl, 0x12 ; SYN + ACK - mov ecx, 0 - mov esi, 0 - - call buildTCPPacket - - mov eax, NET1OUT_QUEUE - mov edx, [stack_ip] - mov ecx, [ sktAddr ] - mov ecx, [ ecx + 16 ] - cmp edx, ecx - jne stl_notlocal - mov eax, IPIN_QUEUE -stl_notlocal: - ; Send it. - pop ebx - call queue +proc tcpStateMachine stdcall, sockAddr:DWORD + ; as a packet has been received, update the TCB timer + mov [ebx + SOCKET.TCBTimer], TWOMSL + + ; If the received packet has an ACK bit set, + ; remove any packets in the resend queue that this + ; received packet acknowledges + pushad + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .call_handler ; No ACK, so no data yet + + ; get skt number in eax + stdcall net_socket_addr_to_num, ebx + + ; The ack number is in [edx + 28], inet format + ; skt in eax + + mov esi, resendQ + xor ecx, ecx + + .next_resendq: + cmp ecx, NUMRESENDENTRIES + je .call_handler ; None left + ;cmp [esi], al ; XTODO: al -> eax + cmp [esi + 4], eax + je @f ; found one + inc ecx + add esi, 8 + jmp .next_resendq + + @@: ; Can we delete this buffer? + + ; If yes, goto @@. No, goto .next_resendq + ; Get packet data address + + push ecx + ; Now get buffer location, and copy buffer across. argh! more copying,, + imul edi, ecx, IPBUFFSIZE + add edi, resendBuffer + + ; we have dest buffer location in edi. incoming packet in edx. + ; Get this packets sequence number + ; preserve al, ecx, esi, edx + mov ecx, [edi + 20 + TCP_PACKET.SequenceNumber] + bswap ecx + movzx ebx, word[edi + 2] + xchg bl, bh + sub ebx, 40 + add ecx, ebx ; ecx is now seq# of last byte +1, intel format + + ; get recievd ack #, in intel format + mov ebx, [edx + 20 + TCP_PACKET.AckNumber] + bswap ebx + + cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que + ; DANGER! need to handle case that we have just + ; passed the 2**32, and wrapped round! + pop ecx + jae @f ; if rx > old, delete old + + inc ecx + add esi, 8 + jmp .next_resendq + + ;@@: mov byte[esi], 0xff ; XTODO: 0xff -> 0 + @@: mov dword[esi + 4], 0 + inc ecx + add esi, 8 + jmp .next_resendq + + .call_handler: + popad + + ; Call handler for given TCB state + + mov eax, [ebx + SOCKET.TCBState] + cmp eax, TCB_LISTEN + jb .exit + cmp eax, TCB_CLOSED + ja .exit + + stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr] + + .exit: + ret +endp + + +proc stateTCB_LISTEN stdcall, sockAddr:DWORD + ; In this case, we are expecting a SYN packet + ; For now, if the packet is a SYN, process it, and send a response + ; If not, ignore it + + ; Look at control flags + test [edx + 20 + TCP_PACKET.Flags], TH_SYN + jz .exit + + ; We have a SYN. update the socket with this IP packets details, + ; And send a response + + mov eax, [edx + IP_PACKET.SourceAddress] + mov [ebx + SOCKET.RemoteIP], eax + mov ax, [edx + 20 + TCP_PACKET.SourcePort] + mov [ebx + SOCKET.RemotePort], ax + mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] + mov [ebx + SOCKET.IRS], eax + mov [ebx + SOCKET.RCV_NXT], eax + lea esi, [ebx + SOCKET.RCV_NXT] + call inc_inet_esi ; RCV.NXT + mov eax, [ebx + SOCKET.ISS] + mov [ebx + SOCKET.SND_NXT], eax + + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit + + push eax + mov bl, TH_SYN + TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] + + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + ; Send it. + pop ebx + call queue + + mov esi, [sockAddr] + mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED + + ; increment SND.NXT in socket + add esi, SOCKET.SND_NXT + call inc_inet_esi + + .exit: + ret +endp + + +proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD + ; We are awaiting an ACK to our SYN, with a SYM + ; Look at control flags - expecting an ACK + + mov al, [edx + 20 + TCP_PACKET.Flags] + and al, TH_SYN + TH_ACK + cmp al, TH_SYN + TH_ACK + je .syn_ack + + test al, TH_SYN + jz .exit + + mov [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED + push TH_SYN + TH_ACK + jmp .send + + .syn_ack: + mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED + push TH_ACK + + .send: + ; Store the recv.nxt field + mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] + + ; Update our recv.nxt field + mov [ebx + SOCKET.RCV_NXT], eax + lea esi, [ebx + SOCKET.RCV_NXT] + call inc_inet_esi + + ; Send an ACK + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + pop ebx + je .exit + + push eax + + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] + + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + ; Send it. + pop ebx + call queue + + .exit: + ret +endp + + +proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD + ; In this case, we are expecting an ACK packet + ; For now, if the packet is an ACK, process it, + ; If not, ignore it + + test [edx + 20 + TCP_PACKET.Flags], TH_RST ;xxx + jz .check_ack ;xxx + + push [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP] + pop [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort] + + mov [ebx + SOCKET.TCBState], TCB_LISTEN ;xxx + jmp .exit ;xxx + + .check_ack: ;xxx + ; Look at control flags - expecting an ACK + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit + + mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED + + .exit: + ret +endp + + +proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD + ; Here we are expecting data, or a request to close + ; OR both... + + ; Did we receive a FIN or RST? +;xxx test [edx + 20 + TCP_PACKET.Flags], TH_FIN + TH_RST +;xxx jz .check_ack + test [edx + 20 + TCP_PACKET.Flags], TH_FIN ;xxx + jz .check_ack ;xxx + ; It was a fin or reset. - mov ebx, TCB_SYN_RECEIVED - mov esi, [sktAddr] - mov [esi + 28], ebx + ; Remove resend entries from the queue - I dont want to send any more data + pushad + + ; get skt # + stdcall net_socket_addr_to_num, ebx - ; increament SND.NXT in socket - add esi, 48 - call inc_inet_esi + mov esi, resendQ + mov ecx, 0 -stl_exit: - ret + .next_resendq: + cmp ecx, NUMRESENDENTRIES + je .last_resendq ; None left + ;cmp [esi], al ; XTODO: al -> eax + cmp [esi + 4], eax + je @f ; found one + inc ecx + add esi, 8 + jmp .next_resendq + + ;@@: mov byte[esi], 0xff ; XTODO: 0xff -> 0 + @@: mov dword[esi + 4], 0 + inc ecx + add esi, 8 + jmp .next_resendq + + .last_resendq: + popad + +;xxx ; was it a reset? +;xxx test [edx + 20 + TCP_PACKET.Flags], TH_RST +;xxx jz @f + +;xxx mov [ebx + SOCKET.TCBState], TCB_CLOSED +;xxx jmp .exit + + @@: ; Send an ACK to that fin, and enter closewait state + + mov [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT + lea esi, [ebx + SOCKET.RCV_NXT] + mov eax, [esi] ; save original + call inc_inet_esi + ;; jmp ste_ack - NO, there may be data + + .check_ack: + ; Check that we received an ACK + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit + ; TODO - done, I think! + ; First, look at the incoming window. If this is less than or equal to 1024, + ; Set the socket window timer to 1. This will stop an additional packets being queued. + ; ** I may need to tweak this value, since I do not know how many packets are already queued + mov cx, [edx + 20 + TCP_PACKET.Window] + xchg cl, ch + cmp cx, 1024 + ja @f + mov [ebx + SOCKET.wndsizeTimer], 1 -stateTCB_SYN_SENT: - ; We are awaiting an ACK to our SYN, with a SYM - ; Look at control flags - expecting an ACK - mov bl, [edx + 33] - and bl, 0x12 - cmp bl, 0x12 - jnz stss_exit + @@: ; OK, here is the deal + ; My recv.nct field holds the seq of the expected next rec byte + ; if the recevied sequence number is not equal to this, do not + ; increment the recv.nxt field, do not copy data - just send a + ; repeat ack. - mov ebx, TCB_ESTABLISHED - mov esi, [sktAddr] - mov [esi + 28], ebx + ; recv.nxt is in dword [edx+24], in inet format + ; recv seq is in [sktAddr]+56, in inet format + ; just do a comparision + mov ecx, [ebx + SOCKET.RCV_NXT] + cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT + jne @f + mov ecx, eax - ; Store the recv.nxt field - mov eax, [edx + 24] + @@: cmp ecx, [edx + 20 + TCP_PACKET.SequenceNumber] + jne .ack - ; Update our recv.nxt field - mov esi, [sktAddr] - add esi, 56 - mov [esi], eax - call inc_inet_esi - ; Send an ACK - ; Now construct the response, and queue for sending by IP - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je stss_exit + ; Read the data bytes, store in socket buffer + movzx ecx, [edx + IP_PACKET.TotalLength] + xchg cl, ch + sub ecx, 40 ; Discard 40 bytes of header + jnz .data ; Read data, if any + + ; If we had received a fin, we need to ACK it. + cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT + je .ack + jmp .exit + + .data: + push ecx + + add [ebx + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer + + mov eax, [ebx + SOCKET.PID] ; get socket owner PID + push eax + + mov eax, [ebx + SOCKET.rxDataCount] ; get # of bytes already in buffer + + ; point to the location to store the data + lea edi, [ebx + eax + SOCKETHEADERSIZE] + sub edi, ecx + + add edx, 40 ; edx now points to the data + mov esi, edx + + cld + rep movsb ; copy the data across + + ; flag an event to the application + pop eax + mov ecx, 1 + mov esi, TASK_DATA + TASKDATA.pid + + .next_pid: + cmp [esi], eax + je .found_pid + inc ecx + add esi, 0x20 + cmp ecx, [TASK_COUNT] + jbe .next_pid + + .found_pid: + shl ecx, 8 + or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event + + pop ecx + + ; Update our recv.nxt field + lea esi, [ebx + SOCKET.RCV_NXT] + call add_inet_esi + + .ack: + ; Send an ACK + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit + + push eax + + mov bl, TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] + + mov eax, NET1OUT_QUEUE + + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE - push eax + .not_local: + ; Send it. + pop ebx + call queue + + .exit: + ret +endp - mov bl, 0x10 ; ACK - mov ecx, 0 - mov esi, 0 - - call buildTCPPacket - - mov eax, NET1OUT_QUEUE - - mov edx, [stack_ip] - mov ecx, [ sktAddr ] - mov ecx, [ ecx + 16 ] - cmp edx, ecx - jne stss_notlocal - mov eax, IPIN_QUEUE - -stss_notlocal: - ; Send it. - pop ebx - call queue - -stss_exit: - ret - - - -stateTCB_SYN_RECEIVED: - ; In this case, we are expecting an ACK packet - ; For now, if the packet is an ACK, process it, - ; If not, ignore it - ; Look at control flags - expecting an ACK - mov bl, [edx + 33] - and bl, 0x10 - cmp bl, 0x10 - jnz stsr_exit +proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD + ; We can either receive an ACK of a fin, or a fin + mov al, [edx + 20 + TCP_PACKET.Flags] + and al, TH_FIN + TH_ACK - mov ebx, TCB_ESTABLISHED - mov esi, [sktAddr] - mov [esi + 28], ebx + cmp al, TH_ACK + jne @f -stsr_exit: - ret + ; It was an ACK + mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2 + jmp .exit + @@: mov [ebx + SOCKET.TCBState], TCB_CLOSING + cmp al, TH_FIN + je @f + mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT + @@: lea esi, [ebx + SOCKET.RCV_NXT] + call inc_inet_esi -stateTCB_ESTABLISHED: - ; Here we are expecting data, or a request to close - ; OR both... - - ; Did we receive a FIN or RST? - mov bl, [edx + 33] - and bl, 0x05 - cmp bl, 0 - je ste_chkack - - ; It was a fin or reset. + ; Send an ACK + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit - ; Remove resend entries from the queue - I dont want to send any more data - pusha + push eax - mov ebx, [sktAddr] - sub ebx, sockets - shr ebx, 12 ; get skt # + mov bl, TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] - mov esi, resendQ - mov ecx, 0 - -ste001: - cmp ecx, NUMRESENDENTRIES - je ste003 ; None left - cmp [esi], bl - je ste002 ; found one - inc ecx - add esi, 4 - jmp ste001 - -ste002: - dec dword [arp_rx_count] ; ************ TEST ONLY! + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE - mov [esi], byte 0xFF - jmp ste001 + .not_local: + ; Send it. + pop ebx + call queue -ste003: - popa + .exit: + ret +endp - ; was it a reset? - mov bl, [edx + 33] - and bl, 0x04 - cmp bl, 0x04 - jne ste003a - mov esi, [sktAddr] - mov ebx, TCB_CLOSED - mov [esi + 28], ebx - jmp ste_exit +proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD + test [edx + 20 + TCP_PACKET.Flags], TH_FIN + jz .exit -ste003a: - ; Send an ACK to that fin, and enter closewait state - - mov esi, [sktAddr] - mov ebx, TCB_CLOSE_WAIT - mov [esi + 28], ebx - add esi, 56 - mov eax, [esi] ; save original - call inc_inet_esi - ;; jmp ste_ack - NO, there may be data - -ste_chkack: - ; Check that we received an ACK - mov bl, [edx + 33] - and bl, 0x10 - cmp bl, 0x10 - jnz ste_exit + ; Change state, as we have a fin + mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT + lea esi, [ebx + SOCKET.RCV_NXT] + call inc_inet_esi - ; TODO - done, I think! - ; First, look at the incoming window. If this is less than or equal to 1024, - ; Set the socket window timer to 1. This will stop an additional packets being - ; queued. - ; ** I may need to tweak this value, since I do not know how many packets are already queued - mov ch, [edx + 34] - mov cl, [edx + 35] - cmp cx, 1024 - ja ste004 - - mov ecx, [sktAddr] - mov [ecx+72], dword 1 - -ste004: - - ; OK, here is the deal - ; My recv.nct field holds the seq of the expected next rec byte - ; if the recevied sequence number is not equal to this, do not - ; increment the recv.nxt field, do not copy data - just send a - ; repeat ack. - - ; recv.nxt is in dword [edx+24], in inext format - ; recv seq is in [sktAddr]+56, in inet format - ; just do a comparision - mov ecx, [sktAddr] - add ecx, 56 - - cmp [ecx - 56 + 28], dword TCB_CLOSE_WAIT - mov ecx, [ecx] - jne stenofin - mov ecx, eax - -stenofin: - cmp ecx, [edx+24] - jne ste_ack - - - ; Read the data bytes, store in socket buffer - xor ecx, ecx - mov ch, [edx + 2] - mov cl, [edx + 3] - sub ecx, 40 ; Discard 40 bytes of header - - cmp ecx, 0 - jnz ste_data ; Read data, if any - - ; If we had received a fin, we need to ACK it. - mov esi, [sktAddr] - mov ebx, [esi + 28] - cmp ebx, TCB_CLOSE_WAIT - jz ste_ack - jnz ste_exit - -ste_data: - push ecx - mov esi, [sktAddr] - - add [esi + 24], ecx ; increment the count of bytes in buffer - - mov eax, [esi + 4] ; get socket owner PID - push eax - - mov eax, [esi + 24] ; get # of bytes already in buffer - - ; point to the location to store the data - add esi, eax - sub esi, ecx - add esi, SOCKETHEADERSIZE - - add edx, 40 ; edx now points to the data - mov edi, esi - mov esi, edx - - cld - rep movsb ; copy the data across - - ; flag an event to the application - pop eax - mov ecx,1 - mov esi,TASK_DATA+TASKDATA.pid - -news: - cmp [esi],eax - je foundPID1 - inc ecx - add esi,0x20 - cmp ecx,[TASK_COUNT] - jbe news - -foundPID1: - shl ecx,8 - or dword [ecx+SLOT_BASE+APPDATA.event_mask],dword 10000000b ; stack event - - pop ecx - - ; Update our recv.nxt field - mov esi, [sktAddr] - add esi, 56 - call add_inet_esi - -ste_ack: - ; Send an ACK - ; Now construct the response, and queue for sending by IP - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je ste_exit + ; Send an ACK + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit - push eax + push eax - mov bl, 0x10 ; ACK - mov ecx, 0 - mov esi, 0 - - call buildTCPPacket - - mov eax, NET1OUT_QUEUE - - mov edx, [stack_ip] - mov ecx, [ sktAddr ] - mov ecx, [ ecx + 16 ] - cmp edx, ecx - jne ste_notlocal - mov eax, IPIN_QUEUE -ste_notlocal: + mov bl, TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] - ; Send it. - pop ebx - call queue + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE -ste_exit: - ret + .not_local: + ; Send it. + pop ebx + call queue + .exit: + ret +endp -stateTCB_FIN_WAIT_1: - ; We can either receive an ACK of a fin, or a fin - mov bl, [edx + 33] - and bl, 0x10 - cmp bl, 0x10 - jnz stfw1_001 +proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD + ; Intentionally left empty + ; socket_close_tcp handles this + ret +endp - ; It was an ACK - mov esi, [sktAddr] - mov ebx, TCB_FIN_WAIT_2 - mov [esi + 28], ebx - jmp stfw1_exit -stfw1_001: - ; It must be a fin then - mov esi, [sktAddr] - mov ebx, TCB_CLOSING - mov [esi + 28], ebx - add esi, 56 - call inc_inet_esi +proc stateTCB_CLOSING stdcall, sockAddr:DWORD + ; We can either receive an ACK of a fin, or a fin + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit - ; Send an ACK - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je stfw1_exit + mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT - push eax + .exit: + ret +endp - mov bl, 0x10 ; ACK - mov ecx, 0 - mov esi, 0 - call buildTCPPacket - mov eax, NET1OUT_QUEUE +proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD + ; Look at control flags - expecting an ACK + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit - mov edx, [stack_ip] - mov ecx, [ sktAddr ] - mov ecx, [ ecx + 16 ] - cmp edx, ecx - jne stfw1_notlocal - mov eax, IPIN_QUEUE + ; delete the socket + stdcall net_socket_free, ebx +; mov edi, ebx +; xor eax, eax +; mov ecx, SOCKETHEADERSIZE +; cld +; rep stosb -stfw1_notlocal: - ; Send it. - pop ebx - call queue + .exit: + ret +endp -stfw1_exit: - ret +proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD + ret +endp -stateTCB_FIN_WAIT_2: - mov esi, [sktAddr] - - ; Get data length - xor ecx, ecx - mov ch, [edx+2] - mov cl, [edx+3] - sub ecx, 40 - - mov bl, [edx + 33] - and bl, 0x01 - cmp bl, 0x01 - jne stfw2001 - - ; Change state, as we have a fin - mov ebx, TCB_TIME_WAIT - mov [esi + 28], ebx - - inc ecx ; FIN is part of the sequence space - -stfw2001: - add esi, 56 - call add_inet_esi - - ; Send an ACK - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je stfw2_exit - - push eax - - mov bl, 0x10 ; ACK - mov ecx, 0 - mov esi, 0 - - call buildTCPPacket - - mov eax, NET1OUT_QUEUE - - mov edx, [stack_ip] - mov ecx, [ sktAddr ] - mov ecx, [ ecx + 16 ] - cmp edx, ecx - jne stfw2_notlocal - mov eax, IPIN_QUEUE - -stfw2_notlocal: - ; Send it. - pop ebx - call queue - - ; Only delete the socket if we received the FIN - - mov edx, [sktAddr] - mov bl, [edx + 33] - and bl, 0x01 - cmp bl, 0x01 - jne stfw2_exit - -; mov edi, [sktAddr] - - ; delete the socket. Should really wait for 2MSL -; xor eax, eax -; mov ecx,SOCKETHEADERSIZE -; cld -; rep stosb - -stfw2_exit: - ret - - - -stateTCB_CLOSE_WAIT: - ; Intentionally left empty - ; socket_close_tcp handles this - ret - - - -stateTCB_CLOSING: - ; We can either receive an ACK of a fin, or a fin - mov bl, [edx + 33] - and bl, 0x10 - cmp bl, 0x10 - jnz stc_exit - - ; It was an ACK - - mov edi, [sktAddr] - - ; delete the socket - xor eax, eax - mov ecx,SOCKETHEADERSIZE - cld - rep stosb - -stc_exit: - ret - - - -stateTCB_LAST_ACK: - ; Look at control flags - expecting an ACK - mov bl, [edx + 33] - and bl, 0x10 - cmp bl, 0x10 - jnz stla_exit - - mov edi, [sktAddr] - - ; delete the socket - xor eax, eax - mov ecx,SOCKETHEADERSIZE - cld - rep stosb - -stla_exit: - ret - - - -stateTCB_TIME_WAIT: - ret - - - -stateTCB_CLOSED: - ret +proc stateTCB_CLOSED stdcall, sockAddr:DWORD + ret +endp diff --git a/kernel/trunk/network/udp.inc b/kernel/trunk/network/udp.inc index a6416c37f7..22efbbfe17 100644 --- a/kernel/trunk/network/udp.inc +++ b/kernel/trunk/network/udp.inc @@ -47,11 +47,11 @@ $Revision$ ; struc UDP_PACKET -{ .SourcePort dw ? ;+00 +{ .SourcePort dw ? ;+00 .DestinationPort dw ? ;+02 - .Length dw ? ;+04 - Length of (UDP Header + Data) - .Checksum dw ? ;+06 - .Data db ? ;+08 + .Length dw ? ;+04 - Length of (UDP Header + Data) + .Checksum dw ? ;+06 + .Data db ? ;+08 } virtual at 0 @@ -71,103 +71,93 @@ end virtual ; Free up (or re-use) IP buffer when finished ; ;*************************************************************************** -udp_rx: - push eax - ; First validate the header & checksum. Discard buffer if error +proc udp_rx stdcall + push eax - ; Look for a socket where - ; IP Packet UDP Destination Port = local Port - ; IP Packet SA = Remote IP + ; First validate the header & checksum. Discard buffer if error - movzx ebx, word [edx + 22] ; get the local port from - ; the IP packet's UDP header - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS + ; Look for a socket where + ; IP Packet UDP Destination Port = local Port + ; IP Packet SA = Remote IP -fs1: - sub eax, SOCKETBUFFSIZE - cmp [eax + sockets + 12], bx ; bx will hold the 'wrong' value, - ; but the comparision is correct - loopnz fs1 ; Return back if no match - jz fs_done + mov ax, [edx + 20 + UDP_PACKET.DestinationPort] ; get the local port from + ; the IP packet's UDP header - ; No match, so exit - jmp udprx_001 + mov ebx, net_sockets_mutex + call wait_mutex + mov ebx, net_sockets -fs_done: - ; For dhcp, we must allow any remote server to respond. - ; I will accept the first incoming response to be the one - ; I bind to, if the socket is opened with a destination IP address of - ; 255.255.255.255 - mov ebx, [eax + sockets + 16] - cmp ebx, 0xffffffff - je udprx_002 + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .exit ; No match, so exit + cmp [ebx + SOCKET.LocalPort], ax ; ax will hold the 'wrong' value, + ; but the comparision is correct + jne .next_socket ; Return back if no match - mov ebx, [edx + 12] ; get the Source address from the IP packet - cmp [eax + sockets + 16], ebx - jne udprx_001 ; Quit if the source IP is not valid + ; For dhcp, we must allow any remote server to respond. + ; I will accept the first incoming response to be the one + ; I bind to, if the socket is opened with a destination IP address of + ; 255.255.255.255 + cmp [ebx + SOCKET.RemoteIP], 0xffffffff + je @f -udprx_002: - ; OK - we have a valid UDP packet for this socket. - ; First, update the sockets remote port number with the incoming msg - ; - it will have changed - ; from the original ( 69 normally ) to allow further connects - movzx ebx, word [edx + 20] ; get the UDP source port - ; ( was 69, now new ) - mov [eax + sockets + 20], bx + mov eax, [edx + IP_PACKET.SourceAddress] ; get the Source address from the IP packet + cmp [ebx + SOCKET.RemoteIP], ebx + jne .exit ; Quit if the source IP is not valid - ; Now, copy data to socket. We have socket address as [eax + sockets]. - ; We have IP packet in edx + @@: ; OK - we have a valid UDP packet for this socket. + ; First, update the sockets remote port number with the incoming msg + ; - it will have changed + ; from the original ( 69 normally ) to allow further connects + mov ax, [edx + 20 + UDP_PACKET.SourcePort] ; get the UDP source port + ; ( was 69, now new ) + mov [ebx + SOCKET.RemotePort], ax - ; get # of bytes in ecx - movzx ecx, byte [edx + 3] ; total length of IP packet. Subtract - mov ch, byte [edx + 2] ; 20 + 8 gives data length - sub ecx, 28 + ; Now, copy data to socket. We have socket address as [eax + sockets]. + ; We have IP packet in edx - mov ebx, eax - add ebx, sockets ; ebx = address of actual socket + ; get # of bytes in ecx + movzx ecx, [edx + IP_PACKET.TotalLength] ; total length of IP packet. Subtract + xchg cl, ch ; 20 + 8 gives data length + sub ecx, 28 - mov eax, [ebx+ 4] ; get socket owner PID - push eax + mov eax, [ebx + SOCKET.rxDataCount] ; get # of bytes already in buffer + add [ebx + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer - mov eax, [ebx + 24] ; get # of bytes already in buffer - add [ebx + 24], ecx ; increment the count of bytes in buffer + ; ecx has count, edx points to data - ; point to the location to store the data - add ebx, eax - add ebx, SOCKETHEADERSIZE + add edx, 28 ; edx now points to the data + lea edi, [ebx + eax + SOCKETHEADERSIZE] + mov esi, edx - ; ebx = location for first byte, ecx has count, - ; edx points to data + cld + rep movsb ; copy the data across - add edx, 28 ; edx now points to the data - mov edi, ebx - mov esi, edx + ; flag an event to the application + mov eax, [ebx + SOCKET.PID] ; get socket owner PID + mov ecx, 1 + mov esi, TASK_DATA + TASKDATA.pid - cld - rep movsb ; copy the data across + .next_pid: + cmp [esi], eax + je .found_pid + inc ecx + add esi, 0x20 + cmp ecx, [TASK_COUNT] + jbe .next_pid - ; flag an event to the application - pop eax - mov ecx,1 - mov esi,TASK_DATA+TASKDATA.pid + jmp .exit -newsearch: - cmp [esi],eax - je foundPID - inc ecx - add esi,0x20 - cmp ecx,[TASK_COUNT] - jbe newsearch + .found_pid: + shl ecx, 8 + or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event -foundPID: - shl ecx,8 - or dword [ecx+SLOT_BASE+APPDATA.event_mask],dword 10000000b ; stack event + mov [check_idle_semaphore], 200 - mov [check_idle_semaphore],200 - -udprx_001: - pop eax - call freeBuff ; Discard the packet - ret + .exit: + pop eax + call freeBuff ; Discard the packet + ret +endp