Subversion Repositories Kolibri OS

Rev

Rev 2301 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1763 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Part of the tcp/ip network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
9
;;                                                                 ;;
10
;;    Based on the code of 4.4BSD                                  ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
17
$Revision: 2305 $
18
 
1733 hidnplayr 19
;-----------------------------------------------------------------
20
;
21
; TCP_input:
22
;
23
;  IN:  [esp] = ptr to buffer
24
;       [esp+4] = buffer size
25
;       ebx = ptr to device struct
26
;       ecx = segment size
27
;       edx = ptr to TCP segment
28
;
29
;       esi = ipv4 source address
30
;       edi = ipv4 dest   address
31
;
32
;  OUT: /
33
;
34
;-----------------------------------------------------------------
1830 hidnplayr 35
 
1733 hidnplayr 36
align 4
37
TCP_input:
38
 
39
       DEBUGF  1,"TCP_input size=%u ", ecx
40
; Offset must be greater than or equal to the size of the standard TCP header (20) and less than or equal to the TCP length.
41
 
2305 hidnplayr 42
	movzx	eax, [edx + TCP_header.DataOffset]
1733 hidnplayr 43
	and	eax, 0xf0
44
	shr	al, 2
45
 
46
	DEBUGF	1,"headersize=%u\n", eax
47
 
2305 hidnplayr 48
	cmp	eax, TCP_header.DataOffset
2300 hidnplayr 49
	jb	.drop_not_locked
1733 hidnplayr 50
 
51
;-------------------------------
52
; Now, re-calculate the checksum
53
 
54
	push	eax ecx edx
2305 hidnplayr 55
	pushw	[edx + TCP_header.Checksum]
56
	mov	[edx + TCP_header.Checksum], 0
1733 hidnplayr 57
	push	esi edi
58
	mov	esi, edx
59
	TCP_checksum (esp), (esp+4)
60
	pop	esi edi ; yes, swap them (we dont need dest addr)
61
	pop	cx	; previous checksum
62
	cmp	cx, dx
63
	pop	edx ecx esi
64
	jnz	.drop_not_locked
65
 
66
	DEBUGF	1,"Checksum is correct\n"
67
 
68
	sub	ecx, esi	; update packet size
2300 hidnplayr 69
	jb	.drop_not_locked
1733 hidnplayr 70
	DEBUGF	1,"we got %u bytes of data\n", ecx
71
 
72
;-----------------------------------------------------------------------------------------
73
; Check if this packet has a timestamp option (We do it here so we can process it quickly)
74
 
2305 hidnplayr 75
	cmp	esi, TCP_header.DataOffset + 12 	       ; Timestamp option is 12 bytes
2300 hidnplayr 76
	jb	.no_timestamp
1733 hidnplayr 77
	je	.is_ok
78
 
2305 hidnplayr 79
	cmp	byte [edx + sizeof.TCP_header + 12], TCP_OPT_EOL ; end of option list
1733 hidnplayr 80
	jne	.no_timestamp
81
 
82
  .is_ok:
2305 hidnplayr 83
	test	[edx + TCP_header.Flags], TH_SYN	       ; SYN flag must not be set
1733 hidnplayr 84
	jnz	.no_timestamp
85
 
2305 hidnplayr 86
	cmp	dword [edx + sizeof.TCP_header], 0x0101080a	 ; Timestamp header
1733 hidnplayr 87
	jne	.no_timestamp
88
 
89
	DEBUGF	1,"timestamp ok\n"
90
 
91
	; TODO: Parse the option
92
	; TODO: Set a Bit in the TCP to tell all options are parsed
93
 
94
  .no_timestamp:
95
 
96
;-------------------------------------------
97
; Convert Big-endian values to little endian
98
 
2305 hidnplayr 99
	ntohd	[edx + TCP_header.SequenceNumber]
100
	ntohd	[edx + TCP_header.AckNumber]
1733 hidnplayr 101
 
2305 hidnplayr 102
	ntohw	[edx + TCP_header.Window]
103
	ntohw	[edx + TCP_header.UrgentPointer]
104
	ntohw	[edx + TCP_header.SourcePort]
105
	ntohw	[edx + TCP_header.DestinationPort]
1733 hidnplayr 106
 
107
;------------------------------------------------------------
1831 hidnplayr 108
; Next thing to do is find the TCPS (thus, the socket pointer)
1733 hidnplayr 109
 
110
; IP Packet TCP Destination Port = local Port
111
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
112
; (IP Packet TCP Source Port = remote Port)  OR (remote Port = 0)
113
 
114
	mov	ebx, net_sockets
115
 
116
  .socket_loop:
117
	mov	ebx, [ebx + SOCKET.NextPtr]
118
	or	ebx, ebx
119
	jz	.drop_with_reset_not_locked
120
 
121
	cmp	[ebx + SOCKET.Domain], AF_INET4
122
	jne	.socket_loop
123
 
124
	cmp	[ebx + SOCKET.Protocol], IP_PROTO_TCP
125
	jne	.socket_loop
126
 
2305 hidnplayr 127
	mov	ax, [edx + TCP_header.DestinationPort]
1733 hidnplayr 128
	cmp	[ebx + TCP_SOCKET.LocalPort], ax
129
	jne	.socket_loop
130
 
131
	mov	eax, [ebx + IP_SOCKET.RemoteIP]
132
	cmp	eax, edi			; edi is source ip from packet
133
	je	@f
134
	test	eax, eax
135
	jnz	.socket_loop
136
       @@:
137
 
138
	mov	ax, [ebx + TCP_SOCKET.RemotePort]
2305 hidnplayr 139
	cmp	[edx + TCP_header.SourcePort] , ax
1733 hidnplayr 140
	je	.found_socket
141
	test	ax, ax
142
	jnz	.socket_loop
143
  .found_socket:
144
	DEBUGF	1,"Socket ptr: %x\n", ebx
145
 
146
; ebx now contains the pointer to the socket
147
 
148
;----------------------------
149
; Check if socket isnt closed
150
 
1831 hidnplayr 151
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_CLOSED
1733 hidnplayr 152
	je	.drop_not_locked
153
 
154
;----------------
155
; Lock the socket
156
 
1830 hidnplayr 157
	cmp	[ebx + SOCKET.lock], 0
158
	jne	.drop_not_locked     ;;; HACK ! HACK ! dirty fucking HACK !   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
159
 
1733 hidnplayr 160
	add	ebx, SOCKET.lock
161
	DEBUGF	1,"lock: %x\n", [ebx]
162
	call	wait_mutex
163
	sub	ebx, SOCKET.lock
164
 
1830 hidnplayr 165
 
1733 hidnplayr 166
	DEBUGF	1,"Socket locked\n"
167
 
168
;---------------------------------------
169
; unscale the window into a 32 bit value
170
 
2305 hidnplayr 171
	movzx	eax, [edx + TCP_header.Window]
1733 hidnplayr 172
	push	ecx
173
	mov	cl, [ebx + TCP_SOCKET.SND_SCALE]
174
	shl	eax, cl
2305 hidnplayr 175
	mov	dword [edx + TCP_header.Window], eax   ; word after window is checksum, we dont need checksum anymore
1733 hidnplayr 176
	pop	ecx
177
 
178
;-----------------------------------
179
; Is this socket a listening socket?
180
 
181
	test	[ebx + SOCKET.options], SO_ACCEPTCON
182
	jz	.no_listening_socket
183
 
1838 hidnplayr 184
	DEBUGF	1,"Accepting new connection\n"
185
 
186
	mov	[ebx + SOCKET.lock], 0
1733 hidnplayr 187
	call	SOCKET_fork
1838 hidnplayr 188
 
189
	test	eax, eax
1733 hidnplayr 190
	jz	.drop
191
 
2305 hidnplayr 192
	push	[edx - sizeof.IPv4_header + IPv4_header.DestinationAddress]	;;; FIXME
1733 hidnplayr 193
	pop	[eax + IP_SOCKET.LocalIP]
194
 
2305 hidnplayr 195
	push	[edx + TCP_header.DestinationPort]
1838 hidnplayr 196
	pop	[eax + TCP_SOCKET.LocalPort]
1733 hidnplayr 197
 
1831 hidnplayr 198
	mov	[eax + TCP_SOCKET.t_state], TCPS_LISTEN
1733 hidnplayr 199
 
1838 hidnplayr 200
;        mov     [ebx + SOCKET.lock], 0
201
	mov	ebx, eax
1733 hidnplayr 202
 
1838 hidnplayr 203
	jmp	.LISTEN
204
 
1733 hidnplayr 205
  .no_listening_socket:
206
 
207
;-------------------------------------
208
; Reset idle timer and keepalive timer
209
 
210
	mov	[ebx + TCP_SOCKET.t_idle], 0
211
	mov	[ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
212
 
213
;--------------------
214
; Process TCP options
215
 
2305 hidnplayr 216
	cmp	esi, TCP_header.DataOffset	       ; esi is headersize
1733 hidnplayr 217
	je	.no_options
218
 
219
	DEBUGF	1,"Segment has options\n"
220
 
2301 hidnplayr 221
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
222
	jz	.not_uni_xfer				; also no header prediction
1733 hidnplayr 223
 
2305 hidnplayr 224
	lea	edi, [edx + sizeof.TCP_header]
1733 hidnplayr 225
	lea	eax, [edx + esi]
226
 
227
  .opt_loop:
228
	cmp	edi, eax
2300 hidnplayr 229
	jae	.no_options
1733 hidnplayr 230
 
231
	cmp	byte [edi], TCP_OPT_EOL 	; end of option list?
232
	jz	.no_options
233
 
234
	cmp	byte [edi], TCP_OPT_NOP 	; nop ?
235
	jz	.opt_nop
236
 
237
	cmp	byte [edi], TCP_OPT_MAXSEG
238
	je	.opt_maxseg
239
 
240
	cmp	byte [edi], TCP_OPT_WINDOW
241
	je	.opt_window
242
 
243
	cmp	byte [edi], TCP_OPT_TIMESTAMP
244
	je	.opt_timestamp
245
 
246
	jmp	.no_options	; If we reach here, some unknown options were received, skip them all!
247
 
248
  .opt_nop:
249
	inc	edi
250
	jmp	.opt_loop
251
 
252
  .opt_maxseg:
253
	cmp	byte [edi+1], 4
254
	jne	.no_options		; error occured, ignore all options!
255
 
2305 hidnplayr 256
	test	[edx + TCP_header.Flags], TH_SYN
1733 hidnplayr 257
	jz	@f
258
 
259
	movzx	eax, word[edi+2]
260
	rol	ax, 8
261
	DEBUGF	1,"Maxseg: %u\n", ax
262
 
263
	mov	[ebx + TCP_SOCKET.t_maxseg], eax
264
 
265
       @@:
266
	add	edi, 4
267
	jmp	.opt_loop
268
 
269
 
270
  .opt_window:
271
	cmp	byte [edi+1], 3
272
	jne	.no_options
273
 
2305 hidnplayr 274
	test	[edx + TCP_header.Flags], TH_SYN
1733 hidnplayr 275
	jz	@f
276
 
277
	DEBUGF	1,"Got window option\n"
278
 
279
	;;;;;
280
       @@:
281
	add	edi, 3
282
	jmp	.opt_loop
283
 
284
 
285
  .opt_timestamp:
286
	cmp	byte [edi+1], 10
287
	jne	.no_options
288
 
289
	DEBUGF	1,"Got timestamp option\n"
290
 
291
	;;;;;
292
 
293
	add	edi, 10
294
	jmp	.opt_loop
295
 
296
  .no_options:
297
 
298
 
299
 
300
 
301
 
302
 
303
;-----------------------------------------------------------------------
304
; Time to do some header prediction (Original Principle by Van Jacobson)
305
 
306
; There are two common cases for an uni-directional data transfer.
307
;
308
; General rule: the packets has no control flags, is in-sequence,
309
;   window width didnt change and we're not retransmitting.
310
;
311
; Second rules:
312
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
313
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
314
;
315
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
316
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
317
 
1831 hidnplayr 318
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1733 hidnplayr 319
	jnz	.not_uni_xfer
320
 
2305 hidnplayr 321
	test	[edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
1733 hidnplayr 322
	jnz	.not_uni_xfer
323
 
2305 hidnplayr 324
	test	[edx + TCP_header.Flags], TH_ACK
1733 hidnplayr 325
	jz	.not_uni_xfer
326
 
2305 hidnplayr 327
	mov	eax, [edx + TCP_header.SequenceNumber]
1733 hidnplayr 328
	cmp	eax, [ebx + TCP_SOCKET.RCV_NXT]
329
	jne	.not_uni_xfer
330
 
2305 hidnplayr 331
	mov	eax, dword [edx + TCP_header.Window]
1733 hidnplayr 332
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
333
	jne	.not_uni_xfer
334
 
335
	mov	eax, [ebx + TCP_SOCKET.SND_NXT]
336
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
337
	jne	.not_uni_xfer
338
 
339
;---------------------------------------
340
; check if we are sender in the uni-xfer
341
 
342
; If the following 4 conditions are all true, this segment is a pure ACK.
343
;
344
; - The segment contains no data.
345
	test	ecx, ecx
346
	jnz	.not_sender
347
 
348
; - The congestion window is greater than or equal to the current send window.
349
;     This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance.
350
	mov	eax, [ebx + TCP_SOCKET.SND_CWND]
351
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
2300 hidnplayr 352
	jb	.not_uni_xfer
1733 hidnplayr 353
 
354
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
2305 hidnplayr 355
	mov	eax, [edx + TCP_header.AckNumber]
1733 hidnplayr 356
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
2300 hidnplayr 357
	ja	.not_uni_xfer
1733 hidnplayr 358
 
359
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
360
	sub	eax, [ebx + TCP_SOCKET.SND_UNA]
2300 hidnplayr 361
	jbe	.not_uni_xfer
1733 hidnplayr 362
 
363
	DEBUGF	1,"Header prediction: we are sender\n"
364
 
365
;---------------------------------
366
; Packet is a pure ACK, process it
367
 
368
; Update RTT estimators
369
 
1763 hidnplayr 370
;;; TODO
371
 
1733 hidnplayr 372
; Delete acknowledged bytes from send buffer
373
	pusha
374
	mov	ecx, eax
375
	lea	eax, [ebx + STREAM_SOCKET.snd]
376
	call	SOCKET_ring_free
377
	popa
378
 
379
; update window pointers
2305 hidnplayr 380
	mov	eax, [edx + TCP_header.AckNumber]
1763 hidnplayr 381
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
1733 hidnplayr 382
 
383
; Stop retransmit timer
1830 hidnplayr 384
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0
1733 hidnplayr 385
 
386
; Awaken waiting processes
1763 hidnplayr 387
	mov	[ebx + SOCKET.lock], 0
1733 hidnplayr 388
	mov	eax, ebx
389
	call	SOCKET_notify_owner
390
 
1763 hidnplayr 391
; Generate more output
392
	call	TCP_output
1733 hidnplayr 393
 
1763 hidnplayr 394
	jmp	.drop_not_locked
395
 
1733 hidnplayr 396
;-------------------------------------------------
397
; maybe we are the receiver in the uni-xfer then..
398
 
399
  .not_sender:
400
; - The amount of data in the segment is greater than 0 (data count is in ecx)
401
 
402
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
2305 hidnplayr 403
	mov	eax, [edx + TCP_header.AckNumber]
1733 hidnplayr 404
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
405
	jne	.not_uni_xfer
406
 
407
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
408
 
409
;;; TODO
410
 
411
	jnz	.not_uni_xfer
412
 
413
; Complete processing of received data
414
 
415
	DEBUGF	1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
416
 
1763 hidnplayr 417
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx 	; Update sequence number with number of bytes we have copied
418
 
1733 hidnplayr 419
	add	esi, edx
420
	lea	eax, [ebx + STREAM_SOCKET.rcv]
421
	call	SOCKET_ring_write			; Add the data to the socket buffer
422
 
423
	mov	eax, ebx
424
	call	SOCKET_notify_owner
425
 
426
	or	[ebx + TCP_SOCKET.t_flags], TF_DELACK	; Set delayed ack flag
427
 
428
	jmp	.drop
429
 
430
 
431
 
432
 
433
 
434
 
435
;--------------------------------------------------
436
; Header prediction failed, do it the slow way
437
 
438
  .not_uni_xfer:
439
 
440
	DEBUGF	1,"Header prediction failed\n"
441
 
442
; Calculate receive window size
443
 
2305 hidnplayr 444
;        mov     eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size]
445
;        neg     eax
446
;        add     eax, SOCKETBUFFSIZE
447
;        mov     edx, [ebx + TCP_SOCKET.RCV_ADV]
448
;        sub     edx, [ebx + TCP_SOCKET.RCV_NXT]
449
;        cmp     eax, edx
450
;        jae     @f
451
;        mov     eax, edx
452
;       @@:
1733 hidnplayr 453
 
1831 hidnplayr 454
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_LISTEN
1733 hidnplayr 455
	je	.LISTEN
456
 
1831 hidnplayr 457
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
1733 hidnplayr 458
	je	.SYN_SENT
459
 
460
	jmp	.NOT_LISTEN_OR_SYN_SENT
461
 
462
 
463
 
464
;-------------
465
; Passive Open
466
 
467
align 4
468
.LISTEN:
469
 
470
	DEBUGF	1,"TCP state: listen\n"
471
 
2305 hidnplayr 472
	test	[edx + TCP_header.Flags], TH_RST       ;;; TODO: kill new socket on error
1733 hidnplayr 473
	jnz	.drop
474
 
2305 hidnplayr 475
	test	[edx + TCP_header.Flags], TH_ACK
1733 hidnplayr 476
	jnz	.drop_with_reset
477
 
2305 hidnplayr 478
	test	[edx + TCP_header.Flags], TH_SYN
1733 hidnplayr 479
	jz	.drop
480
 
481
;;; TODO: check if it's a broadcast or multicast, and drop if so
482
 
2305 hidnplayr 483
	push	[edx - sizeof.IPv4_header + IPv4_header.SourceAddress]	   ;;; FIXME
1838 hidnplayr 484
	pop	[ebx + IP_SOCKET.RemoteIP]
1733 hidnplayr 485
 
2305 hidnplayr 486
	push	[edx + TCP_header.SourcePort]
1838 hidnplayr 487
	pop	[ebx + TCP_SOCKET.RemotePort]
1733 hidnplayr 488
 
2305 hidnplayr 489
	push	[edx + TCP_header.SequenceNumber]
1838 hidnplayr 490
	pop	[ebx + TCP_SOCKET.IRS]
1733 hidnplayr 491
 
1838 hidnplayr 492
	push	[TCP_sequence_num]     ;;;;;
493
	add	[TCP_sequence_num], 64000 / 2
494
	pop	[ebx + TCP_SOCKET.ISS]
1733 hidnplayr 495
 
1838 hidnplayr 496
	push	[ebx + TCP_SOCKET.ISS]
497
	pop	[ebx + TCP_SOCKET.SND_NXT]
1733 hidnplayr 498
 
1838 hidnplayr 499
	TCP_sendseqinit ebx
500
	TCP_rcvseqinit ebx
1733 hidnplayr 501
 
1838 hidnplayr 502
	mov	[ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
503
	mov	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
504
	mov	[ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
505
 
506
	lea	eax, [ebx + STREAM_SOCKET.snd]
1733 hidnplayr 507
	call	SOCKET_ring_create
508
 
1838 hidnplayr 509
	lea	eax, [ebx + STREAM_SOCKET.rcv]
1733 hidnplayr 510
	call	SOCKET_ring_create
511
 
1838 hidnplayr 512
;;;        call    SOCKET_notify_owner
1733 hidnplayr 513
 
514
	jmp	.trim_then_step6
1838 hidnplayr 515
 
1733 hidnplayr 516
 
517
 
518
 
519
 
520
 
521
 
522
 
523
 
1838 hidnplayr 524
 
1733 hidnplayr 525
;------------
526
; Active Open
527
 
528
align 4
529
.SYN_SENT:
530
 
531
	DEBUGF	1,"TCP state: syn_sent\n"
532
 
2305 hidnplayr 533
	test	[edx + TCP_header.Flags], TH_ACK
1733 hidnplayr 534
	jz	@f
535
 
2305 hidnplayr 536
	mov	eax, [edx + TCP_header.AckNumber]
1733 hidnplayr 537
	cmp	eax, [ebx + TCP_SOCKET.ISS]
2300 hidnplayr 538
	jbe	.drop_with_reset
1733 hidnplayr 539
 
540
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
2300 hidnplayr 541
	ja	.drop_with_reset
1733 hidnplayr 542
       @@:
543
 
2305 hidnplayr 544
	test	[edx + TCP_header.Flags], TH_RST
1733 hidnplayr 545
	jz	@f
546
 
2305 hidnplayr 547
	test	[edx + TCP_header.Flags], TH_ACK
1733 hidnplayr 548
	jz	.drop
549
 
550
	mov	eax, ebx
551
	mov	ebx, ECONNREFUSED
552
	call	TCP_drop
553
 
554
	jmp	.drop
555
       @@:
556
 
2305 hidnplayr 557
	test	[edx + TCP_header.Flags], TH_SYN
1733 hidnplayr 558
	jz	.drop
559
 
560
; at this point, segment seems to be valid
561
 
2305 hidnplayr 562
	test	[edx + TCP_header.Flags], TH_ACK
1733 hidnplayr 563
	jz	.no_syn_ack
564
 
565
; now, process received SYN in response to an active open
566
 
2305 hidnplayr 567
	mov	eax, [edx + TCP_header.AckNumber]
1733 hidnplayr 568
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
569
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
2300 hidnplayr 570
	jbe	@f
1733 hidnplayr 571
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
572
       @@:
573
 
574
  .no_syn_ack:
575
 
576
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0	; disable retransmission
577
 
2305 hidnplayr 578
	push	[edx + TCP_header.SequenceNumber]
1733 hidnplayr 579
	pop	[ebx + TCP_SOCKET.IRS]
580
 
581
	TCP_rcvseqinit ebx
582
 
1763 hidnplayr 583
	or	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1733 hidnplayr 584
 
585
	mov	eax, [ebx + TCP_SOCKET.SND_UNA]
586
	cmp	eax, [ebx + TCP_SOCKET.ISS]
2300 hidnplayr 587
	jbe	.simultaneous_open
1733 hidnplayr 588
 
2305 hidnplayr 589
	test	[edx + TCP_header.Flags], TH_ACK
1733 hidnplayr 590
	jz	.simultaneous_open
591
 
592
	DEBUGF	1,"TCP: active open\n"
593
 
594
;;; TODO: update stats
595
 
596
; set socket state to connected
597
 
598
	mov	[ebx + SOCKET.state],1	;;;; FIXME
599
 
1831 hidnplayr 600
	mov	[ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1733 hidnplayr 601
 
602
;;; TODO: check if we should scale the connection (567-572)
603
;;; TODO: update RTT estimators
604
 
605
	jmp	.trim_then_step6
606
 
607
  .simultaneous_open:
608
 
609
	DEBUGF	1,"TCP: simultaneous open\n"
610
; We have received a syn but no ACK, so we are having a simultaneous open..
1831 hidnplayr 611
	mov	[ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1733 hidnplayr 612
 
613
 
614
 
615
 
616
 
617
 
618
 
619
;-------------------------------------
620
; Common processing for receipt of SYN
621
 
622
  .trim_then_step6:
623
 
2305 hidnplayr 624
	inc	[edx + TCP_header.SequenceNumber]
1733 hidnplayr 625
 
626
;;; TODO: Drop any received data that follows receive window (590)
627
 
2305 hidnplayr 628
	mov	eax, [edx + TCP_header.SequenceNumber]
1733 hidnplayr 629
	mov	[ebx + TCP_SOCKET.RCV_UP], eax
630
	dec	eax
631
	mov	[ebx + TCP_SOCKET.SND_WL1], eax
632
 
633
	jmp	.ack_processed
634
 
635
 
636
 
637
 
638
 
639
 
640
 
641
 
642
  .NOT_LISTEN_OR_SYN_SENT:
643
 
644
	DEBUGF	1,"Slow TCP input: not listen or syn_sent state\n"
645
 
646
;--------------------------------------------
647
; Protection Against Wrapped Sequence Numbers
648
 
649
; First, check if timestamp is present
650
 
1763 hidnplayr 651
;;;; TODO 602
1733 hidnplayr 652
 
653
; Then, check if at least some bytes of data are within window
654
 
655
;;;; TODO
656
 
657
 
658
 
659
 
660
 
661
 
662
 
663
 
664
;----------------------------
665
; trim any data not in window
666
 
667
; check for duplicate data at beginning of segment
668
 
669
	mov	eax, [ebx + TCP_SOCKET.RCV_NXT]
2305 hidnplayr 670
	sub	eax, [edx + TCP_header.SequenceNumber]
2300 hidnplayr 671
	jbe	.no_duplicate
1733 hidnplayr 672
 
1830 hidnplayr 673
	DEBUGF	1,"Uh oh.. %u bytes of duplicate data!\n", eax
1763 hidnplayr 674
 
2305 hidnplayr 675
	test	[edx + TCP_header.Flags], TH_SYN
1763 hidnplayr 676
	jz	.no_dup_syn
1733 hidnplayr 677
 
678
; remove duplicate syn
679
 
2305 hidnplayr 680
	and	[edx + TCP_header.Flags], not (TH_SYN)
681
	inc	[edx + TCP_header.SequenceNumber]
1733 hidnplayr 682
 
2305 hidnplayr 683
	cmp	[edx + TCP_header.UrgentPointer], 1
2300 hidnplayr 684
	jbe	@f
2305 hidnplayr 685
	dec	[edx + TCP_header.UrgentPointer]
1838 hidnplayr 686
	jmp	.dup_syn
1733 hidnplayr 687
       @@:
2305 hidnplayr 688
	and	[edx + TCP_header.Flags], not (TH_URG)
1838 hidnplayr 689
  .dup_syn:
1733 hidnplayr 690
	dec	eax
1763 hidnplayr 691
  .no_dup_syn:
1733 hidnplayr 692
 
693
; eax holds number of bytes to drop
694
 
695
; Check for entire duplicate packet
696
 
697
	cmp	eax, ecx
2300 hidnplayr 698
	jae	.duplicate
1733 hidnplayr 699
 
1830 hidnplayr 700
	DEBUGF	1,"Going to drop %u out of %u bytes\n", eax, ecx
701
 
1733 hidnplayr 702
;;; TODO: apply figure 28.30
703
 
704
; Check for duplicate FIN
705
 
2305 hidnplayr 706
	test	[edx + TCP_header.Flags], TH_FIN
1733 hidnplayr 707
	jz	@f
708
	inc	ecx
709
	cmp	eax, ecx
710
	dec	ecx
711
	jne	@f
712
 
713
	mov	eax, ecx
2305 hidnplayr 714
	and	[edx + TCP_header.Flags], not TH_FIN
1733 hidnplayr 715
	or	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
716
	jmp	.no_duplicate
717
       @@:
718
 
719
; Handle the case when a bound socket connects to itself
720
; Allow packets with a SYN and an ACKto continue with the processing
721
 
722
;-------------------------------------
723
; Generate duplicate ACK if nescessary
724
 
725
; This code also handles simultaneous half-open or self-connects
726
 
727
	test	eax, eax
728
	jnz	.drop_after_ack
729
 
2305 hidnplayr 730
	cmp	[edx + TCP_header.Flags], TH_ACK
1733 hidnplayr 731
	jz	.drop_after_ack
732
 
733
  .duplicate:
734
 
735
	DEBUGF	1,"Duplicate received\n"
736
 
737
;----------------------------------------
738
; Update statistics for duplicate packets
739
 
740
;;; TODO
741
 
1830 hidnplayr 742
	jmp	.drop_after_ack
1733 hidnplayr 743
 
744
  .no_duplicate:
745
 
746
;-----------------------------------------------
747
; Remove duplicate data and update urgent offset
748
 
2305 hidnplayr 749
	add	[edx + TCP_header.SequenceNumber], eax
1733 hidnplayr 750
 
751
;;; TODO
752
 
2305 hidnplayr 753
	sub	[edx + TCP_header.UrgentPointer], ax
2300 hidnplayr 754
	ja	@f
1733 hidnplayr 755
 
2305 hidnplayr 756
	and	[edx + TCP_header.Flags], not (TH_URG)
757
	mov	[edx + TCP_header.UrgentPointer], 0
1733 hidnplayr 758
       @@:
759
 
760
;--------------------------------------------------
761
; Handle data that arrives after process terminates
762
 
763
	cmp	[ebx + SOCKET.PID], 0
2300 hidnplayr 764
	ja	@f
1733 hidnplayr 765
 
1831 hidnplayr 766
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
2300 hidnplayr 767
	jbe	@f
1733 hidnplayr 768
 
769
	test	ecx, ecx
770
	jz	@f
771
 
772
;;; Close the socket
773
;;; update stats
774
 
775
	jmp	.drop_with_reset
776
       @@:
777
 
778
;----------------------------------------
779
; Remove data beyond right edge of window
780
 
2305 hidnplayr 781
	mov	eax, [edx + TCP_header.SequenceNumber]
1733 hidnplayr 782
	add	eax, ecx
783
	sub	eax, [ebx + TCP_SOCKET.RCV_NXT]
784
	sub	ax, [ebx + TCP_SOCKET.RCV_WND]
785
 
786
; eax now holds the number of bytes to drop
787
 
2300 hidnplayr 788
	jbe	.no_excess_data
1733 hidnplayr 789
 
790
;;; TODO: update stats
791
 
792
	cmp	eax, ecx
2300 hidnplayr 793
	jb	.dont_drop_all
1733 hidnplayr 794
 
795
;;; TODO 700-736
796
 
797
  .dont_drop_all:
798
 
799
  .no_excess_data:
800
 
801
 
802
 
803
 
804
 
805
 
806
 
807
 
808
;-----------------
809
; Record timestamp
810
 
811
;;; TODO 737-746
812
 
813
 
814
 
815
 
816
 
817
;------------------
818
; Process RST flags
819
 
2305 hidnplayr 820
	test	[edx + TCP_header.Flags], TH_RST
1733 hidnplayr 821
	jz	.rst_skip
822
 
823
	DEBUGF	1,"Got an RST flag"
824
 
825
	mov	eax, [ebx + TCP_SOCKET.t_state]
826
	shl	eax, 2
827
	jmp	dword [eax + .rst_sw_list]
828
 
829
  .rst_sw_list:
1831 hidnplayr 830
	dd	.rst_skip	;TCPS_CLOSED
831
	dd	.rst_skip	;TCPS_LISTEN
832
	dd	.rst_skip	;TCPS_SYN_SENT
833
	dd	.econnrefused	;TCPS_SYN_RECEIVED
834
	dd	.econnreset	;TCPS_ESTABLISHED
835
	dd	.econnreset	;TCPS_CLOSE_WAIT
836
	dd	.econnreset	;TCPS_FIN_WAIT_1
837
	dd	.rst_close	;TCPS_CLOSING
838
	dd	.rst_close	;TCPS_LAST_ACK
839
	dd	.econnreset	;TCPS_FIN_WAIT_2
840
	dd	.rst_close	;TCPS_TIMED_WAIT
1733 hidnplayr 841
 
842
  .econnrefused:
843
	DEBUGF	1,"Connection refused"
844
 
1831 hidnplayr 845
	mov	[ebx + SOCKET.errorcode], ECONNREFUSED
1733 hidnplayr 846
	jmp	.close
847
 
848
  .econnreset:
849
	DEBUGF	1,"Connection reset"
850
 
1831 hidnplayr 851
	mov	[ebx + SOCKET.errorcode], ECONNRESET
1733 hidnplayr 852
 
1831 hidnplayr 853
    .close:
1733 hidnplayr 854
	DEBUGF	1,"Closing connection"
855
 
1831 hidnplayr 856
	mov	[ebx + TCP_SOCKET.t_state], TCPS_CLOSED
857
	;;; TODO: update stats
858
	mov	eax, ebx
859
	call	TCP_close
860
	jmp	.drop
1733 hidnplayr 861
 
862
  .rst_close:
863
	DEBUGF	1,"Closing with reset\n"
864
 
1831 hidnplayr 865
	mov	eax, ebx
866
	call	TCP_close
1733 hidnplayr 867
	jmp	.drop
868
 
869
 
870
 
871
 
872
 
873
 
874
 
1763 hidnplayr 875
  .rst_skip:
1733 hidnplayr 876
 
1763 hidnplayr 877
 
1733 hidnplayr 878
;--------------------------------------
879
; handle SYN-full and ACK-less segments
880
 
2305 hidnplayr 881
	test	[edx + TCP_header.Flags], TH_SYN
1733 hidnplayr 882
	jz	@f
883
 
1831 hidnplayr 884
	mov	eax, ebx
1733 hidnplayr 885
	mov	ebx, ECONNRESET
886
	call	TCP_drop
887
	jmp	.drop_with_reset
888
 
2305 hidnplayr 889
	test	[edx + TCP_header.Flags], TH_ACK
1733 hidnplayr 890
	jz	.drop
891
      @@:
892
 
893
 
894
 
895
 
896
 
897
 
898
 
899
;---------------
900
; ACK processing
901
 
1831 hidnplayr 902
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1733 hidnplayr 903
	jnz	.no_syn_rcv
904
 
905
	DEBUGF	1,"TCP state = syn received\n"
906
 
2305 hidnplayr 907
	mov	eax, [edx + TCP_header.AckNumber]
1838 hidnplayr 908
	cmp	[ebx + TCP_SOCKET.SND_UNA], eax
2300 hidnplayr 909
	ja	.drop_with_reset
1838 hidnplayr 910
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
2300 hidnplayr 911
	ja	.drop_with_reset
1733 hidnplayr 912
 
1831 hidnplayr 913
	;;; update stats
914
	mov	eax, ebx
915
	call	SOCKET_is_connected
916
	mov	[ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
917
 
918
; Do window scaling?
919
 
920
	test	[ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
921
	jz	@f
922
	test	[ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
923
	jz	@f
924
 
925
	;;; 810-811
926
 
927
       @@:
928
 
929
	;;; 813 ?
930
 
2305 hidnplayr 931
	mov	eax, [edx + TCP_header.SequenceNumber]
1831 hidnplayr 932
	dec	eax
933
	mov	[ebx + TCP_SOCKET.SND_WL1], eax
934
	jmp	.not_dup_ack
935
 
1733 hidnplayr 936
  .no_syn_rcv:
937
 
938
; check for duplicate ACK
939
 
2305 hidnplayr 940
	mov	eax, [edx + TCP_header.AckNumber]
1733 hidnplayr 941
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
2300 hidnplayr 942
	ja	.not_dup_ack
1733 hidnplayr 943
 
944
	test	ecx, ecx
1763 hidnplayr 945
	jnz	.reset_dupacks
1733 hidnplayr 946
 
2305 hidnplayr 947
	mov	eax, dword [edx + TCP_header.Window]
1733 hidnplayr 948
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
1763 hidnplayr 949
	jne	.reset_dupacks
1733 hidnplayr 950
 
1763 hidnplayr 951
	DEBUGF	1,"Processing a duplicate ACK..\n"
1733 hidnplayr 952
 
1763 hidnplayr 953
	cmp	[ebx + TCP_SOCKET.timer_retransmission], 10000 ;;;;
2300 hidnplayr 954
	ja	@f
1733 hidnplayr 955
 
2305 hidnplayr 956
	mov	eax, [edx + TCP_header.AckNumber]
1763 hidnplayr 957
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
958
	je	.dup_ack
959
 
960
       @@:
961
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
962
	jmp	.not_dup_ack
963
 
964
  .dup_ack:
965
	inc	[ebx + TCP_SOCKET.t_dupacks]
966
	cmp	[ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
967
	jne	.no_re_xmit
968
 
969
	push	[ebx + TCP_SOCKET.SND_NXT]		; >>>>
970
 
971
	mov	eax, [ebx + TCP_SOCKET.SND_WND]
972
	cmp	eax, [ebx + TCP_SOCKET.SND_CWND]
973
	cmovg	eax, [ebx + TCP_SOCKET.SND_CWND]
974
	shr	eax, 1
975
	push	edx
976
	xor	edx, edx
977
	div	[ebx + TCP_SOCKET.t_maxseg]
978
	cmp	eax, 2
2300 hidnplayr 979
	jae	@f
1763 hidnplayr 980
	mov	ax, 2
981
       @@:
982
	mul	[ebx + TCP_SOCKET.t_maxseg]
983
	pop	edx
984
	mov	[ebx + TCP_SOCKET.SND_SSTHRESH], eax
985
 
986
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0	; turn off retransmission timer
987
	mov	[ebx + TCP_SOCKET.t_rtt], 0
2305 hidnplayr 988
	mov	eax, [edx + TCP_header.AckNumber]
1763 hidnplayr 989
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
990
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
991
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
992
 
993
	mov	eax, ebx
994
	call	TCP_output					; retransmit missing segment
995
 
996
	push	edx
997
	xor	edx, edx
998
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
999
	mul	[ebx + TCP_SOCKET.t_dupacks]
1000
	pop	edx
1001
	add	eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
1002
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
1003
 
1004
	pop	eax					; <<<<
1005
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
2300 hidnplayr 1006
	jb	@f
1763 hidnplayr 1007
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1008
       @@:
1009
 
1733 hidnplayr 1010
	jmp	.drop
1011
 
1012
 
1763 hidnplayr 1013
  .no_re_xmit:
2300 hidnplayr 1014
	jbe	.not_dup_ack
1733 hidnplayr 1015
 
1763 hidnplayr 1016
	DEBUGF	1,"Increasing congestion window\n"
1733 hidnplayr 1017
 
1763 hidnplayr 1018
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
1019
	add	[ebx + TCP_SOCKET.SND_CWND], eax
1733 hidnplayr 1020
 
1763 hidnplayr 1021
	mov	eax, ebx
1022
	call	TCP_output
1733 hidnplayr 1023
 
1763 hidnplayr 1024
	jmp	.drop
1733 hidnplayr 1025
 
1026
 
1027
 
1763 hidnplayr 1028
 
1029
 
1030
 
1031
  .not_dup_ack:
1032
 
1733 hidnplayr 1033
;-------------------------------------------------
1034
; If the congestion window was inflated to account
1035
; for the other side's cached packets, retract it
1036
 
1763 hidnplayr 1037
	mov	eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
1038
	cmp	eax, [ebx + TCP_SOCKET.SND_CWND]
2300 hidnplayr 1039
	ja	@f
1763 hidnplayr 1040
	cmp	[ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
2300 hidnplayr 1041
	jbe	@f
1763 hidnplayr 1042
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
1043
       @@:
1733 hidnplayr 1044
 
1763 hidnplayr 1045
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
1733 hidnplayr 1046
 
2305 hidnplayr 1047
	mov	eax, [edx + TCP_header.AckNumber]
1763 hidnplayr 1048
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
2300 hidnplayr 1049
	jbe	@f
1733 hidnplayr 1050
 
1763 hidnplayr 1051
	;;; TODO: update stats
1052
	jmp	.drop_after_ack
1733 hidnplayr 1053
 
1763 hidnplayr 1054
       @@:
1733 hidnplayr 1055
 
2305 hidnplayr 1056
	mov	edi, [edx + TCP_header.AckNumber]
1763 hidnplayr 1057
	sub	edi, [ebx + TCP_SOCKET.SND_UNA] 	; now we got the number of acked bytes in esi
1733 hidnplayr 1058
 
1763 hidnplayr 1059
	;;; TODO: update stats
1733 hidnplayr 1060
 
1061
 
1763 hidnplayr 1062
	DEBUGF	1,"We have an acceptable ACK of %x bytes\n", esi
1063
 
1064
 
1065
 
1066
 
1067
 
1068
 
1733 hidnplayr 1069
;------------------------------------------
1070
; RTT measurements and retransmission timer
1071
 
1763 hidnplayr 1072
	;;;;; 912 - 926
1733 hidnplayr 1073
 
1074
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0
1075
 
1076
	mov	eax, [ebx + TCP_SOCKET.SND_MAX]
2305 hidnplayr 1077
	cmp	eax, [edx + TCP_header.AckNumber]
1733 hidnplayr 1078
	je	.all_outstanding
1079
	mov	[ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value (use a macro for it)
1080
  .all_outstanding:
1081
 
1082
 
1083
 
1084
 
1085
 
1086
 
1087
 
1088
;-------------------------------------------
1089
; Open congestion window in response to ACKs
1090
 
1763 hidnplayr 1091
	mov	esi, [ebx + TCP_SOCKET.SND_CWND]
1092
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
1733 hidnplayr 1093
 
1763 hidnplayr 1094
	cmp	esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
2300 hidnplayr 1095
	jbe	@f
1763 hidnplayr 1096
	push	edx
1097
	push	eax
1098
	mul	eax
1099
	div	esi
1100
	pop	edx
1101
	shr	edx, 3
1102
	add	eax, edx
1103
	pop	edx
1104
       @@:
1733 hidnplayr 1105
 
1763 hidnplayr 1106
	add	esi, eax
1733 hidnplayr 1107
 
1763 hidnplayr 1108
	push	ecx
1109
	mov	cl, [ebx + TCP_SOCKET.SND_SCALE]
1110
	mov	eax, TCP_max_win
1111
	shl	eax, cl
1112
	pop	ecx
1733 hidnplayr 1113
 
1763 hidnplayr 1114
	cmp	esi, eax
1115
	cmovg	esi, eax
1116
	mov	[ebx + TCP_SOCKET.SND_CWND], esi
1733 hidnplayr 1117
 
1118
 
1119
 
1120
 
1763 hidnplayr 1121
 
1122
 
1123
 
1733 hidnplayr 1124
;------------------------------------------
1125
; Remove acknowledged data from send buffer
1126
 
1763 hidnplayr 1127
	push	ecx edx ebx
1128
	mov	ecx, edi
1733 hidnplayr 1129
	lea	eax, [ebx + STREAM_SOCKET.snd]
1130
	call	SOCKET_ring_free
1763 hidnplayr 1131
	pop	ebx
1132
	sub	[ebx + TCP_SOCKET.SND_WND], ecx
1133
	pop	edx ecx
1733 hidnplayr 1134
 
1135
; Wake up process waiting on send buffer
1136
 
1137
	mov	eax, ebx
1138
	call	SOCKET_notify_owner
1139
 
1831 hidnplayr 1140
; Update TCPS
1733 hidnplayr 1141
 
2305 hidnplayr 1142
	mov	eax, [edx + TCP_header.AckNumber]
1733 hidnplayr 1143
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
1144
 
1145
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
2300 hidnplayr 1146
	jb	@f
1733 hidnplayr 1147
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1148
       @@:
1149
 
1150
 
1772 hidnplayr 1151
	;; TODO: use zero flag as 'ourfinisacked'
1733 hidnplayr 1152
 
1153
 
1154
 
1155
 
1156
; General ACK handling complete
1157
; Now do the state-specific ones
1158
 
1159
	mov	eax, [ebx + TCP_SOCKET.t_state]
1160
	jmp	dword [eax*4 + .ACK_sw_list]
1161
 
1162
  .ACK_sw_list:
1831 hidnplayr 1163
	dd	.ack_processed	;TCPS_CLOSED
1164
	dd	.ack_processed	;TCPS_LISTEN
1165
	dd	.ack_processed	;TCPS_SYN_SENT
1166
	dd	.ack_processed	;TCPS_SYN_RECEIVED
1167
	dd	.ack_processed	;TCPS_ESTABLISHED
1168
	dd	.ack_processed	;TCPS_CLOSE_WAIT
1169
	dd	.ack_fw1	;TCPS_FIN_WAIT_1
1170
	dd	.ack_c		;TCPS_CLOSING
1171
	dd	.ack_la 	;TCPS_LAST_ACK
1172
	dd	.ack_processed	;TCPS_FIN_WAIT_2
1173
	dd	.ack_tw 	;TCPS_TIMED_WAIT
1733 hidnplayr 1174
 
1175
 
1772 hidnplayr 1176
  .ack_fw1:
1177
	jz	.ack_processed
1733 hidnplayr 1178
 
1773 hidnplayr 1179
	test	[ebx + SOCKET.state], SS_CANTRCVMORE
1772 hidnplayr 1180
	jnz	@f
1773 hidnplayr 1181
	mov	eax, ebx
1182
	call	SOCKET_is_disconnected
1183
;;;        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
1772 hidnplayr 1184
       @@:
1733 hidnplayr 1185
 
1831 hidnplayr 1186
	mov	[ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1733 hidnplayr 1187
	jmp	.ack_processed
1188
 
1189
 
1772 hidnplayr 1190
  .ack_c:
1191
	jz	.ack_processed
1192
 
1831 hidnplayr 1193
	mov	[ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1773 hidnplayr 1194
	mov	eax, ebx
1772 hidnplayr 1195
	call	TCP_cancel_timers
1196
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1773 hidnplayr 1197
	mov	eax, ebx
1198
	call	SOCKET_is_disconnected
1733 hidnplayr 1199
	jmp	.ack_processed
1200
 
1201
 
1772 hidnplayr 1202
  .ack_la:
1203
	jz	.ack_processed
1733 hidnplayr 1204
 
1773 hidnplayr 1205
 
1206
	mov	eax, ebx
1772 hidnplayr 1207
	call	TCP_close
1208
	jmp	.drop
1733 hidnplayr 1209
 
1210
 
1772 hidnplayr 1211
  .ack_tw:
1212
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1213
	jmp	.drop_after_ack
1733 hidnplayr 1214
 
1215
 
1772 hidnplayr 1216
 
1217
 
1218
 
1219
 
1220
 
1763 hidnplayr 1221
  .reset_dupacks:		; We got a new ACK, reset duplicate ACK counter
1733 hidnplayr 1222
 
1763 hidnplayr 1223
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
1733 hidnplayr 1224
 
1225
  .ack_processed:	; (step 6)
1226
 
1227
	DEBUGF	1,"ACK processed\n"
1228
 
1229
;----------------------------------------------
1230
; check if we need to update window information
1231
 
2305 hidnplayr 1232
	test	[edx + TCP_header.Flags], TH_ACK
1733 hidnplayr 1233
	jz	.no_window_update
1234
 
1235
	mov	eax, [ebx + TCP_SOCKET.SND_WL1]
2305 hidnplayr 1236
	cmp	eax, [edx + TCP_header.SequenceNumber]
2300 hidnplayr 1237
	jb	.update_window
1238
	ja	@f
1733 hidnplayr 1239
 
1240
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
2305 hidnplayr 1241
	cmp	eax, [edx + TCP_header.AckNumber]
2300 hidnplayr 1242
	jb	.update_window
1243
	ja	.no_window_update
1733 hidnplayr 1244
       @@:
1245
 
1246
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
2305 hidnplayr 1247
	cmp	eax, [edx + TCP_header.AckNumber]
1733 hidnplayr 1248
	jne	.no_window_update
1249
 
2305 hidnplayr 1250
	movzx	eax, [edx + TCP_header.Window]
1733 hidnplayr 1251
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
2300 hidnplayr 1252
	jbe	.no_window_update
1733 hidnplayr 1253
 
1254
  .update_window:
1255
 
1256
	DEBUGF	1,"Updating window\n"
1257
 
1258
; Keep track of pure window updates
1259
 
1260
;        test    ecx, ecx
1261
;        jz      @f
1262
;
1263
;        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
2305 hidnplayr 1264
;        cmp     eax, [edx + TCP_header.AckNumber]
1733 hidnplayr 1265
;        jne     @f
1266
;
1267
;        ;; mov eax, tiwin
1268
;        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
2300 hidnplayr 1269
;        jbe     @f
1733 hidnplayr 1270
;
1271
;        ;;; update stats
1272
;
1273
;       @@:
1274
 
2305 hidnplayr 1275
	mov	eax, dword [edx + TCP_header.Window]
1733 hidnplayr 1276
	cmp	eax, [ebx + TCP_SOCKET.max_sndwnd]
2300 hidnplayr 1277
	jbe	@f
1733 hidnplayr 1278
	mov	[ebx + TCP_SOCKET.max_sndwnd], eax
1279
       @@:
1280
	mov	[ebx + TCP_SOCKET.SND_WND], eax
1281
 
2305 hidnplayr 1282
	push	[edx + TCP_header.SequenceNumber]
1733 hidnplayr 1283
	pop	[ebx + TCP_SOCKET.SND_WL1]
1284
 
2305 hidnplayr 1285
	push	[edx + TCP_header.AckNumber]
1733 hidnplayr 1286
	pop	[ebx + TCP_SOCKET.SND_WL2]
1287
 
1288
	;;; needoutput = 1
1289
 
1290
  .no_window_update:
1291
 
1292
 
1293
 
1294
 
1295
 
1296
 
1297
 
1298
;-----------------
1299
; process URG flag
1300
 
2305 hidnplayr 1301
	test	[edx + TCP_header.Flags], TH_URG
1733 hidnplayr 1302
	jz	.not_urgent
1303
 
2305 hidnplayr 1304
	cmp	[edx + TCP_header.UrgentPointer], 0
1733 hidnplayr 1305
	jz	.not_urgent
1306
 
1831 hidnplayr 1307
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1733 hidnplayr 1308
	je	.not_urgent
1309
 
1310
; Ignore bogus urgent offsets
1311
 
1312
	;;; 1040-1050
1313
 
2305 hidnplayr 1314
	movzx	eax, [edx + TCP_header.UrgentPointer]
1733 hidnplayr 1315
	add	eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size]
1316
	cmp	eax, SOCKET_MAXDATA
2300 hidnplayr 1317
	jbe	.not_urgent
1733 hidnplayr 1318
 
2305 hidnplayr 1319
	mov	[edx + TCP_header.UrgentPointer], 0
1320
	and	[edx + TCP_header.Flags], not (TH_URG)
1733 hidnplayr 1321
	jmp	.do_data
1322
 
1323
  .not_urgent:
1324
 
1325
; processing of received urgent pointer
1326
 
1327
	;;; TODO (1051-1093)
1328
 
1329
 
1330
 
1331
 
1332
 
1333
 
1334
 
1335
 
1336
;--------------------------------
1337
; process the data in the segment
1338
 
1339
  .do_data:
1340
 
1341
	DEBUGF	1,"TCP: do data (%u)\n", ecx
1342
 
2305 hidnplayr 1343
	test	[edx + TCP_header.Flags], TH_FIN
1733 hidnplayr 1344
	jnz	.process_fin
1345
 
1831 hidnplayr 1346
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_1
2300 hidnplayr 1347
	jae	.dont_do_data
1733 hidnplayr 1348
 
1349
	test	ecx, ecx
1350
	jz	.final_processing
1351
 
1352
	DEBUGF	1,"Processing data in segment\n"
1353
 
1354
;; TODO: check if data is in sequence !
1355
 
2305 hidnplayr 1356
	movzx	eax, [edx + TCP_header.DataOffset]	       ;;; todo: remember this in.. edi ?
1733 hidnplayr 1357
	and	eax, 0xf0
1358
	shr	al, 2
1359
 
1360
	lea	esi, [edx + eax]
1361
 
1362
	or	[ebx + TCP_SOCKET.t_flags], TF_DELACK
1363
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx
1364
 
1365
	lea	eax, [ebx + STREAM_SOCKET.rcv]
1366
	call	SOCKET_ring_write
1367
 
1368
	mov	eax, ebx
1369
	call	SOCKET_notify_owner
1370
 
1371
	jmp	.final_processing
1372
 
1373
 
1374
  .dont_do_data:
1375
 
1376
 
1377
 
1378
 
1379
 
1380
 
1381
 
1382
;---------------
1383
; FIN processing
1384
 
1385
  .process_fin:
1386
 
1387
	DEBUGF	1,"Processing FIN\n"
1388
 
1831 hidnplayr 1389
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1774 hidnplayr 1390
	je	.not_first_fin
1831 hidnplayr 1391
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1774 hidnplayr 1392
	je	.not_first_fin
1831 hidnplayr 1393
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1774 hidnplayr 1394
	je	.not_first_fin
1395
 
1396
	DEBUGF	1,"First FIN for this connection\n"
1397
 
1398
	mov	eax, ebx
1399
	call	SOCKET_cant_recv_more
1400
 
1401
	mov	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1402
	inc	[ebx + TCP_SOCKET.RCV_NXT]
1403
 
1404
  .not_first_fin:
1733 hidnplayr 1405
	mov	eax, [ebx + TCP_SOCKET.t_state]
1406
	shl	eax, 2
1407
	jmp	dword [eax + .FIN_sw_list]
1408
 
1409
  .FIN_sw_list:
1831 hidnplayr 1410
	dd	.no_fin 	;TCPS_CLOSED
1411
	dd	.no_fin 	;TCPS_LISTEN
1412
	dd	.no_fin 	;TCPS_SYN_SENT
1413
	dd	.fin_syn_est	;TCPS_SYN_RECEIVED
1414
	dd	.fin_syn_est	;TCPS_ESTABLISHED
1415
	dd	.no_fin 	;TCPS_CLOSE_WAIT
1416
	dd	.fin_wait1	;TCPS_FIN_WAIT_1
1417
	dd	.no_fin 	;TCPS_CLOSING
1418
	dd	.no_fin 	;TCPS_LAST_ACK
1419
	dd	.fin_wait2	;TCPS_FIN_WAIT_2
1420
	dd	.fin_timed	;TCPS_TIMED_WAIT
1733 hidnplayr 1421
 
1422
  .fin_syn_est:
1423
 
1831 hidnplayr 1424
	mov	[ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1774 hidnplayr 1425
	jmp	.no_fin
1733 hidnplayr 1426
 
1427
  .fin_wait1:
1428
 
1831 hidnplayr 1429
	mov	[ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1774 hidnplayr 1430
	jmp	.no_fin
1733 hidnplayr 1431
 
1432
  .fin_wait2:
1433
 
1831 hidnplayr 1434
	mov	[ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1774 hidnplayr 1435
	mov	eax, ebx
1436
	call	TCP_cancel_timers
1437
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1438
	call	SOCKET_is_disconnected
1439
	jmp	.no_fin
1733 hidnplayr 1440
 
1441
  .fin_timed:
1774 hidnplayr 1442
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1443
	jmp	.no_fin
1733 hidnplayr 1444
 
1445
  .no_fin:
1446
 
1447
 
1448
 
1449
 
1450
 
1451
 
1452
 
1453
 
1454
;-----------------
1455
; Final processing
1456
 
1457
  .final_processing:
1458
 
1459
	DEBUGF	1,"Final processing\n"
1460
 
1461
	;;; if debug enabled, output packet
1462
 
1463
	;test    needoutput, needoutput
1464
	;jz      .dumpit
1465
 
1466
	test	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1467
	jz	.dumpit
1468
 
1469
	DEBUGF	1,"ACK now!\n"
1470
 
1471
	push	ebx
1472
	mov	eax, ebx
1473
	call	TCP_output
1474
	pop	ebx
1475
 
1476
  .dumpit:
1477
 
1478
	mov	[ebx + SOCKET.lock], 0
1479
 
1480
	call	kernel_free
1481
	add	esp, 4
1482
	ret
1483
 
1484
 
1485
 
1486
 
1487
 
1488
 
1489
 
1490
;------------------------------------------
1491
; Generate an ACK, droping incoming segment
1492
 
1493
align 4
1494
.drop_after_ack:
1495
 
1496
	DEBUGF	1,"Drop after ACK\n"
1497
 
2305 hidnplayr 1498
	test	[edx + TCP_header.Flags], TH_RST
1733 hidnplayr 1499
	jnz	.drop
1500
 
1501
	and	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1502
 
1503
	mov	[ebx + SOCKET.lock], 0
1504
 
1505
	push	ebx
1838 hidnplayr 1506
;        mov     cl, TH_ACK
1507
;        call    TCP_respond_socket
1508
	mov	eax, ebx
1509
	call	TCP_output
1733 hidnplayr 1510
	pop	ebx
1511
 
1512
	call	kernel_free
1513
	add	esp, 4
1514
	ret
1515
 
1516
 
1517
 
1518
 
1519
 
1520
 
1521
 
1522
 
1523
;-------------------------------------------
1524
; Generate an RST, dropping incoming segment
1525
 
1526
align 4
1527
.drop_with_reset:
1528
 
1529
	mov	[ebx + SOCKET.lock], 0
1530
 
1531
.drop_with_reset_not_locked:
1532
 
1533
	DEBUGF	1,"Drop with reset\n"
1534
 
2305 hidnplayr 1535
	test	[edx + TCP_header.Flags], TH_RST
1733 hidnplayr 1536
	jnz	.drop
1537
 
1538
	;;; if its a multicast/broadcast, also drop
1539
 
2305 hidnplayr 1540
	test	[edx + TCP_header.Flags], TH_ACK
1733 hidnplayr 1541
	jnz	.respond_ack
1542
 
2305 hidnplayr 1543
	test	[edx + TCP_header.Flags], TH_SYN
1733 hidnplayr 1544
	jnz	.respond_syn
1545
 
1546
	call	kernel_free
1547
	add	esp, 4
1548
	ret
1549
 
1550
  .respond_ack:
1551
 
1552
	push	ebx
1830 hidnplayr 1553
	mov	cl, TH_RST
1554
	call	TCP_respond_socket
1733 hidnplayr 1555
	pop	ebx
1556
 
1557
	jmp	.destroy_new_socket
1558
 
1559
 
1560
  .respond_syn:
1561
 
1562
	push	ebx
1830 hidnplayr 1563
	mov	cl, TH_RST + TH_ACK
1733 hidnplayr 1564
	call	TCP_respond_socket
1565
	pop	ebx
1566
 
1567
	jmp	.destroy_new_socket
1568
 
1569
 
1570
 
1571
 
1572
 
1573
 
1574
 
1575
;-----
1576
; Drop
1577
 
1578
align 4
1579
.drop:
1580
 
1581
	mov	[ebx + SOCKET.lock], 0
1582
 
1583
.drop_not_locked:
1584
 
1585
	DEBUGF	1,"Dropping packet\n"
1586
 
1587
	;;;; If debugging options are enabled, output the packet somwhere
1588
 
1589
  .destroy_new_socket:
1590
 
1591
	;;;; kill the newly created socket
1592
 
1593
	call	kernel_free
1594
	add	esp, 4
1595
	ret