Subversion Repositories Kolibri OS

Rev

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