Subversion Repositories Kolibri OS

Rev

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