Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1196 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
1514 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.    ;;
1196 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  TCP.INC                                                        ;;
7
;;                                                                 ;;
8
;;  Part of the tcp/ip network stack for KolibriOS                 ;;
9
;;                                                                 ;;
1514 hidnplayr 10
;;   Written by hidnplayr@kolibrios.org                            ;;
1196 hidnplayr 11
;;                                                                 ;;
1514 hidnplayr 12
;;    Based on the code of 4.4BSD                                  ;;
13
;;                                                                 ;;
1196 hidnplayr 14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
15
;;             Version 2, June 1991                                ;;
16
;;                                                                 ;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1159 hidnplayr 18
 
1206 hidnplayr 19
$Revision: 1514 $
1159 hidnplayr 20
 
1514 hidnplayr 21
; Socket states
22
TCB_CLOSED		equ 0
23
TCB_LISTEN		equ 1
24
TCB_SYN_SENT		equ 2
25
TCB_SYN_RECEIVED	equ 3
26
TCB_ESTABLISHED 	equ 4
27
TCB_CLOSE_WAIT		equ 5
28
TCB_FIN_WAIT_1		equ 6
29
TCB_CLOSING		equ 7
30
TCB_LAST_ACK		equ 8
31
TCB_FIN_WAIT_2		equ 9
32
TCB_TIMED_WAIT		equ 10
1196 hidnplayr 33
 
1514 hidnplayr 34
; Socket Flags
35
TF_ACKNOW		equ 1 shl 0	; ack peer immediately
36
TF_DELACK		equ 1 shl 1	; ack, but try to delay it
37
TF_NODELAY		equ 1 shl 2	; don't delay packets to coalesce
38
TF_NOOPT		equ 1 shl 3	; don't use tcp options
39
TF_SENTFIN		equ 1 shl 4	; have sent FIN
40
TF_REQ_SCALE		equ 1 shl 5	; have/will request window scaling
41
TF_RCVD_SCALE		equ 1 shl 6	; other side has requested scaling
42
TF_REQ_TSTMP		equ 1 shl 7	; have/will request timestamps
43
TF_RCVD_TSTMP		equ 1 shl 8	; a timestamp was received in SYN
44
TF_SACK_PERMIT		equ 1 shl 9	; other side said I could SACK
1249 hidnplayr 45
 
1514 hidnplayr 46
; Segment flags
47
TH_FIN			equ 1 shl 0
48
TH_SYN			equ 1 shl 1
49
TH_RST			equ 1 shl 2
50
TH_PUSH 		equ 1 shl 3
51
TH_ACK			equ 1 shl 4
52
TH_URG			equ 1 shl 5
1318 hidnplayr 53
 
1514 hidnplayr 54
; Segment header options
55
TCP_OPT_EOL		equ 0		; End of option list.
56
TCP_OPT_NOP		equ 1		; No-Operation.
57
TCP_OPT_MAXSEG		equ 2		; Maximum Segment Size.
58
TCP_OPT_WINDOW		equ 3		; window scale
59
TCP_OPT_TIMESTAMP	equ 8
60
 
61
struct	TCP_segment
1159 hidnplayr 62
	.SourcePort		dw ?
63
	.DestinationPort	dw ?
64
	.SequenceNumber 	dd ?
65
	.AckNumber		dd ?
1196 hidnplayr 66
	.DataOffset		db ?	; DataOffset[0-3 bits] and Reserved[4-7]
67
	.Flags			db ?	; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
1159 hidnplayr 68
	.Window 		dw ?
69
	.Checksum		dw ?
70
	.UrgentPointer		dw ?
1514 hidnplayr 71
	.Data:				; ..or options
1159 hidnplayr 72
ends
73
 
1274 hidnplayr 74
struct	tcp_in_queue_entry
75
	.data_ptr	dd ?
76
	.data_size	dd ?
1514 hidnplayr 77
	.offset 	dd ?
1274 hidnplayr 78
	.size:
79
ends
80
 
81
struct	tcp_out_queue_entry
82
	.data_ptr	dd ?
83
	.data_size	dd ?
1514 hidnplayr 84
 
1274 hidnplayr 85
	.size:
86
ends
87
 
1196 hidnplayr 88
align 4
89
uglobal
1514 hidnplayr 90
	TCP_segments_tx 	rd IP_MAX_INTERFACES
91
	TCP_segments_rx 	rd IP_MAX_INTERFACES
92
	TCP_bytes_rx		rq IP_MAX_INTERFACES
93
	TCP_bytes_tx		rq IP_MAX_INTERFACES
94
	TCP_sequence_num	dd ?
1196 hidnplayr 95
endg
96
 
97
 
98
;-----------------------------------------------------------------
99
;
100
; TCP_init
101
;
102
;  This function resets all TCP variables
103
;
104
;  IN:  /
105
;  OUT: /
106
;
107
;-----------------------------------------------------------------
108
align 4
109
TCP_init:
110
 
111
	xor	eax, eax
1514 hidnplayr 112
	mov	edi, TCP_segments_tx
113
	mov	ecx, (6*IP_MAX_INTERFACES)
1196 hidnplayr 114
	rep	stosd
115
 
1514 hidnplayr 116
	mov	[TCP_sequence_num],1
1196 hidnplayr 117
 
118
	ret
119
 
120
 
121
;-----------------------------------------------------------------
122
;
1514 hidnplayr 123
; decrease socket ttls
1159 hidnplayr 124
;
1514 hidnplayr 125
; IN: /
126
; OUT: /
1159 hidnplayr 127
;
1514 hidnplayr 128
; destroys: eax
129
;
1196 hidnplayr 130
;-----------------------------------------------------------------
131
align 4
1514 hidnplayr 132
TCP_timer_1000ms:
133
; scan through all the active TCP sockets, decrementing active timers
1159 hidnplayr 134
 
1514 hidnplayr 135
	mov	eax, net_sockets
136
  .loop:
137
	mov	eax, [eax + SOCKET.NextPtr]
138
  .check_only:
139
	or	eax, eax
1159 hidnplayr 140
	jz	.exit
141
 
1514 hidnplayr 142
	cmp	[eax + SOCKET.Type], IP_PROTO_TCP
143
	jne	.loop
1249 hidnplayr 144
 
1514 hidnplayr 145
	cmp	[eax + TCP_SOCKET.t_timer], 0
1159 hidnplayr 146
	jne	.decrement_tcb
1514 hidnplayr 147
  ;;;;;;      cmp     [eax + TCP_SOCKET.wndsizeTimer], 0
1159 hidnplayr 148
	jne	.decrement_wnd
1514 hidnplayr 149
	jmp	.loop
1159 hidnplayr 150
 
151
  .decrement_tcb:
1274 hidnplayr 152
; decrement it, delete socket if TCB timer = 0 & socket in timewait state
1514 hidnplayr 153
	dec	[eax + TCP_SOCKET.t_timer]
154
	jnz	.loop
1159 hidnplayr 155
 
1514 hidnplayr 156
	cmp	[eax + TCP_SOCKET.t_state], TCB_TIMED_WAIT
157
	jne	.loop
1159 hidnplayr 158
 
1514 hidnplayr 159
	push	[eax + SOCKET.NextPtr]
160
	call	SOCKET_free
161
	pop	eax
162
	jmp	.check_only
1159 hidnplayr 163
 
164
  .decrement_wnd:
1514 hidnplayr 165
;;;;;;        dec     [eax + TCP_SOCKET.wndsizeTimer]
1159 hidnplayr 166
 
167
  .exit:
168
	ret
169
 
170
 
1249 hidnplayr 171
 
1514 hidnplayr 172
;----------------------
1159 hidnplayr 173
;
1514 hidnplayr 174
; TCP_500ms
1159 hidnplayr 175
;
1514 hidnplayr 176
;----------------------
1196 hidnplayr 177
align 4
1514 hidnplayr 178
TCP_500ms:
1159 hidnplayr 179
 
1514 hidnplayr 180
	add	[TCP_sequence_num], 64000
1159 hidnplayr 181
 
1249 hidnplayr 182
	ret
1159 hidnplayr 183
 
184
 
185
 
1514 hidnplayr 186
;----------------------
187
;
188
; TCP_10ms
189
;
190
;----------------------
191
align 4
192
TCP_10ms:
1254 hidnplayr 193
 
1514 hidnplayr 194
	; todo: decrease timers
1159 hidnplayr 195
 
1514 hidnplayr 196
	ret
1159 hidnplayr 197
 
198
 
199
 
1318 hidnplayr 200
 
1249 hidnplayr 201
;-----------------------------------------------------------------
202
;
1514 hidnplayr 203
; TCP_input:
1159 hidnplayr 204
;
1514 hidnplayr 205
;  IN:  [esp] = ptr to buffer
206
;       [esp+4] = buffer size
207
;       ebx = ptr to device struct
208
;       ecx = segment size
209
;       edx = ptr to TCP segment
1196 hidnplayr 210
;
1514 hidnplayr 211
;       esi = ipv4 source address
212
;       edi = ipv4 dest   address
213
;
1196 hidnplayr 214
;  OUT: /
215
;
216
;-----------------------------------------------------------------
1249 hidnplayr 217
align 4
1514 hidnplayr 218
TCP_input:
1159 hidnplayr 219
 
1514 hidnplayr 220
       DEBUGF  1,"TCP_input\n"
1196 hidnplayr 221
 
1514 hidnplayr 222
; Offset must be greater than or equal to the size of the standard TCP header (20) and less than or equal to the TCP length.
1254 hidnplayr 223
 
1514 hidnplayr 224
	movzx	eax, [edx + TCP_segment.DataOffset]
225
	and	eax, 0xf0
226
	shr	al , 2
227
 
228
	DEBUGF	1,"data offset: %u\n", eax
229
 
230
	cmp	eax, 20
231
	jl	.drop
232
 
233
	cmp	eax, ecx
234
	jg	.drop
235
 
236
;-------------------------------
237
; Now, re-calculate the checksum
238
 
239
	push	eax edx ebx
240
 
241
	push	edi
242
	push	esi
243
	mov	esi, edx
244
	call	TCP_checksum	; this destroys edx, ecx and esi (but not edi! :)
245
 
246
	pop	ebx edx eax
247
 
248
	cmp	[edx + TCP_segment.Checksum], 0
249
	jnz	.drop
250
 
251
	DEBUGF	1,"Checksum is correct\n"
252
 
253
;-----------------------------------------------------------------------------------------
254
; Check if this packet has a timestamp option (We do it here so we can process it quickly)
255
 
256
	cmp	eax, 20 + 12					; Timestamp option is 12 bytes
257
	jl	.no_timestamp
258
	je	.is_ok
259
 
260
	cmp	byte [edx + TCP_segment.Data + 12], 0		; end of option list
261
	jne	.no_timestamp
262
 
263
  .is_ok:
264
	test	[edx + TCP_segment.Flags], TH_SYN		; SYN flag must not be set
265
	jnz	.no_timestamp
266
 
267
	cmp	dword [edx + TCP_segment.Data], 0x0101080a	; Timestamp header
268
	jne	.no_timestamp
269
 
270
	DEBUGF	1,"timestamp ok\n"
271
 
272
	; TODO: Parse the options
273
	; TODO: Set a Bit in the TCP to tell all options are parsed
274
 
275
	ret
276
 
277
  .no_timestamp:
278
 
279
;-------------------------------------------
280
; Convert Big-endian values to little endian
281
 
282
	ntohld	[edx + TCP_segment.SequenceNumber]
283
	ntohld	[edx + TCP_segment.AckNumber]
284
 
285
	ntohlw	[edx + TCP_segment.Window]
286
	ntohlw	[edx + TCP_segment.UrgentPointer]
287
 
288
;------------------------------------------------------------
289
; Next thing to do is find the TCB (thus, the socket pointer)
290
 
1274 hidnplayr 291
; IP Packet TCP Destination Port = local Port
1514 hidnplayr 292
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
1318 hidnplayr 293
; (IP Packet TCP Source Port = remote Port)  OR (remote Port = 0)
1159 hidnplayr 294
 
295
	mov	ebx, net_sockets
296
 
1249 hidnplayr 297
  .socket_loop:
1514 hidnplayr 298
	mov	ebx, [ebx + SOCKET.NextPtr]
1159 hidnplayr 299
	or	ebx, ebx
1514 hidnplayr 300
	jz	.drop_with_reset
1159 hidnplayr 301
 
1514 hidnplayr 302
	cmp	[ebx + SOCKET.Type], IP_PROTO_TCP
1249 hidnplayr 303
	jne	.socket_loop
1159 hidnplayr 304
 
1514 hidnplayr 305
	mov	ax, [edx + TCP_segment.DestinationPort]
306
	cmp	[ebx + TCP_SOCKET.LocalPort], ax
307
	jne	.socket_loop
308
 
309
	mov	eax, [ebx + IP_SOCKET.RemoteIP]
1249 hidnplayr 310
	cmp	eax, esi
311
	je	@f
312
	test	eax, eax
1514 hidnplayr 313
	jnz	.socket_loop
1249 hidnplayr 314
       @@:
1159 hidnplayr 315
 
1514 hidnplayr 316
	mov	ax, [ebx + TCP_SOCKET.RemotePort]
317
	cmp	[edx + TCP_segment.SourcePort] , ax
1274 hidnplayr 318
	je	.found_socket
1249 hidnplayr 319
	test	ax, ax
1254 hidnplayr 320
	jnz	.socket_loop
1274 hidnplayr 321
  .found_socket:
1514 hidnplayr 322
       DEBUGF 1,"Socket ptr: %x\n", ebx
1254 hidnplayr 323
 
1514 hidnplayr 324
; ebx now contains the pointer to the socket
1257 hidnplayr 325
 
1514 hidnplayr 326
;----------------------------
327
; Check if socket isnt closed
328
 
329
	cmp	[TCP_SOCKET.t_state], TCB_CLOSED
330
	je	.drop
331
 
332
;----------------
333
; Lock the socket
334
 
335
	add	ebx, SOCKET.lock ; TODO: figure out if we should lock now already
1249 hidnplayr 336
	call	wait_mutex
1514 hidnplayr 337
	sub	ebx, SOCKET.lock
1159 hidnplayr 338
 
1514 hidnplayr 339
;---------------------------------------
340
; unscale the window into a 32 bit value  ;;;;;;
1159 hidnplayr 341
 
1514 hidnplayr 342
	movzx	eax, [edx + TCP_segment.Window]
343
	xchg	al, ah
344
 
345
	test	[edx + TCP_segment.Flags], TH_SYN
346
	jnz	.no_syn
347
 
348
	mov	cl , [ebx + TCP_SOCKET.SND_SCALE]
349
	shl	eax, cl
350
 
351
  .no_syn:
352
 
353
;-----------------------------------
354
; Is this socket a listening socket?
355
 
356
; If so, create a new socket
357
 
358
	test	[ebx + SOCKET.options], SO_ACCEPTCON
359
	jz	.no_accept_conn
360
 
361
 
362
		; TODO: create a new socket
363
 
364
 
365
  .no_accept_conn:
366
 
367
;----------------------------
368
; Compute window scale factor
369
 
370
 
371
; TODO
372
 
373
 
374
;-------------------------------------
375
; Reset idle timer and keepalive timer
376
 
377
 
378
; TODO
379
 
380
;-----------------------------------------
381
; Process TCP options if not in LISTEN state
382
 
383
	test	[ebx + TCP_SOCKET.t_state], TCB_LISTEN
384
	jz	.dont_do_options
385
 
386
	call	TCP_do_options
387
 
388
  .dont_do_options:
389
 
390
;-----------------------------------------------------------------------
391
; Time to do some header prediction (Original Principle by Van Jacobson)
392
 
393
 
394
; There are two common cases for an uni-directional data transfer.
395
;
396
; General rule: the packets has no control flags, is in-sequence,
397
;   window width didnt change and we're not retransmitting.
398
;
399
; Second rules:
400
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
401
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
402
;
403
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
404
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
405
 
406
	cmp	[TCP_SOCKET.t_state], TCB_ESTABLISHED
407
	jnz	.not_uni_xfer
408
 
409
	test	[TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
410
	jnz	.not_uni_xfer
411
 
412
	test	[TCP_segment.Flags], TH_ACK
413
	jz	.not_uni_xfer
414
 
415
	mov	eax, [edx + TCP_segment.SequenceNumber]
416
	cmp	eax, [ebx + TCP_SOCKET.RCV_NXT]
417
	jne	.not_uni_xfer
418
 
419
	movzx	eax, [edx + TCP_segment.Window] ;;;;;
420
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
421
	jne	.not_uni_xfer
422
 
423
	mov	eax, [ebx + TCP_SOCKET.SND_NXT]
424
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
425
	jne	.not_uni_xfer
426
 
427
;-------------------------------------------------------------------------------
428
; If last ACK falls within this segment's sequence number, record the timestamp.
429
 
430
	; TODO: check if it has a timestamp
431
 
432
 
433
 
434
 
435
;---------------------------------------
436
; check if we are sender in the uni-xfer
437
 
438
; If the following 4 conditions are all true, this segment is a pure ACK.
439
;
440
; - The segment contains no data (ti_len is 0).
441
 
442
	movzx	eax, [edx + TCP_segment.DataOffset]
1274 hidnplayr 443
	and	eax, 11110000b
444
	shr	eax, 2
445
	sub	ecx, eax
1514 hidnplayr 446
	jnz	.not_sender
1274 hidnplayr 447
 
1514 hidnplayr 448
; - The acknowledgment field in the segment (ti_ack) is greater than the largest unacknowledged sequence number (snd_una).
449
;     Since this test is "greater than" and not "greater than or equal to," it is true only if some positive amount of data is acknowledged by the ACK.
1274 hidnplayr 450
 
1514 hidnplayr 451
	mov	eax, [edx + TCP_segment.AckNumber]
452
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
453
	jle	.not_uni_xfer
1159 hidnplayr 454
 
1514 hidnplayr 455
; - The acknowledgment field in the segment (ti_ack) is less than or equal to the maximum sequence number sent (snd_max).
1159 hidnplayr 456
 
1514 hidnplayr 457
;        mov     eax, [edx + TCP_segment.Ack]
458
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
459
	jg	.not_uni_xfer
1159 hidnplayr 460
 
1514 hidnplayr 461
; - The congestion window (snd_cwnd) is greater than or equal to the current send window (snd_wnd).
462
;     This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance.
1254 hidnplayr 463
 
1514 hidnplayr 464
	mov	eax, [ebx + TCP_SOCKET.SND_CWND]
465
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
466
	jl	.not_uni_xfer
1318 hidnplayr 467
 
1514 hidnplayr 468
	DEBUGF	1,"Header prediction: we are sender\n"
1274 hidnplayr 469
 
1514 hidnplayr 470
;---------------------------------
471
; Packet is a pure ACK, process it
1274 hidnplayr 472
 
1514 hidnplayr 473
; Update RTT estimators
1159 hidnplayr 474
 
1514 hidnplayr 475
; Delete acknowledged bytes from send buffer
1254 hidnplayr 476
 
1514 hidnplayr 477
; Stop retransmit timer
1159 hidnplayr 478
 
1514 hidnplayr 479
; Awaken waiting processes
1318 hidnplayr 480
 
1514 hidnplayr 481
; Generate more output
1254 hidnplayr 482
 
483
 
1159 hidnplayr 484
 
485
 
1514 hidnplayr 486
	jmp	.drop
1159 hidnplayr 487
 
1196 hidnplayr 488
 
489
 
490
 
1514 hidnplayr 491
;-------------------------------------------------
492
; maybe we are the receiver in the uni-xfer then..
493
 
494
  .not_sender:
495
; The amount of data in the segment (ti_len) is greater than 0 (data count is in ecx)
496
 
497
 
498
; The acknowledgment field (ti_ack) equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
499
	mov	eax, [edx + TCP_segment.AckNumber]
500
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
501
	jne	.not_uni_xfer
502
 
503
; The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
504
;;;;
505
	jnz	.not_uni_xfer
506
 
507
; There is room in the receive buffer for the data in the segment.
508
;;;;
509
	jnz	.not_uni_xfer
510
 
511
;-------------------------------------
512
; Complete processing of received data
513
 
514
	DEBUGF	1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
515
 
516
; The next expected receive sequence number (rcv_nxt) is incremented by the number of bytes of data.
517
 
518
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx
519
 
520
; Add the data to the socket buffer
521
 
522
; The receiving process is awakened (by sorwakeup).
523
 
524
; The delayed-ACK flag is set and the input processing is complete.
525
 
526
	jmp	.drop
527
 
528
 
529
 
530
 
531
 
532
;----------------------------------------------------
533
; Header prediction failed, doing it the slow way..
534
 
535
  .not_uni_xfer:
536
 
537
	DEBUGF	1,"Header prediction failed\n"
538
 
539
;------------------------
540
; calculate header length                               ;;;;; we already calculated this before!
541
	movzx	eax, [edx + TCP_segment.DataOffset]
542
	and	eax, 0xf0
543
	shr	eax, 2
544
 
545
; Update edx to point to data..
546
	add	edx, eax
547
; ..and ecx to give data size
548
	sub	ecx, eax
549
 
550
;------------------------------
551
; Calculate receive window size
552
 
553
	;;;;
554
 
555
 
556
;-------------------------
557
; TCP slow input procedure
558
 
559
	DEBUGF	1,"TCP slow input procedure\n"
560
 
561
	cmp	[eax + TCP_SOCKET.t_state], TCB_LISTEN
562
	je	.LISTEN
563
 
564
	cmp	[eax + TCP_SOCKET.t_state], TCB_SYN_SENT
565
	je	.SYN_SENT
566
 
567
 
568
;--------------------------------------------
569
; Protection Against Wrapped Sequence Numbers
570
 
571
 
572
; First, check timestamp if present
573
 
574
;;;; TODO
575
 
576
; Then, check if at least some bytes of data are within window
577
 
578
;;;; TODO
579
 
580
	jmp	.trim_then_step6
581
 
1249 hidnplayr 582
align 4
1514 hidnplayr 583
.LISTEN:
1196 hidnplayr 584
 
1514 hidnplayr 585
	DEBUGF	1,"TCP state: listen\n"
1159 hidnplayr 586
 
1514 hidnplayr 587
	test	[edx + TCP_segment.Flags], TH_RST
588
	jnz	.drop
1159 hidnplayr 589
 
1514 hidnplayr 590
	test	[edx + TCP_segment.Flags], TH_ACK
591
	jnz	.drop_with_reset
1159 hidnplayr 592
 
1514 hidnplayr 593
	test	[edx + TCP_segment.Flags], TH_SYN
594
	jz	.drop
1159 hidnplayr 595
 
1514 hidnplayr 596
	; TODO: check if it's a broadcast or multicast, and drop if so
1159 hidnplayr 597
 
1514 hidnplayr 598
;;; 28.6
599
 
600
	; create a new socket and fill in the nescessary variables
601
 
602
;; Exit if backlog queue is full
603
;        mov     ax, [ebx + TCP_SOCKET.backlog_cur]
604
;        cmp     ax, [ebx + TCP_SOCKET.backlog]
605
;        jae     .exit
606
 
607
; Allocate new socket
608
	call	SOCKET_alloc
609
     ;;;   jz      .fail
610
 
611
; Copy structure from current socket to new, (including lock!)
612
; We start at PID to reserve the socket num, and the 2 pointers at beginning of socket
613
	lea	esi, [edx + SOCKET.PID]
614
	lea	edi, [eax + SOCKET.PID]
615
	mov	ecx, (TCP_SOCKET.end - SOCKET.PID + 3)/4
1274 hidnplayr 616
	rep	movsd
1159 hidnplayr 617
 
1514 hidnplayr 618
;; Push pointer to new socket to queue
619
;        movzx   ecx, [ebx + TCP_SOCKET.backlog_cur]
620
;        inc     [ebx + TCP_SOCKET.backlog_cur]
621
;        mov     [ebx + TCP_SOCKET.end + ecx*4], eax
1159 hidnplayr 622
 
1514 hidnplayr 623
	mov	[eax + IP_SOCKET.RemoteIP], esi ; IP source address
1159 hidnplayr 624
 
1514 hidnplayr 625
	mov	cx, [edx + TCP_segment.SourcePort]
626
	mov	[eax + TCP_SOCKET.RemotePort], cx
1159 hidnplayr 627
 
1514 hidnplayr 628
	mov	ecx, [edx + TCP_segment.SequenceNumber]
629
	mov	[eax + TCP_SOCKET.IRS], ecx
1159 hidnplayr 630
 
1514 hidnplayr 631
	mov	ecx, [eax + TCP_SOCKET.ISS]
632
	mov	[eax + TCP_SOCKET.SND_NXT], ecx
1159 hidnplayr 633
 
1514 hidnplayr 634
	jmp	.trim_then_step6
1159 hidnplayr 635
 
1254 hidnplayr 636
 
1159 hidnplayr 637
 
1514 hidnplayr 638
align 4
639
.SYN_SENT:
1281 hidnplayr 640
 
1514 hidnplayr 641
	DEBUGF	1,"TCP state: syn_sent\n"
1159 hidnplayr 642
 
1514 hidnplayr 643
	test	[edx + TCP_segment.Flags], TH_ACK
644
	jz	@f
1281 hidnplayr 645
 
1514 hidnplayr 646
	mov	eax, [edx + TCP_segment.AckNumber]
647
	cmp	eax, [ebx + TCP_SOCKET.ISS]
648
	jle	.drop_with_reset
1281 hidnplayr 649
 
1514 hidnplayr 650
	mov	eax, [edx + TCP_segment.AckNumber]
651
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
652
	jg	.drop_with_reset
653
       @@:
1281 hidnplayr 654
 
655
 
1514 hidnplayr 656
	test	[edx + TCP_segment.Flags], TH_RST
657
	jz	@f
1281 hidnplayr 658
 
1514 hidnplayr 659
	test	[edx + TCP_segment.Flags], TH_ACK
660
	jz	.drop
1281 hidnplayr 661
 
1514 hidnplayr 662
	;tp = tcp_drop(tp, ECONNREFUSED)
1159 hidnplayr 663
 
1514 hidnplayr 664
	jmp	.drop
665
       @@:
1159 hidnplayr 666
 
1514 hidnplayr 667
	test	[edx + TCP_segment.Flags], TH_SYN
668
	jz	.drop
1318 hidnplayr 669
 
1514 hidnplayr 670
; now, process received SYN in response to an active open
671
	test	[edx + TCP_segment.Flags], TH_ACK
672
	jz	@f
673
 
674
	mov	eax, [edx + TCP_segment.AckNumber]
675
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
676
 
677
	mov	eax, [ebx + TCP_SOCKET.SND_UNA]
678
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
679
	jle	@f
680
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
681
 
682
 
683
; TODO: turn off retransmission timer
684
 
685
	mov	eax, [edx + TCP_segment.SequenceNumber]
686
	mov	[ebx + TCP_SOCKET.IRS], eax
687
 
688
; TODO: set socket state to connected
689
 
690
	mov	[ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
691
 
692
; TODO: check if we should scale the connection (567-572)
693
; TODO: update RTT estimators
694
 
695
 
696
       @@:
697
 
698
; We have received a syn but no ACK, so we are having a simultaneous open..
699
	mov	[ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
700
 
701
;-------------------------------------
702
; Common processing for receipt of SYN
703
 
704
  .trimthenstep6:
705
 
706
	inc	[edx + TCP_segment.SequenceNumber]
707
 
708
	cmp	cx, [ebx + TCP_SOCKET.RCV_WND]
709
	jle	@f
710
 
711
	movzx	eax, cx
712
	sub	ax, [ebx + TCP_SOCKET.RCV_WND]
713
	; TODO: 592
714
	mov	cx, [ebx + TCP_SOCKET.RCV_WND]
715
	; TODO...
716
       @@:
717
	;;;;;
718
	;;; jmp     .step6
719
 
720
 
721
 
722
 
723
 
1274 hidnplayr 724
align 4
1514 hidnplayr 725
.trim_then_step6:
1159 hidnplayr 726
 
1514 hidnplayr 727
	DEBUGF	1,"Trim, then step 6\n"
1159 hidnplayr 728
 
1514 hidnplayr 729
;----------------------------
730
; trim any data not in window
1159 hidnplayr 731
 
1514 hidnplayr 732
	mov	eax, [ebx + TCP_SOCKET.RCV_NXT]
733
	sub	eax, [edx + TCP_segment.SequenceNumber]
1318 hidnplayr 734
 
1514 hidnplayr 735
	test	eax, eax
736
	jz	.no_drop
1274 hidnplayr 737
 
1514 hidnplayr 738
	test	[edx + TCP_segment.Flags], TH_SYN
739
	jz	.no_drop
740
 
741
	and	[edx + TCP_segment.Flags], not (TH_SYN)
742
	inc	[edx + TCP_segment.SequenceNumber]
743
 
744
	cmp	[edx + TCP_segment.UrgentPointer], 1
745
	jl	@f
746
 
747
	dec	[edx + TCP_segment.UrgentPointer]
748
 
749
	jmp	.no_drop
750
       @@:
751
 
752
	and	[edx + TCP_segment.Flags], not (TH_URG)
753
	dec	eax
754
 
755
  .no_drop:
756
 
757
; eax holds number of bytes to drop
758
 
759
 
760
;----------------------------------
761
; Check for entire duplicate packet
762
 
763
	cmp	eax, ecx
764
	jge	.duplicate
765
 
766
	;;; TODO: figure 28.30
767
 
768
;;        inc     [TCP_segments_rx]
769
 
770
;;        add     dword [TCP_bytes_rx], ecx
771
;;        adc     dword [TCP_bytes_rx+4], 0
772
 
773
;------------------------
774
; Check for duplicate FIN
775
 
776
	test	[edx + TCP_segment.Flags], TH_FIN
777
	jz	@f
778
	inc	ecx
779
	cmp	eax, ecx
780
	dec	ecx
781
	jne	@f
782
 
783
	mov	eax, ecx
784
	and	[edx + TCP_segment.Flags], not TH_FIN
785
	;;; TODO: set ACKNOW flag
786
 
787
	jmp	.no_duplicate
788
       @@:
789
 
790
	; Handle the case when a bound socket connects to itself
791
	; Allow packets with a SYN and an ACKto continue with the processing
792
 
793
 
794
;-------------------------------------
795
; Generate duplicate ACK if nescessary
796
 
797
; This code also handles simultaneous half-open or self-connects
798
 
799
	test	eax, eax
800
	jnz	.drop_after_ack
801
 
802
	cmp	[edx + TCP_segment.Flags], TH_ACK
803
	jz	.drop_after_ack
804
 
805
  .duplicate:
806
 
807
;----------------------------------------
808
; Update statistics for duplicate packets
809
 
810
	;;; TODO
811
 
812
	;;; DROP the packet ??
813
 
814
  .no_duplicate:
815
 
816
;-----------------------------------------------
817
; Remove duplicate data and update urgent offset
818
 
819
	add	[edx + TCP_segment.SequenceNumber], eax
820
 
821
	;;; TODO
822
 
823
	sub	[edx + TCP_segment.UrgentPointer], ax
824
	jg	@f
825
 
826
	and	[edx + TCP_segment.Flags], not (TH_URG)
827
	mov	[edx + TCP_segment.UrgentPointer], 0
828
       @@:
829
 
830
;--------------------------------------------------
831
; Handle data that arrives after process terminates
832
 
833
	cmp	[ebx + SOCKET.PID], 0
834
	jge	@f
835
 
836
	cmp	[ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT
837
	jle	@f
838
 
839
	test	ecx, ecx
840
	jz	@f
841
 
842
	;;; Close the socket
843
	;;; update stats
844
 
845
	jmp	.drop_with_reset
846
 
847
       @@:
848
 
849
;----------------------------------------
850
; Remove data beyond right edge of window
851
 
852
	mov	eax, [edx + TCP_segment.SequenceNumber]
853
	add	eax, ecx
854
	sub	eax, [ebx + TCP_SOCKET.RCV_NXT]
855
	sub	ax, [ebx + TCP_SOCKET.RCV_WND]
856
 
857
	; eax now holds the number of bytes to drop
858
 
859
	jle	.no_excess_data
860
 
861
	;;; TODO: update stats
862
 
863
	cmp	eax, ecx
864
	jl	.dont_drop_all
865
 
866
;;; TODO 700-736
867
 
868
  .dont_drop_all:
869
 
870
  .no_excess_data:
871
 
872
 
873
;-----------------
874
; Record timestamp
875
 
876
	;;; TODO 737-746
877
 
878
;------------------
879
; Process RST flags
880
 
881
	test	[edx + TCP_segment.Flags], TH_RST
882
	jz	.rst_skip
883
 
884
	mov	eax, [ebx + TCP_SOCKET.t_state]
885
	shl	eax, 2
886
	jmp	dword [eax + .rst_sw_list]
887
 
888
  .rst_sw_list:
889
	dd	.rst_skip	;TCB_CLOSED
890
	dd	.rst_skip	;TCB_LISTEN
891
	dd	.rst_skip	;TCB_SYN_SENT
892
	dd	.econnrefused	;TCB_SYN_RECEIVED
893
	dd	.econnreset	;TCB_ESTABLISHED
894
	dd	.econnreset	;TCB_CLOSE_WAIT
895
	dd	.econnreset	;TCB_FIN_WAIT_1
896
	dd	.rst_close	;TCB_CLOSING
897
	dd	.rst_close	;TCB_LAST_ACK
898
	dd	.econnreset	;TCB_FIN_WAIT_2
899
	dd	.rst_close	;TCB_TIMED_WAIT
900
 
901
  .econnrefused:
902
 
903
	;;; TODO: debug info
904
 
905
	jmp	.close
906
 
907
  .econnreset:
908
 
909
	;;; TODO: debug info
910
    .close:
911
 
912
	;;; update stats
913
 
914
  .rst_close:
915
 
916
	;;; Close the socket
917
	jmp	.drop
918
 
919
  .rst_skip:
920
 
921
;--------------------------------------
922
; handle SYN-full and ACK-less segments
923
 
924
	test	[edx + TCP_segment.Flags], TH_SYN
925
	jz	@f
926
 
927
	;;; tcp_drop ( ECONNRESET)
928
	jmp	.drop_with_reset
929
 
930
	test	[edx + TCP_segment.Flags], TH_ACK
931
	jz	.drop
932
 
933
;----------------
934
; Process the ACK
935
 
936
	cmp	[ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
937
	jg	.ack_dup
938
	jl	.ack_nodup
939
 
940
;        dd      .ack_nodup      ;TCB_CLOSED
941
;        dd      .ack_nodup      ;TCB_LISTEN
942
;        dd      .ack_nodup      ;TCB_SYN_SENT
943
;        dd      .ack_syn_rcvd   ;TCB_SYN_RECEIVED
944
;        dd      .ack_dup        ;TCB_ESTABLISHED
945
;        dd      .ack_dup        ;TCB_CLOSE_WAIT
946
;        dd      .ack_dup        ;TCB_FIN_WAIT_1
947
;        dd      .ack_dup        ;TCB_CLOSING
948
;        dd      .ack_dup        ;TCB_LAST_ACK
949
;        dd      .ack_dup        ;TCB_FIN_WAIT_2
950
;        dd      .ack_dup        ;TCB_TIMED_WAIT
951
 
952
	;;;;;
953
 
954
  .ack_dup:
955
 
956
	;;;;
957
 
958
  .ack_nodup:
959
 
960
	;;;; 887
961
 
962
;-------------------------------------------------
963
; If the congestion window was infalted to account
964
; for the other side's cached packets, retrace it
965
 
966
	;;;; 888 -  902
967
 
968
 
969
;------------------------------------------
970
; RTT measurements and retransmission timer
971
 
972
	;;;;; 903 - 926
973
 
974
 
975
;-------------------------------------------
976
; Open congestion window in response to ACKs
977
 
978
	;;;;
979
 
980
 
981
;------------------------------------------
982
; Remove acknowledged data from send buffer
983
 
984
	;;;; 943 - 956
985
 
986
;---------------------------------------
987
; Wake up process waiting on send buffer
988
 
989
	;;;;;
990
 
991
	mov	eax, [ebx + TCP_SOCKET.t_state]
992
	shl	eax, 2
993
	jmp	dword [eax + .ACK_sw_list]
994
 
995
  .ACK_sw_list:
996
	dd	.step6		;TCB_CLOSED
997
	dd	.step6		;TCB_LISTEN
998
	dd	.step6		;TCB_SYN_SENT
999
	dd	.step6		;TCB_SYN_RECEIVED
1000
	dd	.step6		;TCB_ESTABLISHED
1001
	dd	.step6		;TCB_CLOSE_WAIT
1002
	dd	._963		;TCB_FIN_WAIT_1
1003
	dd	._958		;TCB_CLOSING
1004
	dd	._999		;TCB_LAST_ACK
1005
	dd	.step6		;TCB_FIN_WAIT_2
1006
	dd	._1010		;TCB_TIMED_WAIT
1007
 
1008
 
1009
._963:
1010
 
1011
 
1012
	jmp	.step6
1013
 
1014
 
1015
._958:
1016
 
1017
	jmp	.step6
1018
 
1019
._999:
1020
 
1021
	jmp	.step6
1022
 
1023
 
1024
._1010:
1025
 
1026
	jmp	.step6
1027
 
1028
 
1029
 
1030
align 4
1031
.step6:
1032
 
1033
	DEBUGF	1,"step 6\n"
1034
 
1035
;--------------------------
1036
; update window information
1037
 
1038
	test	[edx + TCP_segment.Flags], TH_ACK
1039
	jz	.no_window_update
1040
 
1041
	mov	eax, [ebx + TCP_SOCKET.SND_WL1]
1042
	cmp	eax, [edx + TCP_segment.SequenceNumber]
1043
 
1044
	;;;; 1021
1045
 
1046
;----------------------------------
1047
; Keep track of pure window updates
1048
 
1049
	test	ecx, ecx
1050
	jz	@f
1051
 
1052
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
1053
	cmp	eax, [edx + TCP_segment.AckNumber]
1054
	jne	@f
1055
 
1056
	;; mov eax, tiwin
1057
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
1058
	jle	@f
1059
 
1060
	;;; update stats
1061
 
1062
       @@:
1063
 
1064
	;; mov eax, incoming window
1065
	cmp	eax, [ebx + TCP_SOCKET.max_sndwnd]
1066
	jle	@f
1067
	mov	[ebx + TCP_SOCKET.max_sndwnd], eax
1068
       @@:
1069
	mov	[ebx + TCP_SOCKET.SND_WND], eax
1070
 
1071
	mov	eax, [edx + TCP_segment.SequenceNumber]
1072
	mov	[ebx + TCP_SOCKET.SND_WL1], eax
1073
 
1074
	mov	eax, [edx + TCP_segment.AckNumber]
1075
	mov	[ebx + TCP_SOCKET.SND_WL2], eax
1076
 
1077
	;;; needoutput = 1
1078
 
1079
  .no_window_update:
1080
 
1081
 
1082
;-----------------
1083
; process URG flag
1084
 
1085
	test	[edx + TCP_segment.Flags], TH_URG
1086
	jz	.not_urgent
1087
 
1088
	cmp	[edx + TCP_segment.UrgentPointer], 0
1089
	jz	.not_urgent
1090
 
1091
	cmp	[ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT
1092
	je	.not_urgent
1093
 
1094
; Ignore bogus urgent offsets
1095
 
1096
	;;; 1040-1050
1097
 
1098
	movzx	eax, [edx + TCP_segment.UrgentPointer]
1099
	add	eax, [ebx + SOCKET.SO_RCV.SB_CC]
1100
	cmp	eax, SOCKET_MAXDATA
1101
	jle	.not_urgent
1102
 
1103
	mov	[edx + TCP_segment.UrgentPointer], 0
1104
	and	[edx + TCP_segment.Flags], not (TH_URG)
1105
	jmp	.do_data
1106
 
1107
  .not_urgent:
1108
 
1109
;--------------------------------------
1110
; processing of received urgent pointer
1111
 
1112
	;;; 1051-1093
1113
 
1114
align 4
1115
.do_data:
1116
 
1117
	DEBUGF	1,"Do data:\n"
1118
 
1119
	; process the data in the segment
1120
 
1121
	test	[edx + TCP_segment.Flags], TH_FIN
1122
	jz	.process_fin
1123
 
1124
	test	[ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1 ;;;;;
1125
	jge	.dont_do_data
1126
 
1127
	DEBUGF	1,"Processing data in segment\n"
1128
 
1129
	;;; NOW, process the data
1130
 
1131
	jmp	.final_processing
1132
 
1133
 
1134
  .dont_do_data:
1135
 
1136
 
1137
;---------------
1138
; FIN processing
1139
 
1140
  .process_fin:
1141
 
1142
	DEBUGF	1,"Processing FIN\n"
1143
 
1144
	mov	eax, [ebx + TCP_SOCKET.t_state]
1145
	shl	eax, 2
1146
	jmp	dword [eax + .FIN_sw_list]
1147
 
1148
  .FIN_sw_list:
1149
	dd	.no_fin 	;TCB_CLOSED
1150
	dd	.no_fin 	;TCB_LISTEN
1151
	dd	.no_fin 	;TCB_SYN_SENT
1152
	dd	._1131		;TCB_SYN_RECEIVED
1153
	dd	._1131		;TCB_ESTABLISHED
1154
	dd	.no_fin 	;TCB_CLOSE_WAIT
1155
	dd	._1139		;TCB_FIN_WAIT_1
1156
	dd	.no_fin 	;TCB_CLOSING
1157
	dd	.no_fin 	;TCB_LAST_ACK
1158
	dd	._1147		;TCB_FIN_WAIT_2
1159
	dd	._1156		;TCB_TIMED_WAIT
1160
 
1161
 
1162
 
1163
  ._1131:
1164
 
1165
  ._1139:
1166
 
1167
  ._1147:
1168
 
1169
  ._1156:
1170
 
1171
 
1172
  .no_fin:
1173
 
1174
;-----------------
1175
; Final processing
1176
 
1177
  .final_processing:
1178
 
1179
	DEBUGF	1,"Final processing\n"
1180
 
1181
	;;; if debug enabled, output packet
1182
 
1183
	;test    ;;;needoutput = 1
1184
	;jnz     .outputnow
1185
 
1186
	test	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1187
	jz	.ret
1188
 
1189
  .outputnow:
1190
	call	TCP_output
1191
 
1192
  .ret:
1193
	mov	[ebx + SOCKET.lock], 0
1194
 
1274 hidnplayr 1195
	call	kernel_free
1514 hidnplayr 1196
	ret	4
1274 hidnplayr 1197
 
1514 hidnplayr 1198
;------------------------------------------
1199
; Generate an ACK, droping incoming segment
1274 hidnplayr 1200
 
1514 hidnplayr 1201
align 4
1202
.drop_after_ack:
1274 hidnplayr 1203
 
1514 hidnplayr 1204
	DEBUGF	1,"Drop after ACK\n"
1274 hidnplayr 1205
 
1514 hidnplayr 1206
	test	[edx + TCP_segment.Flags], TH_RST
1207
	jnz	.drop
1274 hidnplayr 1208
 
1514 hidnplayr 1209
	and	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1274 hidnplayr 1210
 
1514 hidnplayr 1211
	call	TCP_output
1318 hidnplayr 1212
 
1514 hidnplayr 1213
	mov	[ebx + SOCKET.lock], 0
1274 hidnplayr 1214
 
1514 hidnplayr 1215
	call	kernel_free
1216
	ret	4
1274 hidnplayr 1217
 
1514 hidnplayr 1218
 
1219
;-------------------------------------------
1220
; Generate an RST, dropping incoming segment
1221
 
1222
align 4
1223
.drop_with_reset:
1224
 
1225
	DEBUGF	1,"Drop with reset\n"
1226
 
1227
	test	[edx + TCP_segment.Flags], TH_RST
1228
	jnz	.drop
1229
 
1230
	;;; if its a multicast/broadcast, also drop
1231
 
1232
	test	[edx + TCP_segment.Flags], TH_ACK
1233
	jnz	.respond_ack
1234
 
1235
	test	[edx + TCP_segment.Flags], TH_SYN
1236
	jnz	.respond_syn
1237
 
1238
	mov	[ebx + SOCKET.lock], 0
1239
 
1240
	call	kernel_free
1241
	ret	4
1242
 
1243
  .respond_ack:
1244
 
1245
	;;;;
1246
 
1247
	call	TCP_respond
1248
 
1249
	jmp	.destroy_new_socket
1250
 
1251
 
1252
  .respond_syn:
1253
 
1254
	;;;;
1255
 
1256
	call	TCP_respond
1257
 
1258
	jmp	.destroy_new_socket
1259
 
1260
;-----
1261
; Drop
1262
 
1263
align 4
1264
.drop:
1265
 
1266
	DEBUGF	1,"Dropping packet\n"
1267
 
1268
	;;;; If debugging options are enabled, output the packet somwhere
1269
 
1270
  .destroy_new_socket:
1271
 
1272
	;;;; kill the newly created socket
1273
 
1274
	mov	[ebx + SOCKET.lock], 0
1275
 
1276
	call	kernel_free
1277
	ret	4
1278
 
1279
 
1280
 
1281
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1282
 
1283
 
1284
 
1285
;---------------------
1318 hidnplayr 1286
;
1514 hidnplayr 1287
; TCP_do_options
1318 hidnplayr 1288
;
1514 hidnplayr 1289
;-------------------
1290
 
1318 hidnplayr 1291
align 4
1514 hidnplayr 1292
TCP_do_options:
1274 hidnplayr 1293
 
1514 hidnplayr 1294
	DEBUGF	1,"TCP_do_options\n"
1274 hidnplayr 1295
 
1514 hidnplayr 1296
	push	eax
1297
	sub	eax, 20
1298
	jz	.no_options
1274 hidnplayr 1299
 
1514 hidnplayr 1300
	lea	esi, [edx + TCP_segment.Data]
1318 hidnplayr 1301
 
1514 hidnplayr 1302
 
1303
;-------------------------------------------
1304
; Begin the loop by checking for EOL and NOP
1305
 
1318 hidnplayr 1306
  .loop:
1307
 
1514 hidnplayr 1308
	cmp	byte [esi], TCP_OPT_EOL 	; end of option list?
1309
	jz	.no_options
1318 hidnplayr 1310
 
1514 hidnplayr 1311
	cmp	byte [esi], TCP_OPT_NOP 	; nop ?
1312
      ;;;  cmove   edi, 1                          ; if so, set option size to 1
1313
	jz	.continue			; and continue scanning
1318 hidnplayr 1314
 
1514 hidnplayr 1315
;------------------
1316
; We have an option
1318 hidnplayr 1317
 
1514 hidnplayr 1318
	movzx	edi, byte [esi + 1]		; get the length of this option in edi
1318 hidnplayr 1319
 
1320
 
1514 hidnplayr 1321
;--------------------------------------
1322
; Check for Maximum segment size option
1318 hidnplayr 1323
 
1514 hidnplayr 1324
	cmp	byte [esi], TCP_OPT_MAXSEG
1325
	jne	.no_maxseg
1318 hidnplayr 1326
 
1514 hidnplayr 1327
	cmp	edi, 4	; option length
1328
	jne	.continue
1318 hidnplayr 1329
 
1514 hidnplayr 1330
	test	[edx + TCP_segment.Flags], TH_SYN
1331
	jz	.continue
1318 hidnplayr 1332
 
1514 hidnplayr 1333
	; Now parse the option...
1318 hidnplayr 1334
 
1514 hidnplayr 1335
	jmp	.continue
1318 hidnplayr 1336
 
1514 hidnplayr 1337
  .no_maxseg:
1318 hidnplayr 1338
 
1514 hidnplayr 1339
;------------------------
1340
; Check for Window option
1318 hidnplayr 1341
 
1514 hidnplayr 1342
	cmp	byte [esi], TCP_OPT_WINDOW
1343
	jne	.no_window
1318 hidnplayr 1344
 
1514 hidnplayr 1345
	cmp	edi, 3 ; option length
1346
	jne	.continue
1318 hidnplayr 1347
 
1514 hidnplayr 1348
	test	[edx + TCP_segment.Flags], TH_SYN
1349
	jz	.continue
1318 hidnplayr 1350
 
1514 hidnplayr 1351
	; ...
1318 hidnplayr 1352
 
1514 hidnplayr 1353
	jmp	.continue
1318 hidnplayr 1354
 
1514 hidnplayr 1355
  .no_window:
1318 hidnplayr 1356
 
1514 hidnplayr 1357
;---------------------------
1358
; Check for Timestamp option
1318 hidnplayr 1359
 
1514 hidnplayr 1360
	cmp	byte [esi], TCP_OPT_TIMESTAMP
1361
	jne	.no_timestamp
1318 hidnplayr 1362
 
1514 hidnplayr 1363
	cmp	edi, 10 ; option length
1364
	jne	.continue
1318 hidnplayr 1365
 
1514 hidnplayr 1366
	; ...
1367
 
1368
 
1369
	jmp	.continue
1370
 
1371
  .no_timestamp:
1372
 
1373
;----------------------------------
1374
; Future options may be placed here
1375
 
1376
 
1377
 
1378
 
1379
;------------------------------
1380
; Continue scanning for options
1381
 
1382
  .continue:
1383
	add	esi, edi
1384
	sub	eax, edi
1385
	jg	.loop
1386
 
1387
  .no_options:
1388
 
1318 hidnplayr 1389
	pop	eax
1514 hidnplayr 1390
 
1318 hidnplayr 1391
	ret
1392
 
1514 hidnplayr 1393
 
1394
 
1395
 
1396
;---------------------------
1397
;
1398
; TCP_pull_out_of_band
1399
;
1400
; IN:  eax =
1401
;      ebx = socket ptr
1402
;      edx = tcp packet ptr
1403
;
1404
; OUT: /
1405
;
1406
;---------------------------
1407
 
1408
align 4
1409
TCP_pull_out_of_band:
1410
 
1411
	DEBUGF	1,"TCP_pull_out_of_band\n"
1412
 
1413
	;;;; 1282-1305
1414
 
1318 hidnplayr 1415
	ret
1416
 
1417
 
1418
 
1419
 
1514 hidnplayr 1420
 
1421
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1422
 
1423
 
1424
 
1425
 
1426
 
1318 hidnplayr 1427
;-----------------------------------------------------------------
1428
;
1514 hidnplayr 1429
; TCP_output
1318 hidnplayr 1430
;
1514 hidnplayr 1431
; IN: eax = socket pointer
1432
;;     esi = ptr to data
1433
;;     ecx = number of data bytes
1434
;
1318 hidnplayr 1435
; OUT: /
1436
;
1437
;-----------------------------------------------------------------
1438
align 4
1514 hidnplayr 1439
TCP_output:
1318 hidnplayr 1440
 
1514 hidnplayr 1441
	DEBUGF 1,"TCP_output, socket: %x\n", eax
1318 hidnplayr 1442
 
1514 hidnplayr 1443
; We'll detect the length of the data to be transmitted, and flags to be used
1444
; If there is some data, or any critical controls to send (SYN / RST), then transmit
1445
; Otherwise, investigate further
1318 hidnplayr 1446
 
1514 hidnplayr 1447
	mov	ebx, [eax + TCP_SOCKET.SND_MAX]
1448
	cmp	ebx, [eax + TCP_SOCKET.SND_UNA]
1449
	jne	.not_idle
1318 hidnplayr 1450
 
1514 hidnplayr 1451
	mov	ebx, [eax + TCP_SOCKET.t_idle]
1452
	cmp	ebx, [eax + TCP_SOCKET.t_rxtcur]
1453
	jle	.not_idle
1318 hidnplayr 1454
 
1514 hidnplayr 1455
; We have been idle for a while and no ACKS are expected to clock out any data we send..
1456
; Slow start to get ack "clock" running again.
1318 hidnplayr 1457
 
1514 hidnplayr 1458
	mov	ebx, [eax + TCP_SOCKET.t_maxseg]
1459
	mov	[eax + TCP_SOCKET.SND_CWND], ebx
1318 hidnplayr 1460
 
1514 hidnplayr 1461
  .not_idle:
1462
  .again:
1463
	mov	ebx, [eax + TCP_SOCKET.SND_NXT] 	; calculate offset
1464
	sub	ebx, [eax + TCP_SOCKET.SND_UNA] 	;
1318 hidnplayr 1465
 
1514 hidnplayr 1466
	mov	ecx, [eax + TCP_SOCKET.SND_WND] 	; determine window
1467
	cmp	ecx, [eax + TCP_SOCKET.SND_CWND]	;
1468
	jl	@f					;
1469
	mov	ecx, [eax + TCP_SOCKET.SND_CWND]	;
1470
       @@:						;
1318 hidnplayr 1471
 
1514 hidnplayr 1472
	call	TCP_outflags
1318 hidnplayr 1473
 
1514 hidnplayr 1474
; If in persist timeout with window of 0, send 1 byte.
1475
; Otherwise, if window is small but nonzero, and timer expired,
1476
; we will send what we can and go to transmit state
1318 hidnplayr 1477
 
1514 hidnplayr 1478
	test	[eax + TCP_SOCKET.t_force], -1
1479
	jz	.no_persist_timeout
1318 hidnplayr 1480
 
1514 hidnplayr 1481
	test	ecx, ecx
1482
	jnz	.no_zero_window
1255 hidnplayr 1483
 
1514 hidnplayr 1484
	cmp	ebx, [eax + SOCKET.SO_SND.SB_CC]
1485
	jge	@f
1255 hidnplayr 1486
 
1514 hidnplayr 1487
	and	dl, not (TH_FIN)	  ; clear the FIN flag    ??? how can it be set before?
1255 hidnplayr 1488
 
1514 hidnplayr 1489
       @@:
1490
	inc	ecx
1491
	jmp	.no_persist_timeout
1255 hidnplayr 1492
 
1514 hidnplayr 1493
  .no_zero_window:
1254 hidnplayr 1494
 
1514 hidnplayr 1495
;;;        mov     [eax + TCP_SOCKET.t_timer....TCPT_PERSIST], 0
1496
	mov	[eax + TCP_SOCKET.t_rxtshift], 0
1254 hidnplayr 1497
 
1514 hidnplayr 1498
  .no_persist_timeout:
1159 hidnplayr 1499
 
1514 hidnplayr 1500
;;;106
1159 hidnplayr 1501
 
1514 hidnplayr 1502
	mov	esi, [eax + SOCKET.SO_SND.SB_CC]
1503
	cmp	esi, ecx
1504
	jl	@f
1505
	mov	esi, ecx
1506
       @@:
1507
	sub	esi, ebx
1254 hidnplayr 1508
 
1514 hidnplayr 1509
	cmp	esi, -1
1510
	jne	.not_minus_one
1159 hidnplayr 1511
 
1514 hidnplayr 1512
; If FIN has been set, but not ACKed, and we havent been called to retransmit,
1513
; len (esi) will be -1
1514
; Otherwise, window shrank after we sent into it.
1515
; If window shrank to 0, cancel pending retransmit and pull SND_NXT back to (closed) window
1516
; We will enter persist state below.
1517
; If window didn't close completely, just wait for an ACK
1159 hidnplayr 1518
 
1514 hidnplayr 1519
	xor	esi, esi
1159 hidnplayr 1520
 
1514 hidnplayr 1521
	test	ecx, ecx
1522
	jnz	@f
1159 hidnplayr 1523
 
1514 hidnplayr 1524
;;;        mov     [eax + TCP_SOCKET.t_timer..TCPT_REXMT], 0
1274 hidnplayr 1525
 
1514 hidnplayr 1526
	push	[eax + TCP_SOCKET.SND_UNA]
1527
	pop	[eax + TCP_SOCKET.SND_NXT]
1528
       @@:
1254 hidnplayr 1529
 
1514 hidnplayr 1530
  .not_minus_one:
1254 hidnplayr 1531
 
1514 hidnplayr 1532
;;; 124
1159 hidnplayr 1533
 
1514 hidnplayr 1534
	cmp	esi, [eax + TCP_SOCKET.t_maxseg]
1535
	jle	@f
1274 hidnplayr 1536
 
1514 hidnplayr 1537
	mov	esi, [eax + TCP_SOCKET.t_maxseg]
1538
	;sendalot = 1
1274 hidnplayr 1539
 
1514 hidnplayr 1540
       @@:
1274 hidnplayr 1541
 
1514 hidnplayr 1542
;;; 128
1274 hidnplayr 1543
 
1514 hidnplayr 1544
	mov	edi, [eax + TCP_SOCKET.SND_NXT]
1545
	add	edi, esi	; len
1546
	sub	edi, [eax + TCP_SOCKET.SND_UNA]
1547
	add	edi, [eax + SOCKET.SO_SND.SB_CC]
1548
	cmp	edi, 0
1549
	jle	@f
1274 hidnplayr 1550
 
1514 hidnplayr 1551
	and	dl, not (TH_FIN)	  ; clear the FIN flag
1159 hidnplayr 1552
 
1514 hidnplayr 1553
       @@:
1159 hidnplayr 1554
 
1555
 
1514 hidnplayr 1556
;;;; 130 TODO: set window (ecx) to space in send buffer
1159 hidnplayr 1557
 
1558
 
1514 hidnplayr 1559
;------------------------------
1560
; Sender silly window avoidance
1159 hidnplayr 1561
 
1514 hidnplayr 1562
	test	esi, esi
1563
	jz	.zero_length
1159 hidnplayr 1564
 
1249 hidnplayr 1565
 
1514 hidnplayr 1566
	cmp	esi, [eax + TCP_SOCKET.t_maxseg]
1567
	je	.send
1274 hidnplayr 1568
 
1514 hidnplayr 1569
;;; TODO: 144-145
1274 hidnplayr 1570
 
1514 hidnplayr 1571
	test	[eax + TCP_SOCKET.t_force], -1
1572
	jnz	.send
1274 hidnplayr 1573
 
1514 hidnplayr 1574
;;; TODO: 149..152
1274 hidnplayr 1575
 
1514 hidnplayr 1576
  .zero_length:
1254 hidnplayr 1577
 
1578
 
1514 hidnplayr 1579
;----------------------------------------
1580
; Check if a window update should be sent
1159 hidnplayr 1581
 
1514 hidnplayr 1582
	cmp	ecx, 0	; window
1583
	jle	.no_window
1159 hidnplayr 1584
 
1514 hidnplayr 1585
;;; TODO 154-172
1159 hidnplayr 1586
 
1514 hidnplayr 1587
  .no_window:
1159 hidnplayr 1588
 
1514 hidnplayr 1589
;--------------------------
1590
; Should a segment be sent?
1159 hidnplayr 1591
 
1514 hidnplayr 1592
	test	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1593
	jnz	.send
1159 hidnplayr 1594
 
1514 hidnplayr 1595
	test	dl, TH_SYN + TH_RST
1596
	jnz	.send
1159 hidnplayr 1597
 
1514 hidnplayr 1598
	mov	eax, [ebx + TCP_SOCKET.SND_UP]
1599
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
1600
	jg	.send
1249 hidnplayr 1601
 
1514 hidnplayr 1602
	test	dl, TH_FIN
1603
	jz	.enter_persist
1318 hidnplayr 1604
 
1514 hidnplayr 1605
	test	[ebx + TCP_SOCKET.t_flags], TF_SENTFIN
1606
	jnz	.send
1254 hidnplayr 1607
 
1514 hidnplayr 1608
	mov	eax, [ebx + TCP_SOCKET.SND_NXT]
1609
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
1610
	je	.send
1254 hidnplayr 1611
 
1514 hidnplayr 1612
;--------------------
1613
; Enter persist state
1318 hidnplayr 1614
 
1514 hidnplayr 1615
  .enter_persist:
1318 hidnplayr 1616
 
1514 hidnplayr 1617
	DEBUGF	1,"Entering pesist state\n"
1318 hidnplayr 1618
 
1619
 
1620
 
1514 hidnplayr 1621
;--------------------------------------
1622
; No reason to send a segment, just ret
1318 hidnplayr 1623
 
1514 hidnplayr 1624
	DEBUGF	1,"No reason to send a segment\n"
1318 hidnplayr 1625
 
1514 hidnplayr 1626
	ret
1318 hidnplayr 1627
 
1628
 
1629
 
1630
 
1631
 
1514 hidnplayr 1632
;-----------------------------------------------
1633
;
1634
; Send a segment
1635
;
1636
; ebx = socket pointer
1637
;  dl = flags
1638
;
1639
;-----------------------------------------------
1318 hidnplayr 1640
 
1514 hidnplayr 1641
.send:
1318 hidnplayr 1642
 
1514 hidnplayr 1643
	DEBUGF	1,"Preparing to send a segment\n"
1318 hidnplayr 1644
 
1514 hidnplayr 1645
	xor	edi, edi	; edi will contain the number of header option bytes
1318 hidnplayr 1646
 
1514 hidnplayr 1647
;------------------------------------
1648
; Send options with first SYN segment
1318 hidnplayr 1649
 
1514 hidnplayr 1650
	test	dl, TH_SYN
1651
	jz	.no_options
1318 hidnplayr 1652
 
1514 hidnplayr 1653
	mov	eax, [ebx + TCP_SOCKET.ISS]
1654
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1318 hidnplayr 1655
 
1514 hidnplayr 1656
	test	[ebx + TCP_SOCKET.t_flags], TF_NOOPT
1657
	jnz	.no_options
1318 hidnplayr 1658
 
1514 hidnplayr 1659
	mov	eax, TCP_OPT_MAXSEG shl 24 + 4 shl 16
1660
	mov	 ax, 1280 ;;;;;;
1318 hidnplayr 1661
	bswap	eax
1514 hidnplayr 1662
	push	eax
1663
 
1664
	mov	di, 4
1665
 
1666
	test	[ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
1667
	jz	.no_syn
1668
 
1669
	test	dl, TH_ACK
1670
	jnz	.scale_opt
1671
 
1672
	test	[ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
1673
	jz	.no_syn
1674
 
1675
  .scale_opt:
1676
 
1677
	mov	eax, TCP_OPT_WINDOW shl 24 + 4 shl 16 + TCP_OPT_NOP
1678
	mov	 ah, byte [ebx + TCP_SOCKET.request_r_scale]
1318 hidnplayr 1679
	bswap	eax
1514 hidnplayr 1680
	push	eax
1255 hidnplayr 1681
 
1514 hidnplayr 1682
	add	di, 4
1159 hidnplayr 1683
 
1514 hidnplayr 1684
  .no_syn:
1159 hidnplayr 1685
 
1514 hidnplayr 1686
;------------------------------------
1687
; Make the timestamp option if needed
1159 hidnplayr 1688
 
1514 hidnplayr 1689
	test	[ebx + TCP_SOCKET.t_flags], TF_REQ_TSTMP
1690
	jz	.no_timestamp
1159 hidnplayr 1691
 
1514 hidnplayr 1692
	test	dl, TH_RST
1693
	jnz	.no_timestamp
1694
 
1695
	test	dl, TH_ACK
1696
	jz	.timestamp
1697
 
1698
	test	[ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
1699
	jz	.no_timestamp
1700
 
1701
  .timestamp:
1702
 
1703
	DEBUGF	1,"Creating a timestamp\n"
1704
 
1705
	push	dword (TCP_OPT_TIMESTAMP shl 8 + 10 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24)
1706
	pushw	0
1707
	mov	eax, [timer_ticks]
1708
	bswap	eax
1709
	push	eax
1710
 
1711
	add	di, 10
1712
 
1713
  .no_timestamp:
1714
 
1715
	;; TODO: check if we dont exceed the max segment size
1716
 
1717
  .no_options:
1718
	add	edi, TCP_segment.Data
1719
 
1720
;-----------------------------------
1721
; Check if we have some data to send
1722
 
1723
     ;;;   mov     ecx, [huppeldepup]
1724
 
1255 hidnplayr 1725
	test	ecx, ecx
1514 hidnplayr 1726
	jz	.no_data
1159 hidnplayr 1727
 
1514 hidnplayr 1728
	;;; 278-316
1281 hidnplayr 1729
 
1514 hidnplayr 1730
	jmp	.header
1281 hidnplayr 1731
 
1514 hidnplayr 1732
  .no_data:
1159 hidnplayr 1733
 
1514 hidnplayr 1734
	;;; 317-338
1281 hidnplayr 1735
 
1736
 
1514 hidnplayr 1737
;----------
1738
 
1739
	push	di dx ebx
1740
 
1741
	add	ecx, edi	; total TCP segment size
1742
 
1743
	mov	eax, [ebx + IP_SOCKET.RemoteIP]
1744
	mov	ebx, [ebx + IP_SOCKET.LocalIP]
1745
	mov	di , IP_PROTO_TCP
1746
	call	IPv4_create_packet
1747
 
1748
;;;;        jz      .fail
1749
 
1750
	push	edx eax
1751
	call	NET_send
1159 hidnplayr 1752
	ret
1753
 
1514 hidnplayr 1754
;----------------
1159 hidnplayr 1755
 
1249 hidnplayr 1756
 
1514 hidnplayr 1757
;-------------------------------
1758
; Now, create the 20-byte header
1274 hidnplayr 1759
 
1514 hidnplayr 1760
  .header:
1274 hidnplayr 1761
 
1514 hidnplayr 1762
;-----------------------
1763
; Fill in the TCP header
1764
	pop	esi
1274 hidnplayr 1765
 
1514 hidnplayr 1766
	push	[esi + TCP_SOCKET.SND_NXT]
1767
	rol	word [esp], 8
1768
	rol	dword [esp], 16
1769
	pop	[edi + TCP_segment.SequenceNumber]
1274 hidnplayr 1770
 
1514 hidnplayr 1771
	push	[esi + TCP_SOCKET.RCV_NXT]
1772
	rol	word [esp], 8
1773
	rol	dword [esp], 16
1774
	pop	[edi + TCP_segment.AckNumber]
1274 hidnplayr 1775
 
1514 hidnplayr 1776
	push	[esi + TCP_SOCKET.LocalPort]
1777
	rol	word [esp], 8
1778
	pop	[edi + TCP_segment.SourcePort]
1274 hidnplayr 1779
 
1514 hidnplayr 1780
	push	[esi + TCP_SOCKET.RemotePort]
1781
	rol	word [esp], 8
1782
	pop	[edi + TCP_segment.DestinationPort]
1254 hidnplayr 1783
 
1784
 
1514 hidnplayr 1785
	mov	[edi + TCP_segment.Window], 0x0005
1786
	; 1280 bytes
1787
	mov	[edi + TCP_segment.UrgentPointer], 0
1159 hidnplayr 1788
 
1514 hidnplayr 1789
	mov	[edi + TCP_segment.DataOffset], 0x50
1159 hidnplayr 1790
 
1514 hidnplayr 1791
	mov	[edi + TCP_segment.Flags], cl
1159 hidnplayr 1792
 
1514 hidnplayr 1793
	mov	[edi + TCP_segment.Checksum], 0
1159 hidnplayr 1794
 
1514 hidnplayr 1795
;-----
1159 hidnplayr 1796
 
1797
 
1514 hidnplayr 1798
;--------------
1799
; Copy the data
1159 hidnplayr 1800
 
1514 hidnplayr 1801
	pop	esi
1802
	push	edi
1803
	add	edi, TCP_segment.Data  ;;
1804
	sub	ecx, TCP_segment.Data  ;;;
1249 hidnplayr 1805
 
1514 hidnplayr 1806
	shr	ecx, 1
1807
	jnc	.nb
1808
	movsb
1809
  .nb:
1810
	shr	ecx, 1
1811
	jnc	.nw
1812
	movsw
1813
  .nw:
1814
	test	ecx, ecx
1815
	jz	.nd
1816
	rep	movsd
1817
  .nd:
1818
	pop	edi
1254 hidnplayr 1819
 
1514 hidnplayr 1820
;--------------------
1821
; Create the checksum
1254 hidnplayr 1822
 
1514 hidnplayr 1823
	push	[ebx + IP_SOCKET.LocalIP]
1824
	push	[ebx + IP_SOCKET.RemoteIP]
1825
	call	TCP_checksum
1159 hidnplayr 1826
 
1514 hidnplayr 1827
;----------------
1828
; Send the packet
1159 hidnplayr 1829
 
1514 hidnplayr 1830
	;;;;;
1159 hidnplayr 1831
 
1514 hidnplayr 1832
 
1833
	DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
1834
	mov	esi, [ebx + ETH_DEVICE.transmit]
1835
 
1159 hidnplayr 1836
	ret
1837
 
1838
 
1249 hidnplayr 1839
 
1514 hidnplayr 1840
;-------------------------
1841
;
1842
; TCP_outflags
1843
;
1844
;  IN:  eax = socket ptr
1845
;
1846
;  OUT: edx = flags
1847
;
1848
;-------------------------
1249 hidnplayr 1849
align 4
1514 hidnplayr 1850
TCP_outflags:
1254 hidnplayr 1851
 
1514 hidnplayr 1852
	mov	edx, [eax + TCP_SOCKET.t_state]
1853
	movzx	edx, byte [edx + .flaglist]
1254 hidnplayr 1854
 
1514 hidnplayr 1855
	DEBUGF	1,"TCP_outflags, socket: %x, flags: %x\n", eax, dl
1856
 
1159 hidnplayr 1857
	ret
1858
 
1514 hidnplayr 1859
  .flaglist:
1159 hidnplayr 1860
 
1514 hidnplayr 1861
	db	TH_RST + TH_ACK 	; TCB_CLOSED
1862
	db	0			; TCB_LISTEN
1863
	db	TH_SYN			; TCB_SYN_SENT
1864
	db	TH_SYN + TH_ACK 	; TCB_SYN_RECEIVED
1865
	db		 TH_ACK 	; TCB_ESTABLISHED
1866
	db		 TH_ACK 	; TCB_CLOSE_WAIT
1867
	db	TH_SYN + TH_ACK 	; TCB_FIN_WAIT_1
1868
	db	TH_SYN + TH_ACK 	; TCB_CLOSING
1869
	db	TH_SYN + TH_ACK 	; TCB_LAST_ACK
1870
	db		 TH_ACK 	; TCB_FIN_WAIT_2
1871
	db		 TH_ACK 	; TCB_TIMED_WAIT
1249 hidnplayr 1872
 
1514 hidnplayr 1873
 
1874
;-------------------------
1875
;
1876
; TCP_drop
1877
;
1878
;  IN:  eax = socket ptr
1879
;
1880
;  OUT: /
1881
;
1882
;-------------------------
1249 hidnplayr 1883
align 4
1514 hidnplayr 1884
TCP_drop:
1254 hidnplayr 1885
 
1514 hidnplayr 1886
	DEBUGF	1,"TCP_drop\n"
1254 hidnplayr 1887
 
1514 hidnplayr 1888
;        cmp     [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
1889
;        jl      .no_syn_received
1159 hidnplayr 1890
 
1514 hidnplayr 1891
	mov	[eax + TCP_SOCKET.t_state], TCB_CLOSED
1159 hidnplayr 1892
 
1514 hidnplayr 1893
	call	TCP_output
1254 hidnplayr 1894
 
1514 hidnplayr 1895
;  .no_syn_received:
1896
 
1159 hidnplayr 1897
	ret
1898
 
1899
 
1254 hidnplayr 1900
 
1901
 
1159 hidnplayr 1902
 
1514 hidnplayr 1903
;---------------------------------------
1904
;
1905
; TCP_respond
1906
;
1907
; The easy way to send a RST/ACK segment
1908
;
1909
;  IN:  eax = socket ptr
1910
;
1911
;  OUT: /
1912
;
1913
;---------------------------------------
1914
align 4
1915
TCP_respond:
1254 hidnplayr 1916
 
1514 hidnplayr 1917
	DEBUGF	1,"TCP_respond\n"
1159 hidnplayr 1918
 
1919
	ret
1920
 
1921
 
1514 hidnplayr 1922
 
1923
;-----------------------------------------------------------------
1924
;
1925
; TCP_checksum
1926
;
1927
; This is the fast procedure to create or check a UDP header
1928
;  - To create a new checksum, the checksum field must be set to 0 before computation
1929
;  - To check an existing checksum, leave the checksum as is,
1930
;     and it will be 0 after this procedure, if it was correct
1931
;
1932
;  IN:  push source ip
1933
;       push dest ip
1934
;
1935
;       esi = packet ptr
1936
;
1937
;  OUT: checksum is filled in in packet! (but also in dx)
1938
;
1939
;-----------------------------------------------------------------
1249 hidnplayr 1940
align 4
1514 hidnplayr 1941
TCP_checksum:
1254 hidnplayr 1942
 
1514 hidnplayr 1943
;-------------
1944
; Pseudoheader
1254 hidnplayr 1945
 
1514 hidnplayr 1946
	; protocol type
1947
	mov	edx, IP_PROTO_TCP		; NO shl 8 here ! (it took me ages to figure this one out)
1254 hidnplayr 1948
 
1514 hidnplayr 1949
	; source address
1950
	add	dl, [esp+1+4]
1951
	adc	dh, [esp+0+4]
1952
	adc	dl, [esp+3+4]
1953
	adc	dh, [esp+2+4]
1159 hidnplayr 1954
 
1514 hidnplayr 1955
	; destination address
1956
	adc	dl, [esp+1+8]
1957
	adc	dh, [esp+0+8]
1958
	adc	dl, [esp+3+8]
1959
	adc	dh, [esp+2+8]
1159 hidnplayr 1960
 
1514 hidnplayr 1961
	; size
1962
	adc	dl, cl
1963
	adc	dh, ch
1254 hidnplayr 1964
 
1514 hidnplayr 1965
;---------------------
1966
; Real header and data
1254 hidnplayr 1967
 
1514 hidnplayr 1968
	push	esi
1969
	call	checksum_1
1970
	call	checksum_2
1971
	pop	esi
1254 hidnplayr 1972
 
1514 hidnplayr 1973
	neg	[esi+UDP_Packet.Checksum]	    ; zero will stay zero so we just get the checksum
1974
	add	[esi+UDP_Packet.Checksum], dx	    ;  , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
1159 hidnplayr 1975
 
1514 hidnplayr 1976
	ret	8			; Remove the IPs from stack
1159 hidnplayr 1977
 
1978
 
1514 hidnplayr 1979
 
1980
 
1254 hidnplayr 1981
;---------------------------------------------------------------------------
1982
;
1983
; TCP_API
1984
;
1985
; This function is called by system function 75
1986
;
1987
; IN:  subfunction number in bl
1988
;      device number in bh
1989
;      ecx, edx, .. depends on subfunction
1990
;
1991
; OUT:
1992
;
1993
;---------------------------------------------------------------------------
1994
align 4
1995
TCP_API:
1996
 
1997
	movzx	eax, bh
1998
	shl	eax, 2
1999
 
2000
	test	bl, bl
2001
	jz	.packets_tx	; 0
2002
	dec	bl
2003
	jz	.packets_rx	; 1
2004
 
2005
.error:
2006
	mov	eax, -1
2007
	ret
2008
 
2009
.packets_tx:
1514 hidnplayr 2010
	add	eax, TCP_segments_tx
1254 hidnplayr 2011
	mov	eax, [eax]
2012
	ret
2013
 
2014
.packets_rx:
1514 hidnplayr 2015
	add	eax, TCP_segments_rx
1254 hidnplayr 2016
	mov	eax, [eax]
2017
	ret