Subversion Repositories Kolibri OS

Rev

Rev 1536 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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