Subversion Repositories Kolibri OS

Rev

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