Subversion Repositories Kolibri OS

Rev

Rev 2957 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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