Subversion Repositories Kolibri OS

Rev

Rev 1257 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1196 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved.    ;;
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
;;                                                                 ;;
10
;;    Written by hidnplayr@kolibrios.org                           ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1159 hidnplayr 16
 
1196 hidnplayr 17
 
1206 hidnplayr 18
$Revision: 1274 $
1159 hidnplayr 19
 
1196 hidnplayr 20
TCP_RETRIES		equ 5		; Number of times to resend a Packet
1254 hidnplayr 21
TCP_PACKET_TTL		equ 50		; resend if not replied to in 1/100 s
22
TCP_SOCKET_TTL		equ 10		; # of secs to wait before closing socket
1196 hidnplayr 23
TCP_QUEUE_SIZE		equ 16
24
 
1249 hidnplayr 25
 
1159 hidnplayr 26
struct	TCP_Packet
27
	.SourcePort		dw ?
28
	.DestinationPort	dw ?
29
	.SequenceNumber 	dd ?
30
	.AckNumber		dd ?
1196 hidnplayr 31
	.DataOffset		db ?	; DataOffset[0-3 bits] and Reserved[4-7]
32
	.Flags			db ?	; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
1159 hidnplayr 33
	.Window 		dw ?
34
	.Checksum		dw ?
35
	.UrgentPointer		dw ?
1274 hidnplayr 36
;        .Options                rb 3
37
;        .Padding                db ?
1159 hidnplayr 38
	.Data:
39
ends
40
 
1274 hidnplayr 41
struct	tcp_in_queue_entry
42
	.data_ptr	dd ?
43
	.data_size	dd ?
44
	.offset 	dd ?
45
	.size:
46
ends
47
 
48
struct	tcp_out_queue_entry
49
	.data_ptr	dd ?
50
	.data_size	dd ?
51
	.ttl		dd ?
52
	.retries	dd ?
53
	.owner		dd ?
54
	.sendproc	dd ?
55
	.seq_num	dd ?
56
	.socket 	dd ?
57
	.size:
58
ends
59
 
1196 hidnplayr 60
align 4
61
uglobal
62
	TCP_PACKETS_TX		rd  MAX_IP
63
	TCP_PACKETS_RX		rd  MAX_IP
1159 hidnplayr 64
 
1249 hidnplayr 65
	TCP_IN_QUEUE		rd  (tcp_in_queue_entry.size*TCP_QUEUE_SIZE+queue.data)/4
1254 hidnplayr 66
	TCP_OUT_QUEUE		dd  ?
1249 hidnplayr 67
				rd  (tcp_out_queue_entry.size*TCP_QUEUE_SIZE)/4
1196 hidnplayr 68
endg
69
 
1249 hidnplayr 70
align 4
71
iglobal
1254 hidnplayr 72
stateHandler:
1196 hidnplayr 73
 
1249 hidnplayr 74
  dd  stateTCB_LISTEN
75
  dd  stateTCB_SYN_SENT
76
  dd  stateTCB_SYN_RECEIVED
77
  dd  stateTCB_ESTABLISHED
78
  dd  stateTCB_FIN_WAIT_1
79
  dd  stateTCB_FIN_WAIT_2
80
  dd  stateTCB_CLOSE_WAIT
81
  dd  stateTCB_CLOSING
82
  dd  stateTCB_LAST_ACK
83
  dd  stateTCB_TIME_WAIT
84
  dd  stateTCB_CLOSED
1196 hidnplayr 85
 
1249 hidnplayr 86
endg
1196 hidnplayr 87
 
1249 hidnplayr 88
 
1196 hidnplayr 89
;-----------------------------------------------------------------
90
;
91
; TCP_init
92
;
93
;  This function resets all TCP variables
94
;
95
;  IN:  /
96
;  OUT: /
97
;
98
;-----------------------------------------------------------------
99
align 4
100
TCP_init:
101
 
102
	xor	eax, eax
103
	mov	edi, TCP_PACKETS_TX
104
	mov	ecx, 2*MAX_IP
105
	rep	stosd
106
 
1249 hidnplayr 107
	init_queue TCP_IN_QUEUE
1196 hidnplayr 108
 
1274 hidnplayr 109
; tcp_out_queue is a special type of queue:
110
; The first dword is a counter of total packets queued.
111
; The remaining bytes are socket 'slots' wich use tcp_out_queue_entry data structure.
112
; An empty slot is know by the fact that tcp_out_queue_entry.data_ptr (first dword of the slot) is set to 0
113
; There are TCP_OUT_QUEUE_SIZE number of slots
1257 hidnplayr 114
 
1254 hidnplayr 115
	xor	eax, eax
116
	mov	esi, TCP_OUT_QUEUE
117
	mov	ecx, TCP_QUEUE_SIZE*tcp_out_queue_entry/4+1
118
	rep	stosd
119
 
1196 hidnplayr 120
	ret
121
 
122
 
123
;-----------------------------------------------------------------
124
;
1249 hidnplayr 125
;  TCP_decrease_socket_ttls
1159 hidnplayr 126
;
1249 hidnplayr 127
;  IN:  /
128
;  OUT: /
1159 hidnplayr 129
;
1196 hidnplayr 130
;-----------------------------------------------------------------
131
align 4
1249 hidnplayr 132
TCP_decrease_socket_ttls:
1274 hidnplayr 133
; scan through all the sockets, decrementing active timers
1159 hidnplayr 134
 
135
	mov	ebx, net_sockets
136
 
1249 hidnplayr 137
	cmp	[ebx + SOCKET_head.NextPtr], 0
1159 hidnplayr 138
	je	.exit
139
 
140
  .next_socket:
1249 hidnplayr 141
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 142
	or	ebx, ebx
143
	jz	.exit
144
 
1249 hidnplayr 145
	cmp	[ebx + SOCKET_head.Type], IP_PROTO_TCP
146
	jne	.next_socket
147
 
1254 hidnplayr 148
;        DEBUGF  1, "K :   %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.state]
1159 hidnplayr 149
 
1254 hidnplayr 150
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], 0
1159 hidnplayr 151
	jne	.decrement_tcb
1249 hidnplayr 152
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0
1159 hidnplayr 153
	jne	.decrement_wnd
154
	jmp	.next_socket
155
 
156
  .decrement_tcb:
1274 hidnplayr 157
; decrement it, delete socket if TCB timer = 0 & socket in timewait state
1254 hidnplayr 158
	dec	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer]
1159 hidnplayr 159
	jnz	.next_socket
160
 
1254 hidnplayr 161
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
1159 hidnplayr 162
	jne	.next_socket
163
 
1249 hidnplayr 164
	push	[ebx + SOCKET_head.PrevPtr]
1159 hidnplayr 165
	stdcall net_socket_free, ebx
166
	pop	ebx
167
	jmp	.next_socket
168
 
169
  .decrement_wnd:
1249 hidnplayr 170
	dec	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer]
1159 hidnplayr 171
	jmp	.next_socket
172
 
173
  .exit:
174
	ret
175
 
176
 
1249 hidnplayr 177
 
178
;-----------------------------------------------------------------
1159 hidnplayr 179
;
1249 hidnplayr 180
; TCP_send_queued:
1159 hidnplayr 181
;
1249 hidnplayr 182
;  Decreases 'ttl' of tcp packets queued.
183
;  if 'ttl' reaches 0, resend the packet and decrease 'retries'
184
;  if 'retries' reaches zero, remove the queued packet
185
;
186
;  IN:  /
187
;  OUT: /
188
;
189
;-----------------------------------------------------------------
1196 hidnplayr 190
align 4
1249 hidnplayr 191
TCP_send_queued:
1159 hidnplayr 192
 
1249 hidnplayr 193
	cmp	[TCP_OUT_QUEUE], 0
194
	je	.exit
1159 hidnplayr 195
 
1249 hidnplayr 196
	mov	eax, TCP_QUEUE_SIZE
197
	mov	ecx, [TCP_OUT_QUEUE]
198
	mov	esi, TCP_OUT_QUEUE+4
1159 hidnplayr 199
 
1249 hidnplayr 200
  .loop:
201
	cmp	[esi + tcp_out_queue_entry.data_ptr], 0
202
	jnz	.found_one
203
	add	esi, tcp_out_queue_entry.size
204
	loop	.loop
205
  .exit:
206
	ret
1159 hidnplayr 207
 
1249 hidnplayr 208
  .found_one:
209
	dec	[esi + tcp_out_queue_entry.ttl]
210
	jz	.send_it
211
  .find_next:
1254 hidnplayr 212
	add	esi, tcp_out_queue_entry.size
1249 hidnplayr 213
	dec	eax
214
	jz	.exit
1254 hidnplayr 215
	test	ecx, ecx
216
	jnz	.loop
217
	ret
1159 hidnplayr 218
 
1249 hidnplayr 219
  .send_it:
220
	push	eax ecx esi
1159 hidnplayr 221
 
1254 hidnplayr 222
	mov	ebx, [esi + tcp_out_queue_entry.owner]
1249 hidnplayr 223
	push	[esi + tcp_out_queue_entry.data_size]
224
	push	[esi + tcp_out_queue_entry.data_ptr]
1254 hidnplayr 225
	DEBUGF 1,"Now sending TCP packet %x, size: %u, owner: %x, sendproc %x\n", [esp], [esp+4], ebx, [esi + tcp_out_queue_entry.sendproc]
1257 hidnplayr 226
	inc	[TCP_PACKETS_TX]
1249 hidnplayr 227
	call	[esi + tcp_out_queue_entry.sendproc]
1254 hidnplayr 228
	add	esp, 8
1249 hidnplayr 229
	pop	esi ecx eax
1159 hidnplayr 230
 
1249 hidnplayr 231
	dec	[esi + tcp_out_queue_entry.retries]
232
	jz	.remove_it
1254 hidnplayr 233
 
234
	mov	[esi + tcp_out_queue_entry.ttl], TCP_PACKET_TTL
1249 hidnplayr 235
	jmp	.find_next
1159 hidnplayr 236
 
1249 hidnplayr 237
  .remove_it:
238
	push	[esi + tcp_out_queue_entry.data_ptr]
239
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
240
	call	kernel_free
241
	jmp	.find_next
1159 hidnplayr 242
 
243
 
244
 
1249 hidnplayr 245
;-----------------------------------------------------------------
246
;
247
; TCP_handler:
1159 hidnplayr 248
;
1196 hidnplayr 249
;  Called by IPv4_handler,
250
;  this procedure will inject the tcp data diagrams in the application sockets.
251
;
252
;  IN:  Pointer to buffer in [esp]
253
;       size of buffer in [esp+4]
254
;       pointer to device struct in ebx
255
;       TCP Packet size in ecx
1274 hidnplayr 256
;       pointer to TCP Packet in edx
257
;       SourceAddres (IPv4) in esi
1196 hidnplayr 258
;  OUT: /
259
;
260
;-----------------------------------------------------------------
1249 hidnplayr 261
align 4
262
TCP_handler :
1159 hidnplayr 263
 
1196 hidnplayr 264
       DEBUGF 1,"TCP_Handler\n"
265
 
1274 hidnplayr 266
; TODO: validate checksum
1254 hidnplayr 267
 
1274 hidnplayr 268
; IP Packet TCP Destination Port = local Port
269
; IP Packet SA = Remote IP  OR = 0
270
; IP Packet TCP Source Port = remote Port  OR = 0
1159 hidnplayr 271
 
272
	mov	ebx, net_sockets
273
 
1249 hidnplayr 274
  .socket_loop:
275
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 276
	or	ebx, ebx
1249 hidnplayr 277
	jz	.dump
1159 hidnplayr 278
 
1249 hidnplayr 279
	mov	ax, [edx + TCP_Packet.DestinationPort]
280
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], ax
281
	jne	.socket_loop
1159 hidnplayr 282
 
1249 hidnplayr 283
	mov	eax, [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
284
	cmp	eax, esi
285
	je	@f
286
	test	eax, eax
287
	jne	.socket_loop
288
       @@:
1159 hidnplayr 289
 
1249 hidnplayr 290
	mov	ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
291
	cmp	[edx + TCP_Packet.SourcePort] , ax
1274 hidnplayr 292
	je	.found_socket
1249 hidnplayr 293
	test	ax, ax
1254 hidnplayr 294
	jnz	.socket_loop
1274 hidnplayr 295
  .found_socket:
1254 hidnplayr 296
       DEBUGF 1,"Found valid socket for packet\n"
297
 
1257 hidnplayr 298
	inc	[TCP_PACKETS_RX]
299
 
1274 hidnplayr 300
	add	ebx, SOCKET_head.lock
1249 hidnplayr 301
	call	wait_mutex
1274 hidnplayr 302
	sub	ebx, SOCKET_head.lock
1159 hidnplayr 303
 
1274 hidnplayr 304
;-------------------------------
1249 hidnplayr 305
; ebx is pointer to socket
306
; ecx is size of tcp packet
307
; edx is pointer to tcp packet
1159 hidnplayr 308
 
1274 hidnplayr 309
; calculate header length
310
	movzx	eax, [edx + TCP_Packet.DataOffset]
311
	and	eax, 11110000b
312
	shr	eax, 2
313
       DEBUGF 1,"TCP header size: %u\n", eax
314
	sub	ecx, eax
315
 
316
;-------------------------------
317
; ecx is size of tcp data
318
 
319
; as a Packet has been received, update the TCB timer
1254 hidnplayr 320
	mov	[ebx +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], TCP_SOCKET_TTL
1159 hidnplayr 321
 
1274 hidnplayr 322
; If the received Packet has an ACK bit set, remove any Packets in the resend queue that this received Packet acknowledges
1249 hidnplayr 323
	test	[edx + TCP_Packet.Flags], TH_ACK
1274 hidnplayr 324
	jz	.no_ack 				 ; No ACK, so no data yet
1159 hidnplayr 325
 
1274 hidnplayr 326
; Calculate ACK number
327
	mov	edi, [edx + TCP_Packet.AckNumber]
328
	bswap	edi
329
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number], edi
330
       DEBUGF 1,"Setting last_ack_number to %u\n", edi
331
	bswap	edi
1159 hidnplayr 332
 
1274 hidnplayr 333
; Dequeue all acknowledged packets
334
	cmp	[TCP_OUT_QUEUE], 0		; first, check if any packets are queued at all
335
	je	.no_ack
1254 hidnplayr 336
 
337
	push	ecx
338
       DEBUGF 1,"Removing all queued packets with smaller ACK\n"
1249 hidnplayr 339
	mov	ecx, TCP_QUEUE_SIZE
340
	mov	esi, TCP_OUT_QUEUE+4
341
  .loop:
342
	cmp	[esi + tcp_out_queue_entry.data_ptr], 0
1254 hidnplayr 343
	je	.maybe_next
1274 hidnplayr 344
 
345
	cmp	[esi + tcp_out_queue_entry.socket], ebx
346
	jne	.maybe_next
347
 
348
	cmp	[esi + tcp_out_queue_entry.seq_num], edi
1249 hidnplayr 349
	jg	.maybe_next
1159 hidnplayr 350
 
1254 hidnplayr 351
       DEBUGF 1,"Removing a queued packet\n"
352
 
1249 hidnplayr 353
	push	[esi + tcp_out_queue_entry.data_ptr]
354
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
355
	dec	[TCP_OUT_QUEUE]
356
	call	kernel_free
1159 hidnplayr 357
 
1249 hidnplayr 358
  .maybe_next:
359
	add	esi, tcp_out_queue_entry.size
360
	loop	.loop
1274 hidnplayr 361
	pop	ecx
1254 hidnplayr 362
 
1274 hidnplayr 363
 
364
; Now call the correct handler, depending on the socket state
365
  .no_ack:
1254 hidnplayr 366
	mov	eax, [ebx +  SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state]
367
 
1249 hidnplayr 368
	cmp	eax, TCB_LISTEN
1254 hidnplayr 369
	jb	.dump
1249 hidnplayr 370
	cmp	eax, TCB_CLOSED
1254 hidnplayr 371
	ja	.dump
1159 hidnplayr 372
 
1254 hidnplayr 373
	dec	eax
1249 hidnplayr 374
	shl	eax, 2
1254 hidnplayr 375
	add	eax, stateHandler
1159 hidnplayr 376
 
1254 hidnplayr 377
	call	dword[eax]
1159 hidnplayr 378
 
1249 hidnplayr 379
  .dump:
380
	DEBUGF 1,"Dumping TCP packet\n"
1196 hidnplayr 381
	call	kernel_free
382
	add	esp, 4 ; pop (balance stack)
1159 hidnplayr 383
 
1249 hidnplayr 384
	ret
1196 hidnplayr 385
 
386
 
387
 
388
;-----------------------------------------------------------------
389
;
1274 hidnplayr 390
; TCP_send  (Assumes socket mutex set)
1196 hidnplayr 391
;
1249 hidnplayr 392
; IN: eax = socket pointer
1274 hidnplayr 393
;      bl = flags
394
;      ecx = number of bytes to send, may be set to 0
395
;      esi = pointer to data
1249 hidnplayr 396
;
1196 hidnplayr 397
;-----------------------------------------------------------------
1249 hidnplayr 398
align 4
1274 hidnplayr 399
TCP_send:
1196 hidnplayr 400
 
1274 hidnplayr 401
	DEBUGF 1,"Creating TCP packet, socket: %x, flags: %x\n",eax, bl
1159 hidnplayr 402
 
1249 hidnplayr 403
	mov	di , IP_PROTO_TCP
1274 hidnplayr 404
	add	ecx, TCP_Packet.Data
1159 hidnplayr 405
 
1274 hidnplayr 406
	push	bx eax esi
1249 hidnplayr 407
; Create an IPv4 Packet of the correct size
408
	mov	ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
409
	mov	eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
1159 hidnplayr 410
 
1249 hidnplayr 411
	call	IPv4_create_packet
412
	cmp	edi, -1
413
	je	.fail
1159 hidnplayr 414
 
1274 hidnplayr 415
; If there is any data, copy it first
1249 hidnplayr 416
	pop	esi
1274 hidnplayr 417
	push	edi
418
	add	edi, TCP_Packet.Data
419
	sub	ecx, TCP_Packet.Data
1159 hidnplayr 420
 
1249 hidnplayr 421
	shr	ecx, 1
422
	jnc	.nb
423
	movsb
424
.nb:	shr	ecx, 1
425
	jnc	.nw
426
	movsw
1274 hidnplayr 427
.nw:	test	ecx, ecx
428
	jz	.nd
429
	rep	movsd
430
.nd:
431
	pop	edi
1159 hidnplayr 432
 
1249 hidnplayr 433
; Fill in the TCP header
434
	pop	esi
1159 hidnplayr 435
 
1274 hidnplayr 436
; fill in tcp sequence number
1249 hidnplayr 437
	push	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
438
	pop	[edi + TCP_Packet.SequenceNumber]
1274 hidnplayr 439
	inc_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT) ;;;;;;;;
1159 hidnplayr 440
 
1274 hidnplayr 441
; Fill in local and remote ports
442
	push	dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
1249 hidnplayr 443
	pop	dword [edi + TCP_Packet.SourcePort]
1159 hidnplayr 444
 
1274 hidnplayr 445
; Acknumber
1254 hidnplayr 446
	push	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
1249 hidnplayr 447
	pop	[edi + TCP_Packet.AckNumber]
1159 hidnplayr 448
 
1274 hidnplayr 449
; Fill  in other tcp options
1249 hidnplayr 450
	pop	cx
451
	mov	[edi + TCP_Packet.Flags], cl
452
	mov	[edi + TCP_Packet.Window], 0x0005	   ; 1280 bytes
453
	mov	[edi + TCP_Packet.UrgentPointer], 0
454
	mov	[edi + TCP_Packet.DataOffset], 0x50
1254 hidnplayr 455
	mov	[edi + TCP_Packet.Checksum], 0
1159 hidnplayr 456
 
1274 hidnplayr 457
; Push pointer to and size of total packet (needed for send procedure)
1254 hidnplayr 458
	push	edx eax
1159 hidnplayr 459
 
1274 hidnplayr 460
; push socket number (for TCP_add_to_queue)
461
	push	esi
1159 hidnplayr 462
 
1274 hidnplayr 463
; Now, calculate the checksum                  ; TODO: calculate correct checksum for packets with data
464
	pushw	TCP_Packet.Data shl 8
1254 hidnplayr 465
	pushw	IP_PROTO_TCP shl 8
1257 hidnplayr 466
	pushd	[edi-4] ; destination address  ; TODO: fix this, IPv4 packet could have options..
1254 hidnplayr 467
	pushd	[edi-8] ; source address
468
 
1249 hidnplayr 469
	xor	edx, edx
1274 hidnplayr 470
	mov	ecx, TCP_Packet.Data
1254 hidnplayr 471
	mov	esi, edi
472
	call	checksum_1
1249 hidnplayr 473
	mov	ecx, 12
474
	mov	esi, esp
475
	call	checksum_1
476
	add	esp, 12 				   ; remove the pseudoheader from stack
1254 hidnplayr 477
; and store it in TCP header
1249 hidnplayr 478
	call	checksum_2
479
	mov	[edi + TCP_Packet.Checksum], dx
1159 hidnplayr 480
 
1274 hidnplayr 481
; At last send the packet!
1249 hidnplayr 482
	DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
1274 hidnplayr 483
	mov	edx, [edi + TCP_Packet.SequenceNumber]
484
	bswap	edx
1254 hidnplayr 485
	mov	esi, [ebx + ETH_DEVICE.transmit]
1274 hidnplayr 486
	pop	edi
487
	jmp	TCP_queue
1159 hidnplayr 488
 
1249 hidnplayr 489
  .fail:
1254 hidnplayr 490
	add	esp, 2+4
1274 hidnplayr 491
	or	eax, -1
1249 hidnplayr 492
	ret
1159 hidnplayr 493
 
494
 
1274 hidnplayr 495
;-----------------------------------------------------------------
496
;
497
;  Queue a TCP packet for sending
498
;
499
;  IN:  [esp] pointer to buffer
500
;       [esp + 4] size of buffer
501
;       ebx = driver struct
502
;       esi = sender proc
503
;       edx = sequence number of this packet in normal byte order
504
;       edi = socket number
505
;  OUT: /
506
;
507
;-----------------------------------------------------------------
508
align 4
509
TCP_queue:
1159 hidnplayr 510
 
1274 hidnplayr 511
	bswap	edx
512
	DEBUGF 1,"Adding packet to TCP queue, buffer: %x, size: %u, driver: %x, acknum: %u\n", [esp], [esp+4], ebx, edx
513
	bswap	edx
1159 hidnplayr 514
 
1274 hidnplayr 515
	cmp	[TCP_OUT_QUEUE], TCP_QUEUE_SIZE
516
	jge	.full
1159 hidnplayr 517
 
1274 hidnplayr 518
	mov	ecx, TCP_QUEUE_SIZE
519
	mov	eax, TCP_OUT_QUEUE+4
520
 
521
  .loop:
522
	cmp	[eax + tcp_out_queue_entry.data_ptr], 0
523
	je	.found_it
524
	add	eax, tcp_out_queue_entry.size
525
	loop	.loop
526
 
527
  .full:			; silently discard the packet
528
	DEBUGF 1,"TCP queue is full!\n"
529
 
530
	call	kernel_free
531
	add	esp, 4
532
 
533
	ret
534
 
535
  .found_it:			; eax points to empty queue entry
536
 
537
	pop	[eax + tcp_out_queue_entry.data_ptr]
538
	pop	[eax + tcp_out_queue_entry.data_size]
539
	mov	[eax + tcp_out_queue_entry.ttl], 1			; send immediately
540
	mov	[eax + tcp_out_queue_entry.retries], TCP_RETRIES
541
	mov	[eax + tcp_out_queue_entry.owner], ebx
542
	mov	[eax + tcp_out_queue_entry.sendproc], esi
543
	mov	[eax + tcp_out_queue_entry.seq_num], edx
544
	mov	[eax + tcp_out_queue_entry.socket], edi
545
 
546
	inc	[TCP_OUT_QUEUE]
547
 
548
	sub	eax, TCP_OUT_QUEUE+4
549
	DEBUGF 1,"Added to queue in pos %u\n", eax
550
 
551
	ret
552
 
553
 
554
 
555
 
556
 
1255 hidnplayr 557
;---------- TCB state handlers start here
558
 
559
 
560
 
561
 
1249 hidnplayr 562
align 4
563
stateTCB_LISTEN:
1254 hidnplayr 564
 
565
	DEBUGF	1,"TCBStateHandler: Listen\n"
566
 
1274 hidnplayr 567
	test	[edx + TCP_Packet.Flags], TH_SYN	; SYN packet? => send syn+ack, open new socket and set connection to established
1159 hidnplayr 568
	jz	.exit
1274 hidnplayr 569
; Exit if backlog queue is full
1256 clevermous 570
	mov	ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
571
	cmp	ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
572
	jae	.exit
1274 hidnplayr 573
; Allocate new socket
574
	push	esi edi
1256 clevermous 575
	call	net_socket_alloc
576
	test	eax, eax
1274 hidnplayr 577
	jz	.fail
578
; Copy structure from current socket to new, including lock
579
	lea	esi, [ebx + SOCKET_head.PID]		; yes, PID must also be copied
1256 clevermous 580
	lea	edi, [eax + SOCKET_head.PID]
581
	mov	ecx, ((SOCKET_head.end - SOCKET_head.PID) + IPv4_SOCKET.end + TCP_SOCKET.end + 3)/4
582
	rep	movsd
583
	pop	edi esi
1274 hidnplayr 584
; Push pointer to new socket to queue
1256 clevermous 585
	movzx	ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
586
	inc	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
587
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end + ecx*4], eax
1159 hidnplayr 588
 
1256 clevermous 589
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi ; IP source address
590
	mov	cx, [edx + TCP_Packet.SourcePort]
591
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], cx
592
	mov	ecx, [edx + TCP_Packet.SequenceNumber]
593
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], ecx
594
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], ecx
595
	lea	esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
1249 hidnplayr 596
	inc_INET esi ; RCV.NXT
1256 clevermous 597
	mov	ecx, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS]
598
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], ecx
1159 hidnplayr 599
 
1254 hidnplayr 600
	mov	[ebx + SOCKET_head.lock], 0
601
 
1256 clevermous 602
	push	eax
1274 hidnplayr 603
; Now construct the response
1159 hidnplayr 604
	mov	bl, TH_SYN + TH_ACK
1274 hidnplayr 605
	xor	ecx, ecx
606
	call	TCP_send
1256 clevermous 607
	pop	eax
1159 hidnplayr 608
 
1274 hidnplayr 609
	mov	[eax + SOCKET_head.lock], 0
1256 clevermous 610
	mov	[eax +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
611
	call	notify_network_event
612
	ret
1159 hidnplayr 613
 
614
  .exit:
1254 hidnplayr 615
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 616
	ret
617
 
1274 hidnplayr 618
  .fail:
619
	add	esp, 8
620
	mov	[ebx + SOCKET_head.lock], 0
621
	ret
1159 hidnplayr 622
 
1274 hidnplayr 623
 
1249 hidnplayr 624
align 4
625
stateTCB_SYN_SENT:
1254 hidnplayr 626
 
627
	DEBUGF	1,"TCBStateHandler: Syn_Sent\n"
628
 
1159 hidnplayr 629
	; We are awaiting an ACK to our SYN, with a SYM
630
	; Look at control flags - expecting an ACK
631
 
1249 hidnplayr 632
	mov	al, [edx + TCP_Packet.Flags]
1274 hidnplayr 633
 
634
	test	al, TH_RST
635
	jnz	.reset			; jump if RST bit set
636
 
637
	push	[edx + TCP_Packet.SequenceNumber]				     ;;
638
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]	     ;;
639
	inc_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT)      ;;
640
 
641
 
642
	push	[edx + TCP_Packet.AckNumber]					    ;;;;;;
643
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]	    ;;;;;;
644
 
1159 hidnplayr 645
	and	al, TH_SYN + TH_ACK
1274 hidnplayr 646
	jz	.exit			; jump if none of the following is set: RST, SYN, ACK
1159 hidnplayr 647
 
1274 hidnplayr 648
	test	al, TH_ACK
649
	jz     .onlysyn 		; jump if only SYN bit is set
1159 hidnplayr 650
 
1274 hidnplayr 651
	; If we arrived here, SYN and ACK are set
1159 hidnplayr 652
 
1254 hidnplayr 653
	mov	[ebx +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
1274 hidnplayr 654
	pushw	TH_ACK
1159 hidnplayr 655
 
1274 hidnplayr 656
  .send:	; Send an ACK
1254 hidnplayr 657
	mov	eax, ebx
1274 hidnplayr 658
	pop	bx
659
	push	eax
660
	xor	ecx, ecx
661
	call	TCP_send
1159 hidnplayr 662
	pop	ebx
663
 
664
  .exit:
1254 hidnplayr 665
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 666
	ret
667
 
1274 hidnplayr 668
  .reset:
669
	; TODO: ....
1159 hidnplayr 670
 
1274 hidnplayr 671
	; remove all queued TCP packets for this connection !
1249 hidnplayr 672
 
1274 hidnplayr 673
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSED
674
	mov	[ebx + SOCKET_head.lock], 0
675
	ret
676
 
677
  .onlysyn:
678
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
679
	pushw	TH_SYN + TH_ACK
680
	jmp	.send
681
 
682
 
683
 
1249 hidnplayr 684
align 4
685
stateTCB_SYN_RECEIVED:
1254 hidnplayr 686
 
687
	DEBUGF	1,"TCBStateHandler: Syn_received\n"
688
 
1274 hidnplayr 689
	test	[edx + TCP_Packet.Flags], TH_RST	; reset connection? => LISTEN
1159 hidnplayr 690
	jz	.check_ack
691
 
1274 hidnplayr 692
	push	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort]
693
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
694
	push	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP]
695
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
1159 hidnplayr 696
 
1254 hidnplayr 697
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
1159 hidnplayr 698
	jmp	.exit
699
 
700
  .check_ack:
1274 hidnplayr 701
	test	[edx + TCP_Packet.Flags], TH_ACK	; ACK? => connection established!
1159 hidnplayr 702
	jz	.exit
703
 
1254 hidnplayr 704
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
1256 clevermous 705
	mov	eax, ebx
706
	call	notify_network_event
1159 hidnplayr 707
 
708
  .exit:
1254 hidnplayr 709
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 710
	ret
711
 
712
 
1249 hidnplayr 713
 
714
align 4
715
stateTCB_ESTABLISHED:
1254 hidnplayr 716
 
717
	DEBUGF	1,"TCBStateHandler: Established\n"
718
 
1255 hidnplayr 719
	mov	eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
1274 hidnplayr 720
	bswap	eax
721
	DEBUGF	1,"RCV_NXT is set to:%u\n", eax
722
	bswap	eax
1255 hidnplayr 723
	cmp	eax, [edx + TCP_Packet.SequenceNumber]
724
	jne	.exit
725
 
1274 hidnplayr 726
; Calculate next sequencenumber
727
	test	ecx, ecx
728
	jnz	@f
729
	inc	ecx
730
       @@:
731
	add_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT)
1159 hidnplayr 732
 
1249 hidnplayr 733
	test	[edx + TCP_Packet.Flags], TH_FIN
1274 hidnplayr 734
	jnz	.fin
1159 hidnplayr 735
 
736
  .check_ack:
1249 hidnplayr 737
	test	[edx + TCP_Packet.Flags], TH_ACK
1159 hidnplayr 738
	jz	.exit
739
 
1254 hidnplayr 740
	DEBUGF	1,"Received ACK\n"
1274 hidnplayr 741
; First, look at the incoming window. If this is less than or equal to 1024,
742
; Set the socket window timer to 1. This will stop an additional Packets being queued.
743
; ** I may need to tweak this value, since I do not know how many Packets are already queued
1255 hidnplayr 744
	push	ecx
1249 hidnplayr 745
	mov	cx, [edx + TCP_Packet.Window]
1159 hidnplayr 746
	xchg	cl, ch
747
	cmp	cx, 1024
748
	ja	@f
1249 hidnplayr 749
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 1
1255 hidnplayr 750
      @@:
751
	pop	ecx
1159 hidnplayr 752
 
1274 hidnplayr 753
; Now, see if we received any data
1255 hidnplayr 754
	test	ecx, ecx
1274 hidnplayr 755
	jz	.ack
1159 hidnplayr 756
 
1274 hidnplayr 757
	DEBUGF	1,"Got %u bytes data!\n", ecx
758
; calculate header length
759
	movzx	eax, [edx + TCP_Packet.DataOffset]
760
	and	eax, 11110000b
761
	shr	eax, 2
762
       DEBUGF 1,"TCP header size: %u\n", eax
763
	add	edx, eax
764
	add	esp, 4
765
	pop	esi
766
	add	esp, 4
1249 hidnplayr 767
	sub	edx, esi
768
	mov	edi, edx
1255 hidnplayr 769
	mov	eax, ebx
1274 hidnplayr 770
	jmp	socket_internal_receiver	; Place the data from packet into socket
1159 hidnplayr 771
 
772
  .ack:
1254 hidnplayr 773
	mov	eax, ebx
1159 hidnplayr 774
	mov	bl, TH_ACK
1274 hidnplayr 775
	push	eax
776
	xor	ecx, ecx
777
	call	TCP_send		    ; send the ack
778
	pop	ebx
1159 hidnplayr 779
  .exit:
1254 hidnplayr 780
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 781
	ret
782
 
1274 hidnplayr 783
  .fin:
784
; Remove all resend entries from the queue
785
	mov	ecx, TCP_QUEUE_SIZE
786
	mov	esi, TCP_OUT_QUEUE+4
1159 hidnplayr 787
 
1274 hidnplayr 788
  .removeloop:
789
	cmp	[esi + tcp_out_queue_entry.data_ptr], 0
790
	je	.maybe_next
1249 hidnplayr 791
 
1274 hidnplayr 792
	; TODO: check if the packets belong to the same tcp connection !
793
 
794
       DEBUGF 1,"Removing a queued packet\n"
795
 
796
	push	[esi + tcp_out_queue_entry.data_ptr]
797
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
798
	dec	[TCP_OUT_QUEUE]
799
	call	kernel_free
800
 
801
  .maybe_next:
802
	add	esi, tcp_out_queue_entry.size
803
	loop	.removeloop
804
 
805
; Send an ACK to that fin, and enter closewait state
806
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT
807
	jmp	.check_ack
808
 
809
 
810
 
1249 hidnplayr 811
align 4
812
stateTCB_FIN_WAIT_1:
1254 hidnplayr 813
 
814
	DEBUGF	1,"TCBStateHandler: Fin_wait_1\n"
815
 
1159 hidnplayr 816
	; We can either receive an ACK of a fin, or a fin
1249 hidnplayr 817
	mov	al, [edx + TCP_Packet.Flags]
1159 hidnplayr 818
	and	al, TH_FIN + TH_ACK
819
 
820
	cmp	al, TH_ACK
821
	jne	@f
822
 
823
	; It was an ACK
1254 hidnplayr 824
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_2
1159 hidnplayr 825
	jmp	.exit
826
 
1254 hidnplayr 827
    @@: mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSING
1159 hidnplayr 828
	cmp	al, TH_FIN
829
	je	@f
1254 hidnplayr 830
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
1159 hidnplayr 831
 
1274 hidnplayr 832
    @@:
1254 hidnplayr 833
 
1274 hidnplayr 834
;        lea     esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
835
;        inc_INET esi
836
 
1159 hidnplayr 837
	; Send an ACK
1254 hidnplayr 838
	mov	eax, ebx
1159 hidnplayr 839
	mov	bl, TH_ACK
1274 hidnplayr 840
	push	eax
841
	xor	ecx, ecx
842
	call	TCP_send
843
	pop	ebx
1159 hidnplayr 844
 
845
  .exit:
1254 hidnplayr 846
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 847
	ret
848
 
849
 
1249 hidnplayr 850
 
851
align 4
852
stateTCB_FIN_WAIT_2:
1254 hidnplayr 853
 
854
	DEBUGF	1,"TCBStateHandler: Fin_wait_2\n"
855
 
1249 hidnplayr 856
	test	[edx + TCP_Packet.Flags], TH_FIN
1159 hidnplayr 857
	jz	.exit
858
 
859
	; Change state, as we have a fin
1254 hidnplayr 860
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
1159 hidnplayr 861
 
1249 hidnplayr 862
	lea	esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
863
	inc_INET esi
1159 hidnplayr 864
 
1254 hidnplayr 865
	mov	[ebx + SOCKET_head.lock], 0
866
 
1159 hidnplayr 867
	; Send an ACK
1254 hidnplayr 868
	mov	eax, ebx
1159 hidnplayr 869
	mov	bl, TH_ACK
1274 hidnplayr 870
	push	eax
871
	xor	ecx, ecx
872
	call	TCP_send
873
	pop	ebx
1159 hidnplayr 874
 
875
  .exit:
1254 hidnplayr 876
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 877
	ret
878
 
879
 
1249 hidnplayr 880
 
881
align 4
882
stateTCB_CLOSE_WAIT:
1254 hidnplayr 883
 
884
	DEBUGF	1,"TCBStateHandler: close_wait\n"
1159 hidnplayr 885
	; Intentionally left empty
886
	; socket_close_tcp handles this
1254 hidnplayr 887
 
888
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 889
	ret
890
 
891
 
1249 hidnplayr 892
 
893
align 4
894
stateTCB_CLOSING:
1254 hidnplayr 895
 
896
	DEBUGF	1,"TCBStateHandler: closingn\n"
897
 
1159 hidnplayr 898
	; We can either receive an ACK of a fin, or a fin
1249 hidnplayr 899
	test	[edx + TCP_Packet.Flags], TH_ACK
1159 hidnplayr 900
	jz	.exit
901
 
1254 hidnplayr 902
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
1159 hidnplayr 903
 
904
  .exit:
1254 hidnplayr 905
 
906
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 907
	ret
908
 
909
 
1249 hidnplayr 910
align 4
911
stateTCB_LAST_ACK:
1254 hidnplayr 912
 
913
	DEBUGF	1,"TCBStateHandler: last_ackn\n"
914
 
1159 hidnplayr 915
	; Look at control flags - expecting an ACK
1249 hidnplayr 916
	test	[edx + TCP_Packet.Flags], TH_ACK
1159 hidnplayr 917
	jz	.exit
918
 
1254 hidnplayr 919
	mov	[ebx + SOCKET_head.lock], 0
920
 
1159 hidnplayr 921
	; delete the socket
922
	stdcall net_socket_free, ebx
923
 
924
  .exit:
925
	ret
926
 
927
 
1249 hidnplayr 928
align 4
929
stateTCB_TIME_WAIT:
1254 hidnplayr 930
 
931
	DEBUGF	1,"TCBStateHandler: time_wait\n"
932
 
933
	mov	[ebx + SOCKET_head.lock], 0
934
 
1159 hidnplayr 935
	ret
936
 
937
 
1249 hidnplayr 938
align 4
939
stateTCB_CLOSED:
1254 hidnplayr 940
 
941
	DEBUGF	1,"TCBStateHandler: closed\n"
942
 
943
	mov	[ebx + SOCKET_head.lock], 0
944
 
1159 hidnplayr 945
	ret
946
 
947
 
948
 
1254 hidnplayr 949
;---------------------------------------------------------------------------
950
;
951
; TCP_API
952
;
953
; This function is called by system function 75
954
;
955
; IN:  subfunction number in bl
956
;      device number in bh
957
;      ecx, edx, .. depends on subfunction
958
;
959
; OUT:
960
;
961
;---------------------------------------------------------------------------
962
align 4
963
TCP_API:
964
 
965
	movzx	eax, bh
966
	shl	eax, 2
967
 
968
	test	bl, bl
969
	jz	.packets_tx	; 0
970
	dec	bl
971
	jz	.packets_rx	; 1
972
 
973
.error:
974
	mov	eax, -1
975
	ret
976
 
977
.packets_tx:
978
	add	eax, TCP_PACKETS_TX
979
	mov	eax, [eax]
980
	ret
981
 
982
.packets_rx:
983
	add	eax, TCP_PACKETS_RX
984
	mov	eax, [eax]
985
	ret