Subversion Repositories Kolibri OS

Rev

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