Subversion Repositories Kolibri OS

Rev

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

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