Subversion Repositories Kolibri OS

Rev

Rev 1534 | 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: 1536 $
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
 
1514 hidnplayr 138
	cmp	[eax + SOCKET.Type], IP_PROTO_TCP
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
 
1519 hidnplayr 180
	cmp	[eax + SOCKET.Type], IP_PROTO_TCP
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
 
1514 hidnplayr 381
	cmp	[ebx + SOCKET.Type], IP_PROTO_TCP
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
 
1109
	mov	eax, [edx + TCP_segment.AckNumber]
1110
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
1111
 
1112
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
1113
	jl	@f
1114
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1115
       @@:
1116
 
1117
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1118
 
1514 hidnplayr 1119
;---------------------------------------
1120
; Wake up process waiting on send buffer
1121
 
1529 hidnplayr 1122
	mov	eax, ebx
1123
	call	SOCKET_notify_owner
1514 hidnplayr 1124
 
1125
	mov	eax, [ebx + TCP_SOCKET.t_state]
1126
	shl	eax, 2
1127
	jmp	dword [eax + .ACK_sw_list]
1128
 
1129
  .ACK_sw_list:
1130
	dd	.step6		;TCB_CLOSED
1131
	dd	.step6		;TCB_LISTEN
1132
	dd	.step6		;TCB_SYN_SENT
1133
	dd	.step6		;TCB_SYN_RECEIVED
1134
	dd	.step6		;TCB_ESTABLISHED
1135
	dd	.step6		;TCB_CLOSE_WAIT
1136
	dd	._963		;TCB_FIN_WAIT_1
1137
	dd	._958		;TCB_CLOSING
1138
	dd	._999		;TCB_LAST_ACK
1139
	dd	.step6		;TCB_FIN_WAIT_2
1140
	dd	._1010		;TCB_TIMED_WAIT
1141
 
1142
 
1536 hidnplayr 1143
  ._963:
1514 hidnplayr 1144
 
1145
 
1146
	jmp	.step6
1147
 
1148
 
1536 hidnplayr 1149
  ._958:
1514 hidnplayr 1150
 
1151
	jmp	.step6
1152
 
1536 hidnplayr 1153
  ._999:
1514 hidnplayr 1154
 
1155
	jmp	.step6
1156
 
1157
 
1536 hidnplayr 1158
  ._1010:
1514 hidnplayr 1159
 
1160
	jmp	.step6
1161
 
1162
 
1536 hidnplayr 1163
  .step6:
1514 hidnplayr 1164
 
1165
	DEBUGF	1,"step 6\n"
1166
 
1536 hidnplayr 1167
;----------------------------------------------
1168
; check if we need to update window information
1514 hidnplayr 1169
 
1170
	test	[edx + TCP_segment.Flags], TH_ACK
1171
	jz	.no_window_update
1172
 
1173
	mov	eax, [ebx + TCP_SOCKET.SND_WL1]
1174
	cmp	eax, [edx + TCP_segment.SequenceNumber]
1536 hidnplayr 1175
	jl	.update_window
1176
	jg	@f
1514 hidnplayr 1177
 
1178
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
1179
	cmp	eax, [edx + TCP_segment.AckNumber]
1536 hidnplayr 1180
	jl	.update_window
1181
	jg	.no_window_update
1182
       @@:
1514 hidnplayr 1183
 
1536 hidnplayr 1184
	mov	eax, [ebx + TCP_SOCKET.SND_WL2] 	  ;;;;
1185
	cmp	eax, [edx + TCP_segment.AckNumber]
1186
	jne	.no_window_update
1187
 
1188
	movzx	eax, [edx + TCP_segment.Window]
1514 hidnplayr 1189
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
1536 hidnplayr 1190
	jle	.no_window_update
1514 hidnplayr 1191
 
1536 hidnplayr 1192
  .update_window:
1514 hidnplayr 1193
 
1536 hidnplayr 1194
	DEBUGF	1,"Updating window\n"
1514 hidnplayr 1195
 
1536 hidnplayr 1196
;----------------------------------
1197
; Keep track of pure window updates
1198
 
1199
;        test    ecx, ecx
1200
;        jz      @f
1201
;
1202
;        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1203
;        cmp     eax, [edx + TCP_segment.AckNumber]
1204
;        jne     @f
1205
;
1206
;        ;; mov eax, tiwin
1207
;        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1208
;        jle     @f
1209
;
1210
;        ;;; update stats
1211
;
1212
;       @@:
1213
 
1214
	movzx	eax, [edx + TCP_segment.Window] 	;;; FIXME: use pre-calculated value instead!
1514 hidnplayr 1215
	cmp	eax, [ebx + TCP_SOCKET.max_sndwnd]
1216
	jle	@f
1217
	mov	[ebx + TCP_SOCKET.max_sndwnd], eax
1218
       @@:
1219
	mov	[ebx + TCP_SOCKET.SND_WND], eax
1220
 
1536 hidnplayr 1221
	push	[edx + TCP_segment.SequenceNumber]
1222
	pop	[ebx + TCP_SOCKET.SND_WL1]
1514 hidnplayr 1223
 
1536 hidnplayr 1224
	push	[edx + TCP_segment.AckNumber]
1225
	pop	[ebx + TCP_SOCKET.SND_WL2]
1514 hidnplayr 1226
 
1227
	;;; needoutput = 1
1228
 
1229
  .no_window_update:
1230
 
1231
;-----------------
1232
; process URG flag
1233
 
1234
	test	[edx + TCP_segment.Flags], TH_URG
1235
	jz	.not_urgent
1236
 
1237
	cmp	[edx + TCP_segment.UrgentPointer], 0
1238
	jz	.not_urgent
1239
 
1240
	cmp	[ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT
1241
	je	.not_urgent
1242
 
1243
; Ignore bogus urgent offsets
1244
 
1245
	;;; 1040-1050
1246
 
1247
	movzx	eax, [edx + TCP_segment.UrgentPointer]
1533 hidnplayr 1248
	add	eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size]
1514 hidnplayr 1249
	cmp	eax, SOCKET_MAXDATA
1250
	jle	.not_urgent
1251
 
1252
	mov	[edx + TCP_segment.UrgentPointer], 0
1253
	and	[edx + TCP_segment.Flags], not (TH_URG)
1254
	jmp	.do_data
1255
 
1256
  .not_urgent:
1257
 
1258
;--------------------------------------
1259
; processing of received urgent pointer
1260
 
1529 hidnplayr 1261
	;;; TODO (1051-1093)
1514 hidnplayr 1262
 
1529 hidnplayr 1263
;--------------------------------
1264
; process the data in the segment
1514 hidnplayr 1265
 
1529 hidnplayr 1266
  .do_data:
1514 hidnplayr 1267
 
1534 hidnplayr 1268
	DEBUGF	1,"TCP: do data (%u)\n", ecx
1514 hidnplayr 1269
 
1270
	test	[edx + TCP_segment.Flags], TH_FIN
1529 hidnplayr 1271
	jnz	.process_fin
1514 hidnplayr 1272
 
1533 hidnplayr 1273
	cmp	[ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1
1514 hidnplayr 1274
	jge	.dont_do_data
1275
 
1533 hidnplayr 1276
	test	ecx, ecx
1277
	jz	.final_processing
1278
 
1514 hidnplayr 1279
	DEBUGF	1,"Processing data in segment\n"
1280
 
1533 hidnplayr 1281
;; TODO: check if data is in sequence !
1514 hidnplayr 1282
 
1533 hidnplayr 1283
	movzx	eax, [edx + TCP_segment.DataOffset]		;;; todo: remember this in.. edi ?
1284
	and	eax, 0xf0
1285
	shr	al, 2
1286
 
1287
	lea	esi, [edx + eax]
1288
 
1289
	or	[ebx + TCP_SOCKET.t_flags], TF_DELACK
1290
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx 	 ;;; right ?
1291
 
1292
	lea	eax, [ebx + STREAM_SOCKET.rcv]
1293
	call	SOCKET_ring_write
1294
 
1295
	mov	eax, ebx
1296
	call	SOCKET_notify_owner
1297
 
1514 hidnplayr 1298
	jmp	.final_processing
1299
 
1300
 
1301
  .dont_do_data:
1302
 
1303
;---------------
1304
; FIN processing
1305
 
1306
  .process_fin:
1307
 
1308
	DEBUGF	1,"Processing FIN\n"
1309
 
1310
	mov	eax, [ebx + TCP_SOCKET.t_state]
1311
	shl	eax, 2
1312
	jmp	dword [eax + .FIN_sw_list]
1313
 
1314
  .FIN_sw_list:
1315
	dd	.no_fin 	;TCB_CLOSED
1316
	dd	.no_fin 	;TCB_LISTEN
1317
	dd	.no_fin 	;TCB_SYN_SENT
1533 hidnplayr 1318
	dd	.fin_syn_est	;TCB_SYN_RECEIVED
1319
	dd	.fin_syn_est	;TCB_ESTABLISHED
1514 hidnplayr 1320
	dd	.no_fin 	;TCB_CLOSE_WAIT
1533 hidnplayr 1321
	dd	.fin_wait1	;TCB_FIN_WAIT_1
1514 hidnplayr 1322
	dd	.no_fin 	;TCB_CLOSING
1323
	dd	.no_fin 	;TCB_LAST_ACK
1533 hidnplayr 1324
	dd	.fin_wait2	;TCB_FIN_WAIT_2
1325
	dd	.fin_timed	;TCB_TIMED_WAIT
1514 hidnplayr 1326
 
1327
 
1328
 
1533 hidnplayr 1329
  .fin_syn_est:
1514 hidnplayr 1330
 
1533 hidnplayr 1331
	jmp	.final_processing
1514 hidnplayr 1332
 
1533 hidnplayr 1333
  .fin_wait1:
1514 hidnplayr 1334
 
1533 hidnplayr 1335
	jmp	.final_processing
1514 hidnplayr 1336
 
1533 hidnplayr 1337
  .fin_wait2:
1514 hidnplayr 1338
 
1533 hidnplayr 1339
	jmp	.final_processing
1340
 
1341
  .fin_timed:
1342
 
1343
	jmp	.final_processing
1344
 
1514 hidnplayr 1345
  .no_fin:
1346
 
1347
;-----------------
1348
; Final processing
1349
 
1350
  .final_processing:
1351
 
1352
	DEBUGF	1,"Final processing\n"
1353
 
1533 hidnplayr 1354
	mov	[ebx + SOCKET.lock], 0
1355
 
1514 hidnplayr 1356
	;;; if debug enabled, output packet
1357
 
1358
	;test    ;;;needoutput = 1
1359
	;jnz     .outputnow
1360
 
1361
	test	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1529 hidnplayr 1362
	jnz	.ack_now
1514 hidnplayr 1363
 
1529 hidnplayr 1364
	call	kernel_free
1365
	add	esp, 4
1366
	ret
1367
 
1368
  .ack_now:
1369
 
1370
	DEBUGF	1,"ACK now!\n"
1371
 
1372
	push	ebx
1373
	mov	eax, ebx
1514 hidnplayr 1374
	call	TCP_output
1529 hidnplayr 1375
	pop	ebx
1514 hidnplayr 1376
 
1274 hidnplayr 1377
	call	kernel_free
1529 hidnplayr 1378
	add	esp, 4
1379
	ret
1274 hidnplayr 1380
 
1514 hidnplayr 1381
;------------------------------------------
1382
; Generate an ACK, droping incoming segment
1274 hidnplayr 1383
 
1514 hidnplayr 1384
align 4
1385
.drop_after_ack:
1274 hidnplayr 1386
 
1514 hidnplayr 1387
	DEBUGF	1,"Drop after ACK\n"
1274 hidnplayr 1388
 
1514 hidnplayr 1389
	test	[edx + TCP_segment.Flags], TH_RST
1390
	jnz	.drop
1274 hidnplayr 1391
 
1514 hidnplayr 1392
	and	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1274 hidnplayr 1393
 
1529 hidnplayr 1394
	push	ebx
1395
	mov	eax, ebx
1514 hidnplayr 1396
	call	TCP_output
1529 hidnplayr 1397
	pop	ebx
1318 hidnplayr 1398
 
1514 hidnplayr 1399
	call	kernel_free
1529 hidnplayr 1400
	add	esp, 4
1401
	ret
1274 hidnplayr 1402
 
1514 hidnplayr 1403
 
1404
;-------------------------------------------
1405
; Generate an RST, dropping incoming segment
1406
 
1407
align 4
1408
.drop_with_reset:
1409
 
1410
	DEBUGF	1,"Drop with reset\n"
1411
 
1412
	test	[edx + TCP_segment.Flags], TH_RST
1413
	jnz	.drop
1414
 
1415
	;;; if its a multicast/broadcast, also drop
1416
 
1417
	test	[edx + TCP_segment.Flags], TH_ACK
1418
	jnz	.respond_ack
1419
 
1420
	test	[edx + TCP_segment.Flags], TH_SYN
1421
	jnz	.respond_syn
1422
 
1423
	call	kernel_free
1529 hidnplayr 1424
	add	esp, 4
1425
	ret
1514 hidnplayr 1426
 
1427
  .respond_ack:
1428
 
1533 hidnplayr 1429
	mov	dl, TH_RST
1514 hidnplayr 1430
 
1533 hidnplayr 1431
	push	ebx
1529 hidnplayr 1432
	call	TCP_respond_segment
1533 hidnplayr 1433
	pop	ebx
1514 hidnplayr 1434
 
1435
	jmp	.destroy_new_socket
1436
 
1437
 
1438
  .respond_syn:
1439
 
1533 hidnplayr 1440
	mov	dl, TH_RST + TH_ACK
1514 hidnplayr 1441
 
1533 hidnplayr 1442
	push	ebx
1443
	call	TCP_respond_socket
1444
	pop	ebx
1514 hidnplayr 1445
 
1446
	jmp	.destroy_new_socket
1447
 
1448
;-----
1449
; Drop
1450
 
1451
align 4
1452
.drop:
1453
 
1454
	DEBUGF	1,"Dropping packet\n"
1455
 
1456
	;;;; If debugging options are enabled, output the packet somwhere
1457
 
1458
  .destroy_new_socket:
1459
 
1460
	;;;; kill the newly created socket
1461
 
1462
	call	kernel_free
1529 hidnplayr 1463
	add	esp, 4
1464
	ret
1514 hidnplayr 1465
 
1466
 
1467
 
1468
 
1469
 
1470
 
1471
;---------------------------
1472
;
1473
; TCP_pull_out_of_band
1474
;
1475
; IN:  eax =
1476
;      ebx = socket ptr
1477
;      edx = tcp packet ptr
1478
;
1479
; OUT: /
1480
;
1481
;---------------------------
1482
 
1483
align 4
1484
TCP_pull_out_of_band:
1485
 
1486
	DEBUGF	1,"TCP_pull_out_of_band\n"
1487
 
1488
	;;;; 1282-1305
1489
 
1318 hidnplayr 1490
	ret
1491
 
1492
 
1493
 
1494
;-----------------------------------------------------------------
1495
;
1514 hidnplayr 1496
; TCP_output
1318 hidnplayr 1497
;
1519 hidnplayr 1498
; IN:  eax = socket pointer
1514 hidnplayr 1499
;
1318 hidnplayr 1500
; OUT: /
1501
;
1502
;-----------------------------------------------------------------
1503
align 4
1514 hidnplayr 1504
TCP_output:
1318 hidnplayr 1505
 
1514 hidnplayr 1506
	DEBUGF 1,"TCP_output, socket: %x\n", eax
1318 hidnplayr 1507
 
1514 hidnplayr 1508
; We'll detect the length of the data to be transmitted, and flags to be used
1509
; If there is some data, or any critical controls to send (SYN / RST), then transmit
1510
; Otherwise, investigate further
1318 hidnplayr 1511
 
1514 hidnplayr 1512
	mov	ebx, [eax + TCP_SOCKET.SND_MAX]
1513
	cmp	ebx, [eax + TCP_SOCKET.SND_UNA]
1514
	jne	.not_idle
1318 hidnplayr 1515
 
1514 hidnplayr 1516
	mov	ebx, [eax + TCP_SOCKET.t_idle]
1517
	cmp	ebx, [eax + TCP_SOCKET.t_rxtcur]
1518
	jle	.not_idle
1318 hidnplayr 1519
 
1514 hidnplayr 1520
; We have been idle for a while and no ACKS are expected to clock out any data we send..
1521
; Slow start to get ack "clock" running again.
1318 hidnplayr 1522
 
1514 hidnplayr 1523
	mov	ebx, [eax + TCP_SOCKET.t_maxseg]
1524
	mov	[eax + TCP_SOCKET.SND_CWND], ebx
1318 hidnplayr 1525
 
1514 hidnplayr 1526
  .not_idle:
1527
  .again:
1528
	mov	ebx, [eax + TCP_SOCKET.SND_NXT] 	; calculate offset
1529
	sub	ebx, [eax + TCP_SOCKET.SND_UNA] 	;
1318 hidnplayr 1530
 
1514 hidnplayr 1531
	mov	ecx, [eax + TCP_SOCKET.SND_WND] 	; determine window
1532
	cmp	ecx, [eax + TCP_SOCKET.SND_CWND]	;
1533
	jl	@f					;
1534
	mov	ecx, [eax + TCP_SOCKET.SND_CWND]	;
1535
       @@:						;
1318 hidnplayr 1536
 
1529 hidnplayr 1537
	call	TCP_outflags	; in dl
1318 hidnplayr 1538
 
1514 hidnplayr 1539
; If in persist timeout with window of 0, send 1 byte.
1540
; Otherwise, if window is small but nonzero, and timer expired,
1541
; we will send what we can and go to transmit state
1318 hidnplayr 1542
 
1514 hidnplayr 1543
	test	[eax + TCP_SOCKET.t_force], -1
1544
	jz	.no_persist_timeout
1318 hidnplayr 1545
 
1514 hidnplayr 1546
	test	ecx, ecx
1547
	jnz	.no_zero_window
1255 hidnplayr 1548
 
1533 hidnplayr 1549
	cmp	ebx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
1514 hidnplayr 1550
	jge	@f
1255 hidnplayr 1551
 
1514 hidnplayr 1552
	and	dl, not (TH_FIN)	  ; clear the FIN flag    ??? how can it be set before?
1255 hidnplayr 1553
 
1514 hidnplayr 1554
       @@:
1555
	inc	ecx
1556
	jmp	.no_persist_timeout
1255 hidnplayr 1557
 
1514 hidnplayr 1558
  .no_zero_window:
1254 hidnplayr 1559
 
1529 hidnplayr 1560
	mov	[eax + TCP_SOCKET.timer_persist], 0	;;;;
1514 hidnplayr 1561
	mov	[eax + TCP_SOCKET.t_rxtshift], 0
1254 hidnplayr 1562
 
1514 hidnplayr 1563
  .no_persist_timeout:
1159 hidnplayr 1564
 
1514 hidnplayr 1565
;;;106
1159 hidnplayr 1566
 
1533 hidnplayr 1567
	mov	esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
1514 hidnplayr 1568
	cmp	esi, ecx
1569
	jl	@f
1570
	mov	esi, ecx
1571
       @@:
1572
	sub	esi, ebx
1254 hidnplayr 1573
 
1514 hidnplayr 1574
	cmp	esi, -1
1575
	jne	.not_minus_one
1159 hidnplayr 1576
 
1514 hidnplayr 1577
; If FIN has been set, but not ACKed, and we havent been called to retransmit,
1578
; len (esi) will be -1
1579
; Otherwise, window shrank after we sent into it.
1580
; If window shrank to 0, cancel pending retransmit and pull SND_NXT back to (closed) window
1581
; We will enter persist state below.
1582
; If window didn't close completely, just wait for an ACK
1159 hidnplayr 1583
 
1514 hidnplayr 1584
	xor	esi, esi
1159 hidnplayr 1585
 
1514 hidnplayr 1586
	test	ecx, ecx
1587
	jnz	@f
1159 hidnplayr 1588
 
1529 hidnplayr 1589
	mov	[eax + TCP_SOCKET.timer_retransmission], 0   ; cancel retransmit
1274 hidnplayr 1590
 
1514 hidnplayr 1591
	push	[eax + TCP_SOCKET.SND_UNA]
1592
	pop	[eax + TCP_SOCKET.SND_NXT]
1593
       @@:
1254 hidnplayr 1594
 
1514 hidnplayr 1595
  .not_minus_one:
1254 hidnplayr 1596
 
1514 hidnplayr 1597
;;; 124
1159 hidnplayr 1598
 
1514 hidnplayr 1599
	cmp	esi, [eax + TCP_SOCKET.t_maxseg]
1600
	jle	@f
1274 hidnplayr 1601
 
1514 hidnplayr 1602
	mov	esi, [eax + TCP_SOCKET.t_maxseg]
1603
	;sendalot = 1
1274 hidnplayr 1604
 
1514 hidnplayr 1605
       @@:
1274 hidnplayr 1606
 
1514 hidnplayr 1607
;;; 128
1274 hidnplayr 1608
 
1514 hidnplayr 1609
	mov	edi, [eax + TCP_SOCKET.SND_NXT]
1610
	add	edi, esi	; len
1611
	sub	edi, [eax + TCP_SOCKET.SND_UNA]
1533 hidnplayr 1612
	add	edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
1514 hidnplayr 1613
	cmp	edi, 0
1614
	jle	@f
1274 hidnplayr 1615
 
1514 hidnplayr 1616
	and	dl, not (TH_FIN)	  ; clear the FIN flag
1159 hidnplayr 1617
 
1514 hidnplayr 1618
       @@:
1159 hidnplayr 1619
 
1620
 
1529 hidnplayr 1621
; set ecx to space available in receive buffer
1622
; From now on, ecx will be the window we advertise to the other end
1159 hidnplayr 1623
 
1529 hidnplayr 1624
	mov	ecx, SOCKET_MAXDATA
1533 hidnplayr 1625
	sub	ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
1159 hidnplayr 1626
 
1514 hidnplayr 1627
;------------------------------
1628
; Sender silly window avoidance
1159 hidnplayr 1629
 
1529 hidnplayr 1630
	cmp	ecx, [eax + TCP_SOCKET.t_maxseg]
1514 hidnplayr 1631
	je	.send
1274 hidnplayr 1632
 
1514 hidnplayr 1633
;;; TODO: 144-145
1274 hidnplayr 1634
 
1514 hidnplayr 1635
	test	[eax + TCP_SOCKET.t_force], -1
1636
	jnz	.send
1274 hidnplayr 1637
 
1529 hidnplayr 1638
	mov	ebx, [eax + TCP_SOCKET.max_sndwnd]
1639
	shr	ebx, 1
1640
	cmp	ecx, ebx
1641
	jge	.send
1274 hidnplayr 1642
 
1529 hidnplayr 1643
	mov	ebx, [eax + TCP_SOCKET.SND_NXT]
1644
	cmp	ebx, [eax + TCP_SOCKET.SND_MAX]
1645
	jl	.send
1254 hidnplayr 1646
 
1514 hidnplayr 1647
;----------------------------------------
1648
; Check if a window update should be sent
1159 hidnplayr 1649
 
1529 hidnplayr 1650
	test	ecx, ecx	; window
1651
	jz	.no_window
1159 hidnplayr 1652
 
1514 hidnplayr 1653
;;; TODO 154-172
1159 hidnplayr 1654
 
1514 hidnplayr 1655
  .no_window:
1159 hidnplayr 1656
 
1514 hidnplayr 1657
;--------------------------
1658
; Should a segment be sent?
1159 hidnplayr 1659
 
1534 hidnplayr 1660
	test	[eax + TCP_SOCKET.t_flags], TF_ACKNOW
1514 hidnplayr 1661
	jnz	.send
1159 hidnplayr 1662
 
1514 hidnplayr 1663
	test	dl, TH_SYN + TH_RST
1664
	jnz	.send
1159 hidnplayr 1665
 
1534 hidnplayr 1666
	mov	ebx, [eax + TCP_SOCKET.SND_UP]
1667
	cmp	ebx, [eax + TCP_SOCKET.SND_UNA]
1514 hidnplayr 1668
	jg	.send
1249 hidnplayr 1669
 
1514 hidnplayr 1670
	test	dl, TH_FIN
1671
	jz	.enter_persist
1318 hidnplayr 1672
 
1534 hidnplayr 1673
	test	[eax + TCP_SOCKET.t_flags], TF_SENTFIN
1514 hidnplayr 1674
	jnz	.send
1254 hidnplayr 1675
 
1534 hidnplayr 1676
	mov	ebx, [eax + TCP_SOCKET.SND_NXT]
1677
	cmp	ebx, [eax + TCP_SOCKET.SND_UNA]
1514 hidnplayr 1678
	je	.send
1254 hidnplayr 1679
 
1514 hidnplayr 1680
;--------------------
1681
; Enter persist state
1318 hidnplayr 1682
 
1514 hidnplayr 1683
  .enter_persist:
1318 hidnplayr 1684
 
1519 hidnplayr 1685
	DEBUGF	1,"Entering persist state\n"
1318 hidnplayr 1686
 
1514 hidnplayr 1687
;--------------------------------------
1688
; No reason to send a segment, just ret
1318 hidnplayr 1689
 
1514 hidnplayr 1690
	DEBUGF	1,"No reason to send a segment\n"
1318 hidnplayr 1691
 
1514 hidnplayr 1692
	ret
1318 hidnplayr 1693
 
1694
 
1514 hidnplayr 1695
;-----------------------------------------------
1696
;
1697
; Send a segment
1698
;
1529 hidnplayr 1699
; eax = socket pointer
1514 hidnplayr 1700
;  dl = flags
1701
;
1702
;-----------------------------------------------
1318 hidnplayr 1703
 
1529 hidnplayr 1704
  .send:
1318 hidnplayr 1705
 
1514 hidnplayr 1706
	DEBUGF	1,"Preparing to send a segment\n"
1318 hidnplayr 1707
 
1529 hidnplayr 1708
	mov	edi, TCP_segment.Data	; edi will contain headersize
1318 hidnplayr 1709
 
1529 hidnplayr 1710
	sub	esp, 8			; create some space on stack
1711
	push	eax			; save this too..
1712
 
1514 hidnplayr 1713
;------------------------------------
1714
; Send options with first SYN segment
1318 hidnplayr 1715
 
1514 hidnplayr 1716
	test	dl, TH_SYN
1717
	jz	.no_options
1318 hidnplayr 1718
 
1529 hidnplayr 1719
	push	[eax + TCP_SOCKET.ISS]
1720
	pop	[eax + TCP_SOCKET.SND_NXT]
1318 hidnplayr 1721
 
1529 hidnplayr 1722
	test	[eax + TCP_SOCKET.t_flags], TF_NOOPT
1514 hidnplayr 1723
	jnz	.no_options
1318 hidnplayr 1724
 
1529 hidnplayr 1725
	mov	ecx, 1460
1726
	or	ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
1727
	bswap	ecx
1728
	push	ecx
1729
	add	di, 4
1514 hidnplayr 1730
 
1529 hidnplayr 1731
	test	[eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
1514 hidnplayr 1732
	jz	.no_syn
1733
 
1734
	test	dl, TH_ACK
1735
	jnz	.scale_opt
1736
 
1529 hidnplayr 1737
	test	[eax + TCP_SOCKET.t_flags], TF_RCVD_SCALE
1514 hidnplayr 1738
	jz	.no_syn
1739
 
1740
  .scale_opt:
1529 hidnplayr 1741
	movzx	ecx, byte [eax + TCP_SOCKET.request_r_scale]
1742
	or	ecx, TCP_OPT_WINDOW shl 24 + 4 shl 16 + TCP_OPT_NOP shl 8
1743
	bswap	ecx
1744
	pushd	ecx
1514 hidnplayr 1745
	add	di, 4
1159 hidnplayr 1746
 
1514 hidnplayr 1747
  .no_syn:
1159 hidnplayr 1748
 
1514 hidnplayr 1749
;------------------------------------
1750
; Make the timestamp option if needed
1159 hidnplayr 1751
 
1529 hidnplayr 1752
	test	[eax + TCP_SOCKET.t_flags], TF_REQ_TSTMP
1514 hidnplayr 1753
	jz	.no_timestamp
1159 hidnplayr 1754
 
1514 hidnplayr 1755
	test	dl, TH_RST
1756
	jnz	.no_timestamp
1757
 
1758
	test	dl, TH_ACK
1759
	jz	.timestamp
1760
 
1529 hidnplayr 1761
	test	[eax + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
1514 hidnplayr 1762
	jz	.no_timestamp
1763
 
1764
  .timestamp:
1529 hidnplayr 1765
	mov	esi, [timer_ticks]
1766
	bswap	esi
1767
	push	esi
1514 hidnplayr 1768
	pushw	0
1529 hidnplayr 1769
	pushd	TCP_OPT_TIMESTAMP + 10 shl 8 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24
1514 hidnplayr 1770
	add	di, 10
1771
 
1772
  .no_timestamp:
1773
	;; TODO: check if we dont exceed the max segment size
1774
 
1775
  .no_options:
1529 hidnplayr 1776
	; eax = socket ptr
1777
	; edx = flags
1778
	; ecx = data size
1779
	; edi = header size
1780
	; esi = snd ring buff ptr
1514 hidnplayr 1781
 
1533 hidnplayr 1782
	mov	ecx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
1783
	cmp	ecx, [eax + TCP_SOCKET.t_maxseg]			;;; right?
1784
	jle	@f
1785
	mov	ecx, [eax + TCP_SOCKET.t_maxseg]
1786
       @@:
1514 hidnplayr 1787
	add	ecx, edi	; total TCP segment size
1788
 
1529 hidnplayr 1789
; Start by pushing all TCP header values in reverse order on stack
1790
; (essentially, creating the tcp header!)
1514 hidnplayr 1791
 
1529 hidnplayr 1792
	pushw	0	;        .UrgentPointer          dw ?
1793
	pushw	0	;        .Checksum               dw ?
1794
	pushw	0x00a0	;        .Window                 dw ?    ;;;;;;;
1795
	shl	edi, 2	;        .DataOffset             db ?  only 4 left-most bits
1796
	shl	dx, 8
1797
	or	dx, di	;        .Flags                  db ?
1798
	pushw	dx
1799
	shr	edi, 2	;        .DataOffset             db ? ;;;;
1514 hidnplayr 1800
 
1529 hidnplayr 1801
	push	[eax + TCP_SOCKET.RCV_NXT]	;        .AckNumber              dd ?
1802
	ntohld	[esp]
1159 hidnplayr 1803
 
1529 hidnplayr 1804
	push	[eax + TCP_SOCKET.SND_NXT]	;        .SequenceNumber         dd ?
1805
	ntohld	[esp]
1159 hidnplayr 1806
 
1529 hidnplayr 1807
	push	[eax + TCP_SOCKET.RemotePort]	;        .DestinationPort        dw ?
1808
	ntohlw	[esp]
1249 hidnplayr 1809
 
1529 hidnplayr 1810
	push	[eax + TCP_SOCKET.LocalPort]	;        .SourcePort             dw ?
1811
	ntohlw	[esp]
1274 hidnplayr 1812
 
1533 hidnplayr 1813
	push	edi		; header size
1274 hidnplayr 1814
 
1529 hidnplayr 1815
; Create the IP packet
1816
	mov	ebx, [eax + IP_SOCKET.LocalIP]	; source ip
1817
	mov	eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
1818
	mov	di, IP_PROTO_TCP shl 8 + 128
1819
	call	IPv4_output
1820
	jz	.fail
1274 hidnplayr 1821
 
1529 hidnplayr 1822
;-----------------------------------------
1823
; Move TCP header from stack to TCP packet
1274 hidnplayr 1824
 
1533 hidnplayr 1825
	push	ecx
1826
	mov	ecx, [esp+4]
1827
	lea	esi, [esp+4+4]
1529 hidnplayr 1828
	shr	ecx, 2
1829
	rep	movsd
1533 hidnplayr 1830
	pop	ecx		; full TCP packet size
1274 hidnplayr 1831
 
1533 hidnplayr 1832
	pop	esi		; headersize
1833
	add	esp, esi
1254 hidnplayr 1834
 
1533 hidnplayr 1835
	mov	[esp + 4], eax		; packet ptr
1530 hidnplayr 1836
	mov	[esp + 4+4], edx	; packet size
1254 hidnplayr 1837
 
1533 hidnplayr 1838
	mov	edx, edi		; begin of data
1839
	sub	edx, esi		; begin of packet (edi = begin of data)
1840
	push	ecx
1841
	sub	ecx, esi		; data size
1159 hidnplayr 1842
 
1514 hidnplayr 1843
;--------------
1844
; Copy the data
1159 hidnplayr 1845
 
1529 hidnplayr 1846
; eax = ptr to ring struct
1847
; ecx = buffer size
1848
; edi = ptr to buffer
1249 hidnplayr 1849
 
1536 hidnplayr 1850
;        test    ecx, ecx
1533 hidnplayr 1851
	mov	eax, [esp+4]		  ; socket ptr
1536 hidnplayr 1852
	add	[eax + TCP_SOCKET.SND_NXT], ecx
1853
	add	eax, STREAM_SOCKET.snd
1533 hidnplayr 1854
	push	edx
1529 hidnplayr 1855
	call	SOCKET_ring_read
1536 hidnplayr 1856
	pop	esi
1857
	pop	ecx
1529 hidnplayr 1858
	pop	eax
1254 hidnplayr 1859
 
1533 hidnplayr 1860
	test	[esi + TCP_segment.Flags], TH_SYN + TH_FIN
1861
	jz	@f
1862
	inc	[eax + TCP_SOCKET.SND_NXT]
1863
	;;; TODO: update sentfin flag
1864
       @@:
1254 hidnplayr 1865
 
1533 hidnplayr 1866
	mov	edx, [eax + TCP_SOCKET.SND_NXT]
1867
	cmp	edx, [eax + TCP_SOCKET.SND_MAX]
1868
	jle	@f
1869
	mov	[eax + TCP_SOCKET.SND_MAX], edx
1870
 
1871
	;;;; TODO: time transmission (420)
1872
       @@:
1873
 
1874
	;;; TODO: set retransmission timer
1875
 
1876
;--------------------
1877
; Create the checksum
1878
 
1529 hidnplayr 1879
	DEBUGF	1,"checksum: ptr=%x size=%u\n", esi, ecx
1159 hidnplayr 1880
 
1529 hidnplayr 1881
	TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
1882
	mov	[esi+TCP_segment.Checksum], dx
1883
 
1514 hidnplayr 1884
;----------------
1885
; Send the packet
1159 hidnplayr 1886
 
1529 hidnplayr 1887
	DEBUGF	1,"Sending TCP Packet to device %x\n", ebx
1888
	call	[ebx + NET_DEVICE.transmit]
1889
	ret
1159 hidnplayr 1890
 
1514 hidnplayr 1891
 
1529 hidnplayr 1892
  .fail:
1893
	pop	ecx
1894
	add	esp, ecx
1536 hidnplayr 1895
	add	esp, 4+8
1529 hidnplayr 1896
	DEBUGF 1,"TCP_output: failed\n"
1159 hidnplayr 1897
	ret
1898
 
1529 hidnplayr 1899
 
1900
 
1514 hidnplayr 1901
;-------------------------
1902
;
1903
; TCP_outflags
1904
;
1905
;  IN:  eax = socket ptr
1906
;
1907
;  OUT: edx = flags
1908
;
1909
;-------------------------
1249 hidnplayr 1910
align 4
1514 hidnplayr 1911
TCP_outflags:
1254 hidnplayr 1912
 
1514 hidnplayr 1913
	mov	edx, [eax + TCP_SOCKET.t_state]
1914
	movzx	edx, byte [edx + .flaglist]
1254 hidnplayr 1915
 
1514 hidnplayr 1916
	DEBUGF	1,"TCP_outflags, socket: %x, flags: %x\n", eax, dl
1917
 
1159 hidnplayr 1918
	ret
1919
 
1514 hidnplayr 1920
  .flaglist:
1159 hidnplayr 1921
 
1514 hidnplayr 1922
	db	TH_RST + TH_ACK 	; TCB_CLOSED
1923
	db	0			; TCB_LISTEN
1924
	db	TH_SYN			; TCB_SYN_SENT
1925
	db	TH_SYN + TH_ACK 	; TCB_SYN_RECEIVED
1926
	db		 TH_ACK 	; TCB_ESTABLISHED
1927
	db		 TH_ACK 	; TCB_CLOSE_WAIT
1928
	db	TH_SYN + TH_ACK 	; TCB_FIN_WAIT_1
1929
	db	TH_SYN + TH_ACK 	; TCB_CLOSING
1930
	db	TH_SYN + TH_ACK 	; TCB_LAST_ACK
1931
	db		 TH_ACK 	; TCB_FIN_WAIT_2
1932
	db		 TH_ACK 	; TCB_TIMED_WAIT
1249 hidnplayr 1933
 
1514 hidnplayr 1934
 
1529 hidnplayr 1935
 
1936
 
1514 hidnplayr 1937
;-------------------------
1938
;
1939
; TCP_drop
1940
;
1941
;  IN:  eax = socket ptr
1942
;
1943
;  OUT: /
1944
;
1945
;-------------------------
1249 hidnplayr 1946
align 4
1514 hidnplayr 1947
TCP_drop:
1254 hidnplayr 1948
 
1514 hidnplayr 1949
	DEBUGF	1,"TCP_drop\n"
1254 hidnplayr 1950
 
1514 hidnplayr 1951
;        cmp     [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
1952
;        jl      .no_syn_received
1159 hidnplayr 1953
 
1514 hidnplayr 1954
	mov	[eax + TCP_SOCKET.t_state], TCB_CLOSED
1159 hidnplayr 1955
 
1514 hidnplayr 1956
	call	TCP_output
1254 hidnplayr 1957
 
1514 hidnplayr 1958
;  .no_syn_received:
1959
 
1159 hidnplayr 1960
	ret
1961
 
1962
 
1254 hidnplayr 1963
 
1964
 
1159 hidnplayr 1965
 
1514 hidnplayr 1966
;---------------------------------------
1967
;
1519 hidnplayr 1968
; The easy way to send an ACK/RST/keepalive segment
1514 hidnplayr 1969
;
1529 hidnplayr 1970
; TCP_respond_socket:
1971
;
1972
;  IN:  ebx = socket ptr
1519 hidnplayr 1973
;        cl = flags
1514 hidnplayr 1974
;
1529 hidnplayr 1975
;--------------------------------------
1514 hidnplayr 1976
align 4
1529 hidnplayr 1977
TCP_respond_socket:
1254 hidnplayr 1978
 
1529 hidnplayr 1979
	DEBUGF	1,"TCP_respond_socket\n"
1159 hidnplayr 1980
 
1519 hidnplayr 1981
;---------------------
1982
; Create the IP packet
1983
 
1529 hidnplayr 1984
	push	cx ebx
1985
	mov	eax, [ebx + IP_SOCKET.RemoteIP]
1986
	mov	ebx, [ebx + IP_SOCKET.LocalIP]
1519 hidnplayr 1987
	mov	ecx, TCP_segment.Data
1529 hidnplayr 1988
	mov	di , IP_PROTO_TCP shl 8 + 128
1989
	call	IPv4_output
1519 hidnplayr 1990
	test	edi, edi
1991
	jz	.error
1529 hidnplayr 1992
	pop	esi cx
1993
	push	edx eax
1519 hidnplayr 1994
 
1529 hidnplayr 1995
;-----------------------------------------------
1996
; Fill in the TCP header by using the socket ptr
1519 hidnplayr 1997
 
1529 hidnplayr 1998
	mov	ax, [esi + TCP_SOCKET.LocalPort]
1999
	rol	ax, 8
2000
	stosw
2001
	mov	ax, [esi + TCP_SOCKET.RemotePort]
2002
	rol	ax, 8
2003
	stosw
2004
	mov	eax, [esi + TCP_SOCKET.SND_NXT]
2005
	bswap	eax
2006
	stosd
2007
	mov	eax, [esi + TCP_SOCKET.RCV_NXT]
2008
	bswap	eax
2009
	stosd
2010
	mov	al, 0x50	; Dataoffset: 20 bytes
2011
	stosb
2012
	mov	al, cl
2013
	stosb
2014
	mov	ax, [esi + TCP_SOCKET.RCV_WND]
2015
	rol	ax, 8
2016
	stosw			; window
2017
	xor	eax, eax
2018
	stosd			; checksum + urgentpointer
1519 hidnplayr 2019
 
2020
;---------------------
2021
; Fill in the checksum
2022
 
2023
  .checksum:
1529 hidnplayr 2024
	sub	edi, TCP_segment.Data
2025
	mov	ecx, TCP_segment.Data
2026
	xchg	esi, edi
2027
	TCP_checksum (edi + IP_SOCKET.LocalIP), (esi + IP_SOCKET.RemoteIP)
2028
	mov	[esi+TCP_segment.Checksum], dx
1519 hidnplayr 2029
 
2030
;--------------------
2031
; And send the segment
2032
 
2033
	call	[ebx + NET_DEVICE.transmit]
1159 hidnplayr 2034
	ret
2035
 
1519 hidnplayr 2036
  .error:
1529 hidnplayr 2037
	DEBUGF	1,"TCP_respond failed\n"
2038
	add	esp, 2+4
1159 hidnplayr 2039
 
1519 hidnplayr 2040
	ret
1514 hidnplayr 2041
 
1529 hidnplayr 2042
 
2043
 
2044
;-------------------------
2045
; TCP_respond.segment:
2046
;
2047
;  IN:  edx = segment ptr (a previously received segment)
2048
;        cl = flags
2049
 
2050
align 4
2051
TCP_respond_segment:
2052
 
2053
	DEBUGF	1,"TCP_respond_segment\n"
2054
 
2055
;---------------------
2056
; Create the IP packet
2057
 
2058
	push	cx edx
2059
	mov	ebx, [edx - 20 + IPv4_Packet.SourceAddress]	 ;;;; and what if ip packet had options?!
2060
	mov	eax, [edx - 20 + IPv4_Packet.DestinationAddress]   ;;;
2061
	mov	ecx, TCP_segment.Data
2062
	mov	di , IP_PROTO_TCP shl 8 + 128
2063
	call	IPv4_output
2064
	jz	.error
1533 hidnplayr 2065
	pop	esi cx
1529 hidnplayr 2066
 
2067
	push	edx eax
2068
 
1519 hidnplayr 2069
;---------------------------------------------------
2070
; Fill in the TCP header by using a received segment
2071
 
2072
	mov	ax, [esi + TCP_segment.DestinationPort]
2073
	rol	ax, 8
2074
	stosw
2075
	mov	ax, [esi + TCP_segment.SourcePort]
2076
	rol	ax, 8
2077
	stosw
2078
	mov	eax, [esi + TCP_segment.AckNumber]
2079
	bswap	eax
2080
	stosd
2081
	xor	eax, eax
2082
	stosd
2083
	mov	al, 0x50	; Dataoffset: 20 bytes
2084
	stosb
2085
	mov	al, cl
2086
	stosb
2087
	mov	ax, 1280
2088
	rol	ax, 8
2089
	stosw			; window
2090
	xor	eax, eax
2091
	stosd			; checksum + urgentpointer
2092
 
1529 hidnplayr 2093
;---------------------
2094
; Fill in the checksum
1519 hidnplayr 2095
 
1529 hidnplayr 2096
  .checksum:
2097
	lea	esi, [edi - TCP_segment.Data]
2098
	mov	ecx, TCP_segment.Data
2099
	TCP_checksum (esi - 20 + IPv4_Packet.DestinationAddress), (esi - 20 + IPv4_Packet.DestinationAddress)
2100
	mov	[esi+TCP_segment.Checksum], dx
1519 hidnplayr 2101
 
1529 hidnplayr 2102
;--------------------
2103
; And send the segment
1519 hidnplayr 2104
 
1529 hidnplayr 2105
	call	[ebx + NET_DEVICE.transmit]
2106
	ret
1519 hidnplayr 2107
 
1529 hidnplayr 2108
  .error:
2109
	DEBUGF	1,"TCP_respond failed\n"
2110
	add	esp, 2+4
1519 hidnplayr 2111
 
2112
	ret
2113
 
2114
 
2115
 
1254 hidnplayr 2116
 
2117
;---------------------------------------------------------------------------
2118
;
2119
; TCP_API
2120
;
2121
; This function is called by system function 75
2122
;
2123
; IN:  subfunction number in bl
2124
;      device number in bh
2125
;      ecx, edx, .. depends on subfunction
2126
;
2127
; OUT:
2128
;
2129
;---------------------------------------------------------------------------
2130
align 4
2131
TCP_API:
2132
 
2133
	movzx	eax, bh
2134
	shl	eax, 2
2135
 
2136
	test	bl, bl
2137
	jz	.packets_tx	; 0
2138
	dec	bl
2139
	jz	.packets_rx	; 1
2140
 
2141
.error:
2142
	mov	eax, -1
2143
	ret
2144
 
2145
.packets_tx:
1514 hidnplayr 2146
	add	eax, TCP_segments_tx
1254 hidnplayr 2147
	mov	eax, [eax]
2148
	ret
2149
 
2150
.packets_rx:
1514 hidnplayr 2151
	add	eax, TCP_segments_rx
1254 hidnplayr 2152
	mov	eax, [eax]
2153
	ret