Subversion Repositories Kolibri OS

Rev

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