Subversion Repositories Kolibri OS

Rev

Rev 1536 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1196 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
1514 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.    ;;
1196 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  TCP.INC                                                        ;;
7
;;                                                                 ;;
8
;;  Part of the tcp/ip network stack for KolibriOS                 ;;
9
;;                                                                 ;;
1514 hidnplayr 10
;;   Written by hidnplayr@kolibrios.org                            ;;
1196 hidnplayr 11
;;                                                                 ;;
1514 hidnplayr 12
;;    Based on the code of 4.4BSD                                  ;;
13
;;                                                                 ;;
1196 hidnplayr 14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
15
;;             Version 2, June 1991                                ;;
16
;;                                                                 ;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1159 hidnplayr 18
 
1206 hidnplayr 19
$Revision: 1542 $
1159 hidnplayr 20
 
1514 hidnplayr 21
; Socket states
22
TCB_CLOSED		equ 0
23
TCB_LISTEN		equ 1
24
TCB_SYN_SENT		equ 2
25
TCB_SYN_RECEIVED	equ 3
26
TCB_ESTABLISHED 	equ 4
27
TCB_CLOSE_WAIT		equ 5
28
TCB_FIN_WAIT_1		equ 6
29
TCB_CLOSING		equ 7
30
TCB_LAST_ACK		equ 8
31
TCB_FIN_WAIT_2		equ 9
32
TCB_TIMED_WAIT		equ 10
1196 hidnplayr 33
 
1514 hidnplayr 34
; Socket Flags
35
TF_ACKNOW		equ 1 shl 0	; ack peer immediately
36
TF_DELACK		equ 1 shl 1	; ack, but try to delay it
37
TF_NODELAY		equ 1 shl 2	; don't delay packets to coalesce
38
TF_NOOPT		equ 1 shl 3	; don't use tcp options
39
TF_SENTFIN		equ 1 shl 4	; have sent FIN
40
TF_REQ_SCALE		equ 1 shl 5	; have/will request window scaling
41
TF_RCVD_SCALE		equ 1 shl 6	; other side has requested scaling
42
TF_REQ_TSTMP		equ 1 shl 7	; have/will request timestamps
43
TF_RCVD_TSTMP		equ 1 shl 8	; a timestamp was received in SYN
44
TF_SACK_PERMIT		equ 1 shl 9	; other side said I could SACK
1249 hidnplayr 45
 
1514 hidnplayr 46
; Segment flags
47
TH_FIN			equ 1 shl 0
48
TH_SYN			equ 1 shl 1
49
TH_RST			equ 1 shl 2
50
TH_PUSH 		equ 1 shl 3
51
TH_ACK			equ 1 shl 4
52
TH_URG			equ 1 shl 5
1318 hidnplayr 53
 
1514 hidnplayr 54
; Segment header options
55
TCP_OPT_EOL		equ 0		; End of option list.
56
TCP_OPT_NOP		equ 1		; No-Operation.
57
TCP_OPT_MAXSEG		equ 2		; Maximum Segment Size.
58
TCP_OPT_WINDOW		equ 3		; window scale
59
TCP_OPT_TIMESTAMP	equ 8
60
 
1519 hidnplayr 61
; Fundamental timer values
62
TCP_time_MSL		equ 47		; max segment lifetime (30s)
63
TCP_time_re_min 	equ 2		; min retransmission (1,28s)
64
TCP_time_re_max 	equ 100 	; max retransmission (64s)
65
TCP_time_pers_min	equ 8		; min persist (5,12s)
66
TCP_time_pers_max	equ 94		; max persist (60,16s)
67
TCP_time_keep_init	equ 118 	; connectione stablishment (75,52s)
68
TCP_time_keep_idle	equ 4608	; idle time before 1st probe (2h)
69
TCP_time_keep_interval	equ 118 	; between probes when no response (75,52s)
70
TCP_time_rtt_default	equ 5		; default Round Trip Time (3,2s)
71
 
72
; timer constants
73
TCP_max_rxtshift	equ 12		; max retransmissions waiting for ACK
74
TCP_max_keepcnt 	equ 8		; max keepalive probes
75
 
1529 hidnplayr 76
;
77
TCP_max_winshift	equ 14
78
TCP_max_win		equ 65535
1519 hidnplayr 79
 
1514 hidnplayr 80
struct	TCP_segment
1159 hidnplayr 81
	.SourcePort		dw ?
82
	.DestinationPort	dw ?
83
	.SequenceNumber 	dd ?
84
	.AckNumber		dd ?
1196 hidnplayr 85
	.DataOffset		db ?	; DataOffset[0-3 bits] and Reserved[4-7]
86
	.Flags			db ?	; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
1159 hidnplayr 87
	.Window 		dw ?
88
	.Checksum		dw ?
89
	.UrgentPointer		dw ?
1514 hidnplayr 90
	.Data:				; ..or options
1159 hidnplayr 91
ends
92
 
1196 hidnplayr 93
align 4
94
uglobal
1514 hidnplayr 95
	TCP_segments_tx 	rd IP_MAX_INTERFACES
96
	TCP_segments_rx 	rd IP_MAX_INTERFACES
97
	TCP_bytes_rx		rq IP_MAX_INTERFACES
98
	TCP_bytes_tx		rq IP_MAX_INTERFACES
99
	TCP_sequence_num	dd ?
1196 hidnplayr 100
endg
101
 
102
 
103
;-----------------------------------------------------------------
104
;
105
; TCP_init
106
;
107
;  This function resets all TCP variables
108
;
109
;-----------------------------------------------------------------
1529 hidnplayr 110
macro	TCP_init {
1196 hidnplayr 111
 
112
	xor	eax, eax
1514 hidnplayr 113
	mov	edi, TCP_segments_tx
114
	mov	ecx, (6*IP_MAX_INTERFACES)
1196 hidnplayr 115
	rep	stosd
116
 
1529 hidnplayr 117
	pseudo_random	eax
118
	mov	[TCP_sequence_num], eax
1196 hidnplayr 119
 
1529 hidnplayr 120
}
1196 hidnplayr 121
 
122
 
1519 hidnplayr 123
;----------------------
1196 hidnplayr 124
;
1159 hidnplayr 125
;
1519 hidnplayr 126
;----------------------
1529 hidnplayr 127
macro	TCP_timer_160ms {
1159 hidnplayr 128
 
1529 hidnplayr 129
local	.loop
130
local	.exit
131
 
1514 hidnplayr 132
	mov	eax, net_sockets
133
  .loop:
134
	mov	eax, [eax + SOCKET.NextPtr]
135
	or	eax, eax
1159 hidnplayr 136
	jz	.exit
137
 
1542 hidnplayr 138
	cmp	[eax + SOCKET.Protocol], IP_PROTO_TCP		;;; We should also check if family is AF_INET
1514 hidnplayr 139
	jne	.loop
1249 hidnplayr 140
 
1519 hidnplayr 141
	dec	[eax + TCP_SOCKET.timer_ack]
1514 hidnplayr 142
	jnz	.loop
1159 hidnplayr 143
 
1519 hidnplayr 144
	DEBUGF	1,"TCP ack for socket %x expired, time to piggyback!\n", eax
1159 hidnplayr 145
 
1519 hidnplayr 146
	push	eax
1529 hidnplayr 147
	call	TCP_respond_socket
1514 hidnplayr 148
	pop	eax
1159 hidnplayr 149
 
1519 hidnplayr 150
	jmp	.loop
1159 hidnplayr 151
 
152
  .exit:
1519 hidnplayr 153
 
1529 hidnplayr 154
}
1159 hidnplayr 155
 
156
 
1519 hidnplayr 157
;-----------------------------------------------------------------
1159 hidnplayr 158
;
159
;
1519 hidnplayr 160
;-----------------------------------------------------------------
1529 hidnplayr 161
macro	TCP_timer_640ms {
1159 hidnplayr 162
 
1529 hidnplayr 163
local	.loop
164
local	.exit
165
 
1519 hidnplayr 166
; Update TCP sequence number
167
 
1514 hidnplayr 168
	add	[TCP_sequence_num], 64000
1159 hidnplayr 169
 
1519 hidnplayr 170
; scan through all the active TCP sockets, decrementing ALL timers
171
; timers do not have the chance to wrap because of the keepalive timer will kill the socket when it expires
1159 hidnplayr 172
 
1519 hidnplayr 173
	mov	eax, net_sockets
174
  .loop:
175
	mov	eax, [eax + SOCKET.NextPtr]
176
  .check_only:
177
	or	eax, eax
178
	jz	.exit
1159 hidnplayr 179
 
1542 hidnplayr 180
	cmp	[eax + SOCKET.Protocol], IP_PROTO_TCP	  ;;; We should also check if family is AF_INET
1519 hidnplayr 181
	jne	.loop
1159 hidnplayr 182
 
1529 hidnplayr 183
	inc	[eax + TCP_SOCKET.t_idle]
184
	dec	[eax + TCP_SOCKET.timer_retransmission]
1519 hidnplayr 185
	jnz	.check_more2
1254 hidnplayr 186
 
1519 hidnplayr 187
	DEBUGF	1,"socket %x: Retransmission timer expired\n", eax
1159 hidnplayr 188
 
1519 hidnplayr 189
	push	eax
190
	call	TCP_output
191
	pop	eax
1159 hidnplayr 192
 
1519 hidnplayr 193
  .check_more2:
194
	dec	[eax + TCP_SOCKET.timer_keepalive]
195
	jnz	.check_more3
1159 hidnplayr 196
 
1519 hidnplayr 197
	DEBUGF	1,"socket %x: Keepalive expired\n", eax
1159 hidnplayr 198
 
1519 hidnplayr 199
	;;; TODO: check socket state and handle accordingly
1318 hidnplayr 200
 
1519 hidnplayr 201
  .check_more3:
202
	dec	[eax + TCP_SOCKET.timer_timed_wait]
203
	jnz	.check_more5
204
 
205
	DEBUGF	1,"socket %x: 2MSL timer expired\n", eax
206
 
207
  .check_more5:
208
	dec	[eax + TCP_SOCKET.timer_persist]
209
	jnz	.loop
210
 
211
	DEBUGF	1,"socket %x: persist timer expired\n", eax
212
 
213
	jmp	.loop
214
  .exit:
1529 hidnplayr 215
}
1519 hidnplayr 216
 
217
 
1529 hidnplayr 218
 
219
 
220
macro	TCP_checksum IP1, IP2 {
221
 
222
;-------------
223
; Pseudoheader
224
 
225
	; protocol type
226
	mov	edx, IP_PROTO_TCP
227
 
228
	; source address
1530 hidnplayr 229
	add	dl, byte [IP1+1]
230
	adc	dh, byte [IP1+0]
231
	adc	dl, byte [IP1+3]
232
	adc	dh, byte [IP1+2]
1529 hidnplayr 233
 
234
	; destination address
1530 hidnplayr 235
	adc	dl, byte [IP2+1]
236
	adc	dh, byte [IP2+0]
237
	adc	dl, byte [IP2+3]
238
	adc	dh, byte [IP2+2]
1529 hidnplayr 239
 
240
	; size
241
	adc	dl, cl
242
	adc	dh, ch
243
 
244
;---------------------
245
; Real header and data
246
 
247
	push	esi
248
	call	checksum_1
249
	call	checksum_2
250
	pop	esi
251
 
252
}	; returns in dx only
253
 
254
 
1533 hidnplayr 255
macro	TCP_sendseqinit ptr {
1529 hidnplayr 256
 
1533 hidnplayr 257
	push	edi			;;;; i dont like this static use of edi
258
	mov	edi, [ptr + TCP_SOCKET.ISS]
259
	mov	[ptr + TCP_SOCKET.SND_UP], edi
260
	mov	[ptr + TCP_SOCKET.SND_MAX], edi
261
	mov	[ptr + TCP_SOCKET.SND_NXT], edi
262
	mov	[ptr + TCP_SOCKET.SND_UNA], edi
263
	pop	edi
264
 
265
}
266
 
267
macro	TCP_rcvseqinit ptr {
268
 
269
	push	edi
270
	mov	edi, [ptr + TCP_SOCKET.IRS]
271
	inc	edi
272
	mov	[ptr + TCP_SOCKET.RCV_NXT], edi
273
	mov	[ptr + TCP_SOCKET.RCV_ADV], edi
274
	pop	edi
275
 
276
}
277
 
278
 
279
 
1249 hidnplayr 280
;-----------------------------------------------------------------
281
;
1514 hidnplayr 282
; TCP_input:
1159 hidnplayr 283
;
1514 hidnplayr 284
;  IN:  [esp] = ptr to buffer
285
;       [esp+4] = buffer size
286
;       ebx = ptr to device struct
287
;       ecx = segment size
288
;       edx = ptr to TCP segment
1196 hidnplayr 289
;
1514 hidnplayr 290
;       esi = ipv4 source address
291
;       edi = ipv4 dest   address
292
;
1196 hidnplayr 293
;  OUT: /
294
;
295
;-----------------------------------------------------------------
1249 hidnplayr 296
align 4
1514 hidnplayr 297
TCP_input:
1159 hidnplayr 298
 
1529 hidnplayr 299
       DEBUGF  1,"TCP_input size=%u\n", ecx
1514 hidnplayr 300
; 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.
1254 hidnplayr 301
 
1514 hidnplayr 302
	movzx	eax, [edx + TCP_segment.DataOffset]
303
	and	eax, 0xf0
1529 hidnplayr 304
	shr	al, 2
1514 hidnplayr 305
 
1529 hidnplayr 306
	DEBUGF	1,"headersize=%u\n", eax
1514 hidnplayr 307
 
308
	cmp	eax, 20
309
	jl	.drop
310
 
311
;-------------------------------
312
; Now, re-calculate the checksum
313
 
1529 hidnplayr 314
	push	eax ecx edx
315
	pushw	[edx + TCP_segment.Checksum]
316
	mov	[edx + TCP_segment.Checksum], 0
317
	push	esi edi
1514 hidnplayr 318
	mov	esi, edx
1530 hidnplayr 319
	TCP_checksum (esp), (esp+4)
1529 hidnplayr 320
	pop	esi edi ; yes, swap them (we dont need dest addr)
321
	pop	cx	; previous checksum
322
	cmp	cx, dx
323
	pop	edx ecx esi
1514 hidnplayr 324
	jnz	.drop
325
 
326
	DEBUGF	1,"Checksum is correct\n"
327
 
1529 hidnplayr 328
	sub	ecx, esi	; update packet size
329
	jl	.drop
1534 hidnplayr 330
	DEBUGF	1,"we got %u bytes of data\n", ecx
1529 hidnplayr 331
 
1514 hidnplayr 332
;-----------------------------------------------------------------------------------------
333
; Check if this packet has a timestamp option (We do it here so we can process it quickly)
334
 
1529 hidnplayr 335
	cmp	esi, 20 + 12					; Timestamp option is 12 bytes
1514 hidnplayr 336
	jl	.no_timestamp
337
	je	.is_ok
338
 
1529 hidnplayr 339
	cmp	byte [edx + TCP_segment.Data + 12], TCP_OPT_EOL ; end of option list
1514 hidnplayr 340
	jne	.no_timestamp
341
 
342
  .is_ok:
343
	test	[edx + TCP_segment.Flags], TH_SYN		; SYN flag must not be set
344
	jnz	.no_timestamp
345
 
346
	cmp	dword [edx + TCP_segment.Data], 0x0101080a	; Timestamp header
347
	jne	.no_timestamp
348
 
349
	DEBUGF	1,"timestamp ok\n"
350
 
1529 hidnplayr 351
	; TODO: Parse the option
1514 hidnplayr 352
	; TODO: Set a Bit in the TCP to tell all options are parsed
353
 
354
  .no_timestamp:
355
 
356
;-------------------------------------------
357
; Convert Big-endian values to little endian
358
 
359
	ntohld	[edx + TCP_segment.SequenceNumber]
360
	ntohld	[edx + TCP_segment.AckNumber]
361
 
362
	ntohlw	[edx + TCP_segment.Window]
363
	ntohlw	[edx + TCP_segment.UrgentPointer]
1529 hidnplayr 364
	ntohlw	[edx + TCP_segment.SourcePort]
365
	ntohlw	[edx + TCP_segment.DestinationPort]
1514 hidnplayr 366
 
367
;------------------------------------------------------------
368
; Next thing to do is find the TCB (thus, the socket pointer)
369
 
1274 hidnplayr 370
; IP Packet TCP Destination Port = local Port
1514 hidnplayr 371
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
1318 hidnplayr 372
; (IP Packet TCP Source Port = remote Port)  OR (remote Port = 0)
1159 hidnplayr 373
 
374
	mov	ebx, net_sockets
375
 
1249 hidnplayr 376
  .socket_loop:
1514 hidnplayr 377
	mov	ebx, [ebx + SOCKET.NextPtr]
1159 hidnplayr 378
	or	ebx, ebx
1514 hidnplayr 379
	jz	.drop_with_reset
1159 hidnplayr 380
 
1542 hidnplayr 381
	cmp	[ebx + SOCKET.Protocol], IP_PROTO_TCP	  ;;; We should also check if family is AF_INET
1249 hidnplayr 382
	jne	.socket_loop
1159 hidnplayr 383
 
1514 hidnplayr 384
	mov	ax, [edx + TCP_segment.DestinationPort]
385
	cmp	[ebx + TCP_SOCKET.LocalPort], ax
386
	jne	.socket_loop
387
 
388
	mov	eax, [ebx + IP_SOCKET.RemoteIP]
1529 hidnplayr 389
	cmp	eax, edi			; sender IP
1249 hidnplayr 390
	je	@f
391
	test	eax, eax
1514 hidnplayr 392
	jnz	.socket_loop
1249 hidnplayr 393
       @@:
1159 hidnplayr 394
 
1514 hidnplayr 395
	mov	ax, [ebx + TCP_SOCKET.RemotePort]
396
	cmp	[edx + TCP_segment.SourcePort] , ax
1274 hidnplayr 397
	je	.found_socket
1249 hidnplayr 398
	test	ax, ax
1254 hidnplayr 399
	jnz	.socket_loop
1274 hidnplayr 400
  .found_socket:
1529 hidnplayr 401
	DEBUGF	1,"Socket ptr: %x\n", ebx
1254 hidnplayr 402
 
1514 hidnplayr 403
; ebx now contains the pointer to the socket
1257 hidnplayr 404
 
1514 hidnplayr 405
;----------------------------
406
; Check if socket isnt closed
407
 
1529 hidnplayr 408
	cmp	[ebx + TCP_SOCKET.t_state], TCB_CLOSED
1514 hidnplayr 409
	je	.drop
410
 
411
;----------------
412
; Lock the socket
413
 
1529 hidnplayr 414
;;        add     ebx, SOCKET.lock ; TODO: figure out if we should lock now already
415
;;        call    wait_mutex
416
;;        sub     ebx, SOCKET.lock
1159 hidnplayr 417
 
1529 hidnplayr 418
	DEBUGF	1,"Socket locked\n"
1159 hidnplayr 419
 
1529 hidnplayr 420
;----------------------------------------------------------------------------------------
421
; unscale the window into a 32 bit value (notice that SND_SCALE must be initialised to 0)
422
 
1514 hidnplayr 423
	movzx	eax, [edx + TCP_segment.Window]
1534 hidnplayr 424
	push	ecx
1529 hidnplayr 425
	mov	cl, [ebx + TCP_SOCKET.SND_SCALE]
1514 hidnplayr 426
	shl	eax, cl
1534 hidnplayr 427
	pop	ecx
1514 hidnplayr 428
 
1529 hidnplayr 429
	;;;; do something with eax
1514 hidnplayr 430
 
431
;-----------------------------------
432
; Is this socket a listening socket?
433
 
1533 hidnplayr 434
	test	[ebx + SOCKET.options], SO_ACCEPTCON
1529 hidnplayr 435
;        jnz     .listening_socket                       ;;;;; TODO
1514 hidnplayr 436
 
1529 hidnplayr 437
;-------------------------------------
438
; Reset idle timer and keepalive timer
1514 hidnplayr 439
 
1529 hidnplayr 440
	mov	[ebx + TCP_SOCKET.t_idle], 0
441
	mov	[ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
1514 hidnplayr 442
 
1529 hidnplayr 443
;--------------------
444
; Process TCP options
1514 hidnplayr 445
 
1529 hidnplayr 446
	cmp	esi, 20 			; esi is headersize
447
	je	.no_options
1514 hidnplayr 448
 
1529 hidnplayr 449
	DEBUGF	1,"Segment has options\n"
1514 hidnplayr 450
 
1530 hidnplayr 451
	cmp	[ebx + TCP_SOCKET.t_state], TCB_LISTEN		; no options when in listen state
1529 hidnplayr 452
	jz	.no_options
1514 hidnplayr 453
 
1529 hidnplayr 454
	lea	edi, [edx + TCP_segment.Data]
455
	lea	eax, [edx + esi]
1514 hidnplayr 456
 
1529 hidnplayr 457
  .opt_loop:
458
	cmp	edi, eax
459
	jge	.no_options
1514 hidnplayr 460
 
1529 hidnplayr 461
	cmp	byte [edi], TCP_OPT_EOL 	; end of option list?
462
	jz	.no_options
1514 hidnplayr 463
 
1529 hidnplayr 464
	cmp	byte [edi], TCP_OPT_NOP 	; nop ?
465
	jz	.opt_nop
1514 hidnplayr 466
 
1529 hidnplayr 467
	cmp	byte [edi], TCP_OPT_MAXSEG
468
	je	.opt_maxseg
1514 hidnplayr 469
 
1529 hidnplayr 470
	cmp	byte [edi], TCP_OPT_WINDOW
471
	je	.opt_window
1514 hidnplayr 472
 
1529 hidnplayr 473
	cmp	byte [edi], TCP_OPT_TIMESTAMP
474
	je	.opt_timestamp
1514 hidnplayr 475
 
1529 hidnplayr 476
	jmp	.no_options	; If we reach here, some unknown options were received, skip them all!
1514 hidnplayr 477
 
1529 hidnplayr 478
  .opt_nop:
479
	inc	edi
480
	jmp	.opt_loop
1514 hidnplayr 481
 
1529 hidnplayr 482
  .opt_maxseg:
483
	cmp	byte [edi+1], 4
484
	jne	.no_options		; error occured, ignore all options!
1514 hidnplayr 485
 
1529 hidnplayr 486
	test	[edx + TCP_segment.Flags], TH_SYN
487
	jz	@f
488
 
1530 hidnplayr 489
	movzx	eax, word[edi+2]
490
	rol	ax, 8
1533 hidnplayr 491
	DEBUGF	1,"Maxseg: %u\n", ax
1529 hidnplayr 492
 
1530 hidnplayr 493
	mov	[ebx + TCP_SOCKET.t_maxseg], eax
494
 
1529 hidnplayr 495
       @@:
496
	add	edi, 4
497
	jmp	.opt_loop
498
 
499
 
500
  .opt_window:
501
	cmp	byte [edi+1], 3
502
	jne	.no_options
503
 
504
	test	[edx + TCP_segment.Flags], TH_SYN
505
	jz	@f
506
 
1533 hidnplayr 507
	DEBUGF	1,"Got window option\n"
1529 hidnplayr 508
 
509
	;;;;;
510
       @@:
511
	add	edi, 3
512
	jmp	.opt_loop
513
 
514
 
515
  .opt_timestamp:
516
	cmp	byte [edi+1], 10
517
	jne	.no_options
518
 
1533 hidnplayr 519
	DEBUGF	1,"Got timestamp option\n"
1529 hidnplayr 520
 
521
	;;;;;
522
 
523
	add	edi, 10
524
	jmp	.opt_loop
525
 
526
  .no_options:
527
 
1514 hidnplayr 528
;-----------------------------------------------------------------------
529
; Time to do some header prediction (Original Principle by Van Jacobson)
530
 
531
; There are two common cases for an uni-directional data transfer.
532
;
533
; General rule: the packets has no control flags, is in-sequence,
534
;   window width didnt change and we're not retransmitting.
535
;
536
; Second rules:
537
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
538
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
539
;
540
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
541
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
542
 
1529 hidnplayr 543
	cmp	[ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
1514 hidnplayr 544
	jnz	.not_uni_xfer
545
 
1529 hidnplayr 546
	test	[edx + TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
1514 hidnplayr 547
	jnz	.not_uni_xfer
548
 
1529 hidnplayr 549
	test	[edx + TCP_segment.Flags], TH_ACK
1514 hidnplayr 550
	jz	.not_uni_xfer
551
 
552
	mov	eax, [edx + TCP_segment.SequenceNumber]
553
	cmp	eax, [ebx + TCP_SOCKET.RCV_NXT]
554
	jne	.not_uni_xfer
555
 
1536 hidnplayr 556
	movzx	eax, [edx + TCP_segment.Window] ;;;;; (should use pre-calculated value instead: todo: figure out where to store it)
557
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
558
	jne	.not_uni_xfer
1514 hidnplayr 559
 
560
	mov	eax, [ebx + TCP_SOCKET.SND_NXT]
561
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
562
	jne	.not_uni_xfer
563
 
564
;---------------------------------------
565
; check if we are sender in the uni-xfer
566
 
567
; If the following 4 conditions are all true, this segment is a pure ACK.
568
;
1529 hidnplayr 569
; - The segment contains no data.
570
	test	ecx, ecx
1514 hidnplayr 571
	jnz	.not_sender
1274 hidnplayr 572
 
1529 hidnplayr 573
; - The congestion window is greater than or equal to the current send window.
1514 hidnplayr 574
;     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.
575
	mov	eax, [ebx + TCP_SOCKET.SND_CWND]
576
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
577
	jl	.not_uni_xfer
1318 hidnplayr 578
 
1529 hidnplayr 579
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
1534 hidnplayr 580
	mov	eax, [edx + TCP_segment.AckNumber]
581
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
1529 hidnplayr 582
	jg	.not_uni_xfer
583
 
584
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
1534 hidnplayr 585
	sub	eax, [ebx + TCP_SOCKET.SND_UNA]
1529 hidnplayr 586
	jle	.not_uni_xfer
587
 
1514 hidnplayr 588
	DEBUGF	1,"Header prediction: we are sender\n"
1274 hidnplayr 589
 
1514 hidnplayr 590
;---------------------------------
591
; Packet is a pure ACK, process it
1274 hidnplayr 592
 
1514 hidnplayr 593
; Update RTT estimators
1159 hidnplayr 594
 
1514 hidnplayr 595
; Delete acknowledged bytes from send buffer
1536 hidnplayr 596
	mov	ecx, eax
1533 hidnplayr 597
	lea	eax, [ebx + STREAM_SOCKET.snd]
1529 hidnplayr 598
	call	SOCKET_ring_free
599
 
1536 hidnplayr 600
; update window pointers
601
	mov	eax, [edx + TCP_segment.AckNumber]
602
	dec	eax
603
	mov	[ebx + TCP_SOCKET.SND_WL1], eax
604
 
1514 hidnplayr 605
; Stop retransmit timer
1519 hidnplayr 606
	mov	[ebx + TCP_SOCKET.timer_ack], 0
1159 hidnplayr 607
 
1514 hidnplayr 608
; Awaken waiting processes
1519 hidnplayr 609
	mov	eax, ebx
610
	call	SOCKET_notify_owner
1318 hidnplayr 611
 
1536 hidnplayr 612
;; Generate more output
613
;;        mov     eax, ebx
614
;;        call    TCP_output
615
;;
616
;;        jmp     .drop
617
	jmp	.step6
1254 hidnplayr 618
 
1514 hidnplayr 619
;-------------------------------------------------
620
; maybe we are the receiver in the uni-xfer then..
621
 
622
  .not_sender:
1529 hidnplayr 623
; - The amount of data in the segment is greater than 0 (data count is in ecx)
1514 hidnplayr 624
 
1529 hidnplayr 625
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
1514 hidnplayr 626
	mov	eax, [edx + TCP_segment.AckNumber]
627
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
628
	jne	.not_uni_xfer
629
 
1529 hidnplayr 630
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp). ;;;;;;;
1514 hidnplayr 631
 
632
	jnz	.not_uni_xfer
633
 
634
;-------------------------------------
635
; Complete processing of received data
636
 
637
	DEBUGF	1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
638
 
1529 hidnplayr 639
	add	esi, edx
1533 hidnplayr 640
	lea	eax, [ebx + STREAM_SOCKET.rcv]
641
	call	SOCKET_ring_write			; Add the data to the socket buffer
1514 hidnplayr 642
 
1533 hidnplayr 643
	mov	eax, ebx
644
	call	SOCKET_notify_owner
645
 
1529 hidnplayr 646
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx 	; Update sequence number with number of bytes we have copied
647
	or	[ebx + TCP_SOCKET.t_flags], TF_DELACK	; Set delayed ack flag
1514 hidnplayr 648
 
649
	jmp	.drop
650
 
651
;----------------------------------------------------
1529 hidnplayr 652
; Header prediction failed, doing it the slow way..     ;;;;; current implementation of header prediction destroys some regs (ecx) !!
1514 hidnplayr 653
 
654
  .not_uni_xfer:
655
 
1533 hidnplayr 656
	DEBUGF	1,"Header prediction failed\n"		; time to do it the "slow" way :)
1514 hidnplayr 657
 
658
;------------------------------
659
; Calculate receive window size
660
 
661
	;;;;
662
 
1529 hidnplayr 663
	cmp	[ebx + TCP_SOCKET.t_state], TCB_LISTEN
1514 hidnplayr 664
	je	.LISTEN
665
 
1529 hidnplayr 666
	cmp	[ebx + TCP_SOCKET.t_state], TCB_SYN_SENT
1514 hidnplayr 667
	je	.SYN_SENT
668
 
669
;--------------------------------------------
670
; Protection Against Wrapped Sequence Numbers
671
 
1533 hidnplayr 672
; First, check if timestamp is present
1514 hidnplayr 673
 
674
;;;; TODO
675
 
676
; Then, check if at least some bytes of data are within window
677
 
678
;;;; TODO
679
 
680
	jmp	.trim_then_step6
681
 
1529 hidnplayr 682
;-------------
683
; Passive Open
684
 
1249 hidnplayr 685
align 4
1514 hidnplayr 686
.LISTEN:
1196 hidnplayr 687
 
1514 hidnplayr 688
	DEBUGF	1,"TCP state: listen\n"
1159 hidnplayr 689
 
1514 hidnplayr 690
	test	[edx + TCP_segment.Flags], TH_RST
691
	jnz	.drop
1159 hidnplayr 692
 
1514 hidnplayr 693
	test	[edx + TCP_segment.Flags], TH_ACK
694
	jnz	.drop_with_reset
1159 hidnplayr 695
 
1514 hidnplayr 696
	test	[edx + TCP_segment.Flags], TH_SYN
697
	jz	.drop
1159 hidnplayr 698
 
1533 hidnplayr 699
	cmp	esi, 0xffffff		; destination ip = 255.255.255.255 ?
700
	jz	.drop
701
 
1514 hidnplayr 702
	; TODO: check if it's a broadcast or multicast, and drop if so
1159 hidnplayr 703
 
1529 hidnplayr 704
	call	SOCKET_fork
705
	jz	.drop		; if we could not open a new connection, drop segment (;;;; should we send RST too?)
1514 hidnplayr 706
 
1529 hidnplayr 707
;-----------------------
708
; Fill in some variables
1514 hidnplayr 709
 
1529 hidnplayr 710
	add	[TCP_sequence_num], 64000
1514 hidnplayr 711
 
1529 hidnplayr 712
	push	[edx + TCP_segment.SourcePort]
713
	pop	[eax + TCP_SOCKET.RemotePort]
1514 hidnplayr 714
 
1529 hidnplayr 715
	push	[edx + TCP_segment.SequenceNumber]
716
	pop	[eax + TCP_SOCKET.IRS]
1159 hidnplayr 717
 
1529 hidnplayr 718
	push	[eax + TCP_SOCKET.ISS]
719
	pop	[eax + TCP_SOCKET.SND_NXT]
1159 hidnplayr 720
 
1529 hidnplayr 721
	mov	[eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
722
	mov	[eax + TCP_SOCKET.t_flags], TF_ACKNOW
723
	mov	[eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
1159 hidnplayr 724
 
1529 hidnplayr 725
	mov	ebx, eax
1514 hidnplayr 726
	jmp	.trim_then_step6
1159 hidnplayr 727
 
1254 hidnplayr 728
 
1529 hidnplayr 729
;------------
730
; Active Open
1159 hidnplayr 731
 
1514 hidnplayr 732
align 4
733
.SYN_SENT:
1281 hidnplayr 734
 
1514 hidnplayr 735
	DEBUGF	1,"TCP state: syn_sent\n"
1159 hidnplayr 736
 
1514 hidnplayr 737
	test	[edx + TCP_segment.Flags], TH_ACK
738
	jz	@f
1281 hidnplayr 739
 
1514 hidnplayr 740
	mov	eax, [edx + TCP_segment.AckNumber]
741
	cmp	eax, [ebx + TCP_SOCKET.ISS]
742
	jle	.drop_with_reset
1281 hidnplayr 743
 
1529 hidnplayr 744
;        mov     eax, [edx + TCP_segment.AckNumber]
1533 hidnplayr 745
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
746
	jg	.drop_with_reset
1514 hidnplayr 747
       @@:
1281 hidnplayr 748
 
1514 hidnplayr 749
	test	[edx + TCP_segment.Flags], TH_RST
750
	jz	@f
1281 hidnplayr 751
 
1514 hidnplayr 752
	test	[edx + TCP_segment.Flags], TH_ACK
753
	jz	.drop
1281 hidnplayr 754
 
1514 hidnplayr 755
	;tp = tcp_drop(tp, ECONNREFUSED)
1159 hidnplayr 756
 
1514 hidnplayr 757
	jmp	.drop
758
       @@:
1159 hidnplayr 759
 
1514 hidnplayr 760
	test	[edx + TCP_segment.Flags], TH_SYN
761
	jz	.drop
1318 hidnplayr 762
 
1529 hidnplayr 763
; at this point, segment seems to be valid
764
 
1514 hidnplayr 765
	test	[edx + TCP_segment.Flags], TH_ACK
1529 hidnplayr 766
	jz	.no_syn_ack
1514 hidnplayr 767
 
1529 hidnplayr 768
; now, process received SYN in response to an active open
769
 
1514 hidnplayr 770
	mov	eax, [edx + TCP_segment.AckNumber]
771
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
772
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
773
	jle	@f
774
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1529 hidnplayr 775
       @@:
1514 hidnplayr 776
 
1529 hidnplayr 777
  .no_syn_ack:
1514 hidnplayr 778
 
1529 hidnplayr 779
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0	; disable retransmission
1514 hidnplayr 780
 
1529 hidnplayr 781
	push	[edx + TCP_segment.SequenceNumber]
782
	pop	[ebx + TCP_SOCKET.IRS]
783
 
1533 hidnplayr 784
	TCP_rcvseqinit ebx
1529 hidnplayr 785
 
786
	mov	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
787
 
788
	mov	eax, [ebx + TCP_SOCKET.SND_UNA]
789
	cmp	eax, [ebx + TCP_SOCKET.ISS]
790
	jle	.simultaneous_open
791
 
792
	test	[edx + TCP_segment.Flags], TH_ACK
793
	jz	.simultaneous_open
794
 
795
	DEBUGF	1,"TCP: active open\n"
796
 
797
; TODO: update stats
1533 hidnplayr 798
; TODO: set general socket state to connected
1514 hidnplayr 799
 
800
	mov	[ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
801
 
802
; TODO: check if we should scale the connection (567-572)
803
; TODO: update RTT estimators
804
 
1529 hidnplayr 805
	jmp	.trimthenstep6
1514 hidnplayr 806
 
1529 hidnplayr 807
  .simultaneous_open:
1514 hidnplayr 808
 
1529 hidnplayr 809
	DEBUGF	1,"TCP: simultaneous open\n"
1514 hidnplayr 810
; We have received a syn but no ACK, so we are having a simultaneous open..
811
	mov	[ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
812
 
813
;-------------------------------------
814
; Common processing for receipt of SYN
815
 
816
  .trimthenstep6:
817
 
818
	inc	[edx + TCP_segment.SequenceNumber]
819
 
820
	cmp	cx, [ebx + TCP_SOCKET.RCV_WND]
821
	jle	@f
822
 
823
	movzx	eax, cx
824
	sub	ax, [ebx + TCP_SOCKET.RCV_WND]
825
	; TODO: 592
826
	mov	cx, [ebx + TCP_SOCKET.RCV_WND]
827
	; TODO...
828
       @@:
829
	;;;;;
1529 hidnplayr 830
	jmp	.step6
1514 hidnplayr 831
 
832
 
833
 
834
 
835
 
1529 hidnplayr 836
  .trim_then_step6:
1159 hidnplayr 837
 
1514 hidnplayr 838
;----------------------------
839
; trim any data not in window
1159 hidnplayr 840
 
1533 hidnplayr 841
	DEBUGF	1,"Trimming window\n"
842
 
1514 hidnplayr 843
	mov	eax, [ebx + TCP_SOCKET.RCV_NXT]
844
	sub	eax, [edx + TCP_segment.SequenceNumber]
1318 hidnplayr 845
 
1514 hidnplayr 846
	test	eax, eax
1533 hidnplayr 847
	jz	.no_duplicate
1274 hidnplayr 848
 
1514 hidnplayr 849
	test	[edx + TCP_segment.Flags], TH_SYN
850
	jz	.no_drop
851
 
852
	and	[edx + TCP_segment.Flags], not (TH_SYN)
853
	inc	[edx + TCP_segment.SequenceNumber]
854
 
855
	cmp	[edx + TCP_segment.UrgentPointer], 1
856
	jl	@f
857
 
858
	dec	[edx + TCP_segment.UrgentPointer]
859
 
860
	jmp	.no_drop
861
       @@:
862
 
863
	and	[edx + TCP_segment.Flags], not (TH_URG)
864
	dec	eax
1533 hidnplayr 865
	jz	.no_duplicate
1514 hidnplayr 866
  .no_drop:
867
 
1533 hidnplayr 868
	DEBUGF	1,"Going to drop %u out of %u bytes\n", eax, ecx
1529 hidnplayr 869
 
1514 hidnplayr 870
; eax holds number of bytes to drop
871
 
872
;----------------------------------
873
; Check for entire duplicate packet
874
 
875
	cmp	eax, ecx
876
	jge	.duplicate
877
 
878
	;;; TODO: figure 28.30
879
 
880
;------------------------
881
; Check for duplicate FIN
882
 
883
	test	[edx + TCP_segment.Flags], TH_FIN
884
	jz	@f
885
	inc	ecx
886
	cmp	eax, ecx
887
	dec	ecx
888
	jne	@f
889
 
890
	mov	eax, ecx
891
	and	[edx + TCP_segment.Flags], not TH_FIN
1529 hidnplayr 892
	or	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1514 hidnplayr 893
	jmp	.no_duplicate
894
       @@:
895
 
896
	; Handle the case when a bound socket connects to itself
897
	; Allow packets with a SYN and an ACKto continue with the processing
898
 
899
;-------------------------------------
900
; Generate duplicate ACK if nescessary
901
 
902
; This code also handles simultaneous half-open or self-connects
903
 
904
	test	eax, eax
905
	jnz	.drop_after_ack
906
 
907
	cmp	[edx + TCP_segment.Flags], TH_ACK
908
	jz	.drop_after_ack
909
 
910
  .duplicate:
911
 
1533 hidnplayr 912
	DEBUGF	1,"Duplicate received\n"
1529 hidnplayr 913
 
1514 hidnplayr 914
;----------------------------------------
915
; Update statistics for duplicate packets
916
 
917
	;;; TODO
918
 
1529 hidnplayr 919
	jmp	.drop	       ;;; DROP the packet ??
1514 hidnplayr 920
 
921
  .no_duplicate:
922
 
923
;-----------------------------------------------
924
; Remove duplicate data and update urgent offset
925
 
926
	add	[edx + TCP_segment.SequenceNumber], eax
927
 
928
	;;; TODO
929
 
930
	sub	[edx + TCP_segment.UrgentPointer], ax
931
	jg	@f
932
 
933
	and	[edx + TCP_segment.Flags], not (TH_URG)
934
	mov	[edx + TCP_segment.UrgentPointer], 0
935
       @@:
936
 
937
;--------------------------------------------------
938
; Handle data that arrives after process terminates
939
 
940
	cmp	[ebx + SOCKET.PID], 0
1533 hidnplayr 941
	jg	@f
1514 hidnplayr 942
 
943
	cmp	[ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT
944
	jle	@f
945
 
946
	test	ecx, ecx
947
	jz	@f
948
 
949
	;;; Close the socket
950
	;;; update stats
951
 
952
	jmp	.drop_with_reset
953
       @@:
954
 
955
;----------------------------------------
956
; Remove data beyond right edge of window
957
 
958
	mov	eax, [edx + TCP_segment.SequenceNumber]
959
	add	eax, ecx
960
	sub	eax, [ebx + TCP_SOCKET.RCV_NXT]
961
	sub	ax, [ebx + TCP_SOCKET.RCV_WND]
962
 
963
	; eax now holds the number of bytes to drop
964
 
965
	jle	.no_excess_data
966
 
967
	;;; TODO: update stats
968
 
969
	cmp	eax, ecx
970
	jl	.dont_drop_all
971
 
972
;;; TODO 700-736
973
 
974
  .dont_drop_all:
975
 
976
  .no_excess_data:
977
 
978
;-----------------
979
; Record timestamp
980
 
981
	;;; TODO 737-746
982
 
983
;------------------
984
; Process RST flags
985
 
986
	test	[edx + TCP_segment.Flags], TH_RST
987
	jz	.rst_skip
988
 
1529 hidnplayr 989
	DEBUGF	1,"Got an RST flag"
990
 
1514 hidnplayr 991
	mov	eax, [ebx + TCP_SOCKET.t_state]
992
	shl	eax, 2
993
	jmp	dword [eax + .rst_sw_list]
994
 
995
  .rst_sw_list:
996
	dd	.rst_skip	;TCB_CLOSED
997
	dd	.rst_skip	;TCB_LISTEN
998
	dd	.rst_skip	;TCB_SYN_SENT
999
	dd	.econnrefused	;TCB_SYN_RECEIVED
1000
	dd	.econnreset	;TCB_ESTABLISHED
1001
	dd	.econnreset	;TCB_CLOSE_WAIT
1002
	dd	.econnreset	;TCB_FIN_WAIT_1
1003
	dd	.rst_close	;TCB_CLOSING
1004
	dd	.rst_close	;TCB_LAST_ACK
1005
	dd	.econnreset	;TCB_FIN_WAIT_2
1006
	dd	.rst_close	;TCB_TIMED_WAIT
1007
 
1008
  .econnrefused:
1009
 
1529 hidnplayr 1010
	DEBUGF	1,"Connection refused"
1011
 
1514 hidnplayr 1012
	;;; TODO: debug info
1013
 
1014
	jmp	.close
1015
 
1016
  .econnreset:
1017
 
1529 hidnplayr 1018
	DEBUGF	1,"Connection reset"
1019
 
1514 hidnplayr 1020
	;;; TODO: debug info
1529 hidnplayr 1021
  .close:
1514 hidnplayr 1022
 
1529 hidnplayr 1023
	DEBUGF	1,"Closing connection"
1024
 
1514 hidnplayr 1025
	;;; update stats
1026
 
1027
  .rst_close:
1028
 
1534 hidnplayr 1029
	DEBUGF	1,"Closing with reset\n"
1529 hidnplayr 1030
 
1514 hidnplayr 1031
	;;; Close the socket
1032
	jmp	.drop
1033
 
1034
  .rst_skip:
1035
 
1036
;--------------------------------------
1037
; handle SYN-full and ACK-less segments
1038
 
1039
	test	[edx + TCP_segment.Flags], TH_SYN
1040
	jz	@f
1041
 
1042
	;;; tcp_drop ( ECONNRESET)
1043
	jmp	.drop_with_reset
1044
 
1045
	test	[edx + TCP_segment.Flags], TH_ACK
1046
	jz	.drop
1534 hidnplayr 1047
      @@:
1514 hidnplayr 1048
;----------------
1049
; Process the ACK
1050
 
1051
	cmp	[ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
1052
	jg	.ack_dup
1053
	jl	.ack_nodup
1054
 
1534 hidnplayr 1055
	DEBUGF	1,"TCP state = syn received\n"
1533 hidnplayr 1056
 
1514 hidnplayr 1057
	;;;;;
1058
 
1536 hidnplayr 1059
  .ack_nodup:
1514 hidnplayr 1060
 
1536 hidnplayr 1061
	DEBUGF	1,"New ACK\n"
1533 hidnplayr 1062
 
1514 hidnplayr 1063
 
1064
 
1536 hidnplayr 1065
  .ack_dup:
1514 hidnplayr 1066
 
1536 hidnplayr 1067
	;;;;
1533 hidnplayr 1068
 
1514 hidnplayr 1069
;-------------------------------------------------
1519 hidnplayr 1070
; If the congestion window was inflated to account
1514 hidnplayr 1071
; for the other side's cached packets, retrace it
1072
 
1073
	;;;; 888 -  902
1074
 
1075
 
1076
;------------------------------------------
1077
; RTT measurements and retransmission timer
1078
 
1079
	;;;;; 903 - 926
1080
 
1519 hidnplayr 1081
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0
1514 hidnplayr 1082
 
1519 hidnplayr 1083
	mov	eax, [ebx + TCP_SOCKET.SND_MAX]
1084
	cmp	eax, [edx + TCP_segment.AckNumber]
1085
	je	.all_outstanding
1086
	mov	[ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value
1087
  .all_outstanding:
1088
 
1514 hidnplayr 1089
;-------------------------------------------
1090
; Open congestion window in response to ACKs
1091
 
1092
	;;;;
1093
 
1094
 
1095
;------------------------------------------
1096
; Remove acknowledged data from send buffer
1097
 
1536 hidnplayr 1098
	pusha
1099
; Delete acknowledged bytes from send buffer
1100
	mov	ecx, [edx + TCP_segment.AckNumber]
1101
	sub	ecx, [ebx + TCP_SOCKET.SND_UNA]
1533 hidnplayr 1102
	lea	eax, [ebx + STREAM_SOCKET.snd]
1536 hidnplayr 1103
	call	SOCKET_ring_free
1104
	popa
1514 hidnplayr 1105
 
1536 hidnplayr 1106
 
1107
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  code missing (943?)
1108
 
1542 hidnplayr 1109
 
1110
 
1536 hidnplayr 1111
	mov	eax, [edx + TCP_segment.AckNumber]
1112
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
1113
 
1114
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
1115
	jl	@f
1116
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1117
       @@:
1118
 
1119
 
1514 hidnplayr 1120
;---------------------------------------
1121
; Wake up process waiting on send buffer
1122
 
1529 hidnplayr 1123
	mov	eax, ebx
1124
	call	SOCKET_notify_owner
1514 hidnplayr 1125
 
1126
	mov	eax, [ebx + TCP_SOCKET.t_state]
1127
	shl	eax, 2
1128
	jmp	dword [eax + .ACK_sw_list]
1129
 
1130
  .ACK_sw_list:
1131
	dd	.step6		;TCB_CLOSED
1132
	dd	.step6		;TCB_LISTEN
1133
	dd	.step6		;TCB_SYN_SENT
1134
	dd	.step6		;TCB_SYN_RECEIVED
1135
	dd	.step6		;TCB_ESTABLISHED
1136
	dd	.step6		;TCB_CLOSE_WAIT
1137
	dd	._963		;TCB_FIN_WAIT_1
1138
	dd	._958		;TCB_CLOSING
1139
	dd	._999		;TCB_LAST_ACK
1140
	dd	.step6		;TCB_FIN_WAIT_2
1141
	dd	._1010		;TCB_TIMED_WAIT
1142
 
1143
 
1536 hidnplayr 1144
  ._963:
1514 hidnplayr 1145
 
1146
 
1147
	jmp	.step6
1148
 
1149
 
1536 hidnplayr 1150
  ._958:
1514 hidnplayr 1151
 
1152
	jmp	.step6
1153
 
1536 hidnplayr 1154
  ._999:
1514 hidnplayr 1155
 
1156
	jmp	.step6
1157
 
1158
 
1536 hidnplayr 1159
  ._1010:
1514 hidnplayr 1160
 
1161
	jmp	.step6
1162
 
1163
 
1536 hidnplayr 1164
  .step6:
1514 hidnplayr 1165
 
1166
	DEBUGF	1,"step 6\n"
1167
 
1536 hidnplayr 1168
;----------------------------------------------
1169
; check if we need to update window information
1514 hidnplayr 1170
 
1171
	test	[edx + TCP_segment.Flags], TH_ACK
1172
	jz	.no_window_update
1173
 
1174
	mov	eax, [ebx + TCP_SOCKET.SND_WL1]
1175
	cmp	eax, [edx + TCP_segment.SequenceNumber]
1536 hidnplayr 1176
	jl	.update_window
1177
	jg	@f
1514 hidnplayr 1178
 
1179
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
1180
	cmp	eax, [edx + TCP_segment.AckNumber]
1536 hidnplayr 1181
	jl	.update_window
1182
	jg	.no_window_update
1183
       @@:
1514 hidnplayr 1184
 
1536 hidnplayr 1185
	mov	eax, [ebx + TCP_SOCKET.SND_WL2] 	  ;;;;
1186
	cmp	eax, [edx + TCP_segment.AckNumber]
1187
	jne	.no_window_update
1188
 
1189
	movzx	eax, [edx + TCP_segment.Window]
1514 hidnplayr 1190
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
1536 hidnplayr 1191
	jle	.no_window_update
1514 hidnplayr 1192
 
1536 hidnplayr 1193
  .update_window:
1514 hidnplayr 1194
 
1536 hidnplayr 1195
	DEBUGF	1,"Updating window\n"
1514 hidnplayr 1196
 
1536 hidnplayr 1197
;----------------------------------
1198
; Keep track of pure window updates
1199
 
1200
;        test    ecx, ecx
1201
;        jz      @f
1202
;
1203
;        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1204
;        cmp     eax, [edx + TCP_segment.AckNumber]
1205
;        jne     @f
1206
;
1207
;        ;; mov eax, tiwin
1208
;        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1209
;        jle     @f
1210
;
1211
;        ;;; update stats
1212
;
1213
;       @@:
1214
 
1215
	movzx	eax, [edx + TCP_segment.Window] 	;;; FIXME: use pre-calculated value instead!
1514 hidnplayr 1216
	cmp	eax, [ebx + TCP_SOCKET.max_sndwnd]
1217
	jle	@f
1218
	mov	[ebx + TCP_SOCKET.max_sndwnd], eax
1219
       @@:
1220
	mov	[ebx + TCP_SOCKET.SND_WND], eax
1221
 
1536 hidnplayr 1222
	push	[edx + TCP_segment.SequenceNumber]
1223
	pop	[ebx + TCP_SOCKET.SND_WL1]
1514 hidnplayr 1224
 
1536 hidnplayr 1225
	push	[edx + TCP_segment.AckNumber]
1226
	pop	[ebx + TCP_SOCKET.SND_WL2]
1514 hidnplayr 1227
 
1228
	;;; needoutput = 1
1229
 
1230
  .no_window_update:
1231
 
1232
;-----------------
1233
; process URG flag
1234
 
1235
	test	[edx + TCP_segment.Flags], TH_URG
1236
	jz	.not_urgent
1237
 
1238
	cmp	[edx + TCP_segment.UrgentPointer], 0
1239
	jz	.not_urgent
1240
 
1241
	cmp	[ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT
1242
	je	.not_urgent
1243
 
1244
; Ignore bogus urgent offsets
1245
 
1246
	;;; 1040-1050
1247
 
1248
	movzx	eax, [edx + TCP_segment.UrgentPointer]
1533 hidnplayr 1249
	add	eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size]
1514 hidnplayr 1250
	cmp	eax, SOCKET_MAXDATA
1251
	jle	.not_urgent
1252
 
1253
	mov	[edx + TCP_segment.UrgentPointer], 0
1254
	and	[edx + TCP_segment.Flags], not (TH_URG)
1255
	jmp	.do_data
1256
 
1257
  .not_urgent:
1258
 
1259
;--------------------------------------
1260
; processing of received urgent pointer
1261
 
1529 hidnplayr 1262
	;;; TODO (1051-1093)
1514 hidnplayr 1263
 
1529 hidnplayr 1264
;--------------------------------
1265
; process the data in the segment
1514 hidnplayr 1266
 
1529 hidnplayr 1267
  .do_data:
1514 hidnplayr 1268
 
1534 hidnplayr 1269
	DEBUGF	1,"TCP: do data (%u)\n", ecx
1514 hidnplayr 1270
 
1271
	test	[edx + TCP_segment.Flags], TH_FIN
1529 hidnplayr 1272
	jnz	.process_fin
1514 hidnplayr 1273
 
1533 hidnplayr 1274
	cmp	[ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1
1514 hidnplayr 1275
	jge	.dont_do_data
1276
 
1533 hidnplayr 1277
	test	ecx, ecx
1278
	jz	.final_processing
1279
 
1514 hidnplayr 1280
	DEBUGF	1,"Processing data in segment\n"
1281
 
1533 hidnplayr 1282
;; TODO: check if data is in sequence !
1514 hidnplayr 1283
 
1533 hidnplayr 1284
	movzx	eax, [edx + TCP_segment.DataOffset]		;;; todo: remember this in.. edi ?
1285
	and	eax, 0xf0
1286
	shr	al, 2
1287
 
1288
	lea	esi, [edx + eax]
1289
 
1290
	or	[ebx + TCP_SOCKET.t_flags], TF_DELACK
1291
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx 	 ;;; right ?
1292
 
1293
	lea	eax, [ebx + STREAM_SOCKET.rcv]
1294
	call	SOCKET_ring_write
1295
 
1296
	mov	eax, ebx
1297
	call	SOCKET_notify_owner
1298
 
1514 hidnplayr 1299
	jmp	.final_processing
1300
 
1301
 
1302
  .dont_do_data:
1303
 
1304
;---------------
1305
; FIN processing
1306
 
1307
  .process_fin:
1308
 
1309
	DEBUGF	1,"Processing FIN\n"
1310
 
1311
	mov	eax, [ebx + TCP_SOCKET.t_state]
1312
	shl	eax, 2
1313
	jmp	dword [eax + .FIN_sw_list]
1314
 
1315
  .FIN_sw_list:
1316
	dd	.no_fin 	;TCB_CLOSED
1317
	dd	.no_fin 	;TCB_LISTEN
1318
	dd	.no_fin 	;TCB_SYN_SENT
1533 hidnplayr 1319
	dd	.fin_syn_est	;TCB_SYN_RECEIVED
1320
	dd	.fin_syn_est	;TCB_ESTABLISHED
1514 hidnplayr 1321
	dd	.no_fin 	;TCB_CLOSE_WAIT
1533 hidnplayr 1322
	dd	.fin_wait1	;TCB_FIN_WAIT_1
1514 hidnplayr 1323
	dd	.no_fin 	;TCB_CLOSING
1324
	dd	.no_fin 	;TCB_LAST_ACK
1533 hidnplayr 1325
	dd	.fin_wait2	;TCB_FIN_WAIT_2
1326
	dd	.fin_timed	;TCB_TIMED_WAIT
1514 hidnplayr 1327
 
1328
 
1329
 
1533 hidnplayr 1330
  .fin_syn_est:
1514 hidnplayr 1331
 
1533 hidnplayr 1332
	jmp	.final_processing
1514 hidnplayr 1333
 
1533 hidnplayr 1334
  .fin_wait1:
1514 hidnplayr 1335
 
1533 hidnplayr 1336
	jmp	.final_processing
1514 hidnplayr 1337
 
1533 hidnplayr 1338
  .fin_wait2:
1514 hidnplayr 1339
 
1533 hidnplayr 1340
	jmp	.final_processing
1341
 
1342
  .fin_timed:
1343
 
1344
	jmp	.final_processing
1345
 
1514 hidnplayr 1346
  .no_fin:
1347
 
1348
;-----------------
1349
; Final processing
1350
 
1351
  .final_processing:
1352
 
1353
	DEBUGF	1,"Final processing\n"
1354
 
1533 hidnplayr 1355
	mov	[ebx + SOCKET.lock], 0
1356
 
1514 hidnplayr 1357
	;;; if debug enabled, output packet
1358
 
1359
	;test    ;;;needoutput = 1
1360
	;jnz     .outputnow
1361
 
1362
	test	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1529 hidnplayr 1363
	jnz	.ack_now
1514 hidnplayr 1364
 
1529 hidnplayr 1365
	call	kernel_free
1366
	add	esp, 4
1367
	ret
1368
 
1369
  .ack_now:
1370
 
1371
	DEBUGF	1,"ACK now!\n"
1372
 
1373
	push	ebx
1374
	mov	eax, ebx
1514 hidnplayr 1375
	call	TCP_output
1529 hidnplayr 1376
	pop	ebx
1514 hidnplayr 1377
 
1274 hidnplayr 1378
	call	kernel_free
1529 hidnplayr 1379
	add	esp, 4
1380
	ret
1274 hidnplayr 1381
 
1514 hidnplayr 1382
;------------------------------------------
1383
; Generate an ACK, droping incoming segment
1274 hidnplayr 1384
 
1514 hidnplayr 1385
align 4
1386
.drop_after_ack:
1274 hidnplayr 1387
 
1514 hidnplayr 1388
	DEBUGF	1,"Drop after ACK\n"
1274 hidnplayr 1389
 
1514 hidnplayr 1390
	test	[edx + TCP_segment.Flags], TH_RST
1391
	jnz	.drop
1274 hidnplayr 1392
 
1514 hidnplayr 1393
	and	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1274 hidnplayr 1394
 
1529 hidnplayr 1395
	push	ebx
1396
	mov	eax, ebx
1514 hidnplayr 1397
	call	TCP_output
1529 hidnplayr 1398
	pop	ebx
1318 hidnplayr 1399
 
1514 hidnplayr 1400
	call	kernel_free
1529 hidnplayr 1401
	add	esp, 4
1402
	ret
1274 hidnplayr 1403
 
1514 hidnplayr 1404
 
1405
;-------------------------------------------
1406
; Generate an RST, dropping incoming segment
1407
 
1408
align 4
1409
.drop_with_reset:
1410
 
1411
	DEBUGF	1,"Drop with reset\n"
1412
 
1413
	test	[edx + TCP_segment.Flags], TH_RST
1414
	jnz	.drop
1415
 
1416
	;;; if its a multicast/broadcast, also drop
1417
 
1418
	test	[edx + TCP_segment.Flags], TH_ACK
1419
	jnz	.respond_ack
1420
 
1421
	test	[edx + TCP_segment.Flags], TH_SYN
1422
	jnz	.respond_syn
1423
 
1424
	call	kernel_free
1529 hidnplayr 1425
	add	esp, 4
1426
	ret
1514 hidnplayr 1427
 
1428
  .respond_ack:
1429
 
1533 hidnplayr 1430
	mov	dl, TH_RST
1514 hidnplayr 1431
 
1533 hidnplayr 1432
	push	ebx
1529 hidnplayr 1433
	call	TCP_respond_segment
1533 hidnplayr 1434
	pop	ebx
1514 hidnplayr 1435
 
1436
	jmp	.destroy_new_socket
1437
 
1438
 
1439
  .respond_syn:
1440
 
1533 hidnplayr 1441
	mov	dl, TH_RST + TH_ACK
1514 hidnplayr 1442
 
1533 hidnplayr 1443
	push	ebx
1444
	call	TCP_respond_socket
1445
	pop	ebx
1514 hidnplayr 1446
 
1447
	jmp	.destroy_new_socket
1448
 
1449
;-----
1450
; Drop
1451
 
1452
align 4
1453
.drop:
1454
 
1455
	DEBUGF	1,"Dropping packet\n"
1456
 
1457
	;;;; If debugging options are enabled, output the packet somwhere
1458
 
1459
  .destroy_new_socket:
1460
 
1461
	;;;; kill the newly created socket
1462
 
1463
	call	kernel_free
1529 hidnplayr 1464
	add	esp, 4
1465
	ret
1514 hidnplayr 1466
 
1467
 
1468
 
1469
 
1470
 
1471
 
1472
;---------------------------
1473
;
1474
; TCP_pull_out_of_band
1475
;
1476
; IN:  eax =
1477
;      ebx = socket ptr
1478
;      edx = tcp packet ptr
1479
;
1480
; OUT: /
1481
;
1482
;---------------------------
1483
 
1484
align 4
1485
TCP_pull_out_of_band:
1486
 
1487
	DEBUGF	1,"TCP_pull_out_of_band\n"
1488
 
1489
	;;;; 1282-1305
1490
 
1318 hidnplayr 1491
	ret
1492
 
1493
 
1494
 
1495
;-----------------------------------------------------------------
1496
;
1514 hidnplayr 1497
; TCP_output
1318 hidnplayr 1498
;
1519 hidnplayr 1499
; IN:  eax = socket pointer
1514 hidnplayr 1500
;
1318 hidnplayr 1501
; OUT: /
1502
;
1503
;-----------------------------------------------------------------
1504
align 4
1514 hidnplayr 1505
TCP_output:
1318 hidnplayr 1506
 
1514 hidnplayr 1507
	DEBUGF 1,"TCP_output, socket: %x\n", eax
1318 hidnplayr 1508
 
1514 hidnplayr 1509
; We'll detect the length of the data to be transmitted, and flags to be used
1510
; If there is some data, or any critical controls to send (SYN / RST), then transmit
1511
; Otherwise, investigate further
1318 hidnplayr 1512
 
1514 hidnplayr 1513
	mov	ebx, [eax + TCP_SOCKET.SND_MAX]
1514
	cmp	ebx, [eax + TCP_SOCKET.SND_UNA]
1515
	jne	.not_idle
1318 hidnplayr 1516
 
1514 hidnplayr 1517
	mov	ebx, [eax + TCP_SOCKET.t_idle]
1518
	cmp	ebx, [eax + TCP_SOCKET.t_rxtcur]
1519
	jle	.not_idle
1318 hidnplayr 1520
 
1514 hidnplayr 1521
; We have been idle for a while and no ACKS are expected to clock out any data we send..
1522
; Slow start to get ack "clock" running again.
1318 hidnplayr 1523
 
1514 hidnplayr 1524
	mov	ebx, [eax + TCP_SOCKET.t_maxseg]
1525
	mov	[eax + TCP_SOCKET.SND_CWND], ebx
1318 hidnplayr 1526
 
1514 hidnplayr 1527
  .not_idle:
1528
  .again:
1529
	mov	ebx, [eax + TCP_SOCKET.SND_NXT] 	; calculate offset
1530
	sub	ebx, [eax + TCP_SOCKET.SND_UNA] 	;
1318 hidnplayr 1531
 
1514 hidnplayr 1532
	mov	ecx, [eax + TCP_SOCKET.SND_WND] 	; determine window
1533
	cmp	ecx, [eax + TCP_SOCKET.SND_CWND]	;
1534
	jl	@f					;
1535
	mov	ecx, [eax + TCP_SOCKET.SND_CWND]	;
1536
       @@:						;
1318 hidnplayr 1537
 
1529 hidnplayr 1538
	call	TCP_outflags	; in dl
1318 hidnplayr 1539
 
1514 hidnplayr 1540
; If in persist timeout with window of 0, send 1 byte.
1541
; Otherwise, if window is small but nonzero, and timer expired,
1542
; we will send what we can and go to transmit state
1318 hidnplayr 1543
 
1514 hidnplayr 1544
	test	[eax + TCP_SOCKET.t_force], -1
1545
	jz	.no_persist_timeout
1318 hidnplayr 1546
 
1514 hidnplayr 1547
	test	ecx, ecx
1548
	jnz	.no_zero_window
1255 hidnplayr 1549
 
1533 hidnplayr 1550
	cmp	ebx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
1514 hidnplayr 1551
	jge	@f
1255 hidnplayr 1552
 
1514 hidnplayr 1553
	and	dl, not (TH_FIN)	  ; clear the FIN flag    ??? how can it be set before?
1255 hidnplayr 1554
 
1514 hidnplayr 1555
       @@:
1556
	inc	ecx
1557
	jmp	.no_persist_timeout
1255 hidnplayr 1558
 
1514 hidnplayr 1559
  .no_zero_window:
1254 hidnplayr 1560
 
1529 hidnplayr 1561
	mov	[eax + TCP_SOCKET.timer_persist], 0	;;;;
1514 hidnplayr 1562
	mov	[eax + TCP_SOCKET.t_rxtshift], 0
1254 hidnplayr 1563
 
1514 hidnplayr 1564
  .no_persist_timeout:
1159 hidnplayr 1565
 
1514 hidnplayr 1566
;;;106
1159 hidnplayr 1567
 
1533 hidnplayr 1568
	mov	esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
1514 hidnplayr 1569
	cmp	esi, ecx
1570
	jl	@f
1571
	mov	esi, ecx
1572
       @@:
1573
	sub	esi, ebx
1254 hidnplayr 1574
 
1514 hidnplayr 1575
	cmp	esi, -1
1576
	jne	.not_minus_one
1159 hidnplayr 1577
 
1514 hidnplayr 1578
; If FIN has been set, but not ACKed, and we havent been called to retransmit,
1579
; len (esi) will be -1
1580
; Otherwise, window shrank after we sent into it.
1581
; If window shrank to 0, cancel pending retransmit and pull SND_NXT back to (closed) window
1582
; We will enter persist state below.
1583
; If window didn't close completely, just wait for an ACK
1159 hidnplayr 1584
 
1514 hidnplayr 1585
	xor	esi, esi
1159 hidnplayr 1586
 
1514 hidnplayr 1587
	test	ecx, ecx
1588
	jnz	@f
1159 hidnplayr 1589
 
1529 hidnplayr 1590
	mov	[eax + TCP_SOCKET.timer_retransmission], 0   ; cancel retransmit
1274 hidnplayr 1591
 
1514 hidnplayr 1592
	push	[eax + TCP_SOCKET.SND_UNA]
1593
	pop	[eax + TCP_SOCKET.SND_NXT]
1594
       @@:
1254 hidnplayr 1595
 
1514 hidnplayr 1596
  .not_minus_one:
1254 hidnplayr 1597
 
1514 hidnplayr 1598
;;; 124
1159 hidnplayr 1599
 
1514 hidnplayr 1600
	cmp	esi, [eax + TCP_SOCKET.t_maxseg]
1601
	jle	@f
1274 hidnplayr 1602
 
1514 hidnplayr 1603
	mov	esi, [eax + TCP_SOCKET.t_maxseg]
1604
	;sendalot = 1
1274 hidnplayr 1605
 
1514 hidnplayr 1606
       @@:
1274 hidnplayr 1607
 
1514 hidnplayr 1608
;;; 128
1274 hidnplayr 1609
 
1514 hidnplayr 1610
	mov	edi, [eax + TCP_SOCKET.SND_NXT]
1611
	add	edi, esi	; len
1612
	sub	edi, [eax + TCP_SOCKET.SND_UNA]
1533 hidnplayr 1613
	add	edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
1514 hidnplayr 1614
	cmp	edi, 0
1615
	jle	@f
1274 hidnplayr 1616
 
1514 hidnplayr 1617
	and	dl, not (TH_FIN)	  ; clear the FIN flag
1159 hidnplayr 1618
 
1514 hidnplayr 1619
       @@:
1159 hidnplayr 1620
 
1621
 
1529 hidnplayr 1622
; set ecx to space available in receive buffer
1623
; From now on, ecx will be the window we advertise to the other end
1159 hidnplayr 1624
 
1529 hidnplayr 1625
	mov	ecx, SOCKET_MAXDATA
1533 hidnplayr 1626
	sub	ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
1159 hidnplayr 1627
 
1514 hidnplayr 1628
;------------------------------
1629
; Sender silly window avoidance
1159 hidnplayr 1630
 
1529 hidnplayr 1631
	cmp	ecx, [eax + TCP_SOCKET.t_maxseg]
1514 hidnplayr 1632
	je	.send
1274 hidnplayr 1633
 
1514 hidnplayr 1634
;;; TODO: 144-145
1274 hidnplayr 1635
 
1514 hidnplayr 1636
	test	[eax + TCP_SOCKET.t_force], -1
1637
	jnz	.send
1274 hidnplayr 1638
 
1529 hidnplayr 1639
	mov	ebx, [eax + TCP_SOCKET.max_sndwnd]
1640
	shr	ebx, 1
1641
	cmp	ecx, ebx
1642
	jge	.send
1274 hidnplayr 1643
 
1529 hidnplayr 1644
	mov	ebx, [eax + TCP_SOCKET.SND_NXT]
1645
	cmp	ebx, [eax + TCP_SOCKET.SND_MAX]
1646
	jl	.send
1254 hidnplayr 1647
 
1514 hidnplayr 1648
;----------------------------------------
1649
; Check if a window update should be sent
1159 hidnplayr 1650
 
1529 hidnplayr 1651
	test	ecx, ecx	; window
1652
	jz	.no_window
1159 hidnplayr 1653
 
1514 hidnplayr 1654
;;; TODO 154-172
1159 hidnplayr 1655
 
1514 hidnplayr 1656
  .no_window:
1159 hidnplayr 1657
 
1514 hidnplayr 1658
;--------------------------
1659
; Should a segment be sent?
1159 hidnplayr 1660
 
1534 hidnplayr 1661
	test	[eax + TCP_SOCKET.t_flags], TF_ACKNOW
1514 hidnplayr 1662
	jnz	.send
1159 hidnplayr 1663
 
1514 hidnplayr 1664
	test	dl, TH_SYN + TH_RST
1665
	jnz	.send
1159 hidnplayr 1666
 
1534 hidnplayr 1667
	mov	ebx, [eax + TCP_SOCKET.SND_UP]
1668
	cmp	ebx, [eax + TCP_SOCKET.SND_UNA]
1514 hidnplayr 1669
	jg	.send
1249 hidnplayr 1670
 
1514 hidnplayr 1671
	test	dl, TH_FIN
1672
	jz	.enter_persist
1318 hidnplayr 1673
 
1534 hidnplayr 1674
	test	[eax + TCP_SOCKET.t_flags], TF_SENTFIN
1514 hidnplayr 1675
	jnz	.send
1254 hidnplayr 1676
 
1534 hidnplayr 1677
	mov	ebx, [eax + TCP_SOCKET.SND_NXT]
1678
	cmp	ebx, [eax + TCP_SOCKET.SND_UNA]
1514 hidnplayr 1679
	je	.send
1254 hidnplayr 1680
 
1514 hidnplayr 1681
;--------------------
1682
; Enter persist state
1318 hidnplayr 1683
 
1514 hidnplayr 1684
  .enter_persist:
1318 hidnplayr 1685
 
1519 hidnplayr 1686
	DEBUGF	1,"Entering persist state\n"
1318 hidnplayr 1687
 
1514 hidnplayr 1688
;--------------------------------------
1689
; No reason to send a segment, just ret
1318 hidnplayr 1690
 
1514 hidnplayr 1691
	DEBUGF	1,"No reason to send a segment\n"
1318 hidnplayr 1692
 
1514 hidnplayr 1693
	ret
1318 hidnplayr 1694
 
1695
 
1514 hidnplayr 1696
;-----------------------------------------------
1697
;
1698
; Send a segment
1699
;
1529 hidnplayr 1700
; eax = socket pointer
1514 hidnplayr 1701
;  dl = flags
1702
;
1703
;-----------------------------------------------
1318 hidnplayr 1704
 
1529 hidnplayr 1705
  .send:
1318 hidnplayr 1706
 
1514 hidnplayr 1707
	DEBUGF	1,"Preparing to send a segment\n"
1318 hidnplayr 1708
 
1529 hidnplayr 1709
	mov	edi, TCP_segment.Data	; edi will contain headersize
1318 hidnplayr 1710
 
1529 hidnplayr 1711
	sub	esp, 8			; create some space on stack
1712
	push	eax			; save this too..
1713
 
1514 hidnplayr 1714
;------------------------------------
1715
; Send options with first SYN segment
1318 hidnplayr 1716
 
1514 hidnplayr 1717
	test	dl, TH_SYN
1718
	jz	.no_options
1318 hidnplayr 1719
 
1529 hidnplayr 1720
	push	[eax + TCP_SOCKET.ISS]
1721
	pop	[eax + TCP_SOCKET.SND_NXT]
1318 hidnplayr 1722
 
1529 hidnplayr 1723
	test	[eax + TCP_SOCKET.t_flags], TF_NOOPT
1514 hidnplayr 1724
	jnz	.no_options
1318 hidnplayr 1725
 
1529 hidnplayr 1726
	mov	ecx, 1460
1727
	or	ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
1728
	bswap	ecx
1729
	push	ecx
1730
	add	di, 4
1514 hidnplayr 1731
 
1529 hidnplayr 1732
	test	[eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
1514 hidnplayr 1733
	jz	.no_syn
1734
 
1735
	test	dl, TH_ACK
1736
	jnz	.scale_opt
1737
 
1529 hidnplayr 1738
	test	[eax + TCP_SOCKET.t_flags], TF_RCVD_SCALE
1514 hidnplayr 1739
	jz	.no_syn
1740
 
1741
  .scale_opt:
1529 hidnplayr 1742
	movzx	ecx, byte [eax + TCP_SOCKET.request_r_scale]
1743
	or	ecx, TCP_OPT_WINDOW shl 24 + 4 shl 16 + TCP_OPT_NOP shl 8
1744
	bswap	ecx
1745
	pushd	ecx
1514 hidnplayr 1746
	add	di, 4
1159 hidnplayr 1747
 
1514 hidnplayr 1748
  .no_syn:
1159 hidnplayr 1749
 
1514 hidnplayr 1750
;------------------------------------
1751
; Make the timestamp option if needed
1159 hidnplayr 1752
 
1529 hidnplayr 1753
	test	[eax + TCP_SOCKET.t_flags], TF_REQ_TSTMP
1514 hidnplayr 1754
	jz	.no_timestamp
1159 hidnplayr 1755
 
1514 hidnplayr 1756
	test	dl, TH_RST
1757
	jnz	.no_timestamp
1758
 
1759
	test	dl, TH_ACK
1760
	jz	.timestamp
1761
 
1529 hidnplayr 1762
	test	[eax + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
1514 hidnplayr 1763
	jz	.no_timestamp
1764
 
1765
  .timestamp:
1529 hidnplayr 1766
	mov	esi, [timer_ticks]
1767
	bswap	esi
1768
	push	esi
1514 hidnplayr 1769
	pushw	0
1529 hidnplayr 1770
	pushd	TCP_OPT_TIMESTAMP + 10 shl 8 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24
1514 hidnplayr 1771
	add	di, 10
1772
 
1773
  .no_timestamp:
1774
	;; TODO: check if we dont exceed the max segment size
1775
 
1776
  .no_options:
1529 hidnplayr 1777
	; eax = socket ptr
1778
	; edx = flags
1779
	; ecx = data size
1780
	; edi = header size
1781
	; esi = snd ring buff ptr
1514 hidnplayr 1782
 
1533 hidnplayr 1783
	mov	ecx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
1784
	cmp	ecx, [eax + TCP_SOCKET.t_maxseg]			;;; right?
1785
	jle	@f
1786
	mov	ecx, [eax + TCP_SOCKET.t_maxseg]
1787
       @@:
1514 hidnplayr 1788
	add	ecx, edi	; total TCP segment size
1789
 
1529 hidnplayr 1790
; Start by pushing all TCP header values in reverse order on stack
1791
; (essentially, creating the tcp header!)
1514 hidnplayr 1792
 
1529 hidnplayr 1793
	pushw	0	;        .UrgentPointer          dw ?
1794
	pushw	0	;        .Checksum               dw ?
1795
	pushw	0x00a0	;        .Window                 dw ?    ;;;;;;;
1796
	shl	edi, 2	;        .DataOffset             db ?  only 4 left-most bits
1797
	shl	dx, 8
1798
	or	dx, di	;        .Flags                  db ?
1799
	pushw	dx
1800
	shr	edi, 2	;        .DataOffset             db ? ;;;;
1514 hidnplayr 1801
 
1529 hidnplayr 1802
	push	[eax + TCP_SOCKET.RCV_NXT]	;        .AckNumber              dd ?
1803
	ntohld	[esp]
1159 hidnplayr 1804
 
1529 hidnplayr 1805
	push	[eax + TCP_SOCKET.SND_NXT]	;        .SequenceNumber         dd ?
1806
	ntohld	[esp]
1159 hidnplayr 1807
 
1529 hidnplayr 1808
	push	[eax + TCP_SOCKET.RemotePort]	;        .DestinationPort        dw ?
1809
	ntohlw	[esp]
1249 hidnplayr 1810
 
1529 hidnplayr 1811
	push	[eax + TCP_SOCKET.LocalPort]	;        .SourcePort             dw ?
1812
	ntohlw	[esp]
1274 hidnplayr 1813
 
1533 hidnplayr 1814
	push	edi		; header size
1274 hidnplayr 1815
 
1529 hidnplayr 1816
; Create the IP packet
1817
	mov	ebx, [eax + IP_SOCKET.LocalIP]	; source ip
1818
	mov	eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
1819
	mov	di, IP_PROTO_TCP shl 8 + 128
1820
	call	IPv4_output
1821
	jz	.fail
1274 hidnplayr 1822
 
1529 hidnplayr 1823
;-----------------------------------------
1824
; Move TCP header from stack to TCP packet
1274 hidnplayr 1825
 
1533 hidnplayr 1826
	push	ecx
1827
	mov	ecx, [esp+4]
1828
	lea	esi, [esp+4+4]
1529 hidnplayr 1829
	shr	ecx, 2
1830
	rep	movsd
1533 hidnplayr 1831
	pop	ecx		; full TCP packet size
1274 hidnplayr 1832
 
1533 hidnplayr 1833
	pop	esi		; headersize
1834
	add	esp, esi
1254 hidnplayr 1835
 
1533 hidnplayr 1836
	mov	[esp + 4], eax		; packet ptr
1530 hidnplayr 1837
	mov	[esp + 4+4], edx	; packet size
1254 hidnplayr 1838
 
1533 hidnplayr 1839
	mov	edx, edi		; begin of data
1840
	sub	edx, esi		; begin of packet (edi = begin of data)
1841
	push	ecx
1842
	sub	ecx, esi		; data size
1159 hidnplayr 1843
 
1514 hidnplayr 1844
;--------------
1845
; Copy the data
1159 hidnplayr 1846
 
1529 hidnplayr 1847
; eax = ptr to ring struct
1848
; ecx = buffer size
1849
; edi = ptr to buffer
1249 hidnplayr 1850
 
1536 hidnplayr 1851
;        test    ecx, ecx
1533 hidnplayr 1852
	mov	eax, [esp+4]		  ; socket ptr
1536 hidnplayr 1853
	add	[eax + TCP_SOCKET.SND_NXT], ecx
1854
	add	eax, STREAM_SOCKET.snd
1533 hidnplayr 1855
	push	edx
1529 hidnplayr 1856
	call	SOCKET_ring_read
1536 hidnplayr 1857
	pop	esi
1858
	pop	ecx
1529 hidnplayr 1859
	pop	eax
1254 hidnplayr 1860
 
1533 hidnplayr 1861
	test	[esi + TCP_segment.Flags], TH_SYN + TH_FIN
1862
	jz	@f
1863
	inc	[eax + TCP_SOCKET.SND_NXT]
1864
	;;; TODO: update sentfin flag
1865
       @@:
1254 hidnplayr 1866
 
1533 hidnplayr 1867
	mov	edx, [eax + TCP_SOCKET.SND_NXT]
1868
	cmp	edx, [eax + TCP_SOCKET.SND_MAX]
1869
	jle	@f
1870
	mov	[eax + TCP_SOCKET.SND_MAX], edx
1871
 
1872
	;;;; TODO: time transmission (420)
1873
       @@:
1874
 
1875
	;;; TODO: set retransmission timer
1876
 
1877
;--------------------
1878
; Create the checksum
1879
 
1529 hidnplayr 1880
	DEBUGF	1,"checksum: ptr=%x size=%u\n", esi, ecx
1159 hidnplayr 1881
 
1529 hidnplayr 1882
	TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
1883
	mov	[esi+TCP_segment.Checksum], dx
1884
 
1514 hidnplayr 1885
;----------------
1886
; Send the packet
1159 hidnplayr 1887
 
1529 hidnplayr 1888
	DEBUGF	1,"Sending TCP Packet to device %x\n", ebx
1889
	call	[ebx + NET_DEVICE.transmit]
1890
	ret
1159 hidnplayr 1891
 
1514 hidnplayr 1892
 
1529 hidnplayr 1893
  .fail:
1894
	pop	ecx
1895
	add	esp, ecx
1536 hidnplayr 1896
	add	esp, 4+8
1529 hidnplayr 1897
	DEBUGF 1,"TCP_output: failed\n"
1159 hidnplayr 1898
	ret
1899
 
1529 hidnplayr 1900
 
1901
 
1514 hidnplayr 1902
;-------------------------
1903
;
1904
; TCP_outflags
1905
;
1906
;  IN:  eax = socket ptr
1907
;
1908
;  OUT: edx = flags
1909
;
1910
;-------------------------
1249 hidnplayr 1911
align 4
1514 hidnplayr 1912
TCP_outflags:
1254 hidnplayr 1913
 
1514 hidnplayr 1914
	mov	edx, [eax + TCP_SOCKET.t_state]
1915
	movzx	edx, byte [edx + .flaglist]
1254 hidnplayr 1916
 
1514 hidnplayr 1917
	DEBUGF	1,"TCP_outflags, socket: %x, flags: %x\n", eax, dl
1918
 
1159 hidnplayr 1919
	ret
1920
 
1514 hidnplayr 1921
  .flaglist:
1159 hidnplayr 1922
 
1514 hidnplayr 1923
	db	TH_RST + TH_ACK 	; TCB_CLOSED
1924
	db	0			; TCB_LISTEN
1925
	db	TH_SYN			; TCB_SYN_SENT
1926
	db	TH_SYN + TH_ACK 	; TCB_SYN_RECEIVED
1927
	db		 TH_ACK 	; TCB_ESTABLISHED
1928
	db		 TH_ACK 	; TCB_CLOSE_WAIT
1929
	db	TH_SYN + TH_ACK 	; TCB_FIN_WAIT_1
1930
	db	TH_SYN + TH_ACK 	; TCB_CLOSING
1931
	db	TH_SYN + TH_ACK 	; TCB_LAST_ACK
1932
	db		 TH_ACK 	; TCB_FIN_WAIT_2
1933
	db		 TH_ACK 	; TCB_TIMED_WAIT
1249 hidnplayr 1934
 
1514 hidnplayr 1935
 
1529 hidnplayr 1936
 
1937
 
1514 hidnplayr 1938
;-------------------------
1939
;
1940
; TCP_drop
1941
;
1942
;  IN:  eax = socket ptr
1943
;
1944
;  OUT: /
1945
;
1946
;-------------------------
1249 hidnplayr 1947
align 4
1514 hidnplayr 1948
TCP_drop:
1254 hidnplayr 1949
 
1514 hidnplayr 1950
	DEBUGF	1,"TCP_drop\n"
1254 hidnplayr 1951
 
1514 hidnplayr 1952
;        cmp     [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
1953
;        jl      .no_syn_received
1159 hidnplayr 1954
 
1514 hidnplayr 1955
	mov	[eax + TCP_SOCKET.t_state], TCB_CLOSED
1159 hidnplayr 1956
 
1514 hidnplayr 1957
	call	TCP_output
1254 hidnplayr 1958
 
1514 hidnplayr 1959
;  .no_syn_received:
1960
 
1159 hidnplayr 1961
	ret
1962
 
1963
 
1254 hidnplayr 1964
 
1965
 
1159 hidnplayr 1966
 
1514 hidnplayr 1967
;---------------------------------------
1968
;
1519 hidnplayr 1969
; The easy way to send an ACK/RST/keepalive segment
1514 hidnplayr 1970
;
1529 hidnplayr 1971
; TCP_respond_socket:
1972
;
1973
;  IN:  ebx = socket ptr
1519 hidnplayr 1974
;        cl = flags
1514 hidnplayr 1975
;
1529 hidnplayr 1976
;--------------------------------------
1514 hidnplayr 1977
align 4
1529 hidnplayr 1978
TCP_respond_socket:
1254 hidnplayr 1979
 
1529 hidnplayr 1980
	DEBUGF	1,"TCP_respond_socket\n"
1159 hidnplayr 1981
 
1519 hidnplayr 1982
;---------------------
1983
; Create the IP packet
1984
 
1529 hidnplayr 1985
	push	cx ebx
1986
	mov	eax, [ebx + IP_SOCKET.RemoteIP]
1987
	mov	ebx, [ebx + IP_SOCKET.LocalIP]
1519 hidnplayr 1988
	mov	ecx, TCP_segment.Data
1529 hidnplayr 1989
	mov	di , IP_PROTO_TCP shl 8 + 128
1990
	call	IPv4_output
1519 hidnplayr 1991
	test	edi, edi
1992
	jz	.error
1529 hidnplayr 1993
	pop	esi cx
1994
	push	edx eax
1519 hidnplayr 1995
 
1529 hidnplayr 1996
;-----------------------------------------------
1997
; Fill in the TCP header by using the socket ptr
1519 hidnplayr 1998
 
1529 hidnplayr 1999
	mov	ax, [esi + TCP_SOCKET.LocalPort]
2000
	rol	ax, 8
2001
	stosw
2002
	mov	ax, [esi + TCP_SOCKET.RemotePort]
2003
	rol	ax, 8
2004
	stosw
2005
	mov	eax, [esi + TCP_SOCKET.SND_NXT]
2006
	bswap	eax
2007
	stosd
2008
	mov	eax, [esi + TCP_SOCKET.RCV_NXT]
2009
	bswap	eax
2010
	stosd
2011
	mov	al, 0x50	; Dataoffset: 20 bytes
2012
	stosb
2013
	mov	al, cl
2014
	stosb
2015
	mov	ax, [esi + TCP_SOCKET.RCV_WND]
2016
	rol	ax, 8
2017
	stosw			; window
2018
	xor	eax, eax
2019
	stosd			; checksum + urgentpointer
1519 hidnplayr 2020
 
2021
;---------------------
2022
; Fill in the checksum
2023
 
2024
  .checksum:
1529 hidnplayr 2025
	sub	edi, TCP_segment.Data
2026
	mov	ecx, TCP_segment.Data
2027
	xchg	esi, edi
2028
	TCP_checksum (edi + IP_SOCKET.LocalIP), (esi + IP_SOCKET.RemoteIP)
2029
	mov	[esi+TCP_segment.Checksum], dx
1519 hidnplayr 2030
 
2031
;--------------------
2032
; And send the segment
2033
 
2034
	call	[ebx + NET_DEVICE.transmit]
1159 hidnplayr 2035
	ret
2036
 
1519 hidnplayr 2037
  .error:
1529 hidnplayr 2038
	DEBUGF	1,"TCP_respond failed\n"
2039
	add	esp, 2+4
1159 hidnplayr 2040
 
1519 hidnplayr 2041
	ret
1514 hidnplayr 2042
 
1529 hidnplayr 2043
 
2044
 
2045
;-------------------------
2046
; TCP_respond.segment:
2047
;
2048
;  IN:  edx = segment ptr (a previously received segment)
2049
;        cl = flags
2050
 
2051
align 4
2052
TCP_respond_segment:
2053
 
2054
	DEBUGF	1,"TCP_respond_segment\n"
2055
 
2056
;---------------------
2057
; Create the IP packet
2058
 
2059
	push	cx edx
2060
	mov	ebx, [edx - 20 + IPv4_Packet.SourceAddress]	 ;;;; and what if ip packet had options?!
2061
	mov	eax, [edx - 20 + IPv4_Packet.DestinationAddress]   ;;;
2062
	mov	ecx, TCP_segment.Data
2063
	mov	di , IP_PROTO_TCP shl 8 + 128
2064
	call	IPv4_output
2065
	jz	.error
1533 hidnplayr 2066
	pop	esi cx
1529 hidnplayr 2067
 
2068
	push	edx eax
2069
 
1519 hidnplayr 2070
;---------------------------------------------------
2071
; Fill in the TCP header by using a received segment
2072
 
2073
	mov	ax, [esi + TCP_segment.DestinationPort]
2074
	rol	ax, 8
2075
	stosw
2076
	mov	ax, [esi + TCP_segment.SourcePort]
2077
	rol	ax, 8
2078
	stosw
2079
	mov	eax, [esi + TCP_segment.AckNumber]
2080
	bswap	eax
2081
	stosd
2082
	xor	eax, eax
2083
	stosd
2084
	mov	al, 0x50	; Dataoffset: 20 bytes
2085
	stosb
2086
	mov	al, cl
2087
	stosb
2088
	mov	ax, 1280
2089
	rol	ax, 8
2090
	stosw			; window
2091
	xor	eax, eax
2092
	stosd			; checksum + urgentpointer
2093
 
1529 hidnplayr 2094
;---------------------
2095
; Fill in the checksum
1519 hidnplayr 2096
 
1529 hidnplayr 2097
  .checksum:
2098
	lea	esi, [edi - TCP_segment.Data]
2099
	mov	ecx, TCP_segment.Data
2100
	TCP_checksum (esi - 20 + IPv4_Packet.DestinationAddress), (esi - 20 + IPv4_Packet.DestinationAddress)
2101
	mov	[esi+TCP_segment.Checksum], dx
1519 hidnplayr 2102
 
1529 hidnplayr 2103
;--------------------
2104
; And send the segment
1519 hidnplayr 2105
 
1529 hidnplayr 2106
	call	[ebx + NET_DEVICE.transmit]
2107
	ret
1519 hidnplayr 2108
 
1529 hidnplayr 2109
  .error:
2110
	DEBUGF	1,"TCP_respond failed\n"
2111
	add	esp, 2+4
1519 hidnplayr 2112
 
2113
	ret
2114
 
2115
 
2116
 
1254 hidnplayr 2117
 
2118
;---------------------------------------------------------------------------
2119
;
2120
; TCP_API
2121
;
2122
; This function is called by system function 75
2123
;
2124
; IN:  subfunction number in bl
2125
;      device number in bh
2126
;      ecx, edx, .. depends on subfunction
2127
;
2128
; OUT:
2129
;
2130
;---------------------------------------------------------------------------
2131
align 4
2132
TCP_API:
2133
 
2134
	movzx	eax, bh
2135
	shl	eax, 2
2136
 
2137
	test	bl, bl
2138
	jz	.packets_tx	; 0
2139
	dec	bl
2140
	jz	.packets_rx	; 1
2141
 
2142
.error:
2143
	mov	eax, -1
2144
	ret
2145
 
2146
.packets_tx:
1514 hidnplayr 2147
	add	eax, TCP_segments_tx
1254 hidnplayr 2148
	mov	eax, [eax]
2149
	ret
2150
 
2151
.packets_rx:
1514 hidnplayr 2152
	add	eax, TCP_segments_rx
1254 hidnplayr 2153
	mov	eax, [eax]
2154
	ret