Rev 2288 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2288 | Rev 2381 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;; TCP.INC ;; |
6 | ;; TCP.INC ;; |
7 | ;; ;; |
7 | ;; ;; |
8 | ;; TCP Processes for Menuet OS TCP/IP stack ;; |
8 | ;; TCP Processes for Menuet OS TCP/IP stack ;; |
9 | ;; ;; |
9 | ;; ;; |
10 | ;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
10 | ;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
11 | ;; ;; |
11 | ;; ;; |
12 | ;; See file COPYING for details ;; |
12 | ;; See file COPYING for details ;; |
13 | ;; v0.6 : Added reset handling in the established state ;; |
13 | ;; v0.6 : Added reset handling in the established state ;; |
14 | ;; Added a timer per socket to allow delays when ;; |
14 | ;; Added a timer per socket to allow delays when ;; |
15 | ;; rx window gets below 1KB ;; |
15 | ;; rx window gets below 1KB ;; |
16 | ;; ;; |
16 | ;; ;; |
17 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
17 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
18 | 18 | ||
19 | $Revision: 2288 $ |
19 | $Revision: 2381 $ |
20 | 20 | ||
21 | 21 | ||
22 | ; TCP TCB states |
22 | ; TCP TCB states |
23 | TCB_LISTEN equ 1 |
23 | TCB_LISTEN equ 1 |
24 | TCB_SYN_SENT equ 2 |
24 | TCB_SYN_SENT equ 2 |
25 | TCB_SYN_RECEIVED equ 3 |
25 | TCB_SYN_RECEIVED equ 3 |
26 | TCB_ESTABLISHED equ 4 |
26 | TCB_ESTABLISHED equ 4 |
27 | TCB_FIN_WAIT_1 equ 5 |
27 | TCB_FIN_WAIT_1 equ 5 |
28 | TCB_FIN_WAIT_2 equ 6 |
28 | TCB_FIN_WAIT_2 equ 6 |
29 | TCB_CLOSE_WAIT equ 7 |
29 | TCB_CLOSE_WAIT equ 7 |
30 | TCB_CLOSING equ 8 |
30 | TCB_CLOSING equ 8 |
31 | TCB_LAST_ACK equ 9 |
31 | TCB_LAST_ACK equ 9 |
32 | TCB_TIMED_WAIT equ 10 |
32 | TCB_TIMED_WAIT equ 10 |
33 | TCB_CLOSED equ 11 |
33 | TCB_CLOSED equ 11 |
34 | 34 | ||
35 | TH_FIN = 0x01 |
35 | TH_FIN = 0x01 |
36 | TH_SYN = 0x02 |
36 | TH_SYN = 0x02 |
37 | TH_RST = 0x04 |
37 | TH_RST = 0x04 |
38 | TH_PUSH = 0x08 |
38 | TH_PUSH = 0x08 |
39 | TH_ACK = 0x10 |
39 | TH_ACK = 0x10 |
40 | TH_URG = 0x20 |
40 | TH_URG = 0x20 |
41 | 41 | ||
42 | TWOMSL equ 10 ; # of secs to wait before closing socket |
42 | TWOMSL equ 10 ; # of secs to wait before closing socket |
43 | 43 | ||
44 | TCP_RETRIES equ 5 ; Number of times to resend a packet |
44 | TCP_RETRIES equ 5 ; Number of times to resend a packet |
45 | TCP_TIMEOUT equ 20 ; resend if not replied to in x hs |
45 | TCP_TIMEOUT equ 20 ; resend if not replied to in x hs |
46 | 46 | ||
47 | ;******************************************************************* |
47 | ;******************************************************************* |
48 | ; Interface |
48 | ; Interface |
49 | ; |
49 | ; |
50 | ; tcp_tx_handler Handles the TCP transmit queue |
50 | ; tcp_tx_handler Handles the TCP transmit queue |
51 | ; tcp_rx The protocol handler for received data |
51 | ; tcp_rx The protocol handler for received data |
52 | ; buildTCPPacket fills in the packet headers and data |
52 | ; buildTCPPacket fills in the packet headers and data |
53 | ; tcpStateMachine Main state machine for received TCP packets |
53 | ; tcpStateMachine Main state machine for received TCP packets |
54 | ; tcp_tcb_handler 1s timer, to erase tcb's in TIME_WAIT state |
54 | ; tcp_tcb_handler 1s timer, to erase tcb's in TIME_WAIT state |
55 | ; |
55 | ; |
56 | ;******************************************************************* |
56 | ;******************************************************************* |
57 | 57 | ||
58 | 58 | ||
59 | ; TCP Payload ( Data field in IP datagram ) |
59 | ; TCP Payload ( Data field in IP datagram ) |
60 | ; |
60 | ; |
61 | ; 0 1 2 3 |
61 | ; 0 1 2 3 |
62 | ; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
62 | ; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
63 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
63 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
64 | ;20 | Source Port | Destination Port | |
64 | ;20 | Source Port | Destination Port | |
65 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
65 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
66 | ;24 | Sequence Number | |
66 | ;24 | Sequence Number | |
67 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
67 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
68 | ;28 | Acknowledgment Number | |
68 | ;28 | Acknowledgment Number | |
69 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
69 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
70 | ;32 | Data | |U|A|P|R|S|F| | |
70 | ;32 | Data | |U|A|P|R|S|F| | |
71 | ; | Offset| Reserved |R|C|S|S|Y|I| Window | |
71 | ; | Offset| Reserved |R|C|S|S|Y|I| Window | |
72 | ; | | |G|K|H|T|N|N| | |
72 | ; | | |G|K|H|T|N|N| | |
73 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
73 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
74 | ;36 | Checksum | Urgent Pointer | |
74 | ;36 | Checksum | Urgent Pointer | |
75 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
75 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
76 | ;40 | Options | Padding | |
76 | ;40 | Options | Padding | |
77 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
77 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
78 | ; | data |
78 | ; | data |
79 | 79 | ||
80 | 80 | ||
81 | struc TCP_PACKET |
81 | struc TCP_PACKET |
82 | { .SourcePort dw ? ;+00 |
82 | { .SourcePort dw ? ;+00 |
83 | .DestinationPort dw ? ;+02 |
83 | .DestinationPort dw ? ;+02 |
84 | .SequenceNumber dd ? ;+04 |
84 | .SequenceNumber dd ? ;+04 |
85 | .AckNumber dd ? ;+08 |
85 | .AckNumber dd ? ;+08 |
86 | .DataOffset db ? ;+12 - DataOffset[0-3 bits] and Reserved[4-7] |
86 | .DataOffset db ? ;+12 - DataOffset[0-3 bits] and Reserved[4-7] |
87 | .Flags db ? ;+13 - Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN |
87 | .Flags db ? ;+13 - Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN |
88 | .Window dw ? ;+14 |
88 | .Window dw ? ;+14 |
89 | .Checksum dw ? ;+16 |
89 | .Checksum dw ? ;+16 |
90 | .UrgentPointer dw ? ;+18 |
90 | .UrgentPointer dw ? ;+18 |
91 | .Options rb 3 ;+20 |
91 | .Options rb 3 ;+20 |
92 | .Padding db ? ;+23 |
92 | .Padding db ? ;+23 |
93 | .Data db ? ;+24 |
93 | .Data db ? ;+24 |
94 | } |
94 | } |
95 | 95 | ||
96 | virtual at 0 |
96 | virtual at 0 |
97 | TCP_PACKET TCP_PACKET |
97 | TCP_PACKET TCP_PACKET |
98 | end virtual |
98 | end virtual |
99 | 99 | ||
100 | 100 | ||
101 | 101 | ||
102 | ;*************************************************************************** |
102 | ;*************************************************************************** |
103 | ; Function |
103 | ; Function |
104 | ; tcp_tcb_handler |
104 | ; tcp_tcb_handler |
105 | ; |
105 | ; |
106 | ; Description |
106 | ; Description |
107 | ; Handles sockets in the timewait state, closing them |
107 | ; Handles sockets in the timewait state, closing them |
108 | ; when the TCB timer expires |
108 | ; when the TCB timer expires |
109 | ; |
109 | ; |
110 | ;*************************************************************************** |
110 | ;*************************************************************************** |
111 | 111 | ||
112 | proc tcp_tcb_handler stdcall uses ebx |
112 | proc tcp_tcb_handler stdcall uses ebx |
113 | ; scan through all the sockets, decrementing active timers |
113 | ; scan through all the sockets, decrementing active timers |
114 | 114 | ||
115 | mov ebx, net_sockets |
115 | mov ebx, net_sockets |
116 | 116 | ||
117 | cmp [ebx + SOCKET.NextPtr], 0 |
117 | cmp [ebx + SOCKET.NextPtr], 0 |
118 | je .exit |
118 | je .exit |
119 | ;DEBUGF 1, "K : sockets:\n" |
119 | ;DEBUGF 1, "K : sockets:\n" |
120 | 120 | ||
121 | .next_socket: |
121 | .next_socket: |
122 | mov ebx, [ebx + SOCKET.NextPtr] |
122 | mov ebx, [ebx + SOCKET.NextPtr] |
123 | or ebx, ebx |
123 | or ebx, ebx |
124 | jz .exit |
124 | jz .exit |
125 | 125 | ||
126 | ;DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] |
126 | ;DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] |
127 | 127 | ||
128 | cmp [ebx + SOCKET.TCBTimer], 0 |
128 | cmp [ebx + SOCKET.TCBTimer], 0 |
129 | jne .decrement_tcb |
129 | jne .decrement_tcb |
130 | cmp [ebx + SOCKET.wndsizeTimer], 0 |
130 | cmp [ebx + SOCKET.wndsizeTimer], 0 |
131 | jne .decrement_wnd |
131 | jne .decrement_wnd |
132 | jmp .next_socket |
132 | jmp .next_socket |
133 | 133 | ||
134 | .decrement_tcb: |
134 | .decrement_tcb: |
135 | ; decrement it, delete socket if TCB timer = 0 & socket in timewait state |
135 | ; decrement it, delete socket if TCB timer = 0 & socket in timewait state |
136 | dec [ebx + SOCKET.TCBTimer] |
136 | dec [ebx + SOCKET.TCBTimer] |
137 | jnz .next_socket |
137 | jnz .next_socket |
138 | 138 | ||
139 | cmp [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
139 | cmp [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
140 | jne .next_socket |
140 | jne .next_socket |
141 | 141 | ||
142 | push [ebx + SOCKET.PrevPtr] |
142 | push [ebx + SOCKET.PrevPtr] |
143 | stdcall net_socket_free, ebx |
143 | stdcall net_socket_free, ebx |
144 | pop ebx |
144 | pop ebx |
145 | jmp .next_socket |
145 | jmp .next_socket |
146 | 146 | ||
147 | .decrement_wnd: |
147 | .decrement_wnd: |
148 | ; TODO - prove it works! |
148 | ; TODO - prove it works! |
149 | dec [ebx + SOCKET.wndsizeTimer] |
149 | dec [ebx + SOCKET.wndsizeTimer] |
150 | jmp .next_socket |
150 | jmp .next_socket |
151 | 151 | ||
152 | .exit: |
152 | .exit: |
153 | ret |
153 | ret |
154 | endp |
154 | endp |
155 | 155 | ||
156 | 156 | ||
157 | ;*************************************************************************** |
157 | ;*************************************************************************** |
158 | ; Function |
158 | ; Function |
159 | ; tcp_tx_handler |
159 | ; tcp_tx_handler |
160 | ; |
160 | ; |
161 | ; Description |
161 | ; Description |
162 | ; Handles queued TCP data |
162 | ; Handles queued TCP data |
163 | ; This is a kernel function, called by stack_handler |
163 | ; This is a kernel function, called by stack_handler |
164 | ; |
164 | ; |
165 | ;*************************************************************************** |
165 | ;*************************************************************************** |
166 | 166 | ||
167 | proc tcp_tx_handler stdcall |
167 | proc tcp_tx_handler stdcall |
168 | ; decrement all resend buffers timers. If they |
168 | ; decrement all resend buffers timers. If they |
169 | ; expire, queue them for sending, and restart the timer. |
169 | ; expire, queue them for sending, and restart the timer. |
170 | ; If the retries counter reach 0, delete the entry |
170 | ; If the retries counter reach 0, delete the entry |
171 | 171 | ||
172 | mov esi, resendQ |
172 | mov esi, resendQ |
173 | mov ecx, 0 |
173 | mov ecx, 0 |
174 | 174 | ||
175 | .next_resendq: |
175 | .next_resendq: |
176 | cmp ecx, NUMRESENDENTRIES |
176 | cmp ecx, NUMRESENDENTRIES |
177 | je .exit ; None left |
177 | je .exit ; None left |
178 | cmp dword[esi + 4], 0 |
178 | cmp dword[esi + 4], 0 |
179 | jne @f ; found one |
179 | jne @f ; found one |
180 | inc ecx |
180 | inc ecx |
181 | add esi, 8 |
181 | add esi, 8 |
182 | jmp .next_resendq |
182 | jmp .next_resendq |
183 | 183 | ||
184 | @@: ; we have one. decrement it's timer by 1 |
184 | @@: ; we have one. decrement it's timer by 1 |
185 | dec word[esi + 2] |
185 | dec word[esi + 2] |
186 | jz @f |
186 | jz @f |
187 | inc ecx |
187 | inc ecx |
188 | add esi, 8 |
188 | add esi, 8 |
189 | jmp .next_resendq ; Timer not zero, so move on |
189 | jmp .next_resendq ; Timer not zero, so move on |
190 | 190 | ||
191 | @@: |
191 | @@: |
192 | xor ebx, ebx |
192 | xor ebx, ebx |
193 | ; restart timer, and decrement retries |
193 | ; restart timer, and decrement retries |
194 | ; After the first resend, back of on next, by a factor of 5 |
194 | ; After the first resend, back of on next, by a factor of 5 |
195 | mov [esi + 2], word TCP_TIMEOUT * 5 |
195 | mov [esi + 2], word TCP_TIMEOUT * 5 |
196 | dec byte[esi + 1] |
196 | dec byte[esi + 1] |
197 | jnz @f |
197 | jnz @f |
198 | 198 | ||
199 | ; retries now 0, so delete from queue |
199 | ; retries now 0, so delete from queue |
200 | xchg [esi + 4], ebx |
200 | xchg [esi + 4], ebx |
201 | 201 | ||
202 | @@: ; resend packet |
202 | @@: ; resend packet |
203 | pushad |
203 | pushad |
204 | 204 | ||
205 | mov eax, EMPTY_QUEUE |
205 | mov eax, EMPTY_QUEUE |
206 | call dequeue |
206 | call dequeue |
207 | cmp ax, NO_BUFFER |
207 | cmp ax, NO_BUFFER |
208 | jne .tth004z |
208 | jne .tth004z |
209 | 209 | ||
210 | ; TODO - try again in 10ms. |
210 | ; TODO - try again in 10ms. |
211 | test ebx, ebx |
211 | test ebx, ebx |
212 | jnz @f |
212 | jnz @f |
213 | mov [esi + 4], ebx |
213 | mov [esi + 4], ebx |
214 | 214 | ||
215 | @@: ; Mark it to expire in 10ms - 1 tick |
215 | @@: ; Mark it to expire in 10ms - 1 tick |
216 | mov byte[esi + 1], 1 |
216 | mov byte[esi + 1], 1 |
217 | mov word[esi + 2], 1 |
217 | mov word[esi + 2], 1 |
218 | jmp .tth005 |
218 | jmp .tth005 |
219 | 219 | ||
220 | .tth004z: |
220 | .tth004z: |
221 | ; we have a buffer # in ax |
221 | ; we have a buffer # in ax |
222 | push eax ecx |
222 | push eax ecx |
223 | mov ecx, IPBUFFSIZE |
223 | mov ecx, IPBUFFSIZE |
224 | mul ecx |
224 | mul ecx |
225 | add eax, IPbuffs |
225 | add eax, IPbuffs |
226 | 226 | ||
227 | ; we have the buffer address in eax |
227 | ; we have the buffer address in eax |
228 | mov edi, eax |
228 | mov edi, eax |
229 | pop ecx |
229 | pop ecx |
230 | ; Now get buffer location, and copy buffer across. argh! more copying,, |
230 | ; Now get buffer location, and copy buffer across. argh! more copying,, |
231 | imul esi, ecx, IPBUFFSIZE |
231 | imul esi, ecx, IPBUFFSIZE |
232 | add esi, resendBuffer |
232 | add esi, resendBuffer |
233 | 233 | ||
234 | ; we have resend buffer location in esi |
234 | ; we have resend buffer location in esi |
235 | mov ecx, IPBUFFSIZE |
235 | mov ecx, IPBUFFSIZE |
236 | 236 | ||
237 | ; copy data across |
237 | ; copy data across |
238 | push edi |
238 | push edi |
239 | cld |
239 | cld |
240 | rep movsb |
240 | rep movsb |
241 | pop edi |
241 | pop edi |
242 | 242 | ||
243 | ; queue packet |
243 | ; queue packet |
244 | mov eax, NET1OUT_QUEUE |
244 | mov eax, NET1OUT_QUEUE |
245 | mov edx, [stack_ip] |
245 | mov edx, [stack_ip] |
246 | cmp edx, [edi + IP_PACKET.DestinationAddress] |
246 | cmp edx, [edi + IP_PACKET.DestinationAddress] |
247 | jne .not_local |
247 | jne .not_local |
248 | mov eax, IPIN_QUEUE |
248 | mov eax, IPIN_QUEUE |
249 | 249 | ||
250 | .not_local: |
250 | .not_local: |
251 | pop ebx |
251 | pop ebx |
252 | call queue |
252 | call queue |
253 | 253 | ||
254 | .tth005: |
254 | .tth005: |
255 | popad |
255 | popad |
256 | 256 | ||
257 | inc ecx |
257 | inc ecx |
258 | add esi, 8 |
258 | add esi, 8 |
259 | jmp .next_resendq |
259 | jmp .next_resendq |
260 | 260 | ||
261 | .exit: |
261 | .exit: |
262 | ret |
262 | ret |
263 | endp |
263 | endp |
264 | 264 | ||
265 | 265 | ||
266 | ;*************************************************************************** |
266 | ;*************************************************************************** |
267 | ; Function |
267 | ; Function |
268 | ; tcp_rx |
268 | ; tcp_rx |
269 | ; |
269 | ; |
270 | ; Description |
270 | ; Description |
271 | ; TCP protocol handler |
271 | ; TCP protocol handler |
272 | ; This is a kernel function, called by ip_rx |
272 | ; This is a kernel function, called by ip_rx |
273 | ; IP buffer address given in edx |
273 | ; IP buffer address given in edx |
274 | ; IP buffer number in eax |
274 | ; IP buffer number in eax |
275 | ; Free up (or re-use) IP buffer when finished |
275 | ; Free up (or re-use) IP buffer when finished |
276 | ; |
276 | ; |
277 | ;*************************************************************************** |
277 | ;*************************************************************************** |
278 | 278 | ||
279 | proc tcp_rx stdcall uses ebx |
279 | proc tcp_rx stdcall uses ebx |
280 | ; The process is as follows. |
280 | ; The process is as follows. |
281 | ; Look for a socket with matching remote IP, remote port, local port |
281 | ; Look for a socket with matching remote IP, remote port, local port |
282 | ; if not found, then |
282 | ; if not found, then |
283 | ; look for remote IP + local port match ( where sockets remote port = 0) |
283 | ; look for remote IP + local port match ( where sockets remote port = 0) |
284 | ; if not found, then |
284 | ; if not found, then |
285 | ; look for a socket where local socket port == IP packets remote port |
285 | ; look for a socket where local socket port == IP packets remote port |
286 | ; where sockets remote port, remote IP = 0 |
286 | ; where sockets remote port, remote IP = 0 |
287 | ; discard if not found |
287 | ; discard if not found |
288 | ; Call sockets tcbStateMachine, with pointer to packet. |
288 | ; Call sockets tcbStateMachine, with pointer to packet. |
289 | ; the state machine will not delete the packet, so do that here. |
289 | ; the state machine will not delete the packet, so do that here. |
290 | 290 | ||
291 | push eax |
291 | push eax |
292 | 292 | ||
293 | ; Look for a socket where |
293 | ; Look for a socket where |
294 | ; IP Packet TCP Destination Port = local Port |
294 | ; IP Packet TCP Destination Port = local Port |
295 | ; IP Packet SA = Remote IP |
295 | ; IP Packet SA = Remote IP |
296 | ; IP Packet TCP Source Port = remote Port |
296 | ; IP Packet TCP Source Port = remote Port |
297 | 297 | ||
298 | mov ebx, net_sockets |
298 | mov ebx, net_sockets |
299 | 299 | ||
300 | .next_socket.1: |
300 | .next_socket.1: |
301 | mov ebx, [ebx + SOCKET.NextPtr] |
301 | mov ebx, [ebx + SOCKET.NextPtr] |
302 | or ebx, ebx |
302 | or ebx, ebx |
303 | jz .next_socket.1.exit |
303 | jz .next_socket.1.exit |
304 | 304 | ||
305 | ; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
305 | ; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
306 | 306 | ||
307 | mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr |
307 | mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr |
308 | cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr |
308 | cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr |
309 | jne .next_socket.1 ; different - try next socket |
309 | jne .next_socket.1 ; different - try next socket |
310 | 310 | ||
311 | ; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] |
311 | ; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] |
312 | 312 | ||
313 | mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr |
313 | mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr |
314 | cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP |
314 | cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP |
315 | jne .next_socket.1 ; different - try next socket |
315 | jne .next_socket.1 ; different - try next socket |
316 | 316 | ||
317 | ; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_PACKET.SourcePort]:4, [ebx + SOCKET.RemotePort]:4 |
317 | ; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_PACKET.SourcePort]:4, [ebx + SOCKET.RemotePort]:4 |
318 | 318 | ||
319 | mov ax, [edx + 20 + TCP_PACKET.SourcePort] ; get the source port from the TCP hdr |
319 | mov ax, [edx + 20 + TCP_PACKET.SourcePort] ; get the source port from the TCP hdr |
320 | cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port |
320 | cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port |
321 | jne .next_socket.1 ; different - try next socket |
321 | jne .next_socket.1 ; different - try next socket |
322 | 322 | ||
323 | ; We have a complete match - use this socket |
323 | ; We have a complete match - use this socket |
324 | jmp .change_state |
324 | jmp .change_state |
325 | 325 | ||
326 | .next_socket.1.exit: |
326 | .next_socket.1.exit: |
327 | 327 | ||
328 | ; If we got here, there was no match |
328 | ; If we got here, there was no match |
329 | ; Look for a socket where |
329 | ; Look for a socket where |
330 | ; IP Packet TCP Destination Port = local Port |
330 | ; IP Packet TCP Destination Port = local Port |
331 | ; IP Packet SA = Remote IP |
331 | ; IP Packet SA = Remote IP |
332 | ; socket remote Port = 0 |
332 | ; socket remote Port = 0 |
333 | 333 | ||
334 | mov ebx, net_sockets |
334 | mov ebx, net_sockets |
335 | 335 | ||
336 | .next_socket.2: |
336 | .next_socket.2: |
337 | mov ebx, [ebx + SOCKET.NextPtr] |
337 | mov ebx, [ebx + SOCKET.NextPtr] |
338 | or ebx, ebx |
338 | or ebx, ebx |
339 | jz .next_socket.2.exit |
339 | jz .next_socket.2.exit |
340 | 340 | ||
341 | ; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
341 | ; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
342 | 342 | ||
343 | mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr |
343 | mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr |
344 | cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
344 | cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
345 | jne .next_socket.2 ; different - try next socket |
345 | jne .next_socket.2 ; different - try next socket |
346 | 346 | ||
347 | ; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] |
347 | ; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] |
348 | 348 | ||
349 | mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr |
349 | mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr |
350 | cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP |
350 | cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP |
351 | jne .next_socket.2 ; different - try next socket |
351 | jne .next_socket.2 ; different - try next socket |
352 | 352 | ||
353 | ; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 |
353 | ; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 |
354 | 354 | ||
355 | cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 |
355 | cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 |
356 | jne .next_socket.2 ; different - try next socket |
356 | jne .next_socket.2 ; different - try next socket |
357 | 357 | ||
358 | ; We have a complete match - use this socket |
358 | ; We have a complete match - use this socket |
359 | jmp .change_state |
359 | jmp .change_state |
360 | 360 | ||
361 | .next_socket.2.exit: |
361 | .next_socket.2.exit: |
362 | 362 | ||
363 | ; If we got here, there was no match |
363 | ; If we got here, there was no match |
364 | ; Look for a socket where |
364 | ; Look for a socket where |
365 | ; IP Packet TCP Destination Port = local Port |
365 | ; IP Packet TCP Destination Port = local Port |
366 | ; socket Remote IP = 0 |
366 | ; socket Remote IP = 0 |
367 | ; socket remote Port = 0 |
367 | ; socket remote Port = 0 |
368 | 368 | ||
369 | mov ebx, net_sockets |
369 | mov ebx, net_sockets |
370 | 370 | ||
371 | .next_socket.3: |
371 | .next_socket.3: |
372 | mov ebx, [ebx + SOCKET.NextPtr] |
372 | mov ebx, [ebx + SOCKET.NextPtr] |
373 | or ebx, ebx |
373 | or ebx, ebx |
374 | jz .next_socket.3.exit |
374 | jz .next_socket.3.exit |
375 | 375 | ||
376 | ; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
376 | ; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
377 | 377 | ||
378 | mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get destination port from the TCP hdr |
378 | mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get destination port from the TCP hdr |
379 | cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
379 | cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
380 | jne .next_socket.3 ; different - try next socket |
380 | jne .next_socket.3 ; different - try next socket |
381 | 381 | ||
382 | ; DEBUGF 1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP] |
382 | ; DEBUGF 1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP] |
383 | 383 | ||
384 | cmp [ebx + SOCKET.RemoteIP], 0 ; only match a socket remote IP of 0 |
384 | cmp [ebx + SOCKET.RemoteIP], 0 ; only match a socket remote IP of 0 |
385 | jne .next_socket.3 ; different - try next socket |
385 | jne .next_socket.3 ; different - try next socket |
386 | 386 | ||
387 | ; DEBUGF 1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 |
387 | ; DEBUGF 1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 |
388 | 388 | ||
389 | cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 |
389 | cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 |
390 | jne .next_socket.3 ; different - try next socket |
390 | jne .next_socket.3 ; different - try next socket |
391 | 391 | ||
392 | ; We have a complete match - use this socket |
392 | ; We have a complete match - use this socket |
393 | jmp .change_state |
393 | jmp .change_state |
394 | 394 | ||
395 | .next_socket.3.exit: |
395 | .next_socket.3.exit: |
396 | 396 | ||
397 | ; If we got here, we need to reject the packet |
397 | ; If we got here, we need to reject the packet |
398 | 398 | ||
399 | DEBUGF 1, "K : tcp_rx - dumped\n" |
399 | DEBUGF 1, "K : tcp_rx - dumped\n" |
400 | 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 |
400 | 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 |
401 | 401 | ||
402 | inc [dumped_rx_count] |
402 | inc [dumped_rx_count] |
403 | jmp .exit |
403 | jmp .exit |
404 | 404 | ||
405 | .change_state: |
405 | .change_state: |
406 | 406 | ||
407 | ; We have a valid socket/TCB, so call the TCB State Machine for that skt. |
407 | ; We have a valid socket/TCB, so call the TCB State Machine for that skt. |
408 | ; socket is pointed to by ebx |
408 | ; socket is pointed to by ebx |
409 | ; IP packet is pointed to by edx |
409 | ; IP packet is pointed to by edx |
410 | ; IP buffer number is on stack ( it will be popped at the end) |
410 | ; IP buffer number is on stack ( it will be popped at the end) |
411 | 411 | ||
412 | stdcall tcpStateMachine, ebx |
412 | stdcall tcpStateMachine, ebx |
413 | 413 | ||
414 | .exit: |
414 | .exit: |
415 | pop eax |
415 | pop eax |
416 | call freeBuff |
416 | call freeBuff |
417 | ret |
417 | ret |
418 | endp |
418 | endp |
419 | 419 | ||
420 | 420 | ||
421 | ;*************************************************************************** |
421 | ;*************************************************************************** |
422 | ; Function |
422 | ; Function |
423 | ; buildTCPPacket |
423 | ; buildTCPPacket |
424 | ; |
424 | ; |
425 | ; Description |
425 | ; Description |
426 | ; builds an IP Packet with TCP data fully populated for transmission |
426 | ; builds an IP Packet with TCP data fully populated for transmission |
427 | ; You may destroy any and all registers |
427 | ; You may destroy any and all registers |
428 | ; TCP control flags specified in bl |
428 | ; TCP control flags specified in bl |
429 | ; This TCB is in [sktAddr] |
429 | ; This TCB is in [sktAddr] |
430 | ; User data pointed to by esi |
430 | ; User data pointed to by esi |
431 | ; Data length in ecx |
431 | ; Data length in ecx |
432 | ; Transmit buffer number in eax |
432 | ; Transmit buffer number in eax |
433 | ; |
433 | ; |
434 | ;*************************************************************************** |
434 | ;*************************************************************************** |
435 | 435 | ||
436 | proc build_tcp_packet stdcall, sockAddr:DWORD |
436 | proc build_tcp_packet stdcall, sockAddr:DWORD |
437 | push ecx ; Save data length |
437 | push ecx ; Save data length |
438 | 438 | ||
439 | ; convert buffer pointer eax to the absolute address |
439 | ; convert buffer pointer eax to the absolute address |
440 | mov ecx, IPBUFFSIZE |
440 | mov ecx, IPBUFFSIZE |
441 | mul ecx |
441 | mul ecx |
442 | add eax, IPbuffs |
442 | add eax, IPbuffs |
443 | 443 | ||
444 | mov edx, eax |
444 | mov edx, eax |
445 | 445 | ||
446 | mov [edx + 20 + TCP_PACKET.Flags], bl ; TCP flags |
446 | mov [edx + 20 + TCP_PACKET.Flags], bl ; TCP flags |
447 | 447 | ||
448 | mov ebx, [sockAddr] |
448 | mov ebx, [sockAddr] |
449 | 449 | ||
450 | ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr |
450 | ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr |
451 | 451 | ||
452 | ; Fill in the IP header ( some data is in the socket descriptor) |
452 | ; Fill in the IP header ( some data is in the socket descriptor) |
453 | mov eax, [ebx + SOCKET.LocalIP] |
453 | mov eax, [ebx + SOCKET.LocalIP] |
454 | mov [edx + IP_PACKET.SourceAddress], eax |
454 | mov [edx + IP_PACKET.SourceAddress], eax |
455 | mov eax, [ebx + SOCKET.RemoteIP] |
455 | mov eax, [ebx + SOCKET.RemoteIP] |
456 | mov [edx + IP_PACKET.DestinationAddress], eax |
456 | mov [edx + IP_PACKET.DestinationAddress], eax |
457 | 457 | ||
458 | mov [edx + IP_PACKET.VersionAndIHL], 0x45 |
458 | mov [edx + IP_PACKET.VersionAndIHL], 0x45 |
459 | mov [edx + IP_PACKET.TypeOfService], 0 |
459 | mov [edx + IP_PACKET.TypeOfService], 0 |
460 | 460 | ||
461 | pop eax ; Get the TCP data length |
461 | pop eax ; Get the TCP data length |
462 | push eax |
462 | push eax |
463 | 463 | ||
464 | add eax, 20 + 20 ; add IP header and TCP header lengths |
464 | add eax, 20 + 20 ; add IP header and TCP header lengths |
465 | rol ax, 8 |
465 | rol ax, 8 |
466 | mov [edx + IP_PACKET.TotalLength], ax |
466 | mov [edx + IP_PACKET.TotalLength], ax |
467 | mov [edx + IP_PACKET.Identification], 0 |
467 | mov [edx + IP_PACKET.Identification], 0 |
468 | mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 |
468 | mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 |
469 | mov [edx + IP_PACKET.TimeToLive], 0x20 |
469 | mov [edx + IP_PACKET.TimeToLive], 0x20 |
470 | mov [edx + IP_PACKET.Protocol], PROTOCOL_TCP |
470 | mov [edx + IP_PACKET.Protocol], PROTOCOL_TCP |
471 | 471 | ||
472 | ; Checksum left unfilled |
472 | ; Checksum left unfilled |
473 | mov [edx + IP_PACKET.HeaderChecksum], 0 |
473 | mov [edx + IP_PACKET.HeaderChecksum], 0 |
474 | 474 | ||
475 | ; Fill in the TCP header (some data is in the socket descriptor) |
475 | ; Fill in the TCP header (some data is in the socket descriptor) |
476 | mov ax, [ebx + SOCKET.LocalPort] |
476 | mov ax, [ebx + SOCKET.LocalPort] |
477 | mov [edx + 20 + TCP_PACKET.SourcePort], ax ; Local Port |
477 | mov [edx + 20 + TCP_PACKET.SourcePort], ax ; Local Port |
478 | 478 | ||
479 | mov ax, [ebx + SOCKET.RemotePort] |
479 | mov ax, [ebx + SOCKET.RemotePort] |
480 | mov [edx + 20 + TCP_PACKET.DestinationPort], ax ; desitination Port |
480 | mov [edx + 20 + TCP_PACKET.DestinationPort], ax ; desitination Port |
481 | 481 | ||
482 | ; Checksum left unfilled |
482 | ; Checksum left unfilled |
483 | mov [edx + 20 + TCP_PACKET.Checksum], 0 |
483 | mov [edx + 20 + TCP_PACKET.Checksum], 0 |
484 | 484 | ||
485 | ; sequence number |
485 | ; sequence number |
486 | mov eax, [ebx + SOCKET.SND_NXT] |
486 | mov eax, [ebx + SOCKET.SND_NXT] |
487 | mov [edx + 20 + TCP_PACKET.SequenceNumber], eax |
487 | mov [edx + 20 + TCP_PACKET.SequenceNumber], eax |
488 | 488 | ||
489 | ; ack number |
489 | ; ack number |
490 | mov eax, [ebx + SOCKET.RCV_NXT] |
490 | mov eax, [ebx + SOCKET.RCV_NXT] |
491 | mov [edx + 20 + TCP_PACKET.AckNumber], eax |
491 | mov [edx + 20 + TCP_PACKET.AckNumber], eax |
492 | 492 | ||
493 | ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) |
493 | ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) |
494 | ; 768 bytes seems better |
494 | ; 768 bytes seems better |
495 | mov [edx + 20 + TCP_PACKET.Window], 0x0003 |
495 | mov [edx + 20 + TCP_PACKET.Window], 0x0003 |
496 | 496 | ||
497 | ; Urgent pointer (0) |
497 | ; Urgent pointer (0) |
498 | mov [edx + 20 + TCP_PACKET.UrgentPointer], 0 |
498 | mov [edx + 20 + TCP_PACKET.UrgentPointer], 0 |
499 | 499 | ||
500 | ; data offset ( 0x50 ) |
500 | ; data offset ( 0x50 ) |
501 | mov [edx + 20 + TCP_PACKET.DataOffset], 0x50 |
501 | mov [edx + 20 + TCP_PACKET.DataOffset], 0x50 |
502 | 502 | ||
503 | pop ecx ; count of bytes to send |
503 | pop ecx ; count of bytes to send |
504 | mov ebx, ecx ; need the length later |
504 | mov ebx, ecx ; need the length later |
505 | 505 | ||
506 | cmp ebx, 0 |
506 | cmp ebx, 0 |
507 | jz @f |
507 | jz @f |
508 | 508 | ||
509 | mov edi, edx |
509 | mov edi, edx |
510 | add edi, 40 |
510 | add edi, 40 |
511 | cld |
511 | cld |
512 | rep movsb ; copy the data across |
512 | rep movsb ; copy the data across |
513 | 513 | ||
514 | @@: ; we have edx as IPbuffer ptr. |
514 | @@: ; we have edx as IPbuffer ptr. |
515 | ; Fill in the TCP checksum |
515 | ; Fill in the TCP checksum |
516 | ; First, fill in pseudoheader |
516 | ; First, fill in pseudoheader |
517 | mov eax, [edx + IP_PACKET.SourceAddress] |
517 | mov eax, [edx + IP_PACKET.SourceAddress] |
518 | mov [pseudoHeader], eax |
518 | mov [pseudoHeader], eax |
519 | mov eax, [edx + IP_PACKET.DestinationAddress] |
519 | mov eax, [edx + IP_PACKET.DestinationAddress] |
520 | mov [pseudoHeader + 4], eax |
520 | mov [pseudoHeader + 4], eax |
521 | mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0 |
521 | mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0 |
522 | add ebx, 20 |
522 | add ebx, 20 |
523 | mov [pseudoHeader + 10], bh |
523 | mov [pseudoHeader + 10], bh |
524 | mov [pseudoHeader + 11], bl |
524 | mov [pseudoHeader + 11], bl |
525 | 525 | ||
526 | mov eax, pseudoHeader |
526 | mov eax, pseudoHeader |
527 | mov [checkAdd1], eax |
527 | mov [checkAdd1], eax |
528 | mov word[checkSize1], 12 |
528 | mov word[checkSize1], 12 |
529 | mov eax, edx |
529 | mov eax, edx |
530 | add eax, 20 |
530 | add eax, 20 |
531 | mov [checkAdd2], eax |
531 | mov [checkAdd2], eax |
532 | mov eax, ebx |
532 | mov eax, ebx |
533 | mov [checkSize2], ax |
533 | mov [checkSize2], ax |
534 | 534 | ||
535 | call checksum |
535 | call checksum |
536 | 536 | ||
537 | ; store it in the TCP checksum ( in the correct order! ) |
537 | ; store it in the TCP checksum ( in the correct order! ) |
538 | mov ax, [checkResult] |
538 | mov ax, [checkResult] |
539 | rol ax, 8 |
539 | rol ax, 8 |
540 | mov [edx + 20 + TCP_PACKET.Checksum], ax |
540 | mov [edx + 20 + TCP_PACKET.Checksum], ax |
541 | 541 | ||
542 | ; Fill in the IP header checksum |
542 | ; Fill in the IP header checksum |
543 | GET_IHL eax, edx ; get IP-Header length |
543 | GET_IHL eax, edx ; get IP-Header length |
544 | stdcall checksum_jb, edx, eax ; buf_ptr, buf_size |
544 | stdcall checksum_jb, edx, eax ; buf_ptr, buf_size |
545 | rol ax, 8 |
545 | rol ax, 8 |
546 | mov [edx + IP_PACKET.HeaderChecksum], ax |
546 | mov [edx + IP_PACKET.HeaderChecksum], ax |
547 | 547 | ||
548 | ret |
548 | ret |
549 | endp |
549 | endp |
550 | 550 | ||
551 | 551 | ||
552 | ; Increments the 32 bit value pointed to by esi in internet order |
552 | ; Increments the 32 bit value pointed to by esi in internet order |
553 | proc inc_inet_esi stdcall |
553 | proc inc_inet_esi stdcall |
554 | push eax |
554 | push eax |
555 | mov eax, [esi] |
555 | mov eax, [esi] |
556 | bswap eax |
556 | bswap eax |
557 | inc eax |
557 | inc eax |
558 | bswap eax |
558 | bswap eax |
559 | mov [esi], eax |
559 | mov [esi], eax |
560 | pop eax |
560 | pop eax |
561 | ret |
561 | ret |
562 | endp |
562 | endp |
563 | 563 | ||
564 | 564 | ||
565 | ; Increments the 32 bit value pointed to by esi in internet order |
565 | ; Increments the 32 bit value pointed to by esi in internet order |
566 | ; by the value in ecx |
566 | ; by the value in ecx |
567 | proc add_inet_esi stdcall |
567 | proc add_inet_esi stdcall |
568 | push eax |
568 | push eax |
569 | mov eax, [esi] |
569 | mov eax, [esi] |
570 | bswap eax |
570 | bswap eax |
571 | add eax, ecx |
571 | add eax, ecx |
572 | bswap eax |
572 | bswap eax |
573 | mov [esi], eax |
573 | mov [esi], eax |
574 | pop eax |
574 | pop eax |
575 | ret |
575 | ret |
576 | endp |
576 | endp |
577 | 577 | ||
578 | 578 | ||
579 | iglobal |
579 | iglobal |
580 | TCBStateHandler dd \ |
580 | TCBStateHandler dd \ |
581 | stateTCB_LISTEN, \ |
581 | stateTCB_LISTEN, \ |
582 | stateTCB_SYN_SENT, \ |
582 | stateTCB_SYN_SENT, \ |
583 | stateTCB_SYN_RECEIVED, \ |
583 | stateTCB_SYN_RECEIVED, \ |
584 | stateTCB_ESTABLISHED, \ |
584 | stateTCB_ESTABLISHED, \ |
585 | stateTCB_FIN_WAIT_1, \ |
585 | stateTCB_FIN_WAIT_1, \ |
586 | stateTCB_FIN_WAIT_2, \ |
586 | stateTCB_FIN_WAIT_2, \ |
587 | stateTCB_CLOSE_WAIT, \ |
587 | stateTCB_CLOSE_WAIT, \ |
588 | stateTCB_CLOSING, \ |
588 | stateTCB_CLOSING, \ |
589 | stateTCB_LAST_ACK, \ |
589 | stateTCB_LAST_ACK, \ |
590 | stateTCB_TIME_WAIT, \ |
590 | stateTCB_TIME_WAIT, \ |
591 | stateTCB_CLOSED |
591 | stateTCB_CLOSED |
592 | endg |
592 | endg |
593 | 593 | ||
594 | 594 | ||
595 | ;*************************************************************************** |
595 | ;*************************************************************************** |
596 | ; Function |
596 | ; Function |
597 | ; tcpStateMachine |
597 | ; tcpStateMachine |
598 | ; |
598 | ; |
599 | ; Description |
599 | ; Description |
600 | ; TCP state machine |
600 | ; TCP state machine |
601 | ; This is a kernel function, called by tcp_rx |
601 | ; This is a kernel function, called by tcp_rx |
602 | ; |
602 | ; |
603 | ; IP buffer address given in edx |
603 | ; IP buffer address given in edx |
604 | ; Socket/TCB address in ebx |
604 | ; Socket/TCB address in ebx |
605 | ; |
605 | ; |
606 | ; The IP buffer will be released by the caller |
606 | ; The IP buffer will be released by the caller |
607 | ;*************************************************************************** |
607 | ;*************************************************************************** |
608 | 608 | ||
609 | proc tcpStateMachine stdcall, sockAddr:DWORD |
609 | proc tcpStateMachine stdcall, sockAddr:DWORD |
610 | ; as a packet has been received, update the TCB timer |
610 | ; as a packet has been received, update the TCB timer |
611 | mov [ebx + SOCKET.TCBTimer], TWOMSL |
611 | mov [ebx + SOCKET.TCBTimer], TWOMSL |
612 | 612 | ||
613 | ; If the received packet has an ACK bit set, |
613 | ; If the received packet has an ACK bit set, |
614 | ; remove any packets in the resend queue that this |
614 | ; remove any packets in the resend queue that this |
615 | ; received packet acknowledges |
615 | ; received packet acknowledges |
616 | pushad |
616 | pushad |
617 | test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
617 | test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
618 | jz .call_handler ; No ACK, so no data yet |
618 | jz .call_handler ; No ACK, so no data yet |
619 | 619 | ||
620 | ; get skt number in eax |
620 | ; get skt number in eax |
621 | stdcall net_socket_addr_to_num, ebx |
621 | stdcall net_socket_addr_to_num, ebx |
622 | 622 | ||
623 | ; The ack number is in [edx + 28], inet format |
623 | ; The ack number is in [edx + 28], inet format |
624 | ; skt in eax |
624 | ; skt in eax |
625 | 625 | ||
626 | mov esi, resendQ |
626 | mov esi, resendQ |
627 | xor ecx, ecx |
627 | xor ecx, ecx |
628 | 628 | ||
629 | .next_resendq: |
629 | .next_resendq: |
630 | cmp ecx, NUMRESENDENTRIES |
630 | cmp ecx, NUMRESENDENTRIES |
631 | je .call_handler ; None left |
631 | je .call_handler ; None left |
632 | cmp [esi + 4], eax |
632 | cmp [esi + 4], eax |
633 | je @f ; found one |
633 | je @f ; found one |
634 | inc ecx |
634 | inc ecx |
635 | add esi, 8 |
635 | add esi, 8 |
636 | jmp .next_resendq |
636 | jmp .next_resendq |
637 | 637 | ||
638 | @@: ; Can we delete this buffer? |
638 | @@: ; Can we delete this buffer? |
639 | 639 | ||
640 | ; If yes, goto @@. No, goto .next_resendq |
640 | ; If yes, goto @@. No, goto .next_resendq |
641 | ; Get packet data address |
641 | ; Get packet data address |
642 | 642 | ||
643 | push ecx |
643 | push ecx |
644 | ; Now get buffer location, and copy buffer across. argh! more copying,, |
644 | ; Now get buffer location, and copy buffer across. argh! more copying,, |
645 | imul edi, ecx, IPBUFFSIZE |
645 | imul edi, ecx, IPBUFFSIZE |
646 | add edi, resendBuffer |
646 | add edi, resendBuffer |
647 | 647 | ||
648 | ; we have dest buffer location in edi. incoming packet in edx. |
648 | ; we have dest buffer location in edi. incoming packet in edx. |
649 | ; Get this packets sequence number |
649 | ; Get this packets sequence number |
650 | ; preserve al, ecx, esi, edx |
650 | ; preserve al, ecx, esi, edx |
651 | mov ecx, [edi + 20 + TCP_PACKET.SequenceNumber] |
651 | mov ecx, [edi + 20 + TCP_PACKET.SequenceNumber] |
652 | bswap ecx |
652 | bswap ecx |
653 | movzx ebx, word[edi + 2] |
653 | movzx ebx, word[edi + 2] |
654 | xchg bl, bh |
654 | xchg bl, bh |
655 | sub ebx, 40 |
655 | sub ebx, 40 |
656 | add ecx, ebx ; ecx is now seq# of last byte +1, intel format |
656 | add ecx, ebx ; ecx is now seq# of last byte +1, intel format |
657 | 657 | ||
658 | ; get recievd ack #, in intel format |
658 | ; get recievd ack #, in intel format |
659 | mov ebx, [edx + 20 + TCP_PACKET.AckNumber] |
659 | mov ebx, [edx + 20 + TCP_PACKET.AckNumber] |
660 | bswap ebx |
660 | bswap ebx |
661 | 661 | ||
662 | cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que |
662 | cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que |
663 | ; DANGER! need to handle case that we have just |
663 | ; DANGER! need to handle case that we have just |
664 | ; passed the 2**32, and wrapped round! |
664 | ; passed the 2**32, and wrapped round! |
665 | pop ecx |
665 | pop ecx |
666 | jae @f ; if rx > old, delete old |
666 | jae @f ; if rx > old, delete old |
667 | 667 | ||
668 | inc ecx |
668 | inc ecx |
669 | add esi, 8 |
669 | add esi, 8 |
670 | jmp .next_resendq |
670 | jmp .next_resendq |
671 | 671 | ||
672 | @@: |
672 | @@: |
673 | mov dword[esi + 4], 0 |
673 | mov dword[esi + 4], 0 |
674 | inc ecx |
674 | inc ecx |
675 | add esi, 8 |
675 | add esi, 8 |
676 | jmp .next_resendq |
676 | jmp .next_resendq |
677 | 677 | ||
678 | .call_handler: |
678 | .call_handler: |
679 | popad |
679 | popad |
680 | 680 | ||
681 | ; Call handler for given TCB state |
681 | ; Call handler for given TCB state |
682 | 682 | ||
683 | mov eax, [ebx + SOCKET.TCBState] |
683 | mov eax, [ebx + SOCKET.TCBState] |
684 | cmp eax, TCB_LISTEN |
684 | cmp eax, TCB_LISTEN |
685 | jb .exit |
685 | jb .exit |
686 | cmp eax, TCB_CLOSED |
686 | cmp eax, TCB_CLOSED |
687 | ja .exit |
687 | ja .exit |
688 | 688 | ||
689 | stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr] |
689 | stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr] |
690 | 690 | ||
691 | .exit: |
691 | .exit: |
692 | ret |
692 | ret |
693 | endp |
693 | endp |
694 | 694 | ||
695 | ;*************************************************************************** |
695 | ;*************************************************************************** |
696 | ; Function |
696 | ; Function |
697 | ; signal_network_event |
697 | ; signal_network_event |
698 | ; |
698 | ; |
699 | ; Description |
699 | ; Description |
700 | ; Signals about network event to socket owner |
700 | ; Signals about network event to socket owner |
701 | ; This is a kernel function, called from TCP handler |
701 | ; This is a kernel function, called from TCP handler |
702 | ; |
702 | ; |
703 | ; Socket/TCB address in ebx |
703 | ; Socket/TCB address in ebx |
704 | ;*************************************************************************** |
704 | ;*************************************************************************** |
705 | proc signal_network_event |
705 | proc signal_network_event |
706 | push ecx esi eax |
706 | push ecx esi eax |
707 | mov eax, [ebx + SOCKET.PID] |
707 | mov eax, [ebx + SOCKET.PID] |
708 | mov ecx, 1 |
708 | mov ecx, 1 |
709 | mov esi, TASK_DATA + TASKDATA.pid |
709 | mov esi, TASK_DATA + TASKDATA.pid |
710 | 710 | ||
711 | .next_pid: |
711 | .next_pid: |
712 | cmp [esi], eax |
712 | cmp [esi], eax |
713 | je .found_pid |
713 | je .found_pid |
714 | inc ecx |
714 | inc ecx |
715 | add esi, 0x20 |
715 | add esi, 0x20 |
716 | cmp ecx, [TASK_COUNT] |
716 | cmp ecx, [TASK_COUNT] |
717 | jbe .next_pid |
717 | jbe .next_pid |
718 | 718 | ||
719 | .found_pid: |
719 | .found_pid: |
720 | shl ecx, 8 |
720 | shl ecx, 8 |
721 | or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event |
721 | or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event |
722 | pop eax esi ecx |
722 | pop eax esi ecx |
723 | ret |
723 | ret |
724 | endp |
724 | endp |
725 | 725 | ||
726 | proc stateTCB_LISTEN stdcall, sockAddr:DWORD |
726 | proc stateTCB_LISTEN stdcall, sockAddr:DWORD |
727 | ; In this case, we are expecting a SYN packet |
727 | ; In this case, we are expecting a SYN packet |
728 | ; For now, if the packet is a SYN, process it, and send a response |
728 | ; For now, if the packet is a SYN, process it, and send a response |
729 | ; If not, ignore it |
729 | ; If not, ignore it |
730 | 730 | ||
731 | ; Look at control flags |
731 | ; Look at control flags |
732 | test [edx + 20 + TCP_PACKET.Flags], TH_SYN |
732 | test [edx + 20 + TCP_PACKET.Flags], TH_SYN |
733 | jz .exit |
733 | jz .exit |
734 | 734 | ||
735 | ; We have a SYN. update the socket with this IP packets details, |
735 | ; We have a SYN. update the socket with this IP packets details, |
736 | ; And send a response |
736 | ; And send a response |
737 | 737 | ||
738 | mov eax, [edx + IP_PACKET.SourceAddress] |
738 | mov eax, [edx + IP_PACKET.SourceAddress] |
739 | mov [ebx + SOCKET.RemoteIP], eax |
739 | mov [ebx + SOCKET.RemoteIP], eax |
740 | mov ax, [edx + 20 + TCP_PACKET.SourcePort] |
740 | mov ax, [edx + 20 + TCP_PACKET.SourcePort] |
741 | mov [ebx + SOCKET.RemotePort], ax |
741 | mov [ebx + SOCKET.RemotePort], ax |
742 | mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
742 | mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
743 | mov [ebx + SOCKET.IRS], eax |
743 | mov [ebx + SOCKET.IRS], eax |
744 | mov [ebx + SOCKET.RCV_NXT], eax |
744 | mov [ebx + SOCKET.RCV_NXT], eax |
745 | lea esi, [ebx + SOCKET.RCV_NXT] |
745 | lea esi, [ebx + SOCKET.RCV_NXT] |
746 | call inc_inet_esi ; RCV.NXT |
746 | call inc_inet_esi ; RCV.NXT |
747 | mov eax, [ebx + SOCKET.ISS] |
747 | mov eax, [ebx + SOCKET.ISS] |
748 | mov [ebx + SOCKET.SND_NXT], eax |
748 | mov [ebx + SOCKET.SND_NXT], eax |
749 | 749 | ||
750 | ; Now construct the response, and queue for sending by IP |
750 | ; Now construct the response, and queue for sending by IP |
751 | mov eax, EMPTY_QUEUE |
751 | mov eax, EMPTY_QUEUE |
752 | call dequeue |
752 | call dequeue |
753 | cmp ax, NO_BUFFER |
753 | cmp ax, NO_BUFFER |
754 | je .exit |
754 | je .exit |
755 | 755 | ||
756 | push ebx |
756 | push ebx |
757 | push eax |
757 | push eax |
758 | mov bl, TH_SYN + TH_ACK |
758 | mov bl, TH_SYN + TH_ACK |
759 | xor ecx, ecx |
759 | xor ecx, ecx |
760 | xor esi, esi |
760 | xor esi, esi |
761 | stdcall build_tcp_packet, [sockAddr] |
761 | stdcall build_tcp_packet, [sockAddr] |
762 | 762 | ||
763 | mov eax, NET1OUT_QUEUE |
763 | mov eax, NET1OUT_QUEUE |
764 | mov edx, [stack_ip] |
764 | mov edx, [stack_ip] |
765 | mov ecx, [sockAddr] |
765 | mov ecx, [sockAddr] |
766 | cmp edx, [ecx + SOCKET.RemoteIP] |
766 | cmp edx, [ecx + SOCKET.RemoteIP] |
767 | jne .not_local |
767 | jne .not_local |
768 | mov eax, IPIN_QUEUE |
768 | mov eax, IPIN_QUEUE |
769 | 769 | ||
770 | .not_local: |
770 | .not_local: |
771 | ; Send it. |
771 | ; Send it. |
772 | pop ebx |
772 | pop ebx |
773 | call queue |
773 | call queue |
774 | 774 | ||
775 | pop ebx |
775 | pop ebx |
776 | mov esi, [sockAddr] |
776 | mov esi, [sockAddr] |
777 | mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED |
777 | mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED |
778 | call signal_network_event |
778 | call signal_network_event |
779 | 779 | ||
780 | ; increment SND.NXT in socket |
780 | ; increment SND.NXT in socket |
781 | add esi, SOCKET.SND_NXT |
781 | add esi, SOCKET.SND_NXT |
782 | call inc_inet_esi |
782 | call inc_inet_esi |
783 | 783 | ||
784 | .exit: |
784 | .exit: |
785 | ret |
785 | ret |
786 | endp |
786 | endp |
787 | 787 | ||
788 | 788 | ||
789 | proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD |
789 | proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD |
790 | ; We are awaiting an ACK to our SYN, with a SYM |
790 | ; We are awaiting an ACK to our SYN, with a SYM |
791 | ; Look at control flags - expecting an ACK |
791 | ; Look at control flags - expecting an ACK |
792 | 792 | ||
793 | mov al, [edx + 20 + TCP_PACKET.Flags] |
793 | mov al, [edx + 20 + TCP_PACKET.Flags] |
794 | and al, TH_SYN + TH_ACK |
794 | and al, TH_SYN + TH_ACK |
795 | cmp al, TH_SYN + TH_ACK |
795 | cmp al, TH_SYN + TH_ACK |
796 | je .syn_ack |
796 | je .syn_ack |
797 | 797 | ||
798 | test al, TH_SYN |
798 | test al, TH_SYN |
799 | jz .exit |
799 | jz .exit |
800 | 800 | ||
801 | mov [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED |
801 | mov [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED |
802 | push TH_SYN + TH_ACK |
802 | push TH_SYN + TH_ACK |
803 | jmp .send |
803 | jmp .send |
804 | 804 | ||
805 | .syn_ack: |
805 | .syn_ack: |
806 | mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED |
806 | mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED |
807 | push TH_ACK |
807 | push TH_ACK |
808 | 808 | ||
809 | .send: |
809 | .send: |
810 | call signal_network_event |
810 | call signal_network_event |
811 | ; Store the recv.nxt field |
811 | ; Store the recv.nxt field |
812 | mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
812 | mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
813 | 813 | ||
814 | ; Update our recv.nxt field |
814 | ; Update our recv.nxt field |
815 | mov [ebx + SOCKET.RCV_NXT], eax |
815 | mov [ebx + SOCKET.RCV_NXT], eax |
816 | lea esi, [ebx + SOCKET.RCV_NXT] |
816 | lea esi, [ebx + SOCKET.RCV_NXT] |
817 | call inc_inet_esi |
817 | call inc_inet_esi |
818 | 818 | ||
819 | ; Send an ACK |
819 | ; Send an ACK |
820 | ; Now construct the response, and queue for sending by IP |
820 | ; Now construct the response, and queue for sending by IP |
821 | mov eax, EMPTY_QUEUE |
821 | mov eax, EMPTY_QUEUE |
822 | call dequeue |
822 | call dequeue |
823 | cmp ax, NO_BUFFER |
823 | cmp ax, NO_BUFFER |
824 | pop ebx |
824 | pop ebx |
825 | je .exit |
825 | je .exit |
826 | 826 | ||
827 | push eax |
827 | push eax |
828 | 828 | ||
829 | xor ecx, ecx |
829 | xor ecx, ecx |
830 | xor esi, esi |
830 | xor esi, esi |
831 | stdcall build_tcp_packet, [sockAddr] |
831 | stdcall build_tcp_packet, [sockAddr] |
832 | 832 | ||
833 | mov eax, NET1OUT_QUEUE |
833 | mov eax, NET1OUT_QUEUE |
834 | mov edx, [stack_ip] |
834 | mov edx, [stack_ip] |
835 | mov ecx, [sockAddr] |
835 | mov ecx, [sockAddr] |
836 | cmp edx, [ecx + SOCKET.RemoteIP] |
836 | cmp edx, [ecx + SOCKET.RemoteIP] |
837 | jne .not_local |
837 | jne .not_local |
838 | mov eax, IPIN_QUEUE |
838 | mov eax, IPIN_QUEUE |
839 | 839 | ||
840 | .not_local: |
840 | .not_local: |
841 | ; Send it. |
841 | ; Send it. |
842 | pop ebx |
842 | pop ebx |
843 | call queue |
843 | call queue |
844 | 844 | ||
845 | .exit: |
845 | .exit: |
846 | ret |
846 | ret |
847 | endp |
847 | endp |
848 | 848 | ||
849 | 849 | ||
850 | proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD |
850 | proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD |
851 | ; In this case, we are expecting an ACK packet |
851 | ; In this case, we are expecting an ACK packet |
852 | ; For now, if the packet is an ACK, process it, |
852 | ; For now, if the packet is an ACK, process it, |
853 | ; If not, ignore it |
853 | ; If not, ignore it |
854 | 854 | ||
855 | test [edx + 20 + TCP_PACKET.Flags], TH_RST |
855 | test [edx + 20 + TCP_PACKET.Flags], TH_RST |
856 | jz .check_ack |
856 | jz .check_ack |
857 | 857 | ||
858 | push [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP] |
858 | push [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP] |
859 | pop [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort] |
859 | pop [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort] |
860 | 860 | ||
861 | mov [ebx + SOCKET.TCBState], TCB_LISTEN |
861 | mov [ebx + SOCKET.TCBState], TCB_LISTEN |
862 | jmp .signal |
862 | jmp .signal |
863 | 863 | ||
864 | .check_ack: |
864 | .check_ack: |
865 | ; Look at control flags - expecting an ACK |
865 | ; Look at control flags - expecting an ACK |
866 | test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
866 | test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
867 | jz .exit |
867 | jz .exit |
868 | 868 | ||
869 | mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED |
869 | mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED |
870 | .signal: |
870 | .signal: |
871 | call signal_network_event |
871 | call signal_network_event |
872 | 872 | ||
873 | .exit: |
873 | .exit: |
874 | ret |
874 | ret |
875 | endp |
875 | endp |
876 | 876 | ||
877 | 877 | ||
878 | proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD |
878 | proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD |
879 | ; Here we are expecting data, or a request to close |
879 | ; Here we are expecting data, or a request to close |
880 | ; OR both... |
880 | ; OR both... |
881 | 881 | ||
882 | ; Ignore all packets with sequnce number other than next expected |
882 | ; Ignore all packets with sequnce number other than next expected |
883 | 883 | ||
884 | ; recv.nxt is in dword [edx+24], in inet format |
884 | ; recv.nxt is in dword [edx+24], in inet format |
885 | ; recv seq is in [sktAddr]+56, in inet format |
885 | ; recv seq is in [sktAddr]+56, in inet format |
886 | ; just do a comparision |
886 | ; just do a comparision |
887 | mov eax, [ebx + SOCKET.RCV_NXT] |
887 | mov eax, [ebx + SOCKET.RCV_NXT] |
888 | cmp eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
888 | cmp eax, [edx + 20 + TCP_PACKET.SequenceNumber] |
889 | jne .exit |
889 | jne .exit |
890 | 890 | ||
891 | ; Did we receive a FIN or RST? |
891 | ; Did we receive a FIN or RST? |
892 | test [edx + 20 + TCP_PACKET.Flags], TH_FIN+TH_RST |
892 | test [edx + 20 + TCP_PACKET.Flags], TH_FIN+TH_RST |
893 | jz .check_ack |
893 | jz .check_ack |
894 | 894 | ||
895 | ; It was a fin or reset. |
895 | ; It was a fin or reset. |
896 | 896 | ||
897 | ; Remove resend entries from the queue - I dont want to send any more data |
897 | ; Remove resend entries from the queue - I dont want to send any more data |
898 | pushad |
898 | pushad |
899 | 899 | ||
900 | ; get skt # |
900 | ; get skt # |
901 | stdcall net_socket_addr_to_num, ebx |
901 | stdcall net_socket_addr_to_num, ebx |
902 | 902 | ||
903 | mov esi, resendQ |
903 | mov esi, resendQ |
904 | mov ecx, 0 |
904 | mov ecx, 0 |
905 | 905 | ||
906 | .next_resendq: |
906 | .next_resendq: |
907 | cmp ecx, NUMRESENDENTRIES |
907 | cmp ecx, NUMRESENDENTRIES |
908 | je .last_resendq ; None left |
908 | je .last_resendq ; None left |
909 | cmp [esi + 4], eax |
909 | cmp [esi + 4], eax |
910 | je @f ; found one |
910 | je @f ; found one |
911 | inc ecx |
911 | inc ecx |
912 | add esi, 8 |
912 | add esi, 8 |
913 | jmp .next_resendq |
913 | jmp .next_resendq |
914 | 914 | ||
915 | @@: |
915 | @@: |
916 | mov dword[esi + 4], 0 |
916 | mov dword[esi + 4], 0 |
917 | inc ecx |
917 | inc ecx |
918 | add esi, 8 |
918 | add esi, 8 |
919 | jmp .next_resendq |
919 | jmp .next_resendq |
920 | 920 | ||
921 | .last_resendq: |
921 | .last_resendq: |
922 | popad |
922 | popad |
923 | 923 | ||
924 | @@: ; Send an ACK to that fin, and enter closewait state |
924 | @@: ; Send an ACK to that fin, and enter closewait state |
925 | 925 | ||
926 | mov [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT |
926 | mov [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT |
927 | test [edx + 20 + TCP_PACKET.Flags], TH_RST |
927 | test [edx + 20 + TCP_PACKET.Flags], TH_RST |
928 | je @f |
928 | je @f |
929 | mov [ebx + SOCKET.TCBState], TCB_CLOSED |
929 | mov [ebx + SOCKET.TCBState], TCB_CLOSED |
930 | @@: |
930 | @@: |
931 | call signal_network_event |
931 | call signal_network_event |
932 | lea esi, [ebx + SOCKET.RCV_NXT] |
932 | lea esi, [ebx + SOCKET.RCV_NXT] |
933 | mov eax, [esi] ; save original |
933 | mov eax, [esi] ; save original |
934 | call inc_inet_esi |
934 | call inc_inet_esi |
935 | ;; jmp ste_ack - NO, there may be data |
935 | ;; jmp ste_ack - NO, there may be data |
936 | 936 | ||
937 | .check_ack: |
937 | .check_ack: |
938 | ; Check that we received an ACK |
938 | ; Check that we received an ACK |
939 | test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
939 | test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
940 | jz .exit |
940 | jz .exit |
941 | 941 | ||
942 | ; TODO - done, I think! |
942 | ; TODO - done, I think! |
943 | ; First, look at the incoming window. If this is less than or equal to 1024, |
943 | ; First, look at the incoming window. If this is less than or equal to 1024, |
944 | ; Set the socket window timer to 1. This will stop an additional packets being queued. |
944 | ; Set the socket window timer to 1. This will stop an additional packets being queued. |
945 | ; ** I may need to tweak this value, since I do not know how many packets are already queued |
945 | ; ** I may need to tweak this value, since I do not know how many packets are already queued |
946 | mov cx, [edx + 20 + TCP_PACKET.Window] |
946 | mov cx, [edx + 20 + TCP_PACKET.Window] |
947 | xchg cl, ch |
947 | xchg cl, ch |
948 | cmp cx, 1024 |
948 | cmp cx, 1024 |
949 | ja @f |
949 | ja @f |
950 | 950 | ||
951 | mov [ebx + SOCKET.wndsizeTimer], 1 |
951 | mov [ebx + SOCKET.wndsizeTimer], 1 |
952 | 952 | ||
953 | @@: ; OK, here is the deal |
953 | @@: ; OK, here is the deal |
954 | 954 | ||
955 | 955 | ||
956 | ; Read the data bytes, store in socket buffer |
956 | ; Read the data bytes, store in socket buffer |
957 | movzx ecx, [edx + IP_PACKET.TotalLength] |
957 | movzx ecx, [edx + IP_PACKET.TotalLength] |
958 | xchg cl, ch |
958 | xchg cl, ch |
959 | sub ecx, 40 ; Discard 40 bytes of header |
959 | sub ecx, 40 ; Discard 40 bytes of header |
960 | ja .data ; Read data, if any |
960 | ja .data ; Read data, if any |
961 | 961 | ||
962 | ; If we had received a fin, we need to ACK it. |
962 | ; If we had received a fin, we need to ACK it. |
963 | cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT |
963 | cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT |
964 | je .ack |
964 | je .ack |
965 | jmp .exit |
965 | jmp .exit |
966 | 966 | ||
967 | .data: |
967 | .data: |
968 | push ecx |
968 | push ecx |
969 | push ecx edx |
969 | push ecx edx |
970 | lea ecx, [ebx+SOCKET.lock] |
970 | lea ecx, [ebx+SOCKET.mutex] |
971 | call mutex_lock |
971 | call mutex_lock |
972 | pop edx ecx |
972 | pop edx ecx |
973 | 973 | ||
974 | push ebx |
974 | push ebx |
975 | mov eax, [ebx + SOCKET.rxDataCount] |
975 | mov eax, [ebx + SOCKET.rxDataCount] |
976 | add eax, ecx |
976 | add eax, ecx |
977 | cmp eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE |
977 | cmp eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE |
978 | ja .overflow |
978 | ja .overflow |
979 | 979 | ||
980 | mov [ebx + SOCKET.rxDataCount], eax ; increment the count of bytes in buffer |
980 | mov [ebx + SOCKET.rxDataCount], eax ; increment the count of bytes in buffer |
981 | 981 | ||
982 | ; point to the location to store the data |
982 | ; point to the location to store the data |
983 | lea edi, [ebx + eax + SOCKETHEADERSIZE] |
983 | lea edi, [ebx + eax + SOCKETHEADERSIZE] |
984 | sub edi, ecx |
984 | sub edi, ecx |
985 | 985 | ||
986 | add edx, 40 ; edx now points to the data |
986 | add edx, 40 ; edx now points to the data |
987 | mov esi, edx |
987 | mov esi, edx |
988 | 988 | ||
989 | cld |
989 | cld |
990 | rep movsb ; copy the data across |
990 | rep movsb ; copy the data across |
991 | 991 | ||
992 | lea ecx, [ebx + SOCKET.lock] |
992 | lea ecx, [ebx + SOCKET.mutex] |
993 | call mutex_unlock |
993 | call mutex_unlock |
994 | 994 | ||
995 | ; flag an event to the application |
995 | ; flag an event to the application |
996 | pop ebx |
996 | pop ebx |
997 | call signal_network_event |
997 | call signal_network_event |
998 | 998 | ||
999 | pop ecx |
999 | pop ecx |
1000 | 1000 | ||
1001 | ; Update our recv.nxt field |
1001 | ; Update our recv.nxt field |
1002 | lea esi, [ebx + SOCKET.RCV_NXT] |
1002 | lea esi, [ebx + SOCKET.RCV_NXT] |
1003 | call add_inet_esi |
1003 | call add_inet_esi |
1004 | 1004 | ||
1005 | .ack: |
1005 | .ack: |
1006 | ; Send an ACK |
1006 | ; Send an ACK |
1007 | ; Now construct the response, and queue for sending by IP |
1007 | ; Now construct the response, and queue for sending by IP |
1008 | mov eax, EMPTY_QUEUE |
1008 | mov eax, EMPTY_QUEUE |
1009 | call dequeue |
1009 | call dequeue |
1010 | cmp ax, NO_BUFFER |
1010 | cmp ax, NO_BUFFER |
1011 | je .exit |
1011 | je .exit |
1012 | 1012 | ||
1013 | push eax |
1013 | push eax |
1014 | 1014 | ||
1015 | mov bl, TH_ACK |
1015 | mov bl, TH_ACK |
1016 | xor ecx, ecx |
1016 | xor ecx, ecx |
1017 | xor esi, esi |
1017 | xor esi, esi |
1018 | stdcall build_tcp_packet, [sockAddr] |
1018 | stdcall build_tcp_packet, [sockAddr] |
1019 | 1019 | ||
1020 | mov eax, NET1OUT_QUEUE |
1020 | mov eax, NET1OUT_QUEUE |
1021 | 1021 | ||
1022 | mov edx, [stack_ip] |
1022 | mov edx, [stack_ip] |
1023 | mov ecx, [sockAddr] |
1023 | mov ecx, [sockAddr] |
1024 | cmp edx, [ecx + SOCKET.RemoteIP] |
1024 | cmp edx, [ecx + SOCKET.RemoteIP] |
1025 | jne .not_local |
1025 | jne .not_local |
1026 | mov eax, IPIN_QUEUE |
1026 | mov eax, IPIN_QUEUE |
1027 | 1027 | ||
1028 | .not_local: |
1028 | .not_local: |
1029 | ; Send it. |
1029 | ; Send it. |
1030 | pop ebx |
1030 | pop ebx |
1031 | call queue |
1031 | call queue |
1032 | 1032 | ||
1033 | .exit: |
1033 | .exit: |
1034 | ret |
1034 | ret |
1035 | .overflow: |
1035 | .overflow: |
1036 | ; no place in buffer |
1036 | ; no place in buffer |
1037 | ; so simply restore stack and exit |
1037 | ; so simply restore stack and exit |
1038 | lea ecx, [ebx + SOCKET.lock] |
1038 | lea ecx, [ebx + SOCKET.mutex] |
1039 | call mutex_unlock |
1039 | call mutex_unlock |
1040 | pop eax ecx |
1040 | pop eax ecx |
1041 | ret |
1041 | ret |
1042 | endp |
1042 | endp |
1043 | 1043 | ||
1044 | 1044 | ||
1045 | proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD |
1045 | proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD |
1046 | ; We can either receive an ACK of a fin, or a fin |
1046 | ; We can either receive an ACK of a fin, or a fin |
1047 | mov al, [edx + 20 + TCP_PACKET.Flags] |
1047 | mov al, [edx + 20 + TCP_PACKET.Flags] |
1048 | and al, TH_FIN + TH_ACK |
1048 | and al, TH_FIN + TH_ACK |
1049 | 1049 | ||
1050 | cmp al, TH_ACK |
1050 | cmp al, TH_ACK |
1051 | jne @f |
1051 | jne @f |
1052 | 1052 | ||
1053 | ; It was an ACK |
1053 | ; It was an ACK |
1054 | mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2 |
1054 | mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2 |
1055 | jmp .exit |
1055 | jmp .exit |
1056 | 1056 | ||
1057 | @@: |
1057 | @@: |
1058 | mov [ebx + SOCKET.TCBState], TCB_CLOSING |
1058 | mov [ebx + SOCKET.TCBState], TCB_CLOSING |
1059 | cmp al, TH_FIN |
1059 | cmp al, TH_FIN |
1060 | je @f |
1060 | je @f |
1061 | mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
1061 | mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
1062 | 1062 | ||
1063 | @@: |
1063 | @@: |
1064 | lea esi, [ebx + SOCKET.RCV_NXT] |
1064 | lea esi, [ebx + SOCKET.RCV_NXT] |
1065 | call inc_inet_esi |
1065 | call inc_inet_esi |
1066 | 1066 | ||
1067 | ; Send an ACK |
1067 | ; Send an ACK |
1068 | mov eax, EMPTY_QUEUE |
1068 | mov eax, EMPTY_QUEUE |
1069 | call dequeue |
1069 | call dequeue |
1070 | cmp ax, NO_BUFFER |
1070 | cmp ax, NO_BUFFER |
1071 | je .exit |
1071 | je .exit |
1072 | 1072 | ||
1073 | push eax |
1073 | push eax |
1074 | 1074 | ||
1075 | mov bl, TH_ACK |
1075 | mov bl, TH_ACK |
1076 | xor ecx, ecx |
1076 | xor ecx, ecx |
1077 | xor esi, esi |
1077 | xor esi, esi |
1078 | stdcall build_tcp_packet, [sockAddr] |
1078 | stdcall build_tcp_packet, [sockAddr] |
1079 | 1079 | ||
1080 | mov eax, NET1OUT_QUEUE |
1080 | mov eax, NET1OUT_QUEUE |
1081 | mov edx, [stack_ip] |
1081 | mov edx, [stack_ip] |
1082 | mov ecx, [sockAddr] |
1082 | mov ecx, [sockAddr] |
1083 | cmp edx, [ecx + SOCKET.RemoteIP] |
1083 | cmp edx, [ecx + SOCKET.RemoteIP] |
1084 | jne .not_local |
1084 | jne .not_local |
1085 | mov eax, IPIN_QUEUE |
1085 | mov eax, IPIN_QUEUE |
1086 | 1086 | ||
1087 | .not_local: |
1087 | .not_local: |
1088 | ; Send it. |
1088 | ; Send it. |
1089 | pop ebx |
1089 | pop ebx |
1090 | call queue |
1090 | call queue |
1091 | 1091 | ||
1092 | .exit: |
1092 | .exit: |
1093 | ret |
1093 | ret |
1094 | endp |
1094 | endp |
1095 | 1095 | ||
1096 | 1096 | ||
1097 | proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD |
1097 | proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD |
1098 | test [edx + 20 + TCP_PACKET.Flags], TH_FIN |
1098 | test [edx + 20 + TCP_PACKET.Flags], TH_FIN |
1099 | jz .exit |
1099 | jz .exit |
1100 | 1100 | ||
1101 | ; Change state, as we have a fin |
1101 | ; Change state, as we have a fin |
1102 | mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
1102 | mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
1103 | 1103 | ||
1104 | lea esi, [ebx + SOCKET.RCV_NXT] |
1104 | lea esi, [ebx + SOCKET.RCV_NXT] |
1105 | call inc_inet_esi |
1105 | call inc_inet_esi |
1106 | 1106 | ||
1107 | ; Send an ACK |
1107 | ; Send an ACK |
1108 | mov eax, EMPTY_QUEUE |
1108 | mov eax, EMPTY_QUEUE |
1109 | call dequeue |
1109 | call dequeue |
1110 | cmp ax, NO_BUFFER |
1110 | cmp ax, NO_BUFFER |
1111 | je .exit |
1111 | je .exit |
1112 | 1112 | ||
1113 | push eax |
1113 | push eax |
1114 | 1114 | ||
1115 | mov bl, TH_ACK |
1115 | mov bl, TH_ACK |
1116 | xor ecx, ecx |
1116 | xor ecx, ecx |
1117 | xor esi, esi |
1117 | xor esi, esi |
1118 | stdcall build_tcp_packet, [sockAddr] |
1118 | stdcall build_tcp_packet, [sockAddr] |
1119 | 1119 | ||
1120 | mov eax, NET1OUT_QUEUE |
1120 | mov eax, NET1OUT_QUEUE |
1121 | mov edx, [stack_ip] |
1121 | mov edx, [stack_ip] |
1122 | mov ecx, [sockAddr] |
1122 | mov ecx, [sockAddr] |
1123 | cmp edx, [ecx + SOCKET.RemoteIP] |
1123 | cmp edx, [ecx + SOCKET.RemoteIP] |
1124 | jne .not_local |
1124 | jne .not_local |
1125 | mov eax, IPIN_QUEUE |
1125 | mov eax, IPIN_QUEUE |
1126 | 1126 | ||
1127 | .not_local: |
1127 | .not_local: |
1128 | ; Send it. |
1128 | ; Send it. |
1129 | pop ebx |
1129 | pop ebx |
1130 | call queue |
1130 | call queue |
1131 | 1131 | ||
1132 | .exit: |
1132 | .exit: |
1133 | ret |
1133 | ret |
1134 | endp |
1134 | endp |
1135 | 1135 | ||
1136 | 1136 | ||
1137 | proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD |
1137 | proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD |
1138 | ; Intentionally left empty |
1138 | ; Intentionally left empty |
1139 | ; socket_close_tcp handles this |
1139 | ; socket_close_tcp handles this |
1140 | ret |
1140 | ret |
1141 | endp |
1141 | endp |
1142 | 1142 | ||
1143 | 1143 | ||
1144 | proc stateTCB_CLOSING stdcall, sockAddr:DWORD |
1144 | proc stateTCB_CLOSING stdcall, sockAddr:DWORD |
1145 | ; We can either receive an ACK of a fin, or a fin |
1145 | ; We can either receive an ACK of a fin, or a fin |
1146 | test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
1146 | test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
1147 | jz .exit |
1147 | jz .exit |
1148 | 1148 | ||
1149 | mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
1149 | mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
1150 | 1150 | ||
1151 | .exit: |
1151 | .exit: |
1152 | ret |
1152 | ret |
1153 | endp |
1153 | endp |
1154 | 1154 | ||
1155 | 1155 | ||
1156 | proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD |
1156 | proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD |
1157 | ; Look at control flags - expecting an ACK |
1157 | ; Look at control flags - expecting an ACK |
1158 | test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
1158 | test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
1159 | jz .exit |
1159 | jz .exit |
1160 | 1160 | ||
1161 | ; delete the socket |
1161 | ; delete the socket |
1162 | stdcall net_socket_free, ebx |
1162 | stdcall net_socket_free, ebx |
1163 | 1163 | ||
1164 | .exit: |
1164 | .exit: |
1165 | ret |
1165 | ret |
1166 | endp |
1166 | endp |
1167 | 1167 | ||
1168 | 1168 | ||
1169 | proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD |
1169 | proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD |
1170 | ret |
1170 | ret |
1171 | endp |
1171 | endp |
1172 | 1172 | ||
1173 | 1173 | ||
1174 | proc stateTCB_CLOSED stdcall, sockAddr:DWORD |
1174 | proc stateTCB_CLOSED stdcall, sockAddr:DWORD |
1175 | ret |
1175 | ret |
1176 | endp |
1176 | endp |