Subversion Repositories Kolibri OS

Rev

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

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