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