Subversion Repositories Kolibri OS

Rev

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