Subversion Repositories Kolibri OS

Rev

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