Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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