Subversion Repositories Kolibri OS

Rev

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