Subversion Repositories Kolibri OS

Rev

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