Subversion Repositories Kolibri OS

Rev

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