Subversion Repositories Kolibri OS

Rev

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

Rev 4850 Rev 5000
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2013. 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
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
7
;;                                                                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
9
;;                                                                 ;;
9
;;                                                                 ;;
10
;;    Based on the code of 4.4BSD                                  ;;
10
;;    Based on the code of 4.4BSD                                  ;;
11
;;                                                                 ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
16
 
17
$Revision: 4850 $
17
$Revision: 5000 $
18
 
18
 
19
;-----------------------------------------------------------------
19
;-----------------------------------------------------------------
20
;
20
;
21
; TCP_input:
21
; TCP_input:
22
;
22
;
23
;       Add a segment to the incoming TCP queue
23
;       Add a segment to the incoming TCP queue
24
;
24
;
25
;  IN:  [esp] = ptr to buffer
25
;  IN:  [esp] = ptr to buffer
26
;       [esp+4] = buffer size (dont care)
26
;       [esp+4] = buffer size (dont care)
27
;       ebx = ptr to device struct
27
;       ebx = ptr to device struct
28
;       ecx = segment size
28
;       ecx = segment size
29
;       esi = ptr to TCP segment
29
;       esi = ptr to TCP segment
30
;       edi = ptr to ipv4 source address, followed by ipv4 dest address
30
;       edi = ptr to ipv4 source address, followed by ipv4 dest address
31
;
31
;
32
;  OUT: /
32
;  OUT: /
33
;
33
;
34
;-----------------------------------------------------------------
34
;-----------------------------------------------------------------
35
 
35
 
36
align 4
36
align 4
37
TCP_input:
37
TCP_input:
38
 
38
 
39
; record the current time
39
; record the current time
40
        mov     eax, [timer_ticks]      ; in 1/100 seconds
40
        mov     eax, [timer_ticks]      ; in 1/100 seconds
41
        mov     [esp + 4], eax
41
        mov     [esp + 4], eax
42
 
42
 
43
        push    ebx ecx esi edi         ; mind the order
43
        push    ebx ecx esi edi         ; mind the order
44
        mov     esi, esp
44
        mov     esi, esp
45
 
45
 
46
        add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail
46
        add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail
47
        add     esp, sizeof.TCP_queue_entry
47
        add     esp, sizeof.TCP_queue_entry
48
 
48
 
49
        call    NET_ptr_to_num4
49
        call    NET_ptr_to_num4
50
        inc     [TCP_segments_rx + edi]
50
        inc     [TCP_segments_rx + edi]
51
 
51
 
52
        xor     edx, edx
52
        xor     edx, edx
53
        mov     eax, [TCP_input_event]
53
        mov     eax, [TCP_input_event]
54
        mov     ebx, [eax + EVENT.id]
54
        mov     ebx, [eax + EVENT.id]
55
        xor     esi, esi
55
        xor     esi, esi
56
        call    raise_event
56
        call    raise_event
57
 
57
 
58
        ret
58
        ret
59
 
59
 
60
  .fail:
60
  .fail:
61
        popf
-
 
62
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n"
61
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n"
63
 
62
 
64
        call    NET_ptr_to_num4
63
        call    NET_ptr_to_num4
65
        inc     [TCP_segments_missed + edi]
64
        inc     [TCP_segments_missed + edi]
66
 
65
 
67
        add     esp, sizeof.TCP_queue_entry - 8
66
        add     esp, sizeof.TCP_queue_entry - 8
68
        call    NET_packet_free
67
        call    NET_packet_free
69
        add     esp, 4
68
        add     esp, 4
70
 
69
 
71
        ret
70
        ret
72
 
71
 
73
 
72
 
74
 
73
 
75
 
74
 
76
align 4
75
align 4
77
proc TCP_process_input
76
proc TCP_process_input
78
 
77
 
79
locals
78
locals
80
        dataoffset      dd ?
79
        dataoffset      dd ?
81
        timestamp       dd ?
80
        timestamp       dd ?
82
        temp_bits       db ?
81
        temp_bits       db ?
83
endl
82
endl
84
 
83
 
85
        xor     esi, esi
84
        xor     esi, esi
86
        mov     ecx, MANUAL_DESTROY
85
        mov     ecx, MANUAL_DESTROY
87
        call    create_event
86
        call    create_event
88
        mov     [TCP_input_event], eax
87
        mov     [TCP_input_event], eax
89
 
88
 
90
  .wait:
89
  .wait:
91
        mov     eax, [TCP_input_event]
90
        mov     eax, [TCP_input_event]
92
        mov     ebx, [eax + EVENT.id]
91
        mov     ebx, [eax + EVENT.id]
93
        call    wait_event
92
        call    wait_event
94
 
93
 
95
  .loop:
94
  .loop:
96
        get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait
95
        get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait
97
 
96
 
98
        push    [esi + TCP_queue_entry.timestamp]
97
        push    [esi + TCP_queue_entry.timestamp]
99
        pop     [timestamp]
98
        pop     [timestamp]
100
        push    [esi + TCP_queue_entry.buffer_ptr]
99
        push    [esi + TCP_queue_entry.buffer_ptr]
101
 
100
 
102
        mov     ebx, [esi + TCP_queue_entry.device_ptr]
101
        mov     ebx, [esi + TCP_queue_entry.device_ptr]
103
        mov     ecx, [esi + TCP_queue_entry.segment_size]
102
        mov     ecx, [esi + TCP_queue_entry.segment_size]
104
        mov     edi, [esi + TCP_queue_entry.ip_ptr]                     ; ptr to ipv4 source address, followed by ipv4 destination address
103
        mov     edi, [esi + TCP_queue_entry.ip_ptr]                     ; ptr to ipv4 source address, followed by ipv4 destination address
105
        mov     esi, [esi + TCP_queue_entry.segment_ptr]                ; change esi last
104
        mov     esi, [esi + TCP_queue_entry.segment_ptr]                ; change esi last
106
 
105
 
107
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
106
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
108
 
107
 
109
        mov     edx, esi
108
        mov     edx, esi
110
 
109
 
111
        cmp     ebx, LOOPBACK_DEVICE
110
        cmp     ebx, LOOPBACK_DEVICE
112
        je      .checksum_ok
111
        je      .checksum_ok
113
 
112
 
114
; re-calculate the checksum (if not already done by hw)
113
; re-calculate the checksum (if not already done by hw)
115
        test    [ebx + NET_DEVICE.hwacc], NET_HWACC_TCP_IPv4_IN
114
        test    [ebx + NET_DEVICE.hwacc], NET_HWACC_TCP_IPv4_IN
116
        jnz     .checksum_ok
115
        jnz     .checksum_ok
117
 
116
 
118
        push    ecx esi
117
        push    ecx esi
119
        pushw   [esi + TCP_header.Checksum]
118
        pushw   [esi + TCP_header.Checksum]
120
        mov     [esi + TCP_header.Checksum], 0
119
        mov     [esi + TCP_header.Checksum], 0
121
        TCP_checksum (edi), (edi+4)
120
        TCP_checksum (edi), (edi+4)
122
        pop     cx                      ; previous checksum
121
        pop     cx                      ; previous checksum
123
        cmp     cx, dx
122
        cmp     cx, dx
124
        pop     edx ecx
123
        pop     edx ecx
125
        jne     .drop_no_socket
124
        jne     .drop_no_socket
126
  .checksum_ok:
125
  .checksum_ok:
127
 
126
 
128
; Verify the data offset
127
; Verify the data offset
129
        movzx   eax, [edx + TCP_header.DataOffset]
128
        movzx   eax, [edx + TCP_header.DataOffset]
130
        and     al, 0xf0                        ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
129
        and     al, 0xf0                        ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
131
        shr     al, 2
130
        shr     al, 2
132
        cmp     al, sizeof.TCP_header           ; Now see if it's at least the size of a standard TCP header
131
        cmp     al, sizeof.TCP_header           ; Now see if it's at least the size of a standard TCP header
133
        jb      .drop_no_socket                 ; If not, drop the packet
132
        jb      .drop_no_socket                 ; If not, drop the packet
134
        mov     [dataoffset], eax
133
        mov     [dataoffset], eax
135
 
134
 
136
        sub     ecx, eax                                                ; substract TCP header size from total segment size
135
        sub     ecx, eax                                                ; substract TCP header size from total segment size
137
        jb      .drop_no_socket                                         ; If total segment size is less then the advertised header size, drop packet
136
        jb      .drop_no_socket                                         ; If total segment size is less then the advertised header size, drop packet
138
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx
137
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx
139
 
138
 
140
;-------------------------------------------
139
;-------------------------------------------
141
; Convert Big-endian values to little endian
140
; Convert Big-endian values to little endian
142
 
141
 
143
        ntohd   [edx + TCP_header.SequenceNumber]
142
        ntohd   [edx + TCP_header.SequenceNumber]
144
        ntohd   [edx + TCP_header.AckNumber]
143
        ntohd   [edx + TCP_header.AckNumber]
145
 
144
 
146
        ntohw   [edx + TCP_header.Window]
145
        ntohw   [edx + TCP_header.Window]
147
        ntohw   [edx + TCP_header.UrgentPointer]
146
        ntohw   [edx + TCP_header.UrgentPointer]
148
 
147
 
149
;------------------------
148
;------------------------
150
; Find the socket pointer
149
; Find the socket pointer
151
 
150
 
152
; IP Packet TCP Destination Port = local Port
151
; IP Packet TCP Destination Port = local Port
153
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
152
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
154
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
153
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
155
 
154
 
156
  .findpcb:
155
  .findpcb:
157
        pusha
156
        pusha
158
        mov     ecx, socket_mutex
157
        mov     ecx, socket_mutex
159
        call    mutex_lock
158
        call    mutex_lock
160
        popa
159
        popa
161
 
160
 
162
        mov     ebx, net_sockets
161
        mov     ebx, net_sockets
163
        mov     si, [edx + TCP_header.DestinationPort]
162
        mov     si, [edx + TCP_header.DestinationPort]
164
 
163
 
165
  .socket_loop:
164
  .socket_loop:
166
        mov     ebx, [ebx + SOCKET.NextPtr]
165
        mov     ebx, [ebx + SOCKET.NextPtr]
167
        or      ebx, ebx
166
        or      ebx, ebx
168
        jz      .no_socket ;respond_seg_reset
167
        jz      .no_socket ;respond_seg_reset
169
 
168
 
170
        cmp     [ebx + SOCKET.Domain], AF_INET4
169
        cmp     [ebx + SOCKET.Domain], AF_INET4
171
        jne     .socket_loop
170
        jne     .socket_loop
172
 
171
 
173
        cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
172
        cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
174
        jne     .socket_loop
173
        jne     .socket_loop
175
 
174
 
176
        cmp     [ebx + TCP_SOCKET.LocalPort], si
175
        cmp     [ebx + TCP_SOCKET.LocalPort], si
177
        jne     .socket_loop
176
        jne     .socket_loop
178
 
177
 
179
        mov     eax, [ebx + IP_SOCKET.RemoteIP]
178
        mov     eax, [ebx + IP_SOCKET.RemoteIP]
180
        cmp     eax, [edi]                              ; Ipv4 source address
179
        cmp     eax, [edi]                              ; Ipv4 source address
181
        je      @f
180
        je      @f
182
        test    eax, eax
181
        test    eax, eax
183
        jnz     .socket_loop
182
        jnz     .socket_loop
184
       @@:
183
       @@:
185
 
184
 
186
        mov     ax, [ebx + TCP_SOCKET.RemotePort]
185
        mov     ax, [ebx + TCP_SOCKET.RemotePort]
187
        cmp     [edx + TCP_header.SourcePort], ax
186
        cmp     [edx + TCP_header.SourcePort], ax
188
        je      .found_socket
187
        je      .found_socket
189
        test    ax, ax
188
        test    ax, ax
190
        jnz     .socket_loop
189
        jnz     .socket_loop
191
  .found_socket:                                        ; ebx now contains the socketpointer
190
  .found_socket:                                        ; ebx now contains the socketpointer
192
        pusha
191
        pusha
193
        mov     ecx, socket_mutex
192
        mov     ecx, socket_mutex
194
        call    mutex_unlock
193
        call    mutex_unlock
195
        popa
194
        popa
196
 
195
 
197
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
196
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
198
 
197
 
199
;----------------------------
198
;----------------------------
200
; Check if socket isnt closed
199
; Check if socket isnt closed
201
 
200
 
202
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
201
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
203
        je      .drop_no_socket
202
        je      .drop_no_socket
204
 
203
 
205
;----------------
204
;----------------
206
; Lock the socket
205
; Lock the socket
207
 
206
 
208
        pusha
207
        pusha
209
        lea     ecx, [ebx + SOCKET.mutex]
208
        lea     ecx, [ebx + SOCKET.mutex]
210
        call    mutex_lock
209
        call    mutex_lock
211
        popa
210
        popa
212
 
211
 
213
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: socket locked\n"
212
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: socket locked\n"
214
 
213
 
215
;---------------------------
214
;---------------------------
216
; disable all temporary bits
215
; disable all temporary bits
217
 
216
 
218
        mov     [temp_bits], 0
217
        mov     [temp_bits], 0
219
 
218
 
220
;---------------------------------------
219
;---------------------------------------
221
; unscale the window into a 32 bit value
220
; unscale the window into a 32 bit value
222
 
221
 
223
        movzx   eax, [edx + TCP_header.Window]
222
        movzx   eax, [edx + TCP_header.Window]
224
        push    ecx
223
        push    ecx
225
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
224
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
226
        shl     eax, cl
225
        shl     eax, cl
227
        mov     dword [edx + TCP_header.Window], eax    ; word after window is checksum, we dont need checksum anymore
226
        mov     dword [edx + TCP_header.Window], eax    ; word after window is checksum, we dont need checksum anymore
228
        pop     ecx
227
        pop     ecx
229
 
228
 
230
;---------------------------------------
229
;---------------------------------------
231
; Are we accepting incoming connections?
230
; Are we accepting incoming connections?
232
 
231
 
233
        test    [ebx + SOCKET.options], SO_ACCEPTCON
232
        test    [ebx + SOCKET.options], SO_ACCEPTCON
234
        jz      .no_accept
233
        jz      .no_accept
235
 
234
 
236
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Accepting new connection\n"
235
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Accepting new connection\n"
237
 
236
 
238
        pusha
237
        pusha
239
        lea     ecx, [ebx + SOCKET.mutex]
238
        lea     ecx, [ebx + SOCKET.mutex]
240
        call    mutex_unlock
239
        call    mutex_unlock
241
        popa
240
        popa
242
 
241
 
243
        push    ecx edx esi edi         ;;;
242
        push    ecx edx esi edi         ;;;
244
        call    SOCKET_fork
243
        call    SOCKET_fork
245
        pop     edi esi edx ecx
244
        pop     edi esi edx ecx
246
 
245
 
247
        test    eax, eax
246
        test    eax, eax
248
        jz      .drop_no_socket
247
        jz      .drop_no_socket
249
 
248
 
250
        mov     ebx, eax
249
        mov     ebx, eax
251
 
250
 
252
        mov     [temp_bits], TCP_BIT_DROPSOCKET
251
        mov     [temp_bits], TCP_BIT_DROPSOCKET
253
 
252
 
254
        push    dword [edi + 4]                         ; Ipv4 destination addres
253
        push    dword [edi + 4]                         ; Ipv4 destination addres
255
        pop     [ebx + IP_SOCKET.LocalIP]
254
        pop     [ebx + IP_SOCKET.LocalIP]
256
 
255
 
257
        push    [edx + TCP_header.DestinationPort]
256
        push    [edx + TCP_header.DestinationPort]
258
        pop     [ebx + TCP_SOCKET.LocalPort]
257
        pop     [ebx + TCP_SOCKET.LocalPort]
259
 
258
 
260
        mov     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
259
        mov     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
261
  .no_accept:
260
  .no_accept:
262
 
261
 
263
 
262
 
264
;-------------------------------------
263
;-------------------------------------
265
; Reset idle timer and keepalive timer
264
; Reset idle timer and keepalive timer
266
 
265
 
267
        mov     [ebx + TCP_SOCKET.t_idle], 0
266
        mov     [ebx + TCP_SOCKET.t_idle], 0
268
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
267
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
269
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
268
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
270
 
269
 
271
;--------------------
270
;--------------------
272
; Process TCP options
271
; Process TCP options
273
 
272
 
274
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
273
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
275
;;;        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
274
;;;        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
276
;;;        jz      .not_uni_xfer                           ; also no header prediction
275
;;;        jz      .not_uni_xfer                           ; also no header prediction
277
 
276
 
278
        push    ecx
277
        push    ecx
279
 
278
 
280
        mov     ecx, [dataoffset]
279
        mov     ecx, [dataoffset]
281
        cmp     ecx, sizeof.TCP_header                  ; Does header contain any options?
280
        cmp     ecx, sizeof.TCP_header                  ; Does header contain any options?
282
        je      .no_options
281
        je      .no_options
283
 
282
 
284
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n"
283
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n"
285
 
284
 
286
        add     ecx, edx
285
        add     ecx, edx
287
        lea     esi, [edx + sizeof.TCP_header]
286
        lea     esi, [edx + sizeof.TCP_header]
288
 
287
 
289
  .opt_loop:
288
  .opt_loop:
290
        cmp     esi, ecx                        ; are we scanning outside of header?
289
        cmp     esi, ecx                        ; are we scanning outside of header?
291
        jae     .no_options
290
        jae     .no_options
292
        lodsb
291
        lodsb
293
        cmp     al, TCP_OPT_EOL                 ; end of option list?
292
        cmp     al, TCP_OPT_EOL                 ; end of option list?
294
        je      .no_options
293
        je      .no_options
295
        cmp     al, TCP_OPT_NOP
294
        cmp     al, TCP_OPT_NOP
296
        je      .opt_loop
295
        je      .opt_loop
297
        cmp     al, TCP_OPT_MAXSEG
296
        cmp     al, TCP_OPT_MAXSEG
298
        je      .opt_maxseg
297
        je      .opt_maxseg
299
        cmp     al, TCP_OPT_WINDOW
298
        cmp     al, TCP_OPT_WINDOW
300
        je      .opt_window
299
        je      .opt_window
301
        cmp     al, TCP_OPT_SACK_PERMIT
300
        cmp     al, TCP_OPT_SACK_PERMIT
302
        je      .opt_sack_permit
301
        je      .opt_sack_permit
303
;        cmp     al, TCP_OPT_SACK
302
;        cmp     al, TCP_OPT_SACK
304
;        je      .opt_sack
303
;        je      .opt_sack
305
        cmp     al, TCP_OPT_TIMESTAMP
304
        cmp     al, TCP_OPT_TIMESTAMP
306
        je      .opt_timestamp
305
        je      .opt_timestamp
307
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: unknown option:%u\n", al
306
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: unknown option:%u\n", al
308
        jmp     .no_options                     ; If we reach here, some unknown options were received, skip them all!
307
        jmp     .no_options                     ; If we reach here, some unknown options were received, skip them all!
309
 
308
 
310
  .opt_maxseg:
309
  .opt_maxseg:
311
        lodsb
310
        lodsb
312
        cmp     al, 4
311
        cmp     al, 4
313
        jne     .no_options                     ; error occured, ignore all options!
312
        jne     .no_options                     ; error occured, ignore all options!
314
 
313
 
315
        test    [edx + TCP_header.Flags], TH_SYN
314
        test    [edx + TCP_header.Flags], TH_SYN
316
        jz      @f
315
        jz      @f
317
 
316
 
318
        xor     eax, eax
317
        xor     eax, eax
319
        lodsw
318
        lodsw
320
        rol     ax, 8
319
        rol     ax, 8
321
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", eax
320
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", eax
322
        call    TCP_mss
321
        call    TCP_mss
323
       @@:
322
       @@:
324
        jmp     .opt_loop
323
        jmp     .opt_loop
325
 
324
 
326
 
325
 
327
  .opt_window:
326
  .opt_window:
328
        lodsb
327
        lodsb
329
        cmp     al, 3
328
        cmp     al, 3
330
        jne     .no_options
329
        jne     .no_options
331
 
330
 
332
        test    [edx + TCP_header.Flags], TH_SYN
331
        test    [edx + TCP_header.Flags], TH_SYN
333
        jz      @f
332
        jz      @f
334
 
333
 
335
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
334
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
336
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
335
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
337
 
336
 
338
        lodsb
337
        lodsb
339
        mov     [ebx + TCP_SOCKET.SND_SCALE], al
338
        mov     [ebx + TCP_SOCKET.SND_SCALE], al
340
        ;;;;; TODO
339
        ;;;;; TODO
341
 
340
 
342
       @@:
341
       @@:
343
        jmp     .opt_loop
342
        jmp     .opt_loop
344
 
343
 
345
 
344
 
346
  .opt_sack_permit:
345
  .opt_sack_permit:
347
        lodsb
346
        lodsb
348
        cmp     al, 2
347
        cmp     al, 2
349
        jne     .no_options
348
        jne     .no_options
350
 
349
 
351
        test    [edx + TCP_header.Flags], TH_SYN
350
        test    [edx + TCP_header.Flags], TH_SYN
352
        jz      @f
351
        jz      @f
353
 
352
 
354
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Selective Acknowledgement permitted\n"
353
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Selective Acknowledgement permitted\n"
355
        or      [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT
354
        or      [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT
356
 
355
 
357
       @@:
356
       @@:
358
        jmp     .opt_loop
357
        jmp     .opt_loop
359
 
358
 
360
 
359
 
361
  .opt_timestamp:
360
  .opt_timestamp:
362
        lodsb
361
        lodsb
363
        cmp     al, 10                          ; length must be 10
362
        cmp     al, 10                          ; length must be 10
364
        jne     .no_options
363
        jne     .no_options
365
 
364
 
366
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got timestamp option\n"
365
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got timestamp option\n"
367
 
366
 
368
        test    [edx + TCP_header.Flags], TH_SYN
367
        test    [edx + TCP_header.Flags], TH_SYN
369
        jz      @f
368
        jz      @f
370
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
369
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
371
       @@:
370
       @@:
372
 
371
 
373
        lodsd
372
        lodsd
374
        bswap   eax
373
        bswap   eax
375
        mov     [ebx + TCP_SOCKET.ts_val], eax
374
        mov     [ebx + TCP_SOCKET.ts_val], eax
376
        lodsd                                   ; timestamp echo reply
375
        lodsd                                   ; timestamp echo reply
377
        mov     [ebx + TCP_SOCKET.ts_ecr], eax
376
        mov     [ebx + TCP_SOCKET.ts_ecr], eax
378
        or      [temp_bits], TCP_BIT_TIMESTAMP
377
        or      [temp_bits], TCP_BIT_TIMESTAMP
379
 
378
 
380
        ; Since we have a timestamp, lets do the paws test right away!
379
        ; Since we have a timestamp, lets do the paws test right away!
381
 
380
 
382
        test    [edx + TCP_header.Flags], TH_RST
381
        test    [edx + TCP_header.Flags], TH_RST
383
        jnz     .no_paws
382
        jnz     .no_paws
384
 
383
 
385
        mov     eax, [ebx + TCP_SOCKET.ts_recent]
384
        mov     eax, [ebx + TCP_SOCKET.ts_recent]
386
        test    eax, eax
385
        test    eax, eax
387
        jz      .no_paws
386
        jz      .no_paws
388
        cmp     eax, [ebx + TCP_SOCKET.ts_val]
387
        cmp     eax, [ebx + TCP_SOCKET.ts_val]
389
        jbe     .no_paws
388
        jbe     .no_paws
390
 
389
 
391
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: PAWS: detected an old segment\n"
390
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: PAWS: detected an old segment\n"
392
 
391
 
393
        mov     eax, [timestamp]
392
        mov     eax, [timestamp]
394
        sub     eax, [ebx + TCP_SOCKET.ts_recent_age]
393
        sub     eax, [ebx + TCP_SOCKET.ts_recent_age]
395
 
394
 
396
        pop     ecx
395
        pop     ecx
397
        cmp     eax, TCP_PAWS_IDLE
396
        cmp     eax, TCP_PAWS_IDLE
398
        jle     .drop_after_ack                         ; TODO: update stats
397
        jle     .drop_after_ack                         ; TODO: update stats
399
        push    ecx
398
        push    ecx
400
 
399
 
401
        mov     [ebx + TCP_SOCKET.ts_recent], 0         ; timestamp was invalid, fix it.
400
        mov     [ebx + TCP_SOCKET.ts_recent], 0         ; timestamp was invalid, fix it.
402
  .no_paws:
401
  .no_paws:
403
        jmp     .opt_loop
402
        jmp     .opt_loop
404
 
403
 
405
  .no_options:
404
  .no_options:
406
 
405
 
407
        pop     ecx
406
        pop     ecx
408
 
407
 
409
;-----------------------------------------------------------------------
408
;-----------------------------------------------------------------------
410
; Time to do some header prediction (Original Principle by Van Jacobson)
409
; Time to do some header prediction (Original Principle by Van Jacobson)
411
 
410
 
412
; There are two common cases for an uni-directional data transfer.
411
; There are two common cases for an uni-directional data transfer.
413
;
412
;
414
; General rule: the packets has no control flags, is in-sequence,
413
; General rule: the packets has no control flags, is in-sequence,
415
;   window width didnt change and we're not retransmitting.
414
;   window width didnt change and we're not retransmitting.
416
;
415
;
417
; Second rules:
416
; Second rules:
418
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
417
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
419
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
418
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
420
;
419
;
421
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
420
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
422
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
421
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
423
 
422
 
424
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
423
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
425
        jnz     .not_uni_xfer
424
        jnz     .not_uni_xfer
426
 
425
 
427
        test    [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
426
        test    [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
428
        jnz     .not_uni_xfer
427
        jnz     .not_uni_xfer
429
 
428
 
430
        test    [edx + TCP_header.Flags], TH_ACK
429
        test    [edx + TCP_header.Flags], TH_ACK
431
        jz      .not_uni_xfer
430
        jz      .not_uni_xfer
432
 
431
 
433
        mov     eax, [edx + TCP_header.SequenceNumber]
432
        mov     eax, [edx + TCP_header.SequenceNumber]
434
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
433
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
435
        jne     .not_uni_xfer
434
        jne     .not_uni_xfer
436
 
435
 
437
        mov     eax, dword [edx + TCP_header.Window]
436
        mov     eax, dword [edx + TCP_header.Window]
438
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
437
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
439
        jne     .not_uni_xfer
438
        jne     .not_uni_xfer
440
 
439
 
441
        mov     eax, [ebx + TCP_SOCKET.SND_NXT]
440
        mov     eax, [ebx + TCP_SOCKET.SND_NXT]
442
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
441
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
443
        jne     .not_uni_xfer
442
        jne     .not_uni_xfer
444
 
443
 
445
;---------------------------------------
444
;---------------------------------------
446
; check if we are sender in the uni-xfer
445
; check if we are sender in the uni-xfer
447
 
446
 
448
; If the following 4 conditions are all true, this segment is a pure ACK.
447
; If the following 4 conditions are all true, this segment is a pure ACK.
449
;
448
;
450
; - The segment contains no data.
449
; - The segment contains no data.
451
        test    ecx, ecx
450
        test    ecx, ecx
452
        jnz     .not_sender
451
        jnz     .not_sender
453
 
452
 
454
; - The congestion window is greater than or equal to the current send window.
453
; - The congestion window is greater than or equal to the current send window.
455
;     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.
454
;     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.
456
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
455
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
457
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
456
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
458
        jb      .not_uni_xfer
457
        jb      .not_uni_xfer
459
 
458
 
460
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
459
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
461
        mov     eax, [edx + TCP_header.AckNumber]
460
        mov     eax, [edx + TCP_header.AckNumber]
462
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
461
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
463
        ja      .not_uni_xfer
462
        ja      .not_uni_xfer
464
 
463
 
465
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
464
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
466
        sub     eax, [ebx + TCP_SOCKET.SND_UNA]
465
        sub     eax, [ebx + TCP_SOCKET.SND_UNA]
467
        jbe     .not_uni_xfer
466
        jbe     .not_uni_xfer
468
 
467
 
469
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are sender\n"
468
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are sender\n"
470
 
469
 
471
;---------------------------------
470
;---------------------------------
472
; Packet is a pure ACK, process it
471
; Packet is a pure ACK, process it
473
 
472
 
474
; Delete acknowledged bytes from send buffer
473
; Delete acknowledged bytes from send buffer
475
        pusha
474
        pusha
476
        mov     ecx, eax
475
        mov     ecx, eax
477
        lea     eax, [ebx + STREAM_SOCKET.snd]
476
        lea     eax, [ebx + STREAM_SOCKET.snd]
478
        call    SOCKET_ring_free
477
        call    SOCKET_ring_free
479
        popa
478
        popa
480
 
479
 
481
; Update RTT estimators
480
; Update RTT estimators
482
 
481
 
483
        test    [temp_bits], TCP_BIT_TIMESTAMP
482
        test    [temp_bits], TCP_BIT_TIMESTAMP
484
        jz      .no_timestamp_rtt
483
        jz      .no_timestamp_rtt
485
        mov     eax, [timestamp]
484
        mov     eax, [timestamp]
486
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
485
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
487
        inc     eax
486
        inc     eax
488
        call    TCP_xmit_timer
487
        call    TCP_xmit_timer
489
        jmp     .rtt_done
488
        jmp     .rtt_done
490
 
489
 
491
  .no_timestamp_rtt:
490
  .no_timestamp_rtt:
492
        cmp     [ebx + TCP_SOCKET.t_rtt], 0
491
        cmp     [ebx + TCP_SOCKET.t_rtt], 0
493
        je      .rtt_done
492
        je      .rtt_done
494
        mov     eax, [edx + TCP_header.AckNumber]
493
        mov     eax, [edx + TCP_header.AckNumber]
495
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
494
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
496
        jbe     .rtt_done
495
        jbe     .rtt_done
497
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
496
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
498
        call    TCP_xmit_timer
497
        call    TCP_xmit_timer
499
 
498
 
500
  .rtt_done:
499
  .rtt_done:
501
 
500
 
502
; update window pointers
501
; update window pointers
503
        mov     eax, [edx + TCP_header.AckNumber]
502
        mov     eax, [edx + TCP_header.AckNumber]
504
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
503
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
505
 
504
 
506
; Stop retransmit timer
505
; Stop retransmit timer
507
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
506
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
508
 
507
 
509
; Unlock the socket
508
; Unlock the socket
510
        pusha
509
        pusha
511
        lea     ecx, [ebx + SOCKET.mutex]
510
        lea     ecx, [ebx + SOCKET.mutex]
512
        call    mutex_unlock
511
        call    mutex_unlock
513
        popa
512
        popa
514
 
513
 
515
; Awaken waiting processes
514
; Awaken waiting processes
516
        mov     eax, ebx
515
        mov     eax, ebx
517
        call    SOCKET_notify
516
        call    SOCKET_notify
518
 
517
 
519
; Generate more output
518
; Generate more output
520
        call    TCP_output
519
        call    TCP_output
521
 
520
 
522
        jmp     .drop_no_socket
521
        jmp     .drop_no_socket
523
 
522
 
524
;-------------------------------------------------
523
;-------------------------------------------------
525
; maybe we are the receiver in the uni-xfer then..
524
; maybe we are the receiver in the uni-xfer then..
526
 
525
 
527
  .not_sender:
526
  .not_sender:
528
; - The amount of data in the segment is greater than 0 (data count is in ecx)
527
; - The amount of data in the segment is greater than 0 (data count is in ecx)
529
 
528
 
530
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
529
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
531
        mov     eax, [edx + TCP_header.AckNumber]
530
        mov     eax, [edx + TCP_header.AckNumber]
532
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
531
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
533
        jne     .not_uni_xfer
532
        jne     .not_uni_xfer
534
 
533
 
535
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
534
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
536
 
535
 
537
;;; TODO
536
;;; TODO
538
 
537
 
539
;       jnz     .not_uni_xfer
538
;       jnz     .not_uni_xfer
540
 
539
 
541
; Complete processing of received data
540
; Complete processing of received data
542
 
541
 
543
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx
542
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx
544
 
543
 
545
        mov     esi, [dataoffset]
544
        mov     esi, [dataoffset]
546
        add     esi, edx
545
        add     esi, edx
547
        lea     eax, [ebx + STREAM_SOCKET.rcv]
546
        lea     eax, [ebx + STREAM_SOCKET.rcv]
548
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
547
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
549
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
548
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
550
 
549
 
551
        mov     eax, ebx
550
        mov     eax, ebx
552
        call    SOCKET_notify
551
        call    SOCKET_notify
553
 
552
 
554
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK   ; Set delayed ack flag
553
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK   ; Set delayed ack flag
555
 
554
 
556
        jmp     .drop
555
        jmp     .drop
557
 
556
 
558
;--------------------------------------------------
557
;--------------------------------------------------
559
; Header prediction failed, do it the slow way
558
; Header prediction failed, do it the slow way
560
 
559
 
561
  .not_uni_xfer:
560
  .not_uni_xfer:
562
 
561
 
563
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n"
562
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n"
564
 
563
 
565
; Calculate receive window size
564
; Calculate receive window size
566
        push    edx
565
        push    edx
567
        mov     eax, SOCKET_MAXDATA
566
        mov     eax, SOCKET_MAXDATA
568
        sub     eax, [ebx + STREAM_SOCKET.rcv.size]
567
        sub     eax, [ebx + STREAM_SOCKET.rcv.size]
569
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Space in receive buffer=%d\n", eax
568
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Space in receive buffer=%d\n", eax
570
        mov     edx, [ebx + TCP_SOCKET.RCV_ADV]
569
        mov     edx, [ebx + TCP_SOCKET.RCV_ADV]
571
        sub     edx, [ebx + TCP_SOCKET.RCV_NXT]
570
        sub     edx, [ebx + TCP_SOCKET.RCV_NXT]
572
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Current advertised window=%d\n", edx
571
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Current advertised window=%d\n", edx
573
        cmp     eax, edx
572
        cmp     eax, edx
574
        jg      @f
573
        jg      @f
575
        mov     eax, edx
574
        mov     eax, edx
576
       @@:
575
       @@:
577
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Receive window size=%d\n", eax
576
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Receive window size=%d\n", eax
578
        mov     [ebx + TCP_SOCKET.RCV_WND], eax
577
        mov     [ebx + TCP_SOCKET.RCV_WND], eax
579
        pop     edx
578
        pop     edx
580
 
579
 
581
; If we are in listen or syn_sent state, go to that specific code right away
580
; If we are in listen or syn_sent state, go to that specific code right away
582
 
581
 
583
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
582
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
584
        je      .LISTEN
583
        je      .LISTEN
585
 
584
 
586
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
585
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
587
        je      .SYN_SENT
586
        je      .SYN_SENT
588
 
587
 
589
;----------------------------
588
;----------------------------
590
; trim any data not in window
589
; trim any data not in window
591
 
590
 
592
; 1. Check for duplicate data at beginning of segment
591
; 1. Check for duplicate data at beginning of segment
593
 
592
 
594
; Calculate number of bytes we need to drop
593
; Calculate number of bytes we need to drop
595
        mov     eax, [ebx + TCP_SOCKET.RCV_NXT]
594
        mov     eax, [ebx + TCP_SOCKET.RCV_NXT]
596
        sub     eax, [edx + TCP_header.SequenceNumber]
595
        sub     eax, [edx + TCP_header.SequenceNumber]
597
        jle     .no_duplicate
596
        jle     .no_duplicate
598
 
597
 
599
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes duplicate data!\n", eax
598
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes duplicate data!\n", eax
600
 
599
 
601
        test    [edx + TCP_header.Flags], TH_SYN
600
        test    [edx + TCP_header.Flags], TH_SYN
602
        jz      .no_dup_syn
601
        jz      .no_dup_syn
603
 
602
 
604
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: got duplicate syn\n"
603
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: got duplicate syn\n"
605
 
604
 
606
        and     [edx + TCP_header.Flags], not (TH_SYN)
605
        and     [edx + TCP_header.Flags], not (TH_SYN)
607
        inc     [edx + TCP_header.SequenceNumber]
606
        inc     [edx + TCP_header.SequenceNumber]
608
 
607
 
609
        cmp     [edx + TCP_header.UrgentPointer], 1
608
        cmp     [edx + TCP_header.UrgentPointer], 1
610
        jbe     @f
609
        jbe     @f
611
        dec     [edx + TCP_header.UrgentPointer]
610
        dec     [edx + TCP_header.UrgentPointer]
612
        jmp     .dup_syn
611
        jmp     .dup_syn
613
       @@:
612
       @@:
614
        and     [edx + TCP_header.Flags], not (TH_URG)
613
        and     [edx + TCP_header.Flags], not (TH_URG)
615
  .dup_syn:
614
  .dup_syn:
616
        dec     eax
615
        dec     eax
617
  .no_dup_syn:
616
  .no_dup_syn:
618
 
617
 
619
; 2. Check for entire duplicate segment
618
; 2. Check for entire duplicate segment
620
        cmp     eax, ecx                ; eax holds number of bytes to drop, ecx is data size
619
        cmp     eax, ecx                ; eax holds number of bytes to drop, ecx is data size
621
        jb      .duplicate
620
        jb      .duplicate
622
        jnz     @f
621
        jnz     @f
623
        test    [edx + TCP_header.Flags], TH_FIN
622
        test    [edx + TCP_header.Flags], TH_FIN
624
        jnz     .duplicate
623
        jnz     .duplicate
625
       @@:
624
       @@:
626
 
625
 
627
; Any valid FIN must be to the left of the window.
626
; Any valid FIN must be to the left of the window.
628
; At this point the FIN must be out of sequence or a duplicate, drop it
627
; At this point the FIN must be out of sequence or a duplicate, drop it
629
        and     [edx + TCP_header.Flags], not TH_FIN
628
        and     [edx + TCP_header.Flags], not TH_FIN
630
 
629
 
631
; send an ACK and resynchronize and drop any data.
630
; send an ACK and resynchronize and drop any data.
632
; But keep on processing for RST or ACK
631
; But keep on processing for RST or ACK
633
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
632
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
634
        mov     eax, ecx
633
        mov     eax, ecx
635
 
634
 
636
;;; TODO: update stats
635
;;; TODO: update stats
637
 
636
 
638
;-----------------------------------------------
637
;-----------------------------------------------
639
; Remove duplicate data and update urgent offset
638
; Remove duplicate data and update urgent offset
640
 
639
 
641
  .duplicate:
640
  .duplicate:
642
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: trimming duplicate data\n"
641
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: trimming duplicate data\n"
643
 
642
 
644
; Trim data from left side of window
643
; Trim data from left side of window
645
        add     [dataoffset], eax
644
        add     [dataoffset], eax
646
        add     [edx + TCP_header.SequenceNumber], eax
645
        add     [edx + TCP_header.SequenceNumber], eax
647
        sub     ecx, eax
646
        sub     ecx, eax
648
 
647
 
649
        sub     [edx + TCP_header.UrgentPointer], ax
648
        sub     [edx + TCP_header.UrgentPointer], ax
650
        jg      @f
649
        jg      @f
651
        and     [edx + TCP_header.Flags], not (TH_URG)
650
        and     [edx + TCP_header.Flags], not (TH_URG)
652
        mov     [edx + TCP_header.UrgentPointer], 0
651
        mov     [edx + TCP_header.UrgentPointer], 0
653
       @@:
652
       @@:
654
 
653
 
655
;--------------------------------------------------
654
;--------------------------------------------------
656
; Handle data that arrives after process terminates
655
; Handle data that arrives after process terminates
657
 
656
 
658
  .no_duplicate:
657
  .no_duplicate:
659
        cmp     [ebx + SOCKET.PID], 0                   ;;; TODO: use socket flags instead??
658
        cmp     [ebx + SOCKET.PID], 0                   ;;; TODO: use socket flags instead??
660
        jne     .not_terminated
659
        jne     .not_terminated
661
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
660
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
662
        jbe     .not_terminated
661
        jbe     .not_terminated
663
        test    ecx, ecx
662
        test    ecx, ecx
664
        jz      .not_terminated
663
        jz      .not_terminated
665
 
664
 
666
        mov     eax, ebx
665
        mov     eax, ebx
667
        call    TCP_close
666
        call    TCP_close
668
;;; TODO: update stats
667
;;; TODO: update stats
669
        jmp     .respond_seg_reset
668
        jmp     .respond_seg_reset
670
 
669
 
671
;----------------------------------------
670
;----------------------------------------
672
; Remove data beyond right edge of window
671
; Remove data beyond right edge of window
673
 
672
 
674
  .not_terminated:
673
  .not_terminated:
675
        mov     eax, [edx + TCP_header.SequenceNumber]
674
        mov     eax, [edx + TCP_header.SequenceNumber]
676
        add     eax, ecx
675
        add     eax, ecx
677
        sub     eax, [ebx + TCP_SOCKET.RCV_NXT]
676
        sub     eax, [ebx + TCP_SOCKET.RCV_NXT]
678
        sub     eax, [ebx + TCP_SOCKET.RCV_WND]         ; eax now holds the number of bytes to drop
677
        sub     eax, [ebx + TCP_SOCKET.RCV_WND]         ; eax now holds the number of bytes to drop
679
        jle     .no_excess_data
678
        jle     .no_excess_data
680
 
679
 
681
        DEBUGF  DEBUG_NETWORK_VERBOSE, "%d bytes beyond right edge of window\n", eax
680
        DEBUGF  DEBUG_NETWORK_VERBOSE, "%d bytes beyond right edge of window\n", eax
682
 
681
 
683
;;; TODO: update stats
682
;;; TODO: update stats
684
        cmp     eax, ecx
683
        cmp     eax, ecx
685
        jl      .dont_drop_all
684
        jl      .dont_drop_all
686
; If a new connection request is received while in TIME_WAIT, drop the old connection and start over,
685
; If a new connection request is received while in TIME_WAIT, drop the old connection and start over,
687
; if the sequence numbers are above the previous ones
686
; if the sequence numbers are above the previous ones
688
 
687
 
689
        test    [edx + TCP_header.Flags], TH_SYN
688
        test    [edx + TCP_header.Flags], TH_SYN
690
        jz      .no_new_request
689
        jz      .no_new_request
691
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
690
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
692
        jne     .no_new_request
691
        jne     .no_new_request
693
;        mov     edx, [ebx + TCP_SOCKET.RCV_NXT]
692
;        mov     edx, [ebx + TCP_SOCKET.RCV_NXT]
694
;        cmp     edx, [edx + TCP_header.SequenceNumber]
693
;        cmp     edx, [edx + TCP_header.SequenceNumber]
695
;        add     edx, 64000      ; TCP_ISSINCR   FIXME
694
;        add     edx, 64000      ; TCP_ISSINCR   FIXME
696
        mov     eax, ebx
695
        mov     eax, ebx
697
        call    TCP_close
696
        call    TCP_close
698
        jmp     .findpcb        ; FIXME: skip code for unscaling window, ...
697
        jmp     .findpcb        ; FIXME: skip code for unscaling window, ...
699
  .no_new_request:
698
  .no_new_request:
700
 
699
 
701
; If window is closed, we can only take segments at window edge, and have to drop data and PUSH from
700
; If window is closed, we can only take segments at window edge, and have to drop data and PUSH from
702
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
701
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
703
 
702
 
704
        cmp     [ebx + TCP_SOCKET.RCV_WND], 0
703
        cmp     [ebx + TCP_SOCKET.RCV_WND], 0
705
        jne     .drop_after_ack
704
        jne     .drop_after_ack
706
        mov     esi, [edx + TCP_header.SequenceNumber]
705
        mov     esi, [edx + TCP_header.SequenceNumber]
707
        cmp     esi, [ebx + TCP_SOCKET.RCV_NXT]
706
        cmp     esi, [ebx + TCP_SOCKET.RCV_NXT]
708
        jne     .drop_after_ack
707
        jne     .drop_after_ack
709
 
708
 
710
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
709
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
711
;;; TODO: update stats
710
;;; TODO: update stats
712
  .dont_drop_all:
711
  .dont_drop_all:
713
;;; TODO: update stats
712
;;; TODO: update stats
714
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Trimming %u bytes from the right of the window\n"
713
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Trimming %u bytes from the right of the window\n"
715
        sub     ecx, eax        ; remove data from the right side of window (decrease data length)
714
        sub     ecx, eax        ; remove data from the right side of window (decrease data length)
716
        and     [edx + TCP_header.Flags], not (TH_PUSH or TH_FIN)
715
        and     [edx + TCP_header.Flags], not (TH_PUSH or TH_FIN)
717
  .no_excess_data:
716
  .no_excess_data:
718
 
717
 
719
;-----------------
718
;-----------------
720
; Record timestamp
719
; Record timestamp
721
 
720
 
722
; If last ACK falls within this segments sequence numbers, record its timestamp
721
; If last ACK falls within this segments sequence numbers, record its timestamp
723
        test    [temp_bits], TCP_BIT_TIMESTAMP
722
        test    [temp_bits], TCP_BIT_TIMESTAMP
724
        jz      .no_timestamp
723
        jz      .no_timestamp
725
        mov     eax, [ebx + TCP_SOCKET.last_ack_sent]
724
        mov     eax, [ebx + TCP_SOCKET.last_ack_sent]
726
        sub     eax, [edx + TCP_header.SequenceNumber]
725
        sub     eax, [edx + TCP_header.SequenceNumber]
727
        jb      .no_timestamp
726
        jb      .no_timestamp
728
        test    [ebx + TCP_header.Flags], TH_SYN or TH_FIN      ; syn and fin occupy one byte
727
        test    [ebx + TCP_header.Flags], TH_SYN or TH_FIN      ; syn and fin occupy one byte
729
        jz      @f
728
        jz      @f
730
        dec     eax
729
        dec     eax
731
       @@:
730
       @@:
732
        sub     eax, ecx
731
        sub     eax, ecx
733
        jae     .no_timestamp
732
        jae     .no_timestamp
734
 
733
 
735
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Recording timestamp\n"
734
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Recording timestamp\n"
736
 
735
 
737
        mov     eax, [timestamp]
736
        mov     eax, [timestamp]
738
        mov     [ebx + TCP_SOCKET.ts_recent_age], eax
737
        mov     [ebx + TCP_SOCKET.ts_recent_age], eax
739
        mov     eax, [ebx + TCP_SOCKET.ts_val]
738
        mov     eax, [ebx + TCP_SOCKET.ts_val]
740
        mov     [ebx + TCP_SOCKET.ts_recent], eax
739
        mov     [ebx + TCP_SOCKET.ts_recent], eax
741
  .no_timestamp:
740
  .no_timestamp:
742
 
741
 
743
;------------------
742
;------------------
744
; Process RST flags
743
; Process RST flags
745
 
744
 
746
        test    [edx + TCP_header.Flags], TH_RST
745
        test    [edx + TCP_header.Flags], TH_RST
747
        jz      .no_rst
746
        jz      .no_rst
748
 
747
 
749
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got an RST flag\n"
748
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got an RST flag\n"
750
 
749
 
751
        mov     eax, [ebx + TCP_SOCKET.t_state]
750
        mov     eax, [ebx + TCP_SOCKET.t_state]
752
        shl     eax, 2
751
        shl     eax, 2
753
        jmp     dword [eax + .rst_sw_list]
752
        jmp     dword [eax + .rst_sw_list]
754
 
753
 
755
  .rst_sw_list:
754
  .rst_sw_list:
756
        dd      .no_rst         ; TCPS_CLOSED
755
        dd      .no_rst         ; TCPS_CLOSED
757
        dd      .no_rst         ; TCPS_LISTEN
756
        dd      .no_rst         ; TCPS_LISTEN
758
        dd      .no_rst         ; TCPS_SYN_SENT
757
        dd      .no_rst         ; TCPS_SYN_SENT
759
        dd      .econnrefused   ; TCPS_SYN_RECEIVED
758
        dd      .econnrefused   ; TCPS_SYN_RECEIVED
760
        dd      .econnreset     ; TCPS_ESTABLISHED
759
        dd      .econnreset     ; TCPS_ESTABLISHED
761
        dd      .econnreset     ; TCPS_CLOSE_WAIT
760
        dd      .econnreset     ; TCPS_CLOSE_WAIT
762
        dd      .econnreset     ; TCPS_FIN_WAIT_1
761
        dd      .econnreset     ; TCPS_FIN_WAIT_1
763
        dd      .rst_close      ; TCPS_CLOSING
762
        dd      .rst_close      ; TCPS_CLOSING
764
        dd      .rst_close      ; TCPS_LAST_ACK
763
        dd      .rst_close      ; TCPS_LAST_ACK
765
        dd      .econnreset     ; TCPS_FIN_WAIT_2
764
        dd      .econnreset     ; TCPS_FIN_WAIT_2
766
        dd      .rst_close      ; TCPS_TIMED_WAIT
765
        dd      .rst_close      ; TCPS_TIMED_WAIT
767
 
766
 
768
  .econnrefused:
767
  .econnrefused:
769
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Connection refused\n"
768
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Connection refused\n"
770
 
769
 
771
        mov     [ebx + SOCKET.errorcode], ECONNREFUSED
770
        mov     [ebx + SOCKET.errorcode], ECONNREFUSED
772
        jmp     .close
771
        jmp     .close
773
 
772
 
774
  .econnreset:
773
  .econnreset:
775
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n"
774
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n"
776
 
775
 
777
        mov     [ebx + SOCKET.errorcode], ECONNRESET
776
        mov     [ebx + SOCKET.errorcode], ECONNRESET
778
 
777
 
779
  .close:
778
  .close:
780
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Closing connection\n"
779
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Closing connection\n"
781
 
780
 
782
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
781
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
783
;;; TODO: update stats (tcp drops)
782
;;; TODO: update stats (tcp drops)
784
        mov     eax, ebx
783
        mov     eax, ebx
785
        call    TCP_close
784
        call    TCP_close
786
        jmp     .drop_no_socket
785
        jmp     .drop_no_socket
787
 
786
 
788
  .rst_close:
787
  .rst_close:
789
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n"
788
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n"
790
 
789
 
791
        mov     eax, ebx
790
        mov     eax, ebx
792
        call    TCP_close
791
        call    TCP_close
793
        jmp     .drop_no_socket
792
        jmp     .drop_no_socket
794
 
793
 
795
  .no_rst:
794
  .no_rst:
796
 
795
 
797
;--------------------------------------
796
;--------------------------------------
798
; handle SYN-full and ACK-less segments
797
; handle SYN-full and ACK-less segments
799
 
798
 
800
        test    [edx + TCP_header.Flags], TH_SYN
799
        test    [edx + TCP_header.Flags], TH_SYN
801
        jz      .not_syn_full
800
        jz      .not_syn_full
802
 
801
 
803
        mov     eax, ebx
802
        mov     eax, ebx
804
        mov     ebx, ECONNRESET
803
        mov     ebx, ECONNRESET
805
        call    TCP_drop
804
        call    TCP_drop
806
        jmp     .drop_with_reset
805
        jmp     .drop_with_reset
807
  .not_syn_full:
806
  .not_syn_full:
808
 
807
 
809
;---------------
808
;---------------
810
; ACK processing
809
; ACK processing
811
 
810
 
812
        test    [edx + TCP_header.Flags], TH_ACK
811
        test    [edx + TCP_header.Flags], TH_ACK
813
        jz      .drop
812
        jz      .drop
814
 
813
 
815
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
814
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
816
        jb      .ack_processed                                  ; states: closed, listen, syn_sent
815
        jb      .ack_processed                                  ; states: closed, listen, syn_sent
817
        ja      .no_syn_rcv                                     ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
816
        ja      .no_syn_rcv                                     ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
818
 
817
 
819
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_received\n"
818
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_received\n"
820
 
819
 
821
        mov     eax, [edx + TCP_header.AckNumber]
820
        mov     eax, [edx + TCP_header.AckNumber]
822
        cmp     [ebx + TCP_SOCKET.SND_UNA], eax
821
        cmp     [ebx + TCP_SOCKET.SND_UNA], eax
823
        ja      .drop_with_reset
822
        ja      .drop_with_reset
824
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
823
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
825
        ja      .drop_with_reset
824
        ja      .drop_with_reset
826
 
825
 
827
;;; TODO: update stats
826
;;; TODO: update stats
828
 
827
 
829
        mov     eax, ebx
828
        mov     eax, ebx
830
        call    SOCKET_is_connected
829
        call    SOCKET_is_connected
831
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
830
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
832
 
831
 
833
; Do window scaling?
832
; Do window scaling?
834
 
833
 
835
        test    [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
834
        test    [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
836
        jz      @f
835
        jz      @f
837
        test    [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
836
        test    [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
838
        jz      @f
837
        jz      @f
839
 
838
 
840
        push    word [ebx + TCP_SOCKET.requested_s_scale]       ; Set send and receive scale factors to the received values
839
        push    word [ebx + TCP_SOCKET.requested_s_scale]       ; Set send and receive scale factors to the received values
841
        pop     word [ebx + TCP_SOCKET.SND_SCALE]
840
        pop     word [ebx + TCP_SOCKET.SND_SCALE]
842
       @@:
841
       @@:
843
 
842
 
844
;;; TODO: call TCP_reassemble
843
;;; TODO: call TCP_reassemble
845
 
844
 
846
        mov     eax, [edx + TCP_header.SequenceNumber]
845
        mov     eax, [edx + TCP_header.SequenceNumber]
847
        dec     eax
846
        dec     eax
848
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
847
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
849
 
848
 
850
  .no_syn_rcv:
849
  .no_syn_rcv:
851
 
850
 
852
;-------------------------
851
;-------------------------
853
; check for duplicate ACKs
852
; check for duplicate ACKs
854
 
853
 
855
        mov     eax, [edx + TCP_header.AckNumber]
854
        mov     eax, [edx + TCP_header.AckNumber]
856
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
855
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
857
        ja      .not_dup_ack
856
        ja      .not_dup_ack
858
 
857
 
859
        test    ecx, ecx
858
        test    ecx, ecx
860
        jnz     .reset_dupacks
859
        jnz     .reset_dupacks
861
 
860
 
862
        mov     eax, dword [edx + TCP_header.Window]
861
        mov     eax, dword [edx + TCP_header.Window]
863
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
862
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
864
        jne     .reset_dupacks
863
        jne     .reset_dupacks
865
 
864
 
866
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n"
865
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n"
867
 
866
 
868
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
867
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
869
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
868
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
870
; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet.
869
; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet.
871
 
870
 
872
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
871
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
873
        jz      @f
872
        jz      @f
874
 
873
 
875
        mov     eax, [edx + TCP_header.AckNumber]
874
        mov     eax, [edx + TCP_header.AckNumber]
876
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
875
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
877
        je      .dup_ack
876
        je      .dup_ack
878
 
877
 
879
       @@:
878
       @@:
880
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
879
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
881
        jmp     .not_dup_ack
880
        jmp     .not_dup_ack
882
 
881
 
883
  .dup_ack:
882
  .dup_ack:
884
        inc     [ebx + TCP_SOCKET.t_dupacks]
883
        inc     [ebx + TCP_SOCKET.t_dupacks]
885
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
884
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
886
        jne     .no_re_xmit
885
        jne     .no_re_xmit
887
 
886
 
888
        push    [ebx + TCP_SOCKET.SND_NXT]              ; >>>>
887
        push    [ebx + TCP_SOCKET.SND_NXT]              ; >>>>
889
 
888
 
890
        mov     eax, [ebx + TCP_SOCKET.SND_WND]
889
        mov     eax, [ebx + TCP_SOCKET.SND_WND]
891
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
890
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
892
        jbe     @f
891
        jbe     @f
893
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
892
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
894
  @@:
893
  @@:
895
        shr     eax, 1
894
        shr     eax, 1
896
        push    edx
895
        push    edx
897
        xor     edx, edx
896
        xor     edx, edx
898
        div     [ebx + TCP_SOCKET.t_maxseg]
897
        div     [ebx + TCP_SOCKET.t_maxseg]
899
        cmp     eax, 2
898
        cmp     eax, 2
900
        ja      @f
899
        ja      @f
901
        xor     eax, eax
900
        xor     eax, eax
902
        mov     al, 2
901
        mov     al, 2
903
       @@:
902
       @@:
904
        mul     [ebx + TCP_SOCKET.t_maxseg]
903
        mul     [ebx + TCP_SOCKET.t_maxseg]
905
        pop     edx
904
        pop     edx
906
        mov     [ebx + TCP_SOCKET.SND_SSTHRESH], eax
905
        mov     [ebx + TCP_SOCKET.SND_SSTHRESH], eax
907
 
906
 
908
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; turn off retransmission timer
907
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; turn off retransmission timer
909
        mov     [ebx + TCP_SOCKET.t_rtt], 0
908
        mov     [ebx + TCP_SOCKET.t_rtt], 0
910
        mov     eax, [edx + TCP_header.AckNumber]
909
        mov     eax, [edx + TCP_header.AckNumber]
911
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
910
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
912
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
911
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
913
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
912
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
914
 
913
 
915
; Unlock the socket
914
; Unlock the socket
916
        push    ebx
915
        push    ebx
917
        lea     ecx, [ebx + SOCKET.mutex]
916
        lea     ecx, [ebx + SOCKET.mutex]
918
        call    mutex_unlock
917
        call    mutex_unlock
919
 
918
 
920
; retransmit missing segment
919
; retransmit missing segment
921
        mov     eax, [esp]
920
        mov     eax, [esp]
922
        call    TCP_output
921
        call    TCP_output
923
 
922
 
924
; Lock the socket again
923
; Lock the socket again
925
        mov     ecx, [esp]
924
        mov     ecx, [esp]
926
        add     ecx, SOCKET.mutex
925
        add     ecx, SOCKET.mutex
927
        call    mutex_lock
926
        call    mutex_lock
928
        pop     ebx
927
        pop     ebx
929
 
928
 
930
; Continue processing
929
; Continue processing
931
        xor     edx, edx
930
        xor     edx, edx
932
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
931
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
933
        mul     [ebx + TCP_SOCKET.t_dupacks]
932
        mul     [ebx + TCP_SOCKET.t_dupacks]
934
        add     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
933
        add     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
935
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
934
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
936
 
935
 
937
        pop     eax                                     ; <<<<
936
        pop     eax                                     ; <<<<
938
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
937
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
939
        jb      @f
938
        jb      @f
940
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
939
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
941
       @@:
940
       @@:
942
 
941
 
943
        jmp     .drop
942
        jmp     .drop
944
 
943
 
945
 
944
 
946
  .no_re_xmit:
945
  .no_re_xmit:
947
        jbe     .not_dup_ack
946
        jbe     .not_dup_ack
948
 
947
 
949
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n"
948
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n"
950
 
949
 
951
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
950
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
952
        add     [ebx + TCP_SOCKET.SND_CWND], eax
951
        add     [ebx + TCP_SOCKET.SND_CWND], eax
953
 
952
 
954
; Unlock the socket
953
; Unlock the socket
955
        push    ebx
954
        push    ebx
956
        lea     ecx, [ebx + SOCKET.mutex]
955
        lea     ecx, [ebx + SOCKET.mutex]
957
        call    mutex_unlock
956
        call    mutex_unlock
958
 
957
 
959
; retransmit missing segment
958
; retransmit missing segment
960
        mov     eax, [esp]
959
        mov     eax, [esp]
961
        call    TCP_output
960
        call    TCP_output
962
 
961
 
963
; Lock the socket again
962
; Lock the socket again
964
        mov     ecx, [esp]
963
        mov     ecx, [esp]
965
        add     ecx, SOCKET.mutex
964
        add     ecx, SOCKET.mutex
966
        call    mutex_lock
965
        call    mutex_lock
967
        pop     ebx
966
        pop     ebx
968
 
967
 
969
        jmp     .drop
968
        jmp     .drop
970
 
969
 
971
 
970
 
972
  .not_dup_ack:
971
  .not_dup_ack:
973
 
972
 
974
;-------------------------------------------------
973
;-------------------------------------------------
975
; If the congestion window was inflated to account
974
; If the congestion window was inflated to account
976
; for the other side's cached packets, retract it
975
; for the other side's cached packets, retract it
977
 
976
 
978
        mov     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
977
        mov     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
979
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
978
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
980
        ja      @f
979
        ja      @f
981
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
980
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
982
        jbe     @f
981
        jbe     @f
983
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
982
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
984
       @@:
983
       @@:
985
 
984
 
986
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
985
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
987
 
986
 
988
        mov     eax, [edx + TCP_header.AckNumber]
987
        mov     eax, [edx + TCP_header.AckNumber]
989
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
988
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
990
        jbe     @f
989
        jbe     @f
991
 
990
 
992
        ;;; TODO: update stats
991
        ;;; TODO: update stats
993
        jmp     .drop_after_ack
992
        jmp     .drop_after_ack
994
 
993
 
995
       @@:
994
       @@:
996
 
995
 
997
        mov     edi, [edx + TCP_header.AckNumber]
996
        mov     edi, [edx + TCP_header.AckNumber]
998
        sub     edi, [ebx + TCP_SOCKET.SND_UNA]         ; now we got the number of acked bytes in edi
997
        sub     edi, [ebx + TCP_SOCKET.SND_UNA]         ; now we got the number of acked bytes in edi
999
 
998
 
1000
        ;;; TODO: update stats
999
        ;;; TODO: update stats
1001
 
1000
 
1002
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi
1001
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi
1003
 
1002
 
1004
;------------------------------------------
1003
;------------------------------------------
1005
; RTT measurements and retransmission timer
1004
; RTT measurements and retransmission timer
1006
 
1005
 
1007
; If we have a timestamp, update smoothed RTT
1006
; If we have a timestamp, update smoothed RTT
1008
 
1007
 
1009
        test    [temp_bits], TCP_BIT_TIMESTAMP
1008
        test    [temp_bits], TCP_BIT_TIMESTAMP
1010
        jz      .timestamp_not_present
1009
        jz      .timestamp_not_present
1011
        mov     eax, [timestamp]
1010
        mov     eax, [timestamp]
1012
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
1011
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
1013
        inc     eax
1012
        inc     eax
1014
        call    TCP_xmit_timer
1013
        call    TCP_xmit_timer
1015
        jmp     .rtt_done_
1014
        jmp     .rtt_done_
1016
 
1015
 
1017
; If no timestamp but transmit timer is running and timed sequence number was acked,
1016
; If no timestamp but transmit timer is running and timed sequence number was acked,
1018
; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff
1017
; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff
1019
; (Phil Karn's retransmit algo)
1018
; (Phil Karn's retransmit algo)
1020
; Recompute the initial retransmit timer
1019
; Recompute the initial retransmit timer
1021
 
1020
 
1022
  .timestamp_not_present:
1021
  .timestamp_not_present:
1023
        mov     eax, [edx + TCP_header.AckNumber]
1022
        mov     eax, [edx + TCP_header.AckNumber]
1024
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
1023
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
1025
        jbe     .rtt_done_
1024
        jbe     .rtt_done_
1026
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1025
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1027
        test    eax, eax
1026
        test    eax, eax
1028
        jz      .rtt_done_
1027
        jz      .rtt_done_
1029
        call    TCP_xmit_timer
1028
        call    TCP_xmit_timer
1030
 
1029
 
1031
  .rtt_done_:
1030
  .rtt_done_:
1032
 
1031
 
1033
; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist)
1032
; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist)
1034
; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value.
1033
; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value.
1035
 
1034
 
1036
        mov     eax, [ebx + TCP_SOCKET.SND_MAX]
1035
        mov     eax, [ebx + TCP_SOCKET.SND_MAX]
1037
        cmp     eax, [edx + TCP_header.AckNumber]
1036
        cmp     eax, [edx + TCP_header.AckNumber]
1038
        jne     .more_data
1037
        jne     .more_data
1039
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
1038
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
1040
        or      [temp_bits], TCP_BIT_NEEDOUTPUT
1039
        or      [temp_bits], TCP_BIT_NEEDOUTPUT
1041
        jmp     .no_restart
1040
        jmp     .no_restart
1042
  .more_data:
1041
  .more_data:
1043
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
1042
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
1044
        jnz     .no_restart
1043
        jnz     .no_restart
1045
 
1044
 
1046
        mov     eax, [ebx + TCP_SOCKET.t_rxtcur]
1045
        mov     eax, [ebx + TCP_SOCKET.t_rxtcur]
1047
        mov     [ebx + TCP_SOCKET.timer_retransmission], eax
1046
        mov     [ebx + TCP_SOCKET.timer_retransmission], eax
1048
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
1047
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
1049
  .no_restart:
1048
  .no_restart:
1050
 
1049
 
1051
 
1050
 
1052
;-------------------------------------------
1051
;-------------------------------------------
1053
; Open congestion window in response to ACKs
1052
; Open congestion window in response to ACKs
1054
 
1053
 
1055
        mov     esi, [ebx + TCP_SOCKET.SND_CWND]
1054
        mov     esi, [ebx + TCP_SOCKET.SND_CWND]
1056
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1055
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1057
 
1056
 
1058
        cmp     esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
1057
        cmp     esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
1059
        jbe     @f
1058
        jbe     @f
1060
        push    edx
1059
        push    edx
1061
        push    eax
1060
        push    eax
1062
        mul     eax
1061
        mul     eax
1063
        div     esi
1062
        div     esi
1064
        pop     edx
1063
        pop     edx
1065
        shr     edx, 3
1064
        shr     edx, 3
1066
        add     eax, edx
1065
        add     eax, edx
1067
        pop     edx
1066
        pop     edx
1068
       @@:
1067
       @@:
1069
 
1068
 
1070
        add     esi, eax
1069
        add     esi, eax
1071
 
1070
 
1072
        push    ecx
1071
        push    ecx
1073
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
1072
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
1074
        mov     eax, TCP_max_win
1073
        mov     eax, TCP_max_win
1075
        shl     eax, cl
1074
        shl     eax, cl
1076
        pop     ecx
1075
        pop     ecx
1077
 
1076
 
1078
        cmp     esi, eax
1077
        cmp     esi, eax
1079
        jbe     @f
1078
        jbe     @f
1080
        mov     esi, eax
1079
        mov     esi, eax
1081
  @@:
1080
  @@:
1082
        mov     [ebx + TCP_SOCKET.SND_CWND], esi
1081
        mov     [ebx + TCP_SOCKET.SND_CWND], esi
1083
 
1082
 
1084
;------------------------------------------
1083
;------------------------------------------
1085
; Remove acknowledged data from send buffer
1084
; Remove acknowledged data from send buffer
1086
 
1085
 
1087
        cmp     edi, [ebx + STREAM_SOCKET.snd.size]
1086
        cmp     edi, [ebx + STREAM_SOCKET.snd.size]
1088
        jbe     .finiacked
1087
        jbe     .finiacked
1089
 
1088
 
1090
        push    ecx edx ebx
1089
        push    ecx edx ebx
1091
        mov     ecx, [ebx + STREAM_SOCKET.snd.size]
1090
        mov     ecx, [ebx + STREAM_SOCKET.snd.size]
1092
        lea     eax, [ebx + STREAM_SOCKET.snd]
1091
        lea     eax, [ebx + STREAM_SOCKET.snd]
1093
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1092
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1094
        call    SOCKET_ring_free
1093
        call    SOCKET_ring_free
1095
        pop     ebx edx ecx
1094
        pop     ebx edx ecx
1096
 
1095
 
1097
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n"
1096
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n"
1098
        stc
1097
        stc
1099
 
1098
 
1100
        jmp     .wakeup
1099
        jmp     .wakeup
1101
 
1100
 
1102
  .finiacked:
1101
  .finiacked:
1103
 
1102
 
1104
        push    ecx edx ebx
1103
        push    ecx edx ebx
1105
        mov     ecx, edi
1104
        mov     ecx, edi
1106
        lea     eax, [ebx + STREAM_SOCKET.snd]
1105
        lea     eax, [ebx + STREAM_SOCKET.snd]
1107
        call    SOCKET_ring_free
1106
        call    SOCKET_ring_free
1108
        pop     ebx
1107
        pop     ebx
1109
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1108
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1110
        pop     edx ecx
1109
        pop     edx ecx
1111
 
1110
 
1112
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n"
1111
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n"
1113
        clc
1112
        clc
1114
 
1113
 
1115
;----------------------------------------
1114
;----------------------------------------
1116
; Wake up process waiting on send buffer
1115
; Wake up process waiting on send buffer
1117
 
1116
 
1118
  .wakeup:
1117
  .wakeup:
1119
 
1118
 
1120
        pushf                   ; Keep the flags (Carry flag)
1119
        pushf                   ; Keep the flags (Carry flag)
1121
        mov     eax, ebx
1120
        mov     eax, ebx
1122
        call    SOCKET_notify
1121
        call    SOCKET_notify
1123
 
1122
 
1124
; Update TCPS
1123
; Update TCPS
1125
 
1124
 
1126
        mov     eax, [edx + TCP_header.AckNumber]
1125
        mov     eax, [edx + TCP_header.AckNumber]
1127
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1126
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1128
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1127
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1129
        jb      @f
1128
        jb      @f
1130
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1129
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1131
       @@:
1130
       @@:
1132
 
1131
 
1133
        popf
1132
        popf
1134
 
1133
 
1135
; General ACK handling complete
1134
; General ACK handling complete
1136
; Now do the state-specific ones
1135
; Now do the state-specific ones
1137
; Carry flag is set when our FIN is acked
1136
; Carry flag is set when our FIN is acked
1138
 
1137
 
1139
        mov     eax, [ebx + TCP_SOCKET.t_state]
1138
        mov     eax, [ebx + TCP_SOCKET.t_state]
1140
        jmp     dword [eax*4 + .ACK_sw_list]
1139
        jmp     dword [eax*4 + .ACK_sw_list]
1141
 
1140
 
1142
  .ACK_sw_list:
1141
  .ACK_sw_list:
1143
        dd      .ack_processed  ; TCPS_CLOSED
1142
        dd      .ack_processed  ; TCPS_CLOSED
1144
        dd      .ack_processed  ; TCPS_LISTEN
1143
        dd      .ack_processed  ; TCPS_LISTEN
1145
        dd      .ack_processed  ; TCPS_SYN_SENT
1144
        dd      .ack_processed  ; TCPS_SYN_SENT
1146
        dd      .ack_processed  ; TCPS_SYN_RECEIVED
1145
        dd      .ack_processed  ; TCPS_SYN_RECEIVED
1147
        dd      .ack_processed  ; TCPS_ESTABLISHED
1146
        dd      .ack_processed  ; TCPS_ESTABLISHED
1148
        dd      .ack_processed  ; TCPS_CLOSE_WAIT
1147
        dd      .ack_processed  ; TCPS_CLOSE_WAIT
1149
        dd      .ack_fw1        ; TCPS_FIN_WAIT_1
1148
        dd      .ack_fw1        ; TCPS_FIN_WAIT_1
1150
        dd      .ack_c          ; TCPS_CLOSING
1149
        dd      .ack_c          ; TCPS_CLOSING
1151
        dd      .ack_la         ; TCPS_LAST_ACK
1150
        dd      .ack_la         ; TCPS_LAST_ACK
1152
        dd      .ack_processed  ; TCPS_FIN_WAIT_2
1151
        dd      .ack_processed  ; TCPS_FIN_WAIT_2
1153
        dd      .ack_tw         ; TCPS_TIMED_WAIT
1152
        dd      .ack_tw         ; TCPS_TIMED_WAIT
1154
 
1153
 
1155
 
1154
 
1156
  .ack_fw1:
1155
  .ack_fw1:
1157
        jnc     .ack_processed
1156
        jnc     .ack_processed
1158
 
1157
 
1159
        test    [ebx + SOCKET.state], SS_CANTRCVMORE
1158
        test    [ebx + SOCKET.state], SS_CANTRCVMORE
1160
        jnz     @f
1159
        jnz     @f
1161
        mov     eax, ebx
1160
        mov     eax, ebx
1162
        call    SOCKET_is_disconnected
1161
        call    SOCKET_is_disconnected
1163
        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
1162
        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
1164
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1163
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1165
       @@:
1164
       @@:
1166
        mov     [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1165
        mov     [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1167
        jmp     .ack_processed
1166
        jmp     .ack_processed
1168
 
1167
 
1169
  .ack_c:
1168
  .ack_c:
1170
        jnc     .ack_processed
1169
        jnc     .ack_processed
1171
 
1170
 
1172
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1171
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1173
        mov     eax, ebx
1172
        mov     eax, ebx
1174
        call    TCP_cancel_timers
1173
        call    TCP_cancel_timers
1175
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1174
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1176
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1175
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1177
        mov     eax, ebx
1176
        mov     eax, ebx
1178
        call    SOCKET_is_disconnected
1177
        call    SOCKET_is_disconnected
1179
        jmp     .ack_processed
1178
        jmp     .ack_processed
1180
 
1179
 
1181
  .ack_la:
1180
  .ack_la:
1182
        jnc     .ack_processed
1181
        jnc     .ack_processed
1183
 
1182
 
1184
        push    ebx
1183
        push    ebx
1185
        lea     ecx, [ebx + SOCKET.mutex]
1184
        lea     ecx, [ebx + SOCKET.mutex]
1186
        call    mutex_unlock
1185
        call    mutex_unlock
1187
        pop     ebx
1186
        pop     ebx
1188
 
1187
 
1189
        mov     eax, ebx
1188
        mov     eax, ebx
1190
        call    TCP_close
1189
        call    TCP_close
1191
        jmp     .drop_no_socket
1190
        jmp     .drop_no_socket
1192
 
1191
 
1193
  .ack_tw:
1192
  .ack_tw:
1194
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1193
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1195
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1194
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1196
        jmp     .drop_after_ack
1195
        jmp     .drop_after_ack
1197
 
1196
 
1198
  .reset_dupacks:               ; We got a new ACK, reset duplicate ACK counter
1197
  .reset_dupacks:               ; We got a new ACK, reset duplicate ACK counter
1199
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
1198
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
1200
        jmp     .ack_processed
1199
        jmp     .ack_processed
1201
 
1200
 
1202
;-------
1201
;-------
1203
; LISTEN
1202
; LISTEN
1204
 
1203
 
1205
align 4
1204
align 4
1206
  .LISTEN:
1205
  .LISTEN:
1207
 
1206
 
1208
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n"
1207
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n"
1209
 
1208
 
1210
        test    [edx + TCP_header.Flags], TH_RST
1209
        test    [edx + TCP_header.Flags], TH_RST
1211
        jnz     .drop
1210
        jnz     .drop
1212
 
1211
 
1213
        test    [edx + TCP_header.Flags], TH_ACK
1212
        test    [edx + TCP_header.Flags], TH_ACK
1214
        jnz     .drop_with_reset
1213
        jnz     .drop_with_reset
1215
 
1214
 
1216
        test    [edx + TCP_header.Flags], TH_SYN
1215
        test    [edx + TCP_header.Flags], TH_SYN
1217
        jz      .drop
1216
        jz      .drop
1218
 
1217
 
1219
;;; TODO: check if it's a broadcast or multicast, and drop if so
1218
;;; TODO: check if it's a broadcast or multicast, and drop if so
1220
 
1219
 
1221
        push    dword [edi]                             ; Ipv4 source addres
1220
        push    dword [edi]                             ; Ipv4 source addres
1222
        pop     [ebx + IP_SOCKET.RemoteIP]
1221
        pop     [ebx + IP_SOCKET.RemoteIP]
1223
 
1222
 
1224
        push    [edx + TCP_header.SourcePort]
1223
        push    [edx + TCP_header.SourcePort]
1225
        pop     [ebx + TCP_SOCKET.RemotePort]
1224
        pop     [ebx + TCP_SOCKET.RemotePort]
1226
 
1225
 
1227
        push    [edx + TCP_header.SequenceNumber]
1226
        push    [edx + TCP_header.SequenceNumber]
1228
        pop     [ebx + TCP_SOCKET.IRS]
1227
        pop     [ebx + TCP_SOCKET.IRS]
1229
 
1228
 
1230
        mov     eax, [TCP_sequence_num]
1229
        mov     eax, [TCP_sequence_num]
1231
        add     [TCP_sequence_num], 64000 / 2
1230
        add     [TCP_sequence_num], 64000 / 2
1232
        mov     [ebx + TCP_SOCKET.ISS], eax
1231
        mov     [ebx + TCP_SOCKET.ISS], eax
1233
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1232
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1234
 
1233
 
1235
        TCP_sendseqinit ebx
1234
        TCP_sendseqinit ebx
1236
        TCP_rcvseqinit ebx
1235
        TCP_rcvseqinit ebx
1237
 
1236
 
1238
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1237
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1239
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1238
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1240
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
1239
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
1241
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
1240
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
1242
 
1241
 
1243
        lea     eax, [ebx + STREAM_SOCKET.snd]
1242
        lea     eax, [ebx + STREAM_SOCKET.snd]
1244
        call    SOCKET_ring_create
1243
        call    SOCKET_ring_create
1245
 
1244
 
1246
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1245
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1247
        call    SOCKET_ring_create
1246
        call    SOCKET_ring_create
1248
 
1247
 
1249
        and     [temp_bits], not TCP_BIT_DROPSOCKET
1248
        and     [temp_bits], not TCP_BIT_DROPSOCKET
1250
 
1249
 
1251
        pusha
1250
        pusha
1252
        mov     eax, ebx
1251
        mov     eax, ebx
1253
        call    SOCKET_notify
1252
        call    SOCKET_notify
1254
        popa
1253
        popa
1255
 
1254
 
1256
        jmp     .trim_then_step6
1255
        jmp     .trim_then_step6
1257
 
1256
 
1258
;------------
1257
;------------
1259
; Active Open
1258
; Active Open
1260
 
1259
 
1261
align 4
1260
align 4
1262
  .SYN_SENT:
1261
  .SYN_SENT:
1263
 
1262
 
1264
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n"
1263
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n"
1265
 
1264
 
1266
        test    [edx + TCP_header.Flags], TH_ACK
1265
        test    [edx + TCP_header.Flags], TH_ACK
1267
        jz      @f
1266
        jz      @f
1268
 
1267
 
1269
        mov     eax, [edx + TCP_header.AckNumber]
1268
        mov     eax, [edx + TCP_header.AckNumber]
1270
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1269
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1271
        jbe     .drop_with_reset
1270
        jbe     .drop_with_reset
1272
 
1271
 
1273
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
1272
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
1274
        ja      .drop_with_reset
1273
        ja      .drop_with_reset
1275
       @@:
1274
       @@:
1276
 
1275
 
1277
        test    [edx + TCP_header.Flags], TH_RST
1276
        test    [edx + TCP_header.Flags], TH_RST
1278
        jz      @f
1277
        jz      @f
1279
 
1278
 
1280
        test    [edx + TCP_header.Flags], TH_ACK
1279
        test    [edx + TCP_header.Flags], TH_ACK
1281
        jz      .drop
1280
        jz      .drop
1282
 
1281
 
1283
        mov     eax, ebx
1282
        mov     eax, ebx
1284
        mov     ebx, ECONNREFUSED
1283
        mov     ebx, ECONNREFUSED
1285
        call    TCP_drop
1284
        call    TCP_drop
1286
 
1285
 
1287
        jmp     .drop
1286
        jmp     .drop
1288
       @@:
1287
       @@:
1289
 
1288
 
1290
        test    [edx + TCP_header.Flags], TH_SYN
1289
        test    [edx + TCP_header.Flags], TH_SYN
1291
        jz      .drop
1290
        jz      .drop
1292
 
1291
 
1293
; at this point, segment seems to be valid
1292
; at this point, segment seems to be valid
1294
 
1293
 
1295
        test    [edx + TCP_header.Flags], TH_ACK
1294
        test    [edx + TCP_header.Flags], TH_ACK
1296
        jz      .no_syn_ack
1295
        jz      .no_syn_ack
1297
 
1296
 
1298
; now, process received SYN in response to an active open
1297
; now, process received SYN in response to an active open
1299
 
1298
 
1300
        mov     eax, [edx + TCP_header.AckNumber]
1299
        mov     eax, [edx + TCP_header.AckNumber]
1301
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1300
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1302
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1301
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1303
        jbe     @f
1302
        jbe     @f
1304
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1303
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1305
       @@:
1304
       @@:
1306
 
1305
 
1307
  .no_syn_ack:
1306
  .no_syn_ack:
1308
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; disable retransmission timer
1307
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; disable retransmission timer
1309
 
1308
 
1310
        push    [edx + TCP_header.SequenceNumber]
1309
        push    [edx + TCP_header.SequenceNumber]
1311
        pop     [ebx + TCP_SOCKET.IRS]
1310
        pop     [ebx + TCP_SOCKET.IRS]
1312
 
1311
 
1313
        TCP_rcvseqinit ebx
1312
        TCP_rcvseqinit ebx
1314
 
1313
 
1315
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1314
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1316
 
1315
 
1317
        mov     eax, [ebx + TCP_SOCKET.SND_UNA]
1316
        mov     eax, [ebx + TCP_SOCKET.SND_UNA]
1318
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1317
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1319
        jbe     .simultaneous_open
1318
        jbe     .simultaneous_open
1320
 
1319
 
1321
        test    [edx + TCP_header.Flags], TH_ACK
1320
        test    [edx + TCP_header.Flags], TH_ACK
1322
        jz      .simultaneous_open
1321
        jz      .simultaneous_open
1323
 
1322
 
1324
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n"
1323
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n"
1325
 
1324
 
1326
;;; TODO: update stats
1325
;;; TODO: update stats
1327
 
1326
 
1328
; set socket state to connected
1327
; set socket state to connected
1329
        push    eax
1328
        push    eax
1330
        mov     eax, ebx
1329
        mov     eax, ebx
1331
        call    SOCKET_is_connected
1330
        call    SOCKET_is_connected
1332
        pop     eax
1331
        pop     eax
1333
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1332
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1334
 
1333
 
1335
; Do window scaling on this connection ?
1334
; Do window scaling on this connection ?
1336
        mov     eax, [ebx + TCP_SOCKET.t_flags]
1335
        mov     eax, [ebx + TCP_SOCKET.t_flags]
1337
        and     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1336
        and     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1338
        cmp     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1337
        cmp     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1339
        jne     .no_scaling
1338
        jne     .no_scaling
1340
 
1339
 
1341
        mov     ax, word [ebx + TCP_SOCKET.requested_s_scale]
1340
        mov     ax, word [ebx + TCP_SOCKET.requested_s_scale]
1342
        mov     word [ebx + TCP_SOCKET.SND_SCALE], ax
1341
        mov     word [ebx + TCP_SOCKET.SND_SCALE], ax
1343
  .no_scaling:
1342
  .no_scaling:
1344
 
1343
 
1345
;;; TODO: reassemble packets queue
1344
;;; TODO: reassemble packets queue
1346
 
1345
 
1347
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1346
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1348
        test    eax, eax
1347
        test    eax, eax
1349
        je      .trim_then_step6
1348
        je      .trim_then_step6
1350
        call    TCP_xmit_timer
1349
        call    TCP_xmit_timer
1351
        jmp     .trim_then_step6
1350
        jmp     .trim_then_step6
1352
 
1351
 
1353
  .simultaneous_open:
1352
  .simultaneous_open:
1354
 
1353
 
1355
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n"
1354
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n"
1356
; We have received a syn but no ACK, so we are having a simultaneous open..
1355
; We have received a syn but no ACK, so we are having a simultaneous open..
1357
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1356
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1358
 
1357
 
1359
;-------------------------------------
1358
;-------------------------------------
1360
; Common processing for receipt of SYN
1359
; Common processing for receipt of SYN
1361
 
1360
 
1362
  .trim_then_step6:
1361
  .trim_then_step6:
1363
 
1362
 
1364
        inc     [edx + TCP_header.SequenceNumber]
1363
        inc     [edx + TCP_header.SequenceNumber]
1365
 
1364
 
1366
; Drop any received data that doesnt fit in the receive window.
1365
; Drop any received data that doesnt fit in the receive window.
1367
        cmp     ecx, [ebx + TCP_SOCKET.RCV_WND]
1366
        cmp     ecx, [ebx + TCP_SOCKET.RCV_WND]
1368
        jbe     .dont_trim
1367
        jbe     .dont_trim
1369
 
1368
 
1370
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: received data does not fit in window, trimming %u bytes\n", eax
1369
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: received data does not fit in window, trimming %u bytes\n", eax
1371
        mov     ecx, [ebx + TCP_SOCKET.RCV_WND]
1370
        mov     ecx, [ebx + TCP_SOCKET.RCV_WND]
1372
        and     [edx + TCP_header.Flags], not (TH_FIN)
1371
        and     [edx + TCP_header.Flags], not (TH_FIN)
1373
;;; TODO: update stats
1372
;;; TODO: update stats
1374
 
1373
 
1375
  .dont_trim:
1374
  .dont_trim:
1376
 
1375
 
1377
        mov     eax, [edx + TCP_header.SequenceNumber]
1376
        mov     eax, [edx + TCP_header.SequenceNumber]
1378
        mov     [ebx + TCP_SOCKET.RCV_UP], eax
1377
        mov     [ebx + TCP_SOCKET.RCV_UP], eax
1379
        dec     eax
1378
        dec     eax
1380
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
1379
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
1381
 
1380
 
1382
;-------
1381
;-------
1383
; step 6
1382
; step 6
1384
 
1383
 
1385
  .ack_processed:
1384
  .ack_processed:
1386
 
1385
 
1387
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n"
1386
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n"
1388
 
1387
 
1389
;----------------------------------------------
1388
;----------------------------------------------
1390
; check if we need to update window information
1389
; check if we need to update window information
1391
 
1390
 
1392
        test    [edx + TCP_header.Flags], TH_ACK
1391
        test    [edx + TCP_header.Flags], TH_ACK
1393
        jz      .no_window_update
1392
        jz      .no_window_update
1394
 
1393
 
1395
        mov     eax, [ebx + TCP_SOCKET.SND_WL1]
1394
        mov     eax, [ebx + TCP_SOCKET.SND_WL1]
1396
        cmp     eax, [edx + TCP_header.SequenceNumber]
1395
        cmp     eax, [edx + TCP_header.SequenceNumber]
1397
        jb      .update_window
1396
        jb      .update_window
1398
        ja      @f
1397
        ja      @f
1399
 
1398
 
1400
        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1399
        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1401
        cmp     eax, [edx + TCP_header.AckNumber]
1400
        cmp     eax, [edx + TCP_header.AckNumber]
1402
        jb      .update_window
1401
        jb      .update_window
1403
        ja      .no_window_update
1402
        ja      .no_window_update
1404
       @@:
1403
       @@:
1405
 
1404
 
1406
        mov     eax, dword [edx + TCP_header.Window]
1405
        mov     eax, dword [edx + TCP_header.Window]
1407
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1406
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1408
        jbe     .no_window_update
1407
        jbe     .no_window_update
1409
 
1408
 
1410
  .update_window:
1409
  .update_window:
1411
 
1410
 
1412
;;; TODO: update stats (Keep track of pure window updates)
1411
;;; TODO: update stats (Keep track of pure window updates)
1413
 
1412
 
1414
        mov     eax, dword [edx + TCP_header.Window]
1413
        mov     eax, dword [edx + TCP_header.Window]
1415
        cmp     eax, [ebx + TCP_SOCKET.max_sndwnd]
1414
        cmp     eax, [ebx + TCP_SOCKET.max_sndwnd]
1416
        jbe     @f
1415
        jbe     @f
1417
        mov     [ebx + TCP_SOCKET.max_sndwnd], eax
1416
        mov     [ebx + TCP_SOCKET.max_sndwnd], eax
1418
       @@:
1417
       @@:
1419
        mov     [ebx + TCP_SOCKET.SND_WND], eax
1418
        mov     [ebx + TCP_SOCKET.SND_WND], eax
1420
 
1419
 
1421
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax
1420
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax
1422
 
1421
 
1423
        push    [edx + TCP_header.SequenceNumber]
1422
        push    [edx + TCP_header.SequenceNumber]
1424
        pop     [ebx + TCP_SOCKET.SND_WL1]
1423
        pop     [ebx + TCP_SOCKET.SND_WL1]
1425
 
1424
 
1426
        push    [edx + TCP_header.AckNumber]
1425
        push    [edx + TCP_header.AckNumber]
1427
        pop     [ebx + TCP_SOCKET.SND_WL2]
1426
        pop     [ebx + TCP_SOCKET.SND_WL2]
1428
 
1427
 
1429
        or      [temp_bits], TCP_BIT_NEEDOUTPUT
1428
        or      [temp_bits], TCP_BIT_NEEDOUTPUT
1430
 
1429
 
1431
  .no_window_update:
1430
  .no_window_update:
1432
 
1431
 
1433
;-----------------
1432
;-----------------
1434
; process URG flag
1433
; process URG flag
1435
 
1434
 
1436
        test    [edx + TCP_header.Flags], TH_URG
1435
        test    [edx + TCP_header.Flags], TH_URG
1437
        jz      .not_urgent
1436
        jz      .not_urgent
1438
 
1437
 
1439
        cmp     [edx + TCP_header.UrgentPointer], 0
1438
        cmp     [edx + TCP_header.UrgentPointer], 0
1440
        jz      .not_urgent
1439
        jz      .not_urgent
1441
 
1440
 
1442
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1441
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1443
        je      .not_urgent
1442
        je      .not_urgent
1444
 
1443
 
1445
; Ignore bogus urgent offsets
1444
; Ignore bogus urgent offsets
1446
 
1445
 
1447
        movzx   eax, [edx + TCP_header.UrgentPointer]
1446
        movzx   eax, [edx + TCP_header.UrgentPointer]
1448
        add     eax, [ebx + STREAM_SOCKET.rcv.size]
1447
        add     eax, [ebx + STREAM_SOCKET.rcv.size]
1449
        cmp     eax, SOCKET_MAXDATA
1448
        cmp     eax, SOCKET_MAXDATA
1450
        jbe     .not_urgent
1449
        jbe     .not_urgent
1451
 
1450
 
1452
        mov     [edx + TCP_header.UrgentPointer], 0
1451
        mov     [edx + TCP_header.UrgentPointer], 0
1453
        and     [edx + TCP_header.Flags], not (TH_URG)
1452
        and     [edx + TCP_header.Flags], not (TH_URG)
1454
        jmp     .do_data
1453
        jmp     .do_data
1455
 
1454
 
1456
  .not_urgent:
1455
  .not_urgent:
1457
 
1456
 
1458
; processing of received urgent pointer
1457
; processing of received urgent pointer
1459
 
1458
 
1460
        ;;; TODO (1051-1093)
1459
        ;;; TODO (1051-1093)
1461
 
1460
 
1462
 
1461
 
1463
;---------------------------------------
1462
;---------------------------------------
1464
; process the data in the segment (1094)
1463
; process the data in the segment (1094)
1465
 
1464
 
1466
  .do_data:
1465
  .do_data:
1467
 
1466
 
1468
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1467
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1469
        jae     .final_processing
1468
        jae     .final_processing
1470
 
1469
 
1471
        test    [edx + TCP_header.Flags], TH_FIN
1470
        test    [edx + TCP_header.Flags], TH_FIN
1472
        jnz     @f
1471
        jnz     @f
1473
 
1472
 
1474
        test    ecx, ecx
1473
        test    ecx, ecx
1475
        jz      .final_processing
1474
        jz      .final_processing
1476
       @@:
1475
       @@:
1477
 
1476
 
1478
; The segment is in order?
1477
; The segment is in order?
1479
        mov     eax, [edx + TCP_header.SequenceNumber]
1478
        mov     eax, [edx + TCP_header.SequenceNumber]
1480
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
1479
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
1481
        jne     .out_of_order
1480
        jne     .out_of_order
1482
 
1481
 
1483
; The reassembly queue is empty?
1482
; The reassembly queue is empty?
1484
        cmp     [ebx + TCP_SOCKET.seg_next], 0
1483
        cmp     [ebx + TCP_SOCKET.seg_next], 0
1485
        jne     .out_of_order
1484
        jne     .out_of_order
1486
 
1485
 
1487
; The connection is established?
1486
; The connection is established?
1488
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1487
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1489
        jne     .out_of_order
1488
        jne     .out_of_order
1490
 
1489
 
1491
; Ok, lets do this..  Set delayed ACK flag and copy data into socket buffer
1490
; Ok, lets do this..  Set delayed ACK flag and copy data into socket buffer
1492
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK
1491
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK
1493
 
1492
 
1494
        pusha
1493
        pusha
1495
        mov     esi, [dataoffset]
1494
        mov     esi, [dataoffset]
1496
        add     esi, edx
1495
        add     esi, edx
1497
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1496
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1498
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
1497
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
1499
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
1498
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
1500
        popa
1499
        popa
1501
 
1500
 
1502
; Wake up the sleeping process
1501
; Wake up the sleeping process
1503
        mov     eax, ebx
1502
        mov     eax, ebx
1504
        call    SOCKET_notify
1503
        call    SOCKET_notify
1505
 
1504
 
1506
        jmp     .data_done
1505
        jmp     .data_done
1507
 
1506
 
1508
  .out_of_order:
1507
  .out_of_order:
1509
        DEBUGF  DEBUG_NETWORK_VERBOSE,  "TCP data is out of order!\nSequencenumber is %u, we expected %u.\n", \
1508
        DEBUGF  DEBUG_NETWORK_VERBOSE,  "TCP data is out of order!\nSequencenumber is %u, we expected %u.\n", \
1510
        [edx + TCP_header.SequenceNumber], [ebx + TCP_SOCKET.RCV_NXT]
1509
        [edx + TCP_header.SequenceNumber], [ebx + TCP_SOCKET.RCV_NXT]
1511
 
1510
 
1512
; Uh-oh, some data is out of order, lets call TCP reassemble for help
1511
; Uh-oh, some data is out of order, lets call TCP reassemble for help
1513
 
1512
 
1514
        call    TCP_reassemble
1513
        call    TCP_reassemble
1515
 
1514
 
1516
; Generate ACK immediately, to let the other end know that a segment was received out of order,
1515
; Generate ACK immediately, to let the other end know that a segment was received out of order,
1517
; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm.
1516
; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm.
1518
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1517
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1519
  .data_done:
1518
  .data_done:
1520
 
1519
 
1521
;---------------
1520
;---------------
1522
; FIN processing
1521
; FIN processing
1523
 
1522
 
1524
        test    [edx + TCP_header.Flags], TH_FIN
1523
        test    [edx + TCP_header.Flags], TH_FIN
1525
        jz      .final_processing
1524
        jz      .final_processing
1526
 
1525
 
1527
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n"
1526
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n"
1528
 
1527
 
1529
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1528
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1530
        jae     .not_first_fin
1529
        jae     .not_first_fin
1531
 
1530
 
1532
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n"
1531
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n"
1533
 
1532
 
1534
        mov     eax, ebx
1533
        mov     eax, ebx
1535
        call    SOCKET_cant_recv_more
1534
        call    SOCKET_cant_recv_more
1536
 
1535
 
1537
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1536
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1538
        inc     [ebx + TCP_SOCKET.RCV_NXT]
1537
        inc     [ebx + TCP_SOCKET.RCV_NXT]
1539
 
1538
 
1540
  .not_first_fin:
1539
  .not_first_fin:
1541
        mov     eax, [ebx + TCP_SOCKET.t_state]
1540
        mov     eax, [ebx + TCP_SOCKET.t_state]
1542
        shl     eax, 2
1541
        shl     eax, 2
1543
        jmp     dword [eax + .FIN_sw_list]
1542
        jmp     dword [eax + .FIN_sw_list]
1544
 
1543
 
1545
  .FIN_sw_list:
1544
  .FIN_sw_list:
1546
        dd      .final_processing       ; TCPS_CLOSED
1545
        dd      .final_processing       ; TCPS_CLOSED
1547
        dd      .final_processing       ; TCPS_LISTEN
1546
        dd      .final_processing       ; TCPS_LISTEN
1548
        dd      .final_processing       ; TCPS_SYN_SENT
1547
        dd      .final_processing       ; TCPS_SYN_SENT
1549
        dd      .fin_syn_est            ; TCPS_SYN_RECEIVED
1548
        dd      .fin_syn_est            ; TCPS_SYN_RECEIVED
1550
        dd      .fin_syn_est            ; TCPS_ESTABLISHED
1549
        dd      .fin_syn_est            ; TCPS_ESTABLISHED
1551
        dd      .final_processing       ; TCPS_CLOSE_WAIT
1550
        dd      .final_processing       ; TCPS_CLOSE_WAIT
1552
        dd      .fin_wait1              ; TCPS_FIN_WAIT_1
1551
        dd      .fin_wait1              ; TCPS_FIN_WAIT_1
1553
        dd      .final_processing       ; TCPS_CLOSING
1552
        dd      .final_processing       ; TCPS_CLOSING
1554
        dd      .final_processing       ; TCPS_LAST_ACK
1553
        dd      .final_processing       ; TCPS_LAST_ACK
1555
        dd      .fin_wait2              ; TCPS_FIN_WAIT_2
1554
        dd      .fin_wait2              ; TCPS_FIN_WAIT_2
1556
        dd      .fin_timed              ; TCPS_TIMED_WAIT
1555
        dd      .fin_timed              ; TCPS_TIMED_WAIT
1557
 
1556
 
1558
  .fin_syn_est:
1557
  .fin_syn_est:
1559
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1558
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1560
        jmp     .final_processing
1559
        jmp     .final_processing
1561
 
1560
 
1562
  .fin_wait1:
1561
  .fin_wait1:
1563
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1562
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1564
        jmp     .final_processing
1563
        jmp     .final_processing
1565
 
1564
 
1566
  .fin_wait2:
1565
  .fin_wait2:
1567
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1566
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1568
        mov     eax, ebx
1567
        mov     eax, ebx
1569
        call    TCP_cancel_timers
1568
        call    TCP_cancel_timers
1570
        call    SOCKET_is_disconnected
1569
        call    SOCKET_is_disconnected
1571
 
1570
 
1572
  .fin_timed:
1571
  .fin_timed:
1573
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1572
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1574
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1573
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1575
 
1574
 
1576
;-----------------
1575
;-----------------
1577
; Final processing
1576
; Final processing
1578
 
1577
 
1579
  .final_processing:
1578
  .final_processing:
1580
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
1579
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
1581
 
1580
 
1582
        push    ebx
1581
        push    ebx
1583
        lea     ecx, [ebx + SOCKET.mutex]
1582
        lea     ecx, [ebx + SOCKET.mutex]
1584
        call    mutex_unlock
1583
        call    mutex_unlock
1585
        pop     eax
1584
        pop     eax
1586
 
1585
 
1587
        test    [temp_bits], TCP_BIT_NEEDOUTPUT
1586
        test    [temp_bits], TCP_BIT_NEEDOUTPUT
1588
        jnz     .need_output
1587
        jnz     .need_output
1589
 
1588
 
1590
        test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1589
        test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1591
        jz      .dumpit
1590
        jz      .dumpit
1592
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
1591
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
1593
 
1592
 
1594
  .need_output:
1593
  .need_output:
1595
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
1594
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
1596
        call    TCP_output
1595
        call    TCP_output
1597
 
1596
 
1598
  .dumpit:
1597
  .dumpit:
1599
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
1598
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
1600
 
1599
 
1601
        call    NET_packet_free
1600
        call    NET_packet_free
1602
        jmp     .loop
1601
        jmp     .loop
1603
 
1602
 
1604
 
1603
 
1605
;-----------------
1604
;-----------------
1606
; Drop the segment
1605
; Drop the segment
1607
 
1606
 
1608
 
1607
 
1609
  .drop_after_ack:
1608
  .drop_after_ack:
1610
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n"
1609
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n"
1611
 
1610
 
1612
        push    edx ebx
1611
        push    edx ebx
1613
        lea     ecx, [ebx + SOCKET.mutex]
1612
        lea     ecx, [ebx + SOCKET.mutex]
1614
        call    mutex_unlock
1613
        call    mutex_unlock
1615
        pop     eax edx
1614
        pop     eax edx
1616
 
1615
 
1617
        test    [edx + TCP_header.Flags], TH_RST
1616
        test    [edx + TCP_header.Flags], TH_RST
1618
        jnz     .dumpit
1617
        jnz     .dumpit
1619
 
1618
 
1620
        or      [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1619
        or      [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1621
        jmp     .need_output
1620
        jmp     .need_output
1622
 
1621
 
1623
  .drop_with_reset:
1622
  .drop_with_reset:
1624
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n"
1623
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n"
1625
 
1624
 
1626
        push    ebx edx
1625
        push    ebx edx
1627
        lea     ecx, [ebx + SOCKET.mutex]
1626
        lea     ecx, [ebx + SOCKET.mutex]
1628
        call    mutex_unlock
1627
        call    mutex_unlock
1629
        pop     edx ebx
1628
        pop     edx ebx
1630
 
1629
 
1631
        test    [edx + TCP_header.Flags], TH_RST
1630
        test    [edx + TCP_header.Flags], TH_RST
1632
        jnz     .dumpit
1631
        jnz     .dumpit
1633
 
1632
 
1634
        ;;; if its a multicast/broadcast, also drop
1633
        ;;; if its a multicast/broadcast, also drop
1635
 
1634
 
1636
        test    [edx + TCP_header.Flags], TH_ACK
1635
        test    [edx + TCP_header.Flags], TH_ACK
1637
        jnz     .respond_ack
1636
        jnz     .respond_ack
1638
 
1637
 
1639
        test    [edx + TCP_header.Flags], TH_SYN
1638
        test    [edx + TCP_header.Flags], TH_SYN
1640
        jnz     .respond_syn
1639
        jnz     .respond_syn
1641
        jmp     .dumpit
1640
        jmp     .dumpit
1642
 
1641
 
1643
;---------
1642
;---------
1644
; Respond
1643
; Respond
1645
 
1644
 
1646
  .respond_ack:
1645
  .respond_ack:
1647
        push    ebx
1646
        push    ebx
1648
        mov     cl, TH_RST
1647
        mov     cl, TH_RST
1649
        call    TCP_respond
1648
        call    TCP_respond
1650
        pop     ebx
1649
        pop     ebx
1651
        jmp     .destroy_new_socket
1650
        jmp     .destroy_new_socket
1652
 
1651
 
1653
  .respond_syn:
1652
  .respond_syn:
1654
        push    ebx
1653
        push    ebx
1655
        mov     cl, TH_RST + TH_ACK
1654
        mov     cl, TH_RST + TH_ACK
1656
        call    TCP_respond
1655
        call    TCP_respond
1657
        pop     ebx
1656
        pop     ebx
1658
        jmp     .destroy_new_socket
1657
        jmp     .destroy_new_socket
1659
 
1658
 
1660
  .no_socket:
1659
  .no_socket:
1661
 
1660
 
1662
        pusha
1661
        pusha
1663
        mov     ecx, socket_mutex
1662
        mov     ecx, socket_mutex
1664
        call    mutex_unlock
1663
        call    mutex_unlock
1665
        popa
1664
        popa
1666
 
1665
 
1667
  .respond_seg_reset:
1666
  .respond_seg_reset:
1668
        test    [edx + TCP_header.Flags], TH_RST
1667
        test    [edx + TCP_header.Flags], TH_RST
1669
        jnz     .drop_no_socket
1668
        jnz     .drop_no_socket
1670
 
1669
 
1671
        ;;; TODO: if its a multicast/broadcast, also drop
1670
        ;;; TODO: if its a multicast/broadcast, also drop
1672
 
1671
 
1673
        test    [edx + TCP_header.Flags], TH_ACK
1672
        test    [edx + TCP_header.Flags], TH_ACK
1674
        jnz     .respond_seg_ack
1673
        jnz     .respond_seg_ack
1675
 
1674
 
1676
        test    [edx + TCP_header.Flags], TH_SYN
1675
        test    [edx + TCP_header.Flags], TH_SYN
1677
        jnz     .respond_seg_syn
1676
        jnz     .respond_seg_syn
1678
 
1677
 
1679
        jmp     .drop_no_socket
1678
        jmp     .drop_no_socket
1680
 
1679
 
1681
  .respond_seg_ack:
1680
  .respond_seg_ack:
1682
        mov     cl, TH_RST
1681
        mov     cl, TH_RST
1683
        call    TCP_respond_segment
1682
        call    TCP_respond_segment
1684
        jmp     .drop_no_socket
1683
        jmp     .drop_no_socket
1685
 
1684
 
1686
  .respond_seg_syn:
1685
  .respond_seg_syn:
1687
        mov     cl, TH_RST + TH_ACK
1686
        mov     cl, TH_RST + TH_ACK
1688
        call    TCP_respond_segment
1687
        call    TCP_respond_segment
1689
        jmp     .drop_no_socket
1688
        jmp     .drop_no_socket
1690
 
1689
 
1691
;-----
1690
;-----
1692
; Drop
1691
; Drop
1693
 
1692
 
1694
  .drop:
1693
  .drop:
1695
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n"
1694
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n"
1696
 
1695
 
1697
        pusha
1696
        pusha
1698
        lea     ecx, [ebx + SOCKET.mutex]
1697
        lea     ecx, [ebx + SOCKET.mutex]
1699
        call    mutex_unlock
1698
        call    mutex_unlock
1700
        popa
1699
        popa
1701
 
1700
 
1702
  .destroy_new_socket:
1701
  .destroy_new_socket:
1703
        test    [temp_bits], TCP_BIT_DROPSOCKET
1702
        test    [temp_bits], TCP_BIT_DROPSOCKET
1704
        jz      .drop_no_socket
1703
        jz      .drop_no_socket
1705
 
1704
 
1706
        mov     eax, ebx
1705
        mov     eax, ebx
1707
        call    SOCKET_free
1706
        call    SOCKET_free
1708
 
1707
 
1709
  .drop_no_socket:
1708
  .drop_no_socket:
1710
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n"
1709
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n"
1711
 
1710
 
1712
        call    NET_packet_free
1711
        call    NET_packet_free
1713
        jmp     .loop
1712
        jmp     .loop
1714
 
1713
 
1715
endp
1714
endp
1716
>
1715
>
1717
>
1716
>
1718
>
1717
>
1719
>
1718
>