Subversion Repositories Kolibri OS

Rev

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