Subversion Repositories Kolibri OS

Rev

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