Subversion Repositories Kolibri OS

Rev

Rev 1774 | 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: 1830 $
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
;------------------------------------------------------------
108
; Next thing to do is find the TCB (thus, the socket pointer)
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
 
151
	cmp	[ebx + TCP_SOCKET.t_state], TCB_CLOSED
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
 
196
	mov	[eax + TCP_SOCKET.t_state], TCB_LISTEN
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
 
216
	cmp	[ebx + TCP_SOCKET.t_state], TCB_LISTEN		; no options when in listen state
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
 
313
	cmp	[ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
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
 
441
	cmp	[ebx + TCP_SOCKET.t_state], TCB_LISTEN
442
	je	.LISTEN
443
 
444
	cmp	[ebx + TCP_SOCKET.t_state], TCB_SYN_SENT
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
 
484
	mov	[eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
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
 
581
	mov	[ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
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..
592
	mov	[ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
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
 
750
	cmp	[ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT
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:
814
	dd	.rst_skip	;TCB_CLOSED
815
	dd	.rst_skip	;TCB_LISTEN
816
	dd	.rst_skip	;TCB_SYN_SENT
817
	dd	.econnrefused	;TCB_SYN_RECEIVED
818
	dd	.econnreset	;TCB_ESTABLISHED
819
	dd	.econnreset	;TCB_CLOSE_WAIT
820
	dd	.econnreset	;TCB_FIN_WAIT_1
821
	dd	.rst_close	;TCB_CLOSING
822
	dd	.rst_close	;TCB_LAST_ACK
823
	dd	.econnreset	;TCB_FIN_WAIT_2
824
	dd	.rst_close	;TCB_TIMED_WAIT
825
 
826
  .econnrefused:
827
 
828
	DEBUGF	1,"Connection refused"
829
 
830
;;; TODO: debug info
831
 
832
	jmp	.close
833
 
834
  .econnreset:
835
 
836
	DEBUGF	1,"Connection reset"
837
 
838
;;; TODO: debug info
839
 
840
  .close:
841
 
842
	DEBUGF	1,"Closing connection"
843
 
844
;;; update stats
845
 
846
  .rst_close:
847
 
848
	DEBUGF	1,"Closing with reset\n"
849
 
850
;;; Close the socket
851
 
852
	jmp	.drop
853
 
854
 
855
 
856
 
857
 
858
 
859
 
1763 hidnplayr 860
  .rst_skip:
1733 hidnplayr 861
 
1763 hidnplayr 862
 
1733 hidnplayr 863
;--------------------------------------
864
; handle SYN-full and ACK-less segments
865
 
866
	test	[edx + TCP_segment.Flags], TH_SYN
867
	jz	@f
868
 
869
	mov	ebx, ECONNRESET
870
	call	TCP_drop
871
 
872
	jmp	.drop_with_reset
873
 
874
	test	[edx + TCP_segment.Flags], TH_ACK
875
	jz	.drop
876
      @@:
877
 
878
 
879
 
880
 
881
 
882
 
883
 
884
;---------------
885
; ACK processing
886
 
887
	cmp	[ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
888
	jnz	.no_syn_rcv
889
 
890
	DEBUGF	1,"TCP state = syn received\n"
891
 
892
	;;;;;  801-815
893
 
894
  .no_syn_rcv:
895
 
896
; check for duplicate ACK
897
 
898
	mov	eax, [edx + TCP_segment.AckNumber]
899
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
900
	jg	.not_dup_ack
901
 
902
	test	ecx, ecx
1763 hidnplayr 903
	jnz	.reset_dupacks
1733 hidnplayr 904
 
905
	mov	eax, dword [edx + TCP_segment.Window]
906
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
1763 hidnplayr 907
	jne	.reset_dupacks
1733 hidnplayr 908
 
1763 hidnplayr 909
	DEBUGF	1,"Processing a duplicate ACK..\n"
1733 hidnplayr 910
 
1763 hidnplayr 911
	cmp	[ebx + TCP_SOCKET.timer_retransmission], 10000 ;;;;
912
	jg	@f
1733 hidnplayr 913
 
1763 hidnplayr 914
	mov	eax, [edx + TCP_segment.AckNumber]
915
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
916
	je	.dup_ack
917
 
918
       @@:
919
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
920
	jmp	.not_dup_ack
921
 
922
  .dup_ack:
923
	inc	[ebx + TCP_SOCKET.t_dupacks]
924
	cmp	[ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
925
	jne	.no_re_xmit
926
 
927
	push	[ebx + TCP_SOCKET.SND_NXT]		; >>>>
928
 
929
	mov	eax, [ebx + TCP_SOCKET.SND_WND]
930
	cmp	eax, [ebx + TCP_SOCKET.SND_CWND]
931
	cmovg	eax, [ebx + TCP_SOCKET.SND_CWND]
932
	shr	eax, 1
933
	push	edx
934
	xor	edx, edx
935
	div	[ebx + TCP_SOCKET.t_maxseg]
936
	cmp	eax, 2
937
	jge	@f
938
	mov	ax, 2
939
       @@:
940
	mul	[ebx + TCP_SOCKET.t_maxseg]
941
	pop	edx
942
	mov	[ebx + TCP_SOCKET.SND_SSTHRESH], eax
943
 
944
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0	; turn off retransmission timer
945
	mov	[ebx + TCP_SOCKET.t_rtt], 0
946
	mov	eax, [edx + TCP_segment.AckNumber]
947
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
948
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
949
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
950
 
951
	mov	eax, ebx
952
	call	TCP_output					; retransmit missing segment
953
 
954
	push	edx
955
	xor	edx, edx
956
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
957
	mul	[ebx + TCP_SOCKET.t_dupacks]
958
	pop	edx
959
	add	eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
960
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
961
 
962
	pop	eax					; <<<<
963
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
964
	jl	@f
965
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
966
       @@:
967
 
1733 hidnplayr 968
	jmp	.drop
969
 
970
 
1763 hidnplayr 971
  .no_re_xmit:
972
	jle	.not_dup_ack
1733 hidnplayr 973
 
1763 hidnplayr 974
	DEBUGF	1,"Increasing congestion window\n"
1733 hidnplayr 975
 
1763 hidnplayr 976
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
977
	add	[ebx + TCP_SOCKET.SND_CWND], eax
1733 hidnplayr 978
 
1763 hidnplayr 979
	mov	eax, ebx
980
	call	TCP_output
1733 hidnplayr 981
 
1763 hidnplayr 982
	jmp	.drop
1733 hidnplayr 983
 
984
 
985
 
1763 hidnplayr 986
 
987
 
988
 
989
  .not_dup_ack:
990
 
1733 hidnplayr 991
;-------------------------------------------------
992
; If the congestion window was inflated to account
993
; for the other side's cached packets, retract it
994
 
1763 hidnplayr 995
	mov	eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
996
	cmp	eax, [ebx + TCP_SOCKET.SND_CWND]
997
	jg	@f
998
	cmp	[ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
999
	jle	@f
1000
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
1001
       @@:
1733 hidnplayr 1002
 
1763 hidnplayr 1003
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
1733 hidnplayr 1004
 
1763 hidnplayr 1005
	mov	eax, [edx + TCP_segment.AckNumber]
1006
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
1007
	jle	@f
1733 hidnplayr 1008
 
1763 hidnplayr 1009
	;;; TODO: update stats
1010
	jmp	.drop_after_ack
1733 hidnplayr 1011
 
1763 hidnplayr 1012
       @@:
1733 hidnplayr 1013
 
1763 hidnplayr 1014
	mov	edi, [edx + TCP_segment.AckNumber]
1015
	sub	edi, [ebx + TCP_SOCKET.SND_UNA] 	; now we got the number of acked bytes in esi
1733 hidnplayr 1016
 
1763 hidnplayr 1017
	;;; TODO: update stats
1733 hidnplayr 1018
 
1019
 
1763 hidnplayr 1020
	DEBUGF	1,"We have an acceptable ACK of %x bytes\n", esi
1021
 
1022
 
1023
 
1024
 
1025
 
1026
 
1733 hidnplayr 1027
;------------------------------------------
1028
; RTT measurements and retransmission timer
1029
 
1763 hidnplayr 1030
	;;;;; 912 - 926
1733 hidnplayr 1031
 
1032
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0
1033
 
1034
	mov	eax, [ebx + TCP_SOCKET.SND_MAX]
1035
	cmp	eax, [edx + TCP_segment.AckNumber]
1036
	je	.all_outstanding
1037
	mov	[ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value (use a macro for it)
1038
  .all_outstanding:
1039
 
1040
 
1041
 
1042
 
1043
 
1044
 
1045
 
1046
;-------------------------------------------
1047
; Open congestion window in response to ACKs
1048
 
1763 hidnplayr 1049
	mov	esi, [ebx + TCP_SOCKET.SND_CWND]
1050
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
1733 hidnplayr 1051
 
1763 hidnplayr 1052
	cmp	esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
1053
	jle	@f
1054
	push	edx
1055
	push	eax
1056
	mul	eax
1057
	div	esi
1058
	pop	edx
1059
	shr	edx, 3
1060
	add	eax, edx
1061
	pop	edx
1062
       @@:
1733 hidnplayr 1063
 
1763 hidnplayr 1064
	add	esi, eax
1733 hidnplayr 1065
 
1763 hidnplayr 1066
	push	ecx
1067
	mov	cl, [ebx + TCP_SOCKET.SND_SCALE]
1068
	mov	eax, TCP_max_win
1069
	shl	eax, cl
1070
	pop	ecx
1733 hidnplayr 1071
 
1763 hidnplayr 1072
	cmp	esi, eax
1073
	cmovg	esi, eax
1074
	mov	[ebx + TCP_SOCKET.SND_CWND], esi
1733 hidnplayr 1075
 
1076
 
1077
 
1078
 
1763 hidnplayr 1079
 
1080
 
1081
 
1733 hidnplayr 1082
;------------------------------------------
1083
; Remove acknowledged data from send buffer
1084
 
1763 hidnplayr 1085
	push	ecx edx ebx
1086
	mov	ecx, edi
1733 hidnplayr 1087
	lea	eax, [ebx + STREAM_SOCKET.snd]
1088
	call	SOCKET_ring_free
1763 hidnplayr 1089
	pop	ebx
1090
	sub	[ebx + TCP_SOCKET.SND_WND], ecx
1091
	pop	edx ecx
1733 hidnplayr 1092
 
1093
; Wake up process waiting on send buffer
1094
 
1095
	mov	eax, ebx
1096
	call	SOCKET_notify_owner
1097
 
1098
; Update TCB
1099
 
1100
	mov	eax, [edx + TCP_segment.AckNumber]
1101
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
1102
 
1103
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
1104
	jl	@f
1105
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1106
       @@:
1107
 
1108
 
1772 hidnplayr 1109
	;; TODO: use zero flag as 'ourfinisacked'
1733 hidnplayr 1110
 
1111
 
1112
 
1113
 
1114
; General ACK handling complete
1115
; Now do the state-specific ones
1116
 
1117
	mov	eax, [ebx + TCP_SOCKET.t_state]
1118
	jmp	dword [eax*4 + .ACK_sw_list]
1119
 
1120
  .ACK_sw_list:
1121
	dd	.ack_processed	;TCB_CLOSED
1122
	dd	.ack_processed	;TCB_LISTEN
1123
	dd	.ack_processed	;TCB_SYN_SENT
1124
	dd	.ack_processed	;TCB_SYN_RECEIVED
1125
	dd	.ack_processed	;TCB_ESTABLISHED
1126
	dd	.ack_processed	;TCB_CLOSE_WAIT
1127
	dd	.ack_fw1	;TCB_FIN_WAIT_1
1128
	dd	.ack_c		;TCB_CLOSING
1129
	dd	.ack_la 	;TCB_LAST_ACK
1130
	dd	.ack_processed	;TCB_FIN_WAIT_2
1131
	dd	.ack_tw 	;TCB_TIMED_WAIT
1132
 
1133
 
1772 hidnplayr 1134
  .ack_fw1:
1135
	jz	.ack_processed
1733 hidnplayr 1136
 
1773 hidnplayr 1137
	test	[ebx + SOCKET.state], SS_CANTRCVMORE
1772 hidnplayr 1138
	jnz	@f
1773 hidnplayr 1139
	mov	eax, ebx
1140
	call	SOCKET_is_disconnected
1141
;;;        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
1772 hidnplayr 1142
       @@:
1733 hidnplayr 1143
 
1772 hidnplayr 1144
	mov	[ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_2
1733 hidnplayr 1145
	jmp	.ack_processed
1146
 
1147
 
1772 hidnplayr 1148
  .ack_c:
1149
	jz	.ack_processed
1150
 
1151
	mov	[ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT
1773 hidnplayr 1152
	mov	eax, ebx
1772 hidnplayr 1153
	call	TCP_cancel_timers
1154
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1773 hidnplayr 1155
	mov	eax, ebx
1156
	call	SOCKET_is_disconnected
1733 hidnplayr 1157
	jmp	.ack_processed
1158
 
1159
 
1772 hidnplayr 1160
  .ack_la:
1161
	jz	.ack_processed
1733 hidnplayr 1162
 
1773 hidnplayr 1163
 
1164
	mov	eax, ebx
1772 hidnplayr 1165
	call	TCP_close
1166
	jmp	.drop
1733 hidnplayr 1167
 
1168
 
1772 hidnplayr 1169
  .ack_tw:
1170
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1171
	jmp	.drop_after_ack
1733 hidnplayr 1172
 
1173
 
1772 hidnplayr 1174
 
1175
 
1176
 
1177
 
1178
 
1763 hidnplayr 1179
  .reset_dupacks:		; We got a new ACK, reset duplicate ACK counter
1733 hidnplayr 1180
 
1763 hidnplayr 1181
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
1733 hidnplayr 1182
 
1183
  .ack_processed:	; (step 6)
1184
 
1185
	DEBUGF	1,"ACK processed\n"
1186
 
1187
;----------------------------------------------
1188
; check if we need to update window information
1189
 
1190
	test	[edx + TCP_segment.Flags], TH_ACK
1191
	jz	.no_window_update
1192
 
1193
	mov	eax, [ebx + TCP_SOCKET.SND_WL1]
1194
	cmp	eax, [edx + TCP_segment.SequenceNumber]
1195
	jl	.update_window
1196
	jg	@f
1197
 
1198
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
1199
	cmp	eax, [edx + TCP_segment.AckNumber]
1200
	jl	.update_window
1201
	jg	.no_window_update
1202
       @@:
1203
 
1204
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
1205
	cmp	eax, [edx + TCP_segment.AckNumber]
1206
	jne	.no_window_update
1207
 
1208
	movzx	eax, [edx + TCP_segment.Window]
1209
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
1210
	jle	.no_window_update
1211
 
1212
  .update_window:
1213
 
1214
	DEBUGF	1,"Updating window\n"
1215
 
1216
; Keep track of pure window updates
1217
 
1218
;        test    ecx, ecx
1219
;        jz      @f
1220
;
1221
;        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1222
;        cmp     eax, [edx + TCP_segment.AckNumber]
1223
;        jne     @f
1224
;
1225
;        ;; mov eax, tiwin
1226
;        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1227
;        jle     @f
1228
;
1229
;        ;;; update stats
1230
;
1231
;       @@:
1232
 
1233
	mov	eax, dword [edx + TCP_segment.Window]
1234
	cmp	eax, [ebx + TCP_SOCKET.max_sndwnd]
1235
	jle	@f
1236
	mov	[ebx + TCP_SOCKET.max_sndwnd], eax
1237
       @@:
1238
	mov	[ebx + TCP_SOCKET.SND_WND], eax
1239
 
1240
	push	[edx + TCP_segment.SequenceNumber]
1241
	pop	[ebx + TCP_SOCKET.SND_WL1]
1242
 
1243
	push	[edx + TCP_segment.AckNumber]
1244
	pop	[ebx + TCP_SOCKET.SND_WL2]
1245
 
1246
	;;; needoutput = 1
1247
 
1248
  .no_window_update:
1249
 
1250
 
1251
 
1252
 
1253
 
1254
 
1255
 
1256
;-----------------
1257
; process URG flag
1258
 
1259
	test	[edx + TCP_segment.Flags], TH_URG
1260
	jz	.not_urgent
1261
 
1262
	cmp	[edx + TCP_segment.UrgentPointer], 0
1263
	jz	.not_urgent
1264
 
1265
	cmp	[ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT
1266
	je	.not_urgent
1267
 
1268
; Ignore bogus urgent offsets
1269
 
1270
	;;; 1040-1050
1271
 
1272
	movzx	eax, [edx + TCP_segment.UrgentPointer]
1273
	add	eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size]
1274
	cmp	eax, SOCKET_MAXDATA
1275
	jle	.not_urgent
1276
 
1277
	mov	[edx + TCP_segment.UrgentPointer], 0
1278
	and	[edx + TCP_segment.Flags], not (TH_URG)
1279
	jmp	.do_data
1280
 
1281
  .not_urgent:
1282
 
1283
; processing of received urgent pointer
1284
 
1285
	;;; TODO (1051-1093)
1286
 
1287
 
1288
 
1289
 
1290
 
1291
 
1292
 
1293
 
1294
;--------------------------------
1295
; process the data in the segment
1296
 
1297
  .do_data:
1298
 
1299
	DEBUGF	1,"TCP: do data (%u)\n", ecx
1300
 
1301
	test	[edx + TCP_segment.Flags], TH_FIN
1302
	jnz	.process_fin
1303
 
1304
	cmp	[ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1
1305
	jge	.dont_do_data
1306
 
1307
	test	ecx, ecx
1308
	jz	.final_processing
1309
 
1310
	DEBUGF	1,"Processing data in segment\n"
1311
 
1312
;; TODO: check if data is in sequence !
1313
 
1314
	movzx	eax, [edx + TCP_segment.DataOffset]		;;; todo: remember this in.. edi ?
1315
	and	eax, 0xf0
1316
	shr	al, 2
1317
 
1318
	lea	esi, [edx + eax]
1319
 
1320
	or	[ebx + TCP_SOCKET.t_flags], TF_DELACK
1321
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx
1322
 
1323
	lea	eax, [ebx + STREAM_SOCKET.rcv]
1324
	call	SOCKET_ring_write
1325
 
1326
	mov	eax, ebx
1327
	call	SOCKET_notify_owner
1328
 
1329
	jmp	.final_processing
1330
 
1331
 
1332
  .dont_do_data:
1333
 
1334
 
1335
 
1336
 
1337
 
1338
 
1339
 
1340
;---------------
1341
; FIN processing
1342
 
1343
  .process_fin:
1344
 
1345
	DEBUGF	1,"Processing FIN\n"
1346
 
1774 hidnplayr 1347
	cmp	[ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT
1348
	je	.not_first_fin
1349
	cmp	[ebx + TCP_SOCKET.t_state], TCB_CLOSING
1350
	je	.not_first_fin
1351
	cmp	[ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_2
1352
	je	.not_first_fin
1353
 
1354
	DEBUGF	1,"First FIN for this connection\n"
1355
 
1356
	mov	eax, ebx
1357
	call	SOCKET_cant_recv_more
1358
 
1359
	mov	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1360
	inc	[ebx + TCP_SOCKET.RCV_NXT]
1361
 
1362
  .not_first_fin:
1733 hidnplayr 1363
	mov	eax, [ebx + TCP_SOCKET.t_state]
1364
	shl	eax, 2
1365
	jmp	dword [eax + .FIN_sw_list]
1366
 
1367
  .FIN_sw_list:
1368
	dd	.no_fin 	;TCB_CLOSED
1369
	dd	.no_fin 	;TCB_LISTEN
1370
	dd	.no_fin 	;TCB_SYN_SENT
1371
	dd	.fin_syn_est	;TCB_SYN_RECEIVED
1372
	dd	.fin_syn_est	;TCB_ESTABLISHED
1373
	dd	.no_fin 	;TCB_CLOSE_WAIT
1374
	dd	.fin_wait1	;TCB_FIN_WAIT_1
1375
	dd	.no_fin 	;TCB_CLOSING
1376
	dd	.no_fin 	;TCB_LAST_ACK
1377
	dd	.fin_wait2	;TCB_FIN_WAIT_2
1378
	dd	.fin_timed	;TCB_TIMED_WAIT
1379
 
1380
  .fin_syn_est:
1381
 
1774 hidnplayr 1382
	mov	[ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT
1383
	jmp	.no_fin
1733 hidnplayr 1384
 
1385
  .fin_wait1:
1386
 
1774 hidnplayr 1387
	mov	[ebx + TCP_SOCKET.t_state], TCB_CLOSING
1388
	jmp	.no_fin
1733 hidnplayr 1389
 
1390
  .fin_wait2:
1391
 
1774 hidnplayr 1392
	mov	[ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT
1393
	mov	eax, ebx
1394
	call	TCP_cancel_timers
1395
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1396
	call	SOCKET_is_disconnected
1397
	jmp	.no_fin
1733 hidnplayr 1398
 
1399
  .fin_timed:
1774 hidnplayr 1400
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1401
	jmp	.no_fin
1733 hidnplayr 1402
 
1403
  .no_fin:
1404
 
1405
 
1406
 
1407
 
1408
 
1409
 
1410
 
1411
 
1412
;-----------------
1413
; Final processing
1414
 
1415
  .final_processing:
1416
 
1417
	DEBUGF	1,"Final processing\n"
1418
 
1419
	;;; if debug enabled, output packet
1420
 
1421
	;test    needoutput, needoutput
1422
	;jz      .dumpit
1423
 
1424
	test	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1425
	jz	.dumpit
1426
 
1427
	DEBUGF	1,"ACK now!\n"
1428
 
1429
	push	ebx
1430
	mov	eax, ebx
1431
	call	TCP_output
1432
	pop	ebx
1433
 
1434
  .dumpit:
1435
 
1436
	mov	[ebx + SOCKET.lock], 0
1437
 
1438
	call	kernel_free
1439
	add	esp, 4
1440
	ret
1441
 
1442
 
1443
 
1444
 
1445
 
1446
 
1447
 
1448
;------------------------------------------
1449
; Generate an ACK, droping incoming segment
1450
 
1451
align 4
1452
.drop_after_ack:
1453
 
1454
	DEBUGF	1,"Drop after ACK\n"
1455
 
1456
	test	[edx + TCP_segment.Flags], TH_RST
1457
	jnz	.drop
1458
 
1459
	and	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1460
 
1461
	mov	[ebx + SOCKET.lock], 0
1462
 
1463
	push	ebx
1830 hidnplayr 1464
	mov	cl, TH_ACK
1465
	call	TCP_respond_socket
1733 hidnplayr 1466
	pop	ebx
1467
 
1468
	call	kernel_free
1469
	add	esp, 4
1470
	ret
1471
 
1472
 
1473
 
1474
 
1475
 
1476
 
1477
 
1478
 
1479
;-------------------------------------------
1480
; Generate an RST, dropping incoming segment
1481
 
1482
align 4
1483
.drop_with_reset:
1484
 
1485
	mov	[ebx + SOCKET.lock], 0
1486
 
1487
.drop_with_reset_not_locked:
1488
 
1489
	DEBUGF	1,"Drop with reset\n"
1490
 
1491
	test	[edx + TCP_segment.Flags], TH_RST
1492
	jnz	.drop
1493
 
1494
	;;; if its a multicast/broadcast, also drop
1495
 
1496
	test	[edx + TCP_segment.Flags], TH_ACK
1497
	jnz	.respond_ack
1498
 
1499
	test	[edx + TCP_segment.Flags], TH_SYN
1500
	jnz	.respond_syn
1501
 
1502
	call	kernel_free
1503
	add	esp, 4
1504
	ret
1505
 
1506
  .respond_ack:
1507
 
1508
	push	ebx
1830 hidnplayr 1509
	mov	cl, TH_RST
1510
	call	TCP_respond_socket
1733 hidnplayr 1511
	pop	ebx
1512
 
1513
	jmp	.destroy_new_socket
1514
 
1515
 
1516
  .respond_syn:
1517
 
1518
	push	ebx
1830 hidnplayr 1519
	mov	cl, TH_RST + TH_ACK
1733 hidnplayr 1520
	call	TCP_respond_socket
1521
	pop	ebx
1522
 
1523
	jmp	.destroy_new_socket
1524
 
1525
 
1526
 
1527
 
1528
 
1529
 
1530
 
1531
;-----
1532
; Drop
1533
 
1534
align 4
1535
.drop:
1536
 
1537
	mov	[ebx + SOCKET.lock], 0
1538
 
1539
.drop_not_locked:
1540
 
1541
	DEBUGF	1,"Dropping packet\n"
1542
 
1543
	;;;; If debugging options are enabled, output the packet somwhere
1544
 
1545
  .destroy_new_socket:
1546
 
1547
	;;;; kill the newly created socket
1548
 
1549
	call	kernel_free
1550
	add	esp, 4
1551
	ret