Subversion Repositories Kolibri OS

Rev

Rev 1831 | 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: 1838 $
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
 
42
	movzx	eax, [edx + TCP_segment.DataOffset]
43
	and	eax, 0xf0
44
	shr	al, 2
45
 
46
	DEBUGF	1,"headersize=%u\n", eax
47
 
48
	cmp	eax, 20
49
	jl	.drop_not_locked
50
 
51
;-------------------------------
52
; Now, re-calculate the checksum
53
 
54
	push	eax ecx edx
55
	pushw	[edx + TCP_segment.Checksum]
56
	mov	[edx + TCP_segment.Checksum], 0
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
69
	jl	.drop_not_locked
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
 
75
	cmp	esi, 20 + 12					; Timestamp option is 12 bytes
76
	jl	.no_timestamp
77
	je	.is_ok
78
 
79
	cmp	byte [edx + TCP_segment.Data + 12], TCP_OPT_EOL ; end of option list
80
	jne	.no_timestamp
81
 
82
  .is_ok:
83
	test	[edx + TCP_segment.Flags], TH_SYN		; SYN flag must not be set
84
	jnz	.no_timestamp
85
 
86
	cmp	dword [edx + TCP_segment.Data], 0x0101080a	; Timestamp header
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
 
99
	ntohd	[edx + TCP_segment.SequenceNumber]
100
	ntohd	[edx + TCP_segment.AckNumber]
101
 
102
	ntohw	[edx + TCP_segment.Window]
103
	ntohw	[edx + TCP_segment.UrgentPointer]
104
	ntohw	[edx + TCP_segment.SourcePort]
105
	ntohw	[edx + TCP_segment.DestinationPort]
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
 
127
	mov	ax, [edx + TCP_segment.DestinationPort]
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]
139
	cmp	[edx + TCP_segment.SourcePort] , ax
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
 
171
	movzx	eax, [edx + TCP_segment.Window]
172
	push	ecx
173
	mov	cl, [ebx + TCP_SOCKET.SND_SCALE]
174
	shl	eax, cl
175
	mov	dword [edx + TCP_segment.Window], eax	; word after window is checksum, we dont need checksum anymore
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
 
192
	push	[edx - IPv4_Packet.DataOrOptional + IPv4_Packet.DestinationAddress]	;;; FIXME
193
	pop	[eax + IP_SOCKET.LocalIP]
194
 
1838 hidnplayr 195
	push	[edx + TCP_segment.DestinationPort]
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
 
216
	cmp	esi, 20 			; esi is headersize
217
	je	.no_options
218
 
219
	DEBUGF	1,"Segment has options\n"
220
 
1831 hidnplayr 221
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_LISTEN 	 ; no options when in listen state
1733 hidnplayr 222
	jz	.not_uni_xfer					; also no header prediction
223
 
224
	lea	edi, [edx + TCP_segment.Data]
225
	lea	eax, [edx + esi]
226
 
227
  .opt_loop:
228
	cmp	edi, eax
229
	jge	.no_options
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
 
256
	test	[edx + TCP_segment.Flags], TH_SYN
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
 
274
	test	[edx + TCP_segment.Flags], TH_SYN
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
 
321
	test	[edx + TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
322
	jnz	.not_uni_xfer
323
 
324
	test	[edx + TCP_segment.Flags], TH_ACK
325
	jz	.not_uni_xfer
326
 
327
	mov	eax, [edx + TCP_segment.SequenceNumber]
328
	cmp	eax, [ebx + TCP_SOCKET.RCV_NXT]
329
	jne	.not_uni_xfer
330
 
331
	mov	eax, dword [edx + TCP_segment.Window]
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]
352
	jl	.not_uni_xfer
353
 
354
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
355
	mov	eax, [edx + TCP_segment.AckNumber]
356
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
357
	jg	.not_uni_xfer
358
 
359
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
360
	sub	eax, [ebx + TCP_SOCKET.SND_UNA]
361
	jle	.not_uni_xfer
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
380
	mov	eax, [edx + TCP_segment.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.
403
	mov	eax, [edx + TCP_segment.AckNumber]
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
 
1763 hidnplayr 444
;;;; TODO: 444
1733 hidnplayr 445
 
1831 hidnplayr 446
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_LISTEN
1733 hidnplayr 447
	je	.LISTEN
448
 
1831 hidnplayr 449
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
1733 hidnplayr 450
	je	.SYN_SENT
451
 
452
	jmp	.NOT_LISTEN_OR_SYN_SENT
453
 
454
 
455
 
456
;-------------
457
; Passive Open
458
 
459
align 4
460
.LISTEN:
461
 
462
	DEBUGF	1,"TCP state: listen\n"
463
 
464
	test	[edx + TCP_segment.Flags], TH_RST	;;; TODO: kill new socket on error
465
	jnz	.drop
466
 
467
	test	[edx + TCP_segment.Flags], TH_ACK
468
	jnz	.drop_with_reset
469
 
470
	test	[edx + TCP_segment.Flags], TH_SYN
471
	jz	.drop
472
 
473
;;; TODO: check if it's a broadcast or multicast, and drop if so
474
 
1838 hidnplayr 475
	push	[edx - IPv4_Packet.DataOrOptional + IPv4_Packet.SourceAddress]	   ;;; FIXME
476
	pop	[ebx + IP_SOCKET.RemoteIP]
1733 hidnplayr 477
 
478
	push	[edx + TCP_segment.SourcePort]
1838 hidnplayr 479
	pop	[ebx + TCP_SOCKET.RemotePort]
1733 hidnplayr 480
 
481
	push	[edx + TCP_segment.SequenceNumber]
1838 hidnplayr 482
	pop	[ebx + TCP_SOCKET.IRS]
1733 hidnplayr 483
 
1838 hidnplayr 484
	push	[TCP_sequence_num]     ;;;;;
485
	add	[TCP_sequence_num], 64000 / 2
486
	pop	[ebx + TCP_SOCKET.ISS]
1733 hidnplayr 487
 
1838 hidnplayr 488
	push	[ebx + TCP_SOCKET.ISS]
489
	pop	[ebx + TCP_SOCKET.SND_NXT]
1733 hidnplayr 490
 
1838 hidnplayr 491
	TCP_sendseqinit ebx
492
	TCP_rcvseqinit ebx
1733 hidnplayr 493
 
1838 hidnplayr 494
	mov	[ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
495
	mov	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
496
	mov	[ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
497
 
498
	lea	eax, [ebx + STREAM_SOCKET.snd]
1733 hidnplayr 499
	call	SOCKET_ring_create
500
 
1838 hidnplayr 501
	lea	eax, [ebx + STREAM_SOCKET.rcv]
1733 hidnplayr 502
	call	SOCKET_ring_create
503
 
1838 hidnplayr 504
;;;        call    SOCKET_notify_owner
1733 hidnplayr 505
 
506
	jmp	.trim_then_step6
1838 hidnplayr 507
 
1733 hidnplayr 508
 
509
 
510
 
511
 
512
 
513
 
514
 
515
 
1838 hidnplayr 516
 
1733 hidnplayr 517
;------------
518
; Active Open
519
 
520
align 4
521
.SYN_SENT:
522
 
523
	DEBUGF	1,"TCP state: syn_sent\n"
524
 
525
	test	[edx + TCP_segment.Flags], TH_ACK
526
	jz	@f
527
 
528
	mov	eax, [edx + TCP_segment.AckNumber]
529
	cmp	eax, [ebx + TCP_SOCKET.ISS]
530
	jle	.drop_with_reset
531
 
532
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
533
	jg	.drop_with_reset
534
       @@:
535
 
536
	test	[edx + TCP_segment.Flags], TH_RST
537
	jz	@f
538
 
539
	test	[edx + TCP_segment.Flags], TH_ACK
540
	jz	.drop
541
 
542
	mov	eax, ebx
543
	mov	ebx, ECONNREFUSED
544
	call	TCP_drop
545
 
546
	jmp	.drop
547
       @@:
548
 
549
	test	[edx + TCP_segment.Flags], TH_SYN
550
	jz	.drop
551
 
552
; at this point, segment seems to be valid
553
 
554
	test	[edx + TCP_segment.Flags], TH_ACK
555
	jz	.no_syn_ack
556
 
557
; now, process received SYN in response to an active open
558
 
559
	mov	eax, [edx + TCP_segment.AckNumber]
560
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
561
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
562
	jle	@f
563
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
564
       @@:
565
 
566
  .no_syn_ack:
567
 
568
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0	; disable retransmission
569
 
570
	push	[edx + TCP_segment.SequenceNumber]
571
	pop	[ebx + TCP_SOCKET.IRS]
572
 
573
	TCP_rcvseqinit ebx
574
 
1763 hidnplayr 575
	or	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1733 hidnplayr 576
 
577
	mov	eax, [ebx + TCP_SOCKET.SND_UNA]
578
	cmp	eax, [ebx + TCP_SOCKET.ISS]
579
	jle	.simultaneous_open
580
 
581
	test	[edx + TCP_segment.Flags], TH_ACK
582
	jz	.simultaneous_open
583
 
584
	DEBUGF	1,"TCP: active open\n"
585
 
586
;;; TODO: update stats
587
 
588
; set socket state to connected
589
 
590
	mov	[ebx + SOCKET.state],1	;;;; FIXME
591
 
1831 hidnplayr 592
	mov	[ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1733 hidnplayr 593
 
594
;;; TODO: check if we should scale the connection (567-572)
595
;;; TODO: update RTT estimators
596
 
597
	jmp	.trim_then_step6
598
 
599
  .simultaneous_open:
600
 
601
	DEBUGF	1,"TCP: simultaneous open\n"
602
; We have received a syn but no ACK, so we are having a simultaneous open..
1831 hidnplayr 603
	mov	[ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1733 hidnplayr 604
 
605
 
606
 
607
 
608
 
609
 
610
 
611
;-------------------------------------
612
; Common processing for receipt of SYN
613
 
614
  .trim_then_step6:
615
 
616
	inc	[edx + TCP_segment.SequenceNumber]
617
 
618
;;; TODO: Drop any received data that follows receive window (590)
619
 
620
	mov	eax, [edx + TCP_segment.SequenceNumber]
621
	mov	[ebx + TCP_SOCKET.RCV_UP], eax
622
	dec	eax
623
	mov	[ebx + TCP_SOCKET.SND_WL1], eax
624
 
625
	jmp	.ack_processed
626
 
627
 
628
 
629
 
630
 
631
 
632
 
633
 
634
  .NOT_LISTEN_OR_SYN_SENT:
635
 
636
	DEBUGF	1,"Slow TCP input: not listen or syn_sent state\n"
637
 
638
;--------------------------------------------
639
; Protection Against Wrapped Sequence Numbers
640
 
641
; First, check if timestamp is present
642
 
1763 hidnplayr 643
;;;; TODO 602
1733 hidnplayr 644
 
645
; Then, check if at least some bytes of data are within window
646
 
647
;;;; TODO
648
 
649
 
650
 
651
 
652
 
653
 
654
 
655
 
656
;----------------------------
657
; trim any data not in window
658
 
659
; check for duplicate data at beginning of segment
660
 
661
	mov	eax, [ebx + TCP_SOCKET.RCV_NXT]
662
	sub	eax, [edx + TCP_segment.SequenceNumber]
1763 hidnplayr 663
	jle	.no_duplicate
1733 hidnplayr 664
 
1830 hidnplayr 665
	DEBUGF	1,"Uh oh.. %u bytes of duplicate data!\n", eax
1763 hidnplayr 666
 
1733 hidnplayr 667
	test	[edx + TCP_segment.Flags], TH_SYN
1763 hidnplayr 668
	jz	.no_dup_syn
1733 hidnplayr 669
 
670
; remove duplicate syn
671
 
672
	and	[edx + TCP_segment.Flags], not (TH_SYN)
673
	inc	[edx + TCP_segment.SequenceNumber]
674
 
675
	cmp	[edx + TCP_segment.UrgentPointer], 1
1838 hidnplayr 676
	jle	@f
1733 hidnplayr 677
	dec	[edx + TCP_segment.UrgentPointer]
1838 hidnplayr 678
	jmp	.dup_syn
1733 hidnplayr 679
       @@:
680
	and	[edx + TCP_segment.Flags], not (TH_URG)
1838 hidnplayr 681
  .dup_syn:
1733 hidnplayr 682
	dec	eax
1763 hidnplayr 683
  .no_dup_syn:
1733 hidnplayr 684
 
685
; eax holds number of bytes to drop
686
 
687
; Check for entire duplicate packet
688
 
689
	cmp	eax, ecx
690
	jge	.duplicate
691
 
1830 hidnplayr 692
	DEBUGF	1,"Going to drop %u out of %u bytes\n", eax, ecx
693
 
1733 hidnplayr 694
;;; TODO: apply figure 28.30
695
 
696
; Check for duplicate FIN
697
 
698
	test	[edx + TCP_segment.Flags], TH_FIN
699
	jz	@f
700
	inc	ecx
701
	cmp	eax, ecx
702
	dec	ecx
703
	jne	@f
704
 
705
	mov	eax, ecx
706
	and	[edx + TCP_segment.Flags], not TH_FIN
707
	or	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
708
	jmp	.no_duplicate
709
       @@:
710
 
711
; Handle the case when a bound socket connects to itself
712
; Allow packets with a SYN and an ACKto continue with the processing
713
 
714
;-------------------------------------
715
; Generate duplicate ACK if nescessary
716
 
717
; This code also handles simultaneous half-open or self-connects
718
 
719
	test	eax, eax
720
	jnz	.drop_after_ack
721
 
722
	cmp	[edx + TCP_segment.Flags], TH_ACK
723
	jz	.drop_after_ack
724
 
725
  .duplicate:
726
 
727
	DEBUGF	1,"Duplicate received\n"
728
 
729
;----------------------------------------
730
; Update statistics for duplicate packets
731
 
732
;;; TODO
733
 
1830 hidnplayr 734
	jmp	.drop_after_ack
1733 hidnplayr 735
 
736
  .no_duplicate:
737
 
738
;-----------------------------------------------
739
; Remove duplicate data and update urgent offset
740
 
741
	add	[edx + TCP_segment.SequenceNumber], eax
742
 
743
;;; TODO
744
 
745
	sub	[edx + TCP_segment.UrgentPointer], ax
746
	jg	@f
747
 
748
	and	[edx + TCP_segment.Flags], not (TH_URG)
749
	mov	[edx + TCP_segment.UrgentPointer], 0
750
       @@:
751
 
752
;--------------------------------------------------
753
; Handle data that arrives after process terminates
754
 
755
	cmp	[ebx + SOCKET.PID], 0
756
	jg	@f
757
 
1831 hidnplayr 758
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1733 hidnplayr 759
	jle	@f
760
 
761
	test	ecx, ecx
762
	jz	@f
763
 
764
;;; Close the socket
765
;;; update stats
766
 
767
	jmp	.drop_with_reset
768
       @@:
769
 
770
;----------------------------------------
771
; Remove data beyond right edge of window
772
 
773
	mov	eax, [edx + TCP_segment.SequenceNumber]
774
	add	eax, ecx
775
	sub	eax, [ebx + TCP_SOCKET.RCV_NXT]
776
	sub	ax, [ebx + TCP_SOCKET.RCV_WND]
777
 
778
; eax now holds the number of bytes to drop
779
 
780
	jle	.no_excess_data
781
 
782
;;; TODO: update stats
783
 
784
	cmp	eax, ecx
785
	jl	.dont_drop_all
786
 
787
;;; TODO 700-736
788
 
789
  .dont_drop_all:
790
 
791
  .no_excess_data:
792
 
793
 
794
 
795
 
796
 
797
 
798
 
799
 
800
;-----------------
801
; Record timestamp
802
 
803
;;; TODO 737-746
804
 
805
 
806
 
807
 
808
 
809
;------------------
810
; Process RST flags
811
 
812
	test	[edx + TCP_segment.Flags], TH_RST
813
	jz	.rst_skip
814
 
815
	DEBUGF	1,"Got an RST flag"
816
 
817
	mov	eax, [ebx + TCP_SOCKET.t_state]
818
	shl	eax, 2
819
	jmp	dword [eax + .rst_sw_list]
820
 
821
  .rst_sw_list:
1831 hidnplayr 822
	dd	.rst_skip	;TCPS_CLOSED
823
	dd	.rst_skip	;TCPS_LISTEN
824
	dd	.rst_skip	;TCPS_SYN_SENT
825
	dd	.econnrefused	;TCPS_SYN_RECEIVED
826
	dd	.econnreset	;TCPS_ESTABLISHED
827
	dd	.econnreset	;TCPS_CLOSE_WAIT
828
	dd	.econnreset	;TCPS_FIN_WAIT_1
829
	dd	.rst_close	;TCPS_CLOSING
830
	dd	.rst_close	;TCPS_LAST_ACK
831
	dd	.econnreset	;TCPS_FIN_WAIT_2
832
	dd	.rst_close	;TCPS_TIMED_WAIT
1733 hidnplayr 833
 
834
  .econnrefused:
835
	DEBUGF	1,"Connection refused"
836
 
1831 hidnplayr 837
	mov	[ebx + SOCKET.errorcode], ECONNREFUSED
1733 hidnplayr 838
	jmp	.close
839
 
840
  .econnreset:
841
	DEBUGF	1,"Connection reset"
842
 
1831 hidnplayr 843
	mov	[ebx + SOCKET.errorcode], ECONNRESET
1733 hidnplayr 844
 
1831 hidnplayr 845
    .close:
1733 hidnplayr 846
	DEBUGF	1,"Closing connection"
847
 
1831 hidnplayr 848
	mov	[ebx + TCP_SOCKET.t_state], TCPS_CLOSED
849
	;;; TODO: update stats
850
	mov	eax, ebx
851
	call	TCP_close
852
	jmp	.drop
1733 hidnplayr 853
 
854
  .rst_close:
855
	DEBUGF	1,"Closing with reset\n"
856
 
1831 hidnplayr 857
	mov	eax, ebx
858
	call	TCP_close
1733 hidnplayr 859
	jmp	.drop
860
 
861
 
862
 
863
 
864
 
865
 
866
 
1763 hidnplayr 867
  .rst_skip:
1733 hidnplayr 868
 
1763 hidnplayr 869
 
1733 hidnplayr 870
;--------------------------------------
871
; handle SYN-full and ACK-less segments
872
 
873
	test	[edx + TCP_segment.Flags], TH_SYN
874
	jz	@f
875
 
1831 hidnplayr 876
	mov	eax, ebx
1733 hidnplayr 877
	mov	ebx, ECONNRESET
878
	call	TCP_drop
879
	jmp	.drop_with_reset
880
 
881
	test	[edx + TCP_segment.Flags], TH_ACK
882
	jz	.drop
883
      @@:
884
 
885
 
886
 
887
 
888
 
889
 
890
 
891
;---------------
892
; ACK processing
893
 
1831 hidnplayr 894
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1733 hidnplayr 895
	jnz	.no_syn_rcv
896
 
897
	DEBUGF	1,"TCP state = syn received\n"
898
 
1831 hidnplayr 899
	mov	eax, [edx + TCP_segment.AckNumber]
1838 hidnplayr 900
	cmp	[ebx + TCP_SOCKET.SND_UNA], eax
1831 hidnplayr 901
	jg	.drop_with_reset
1838 hidnplayr 902
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
903
	jg	.drop_with_reset
1733 hidnplayr 904
 
1831 hidnplayr 905
	;;; update stats
906
	mov	eax, ebx
907
	call	SOCKET_is_connected
908
	mov	[ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
909
 
910
; Do window scaling?
911
 
912
	test	[ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
913
	jz	@f
914
	test	[ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
915
	jz	@f
916
 
917
	;;; 810-811
918
 
919
       @@:
920
 
921
	;;; 813 ?
922
 
923
	mov	eax, [edx + TCP_segment.SequenceNumber]
924
	dec	eax
925
	mov	[ebx + TCP_SOCKET.SND_WL1], eax
926
	jmp	.not_dup_ack
927
 
1733 hidnplayr 928
  .no_syn_rcv:
929
 
930
; check for duplicate ACK
931
 
932
	mov	eax, [edx + TCP_segment.AckNumber]
933
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
934
	jg	.not_dup_ack
935
 
936
	test	ecx, ecx
1763 hidnplayr 937
	jnz	.reset_dupacks
1733 hidnplayr 938
 
939
	mov	eax, dword [edx + TCP_segment.Window]
940
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
1763 hidnplayr 941
	jne	.reset_dupacks
1733 hidnplayr 942
 
1763 hidnplayr 943
	DEBUGF	1,"Processing a duplicate ACK..\n"
1733 hidnplayr 944
 
1763 hidnplayr 945
	cmp	[ebx + TCP_SOCKET.timer_retransmission], 10000 ;;;;
946
	jg	@f
1733 hidnplayr 947
 
1763 hidnplayr 948
	mov	eax, [edx + TCP_segment.AckNumber]
949
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
950
	je	.dup_ack
951
 
952
       @@:
953
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
954
	jmp	.not_dup_ack
955
 
956
  .dup_ack:
957
	inc	[ebx + TCP_SOCKET.t_dupacks]
958
	cmp	[ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
959
	jne	.no_re_xmit
960
 
961
	push	[ebx + TCP_SOCKET.SND_NXT]		; >>>>
962
 
963
	mov	eax, [ebx + TCP_SOCKET.SND_WND]
964
	cmp	eax, [ebx + TCP_SOCKET.SND_CWND]
965
	cmovg	eax, [ebx + TCP_SOCKET.SND_CWND]
966
	shr	eax, 1
967
	push	edx
968
	xor	edx, edx
969
	div	[ebx + TCP_SOCKET.t_maxseg]
970
	cmp	eax, 2
971
	jge	@f
972
	mov	ax, 2
973
       @@:
974
	mul	[ebx + TCP_SOCKET.t_maxseg]
975
	pop	edx
976
	mov	[ebx + TCP_SOCKET.SND_SSTHRESH], eax
977
 
978
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0	; turn off retransmission timer
979
	mov	[ebx + TCP_SOCKET.t_rtt], 0
980
	mov	eax, [edx + TCP_segment.AckNumber]
981
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
982
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
983
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
984
 
985
	mov	eax, ebx
986
	call	TCP_output					; retransmit missing segment
987
 
988
	push	edx
989
	xor	edx, edx
990
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
991
	mul	[ebx + TCP_SOCKET.t_dupacks]
992
	pop	edx
993
	add	eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
994
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
995
 
996
	pop	eax					; <<<<
997
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
998
	jl	@f
999
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1000
       @@:
1001
 
1733 hidnplayr 1002
	jmp	.drop
1003
 
1004
 
1763 hidnplayr 1005
  .no_re_xmit:
1006
	jle	.not_dup_ack
1733 hidnplayr 1007
 
1763 hidnplayr 1008
	DEBUGF	1,"Increasing congestion window\n"
1733 hidnplayr 1009
 
1763 hidnplayr 1010
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
1011
	add	[ebx + TCP_SOCKET.SND_CWND], eax
1733 hidnplayr 1012
 
1763 hidnplayr 1013
	mov	eax, ebx
1014
	call	TCP_output
1733 hidnplayr 1015
 
1763 hidnplayr 1016
	jmp	.drop
1733 hidnplayr 1017
 
1018
 
1019
 
1763 hidnplayr 1020
 
1021
 
1022
 
1023
  .not_dup_ack:
1024
 
1733 hidnplayr 1025
;-------------------------------------------------
1026
; If the congestion window was inflated to account
1027
; for the other side's cached packets, retract it
1028
 
1763 hidnplayr 1029
	mov	eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
1030
	cmp	eax, [ebx + TCP_SOCKET.SND_CWND]
1031
	jg	@f
1032
	cmp	[ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
1033
	jle	@f
1034
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
1035
       @@:
1733 hidnplayr 1036
 
1763 hidnplayr 1037
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
1733 hidnplayr 1038
 
1763 hidnplayr 1039
	mov	eax, [edx + TCP_segment.AckNumber]
1040
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
1041
	jle	@f
1733 hidnplayr 1042
 
1763 hidnplayr 1043
	;;; TODO: update stats
1044
	jmp	.drop_after_ack
1733 hidnplayr 1045
 
1763 hidnplayr 1046
       @@:
1733 hidnplayr 1047
 
1763 hidnplayr 1048
	mov	edi, [edx + TCP_segment.AckNumber]
1049
	sub	edi, [ebx + TCP_SOCKET.SND_UNA] 	; now we got the number of acked bytes in esi
1733 hidnplayr 1050
 
1763 hidnplayr 1051
	;;; TODO: update stats
1733 hidnplayr 1052
 
1053
 
1763 hidnplayr 1054
	DEBUGF	1,"We have an acceptable ACK of %x bytes\n", esi
1055
 
1056
 
1057
 
1058
 
1059
 
1060
 
1733 hidnplayr 1061
;------------------------------------------
1062
; RTT measurements and retransmission timer
1063
 
1763 hidnplayr 1064
	;;;;; 912 - 926
1733 hidnplayr 1065
 
1066
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0
1067
 
1068
	mov	eax, [ebx + TCP_SOCKET.SND_MAX]
1069
	cmp	eax, [edx + TCP_segment.AckNumber]
1070
	je	.all_outstanding
1071
	mov	[ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value (use a macro for it)
1072
  .all_outstanding:
1073
 
1074
 
1075
 
1076
 
1077
 
1078
 
1079
 
1080
;-------------------------------------------
1081
; Open congestion window in response to ACKs
1082
 
1763 hidnplayr 1083
	mov	esi, [ebx + TCP_SOCKET.SND_CWND]
1084
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
1733 hidnplayr 1085
 
1763 hidnplayr 1086
	cmp	esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
1087
	jle	@f
1088
	push	edx
1089
	push	eax
1090
	mul	eax
1091
	div	esi
1092
	pop	edx
1093
	shr	edx, 3
1094
	add	eax, edx
1095
	pop	edx
1096
       @@:
1733 hidnplayr 1097
 
1763 hidnplayr 1098
	add	esi, eax
1733 hidnplayr 1099
 
1763 hidnplayr 1100
	push	ecx
1101
	mov	cl, [ebx + TCP_SOCKET.SND_SCALE]
1102
	mov	eax, TCP_max_win
1103
	shl	eax, cl
1104
	pop	ecx
1733 hidnplayr 1105
 
1763 hidnplayr 1106
	cmp	esi, eax
1107
	cmovg	esi, eax
1108
	mov	[ebx + TCP_SOCKET.SND_CWND], esi
1733 hidnplayr 1109
 
1110
 
1111
 
1112
 
1763 hidnplayr 1113
 
1114
 
1115
 
1733 hidnplayr 1116
;------------------------------------------
1117
; Remove acknowledged data from send buffer
1118
 
1763 hidnplayr 1119
	push	ecx edx ebx
1120
	mov	ecx, edi
1733 hidnplayr 1121
	lea	eax, [ebx + STREAM_SOCKET.snd]
1122
	call	SOCKET_ring_free
1763 hidnplayr 1123
	pop	ebx
1124
	sub	[ebx + TCP_SOCKET.SND_WND], ecx
1125
	pop	edx ecx
1733 hidnplayr 1126
 
1127
; Wake up process waiting on send buffer
1128
 
1129
	mov	eax, ebx
1130
	call	SOCKET_notify_owner
1131
 
1831 hidnplayr 1132
; Update TCPS
1733 hidnplayr 1133
 
1134
	mov	eax, [edx + TCP_segment.AckNumber]
1135
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
1136
 
1137
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
1138
	jl	@f
1139
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1140
       @@:
1141
 
1142
 
1772 hidnplayr 1143
	;; TODO: use zero flag as 'ourfinisacked'
1733 hidnplayr 1144
 
1145
 
1146
 
1147
 
1148
; General ACK handling complete
1149
; Now do the state-specific ones
1150
 
1151
	mov	eax, [ebx + TCP_SOCKET.t_state]
1152
	jmp	dword [eax*4 + .ACK_sw_list]
1153
 
1154
  .ACK_sw_list:
1831 hidnplayr 1155
	dd	.ack_processed	;TCPS_CLOSED
1156
	dd	.ack_processed	;TCPS_LISTEN
1157
	dd	.ack_processed	;TCPS_SYN_SENT
1158
	dd	.ack_processed	;TCPS_SYN_RECEIVED
1159
	dd	.ack_processed	;TCPS_ESTABLISHED
1160
	dd	.ack_processed	;TCPS_CLOSE_WAIT
1161
	dd	.ack_fw1	;TCPS_FIN_WAIT_1
1162
	dd	.ack_c		;TCPS_CLOSING
1163
	dd	.ack_la 	;TCPS_LAST_ACK
1164
	dd	.ack_processed	;TCPS_FIN_WAIT_2
1165
	dd	.ack_tw 	;TCPS_TIMED_WAIT
1733 hidnplayr 1166
 
1167
 
1772 hidnplayr 1168
  .ack_fw1:
1169
	jz	.ack_processed
1733 hidnplayr 1170
 
1773 hidnplayr 1171
	test	[ebx + SOCKET.state], SS_CANTRCVMORE
1772 hidnplayr 1172
	jnz	@f
1773 hidnplayr 1173
	mov	eax, ebx
1174
	call	SOCKET_is_disconnected
1175
;;;        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
1772 hidnplayr 1176
       @@:
1733 hidnplayr 1177
 
1831 hidnplayr 1178
	mov	[ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1733 hidnplayr 1179
	jmp	.ack_processed
1180
 
1181
 
1772 hidnplayr 1182
  .ack_c:
1183
	jz	.ack_processed
1184
 
1831 hidnplayr 1185
	mov	[ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1773 hidnplayr 1186
	mov	eax, ebx
1772 hidnplayr 1187
	call	TCP_cancel_timers
1188
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1773 hidnplayr 1189
	mov	eax, ebx
1190
	call	SOCKET_is_disconnected
1733 hidnplayr 1191
	jmp	.ack_processed
1192
 
1193
 
1772 hidnplayr 1194
  .ack_la:
1195
	jz	.ack_processed
1733 hidnplayr 1196
 
1773 hidnplayr 1197
 
1198
	mov	eax, ebx
1772 hidnplayr 1199
	call	TCP_close
1200
	jmp	.drop
1733 hidnplayr 1201
 
1202
 
1772 hidnplayr 1203
  .ack_tw:
1204
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1205
	jmp	.drop_after_ack
1733 hidnplayr 1206
 
1207
 
1772 hidnplayr 1208
 
1209
 
1210
 
1211
 
1212
 
1763 hidnplayr 1213
  .reset_dupacks:		; We got a new ACK, reset duplicate ACK counter
1733 hidnplayr 1214
 
1763 hidnplayr 1215
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
1733 hidnplayr 1216
 
1217
  .ack_processed:	; (step 6)
1218
 
1219
	DEBUGF	1,"ACK processed\n"
1220
 
1221
;----------------------------------------------
1222
; check if we need to update window information
1223
 
1224
	test	[edx + TCP_segment.Flags], TH_ACK
1225
	jz	.no_window_update
1226
 
1227
	mov	eax, [ebx + TCP_SOCKET.SND_WL1]
1228
	cmp	eax, [edx + TCP_segment.SequenceNumber]
1229
	jl	.update_window
1230
	jg	@f
1231
 
1232
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
1233
	cmp	eax, [edx + TCP_segment.AckNumber]
1234
	jl	.update_window
1235
	jg	.no_window_update
1236
       @@:
1237
 
1238
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
1239
	cmp	eax, [edx + TCP_segment.AckNumber]
1240
	jne	.no_window_update
1241
 
1242
	movzx	eax, [edx + TCP_segment.Window]
1243
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
1244
	jle	.no_window_update
1245
 
1246
  .update_window:
1247
 
1248
	DEBUGF	1,"Updating window\n"
1249
 
1250
; Keep track of pure window updates
1251
 
1252
;        test    ecx, ecx
1253
;        jz      @f
1254
;
1255
;        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1256
;        cmp     eax, [edx + TCP_segment.AckNumber]
1257
;        jne     @f
1258
;
1259
;        ;; mov eax, tiwin
1260
;        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1261
;        jle     @f
1262
;
1263
;        ;;; update stats
1264
;
1265
;       @@:
1266
 
1267
	mov	eax, dword [edx + TCP_segment.Window]
1268
	cmp	eax, [ebx + TCP_SOCKET.max_sndwnd]
1269
	jle	@f
1270
	mov	[ebx + TCP_SOCKET.max_sndwnd], eax
1271
       @@:
1272
	mov	[ebx + TCP_SOCKET.SND_WND], eax
1273
 
1274
	push	[edx + TCP_segment.SequenceNumber]
1275
	pop	[ebx + TCP_SOCKET.SND_WL1]
1276
 
1277
	push	[edx + TCP_segment.AckNumber]
1278
	pop	[ebx + TCP_SOCKET.SND_WL2]
1279
 
1280
	;;; needoutput = 1
1281
 
1282
  .no_window_update:
1283
 
1284
 
1285
 
1286
 
1287
 
1288
 
1289
 
1290
;-----------------
1291
; process URG flag
1292
 
1293
	test	[edx + TCP_segment.Flags], TH_URG
1294
	jz	.not_urgent
1295
 
1296
	cmp	[edx + TCP_segment.UrgentPointer], 0
1297
	jz	.not_urgent
1298
 
1831 hidnplayr 1299
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1733 hidnplayr 1300
	je	.not_urgent
1301
 
1302
; Ignore bogus urgent offsets
1303
 
1304
	;;; 1040-1050
1305
 
1306
	movzx	eax, [edx + TCP_segment.UrgentPointer]
1307
	add	eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size]
1308
	cmp	eax, SOCKET_MAXDATA
1309
	jle	.not_urgent
1310
 
1311
	mov	[edx + TCP_segment.UrgentPointer], 0
1312
	and	[edx + TCP_segment.Flags], not (TH_URG)
1313
	jmp	.do_data
1314
 
1315
  .not_urgent:
1316
 
1317
; processing of received urgent pointer
1318
 
1319
	;;; TODO (1051-1093)
1320
 
1321
 
1322
 
1323
 
1324
 
1325
 
1326
 
1327
 
1328
;--------------------------------
1329
; process the data in the segment
1330
 
1331
  .do_data:
1332
 
1333
	DEBUGF	1,"TCP: do data (%u)\n", ecx
1334
 
1335
	test	[edx + TCP_segment.Flags], TH_FIN
1336
	jnz	.process_fin
1337
 
1831 hidnplayr 1338
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_1
1733 hidnplayr 1339
	jge	.dont_do_data
1340
 
1341
	test	ecx, ecx
1342
	jz	.final_processing
1343
 
1344
	DEBUGF	1,"Processing data in segment\n"
1345
 
1346
;; TODO: check if data is in sequence !
1347
 
1348
	movzx	eax, [edx + TCP_segment.DataOffset]		;;; todo: remember this in.. edi ?
1349
	and	eax, 0xf0
1350
	shr	al, 2
1351
 
1352
	lea	esi, [edx + eax]
1353
 
1354
	or	[ebx + TCP_SOCKET.t_flags], TF_DELACK
1355
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx
1356
 
1357
	lea	eax, [ebx + STREAM_SOCKET.rcv]
1358
	call	SOCKET_ring_write
1359
 
1360
	mov	eax, ebx
1361
	call	SOCKET_notify_owner
1362
 
1363
	jmp	.final_processing
1364
 
1365
 
1366
  .dont_do_data:
1367
 
1368
 
1369
 
1370
 
1371
 
1372
 
1373
 
1374
;---------------
1375
; FIN processing
1376
 
1377
  .process_fin:
1378
 
1379
	DEBUGF	1,"Processing FIN\n"
1380
 
1831 hidnplayr 1381
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1774 hidnplayr 1382
	je	.not_first_fin
1831 hidnplayr 1383
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1774 hidnplayr 1384
	je	.not_first_fin
1831 hidnplayr 1385
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1774 hidnplayr 1386
	je	.not_first_fin
1387
 
1388
	DEBUGF	1,"First FIN for this connection\n"
1389
 
1390
	mov	eax, ebx
1391
	call	SOCKET_cant_recv_more
1392
 
1393
	mov	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1394
	inc	[ebx + TCP_SOCKET.RCV_NXT]
1395
 
1396
  .not_first_fin:
1733 hidnplayr 1397
	mov	eax, [ebx + TCP_SOCKET.t_state]
1398
	shl	eax, 2
1399
	jmp	dword [eax + .FIN_sw_list]
1400
 
1401
  .FIN_sw_list:
1831 hidnplayr 1402
	dd	.no_fin 	;TCPS_CLOSED
1403
	dd	.no_fin 	;TCPS_LISTEN
1404
	dd	.no_fin 	;TCPS_SYN_SENT
1405
	dd	.fin_syn_est	;TCPS_SYN_RECEIVED
1406
	dd	.fin_syn_est	;TCPS_ESTABLISHED
1407
	dd	.no_fin 	;TCPS_CLOSE_WAIT
1408
	dd	.fin_wait1	;TCPS_FIN_WAIT_1
1409
	dd	.no_fin 	;TCPS_CLOSING
1410
	dd	.no_fin 	;TCPS_LAST_ACK
1411
	dd	.fin_wait2	;TCPS_FIN_WAIT_2
1412
	dd	.fin_timed	;TCPS_TIMED_WAIT
1733 hidnplayr 1413
 
1414
  .fin_syn_est:
1415
 
1831 hidnplayr 1416
	mov	[ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1774 hidnplayr 1417
	jmp	.no_fin
1733 hidnplayr 1418
 
1419
  .fin_wait1:
1420
 
1831 hidnplayr 1421
	mov	[ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1774 hidnplayr 1422
	jmp	.no_fin
1733 hidnplayr 1423
 
1424
  .fin_wait2:
1425
 
1831 hidnplayr 1426
	mov	[ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1774 hidnplayr 1427
	mov	eax, ebx
1428
	call	TCP_cancel_timers
1429
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1430
	call	SOCKET_is_disconnected
1431
	jmp	.no_fin
1733 hidnplayr 1432
 
1433
  .fin_timed:
1774 hidnplayr 1434
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1435
	jmp	.no_fin
1733 hidnplayr 1436
 
1437
  .no_fin:
1438
 
1439
 
1440
 
1441
 
1442
 
1443
 
1444
 
1445
 
1446
;-----------------
1447
; Final processing
1448
 
1449
  .final_processing:
1450
 
1451
	DEBUGF	1,"Final processing\n"
1452
 
1453
	;;; if debug enabled, output packet
1454
 
1455
	;test    needoutput, needoutput
1456
	;jz      .dumpit
1457
 
1458
	test	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1459
	jz	.dumpit
1460
 
1461
	DEBUGF	1,"ACK now!\n"
1462
 
1463
	push	ebx
1464
	mov	eax, ebx
1465
	call	TCP_output
1466
	pop	ebx
1467
 
1468
  .dumpit:
1469
 
1470
	mov	[ebx + SOCKET.lock], 0
1471
 
1472
	call	kernel_free
1473
	add	esp, 4
1474
	ret
1475
 
1476
 
1477
 
1478
 
1479
 
1480
 
1481
 
1482
;------------------------------------------
1483
; Generate an ACK, droping incoming segment
1484
 
1485
align 4
1486
.drop_after_ack:
1487
 
1488
	DEBUGF	1,"Drop after ACK\n"
1489
 
1490
	test	[edx + TCP_segment.Flags], TH_RST
1491
	jnz	.drop
1492
 
1493
	and	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1494
 
1495
	mov	[ebx + SOCKET.lock], 0
1496
 
1497
	push	ebx
1838 hidnplayr 1498
;        mov     cl, TH_ACK
1499
;        call    TCP_respond_socket
1500
	mov	eax, ebx
1501
	call	TCP_output
1733 hidnplayr 1502
	pop	ebx
1503
 
1504
	call	kernel_free
1505
	add	esp, 4
1506
	ret
1507
 
1508
 
1509
 
1510
 
1511
 
1512
 
1513
 
1514
 
1515
;-------------------------------------------
1516
; Generate an RST, dropping incoming segment
1517
 
1518
align 4
1519
.drop_with_reset:
1520
 
1521
	mov	[ebx + SOCKET.lock], 0
1522
 
1523
.drop_with_reset_not_locked:
1524
 
1525
	DEBUGF	1,"Drop with reset\n"
1526
 
1527
	test	[edx + TCP_segment.Flags], TH_RST
1528
	jnz	.drop
1529
 
1530
	;;; if its a multicast/broadcast, also drop
1531
 
1532
	test	[edx + TCP_segment.Flags], TH_ACK
1533
	jnz	.respond_ack
1534
 
1535
	test	[edx + TCP_segment.Flags], TH_SYN
1536
	jnz	.respond_syn
1537
 
1538
	call	kernel_free
1539
	add	esp, 4
1540
	ret
1541
 
1542
  .respond_ack:
1543
 
1544
	push	ebx
1830 hidnplayr 1545
	mov	cl, TH_RST
1546
	call	TCP_respond_socket
1733 hidnplayr 1547
	pop	ebx
1548
 
1549
	jmp	.destroy_new_socket
1550
 
1551
 
1552
  .respond_syn:
1553
 
1554
	push	ebx
1830 hidnplayr 1555
	mov	cl, TH_RST + TH_ACK
1733 hidnplayr 1556
	call	TCP_respond_socket
1557
	pop	ebx
1558
 
1559
	jmp	.destroy_new_socket
1560
 
1561
 
1562
 
1563
 
1564
 
1565
 
1566
 
1567
;-----
1568
; Drop
1569
 
1570
align 4
1571
.drop:
1572
 
1573
	mov	[ebx + SOCKET.lock], 0
1574
 
1575
.drop_not_locked:
1576
 
1577
	DEBUGF	1,"Dropping packet\n"
1578
 
1579
	;;;; If debugging options are enabled, output the packet somwhere
1580
 
1581
  .destroy_new_socket:
1582
 
1583
	;;;; kill the newly created socket
1584
 
1585
	call	kernel_free
1586
	add	esp, 4
1587
	ret