Subversion Repositories Kolibri OS

Rev

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

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