Subversion Repositories Kolibri OS

Rev

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