Subversion Repositories Kolibri OS

Rev

Rev 2955 | 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: 2957 $
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]
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
       @@:
2957 hidnplayr 503
        DEBUGF  1,"Receive window size=%d\n", eax
504
        mov     [ebx + TCP_SOCKET.RCV_WND], eax
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]
2957 hidnplayr 601
        sub     eax, [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
2957 hidnplayr 639
 
2937 hidnplayr 640
        sub     ecx, eax
641
        and     [ebx + TCP_SOCKET.t_flags], not (TH_PUSH or TH_FIN)
1733 hidnplayr 642
  .no_excess_data:
643
 
2957 hidnplayr 644
;--------------------- FIXME -------------------
645
 
646
        pusha
647
        movzx   esi, [edx + TCP_header.DataOffset]
648
        add     esi, edx
649
        lea     eax, [ebx + STREAM_SOCKET.rcv]
650
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
651
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
652
        popa
653
 
654
;--------------------- FIXME --------------------
655
 
1733 hidnplayr 656
;-----------------
2948 hidnplayr 657
; Record timestamp (737-746)
1733 hidnplayr 658
 
2937 hidnplayr 659
; If last ACK falls within this segments sequence numbers, record its timestamp
660
        test    [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
661
        jz      .no_timestamp
662
        mov     eax, [ebx + TCP_SOCKET.last_ack_sent]
663
        sub     eax, [edx + TCP_header.SequenceNumber]
664
        jb      .no_timestamp
665
        test    [ebx + TCP_header.Flags], TH_SYN or TH_FIN      ; syn and fin occupy one byte
666
        jz      @f
667
        dec     eax
668
       @@:
669
        sub     eax, ecx
670
        jae     .no_timestamp
1733 hidnplayr 671
 
2948 hidnplayr 672
        DEBUGF  1,"Recording timestamp\n"
673
 
674
        mov     eax, [esp + 4+4]                                ; tcp_now
2937 hidnplayr 675
        mov     [ebx + TCP_SOCKET.ts_recent_age], eax
676
        mov     eax, [ebx + TCP_SOCKET.ts_val]
677
        mov     [ebx + TCP_SOCKET.ts_recent], eax
678
  .no_timestamp:
1733 hidnplayr 679
 
680
;------------------
681
; Process RST flags
682
 
2390 hidnplayr 683
        test    [edx + TCP_header.Flags], TH_RST
2891 hidnplayr 684
        jz      .no_rst
1733 hidnplayr 685
 
2891 hidnplayr 686
        DEBUGF  1,"TCP_input: Got an RST flag\n"
1733 hidnplayr 687
 
2390 hidnplayr 688
        mov     eax, [ebx + TCP_SOCKET.t_state]
689
        shl     eax, 2
690
        jmp     dword [eax + .rst_sw_list]
1733 hidnplayr 691
 
692
  .rst_sw_list:
2891 hidnplayr 693
        dd      .no_rst         ; TCPS_CLOSED
694
        dd      .no_rst         ; TCPS_LISTEN
695
        dd      .no_rst         ; TCPS_SYN_SENT
696
        dd      .econnrefused   ; TCPS_SYN_RECEIVED
697
        dd      .econnreset     ; TCPS_ESTABLISHED
698
        dd      .econnreset     ; TCPS_CLOSE_WAIT
699
        dd      .econnreset     ; TCPS_FIN_WAIT_1
700
        dd      .rst_close      ; TCPS_CLOSING
701
        dd      .rst_close      ; TCPS_LAST_ACK
702
        dd      .econnreset     ; TCPS_FIN_WAIT_2
703
        dd      .rst_close      ; TCPS_TIMED_WAIT
1733 hidnplayr 704
 
705
  .econnrefused:
2891 hidnplayr 706
        DEBUGF  1,"TCP_input: Connection refused\n"
1733 hidnplayr 707
 
2390 hidnplayr 708
        mov     [ebx + SOCKET.errorcode], ECONNREFUSED
709
        jmp     .close
1733 hidnplayr 710
 
711
  .econnreset:
2891 hidnplayr 712
        DEBUGF  1,"TCP_input: Connection reset\n"
1733 hidnplayr 713
 
2390 hidnplayr 714
        mov     [ebx + SOCKET.errorcode], ECONNRESET
1733 hidnplayr 715
 
2882 hidnplayr 716
  .close:
2891 hidnplayr 717
        DEBUGF  1,"TCP_input: Closing connection\n"
1733 hidnplayr 718
 
2390 hidnplayr 719
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
2937 hidnplayr 720
;;; TODO: update stats (tcp drops)
2390 hidnplayr 721
        mov     eax, ebx
722
        call    TCP_close
723
        jmp     .drop
1733 hidnplayr 724
 
725
  .rst_close:
2891 hidnplayr 726
        DEBUGF  1,"TCP_input: Closing with reset\n"
1733 hidnplayr 727
 
2390 hidnplayr 728
        mov     eax, ebx
729
        call    TCP_close
730
        jmp     .drop
1733 hidnplayr 731
 
2891 hidnplayr 732
  .no_rst:
1733 hidnplayr 733
 
734
;--------------------------------------
735
; handle SYN-full and ACK-less segments
736
 
2390 hidnplayr 737
        test    [edx + TCP_header.Flags], TH_SYN
2937 hidnplayr 738
        jz      .not_syn_full
1733 hidnplayr 739
 
2390 hidnplayr 740
        mov     eax, ebx
741
        mov     ebx, ECONNRESET
742
        call    TCP_drop
743
        jmp     .drop_with_reset
2937 hidnplayr 744
  .not_syn_full:
1733 hidnplayr 745
 
746
;---------------
747
; ACK processing
748
 
2891 hidnplayr 749
        test    [edx + TCP_header.Flags], TH_ACK
750
        jz      .drop
751
 
2390 hidnplayr 752
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
2937 hidnplayr 753
        jb      .ack_processed                                  ; states: closed, listen, syn_sent
754
        ja      .no_syn_rcv                                     ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
1733 hidnplayr 755
 
2891 hidnplayr 756
        DEBUGF  1,"TCP_input: state=syn_received\n"
1733 hidnplayr 757
 
2390 hidnplayr 758
        mov     eax, [edx + TCP_header.AckNumber]
759
        cmp     [ebx + TCP_SOCKET.SND_UNA], eax
760
        ja      .drop_with_reset
761
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
762
        ja      .drop_with_reset
1733 hidnplayr 763
 
2309 hidnplayr 764
;;; TODO: update stats
765
 
2390 hidnplayr 766
        mov     eax, ebx
767
        call    SOCKET_is_connected
768
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1831 hidnplayr 769
 
770
; Do window scaling?
771
 
2390 hidnplayr 772
        test    [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
773
        jz      @f
774
        test    [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
775
        jz      @f
1831 hidnplayr 776
 
2390 hidnplayr 777
        push    word [ebx + TCP_SOCKET.requested_s_scale]       ; Set send and receive scale factors to the received values
778
        pop     word [ebx + TCP_SOCKET.SND_SCALE]
1831 hidnplayr 779
       @@:
780
 
2891 hidnplayr 781
;;; TODO: call TCP_reassemble
1831 hidnplayr 782
 
2390 hidnplayr 783
        mov     eax, [edx + TCP_header.SequenceNumber]
784
        dec     eax
785
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
1831 hidnplayr 786
 
1733 hidnplayr 787
  .no_syn_rcv:
788
 
2937 hidnplayr 789
;-------------------------
790
; check for duplicate ACKs
1733 hidnplayr 791
 
2390 hidnplayr 792
        mov     eax, [edx + TCP_header.AckNumber]
793
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
794
        ja      .not_dup_ack
1733 hidnplayr 795
 
2390 hidnplayr 796
        test    ecx, ecx
797
        jnz     .reset_dupacks
1733 hidnplayr 798
 
2390 hidnplayr 799
        mov     eax, dword [edx + TCP_header.Window]
800
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
801
        jne     .reset_dupacks
1733 hidnplayr 802
 
2891 hidnplayr 803
        DEBUGF  1,"TCP_input: Processing duplicate ACK\n"
1733 hidnplayr 804
 
2948 hidnplayr 805
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
2937 hidnplayr 806
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
807
; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet.
1733 hidnplayr 808
 
2937 hidnplayr 809
        cmp     [ebx + TCP_SOCKET.timer_retransmission], 0 ;;;;  FIXME
810
        jg      @f
811
 
2390 hidnplayr 812
        mov     eax, [edx + TCP_header.AckNumber]
813
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
814
        je      .dup_ack
1763 hidnplayr 815
 
816
       @@:
2390 hidnplayr 817
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
818
        jmp     .not_dup_ack
1763 hidnplayr 819
 
820
  .dup_ack:
2390 hidnplayr 821
        inc     [ebx + TCP_SOCKET.t_dupacks]
822
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
823
        jne     .no_re_xmit
1763 hidnplayr 824
 
2390 hidnplayr 825
        push    [ebx + TCP_SOCKET.SND_NXT]              ; >>>>
1763 hidnplayr 826
 
2390 hidnplayr 827
        mov     eax, [ebx + TCP_SOCKET.SND_WND]
828
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
2866 hidnplayr 829
        cmova   eax, [ebx + TCP_SOCKET.SND_CWND]
2390 hidnplayr 830
        shr     eax, 1
831
        push    edx
832
        xor     edx, edx
833
        div     [ebx + TCP_SOCKET.t_maxseg]
834
        cmp     eax, 2
2937 hidnplayr 835
        ja      @f
836
        xor     eax, eax
837
        mov     al, 2
1763 hidnplayr 838
       @@:
2390 hidnplayr 839
        mul     [ebx + TCP_SOCKET.t_maxseg]
840
        pop     edx
841
        mov     [ebx + TCP_SOCKET.SND_SSTHRESH], eax
1763 hidnplayr 842
 
2390 hidnplayr 843
        mov     [ebx + TCP_SOCKET.timer_retransmission], 0      ; turn off retransmission timer
844
        mov     [ebx + TCP_SOCKET.t_rtt], 0
845
        mov     eax, [edx + TCP_header.AckNumber]
846
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
847
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
848
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
1763 hidnplayr 849
 
2390 hidnplayr 850
        mov     eax, ebx
851
        call    TCP_output                                      ; retransmit missing segment
1763 hidnplayr 852
 
2390 hidnplayr 853
        push    edx
854
        xor     edx, edx
855
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
856
        mul     [ebx + TCP_SOCKET.t_dupacks]
857
        pop     edx
858
        add     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
859
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
1763 hidnplayr 860
 
2390 hidnplayr 861
        pop     eax                                     ; <<<<
862
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
863
        jb      @f
864
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1763 hidnplayr 865
       @@:
866
 
2390 hidnplayr 867
        jmp     .drop
1733 hidnplayr 868
 
869
 
1763 hidnplayr 870
  .no_re_xmit:
2390 hidnplayr 871
        jbe     .not_dup_ack
1733 hidnplayr 872
 
2891 hidnplayr 873
        DEBUGF  1,"TCP_input: Increasing congestion window\n"
1733 hidnplayr 874
 
2390 hidnplayr 875
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
876
        add     [ebx + TCP_SOCKET.SND_CWND], eax
1733 hidnplayr 877
 
2390 hidnplayr 878
        mov     eax, ebx
879
        call    TCP_output
1733 hidnplayr 880
 
2390 hidnplayr 881
        jmp     .drop
1733 hidnplayr 882
 
883
 
1763 hidnplayr 884
  .not_dup_ack:
885
 
1733 hidnplayr 886
;-------------------------------------------------
887
; If the congestion window was inflated to account
888
; for the other side's cached packets, retract it
889
 
2390 hidnplayr 890
        mov     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
891
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
892
        ja      @f
893
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
894
        jbe     @f
895
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
1763 hidnplayr 896
       @@:
1733 hidnplayr 897
 
2390 hidnplayr 898
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
1733 hidnplayr 899
 
2390 hidnplayr 900
        mov     eax, [edx + TCP_header.AckNumber]
901
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
902
        jbe     @f
1733 hidnplayr 903
 
2390 hidnplayr 904
        ;;; TODO: update stats
905
        jmp     .drop_after_ack
1733 hidnplayr 906
 
1763 hidnplayr 907
       @@:
1733 hidnplayr 908
 
2390 hidnplayr 909
        mov     edi, [edx + TCP_header.AckNumber]
910
        sub     edi, [ebx + TCP_SOCKET.SND_UNA]         ; now we got the number of acked bytes in edi
1733 hidnplayr 911
 
2390 hidnplayr 912
        ;;; TODO: update stats
1733 hidnplayr 913
 
2891 hidnplayr 914
        DEBUGF  1,"TCP_input: acceptable ACK for %u bytes\n", edi
1763 hidnplayr 915
 
1733 hidnplayr 916
;------------------------------------------
2937 hidnplayr 917
; RTT measurements and retransmission timer  (912-926)
1733 hidnplayr 918
 
2937 hidnplayr 919
; If we have a timestamp, update smoothed RTT
1733 hidnplayr 920
 
2937 hidnplayr 921
        test    [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
2948 hidnplayr 922
        jz      .timestamp_not_present
2942 hidnplayr 923
        mov     eax, [esp+4+4]
2937 hidnplayr 924
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
925
        inc     eax
926
        call    TCP_xmit_timer
927
        jmp     .rtt_done_
1733 hidnplayr 928
 
2937 hidnplayr 929
; If no timestamp but transmit timer is running and timed sequence number was acked,
930
; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff
931
; (Phil Karn's retransmit algo)
932
; Recompute the initial retransmit timer
933
 
934
  .timestamp_not_present:
935
        mov     eax, [edx + TCP_header.AckNumber]
936
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
937
        jbe     .rtt_done_
938
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
939
        test    eax, eax
940
        jz      .rtt_done_
941
        call    TCP_xmit_timer
942
 
943
  .rtt_done_:
944
 
945
; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist)
946
; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value.
947
 
2390 hidnplayr 948
        mov     eax, [ebx + TCP_SOCKET.SND_MAX]
949
        cmp     eax, [edx + TCP_header.AckNumber]
2937 hidnplayr 950
        jne     .more_data
951
        mov     [ebx + TCP_SOCKET.timer_retransmission], 0
952
        or      [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
953
        jmp     .no_restart
954
  .more_data:
955
        cmp     [ebx + TCP_SOCKET.timer_persist], 0
956
        jne     .no_restart
2891 hidnplayr 957
 
2937 hidnplayr 958
        mov     eax, [ebx + TCP_SOCKET.t_rxtcur]
2955 hidnplayr 959
        mov     [ebx + TCP_SOCKET.timer_retransmission], eax
1733 hidnplayr 960
 
2937 hidnplayr 961
  .no_restart:
962
 
963
 
1733 hidnplayr 964
;-------------------------------------------
965
; Open congestion window in response to ACKs
966
 
2390 hidnplayr 967
        mov     esi, [ebx + TCP_SOCKET.SND_CWND]
968
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1733 hidnplayr 969
 
2390 hidnplayr 970
        cmp     esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
971
        jbe     @f
972
        push    edx
973
        push    eax
974
        mul     eax
975
        div     esi
976
        pop     edx
977
        shr     edx, 3
978
        add     eax, edx
979
        pop     edx
1763 hidnplayr 980
       @@:
1733 hidnplayr 981
 
2390 hidnplayr 982
        add     esi, eax
1733 hidnplayr 983
 
2390 hidnplayr 984
        push    ecx
985
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
986
        mov     eax, TCP_max_win
987
        shl     eax, cl
988
        pop     ecx
1733 hidnplayr 989
 
2390 hidnplayr 990
        cmp     esi, eax
2866 hidnplayr 991
        cmova   esi, eax
2390 hidnplayr 992
        mov     [ebx + TCP_SOCKET.SND_CWND], esi
1733 hidnplayr 993
 
2891 hidnplayr 994
;------------------------------------------
995
; Remove acknowledged data from send buffer
1733 hidnplayr 996
 
2891 hidnplayr 997
        cmp     edi, [ebx + STREAM_SOCKET.snd.size]
998
        jbe     .finiacked
1733 hidnplayr 999
 
2891 hidnplayr 1000
        push    ecx edx ebx
1001
        mov     ecx, [ebx + STREAM_SOCKET.snd.size]
1002
        lea     eax, [ebx + STREAM_SOCKET.snd]
1003
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1004
        call    SOCKET_ring_free
1005
        pop     ebx edx ecx
1733 hidnplayr 1006
 
2891 hidnplayr 1007
        DEBUGF  1,"TCP_input: our FIN is acked\n"
1008
        stc
1763 hidnplayr 1009
 
2891 hidnplayr 1010
        jmp     .wakeup
1763 hidnplayr 1011
 
2891 hidnplayr 1012
  .finiacked:
1763 hidnplayr 1013
 
2390 hidnplayr 1014
        push    ecx edx ebx
1015
        mov     ecx, edi
1016
        lea     eax, [ebx + STREAM_SOCKET.snd]
1017
        call    SOCKET_ring_free
1018
        pop     ebx
1019
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1020
        pop     edx ecx
1733 hidnplayr 1021
 
2891 hidnplayr 1022
        DEBUGF  1,"TCP_input: our FIN is not acked\n"
1023
        clc
1024
 
1025
;----------------------------------------
1733 hidnplayr 1026
; Wake up process waiting on send buffer
1027
 
2891 hidnplayr 1028
  .wakeup:
1029
 
1030
        pushf
2390 hidnplayr 1031
        mov     eax, ebx
1032
        call    SOCKET_notify_owner
1733 hidnplayr 1033
 
1831 hidnplayr 1034
; Update TCPS
1733 hidnplayr 1035
 
2390 hidnplayr 1036
        mov     eax, [edx + TCP_header.AckNumber]
1037
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1038
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1039
        jb      @f
1040
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1733 hidnplayr 1041
       @@:
1042
 
2891 hidnplayr 1043
        popf
1733 hidnplayr 1044
 
1045
; General ACK handling complete
1046
; Now do the state-specific ones
1047
 
2390 hidnplayr 1048
        mov     eax, [ebx + TCP_SOCKET.t_state]
1049
        jmp     dword [eax*4 + .ACK_sw_list]
1733 hidnplayr 1050
 
1051
  .ACK_sw_list:
2891 hidnplayr 1052
        dd      .ack_processed  ; TCPS_CLOSED
1053
        dd      .ack_processed  ; TCPS_LISTEN
1054
        dd      .ack_processed  ; TCPS_SYN_SENT
1055
        dd      .ack_processed  ; TCPS_SYN_RECEIVED
1056
        dd      .ack_processed  ; TCPS_ESTABLISHED
1057
        dd      .ack_processed  ; TCPS_CLOSE_WAIT
1058
        dd      .ack_fw1        ; TCPS_FIN_WAIT_1
1059
        dd      .ack_c          ; TCPS_CLOSING
1060
        dd      .ack_la         ; TCPS_LAST_ACK
1061
        dd      .ack_processed  ; TCPS_FIN_WAIT_2
1062
        dd      .ack_tw         ; TCPS_TIMED_WAIT
1733 hidnplayr 1063
 
1064
 
1772 hidnplayr 1065
  .ack_fw1:
2891 hidnplayr 1066
        jnc     .ack_processed
1733 hidnplayr 1067
 
2390 hidnplayr 1068
        test    [ebx + SOCKET.state], SS_CANTRCVMORE
1069
        jnz     @f
1070
        mov     eax, ebx
1071
        call    SOCKET_is_disconnected
2937 hidnplayr 1072
        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
1772 hidnplayr 1073
       @@:
2390 hidnplayr 1074
        mov     [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1075
        jmp     .ack_processed
1733 hidnplayr 1076
 
1772 hidnplayr 1077
  .ack_c:
2891 hidnplayr 1078
        jnc     .ack_processed
1772 hidnplayr 1079
 
2390 hidnplayr 1080
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1081
        mov     eax, ebx
1082
        call    TCP_cancel_timers
1083
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1084
        mov     eax, ebx
1085
        call    SOCKET_is_disconnected
1086
        jmp     .ack_processed
1733 hidnplayr 1087
 
1772 hidnplayr 1088
  .ack_la:
2891 hidnplayr 1089
        jnc     .ack_processed
1733 hidnplayr 1090
 
2390 hidnplayr 1091
        mov     eax, ebx
2882 hidnplayr 1092
        call    TCP_disconnect
2390 hidnplayr 1093
        jmp     .drop
1733 hidnplayr 1094
 
1772 hidnplayr 1095
  .ack_tw:
2390 hidnplayr 1096
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1097
        jmp     .drop_after_ack
1733 hidnplayr 1098
 
2930 hidnplayr 1099
  .reset_dupacks:               ; We got a new ACK, reset duplicate ACK counter
1100
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
1101
        jmp     .ack_processed
1733 hidnplayr 1102
 
1772 hidnplayr 1103
 
1733 hidnplayr 1104
 
1105
 
2930 hidnplayr 1106
 
1107
 
1108
  .LISTEN:
1109
 
1110
        DEBUGF  1,"TCP_input: state=listen\n"
1111
 
2937 hidnplayr 1112
        test    [edx + TCP_header.Flags], TH_RST
2930 hidnplayr 1113
        jnz     .drop
1114
 
1115
        test    [edx + TCP_header.Flags], TH_ACK
1116
        jnz     .drop_with_reset
1117
 
1118
        test    [edx + TCP_header.Flags], TH_SYN
1119
        jz      .drop
1120
 
1121
;;; TODO: check if it's a broadcast or multicast, and drop if so
1122
 
1123
        push    dword [edi]                             ; Ipv4 source addres
1124
        pop     [ebx + IP_SOCKET.RemoteIP]
1125
 
1126
        push    [edx + TCP_header.SourcePort]
1127
        pop     [ebx + TCP_SOCKET.RemotePort]
1128
 
1129
        push    [edx + TCP_header.SequenceNumber]
1130
        pop     [ebx + TCP_SOCKET.IRS]
1131
 
1132
        mov     eax, [TCP_sequence_num]
1133
        add     [TCP_sequence_num], 64000 / 2
1134
        mov     [ebx + TCP_SOCKET.ISS], eax
1135
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1136
 
1137
        TCP_sendseqinit ebx
1138
        TCP_rcvseqinit ebx
1139
 
1140
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1141
        mov     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1142
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
1143
 
1144
        lea     eax, [ebx + STREAM_SOCKET.snd]
1145
        call    SOCKET_ring_create
1146
 
1147
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1148
        call    SOCKET_ring_create
1149
 
2937 hidnplayr 1150
        and     [ebx + TCP_SOCKET.temp_bits], not TCP_BIT_DROPSOCKET
1151
 
2930 hidnplayr 1152
;;;        call    SOCKET_notify_owner
1153
 
1154
        jmp     .trim_then_step6
1155
 
1156
 
1157
 
1158
 
1159
 
1160
 
1161
 
1162
 
1163
 
1164
 
1165
;------------
1166
; Active Open
1167
 
1168
align 4
2937 hidnplayr 1169
  .SYN_SENT:
2930 hidnplayr 1170
 
1171
        DEBUGF  1,"TCP_input: state=syn_sent\n"
1172
 
1173
        test    [edx + TCP_header.Flags], TH_ACK
1174
        jz      @f
1175
 
1176
        mov     eax, [edx + TCP_header.AckNumber]
1177
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1178
        jbe     .drop_with_reset
1179
 
1180
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
1181
        ja      .drop_with_reset
1182
       @@:
1183
 
1184
        test    [edx + TCP_header.Flags], TH_RST
1185
        jz      @f
1186
 
1187
        test    [edx + TCP_header.Flags], TH_ACK
1188
        jz      .drop
1189
 
1190
        mov     eax, ebx
1191
        mov     ebx, ECONNREFUSED
1192
        call    TCP_drop
1193
 
1194
        jmp     .drop
1195
       @@:
1196
 
1197
        test    [edx + TCP_header.Flags], TH_SYN
1198
        jz      .drop
1199
 
1200
; at this point, segment seems to be valid
1201
 
1202
        test    [edx + TCP_header.Flags], TH_ACK
1203
        jz      .no_syn_ack
1204
 
1205
; now, process received SYN in response to an active open
1206
 
1207
        mov     eax, [edx + TCP_header.AckNumber]
1208
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1209
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1210
        jbe     @f
1211
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1212
       @@:
1213
 
1214
  .no_syn_ack:
1215
        mov     [ebx + TCP_SOCKET.timer_retransmission], 0      ; disable retransmission
1216
 
1217
        push    [edx + TCP_header.SequenceNumber]
1218
        pop     [ebx + TCP_SOCKET.IRS]
1219
 
1220
        TCP_rcvseqinit ebx
1221
 
1222
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1223
 
1224
        mov     eax, [ebx + TCP_SOCKET.SND_UNA]
1225
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1226
        jbe     .simultaneous_open
1227
 
1228
        test    [edx + TCP_header.Flags], TH_ACK
1229
        jz      .simultaneous_open
1230
 
1231
        DEBUGF  1,"TCP_input: active open\n"
1232
 
1233
;;; TODO: update stats
1234
 
1235
; set socket state to connected
1236
        mov     [ebx + SOCKET.state], SS_ISCONNECTED
1237
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1238
 
2937 hidnplayr 1239
; Do window scaling on this connection ?
1240
        mov     eax, [ebx + TCP_SOCKET.t_flags]
1241
        and     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1242
        cmp     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1243
        jne     .no_scaling
2930 hidnplayr 1244
 
2937 hidnplayr 1245
        mov     ax, word [ebx + TCP_SOCKET.requested_s_scale]
1246
        mov     word [ebx + TCP_SOCKET.SND_SCALE], ax
1247
  .no_scaling:
2930 hidnplayr 1248
 
2937 hidnplayr 1249
;;; TODO: reassemble packets queue
1250
 
1251
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1252
        test    eax, eax
1253
        je      .trim_then_step6
1254
        call    TCP_xmit_timer
2930 hidnplayr 1255
        jmp     .trim_then_step6
1256
 
1257
  .simultaneous_open:
1258
 
1259
        DEBUGF  1,"TCP_input: simultaneous open\n"
1260
; We have received a syn but no ACK, so we are having a simultaneous open..
1261
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1262
 
1263
;-------------------------------------
1264
; Common processing for receipt of SYN
1265
 
1266
  .trim_then_step6:
1267
 
1268
        inc     [edx + TCP_header.SequenceNumber]
1269
 
1270
;;; TODO: Drop any received data that follows receive window (590)
1271
 
1272
        mov     eax, [edx + TCP_header.SequenceNumber]
1273
        mov     [ebx + TCP_SOCKET.RCV_UP], eax
1274
        dec     eax
1275
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
1276
 
1277
 
1278
 
2390 hidnplayr 1279
  .ack_processed:       ; (step 6)
1733 hidnplayr 1280
 
2891 hidnplayr 1281
        DEBUGF  1,"TCP_input: ACK processed\n"
1733 hidnplayr 1282
 
1283
;----------------------------------------------
1284
; check if we need to update window information
1285
 
2390 hidnplayr 1286
        test    [edx + TCP_header.Flags], TH_ACK
1287
        jz      .no_window_update
1733 hidnplayr 1288
 
2390 hidnplayr 1289
        mov     eax, [ebx + TCP_SOCKET.SND_WL1]
1290
        cmp     eax, [edx + TCP_header.SequenceNumber]
1291
        jb      .update_window
1292
        ja      @f
1733 hidnplayr 1293
 
2390 hidnplayr 1294
        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1295
        cmp     eax, [edx + TCP_header.AckNumber]
1296
        jb      .update_window
1297
        ja      .no_window_update
1733 hidnplayr 1298
       @@:
1299
 
2390 hidnplayr 1300
        mov     eax, dword [edx + TCP_header.Window]
1301
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1302
        jbe     .no_window_update
1733 hidnplayr 1303
 
1304
  .update_window:
1305
 
2954 hidnplayr 1306
;;; TODO: update stats (Keep track of pure window updates)
1733 hidnplayr 1307
 
2390 hidnplayr 1308
        mov     eax, dword [edx + TCP_header.Window]
1309
        cmp     eax, [ebx + TCP_SOCKET.max_sndwnd]
1310
        jbe     @f
1311
        mov     [ebx + TCP_SOCKET.max_sndwnd], eax
1733 hidnplayr 1312
       @@:
2390 hidnplayr 1313
        mov     [ebx + TCP_SOCKET.SND_WND], eax
1733 hidnplayr 1314
 
2891 hidnplayr 1315
        DEBUGF  1,"TCP_input: Updating window to %u\n", eax
2612 hidnplayr 1316
 
2390 hidnplayr 1317
        push    [edx + TCP_header.SequenceNumber]
1318
        pop     [ebx + TCP_SOCKET.SND_WL1]
1733 hidnplayr 1319
 
2390 hidnplayr 1320
        push    [edx + TCP_header.AckNumber]
1321
        pop     [ebx + TCP_SOCKET.SND_WL2]
1733 hidnplayr 1322
 
2937 hidnplayr 1323
        or      [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
1733 hidnplayr 1324
 
1325
  .no_window_update:
1326
 
1327
;-----------------
1328
; process URG flag
1329
 
2390 hidnplayr 1330
        test    [edx + TCP_header.Flags], TH_URG
1331
        jz      .not_urgent
1733 hidnplayr 1332
 
2390 hidnplayr 1333
        cmp     [edx + TCP_header.UrgentPointer], 0
1334
        jz      .not_urgent
1733 hidnplayr 1335
 
2390 hidnplayr 1336
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1337
        je      .not_urgent
1733 hidnplayr 1338
 
1339
; Ignore bogus urgent offsets
1340
 
2390 hidnplayr 1341
        movzx   eax, [edx + TCP_header.UrgentPointer]
1342
        add     eax, [ebx + STREAM_SOCKET.rcv.size]
1343
        cmp     eax, SOCKET_MAXDATA
1344
        jbe     .not_urgent
1733 hidnplayr 1345
 
2390 hidnplayr 1346
        mov     [edx + TCP_header.UrgentPointer], 0
1347
        and     [edx + TCP_header.Flags], not (TH_URG)
1348
        jmp     .do_data
1733 hidnplayr 1349
 
1350
  .not_urgent:
1351
 
1352
; processing of received urgent pointer
1353
 
2390 hidnplayr 1354
        ;;; TODO (1051-1093)
1733 hidnplayr 1355
 
1356
 
2891 hidnplayr 1357
;---------------------------------------
1358
; process the data in the segment (1094)
1733 hidnplayr 1359
 
1360
  .do_data:
1361
 
2891 hidnplayr 1362
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1363
        jae     .final_processing
1733 hidnplayr 1364
 
2390 hidnplayr 1365
        test    [edx + TCP_header.Flags], TH_FIN
2891 hidnplayr 1366
        jnz     @f
1733 hidnplayr 1367
 
2390 hidnplayr 1368
        test    ecx, ecx
2891 hidnplayr 1369
        jnz     .final_processing
1370
       @@:
1733 hidnplayr 1371
 
2891 hidnplayr 1372
;        call    TCP_reassemble        ;;; TODO
1733 hidnplayr 1373
 
1374
;---------------
1375
; FIN processing
1376
 
2891 hidnplayr 1377
        test    [edx + TCP_header.Flags], TH_FIN
2930 hidnplayr 1378
        jz      .final_processing
1733 hidnplayr 1379
 
2891 hidnplayr 1380
        DEBUGF  1,"TCP_input: Processing FIN\n"
1733 hidnplayr 1381
 
2891 hidnplayr 1382
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1383
        jae     .not_first_fin
1774 hidnplayr 1384
 
2891 hidnplayr 1385
        DEBUGF  1,"TCP_input: First FIN for this connection\n"
1774 hidnplayr 1386
 
2390 hidnplayr 1387
        mov     eax, ebx
1388
        call    SOCKET_cant_recv_more
1774 hidnplayr 1389
 
2390 hidnplayr 1390
        mov     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1391
        inc     [ebx + TCP_SOCKET.RCV_NXT]
1774 hidnplayr 1392
 
1393
  .not_first_fin:
2390 hidnplayr 1394
        mov     eax, [ebx + TCP_SOCKET.t_state]
1395
        shl     eax, 2
1396
        jmp     dword [eax + .FIN_sw_list]
1733 hidnplayr 1397
 
1398
  .FIN_sw_list:
2937 hidnplayr 1399
        dd      .final_processing       ; TCPS_CLOSED
1400
        dd      .final_processing       ; TCPS_LISTEN
1401
        dd      .final_processing       ; TCPS_SYN_SENT
1402
        dd      .fin_syn_est            ; TCPS_SYN_RECEIVED
1403
        dd      .fin_syn_est            ; TCPS_ESTABLISHED
1404
        dd      .final_processing       ; TCPS_CLOSE_WAIT
1405
        dd      .fin_wait1              ; TCPS_FIN_WAIT_1
1406
        dd      .final_processing       ; TCPS_CLOSING
1407
        dd      .final_processing       ; TCPS_LAST_ACK
1408
        dd      .fin_wait2              ; TCPS_FIN_WAIT_2
1409
        dd      .fin_timed              ; TCPS_TIMED_WAIT
1733 hidnplayr 1410
 
1411
  .fin_syn_est:
1412
 
2390 hidnplayr 1413
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
2930 hidnplayr 1414
        jmp     .final_processing
1733 hidnplayr 1415
 
1416
  .fin_wait1:
1417
 
2390 hidnplayr 1418
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
2930 hidnplayr 1419
        jmp     .final_processing
1733 hidnplayr 1420
 
1421
  .fin_wait2:
1422
 
2390 hidnplayr 1423
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1424
        mov     eax, ebx
1425
        call    TCP_cancel_timers
1426
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1427
        call    SOCKET_is_disconnected
2930 hidnplayr 1428
        jmp     .final_processing
1733 hidnplayr 1429
 
1430
  .fin_timed:
2390 hidnplayr 1431
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
2930 hidnplayr 1432
        jmp     .final_processing
1733 hidnplayr 1433
 
1434
 
2930 hidnplayr 1435
  .drop_after_ack:
1436
        DEBUGF  1,"TCP_input: Drop after ACK\n"
1733 hidnplayr 1437
 
2930 hidnplayr 1438
        push    edx ebx
2891 hidnplayr 1439
        lea     ecx, [ebx + SOCKET.mutex]
1440
        call    mutex_unlock
2930 hidnplayr 1441
        pop     eax edx
2891 hidnplayr 1442
 
2930 hidnplayr 1443
        test    [edx + TCP_header.Flags], TH_RST
1444
        jnz     .dumpit
1733 hidnplayr 1445
 
2930 hidnplayr 1446
        or      [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1447
        jmp     .need_output
2891 hidnplayr 1448
 
1733 hidnplayr 1449
 
2891 hidnplayr 1450
 
2930 hidnplayr 1451
  .drop_with_reset:
1452
        DEBUGF  1,"TCP_input: Drop with reset\n"
1453
 
1454
        push    ebx edx
2402 hidnplayr 1455
        lea     ecx, [ebx + SOCKET.mutex]
1456
        call    mutex_unlock
2930 hidnplayr 1457
        pop     edx ebx
1733 hidnplayr 1458
 
2930 hidnplayr 1459
        test    [edx + TCP_header.Flags], TH_RST
1460
        jnz     .dumpit
1733 hidnplayr 1461
 
2930 hidnplayr 1462
        ;;; if its a multicast/broadcast, also drop
1733 hidnplayr 1463
 
2930 hidnplayr 1464
        test    [edx + TCP_header.Flags], TH_ACK
1465
        jnz     .respond_ack
1733 hidnplayr 1466
 
2930 hidnplayr 1467
        test    [edx + TCP_header.Flags], TH_SYN
1468
        jnz     .respond_syn
1469
        jmp     .dumpit
1733 hidnplayr 1470
 
2930 hidnplayr 1471
;-----------------
1472
; Final processing
1733 hidnplayr 1473
 
2930 hidnplayr 1474
  .final_processing:
1475
        DEBUGF  1,"TCP_input: Final processing\n"
1733 hidnplayr 1476
 
2930 hidnplayr 1477
        push    ebx
1478
        lea     ecx, [ebx + SOCKET.mutex]
1479
        call    mutex_unlock
1480
        pop     eax
1733 hidnplayr 1481
 
2937 hidnplayr 1482
        test    [eax + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
1483
        jnz     .need_output
1733 hidnplayr 1484
 
2930 hidnplayr 1485
        test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1486
        jz      .dumpit
1487
        DEBUGF  1,"TCP_input: ACK now!\n"
1733 hidnplayr 1488
 
2930 hidnplayr 1489
  .need_output:
2954 hidnplayr 1490
        DEBUGF  1,"TCP_input: need output\n"
2930 hidnplayr 1491
        call    TCP_output
1733 hidnplayr 1492
 
2930 hidnplayr 1493
  .dumpit:
1494
        DEBUGF  1,"TCP_input: dumping\n"
1733 hidnplayr 1495
 
2942 hidnplayr 1496
        popf
2390 hidnplayr 1497
        call    kernel_free
1498
        add     esp, 4
2942 hidnplayr 1499
 
2390 hidnplayr 1500
        ret
1733 hidnplayr 1501
 
1502
 
1503
  .respond_ack:
2390 hidnplayr 1504
        push    ebx
1505
        mov     cl, TH_RST
1506
        call    TCP_respond_socket
1507
        pop     ebx
1508
        jmp     .destroy_new_socket
1733 hidnplayr 1509
 
1510
 
1511
  .respond_syn:
2390 hidnplayr 1512
        push    ebx
1513
        mov     cl, TH_RST + TH_ACK
1514
        call    TCP_respond_socket
1515
        pop     ebx
1516
        jmp     .destroy_new_socket
1733 hidnplayr 1517
 
1518
 
1519
 
1520
;-----
1521
; Drop
1522
 
2930 hidnplayr 1523
  .drop:
1733 hidnplayr 1524
 
2937 hidnplayr 1525
        DEBUGF  1,"TCP_input: Dropping packet\n"
1526
 
2402 hidnplayr 1527
        pusha
1528
        lea     ecx, [ebx + SOCKET.mutex]
1529
        call    mutex_unlock
1530
        popa
1733 hidnplayr 1531
 
2937 hidnplayr 1532
  .destroy_new_socket:
1733 hidnplayr 1533
 
2937 hidnplayr 1534
        test    [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET
1535
        jz      .drop_no_socket
1733 hidnplayr 1536
 
2937 hidnplayr 1537
        mov     eax, ebx
1538
        call    SOCKET_free
1733 hidnplayr 1539
 
2930 hidnplayr 1540
  .drop_no_socket:
1541
        DEBUGF  1,"TCP_input: Drop (no socket)\n"
1542
 
2942 hidnplayr 1543
        popf
2390 hidnplayr 1544
        call    kernel_free
1545
        add     esp, 4
2942 hidnplayr 1546
 
2600 hidnplayr 1547
        ret
1548
 
2930 hidnplayr 1549
  .drop_with_reset_no_socket:
2600 hidnplayr 1550
 
2891 hidnplayr 1551
        DEBUGF  1,"TCP_input: Drop with reset (no socket)\n"
2600 hidnplayr 1552
 
1553
        test    [edx + TCP_header.Flags], TH_RST
1554
        jnz     .drop_no_socket
1555
 
1556
        ;;; if its a multicast/broadcast, also drop
1557
 
1558
        test    [edx + TCP_header.Flags], TH_ACK
1559
        jnz     .respond_seg_ack
1560
 
1561
        test    [edx + TCP_header.Flags], TH_SYN
1562
        jnz     .respond_seg_syn
1563
 
2930 hidnplayr 1564
        jmp     .drop_no_socket
2600 hidnplayr 1565
 
1566
  .respond_seg_ack:
1567
 
1568
        mov     cl, TH_RST
1569
        call    TCP_respond_segment
1570
        jmp     .drop_no_socket
1571
 
1572
  .respond_seg_syn:
1573
 
1574
        mov     cl, TH_RST + TH_ACK
1575
        call    TCP_respond_segment
1576
        jmp     .drop_no_socket