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 |