Subversion Repositories Kolibri OS

Rev

Rev 1255 | 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: 1256 $
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]
1256 clevermous 363
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number], eax
1254 hidnplayr 364
	;---------
365
 
1249 hidnplayr 366
	cmp	[TCP_OUT_QUEUE], 0
367
	je	.call_handler
1254 hidnplayr 368
	push	ecx
1159 hidnplayr 369
 
1254 hidnplayr 370
       DEBUGF 1,"Removing all queued packets with smaller ACK\n"
371
 
1249 hidnplayr 372
	mov	ecx, TCP_QUEUE_SIZE
373
	mov	esi, TCP_OUT_QUEUE+4
1159 hidnplayr 374
 
1249 hidnplayr 375
  .loop:
376
	cmp	[esi + tcp_out_queue_entry.data_ptr], 0
1254 hidnplayr 377
	je	.maybe_next
378
	cmp	[esi + tcp_out_queue_entry.seq_num], eax
1249 hidnplayr 379
	jg	.maybe_next
1254 hidnplayr 380
	; TODO: check if the packets belong to the same tcp connection !
1159 hidnplayr 381
 
1254 hidnplayr 382
       DEBUGF 1,"Removing a queued packet\n"
383
 
1249 hidnplayr 384
	push	[esi + tcp_out_queue_entry.data_ptr]
385
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
386
	dec	[TCP_OUT_QUEUE]
387
	call	kernel_free
1159 hidnplayr 388
 
1249 hidnplayr 389
  .maybe_next:
390
	add	esi, tcp_out_queue_entry.size
391
	loop	.loop
1254 hidnplayr 392
 
1249 hidnplayr 393
	pop	ecx
394
  .call_handler:
395
	; Call handler for given TCB state
1254 hidnplayr 396
	mov	eax, [ebx +  SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state]
397
	DEBUGF 1,"Socket state: %u\n", eax
398
 
1249 hidnplayr 399
	cmp	eax, TCB_LISTEN
1254 hidnplayr 400
	jb	.dump
1249 hidnplayr 401
	cmp	eax, TCB_CLOSED
1254 hidnplayr 402
	ja	.dump
1159 hidnplayr 403
 
1254 hidnplayr 404
	dec	eax
1249 hidnplayr 405
	shl	eax, 2
1254 hidnplayr 406
	add	eax, stateHandler
1159 hidnplayr 407
 
1254 hidnplayr 408
	call	dword[eax]
1159 hidnplayr 409
 
1249 hidnplayr 410
  .dump:
411
	DEBUGF 1,"Dumping TCP packet\n"
1196 hidnplayr 412
	call	kernel_free
413
	add	esp, 4 ; pop (balance stack)
1159 hidnplayr 414
 
1249 hidnplayr 415
	ret
1196 hidnplayr 416
 
417
 
418
 
419
;-----------------------------------------------------------------
420
;
1249 hidnplayr 421
; TCP_socket_send
1196 hidnplayr 422
;
1249 hidnplayr 423
; IN: eax = socket pointer
424
;     ecx = number of bytes to send
425
;     esi = pointer to data
426
;
1196 hidnplayr 427
;-----------------------------------------------------------------
428
 
1249 hidnplayr 429
align 4
430
TCP_socket_send:
1196 hidnplayr 431
 
1249 hidnplayr 432
	DEBUGF 1,"Creating TCP Packet\n"
1159 hidnplayr 433
 
1249 hidnplayr 434
	mov	di , IP_PROTO_TCP
1159 hidnplayr 435
 
1249 hidnplayr 436
; Create an IPv4 Packet of the correct size
437
	push	eax
438
	mov	ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
439
	mov	eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
1159 hidnplayr 440
 
1249 hidnplayr 441
; meanwhile, create the pseudoheader in stack,
442
; (now that we still have all the variables that are needed.)
443
	push	cx
444
	push	di
1159 hidnplayr 445
	push	eax
1249 hidnplayr 446
	push	ebx
1159 hidnplayr 447
 
448
 
1249 hidnplayr 449
	push	ecx esi eax		; save some variables for later
1254 hidnplayr 450
	add	ecx, TCP_Packet.Options
1249 hidnplayr 451
	call	IPv4_create_packet
452
	cmp	edi, -1
453
	je	.fail
1159 hidnplayr 454
 
1249 hidnplayr 455
	pop	esi
1159 hidnplayr 456
 
1249 hidnplayr 457
; Now add the TCP header to the IPv4 packet
1159 hidnplayr 458
 
1249 hidnplayr 459
	push	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
460
	pop	[edi + TCP_Packet.SequenceNumber]
1159 hidnplayr 461
 
1249 hidnplayr 462
	push	dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
463
	pop	dword [edi + TCP_Packet.SourcePort]
1159 hidnplayr 464
 
465
 
1249 hidnplayr 466
	push	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
467
	pop	[edi + TCP_Packet.AckNumber]
1159 hidnplayr 468
 
1249 hidnplayr 469
	mov	al, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.flags]
470
	mov	[edi + TCP_Packet.Flags], al
1159 hidnplayr 471
 
1254 hidnplayr 472
	mov	[edi + TCP_Packet.Window], 0x0005	   ; 1280 bytes
1249 hidnplayr 473
	mov	[edi + TCP_Packet.UrgentPointer], 0
474
	mov	[edi + TCP_Packet.DataOffset], 0x50
475
	mov	[edi + TCP_Packet.Checksum], 0
1159 hidnplayr 476
 
1249 hidnplayr 477
; Copy the data
478
	mov	esi, [esp]
479
	mov	ecx, [esp+4]
1254 hidnplayr 480
	add	edi, TCP_Packet.Options
1159 hidnplayr 481
 
1249 hidnplayr 482
	shr	ecx, 1
483
	jnc	.nb
484
	movsb
485
.nb:	shr	ecx, 1
486
	jnc	.nw
487
	movsw
488
.nw:	rep movsd
1159 hidnplayr 489
 
1249 hidnplayr 490
; Now, calculate the checksum for pseudoheader
491
	xor	edx, edx
492
	mov	ecx, 12
493
	mov	esi, esp
494
	call	checksum_1
495
	add	esp, 12 				   ; remove the pseudoheader from stack
496
; And that of the data
497
	pop	esi
498
	pop	ecx
499
	call	checksum_1
500
; Now create the final checksum and store it in TCP header
501
	call	checksum_2
502
	mov	[edi + TCP_Packet.Checksum], dx
1159 hidnplayr 503
 
1249 hidnplayr 504
; And now, send it!
505
	DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
1254 hidnplayr 506
	lea	esi, [ebx+ETH_DEVICE.transmit]
1249 hidnplayr 507
	mov	edx, [edi + TCP_Packet.AckNumber]
508
	jmp	TCP_add_to_queue
1159 hidnplayr 509
 
1249 hidnplayr 510
  .fail:
1254 hidnplayr 511
	add	esp, 12+12+4
1159 hidnplayr 512
	ret
513
 
514
 
515
 
516
 
517
 
1249 hidnplayr 518
;-----------------------------------------------------------------
1159 hidnplayr 519
;
1249 hidnplayr 520
; TCP_send_ack
1159 hidnplayr 521
;
1249 hidnplayr 522
; IN: eax = socket pointer
523
;      bl = flags
1159 hidnplayr 524
;
1249 hidnplayr 525
;-----------------------------------------------------------------
1159 hidnplayr 526
 
1249 hidnplayr 527
align 4
528
TCP_send_ack:
1159 hidnplayr 529
 
1254 hidnplayr 530
	DEBUGF 1,"Creating TCP ACK, socket: %x, flags: %x\n",eax, bl
1159 hidnplayr 531
 
1249 hidnplayr 532
	mov	di , IP_PROTO_TCP
1254 hidnplayr 533
	mov	ecx, TCP_Packet.Options
1159 hidnplayr 534
 
1249 hidnplayr 535
	push	bx eax
1159 hidnplayr 536
 
1249 hidnplayr 537
; Create an IPv4 Packet of the correct size
1254 hidnplayr 538
 
1249 hidnplayr 539
	mov	ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
540
	mov	eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
1159 hidnplayr 541
 
1249 hidnplayr 542
	call	IPv4_create_packet
543
	cmp	edi, -1
544
	je	.fail
1159 hidnplayr 545
 
1249 hidnplayr 546
; Fill in the TCP header
547
	pop	esi
1159 hidnplayr 548
 
1249 hidnplayr 549
	push	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
550
	pop	[edi + TCP_Packet.SequenceNumber]
1159 hidnplayr 551
 
1254 hidnplayr 552
	push	dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort] ; both ports at once
1249 hidnplayr 553
	pop	dword [edi + TCP_Packet.SourcePort]
1159 hidnplayr 554
 
1254 hidnplayr 555
	push	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
1249 hidnplayr 556
	pop	[edi + TCP_Packet.AckNumber]
1159 hidnplayr 557
 
1249 hidnplayr 558
	pop	cx
559
	mov	[edi + TCP_Packet.Flags], cl
560
	mov	[edi + TCP_Packet.Window], 0x0005	   ; 1280 bytes
561
	mov	[edi + TCP_Packet.UrgentPointer], 0
562
	mov	[edi + TCP_Packet.DataOffset], 0x50
1254 hidnplayr 563
	mov	[edi + TCP_Packet.Checksum], 0
1159 hidnplayr 564
 
1254 hidnplayr 565
	push	edx eax
1159 hidnplayr 566
 
1255 hidnplayr 567
;        lea     esi, [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
568
;        inc_INET esi
1159 hidnplayr 569
 
1254 hidnplayr 570
; Now, calculate the checksum
571
	pushw	TCP_Packet.Options shl 8
572
	pushw	IP_PROTO_TCP shl 8
573
	pushd	[edi-4] ; destination address
574
	pushd	[edi-8] ; source address
575
 
1249 hidnplayr 576
	xor	edx, edx
1254 hidnplayr 577
	mov	ecx, TCP_Packet.Options
578
	mov	esi, edi
579
	call	checksum_1
1249 hidnplayr 580
	mov	ecx, 12
581
	mov	esi, esp
582
	call	checksum_1
583
	add	esp, 12 				   ; remove the pseudoheader from stack
1254 hidnplayr 584
; and store it in TCP header
1249 hidnplayr 585
	call	checksum_2
586
	mov	[edi + TCP_Packet.Checksum], dx
1159 hidnplayr 587
 
1254 hidnplayr 588
; And now, send the packet!
1249 hidnplayr 589
	DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
1254 hidnplayr 590
	mov	esi, [ebx + ETH_DEVICE.transmit]
591
	mov	edx, [edi + TCP_Packet.SequenceNumber]
1249 hidnplayr 592
	jmp	TCP_add_to_queue
1159 hidnplayr 593
 
1249 hidnplayr 594
  .fail:
1254 hidnplayr 595
	add	esp, 2+4
1249 hidnplayr 596
	ret
1159 hidnplayr 597
 
598
 
599
 
600
 
601
 
1255 hidnplayr 602
;---------- TCB state handlers start here
603
 
604
 
605
 
606
 
1249 hidnplayr 607
align 4
608
stateTCB_LISTEN:
1254 hidnplayr 609
 
610
	DEBUGF	1,"TCBStateHandler: Listen\n"
611
 
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
1256 clevermous 619
	; Exit if backlog queue is full
620
	mov	ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
621
	cmp	ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
622
	jae	.exit
623
	; Allocate new socket
624
	push	esi
625
	call	net_socket_alloc
626
	pop	esi
627
	test	eax, eax
628
	jz	.exit
629
	; Copy structure from current socket to new, including lock
630
	push	esi edi
631
	lea	esi, [ebx + SOCKET_head.PID]	; yes, PID must also be copied
632
	lea	edi, [eax + SOCKET_head.PID]
633
	mov	ecx, ((SOCKET_head.end - SOCKET_head.PID) + IPv4_SOCKET.end + TCP_SOCKET.end + 3)/4
634
	rep	movsd
635
	pop	edi esi
636
	; Push pointer to new socket to queue
637
	movzx	ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
638
	inc	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
639
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end + ecx*4], eax
1159 hidnplayr 640
 
641
	; We have a SYN. update the socket with this IP Packets details,
642
	; And send a response
643
 
1256 clevermous 644
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi ; IP source address
645
	mov	cx, [edx + TCP_Packet.SourcePort]
646
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], cx
647
	mov	ecx, [edx + TCP_Packet.SequenceNumber]
648
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], ecx
649
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], ecx
650
	lea	esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
1249 hidnplayr 651
	inc_INET esi ; RCV.NXT
1256 clevermous 652
	mov	ecx, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS]
653
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], ecx
1159 hidnplayr 654
 
1256 clevermous 655
	mov	[eax + SOCKET_head.lock], 0
1254 hidnplayr 656
	mov	[ebx + SOCKET_head.lock], 0
657
 
1256 clevermous 658
	push	eax
1249 hidnplayr 659
	; Now construct the response
1159 hidnplayr 660
	mov	bl, TH_SYN + TH_ACK
1249 hidnplayr 661
	call	TCP_send_ack
1256 clevermous 662
	pop	eax
1159 hidnplayr 663
 
1256 clevermous 664
	mov	[eax +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
665
	call	notify_network_event
1159 hidnplayr 666
 
667
	; increment SND.NXT in socket
1256 clevermous 668
	lea	esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
1249 hidnplayr 669
	inc_INET esi
1256 clevermous 670
	ret
1159 hidnplayr 671
 
672
  .exit:
1254 hidnplayr 673
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 674
	ret
675
 
676
 
1249 hidnplayr 677
align 4
678
stateTCB_SYN_SENT:
1254 hidnplayr 679
 
680
	DEBUGF	1,"TCBStateHandler: Syn_Sent\n"
681
 
1159 hidnplayr 682
	; We are awaiting an ACK to our SYN, with a SYM
683
	; Look at control flags - expecting an ACK
684
 
1249 hidnplayr 685
	mov	al, [edx + TCP_Packet.Flags]
1159 hidnplayr 686
	and	al, TH_SYN + TH_ACK
687
	cmp	al, TH_SYN + TH_ACK
688
	je	.syn_ack
689
 
690
	test	al, TH_SYN
691
	jz	.exit
692
 
1254 hidnplayr 693
	mov	[ebx +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
694
	pushd	TH_SYN + TH_ACK
1159 hidnplayr 695
	jmp	.send
696
 
697
  .syn_ack:
1254 hidnplayr 698
	mov	[ebx +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
699
	pushd	TH_ACK
1159 hidnplayr 700
 
701
  .send:
702
	; Store the recv.nxt field
1249 hidnplayr 703
	mov	eax, [edx + TCP_Packet.SequenceNumber]
1254 hidnplayr 704
	mov	[ebx +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], eax
705
	bswap	eax
706
	inc	eax
707
	bswap	eax
708
	mov	[ebx +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax	      ; Update our recv.nxt field
709
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 710
 
1255 hidnplayr 711
	lea	esi, [ebx +  SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
712
	inc_INET esi
713
 
1159 hidnplayr 714
	; Send an ACK
1254 hidnplayr 715
	mov	eax, ebx
1159 hidnplayr 716
	pop	ebx
1249 hidnplayr 717
	call	TCP_send_ack
1159 hidnplayr 718
 
719
  .exit:
1254 hidnplayr 720
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 721
	ret
722
 
723
 
1249 hidnplayr 724
 
725
align 4
726
stateTCB_SYN_RECEIVED:
1254 hidnplayr 727
 
728
	DEBUGF	1,"TCBStateHandler: Syn_received\n"
729
 
1159 hidnplayr 730
	; In this case, we are expecting an ACK Packet
731
	; For now, if the Packet is an ACK, process it,
732
	; If not, ignore it
733
 
1249 hidnplayr 734
	test	[edx + TCP_Packet.Flags], TH_RST
1159 hidnplayr 735
	jz	.check_ack
736
 
1254 hidnplayr 737
  ;      push    [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort]
738
 ;       pop     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
739
  ;      push    [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP]
740
 ;       pop     [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
1159 hidnplayr 741
 
1254 hidnplayr 742
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
1159 hidnplayr 743
	jmp	.exit
744
 
745
  .check_ack:
746
	; Look at control flags - expecting an ACK
1249 hidnplayr 747
	test	[edx + TCP_Packet.Flags], TH_ACK
1159 hidnplayr 748
	jz	.exit
749
 
1254 hidnplayr 750
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
1256 clevermous 751
	mov	eax, ebx
752
	call	notify_network_event
1159 hidnplayr 753
 
754
  .exit:
1254 hidnplayr 755
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 756
	ret
757
 
758
 
1249 hidnplayr 759
 
760
align 4
761
stateTCB_ESTABLISHED:
1254 hidnplayr 762
 
763
 
764
	DEBUGF	1,"TCBStateHandler: Established\n"
765
 
1255 hidnplayr 766
	mov	eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
767
	cmp	eax, [edx + TCP_Packet.SequenceNumber]
768
	jne	.exit
769
 
1159 hidnplayr 770
	; Here we are expecting data, or a request to close
771
	; OR both...
772
 
773
	; Did we receive a FIN or RST?
1249 hidnplayr 774
	test	[edx + TCP_Packet.Flags], TH_FIN
1159 hidnplayr 775
	jz	.check_ack
776
 
777
	; It was a fin or reset.
778
 
1254 hidnplayr 779
;;; TODO: write following code:
1159 hidnplayr 780
	; Remove resend entries from the queue  - I dont want to send any more data
1249 hidnplayr 781
	; Send an ACK to that fin, and enter closewait state
1159 hidnplayr 782
 
783
  .check_ack:
784
	; Check that we received an ACK
1249 hidnplayr 785
	test	[edx + TCP_Packet.Flags], TH_ACK
1159 hidnplayr 786
	jz	.exit
787
 
1254 hidnplayr 788
	DEBUGF	1,"Received ACK\n"
789
 
1159 hidnplayr 790
	; First, look at the incoming window. If this is less than or equal to 1024,
791
	; Set the socket window timer to 1. This will stop an additional Packets being queued.
792
	; ** I may need to tweak this value, since I do not know how many Packets are already queued
1255 hidnplayr 793
	push	ecx
1249 hidnplayr 794
	mov	cx, [edx + TCP_Packet.Window]
1159 hidnplayr 795
	xchg	cl, ch
796
	cmp	cx, 1024
797
	ja	@f
1249 hidnplayr 798
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 1
1255 hidnplayr 799
      @@:
800
	pop	ecx
1159 hidnplayr 801
 
1255 hidnplayr 802
	test	ecx, ecx
803
	jnz	.data			   ; Read data, if any
1159 hidnplayr 804
 
1255 hidnplayr 805
	lea	esi, [ebx +  SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
806
	inc_INET esi
1159 hidnplayr 807
 
808
	; If we had received a fin, we need to ACK it.
1254 hidnplayr 809
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT
1159 hidnplayr 810
	je	.ack
811
	jmp	.exit
812
 
813
  .data:
1255 hidnplayr 814
	     ;;;
815
	lea	esi, [ebx +  SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
816
	add_INET esi
817
 
1254 hidnplayr 818
	DEBUGF	1,"Got data!\n"
1249 hidnplayr 819
	mov	esi, [esp + 4]
820
	sub	edx, esi
821
	mov	edi, edx
1255 hidnplayr 822
	mov	eax, ebx
1249 hidnplayr 823
	call	socket_internal_receiver
1159 hidnplayr 824
 
825
  .ack:
1254 hidnplayr 826
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 827
	; Send an ACK
1254 hidnplayr 828
	mov	eax, ebx
1159 hidnplayr 829
	mov	bl, TH_ACK
1249 hidnplayr 830
	call	TCP_send_ack
1159 hidnplayr 831
  .exit:
1254 hidnplayr 832
 
833
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 834
	ret
835
 
836
 
1249 hidnplayr 837
 
838
align 4
839
stateTCB_FIN_WAIT_1:
1254 hidnplayr 840
 
841
	DEBUGF	1,"TCBStateHandler: Fin_wait_1\n"
842
 
1159 hidnplayr 843
	; We can either receive an ACK of a fin, or a fin
1249 hidnplayr 844
	mov	al, [edx + TCP_Packet.Flags]
1159 hidnplayr 845
	and	al, TH_FIN + TH_ACK
846
 
847
	cmp	al, TH_ACK
848
	jne	@f
849
 
850
	; It was an ACK
1254 hidnplayr 851
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_2
1159 hidnplayr 852
	jmp	.exit
853
 
1254 hidnplayr 854
    @@: mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSING
1159 hidnplayr 855
	cmp	al, TH_FIN
856
	je	@f
1254 hidnplayr 857
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
1159 hidnplayr 858
 
1249 hidnplayr 859
    @@: lea	esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
860
	inc_INET esi
1254 hidnplayr 861
 
862
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 863
	; Send an ACK
1254 hidnplayr 864
	mov	eax, ebx
1159 hidnplayr 865
	mov	bl, TH_ACK
1249 hidnplayr 866
	call	TCP_send_ack
1159 hidnplayr 867
 
868
  .exit:
1254 hidnplayr 869
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 870
	ret
871
 
872
 
1249 hidnplayr 873
 
874
align 4
875
stateTCB_FIN_WAIT_2:
1254 hidnplayr 876
 
877
	DEBUGF	1,"TCBStateHandler: Fin_wait_2\n"
878
 
1249 hidnplayr 879
	test	[edx + TCP_Packet.Flags], TH_FIN
1159 hidnplayr 880
	jz	.exit
881
 
882
	; Change state, as we have a fin
1254 hidnplayr 883
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
1159 hidnplayr 884
 
1249 hidnplayr 885
	lea	esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
886
	inc_INET esi
1159 hidnplayr 887
 
1254 hidnplayr 888
	mov	[ebx + SOCKET_head.lock], 0
889
 
1159 hidnplayr 890
	; Send an ACK
1254 hidnplayr 891
	mov	eax, ebx
1159 hidnplayr 892
	mov	bl, TH_ACK
1249 hidnplayr 893
	call	TCP_send_ack
1159 hidnplayr 894
 
895
  .exit:
1254 hidnplayr 896
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 897
	ret
898
 
899
 
1249 hidnplayr 900
 
901
align 4
902
stateTCB_CLOSE_WAIT:
1254 hidnplayr 903
 
904
	DEBUGF	1,"TCBStateHandler: close_wait\n"
1159 hidnplayr 905
	; Intentionally left empty
906
	; socket_close_tcp handles this
1254 hidnplayr 907
 
908
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 909
	ret
910
 
911
 
1249 hidnplayr 912
 
913
align 4
914
stateTCB_CLOSING:
1254 hidnplayr 915
 
916
	DEBUGF	1,"TCBStateHandler: closingn\n"
917
 
1159 hidnplayr 918
	; We can either receive an ACK of a fin, or a fin
1249 hidnplayr 919
	test	[edx + TCP_Packet.Flags], TH_ACK
1159 hidnplayr 920
	jz	.exit
921
 
1254 hidnplayr 922
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
1159 hidnplayr 923
 
924
  .exit:
1254 hidnplayr 925
 
926
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 927
	ret
928
 
929
 
1249 hidnplayr 930
align 4
931
stateTCB_LAST_ACK:
1254 hidnplayr 932
 
933
	DEBUGF	1,"TCBStateHandler: last_ackn\n"
934
 
1159 hidnplayr 935
	; Look at control flags - expecting an ACK
1249 hidnplayr 936
	test	[edx + TCP_Packet.Flags], TH_ACK
1159 hidnplayr 937
	jz	.exit
938
 
1254 hidnplayr 939
	mov	[ebx + SOCKET_head.lock], 0
940
 
1159 hidnplayr 941
	; delete the socket
942
	stdcall net_socket_free, ebx
943
 
944
  .exit:
945
	ret
946
 
947
 
1249 hidnplayr 948
align 4
949
stateTCB_TIME_WAIT:
1254 hidnplayr 950
 
951
	DEBUGF	1,"TCBStateHandler: time_wait\n"
952
 
953
	mov	[ebx + SOCKET_head.lock], 0
954
 
1159 hidnplayr 955
	ret
956
 
957
 
1249 hidnplayr 958
align 4
959
stateTCB_CLOSED:
1254 hidnplayr 960
 
961
	DEBUGF	1,"TCBStateHandler: closed\n"
962
 
963
	mov	[ebx + SOCKET_head.lock], 0
964
 
1159 hidnplayr 965
	ret
966
 
967
 
968
 
1254 hidnplayr 969
;---------------------------------------------------------------------------
970
;
971
; TCP_API
972
;
973
; This function is called by system function 75
974
;
975
; IN:  subfunction number in bl
976
;      device number in bh
977
;      ecx, edx, .. depends on subfunction
978
;
979
; OUT:
980
;
981
;---------------------------------------------------------------------------
1159 hidnplayr 982
 
1254 hidnplayr 983
align 4
984
TCP_API:
985
 
986
	movzx	eax, bh
987
	shl	eax, 2
988
 
989
	test	bl, bl
990
	jz	.packets_tx	; 0
991
	dec	bl
992
	jz	.packets_rx	; 1
993
 
994
.error:
995
	mov	eax, -1
996
	ret
997
 
998
.packets_tx:
999
	add	eax, TCP_PACKETS_TX
1000
	mov	eax, [eax]
1001
	ret
1002
 
1003
.packets_rx:
1004
	add	eax, TCP_PACKETS_RX
1005
	mov	eax, [eax]
1006
	ret