Rev 1196 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1196 | hidnplayr | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
||
3 | ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
||
4 | ;; Distributed under terms of the GNU General Public License ;; |
||
5 | ;; ;; |
||
6 | ;; TCP.INC ;; |
||
7 | ;; ;; |
||
8 | ;; Part of the tcp/ip network stack for KolibriOS ;; |
||
9 | ;; ;; |
||
10 | ;; Written by hidnplayr@kolibrios.org ;; |
||
11 | ;; ;; |
||
12 | ;; GNU GENERAL PUBLIC LICENSE ;; |
||
13 | ;; Version 2, June 1991 ;; |
||
14 | ;; ;; |
||
15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
1159 | hidnplayr | 16 | |
1196 | hidnplayr | 17 | |
1206 | hidnplayr | 18 | $Revision: 1206 $ |
1159 | hidnplayr | 19 | |
20 | |||
21 | ; TCP TCB states |
||
22 | TCB_LISTEN equ 1 |
||
23 | TCB_SYN_SENT equ 2 |
||
24 | TCB_SYN_RECEIVED equ 3 |
||
25 | TCB_ESTABLISHED equ 4 |
||
26 | TCB_FIN_WAIT_1 equ 5 |
||
27 | TCB_FIN_WAIT_2 equ 6 |
||
28 | TCB_CLOSE_WAIT equ 7 |
||
29 | TCB_CLOSING equ 8 |
||
30 | TCB_LAST_ACK equ 9 |
||
31 | TCB_TIMED_WAIT equ 10 |
||
32 | TCB_CLOSED equ 11 |
||
33 | |||
34 | TH_FIN equ 0x01 |
||
35 | TH_SYN equ 0x02 |
||
36 | TH_RST equ 0x04 |
||
37 | TH_PUSH equ 0x08 |
||
38 | TH_ACK equ 0x10 |
||
39 | TH_URG equ 0x20 |
||
40 | |||
1196 | hidnplayr | 41 | TWOMSL equ 10 ; # of secs to wait before closing socket |
1159 | hidnplayr | 42 | |
1196 | hidnplayr | 43 | TCP_RETRIES equ 5 ; Number of times to resend a Packet |
44 | TCP_TIMEOUT equ 10 ; resend if not replied to in x hs |
||
1159 | hidnplayr | 45 | |
1196 | hidnplayr | 46 | TCP_QUEUE_SIZE equ 16 |
47 | |||
1159 | hidnplayr | 48 | struct TCP_Packet |
49 | .SourcePort dw ? |
||
50 | .DestinationPort dw ? |
||
51 | .SequenceNumber dd ? |
||
52 | .AckNumber dd ? |
||
1196 | hidnplayr | 53 | .DataOffset db ? ; DataOffset[0-3 bits] and Reserved[4-7] |
54 | .Flags db ? ; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN |
||
1159 | hidnplayr | 55 | .Window dw ? |
56 | .Checksum dw ? |
||
57 | .UrgentPointer dw ? |
||
58 | .Options rb 3 |
||
59 | .Padding db ? |
||
60 | .Data: |
||
61 | ends |
||
62 | |||
1196 | hidnplayr | 63 | align 4 |
64 | uglobal |
||
65 | TCP_PACKETS_TX rd MAX_IP |
||
66 | TCP_PACKETS_RX rd MAX_IP |
||
1159 | hidnplayr | 67 | |
1196 | hidnplayr | 68 | TCP_IN_QUEUE rd 3*TCP_QUEUE_SIZE+3 |
69 | TCP_OUT_QUEUE rd 3*TCP_QUEUE_SIZE+3 |
||
70 | endg |
||
71 | |||
72 | |||
73 | |||
74 | |||
75 | |||
76 | ;----------------------------------------------------------------- |
||
77 | ; |
||
78 | ; TCP_init |
||
79 | ; |
||
80 | ; This function resets all TCP variables |
||
81 | ; |
||
82 | ; IN: / |
||
83 | ; OUT: / |
||
84 | ; |
||
85 | ;----------------------------------------------------------------- |
||
86 | |||
87 | align 4 |
||
88 | TCP_init: |
||
89 | |||
90 | xor eax, eax |
||
91 | mov edi, TCP_PACKETS_TX |
||
92 | mov ecx, 2*MAX_IP |
||
93 | rep stosd |
||
94 | |||
95 | mov dword [TCP_IN_QUEUE], TCP_QUEUE_SIZE |
||
96 | mov dword [TCP_IN_QUEUE+4], TCP_IN_QUEUE + queue.data |
||
97 | mov dword [TCP_IN_QUEUE+8], TCP_IN_QUEUE + queue.data |
||
98 | |||
99 | mov dword [TCP_OUT_QUEUE], TCP_QUEUE_SIZE |
||
100 | mov dword [TCP_OUT_QUEUE+4], TCP_OUT_QUEUE + queue.data |
||
101 | mov dword [TCP_OUT_QUEUE+8], TCP_OUT_QUEUE + queue.data |
||
102 | |||
103 | ret |
||
104 | |||
105 | |||
106 | ;----------------------------------------------------------------- |
||
107 | ; |
||
1159 | hidnplayr | 108 | ; tcp_tcb_handler |
109 | ; |
||
110 | ; Handles sockets in the timewait state, closing them |
||
111 | ; when the TCB timer expires |
||
112 | ; |
||
1196 | hidnplayr | 113 | ;----------------------------------------------------------------- |
1159 | hidnplayr | 114 | |
1196 | hidnplayr | 115 | align 4 |
1159 | hidnplayr | 116 | tcp_tcb_handler: |
117 | ; scan through all the sockets, decrementing active timers |
||
118 | |||
119 | mov ebx, net_sockets |
||
120 | |||
121 | cmp [ebx + SOCKET.NextPtr], 0 |
||
122 | je .exit |
||
123 | DEBUGF 1, "K : sockets:\n" |
||
124 | |||
125 | .next_socket: |
||
126 | mov ebx, [ebx + SOCKET.NextPtr] |
||
127 | or ebx, ebx |
||
128 | jz .exit |
||
129 | |||
1196 | hidnplayr | 130 | ; 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] |
1159 | hidnplayr | 131 | |
132 | cmp [ebx + SOCKET.TCBTimer], 0 |
||
133 | jne .decrement_tcb |
||
134 | cmp [ebx + SOCKET.wndsizeTimer], 0 |
||
135 | jne .decrement_wnd |
||
136 | jmp .next_socket |
||
137 | |||
138 | .decrement_tcb: |
||
139 | ; decrement it, delete socket if TCB timer = 0 & socket in timewait state |
||
140 | dec [ebx + SOCKET.TCBTimer] |
||
141 | jnz .next_socket |
||
142 | |||
143 | cmp [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
||
144 | jne .next_socket |
||
145 | |||
146 | push [ebx + SOCKET.PrevPtr] |
||
147 | stdcall net_socket_free, ebx |
||
148 | pop ebx |
||
149 | jmp .next_socket |
||
150 | |||
151 | .decrement_wnd: |
||
152 | ; TODO - prove it works! |
||
153 | dec [ebx + SOCKET.wndsizeTimer] |
||
154 | jmp .next_socket |
||
155 | |||
156 | .exit: |
||
157 | ret |
||
158 | |||
159 | |||
160 | ;*************************************************************************** |
||
161 | ; Function |
||
162 | ; tcp_tx_handler |
||
163 | ; |
||
164 | ; Description |
||
165 | ; Handles queued TCP data |
||
166 | ; This is a kernel function, called by stack_handler |
||
167 | ; |
||
168 | ;*************************************************************************** |
||
169 | |||
1196 | hidnplayr | 170 | align 4 |
171 | tcp_tx_handler: |
||
1159 | hidnplayr | 172 | ; decrement all resend buffers timers. If they |
173 | ; expire, queue them for sending, and restart the timer. |
||
174 | ; If the retries counter reach 0, delete the entry |
||
175 | |||
176 | mov esi, resendQ |
||
177 | mov ecx, 0 |
||
178 | |||
179 | .next_resendq: |
||
1196 | hidnplayr | 180 | ; cmp ecx, NUMRESENDENTRIES |
1159 | hidnplayr | 181 | je .exit ; None left |
182 | cmp dword[esi + 4], 0 |
||
183 | jne @f ; found one |
||
184 | inc ecx |
||
185 | add esi, 8 |
||
186 | jmp .next_resendq |
||
187 | |||
188 | @@: ; we have one. decrement it's timer by 1 |
||
189 | dec word[esi + 2] |
||
190 | jz @f |
||
191 | inc ecx |
||
192 | add esi, 8 |
||
193 | jmp .next_resendq ; Timer not zero, so move on |
||
194 | |||
195 | @@: |
||
196 | xor ebx, ebx |
||
197 | ; restart timer, and decrement retries |
||
198 | ; After the first resend, back of on next, by a factor of 5 |
||
199 | mov [esi + 2], word TCP_TIMEOUT * 5 |
||
200 | dec byte[esi + 1] |
||
201 | jnz @f |
||
202 | |||
203 | ; retries now 0, so delete from queue |
||
204 | xchg [esi + 4], ebx |
||
205 | |||
206 | @@: ; resend Packet |
||
207 | pushad |
||
208 | |||
1196 | hidnplayr | 209 | ; mov eax, EMPTY_QUEUE |
210 | ; call dequeue |
||
211 | ; cmp ax, NO_BUFFER |
||
1159 | hidnplayr | 212 | jne .tth004z |
213 | |||
214 | ; TODO - try again in 10ms. |
||
215 | test ebx, ebx |
||
216 | jnz @f |
||
217 | mov [esi + 4], ebx |
||
218 | |||
219 | @@: ; Mark it to expire in 10ms - 1 tick |
||
220 | mov byte[esi + 1], 1 |
||
221 | mov word[esi + 2], 1 |
||
222 | jmp .tth005 |
||
223 | |||
224 | .tth004z: |
||
225 | ; we have a buffer # in ax |
||
1196 | hidnplayr | 226 | ; push eax ecx |
227 | ; mov ecx, IPBUFFSIZE |
||
228 | ; mul ecx |
||
229 | ; add eax, IPbuffs |
||
1159 | hidnplayr | 230 | |
231 | ; we have the buffer address in eax |
||
232 | mov edi, eax |
||
233 | pop ecx |
||
234 | ; Now get buffer location, and copy buffer across. argh! more copying,, |
||
1196 | hidnplayr | 235 | ; mov esi, resendBuffer |
236 | ; @@: add esi, IPBUFFSIZE |
||
1159 | hidnplayr | 237 | loop @b |
238 | |||
239 | ; we have resend buffer location in esi |
||
1196 | hidnplayr | 240 | ; mov ecx, IPBUFFSIZE |
1159 | hidnplayr | 241 | |
242 | ; copy data across |
||
243 | push edi |
||
244 | cld |
||
245 | rep movsb |
||
246 | pop edi |
||
247 | |||
248 | ; queue Packet |
||
1196 | hidnplayr | 249 | ; mov eax, NET1OUT_QUEUE |
250 | ; mov edx, [IP_LIST] |
||
251 | ; cmp edx, [edi + IP_Packet.DestinationAddress] |
||
252 | ; jne .not_local |
||
253 | ; mov eax, IPIN_QUEUE |
||
1159 | hidnplayr | 254 | |
255 | .not_local: |
||
256 | pop ebx |
||
1196 | hidnplayr | 257 | ; call queue |
1159 | hidnplayr | 258 | |
259 | .tth005: |
||
260 | popad |
||
261 | |||
262 | inc ecx |
||
263 | add esi, 8 |
||
264 | jmp .next_resendq |
||
265 | |||
266 | .exit: |
||
267 | ret |
||
268 | |||
269 | |||
1196 | hidnplayr | 270 | |
271 | ;----------------------------------------------------------------- |
||
1159 | hidnplayr | 272 | ; |
1196 | hidnplayr | 273 | ; TCP_Handler: |
1159 | hidnplayr | 274 | ; |
1196 | hidnplayr | 275 | ; Called by IPv4_handler, |
276 | ; this procedure will inject the tcp data diagrams in the application sockets. |
||
277 | ; |
||
278 | ; IN: Pointer to buffer in [esp] |
||
279 | ; size of buffer in [esp+4] |
||
280 | ; pointer to device struct in ebx |
||
281 | ; TCP Packet size in ecx |
||
282 | ; pointer to TCP Packet data in edx |
||
283 | ; SourceAddres in esi |
||
284 | ; OUT: / |
||
285 | ; |
||
286 | ;----------------------------------------------------------------- |
||
1159 | hidnplayr | 287 | |
1196 | hidnplayr | 288 | TCP_Handler : |
1159 | hidnplayr | 289 | |
290 | |||
1196 | hidnplayr | 291 | DEBUGF 1,"TCP_Handler\n" |
292 | |||
293 | jmp .exit ;;;; |
||
294 | |||
1159 | hidnplayr | 295 | ; Look for a socket where |
296 | ; IP Packet TCP Destination Port = local Port |
||
297 | ; IP Packet SA = Remote IP |
||
298 | ; IP Packet TCP Source Port = remote Port |
||
299 | |||
300 | mov ebx, net_sockets |
||
301 | |||
302 | .next_socket.1: |
||
303 | mov ebx, [ebx + SOCKET.NextPtr] |
||
304 | or ebx, ebx |
||
305 | jz .next_socket.1.exit |
||
306 | |||
307 | ; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
||
308 | |||
1196 | hidnplayr | 309 | mov ax, [edx + TCP_Packet.DestinationPort] ; get the dest. port from the TCP hdr |
1159 | hidnplayr | 310 | cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr |
311 | jne .next_socket.1 ; different - try next socket |
||
312 | |||
313 | ; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_Packet.SourceAddress], [ebx + SOCKET.RemoteIP] |
||
314 | |||
1196 | hidnplayr | 315 | mov eax, esi ;[edx + IP_Packet.SourceAddress] ; get the source IP Addr from the IP hdr |
1159 | hidnplayr | 316 | cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP |
317 | jne .next_socket.1 ; different - try next socket |
||
318 | |||
319 | ; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_Packet.SourcePort]:4, [ebx + SOCKET.RemotePort]:4 |
||
320 | |||
1196 | hidnplayr | 321 | mov ax, [edx + TCP_Packet.SourcePort] ; get the source port from the TCP hdr |
1159 | hidnplayr | 322 | cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port |
323 | jne .next_socket.1 ; different - try next socket |
||
324 | |||
325 | ; We have a complete match - use this socket |
||
326 | jmp .change_state |
||
327 | |||
328 | .next_socket.1.exit: |
||
329 | |||
330 | ; If we got here, there was no match |
||
331 | ; Look for a socket where |
||
332 | ; IP Packet TCP Destination Port = local Port |
||
333 | ; IP Packet SA = Remote IP |
||
334 | ; socket remote Port = 0 |
||
335 | |||
336 | mov ebx, net_sockets |
||
337 | |||
338 | .next_socket.2: |
||
339 | mov ebx, [ebx + SOCKET.NextPtr] |
||
340 | or ebx, ebx |
||
341 | jz .next_socket.2.exit |
||
342 | |||
343 | ; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
||
344 | |||
1196 | hidnplayr | 345 | mov ax, [edx + TCP_Packet.DestinationPort] ; get the dest. port from the TCP hdr |
1159 | hidnplayr | 346 | cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
347 | jne .next_socket.2 ; different - try next socket |
||
348 | |||
349 | ; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_Packet.SourceAddress], [ebx + SOCKET.RemoteIP] |
||
350 | |||
1196 | hidnplayr | 351 | ; mov eax, esi ;[edx + IP_Packet.SourceAddress] ; get the source IP Addr from the IP hdr |
352 | cmp [ebx + SOCKET.RemoteIP], esi ; compare with socket's remote IP |
||
1159 | hidnplayr | 353 | jne .next_socket.2 ; different - try next socket |
354 | |||
355 | ; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 |
||
356 | |||
357 | cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 |
||
358 | jne .next_socket.2 ; different - try next socket |
||
359 | |||
360 | ; We have a complete match - use this socket |
||
361 | jmp .change_state |
||
362 | |||
363 | .next_socket.2.exit: |
||
364 | |||
365 | ; If we got here, there was no match |
||
366 | ; Look for a socket where |
||
367 | ; IP Packet TCP Destination Port = local Port |
||
368 | ; socket Remote IP = 0 |
||
369 | ; socket remote Port = 0 |
||
370 | |||
371 | mov ebx, net_sockets |
||
372 | |||
373 | .next_socket.3: |
||
374 | mov ebx, [ebx + SOCKET.NextPtr] |
||
375 | or ebx, ebx |
||
376 | jz .next_socket.3.exit |
||
377 | |||
378 | ; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
||
379 | |||
1196 | hidnplayr | 380 | mov ax, [edx + TCP_Packet.DestinationPort] ; get destination port from the TCP hdr |
1159 | hidnplayr | 381 | cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
382 | jne .next_socket.3 ; different - try next socket |
||
383 | |||
384 | ; DEBUGF 1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP] |
||
385 | |||
386 | cmp [ebx + SOCKET.RemoteIP], 0 ; only match a socket remote IP of 0 |
||
387 | jne .next_socket.3 ; different - try next socket |
||
388 | |||
389 | ; DEBUGF 1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 |
||
390 | |||
391 | cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 |
||
392 | jne .next_socket.3 ; different - try next socket |
||
393 | |||
394 | ; We have a complete match - use this socket |
||
395 | jmp .change_state |
||
396 | |||
397 | .next_socket.3.exit: |
||
398 | |||
399 | ; If we got here, we need to reject the Packet |
||
400 | |||
401 | DEBUGF 1, "K : tcp_rx - dumped\n" |
||
1196 | hidnplayr | 402 | ; 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 |
1159 | hidnplayr | 403 | |
1196 | hidnplayr | 404 | ; inc [dumped_rx_count] |
1159 | hidnplayr | 405 | jmp .exit |
406 | |||
407 | .change_state: |
||
408 | |||
409 | ; We have a valid socket/TCB, so call the TCB State Machine for that skt. |
||
410 | ; socket is pointed to by ebx |
||
411 | ; IP Packet is pointed to by edx |
||
412 | ; IP buffer number is on stack ( it will be popped at the end) |
||
413 | |||
414 | stdcall tcpStateMachine, ebx |
||
415 | |||
416 | .exit: |
||
417 | |||
1196 | hidnplayr | 418 | call kernel_free |
419 | add esp, 4 ; pop (balance stack) |
||
1159 | hidnplayr | 420 | |
1196 | hidnplayr | 421 | ret |
422 | |||
423 | |||
424 | |||
425 | ;----------------------------------------------------------------- |
||
426 | ; |
||
427 | ; IN: eax = dest ip |
||
428 | ; ebx = source ip |
||
429 | ; ecx = data length |
||
430 | ; edx = remote port shl 16 + local port |
||
431 | ; esi = data offset |
||
432 | ; |
||
433 | ;----------------------------------------------------------------- |
||
434 | |||
435 | TCP_create_Packet: |
||
436 | |||
437 | DEBUGF 1,"Create TCP Packet\n" |
||
1159 | hidnplayr | 438 | ;*************************************************************************** |
439 | ; Function |
||
440 | ; buildTCPPacket |
||
441 | ; |
||
442 | ; Description |
||
443 | ; builds an IP Packet with TCP data fully populated for transmission |
||
444 | ; You may destroy any and all registers |
||
445 | ; TCP control flags specified in bl |
||
446 | ; This TCB is in [sktAddr] |
||
447 | ; User data pointed to by esi |
||
448 | ; Data length in ecx |
||
449 | ; Transmit buffer number in eax |
||
450 | ; |
||
451 | ;*************************************************************************** |
||
452 | |||
453 | push ecx ; Save data length |
||
454 | |||
1196 | hidnplayr | 455 | add ecx, UDP_Packet.Data |
456 | mov di , IP_PROTO_UDP |
||
1159 | hidnplayr | 457 | |
1196 | hidnplayr | 458 | ; dx = fragment id |
1159 | hidnplayr | 459 | |
1196 | hidnplayr | 460 | call IPv4_create_Packet ; TODO: figure out a way to choose between IPv4 and IPv6 |
461 | cmp edi, -1 |
||
462 | je .exit |
||
1159 | hidnplayr | 463 | |
1196 | hidnplayr | 464 | mov [edi + TCP_Packet.Flags], bl ; TCP flags |
1159 | hidnplayr | 465 | |
1196 | hidnplayr | 466 | ; mov ebx, [sockAddr];---------------------------------------------------------- eof |
467 | |||
1159 | hidnplayr | 468 | ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr |
469 | |||
470 | ; Fill in the IP header ( some data is in the socket descriptor) |
||
471 | mov eax, [ebx + SOCKET.LocalIP] |
||
1196 | hidnplayr | 472 | ; mov [edx + IP_Packet.SourceAddress], eax |
1159 | hidnplayr | 473 | mov eax, [ebx + SOCKET.RemoteIP] |
1196 | hidnplayr | 474 | ; mov [edx + IP_Packet.DestinationAddress], eax |
1159 | hidnplayr | 475 | |
1196 | hidnplayr | 476 | ; mov [edx + IP_Packet.VersionAndIHL], 0x45 |
477 | ; mov [edx + IP_Packet.TypeOfService], 0 |
||
1159 | hidnplayr | 478 | |
479 | pop eax ; Get the TCP data length |
||
480 | push eax |
||
481 | |||
482 | add eax, 20 + 20 ; add IP header and TCP header lengths |
||
483 | rol ax, 8 |
||
1196 | hidnplayr | 484 | ; mov [edx + IP_Packet.TotalLength], ax |
485 | ; mov [edx + IP_Packet.Identification], 0 |
||
486 | ; mov [edx + IP_Packet.FlagsAndFragmentOffset], 0x0040 |
||
487 | ; mov [edx + IP_Packet.TimeToLive], 0x20 |
||
488 | ; mov [edx + IP_Packet.Protocol], PROTOCOL_TCP |
||
1159 | hidnplayr | 489 | |
490 | ; Checksum left unfilled |
||
1196 | hidnplayr | 491 | ; mov [edx + IP_Packet.HeaderChecksum], 0 |
1159 | hidnplayr | 492 | |
493 | ; Fill in the TCP header (some data is in the socket descriptor) |
||
494 | mov ax, [ebx + SOCKET.LocalPort] |
||
495 | mov [edx + 20 + TCP_Packet.SourcePort], ax ; Local Port |
||
496 | |||
497 | mov ax, [ebx + SOCKET.RemotePort] |
||
498 | mov [edx + 20 + TCP_Packet.DestinationPort], ax ; desitination Port |
||
499 | |||
500 | ; Checksum left unfilled |
||
501 | mov [edx + 20 + TCP_Packet.Checksum], 0 |
||
502 | |||
503 | ; sequence number |
||
504 | mov eax, [ebx + SOCKET.SND_NXT] |
||
505 | mov [edx + 20 + TCP_Packet.SequenceNumber], eax |
||
506 | |||
507 | ; ack number |
||
508 | mov eax, [ebx + SOCKET.RCV_NXT] |
||
509 | mov [edx + 20 + TCP_Packet.AckNumber], eax |
||
510 | |||
511 | ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) |
||
512 | ; 768 bytes seems better |
||
513 | mov [edx + 20 + TCP_Packet.Window], 0x0003 |
||
514 | |||
515 | ; Urgent pointer (0) |
||
516 | mov [edx + 20 + TCP_Packet.UrgentPointer], 0 |
||
517 | |||
518 | ; data offset ( 0x50 ) |
||
519 | mov [edx + 20 + TCP_Packet.DataOffset], 0x50 |
||
520 | |||
521 | pop ecx ; count of bytes to send |
||
522 | mov ebx, ecx ; need the length later |
||
523 | |||
524 | cmp ebx, 0 |
||
525 | jz @f |
||
526 | |||
527 | mov edi, edx |
||
528 | add edi, 40 |
||
529 | cld |
||
530 | rep movsb ; copy the data across |
||
531 | |||
532 | @@: ; we have edx as IPbuffer ptr. |
||
533 | ; Fill in the TCP checksum |
||
534 | ; First, fill in pseudoheader |
||
1196 | hidnplayr | 535 | ; mov eax, [edx + IP_Packet.SourceAddress] |
536 | ; mov [pseudoHeader], eax |
||
537 | ; mov eax, [edx + IP_Packet.DestinationAddress] |
||
538 | ; mov [pseudoHeader + 4], eax |
||
539 | ; mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0 |
||
540 | ; add ebx, 20 |
||
541 | ; mov [pseudoHeader + 10], bh |
||
542 | ; mov [pseudoHeader + 11], bl |
||
543 | ; |
||
544 | ; mov eax, pseudoHeader |
||
545 | ; mov [checkAdd1], eax |
||
546 | ; mov word[checkSize1], 12 |
||
547 | ; mov eax, edx |
||
548 | ; add eax, 20 |
||
549 | ; mov [checkAdd2], eax |
||
550 | ; mov eax, ebx |
||
551 | ; mov [checkSize2], ax |
||
552 | ; |
||
553 | ; call checksum |
||
1159 | hidnplayr | 554 | |
555 | ; store it in the TCP checksum ( in the correct order! ) |
||
1196 | hidnplayr | 556 | ; mov ax, [checkResult] |
557 | ; rol ax, 8 |
||
558 | ; mov [edx + 20 + TCP_Packet.Checksum], ax |
||
1159 | hidnplayr | 559 | |
560 | ; Fill in the IP header checksum |
||
1196 | hidnplayr | 561 | ; movzx eax, byte [edx + IP_Packet.VersionAndIHL] ; Calculate Header length by using IHL field |
562 | ; and eax, 0x0000000F ; |
||
563 | ; shl eax, 2 ; |
||
564 | ; |
||
1159 | hidnplayr | 565 | stdcall checksum_jb, edx, eax ; buf_ptr, buf_size |
566 | rol ax, 8 |
||
1196 | hidnplayr | 567 | ; mov [edx + IP_Packet.HeaderChecksum], ax |
1159 | hidnplayr | 568 | |
1196 | hidnplayr | 569 | |
570 | .exit: |
||
571 | |||
572 | call kernel_free |
||
573 | add esp, 4 ; pop (balance stack) |
||
574 | |||
1159 | hidnplayr | 575 | ret |
1196 | hidnplayr | 576 | ;endp |
1159 | hidnplayr | 577 | |
578 | |||
579 | ; Increments the 32 bit value pointed to by esi in internet order |
||
580 | proc inc_inet_esi stdcall |
||
1196 | hidnplayr | 581 | ; push eax |
582 | ; mov eax, [esi] |
||
583 | ; bswap eax |
||
584 | ; inc eax |
||
585 | ; bswap eax |
||
586 | ; mov [esi], eax |
||
587 | ; pop eax |
||
588 | ; ret |
||
589 | inc byte[esi+0] |
||
590 | adc byte[esi+1],0 |
||
591 | adc byte[esi+2],0 |
||
592 | adc byte[esi+3],0 |
||
1159 | hidnplayr | 593 | endp |
594 | |||
595 | |||
596 | ; Increments the 32 bit value pointed to by esi in internet order |
||
597 | ; by the value in ecx |
||
598 | proc add_inet_esi stdcall |
||
599 | push eax |
||
600 | mov eax, [esi] |
||
601 | bswap eax |
||
602 | add eax, ecx |
||
603 | bswap eax |
||
604 | mov [esi], eax |
||
605 | pop eax |
||
606 | ret |
||
607 | endp |
||
608 | |||
609 | |||
610 | iglobal |
||
611 | TCBStateHandler dd \ |
||
612 | stateTCB_LISTEN, \ |
||
613 | stateTCB_SYN_SENT, \ |
||
614 | stateTCB_SYN_RECEIVED, \ |
||
615 | stateTCB_ESTABLISHED, \ |
||
616 | stateTCB_FIN_WAIT_1, \ |
||
617 | stateTCB_FIN_WAIT_2, \ |
||
618 | stateTCB_CLOSE_WAIT, \ |
||
619 | stateTCB_CLOSING, \ |
||
620 | stateTCB_LAST_ACK, \ |
||
621 | stateTCB_TIME_WAIT, \ |
||
622 | stateTCB_CLOSED |
||
623 | endg |
||
624 | |||
625 | |||
626 | ;*************************************************************************** |
||
627 | ; Function |
||
628 | ; tcpStateMachine |
||
629 | ; |
||
630 | ; Description |
||
631 | ; TCP state machine |
||
632 | ; This is a kernel function, called by tcp_rx |
||
633 | ; |
||
634 | ; IP buffer address given in edx |
||
635 | ; Socket/TCB address in ebx |
||
636 | ; |
||
637 | ; The IP buffer will be released by the caller |
||
638 | ;*************************************************************************** |
||
639 | |||
640 | proc tcpStateMachine stdcall, sockAddr:DWORD |
||
641 | ; as a Packet has been received, update the TCB timer |
||
642 | mov [ebx + SOCKET.TCBTimer], TWOMSL |
||
643 | |||
644 | ; If the received Packet has an ACK bit set, |
||
645 | ; remove any Packets in the resend queue that this |
||
646 | ; received Packet acknowledges |
||
647 | pushad |
||
648 | test [edx + 20 + TCP_Packet.Flags], TH_ACK |
||
649 | jz .call_handler ; No ACK, so no data yet |
||
650 | |||
651 | ; get skt number in eax |
||
652 | stdcall net_socket_addr_to_num, ebx |
||
653 | |||
654 | ; The ack number is in [edx + 28], inet format |
||
655 | ; skt in eax |
||
656 | |||
657 | mov esi, resendQ |
||
658 | xor ecx, ecx |
||
659 | |||
660 | .next_resendq: |
||
1196 | hidnplayr | 661 | ; cmp ecx, NUMRESENDENTRIES |
1159 | hidnplayr | 662 | je .call_handler ; None left |
663 | cmp [esi + 4], eax |
||
664 | je @f ; found one |
||
665 | inc ecx |
||
666 | add esi, 8 |
||
667 | jmp .next_resendq |
||
668 | |||
669 | @@: ; Can we delete this buffer? |
||
670 | |||
671 | ; If yes, goto @@. No, goto .next_resendq |
||
672 | ; Get Packet data address |
||
673 | |||
674 | push ecx |
||
675 | ; Now get buffer location, and copy buffer across. argh! more copying,, |
||
1196 | hidnplayr | 676 | ; imul edi, ecx, IPBUFFSIZE |
677 | ; add edi, resendBuffer |
||
1159 | hidnplayr | 678 | |
679 | ; we have dest buffer location in edi. incoming Packet in edx. |
||
680 | ; Get this Packets sequence number |
||
681 | ; preserve al, ecx, esi, edx |
||
682 | mov ecx, [edi + 20 + TCP_Packet.SequenceNumber] |
||
683 | bswap ecx |
||
684 | movzx ebx, word[edi + 2] |
||
685 | xchg bl, bh |
||
686 | sub ebx, 40 |
||
687 | add ecx, ebx ; ecx is now seq# of last byte +1, intel format |
||
688 | |||
689 | ; get recievd ack #, in intel format |
||
690 | mov ebx, [edx + 20 + TCP_Packet.AckNumber] |
||
691 | bswap ebx |
||
692 | |||
693 | cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que |
||
694 | ; DANGER! need to handle case that we have just |
||
695 | ; passed the 2**32, and wrapped round! |
||
696 | pop ecx |
||
697 | jae @f ; if rx > old, delete old |
||
698 | |||
699 | inc ecx |
||
700 | add esi, 8 |
||
701 | jmp .next_resendq |
||
702 | |||
703 | @@: mov dword[esi + 4], 0 |
||
704 | inc ecx |
||
705 | add esi, 8 |
||
706 | jmp .next_resendq |
||
707 | |||
708 | .call_handler: |
||
709 | popad |
||
710 | |||
711 | ; Call handler for given TCB state |
||
712 | |||
713 | mov eax, [ebx + SOCKET.TCBState] |
||
714 | cmp eax, TCB_LISTEN |
||
715 | jb .exit |
||
716 | cmp eax, TCB_CLOSED |
||
717 | ja .exit |
||
718 | |||
719 | stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr] |
||
720 | |||
721 | .exit: |
||
722 | ret |
||
723 | endp |
||
724 | |||
725 | |||
726 | proc stateTCB_LISTEN stdcall, sockAddr:DWORD |
||
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 |
||
729 | ; If not, ignore it |
||
730 | |||
731 | ; Look at control flags |
||
732 | test [edx + 20 + TCP_Packet.Flags], TH_SYN |
||
733 | jz .exit |
||
734 | |||
735 | ; We have a SYN. update the socket with this IP Packets details, |
||
736 | ; And send a response |
||
737 | |||
1196 | hidnplayr | 738 | ; mov eax, [edx + IP_Packet.SourceAddress] |
739 | ; mov [ebx + SOCKET.RemoteIP], eax |
||
740 | ; mov ax, [edx + 20 + TCP_Packet.SourcePort] |
||
741 | ; mov [ebx + SOCKET.RemotePort], ax |
||
742 | ; mov eax, [edx + 20 + TCP_Packet.SequenceNumber] |
||
743 | ; mov [ebx + SOCKET.IRS], eax |
||
744 | ; mov [ebx + SOCKET.RCV_NXT], eax |
||
745 | ; lea esi, [ebx + SOCKET.RCV_NXT] |
||
746 | ; call inc_inet_esi ; RCV.NXT |
||
747 | ; mov eax, [ebx + SOCKET.ISS] |
||
748 | ; mov [ebx + SOCKET.SND_NXT], eax |
||
749 | ; |
||
1159 | hidnplayr | 750 | ; Now construct the response, and queue for sending by IP |
1196 | hidnplayr | 751 | ; mov eax, EMPTY_QUEUE |
752 | ; call dequeue |
||
753 | ; cmp ax, NO_BUFFER |
||
754 | ; je .exit |
||
1159 | hidnplayr | 755 | |
756 | push eax |
||
757 | mov bl, TH_SYN + TH_ACK |
||
758 | xor ecx, ecx |
||
759 | xor esi, esi |
||
1196 | hidnplayr | 760 | ; stdcall build_tcp_Packet, [sockAddr] |
1159 | hidnplayr | 761 | |
1196 | hidnplayr | 762 | ; mov eax, NET1OUT_QUEUE |
1159 | hidnplayr | 763 | ;;; mov edx, [stack_ip] |
764 | mov ecx, [sockAddr] |
||
765 | cmp edx, [ecx + SOCKET.RemoteIP] |
||
766 | jne .not_local |
||
1196 | hidnplayr | 767 | ; mov eax, IPIN_QUEUE |
1159 | hidnplayr | 768 | |
769 | .not_local: |
||
770 | ; Send it. |
||
771 | pop ebx |
||
1196 | hidnplayr | 772 | ;;; call queue |
1159 | hidnplayr | 773 | |
774 | mov esi, [sockAddr] |
||
775 | mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED |
||
776 | |||
777 | ; increment SND.NXT in socket |
||
778 | add esi, SOCKET.SND_NXT |
||
779 | call inc_inet_esi |
||
780 | |||
781 | .exit: |
||
782 | ret |
||
783 | endp |
||
784 | |||
785 | |||
786 | proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD |
||
787 | ; We are awaiting an ACK to our SYN, with a SYM |
||
788 | ; Look at control flags - expecting an ACK |
||
789 | |||
790 | mov al, [edx + 20 + TCP_Packet.Flags] |
||
791 | and al, TH_SYN + TH_ACK |
||
792 | cmp al, TH_SYN + TH_ACK |
||
793 | je .syn_ack |
||
794 | |||
795 | test al, TH_SYN |
||
796 | jz .exit |
||
797 | |||
798 | mov [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED |
||
799 | push TH_SYN + TH_ACK |
||
800 | jmp .send |
||
801 | |||
802 | .syn_ack: |
||
803 | mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED |
||
804 | push TH_ACK |
||
805 | |||
806 | .send: |
||
807 | ; Store the recv.nxt field |
||
808 | mov eax, [edx + 20 + TCP_Packet.SequenceNumber] |
||
809 | |||
810 | ; Update our recv.nxt field |
||
811 | mov [ebx + SOCKET.RCV_NXT], eax |
||
812 | lea esi, [ebx + SOCKET.RCV_NXT] |
||
813 | call inc_inet_esi |
||
814 | |||
815 | ; Send an ACK |
||
816 | ; Now construct the response, and queue for sending by IP |
||
1196 | hidnplayr | 817 | ; mov eax, EMPTY_QUEUE |
818 | ; call dequeue |
||
819 | ; cmp ax, NO_BUFFER |
||
1159 | hidnplayr | 820 | pop ebx |
821 | je .exit |
||
822 | |||
823 | push eax |
||
824 | |||
825 | xor ecx, ecx |
||
826 | xor esi, esi |
||
1196 | hidnplayr | 827 | ; stdcall build_tcp_Packet, [sockAddr] |
1159 | hidnplayr | 828 | |
1196 | hidnplayr | 829 | ; mov eax, NET1OUT_QUEUE |
1159 | hidnplayr | 830 | ;;; mov edx, [stack_ip] |
1196 | hidnplayr | 831 | ; mov ecx, [sockAddr] |
832 | ; cmp edx, [ecx + SOCKET.RemoteIP] |
||
833 | ; jne .not_local |
||
834 | ; mov eax, IPIN_QUEUE |
||
1159 | hidnplayr | 835 | |
836 | .not_local: |
||
837 | ; Send it. |
||
838 | pop ebx |
||
1196 | hidnplayr | 839 | ;;; call queue |
1159 | hidnplayr | 840 | |
841 | .exit: |
||
842 | ret |
||
843 | endp |
||
844 | |||
845 | |||
846 | proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD |
||
847 | ; In this case, we are expecting an ACK Packet |
||
848 | ; For now, if the Packet is an ACK, process it, |
||
849 | ; If not, ignore it |
||
850 | |||
851 | test [edx + 20 + TCP_Packet.Flags], TH_RST |
||
852 | jz .check_ack |
||
853 | |||
854 | push [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP] |
||
855 | pop [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort] |
||
856 | |||
857 | mov [ebx + SOCKET.TCBState], TCB_LISTEN |
||
858 | jmp .exit |
||
859 | |||
860 | .check_ack: |
||
861 | ; Look at control flags - expecting an ACK |
||
862 | test [edx + 20 + TCP_Packet.Flags], TH_ACK |
||
863 | jz .exit |
||
864 | |||
865 | mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED |
||
866 | |||
867 | .exit: |
||
868 | ret |
||
869 | endp |
||
870 | |||
871 | |||
872 | proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD |
||
873 | ; Here we are expecting data, or a request to close |
||
874 | ; OR both... |
||
875 | |||
876 | ; Did we receive a FIN or RST? |
||
877 | test [edx + 20 + TCP_Packet.Flags], TH_FIN |
||
878 | jz .check_ack |
||
879 | |||
880 | ; It was a fin or reset. |
||
881 | |||
882 | ; Remove resend entries from the queue - I dont want to send any more data |
||
883 | pushad |
||
884 | |||
885 | ; get skt # |
||
886 | stdcall net_socket_addr_to_num, ebx |
||
887 | |||
888 | mov esi, resendQ |
||
889 | mov ecx, 0 |
||
890 | |||
891 | .next_resendq: |
||
1196 | hidnplayr | 892 | ; cmp ecx, NUMRESENDENTRIES |
893 | ; je .last_resendq ; None left |
||
894 | ; cmp [esi + 4], eax |
||
895 | ; je @f ; found one |
||
896 | ; inc ecx |
||
897 | ; add esi, 8 |
||
898 | ; jmp .next_resendq |
||
1159 | hidnplayr | 899 | |
900 | @@: mov dword[esi + 4], 0 |
||
901 | inc ecx |
||
902 | add esi, 8 |
||
903 | jmp .next_resendq |
||
904 | |||
905 | .last_resendq: |
||
906 | popad |
||
907 | |||
908 | @@: ; Send an ACK to that fin, and enter closewait state |
||
909 | |||
910 | mov [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT |
||
911 | lea esi, [ebx + SOCKET.RCV_NXT] |
||
912 | mov eax, [esi] ; save original |
||
913 | call inc_inet_esi |
||
914 | ;; jmp ste_ack - NO, there may be data |
||
915 | |||
916 | .check_ack: |
||
917 | ; Check that we received an ACK |
||
918 | test [edx + 20 + TCP_Packet.Flags], TH_ACK |
||
919 | jz .exit |
||
920 | |||
921 | ; TODO - done, I think! |
||
922 | ; First, look at the incoming window. If this is less than or equal to 1024, |
||
923 | ; Set the socket window timer to 1. This will stop an additional Packets being queued. |
||
924 | ; ** I may need to tweak this value, since I do not know how many Packets are already queued |
||
925 | mov cx, [edx + 20 + TCP_Packet.Window] |
||
926 | xchg cl, ch |
||
927 | cmp cx, 1024 |
||
928 | ja @f |
||
929 | |||
930 | mov [ebx + SOCKET.wndsizeTimer], 1 |
||
931 | |||
932 | @@: ; OK, here is the deal |
||
933 | ; My recv.nct field holds the seq of the expected next rec byte |
||
934 | ; if the recevied sequence number is not equal to this, do not |
||
935 | ; increment the recv.nxt field, do not copy data - just send a |
||
936 | ; repeat ack. |
||
937 | |||
938 | ; recv.nxt is in dword [edx+24], in inet format |
||
939 | ; recv seq is in [sktAddr]+56, in inet format |
||
940 | ; just do a comparision |
||
941 | mov ecx, [ebx + SOCKET.RCV_NXT] |
||
942 | cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT |
||
943 | jne @f |
||
944 | mov ecx, eax |
||
945 | |||
946 | @@: cmp ecx, [edx + 20 + TCP_Packet.SequenceNumber] |
||
947 | jne .ack |
||
948 | |||
949 | |||
950 | ; Read the data bytes, store in socket buffer |
||
1196 | hidnplayr | 951 | ; movzx ecx, [edx + IP_Packet.TotalLength] |
1159 | hidnplayr | 952 | xchg cl, ch |
953 | sub ecx, 40 ; Discard 40 bytes of header |
||
954 | ja .data ; Read data, if any |
||
955 | |||
956 | ; If we had received a fin, we need to ACK it. |
||
957 | cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT |
||
958 | je .ack |
||
959 | jmp .exit |
||
960 | |||
961 | .data: |
||
962 | push ebx |
||
963 | add ebx, SOCKET.lock |
||
964 | call wait_mutex |
||
965 | pop ebx |
||
966 | |||
967 | push ecx |
||
968 | push [ebx + SOCKET.PID] ; get socket owner PID |
||
969 | mov eax, [ebx + SOCKET.rxDataCount] |
||
970 | add eax, ecx |
||
971 | cmp eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE |
||
972 | ja .overflow |
||
973 | |||
974 | mov [ebx + SOCKET.rxDataCount], eax ; increment the count of bytes in buffer |
||
975 | |||
976 | ; point to the location to store the data |
||
977 | lea edi, [ebx + eax + SOCKETHEADERSIZE] |
||
978 | sub edi, ecx |
||
979 | |||
980 | add edx, 40 ; edx now points to the data |
||
981 | mov esi, edx |
||
982 | |||
983 | cld |
||
984 | rep movsb ; copy the data across |
||
985 | mov [ebx + SOCKET.lock], 0 ; release mutex |
||
986 | |||
987 | ; flag an event to the application |
||
988 | pop eax |
||
989 | mov ecx, 1 |
||
990 | mov esi, TASK_DATA + TASKDATA.pid |
||
991 | |||
992 | .next_pid: |
||
993 | cmp [esi], eax |
||
994 | je .found_pid |
||
995 | inc ecx |
||
996 | add esi, 0x20 |
||
997 | cmp ecx, [TASK_COUNT] |
||
998 | jbe .next_pid |
||
999 | |||
1000 | .found_pid: |
||
1001 | shl ecx, 8 |
||
1002 | or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event |
||
1003 | |||
1004 | pop ecx |
||
1005 | |||
1006 | ; Update our recv.nxt field |
||
1007 | lea esi, [ebx + SOCKET.RCV_NXT] |
||
1008 | call add_inet_esi |
||
1009 | |||
1010 | .ack: |
||
1011 | ; Send an ACK |
||
1012 | ; Now construct the response, and queue for sending by IP |
||
1196 | hidnplayr | 1013 | ; mov eax, EMPTY_QUEUE |
1014 | ; call dequeue |
||
1015 | ; cmp ax, NO_BUFFER |
||
1159 | hidnplayr | 1016 | je .exit |
1017 | |||
1018 | push eax |
||
1019 | |||
1020 | mov bl, TH_ACK |
||
1021 | xor ecx, ecx |
||
1022 | xor esi, esi |
||
1196 | hidnplayr | 1023 | ; stdcall build_tcp_Packet, [sockAddr] |
1159 | hidnplayr | 1024 | |
1196 | hidnplayr | 1025 | ; mov eax, NET1OUT_QUEUE |
1159 | hidnplayr | 1026 | |
1027 | ;;; mov edx, [stack_ip] |
||
1196 | hidnplayr | 1028 | ; mov ecx, [sockAddr] |
1029 | ; cmp edx, [ecx + SOCKET.RemoteIP] |
||
1030 | ; jne .not_local |
||
1031 | ; mov eax, IPIN_QUEUE |
||
1159 | hidnplayr | 1032 | |
1033 | .not_local: |
||
1034 | ; Send it. |
||
1035 | pop ebx |
||
1196 | hidnplayr | 1036 | ;;; call queue |
1159 | hidnplayr | 1037 | |
1038 | .exit: |
||
1039 | ret |
||
1040 | .overflow: |
||
1041 | ; no place in buffer |
||
1042 | ; so simply restore stack and exit |
||
1043 | pop eax ecx |
||
1044 | mov [ebx + SOCKET.lock], 0 |
||
1045 | ret |
||
1046 | endp |
||
1047 | |||
1048 | |||
1049 | proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD |
||
1050 | ; We can either receive an ACK of a fin, or a fin |
||
1051 | mov al, [edx + 20 + TCP_Packet.Flags] |
||
1052 | and al, TH_FIN + TH_ACK |
||
1053 | |||
1054 | cmp al, TH_ACK |
||
1055 | jne @f |
||
1056 | |||
1057 | ; It was an ACK |
||
1058 | mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2 |
||
1059 | jmp .exit |
||
1060 | |||
1061 | @@: mov [ebx + SOCKET.TCBState], TCB_CLOSING |
||
1062 | cmp al, TH_FIN |
||
1063 | je @f |
||
1064 | mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
||
1065 | |||
1066 | @@: lea esi, [ebx + SOCKET.RCV_NXT] |
||
1067 | call inc_inet_esi |
||
1068 | |||
1069 | ; Send an ACK |
||
1196 | hidnplayr | 1070 | ; mov eax, EMPTY_QUEUE |
1071 | ; call dequeue |
||
1072 | ; cmp ax, NO_BUFFER |
||
1159 | hidnplayr | 1073 | je .exit |
1074 | |||
1075 | push eax |
||
1076 | |||
1077 | mov bl, TH_ACK |
||
1078 | xor ecx, ecx |
||
1079 | xor esi, esi |
||
1196 | hidnplayr | 1080 | ; stdcall build_tcp_Packet, [sockAddr] |
1159 | hidnplayr | 1081 | |
1196 | hidnplayr | 1082 | ; mov eax, NET1OUT_QUEUE |
1159 | hidnplayr | 1083 | ;;; mov edx, [stack_ip] |
1196 | hidnplayr | 1084 | ; mov ecx, [sockAddr] |
1085 | ; cmp edx, [ecx + SOCKET.RemoteIP] |
||
1086 | ; jne .not_local |
||
1087 | ; mov eax, IPIN_QUEUE |
||
1159 | hidnplayr | 1088 | |
1089 | .not_local: |
||
1090 | ; Send it. |
||
1091 | pop ebx |
||
1196 | hidnplayr | 1092 | ;;; call queue |
1159 | hidnplayr | 1093 | |
1094 | .exit: |
||
1095 | ret |
||
1096 | endp |
||
1097 | |||
1098 | |||
1099 | proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD |
||
1100 | test [edx + 20 + TCP_Packet.Flags], TH_FIN |
||
1101 | jz .exit |
||
1102 | |||
1103 | ; Change state, as we have a fin |
||
1104 | mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
||
1105 | |||
1106 | lea esi, [ebx + SOCKET.RCV_NXT] |
||
1107 | call inc_inet_esi |
||
1108 | |||
1109 | ; Send an ACK |
||
1196 | hidnplayr | 1110 | ; mov eax, EMPTY_QUEUE |
1111 | ; call dequeue |
||
1112 | ;; cmp ax, NO_BUFFER |
||
1113 | ; je .exit |
||
1159 | hidnplayr | 1114 | |
1115 | push eax |
||
1116 | |||
1117 | mov bl, TH_ACK |
||
1118 | xor ecx, ecx |
||
1119 | xor esi, esi |
||
1196 | hidnplayr | 1120 | ; stdcall build_tcp_Packet, [sockAddr] |
1159 | hidnplayr | 1121 | |
1196 | hidnplayr | 1122 | ; mov eax, NET1OUT_QUEUE |
1159 | hidnplayr | 1123 | ;;; mov edx, [stack_ip] |
1124 | mov ecx, [sockAddr] |
||
1125 | cmp edx, [ecx + SOCKET.RemoteIP] |
||
1126 | jne .not_local |
||
1196 | hidnplayr | 1127 | ; mov eax, IPIN_QUEUE |
1159 | hidnplayr | 1128 | |
1129 | .not_local: |
||
1130 | ; Send it. |
||
1131 | pop ebx |
||
1196 | hidnplayr | 1132 | ;;; call queue |
1159 | hidnplayr | 1133 | |
1134 | .exit: |
||
1135 | ret |
||
1136 | endp |
||
1137 | |||
1138 | |||
1139 | proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD |
||
1140 | ; Intentionally left empty |
||
1141 | ; socket_close_tcp handles this |
||
1142 | ret |
||
1143 | endp |
||
1144 | |||
1145 | |||
1146 | proc stateTCB_CLOSING stdcall, sockAddr:DWORD |
||
1147 | ; We can either receive an ACK of a fin, or a fin |
||
1148 | test [edx + 20 + TCP_Packet.Flags], TH_ACK |
||
1149 | jz .exit |
||
1150 | |||
1151 | mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT |
||
1152 | |||
1153 | .exit: |
||
1154 | ret |
||
1155 | endp |
||
1156 | |||
1157 | |||
1158 | proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD |
||
1159 | ; Look at control flags - expecting an ACK |
||
1160 | test [edx + 20 + TCP_Packet.Flags], TH_ACK |
||
1161 | jz .exit |
||
1162 | |||
1163 | ; delete the socket |
||
1164 | stdcall net_socket_free, ebx |
||
1165 | |||
1166 | .exit: |
||
1167 | ret |
||
1168 | endp |
||
1169 | |||
1170 | |||
1171 | proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD |
||
1172 | ret |
||
1173 | endp |
||
1174 | |||
1175 | |||
1176 | proc stateTCB_CLOSED stdcall, sockAddr:DWORD |
||
1177 | ret |
||
1178 | endp |
||
1179 | |||
1180 | |||
1181 | |||
1182 | ;; [53.7] Send data through STREAM socket |
||
1183 | ; |
||
1184 | ; @param EBX is socket number |
||
1185 | ; @param ECX is application data size (number of bytes to send) |
||
1186 | ; @param EDX is pointer to application data buffer |
||
1187 | ; @return 0 (sent successfully) or -1 (error) in EAX |
||
1188 | ;; |
||
1196 | hidnplayr | 1189 | ;proc socket_write_tcp stdcall |
1190 | ;local sockAddr dd ? |
||
1159 | hidnplayr | 1191 | |
1192 | ; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx |
||
1193 | stdcall net_socket_num_to_addr, ebx |
||
1194 | or eax, eax |
||
1195 | jz .error |
||
1196 | |||
1197 | mov ebx, eax |
||
1196 | hidnplayr | 1198 | ; mov [sockAddr], ebx |
1159 | hidnplayr | 1199 | |
1200 | ; If the sockets window timer is nonzero, do not queue Packet |
||
1201 | cmp [ebx + SOCKET.wndsizeTimer], 0 |
||
1202 | jne .error |
||
1203 | |||
1196 | hidnplayr | 1204 | ; mov eax, EMPTY_QUEUE |
1205 | ; call dequeue |
||
1206 | ; cmp ax, NO_BUFFER |
||
1207 | ; je .error |
||
1159 | hidnplayr | 1208 | |
1209 | push eax |
||
1210 | |||
1211 | ; Get the address of the callers data |
||
1212 | mov edi, [TASK_BASE] |
||
1213 | add edi, TASKDATA.mem_start |
||
1214 | add edx, [edi] |
||
1215 | mov esi, edx |
||
1216 | |||
1217 | pop eax |
||
1218 | push eax |
||
1219 | |||
1220 | push ecx |
||
1221 | mov bl, TH_ACK |
||
1196 | hidnplayr | 1222 | ; stdcall build_tcp_Packet, [sockAddr] |
1159 | hidnplayr | 1223 | pop ecx |
1224 | |||
1225 | ; Check destination IP address. |
||
1226 | ; If it is the local host IP, route it back to IP_RX |
||
1227 | |||
1228 | pop ebx |
||
1229 | push ecx |
||
1230 | |||
1196 | hidnplayr | 1231 | ; mov eax, NET1OUT_QUEUE |
1159 | hidnplayr | 1232 | ;;; TODO: get device id in edx |
1233 | xor edx, edx |
||
1234 | |||
1235 | shl edx, 2 |
||
1236 | mov edx, [IP_LIST+edx] |
||
1196 | hidnplayr | 1237 | ; mov ecx, [sockAddr] |
1238 | ; cmp edx, [ecx + SOCKET.RemoteIP] |
||
1239 | ; jne .not_local |
||
1240 | ; mov eax, IPIN_QUEUE |
||
1159 | hidnplayr | 1241 | |
1242 | .not_local: |
||
1243 | pop ecx |
||
1244 | push ebx ; save ipbuffer number |
||
1245 | |||
1196 | hidnplayr | 1246 | ;;;; call queue |
1159 | hidnplayr | 1247 | |
1196 | hidnplayr | 1248 | ; mov esi, [sockAddr] |
1159 | hidnplayr | 1249 | |
1250 | ; increament SND.NXT in socket |
||
1251 | ; Amount to increment by is in ecx |
||
1252 | add esi, SOCKET.SND_NXT |
||
1253 | call add_inet_esi |
||
1254 | |||
1255 | pop ebx |
||
1256 | |||
1257 | ; Copy the IP buffer to a resend queue |
||
1258 | ; If there isn't one, dont worry about it for now |
||
1259 | mov esi, resendQ |
||
1260 | mov ecx, 0 |
||
1261 | |||
1262 | .next_resendq: |
||
1196 | hidnplayr | 1263 | ; cmp ecx, NUMRESENDENTRIES |
1159 | hidnplayr | 1264 | je .exit ; None found |
1265 | cmp dword[esi + 4], 0 |
||
1266 | je @f ; found one |
||
1267 | inc ecx |
||
1268 | add esi, 8 |
||
1269 | jmp .next_resendq |
||
1270 | |||
1271 | @@: push ebx |
||
1272 | |||
1273 | ; OK, we have a buffer descriptor ptr in esi. |
||
1274 | ; resend entry # in ecx |
||
1275 | ; Populate it |
||
1276 | ; socket # |
||
1277 | ; retries count |
||
1278 | ; retry time |
||
1279 | ; fill IP buffer associated with this descriptor |
||
1280 | |||
1196 | hidnplayr | 1281 | ; stdcall net_socket_addr_to_num, [sockAddr] |
1159 | hidnplayr | 1282 | mov [esi + 4], eax |
1283 | mov byte[esi + 1], TCP_RETRIES |
||
1284 | mov word[esi + 2], TCP_TIMEOUT |
||
1285 | |||
1286 | inc ecx |
||
1287 | ; Now get buffer location, and copy buffer across. argh! more copying,, |
||
1196 | hidnplayr | 1288 | ; mov edi, resendBuffer - IPBUFFSIZE |
1159 | hidnplayr | 1289 | |
1196 | hidnplayr | 1290 | ; @@: add edi, IPBUFFSIZE |
1159 | hidnplayr | 1291 | loop @b |
1292 | |||
1293 | ; we have dest buffer location in edi |
||
1294 | pop eax |
||
1295 | ; convert source buffer pointer eax to the absolute address |
||
1196 | hidnplayr | 1296 | ; mov ecx, IPBUFFSIZE |
1297 | ; mul ecx |
||
1298 | ; add eax, IPbuffs |
||
1299 | ; mov esi, eax |
||
1159 | hidnplayr | 1300 | |
1301 | ; do copy |
||
1196 | hidnplayr | 1302 | ; mov ecx, IPBUFFSIZE |
1159 | hidnplayr | 1303 | ; cld |
1304 | rep movsb |
||
1305 | |||
1306 | .exit: |
||
1307 | xor eax, eax |
||
1308 | ret |
||
1309 | |||
1310 | .error: |
||
1311 | or eax, -1 |
||
1312 | ret |
||
1196 | hidnplayr | 1313 | ;endp |
1159 | hidnplayr | 1314 | |
1315 | |||
1316 | |||
1317 | ;*************************************************************************** |
||
1318 | ; Function |
||
1319 | ; checksum |
||
1320 | ; |
||
1321 | ; Description |
||
1322 | ; checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult |
||
1323 | ; Dont break anything; Most registers are used by the caller |
||
1324 | ; This code is derived from the 'C' source, cksum.c, in the book |
||
1325 | ; Internetworking with TCP/IP Volume II by D.E. Comer |
||
1326 | ; |
||
1327 | ;*************************************************************************** |
||
1328 | |||
1329 | |||
1330 | checksum: |
||
1331 | pusha |
||
1196 | hidnplayr | 1332 | ; mov eax, [checkAdd1] |
1159 | hidnplayr | 1333 | xor edx, edx ; edx is the accumulative checksum |
1334 | xor ebx, ebx |
||
1196 | hidnplayr | 1335 | ; mov cx, [checkSize1] |
1159 | hidnplayr | 1336 | shr cx, 1 |
1337 | jz cs1_1 |
||
1338 | |||
1339 | cs1: |
||
1340 | mov bh, [eax] |
||
1341 | mov bl, [eax + 1] |
||
1342 | |||
1343 | add eax, 2 |
||
1344 | add edx, ebx |
||
1345 | |||
1346 | loopw cs1 |
||
1347 | |||
1348 | cs1_1: |
||
1196 | hidnplayr | 1349 | ; and word [checkSize1], 0x01 |
1159 | hidnplayr | 1350 | jz cs_test2 |
1351 | |||
1352 | mov bh, [eax] |
||
1353 | xor bl, bl |
||
1354 | |||
1355 | add edx, ebx |
||
1356 | |||
1357 | cs_test2: |
||
1196 | hidnplayr | 1358 | ; mov cx, [checkSize2] |
1159 | hidnplayr | 1359 | cmp cx, 0 |
1360 | jz cs_exit ; Finished if no 2nd buffer |
||
1361 | |||
1196 | hidnplayr | 1362 | ; mov eax, [checkAdd2] |
1159 | hidnplayr | 1363 | |
1364 | shr cx, 1 |
||
1365 | jz cs2_1 |
||
1366 | |||
1367 | cs2: |
||
1368 | mov bh, [eax] |
||
1369 | mov bl, [eax + 1] |
||
1370 | |||
1371 | add eax, 2 |
||
1372 | add edx, ebx |
||
1373 | |||
1374 | loopw cs2 |
||
1375 | |||
1376 | cs2_1: |
||
1196 | hidnplayr | 1377 | ; and word [checkSize2], 0x01 |
1159 | hidnplayr | 1378 | jz cs_exit |
1379 | |||
1380 | mov bh, [eax] |
||
1381 | xor bl, bl |
||
1382 | |||
1383 | add edx, ebx |
||
1384 | |||
1385 | cs_exit: |
||
1386 | mov ebx, edx |
||
1387 | |||
1388 | shr ebx, 16 |
||
1389 | and edx, 0xffff |
||
1390 | add edx, ebx |
||
1391 | mov eax, edx |
||
1392 | shr eax, 16 |
||
1393 | add edx, eax |
||
1394 | not dx |
||
1395 | |||
1196 | hidnplayr | 1396 | ; mov [checkResult], dx |
1159 | hidnplayr | 1397 | popa |
1398 | ret |
||
1399 |