Subversion Repositories Kolibri OS

Rev

Details | 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: 2612 $
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
 
136
 
137
;----------------------------
138
; Check if socket isnt closed
139
 
2390 hidnplayr 140
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
141
        je      .drop_not_locked
1733 hidnplayr 142
 
143
;----------------
144
; Lock the socket
145
 
2402 hidnplayr 146
        pusha
147
        lea     ecx, [ebx + SOCKET.mutex]
148
        call    mutex_lock
149
        popa
1830 hidnplayr 150
 
2390 hidnplayr 151
        DEBUGF  1,"Socket locked\n"
1733 hidnplayr 152
 
153
;---------------------------------------
154
; unscale the window into a 32 bit value
155
 
2390 hidnplayr 156
        movzx   eax, [edx + TCP_header.Window]
157
        push    ecx
158
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
159
        shl     eax, cl
160
        mov     dword [edx + TCP_header.Window], eax    ; word after window is checksum, we dont need checksum anymore
161
        pop     ecx
1733 hidnplayr 162
 
163
;-----------------------------------
164
; Is this socket a listening socket?
165
 
2390 hidnplayr 166
        test    [ebx + SOCKET.options], SO_ACCEPTCON
167
        jz      .no_listening_socket
1733 hidnplayr 168
 
2390 hidnplayr 169
        DEBUGF  1,"Accepting new connection\n"
1838 hidnplayr 170
 
2402 hidnplayr 171
        pusha
172
        lea     ecx, [ebx + SOCKET.mutex]
173
        call    mutex_unlock
174
        popa
175
 
2390 hidnplayr 176
        push    ecx edx esi edi         ;;;
177
        call    SOCKET_fork
178
        pop     edi esi edx ecx
1838 hidnplayr 179
 
2390 hidnplayr 180
        test    eax, eax
181
        jz      .drop
1733 hidnplayr 182
 
2390 hidnplayr 183
        push    dword [edi + 4]                         ; Ipv4 destination addres
184
        pop     [eax + IP_SOCKET.LocalIP]
1733 hidnplayr 185
 
2390 hidnplayr 186
        push    [edx + TCP_header.DestinationPort]
187
        pop     [eax + TCP_SOCKET.LocalPort]
1733 hidnplayr 188
 
2390 hidnplayr 189
        mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
190
        mov     ebx, eax
1733 hidnplayr 191
 
2390 hidnplayr 192
        jmp     .LISTEN
1838 hidnplayr 193
 
1733 hidnplayr 194
  .no_listening_socket:
195
 
196
;-------------------------------------
197
; Reset idle timer and keepalive timer
198
 
2390 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
 
2390 hidnplayr 205
        movzx   eax, [edx + TCP_header.DataOffset]
206
        cmp     eax, sizeof.TCP_header                  ; Does header contain any options?
207
        je      .no_options
1733 hidnplayr 208
 
2390 hidnplayr 209
        DEBUGF  1,"Segment has options\n"
1733 hidnplayr 210
 
2390 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
 
2390 hidnplayr 214
        add     eax, edx
215
        lea     esi, [edx + sizeof.TCP_header]
1733 hidnplayr 216
 
217
  .opt_loop:
2390 hidnplayr 218
        cmp     esi, eax                        ; are we scanning outside of header?
219
        jae     .no_options
1733 hidnplayr 220
 
2390 hidnplayr 221
        cmp     byte [esi], TCP_OPT_EOL         ; end of option list?
222
        jz      .no_options
1733 hidnplayr 223
 
2390 hidnplayr 224
        cmp     byte [esi], TCP_OPT_NOP         ; nop ?
225
        jz      .opt_nop
1733 hidnplayr 226
 
2390 hidnplayr 227
        cmp     byte [esi], TCP_OPT_MAXSEG
228
        je      .opt_maxseg
1733 hidnplayr 229
 
2390 hidnplayr 230
        cmp     byte [esi], TCP_OPT_WINDOW
231
        je      .opt_window
1733 hidnplayr 232
 
2390 hidnplayr 233
        cmp     byte [esi], TCP_OPT_TIMESTAMP
234
        je      .opt_timestamp
1733 hidnplayr 235
 
2390 hidnplayr 236
        jmp     .no_options     ; If we reach here, some unknown options were received, skip them all!
1733 hidnplayr 237
 
238
  .opt_nop:
2390 hidnplayr 239
        inc     edi
240
        jmp     .opt_loop
1733 hidnplayr 241
 
242
  .opt_maxseg:
2390 hidnplayr 243
        cmp     byte [esi+1], 4
244
        jne     .no_options             ; error occured, ignore all options!
1733 hidnplayr 245
 
2390 hidnplayr 246
        test    [edx + TCP_header.Flags], TH_SYN
247
        jz      @f
1733 hidnplayr 248
 
2390 hidnplayr 249
        movzx   eax, word[esi+2]
250
        rol     ax, 8
251
        DEBUGF  1,"Maxseg: %u\n", ax
1733 hidnplayr 252
 
2390 hidnplayr 253
        mov     [ebx + TCP_SOCKET.t_maxseg], eax
1733 hidnplayr 254
 
255
       @@:
2390 hidnplayr 256
        add     edi, 4
257
        jmp     .opt_loop
1733 hidnplayr 258
 
259
 
260
  .opt_window:
2390 hidnplayr 261
        cmp     byte [esi+1], 3
262
        jne     .no_options
1733 hidnplayr 263
 
2390 hidnplayr 264
        test    [edx + TCP_header.Flags], TH_SYN
265
        jz      @f
1733 hidnplayr 266
 
2390 hidnplayr 267
        DEBUGF  1,"Got window option\n"
1733 hidnplayr 268
 
2390 hidnplayr 269
        ;;;;;
1733 hidnplayr 270
       @@:
2390 hidnplayr 271
        add     edi, 3
272
        jmp     .opt_loop
1733 hidnplayr 273
 
274
 
275
  .opt_timestamp:
2390 hidnplayr 276
        cmp     byte [esi+1], 10
277
        jne     .no_options
1733 hidnplayr 278
 
2390 hidnplayr 279
        DEBUGF  1,"Got timestamp option\n"
1733 hidnplayr 280
 
2390 hidnplayr 281
        ;;;;;
1733 hidnplayr 282
 
2390 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
 
2390 hidnplayr 308
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
309
        jnz     .not_uni_xfer
1733 hidnplayr 310
 
2390 hidnplayr 311
        test    [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
312
        jnz     .not_uni_xfer
1733 hidnplayr 313
 
2390 hidnplayr 314
        test    [edx + TCP_header.Flags], TH_ACK
315
        jz      .not_uni_xfer
1733 hidnplayr 316
 
2390 hidnplayr 317
        mov     eax, [edx + TCP_header.SequenceNumber]
318
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
319
        jne     .not_uni_xfer
1733 hidnplayr 320
 
2390 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
 
2390 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.
2390 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.
2390 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.
2390 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.
2390 hidnplayr 350
        sub     eax, [ebx + TCP_SOCKET.SND_UNA]
351
        jbe     .not_uni_xfer
1733 hidnplayr 352
 
2390 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
2390 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
2390 hidnplayr 370
        mov     eax, [edx + TCP_header.AckNumber]
371
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1733 hidnplayr 372
 
373
; Stop retransmit timer
2390 hidnplayr 374
        mov     [ebx + TCP_SOCKET.timer_retransmission], 0
1733 hidnplayr 375
 
376
; Awaken waiting processes
2402 hidnplayr 377
        pusha
378
        lea     ecx, [ebx + SOCKET.mutex]
379
        call    mutex_unlock
380
        popa
381
 
2390 hidnplayr 382
        mov     eax, ebx
383
        call    SOCKET_notify_owner
1733 hidnplayr 384
 
1763 hidnplayr 385
; Generate more output
2390 hidnplayr 386
        call    TCP_output
1733 hidnplayr 387
 
2390 hidnplayr 388
        jmp     .drop_not_locked
1763 hidnplayr 389
 
1733 hidnplayr 390
;-------------------------------------------------
391
; maybe we are the receiver in the uni-xfer then..
392
 
393
  .not_sender:
394
; - The amount of data in the segment is greater than 0 (data count is in ecx)
395
 
396
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
2390 hidnplayr 397
        mov     eax, [edx + TCP_header.AckNumber]
398
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
399
        jne     .not_uni_xfer
1733 hidnplayr 400
 
401
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
402
 
403
;;; TODO
404
 
2390 hidnplayr 405
        jnz     .not_uni_xfer
1733 hidnplayr 406
 
407
; Complete processing of received data
408
 
2390 hidnplayr 409
        DEBUGF  1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
1733 hidnplayr 410
 
2390 hidnplayr 411
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
1763 hidnplayr 412
 
2390 hidnplayr 413
        movzx   esi, [edx + TCP_header.DataOffset]
414
        add     esi, edx
415
        lea     eax, [ebx + STREAM_SOCKET.rcv]
416
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
1733 hidnplayr 417
 
2390 hidnplayr 418
        mov     eax, ebx
419
        call    SOCKET_notify_owner
1733 hidnplayr 420
 
2390 hidnplayr 421
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK   ; Set delayed ack flag
1733 hidnplayr 422
 
2390 hidnplayr 423
        jmp     .drop
1733 hidnplayr 424
 
425
 
426
 
427
 
428
 
429
 
430
;--------------------------------------------------
431
; Header prediction failed, do it the slow way
432
 
433
  .not_uni_xfer:
434
 
2390 hidnplayr 435
        DEBUGF  1,"Header prediction failed\n"
1733 hidnplayr 436
 
437
; Calculate receive window size
438
 
2362 hidnplayr 439
;        mov     eax, [ebx + STREAM_SOCKET.rcv.size]
2305 hidnplayr 440
;        neg     eax
441
;        add     eax, SOCKETBUFFSIZE
442
;        mov     edx, [ebx + TCP_SOCKET.RCV_ADV]
443
;        sub     edx, [ebx + TCP_SOCKET.RCV_NXT]
444
;        cmp     eax, edx
445
;        jae     @f
446
;        mov     eax, edx
447
;       @@:
1733 hidnplayr 448
 
2390 hidnplayr 449
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
450
        je      .LISTEN
1733 hidnplayr 451
 
2390 hidnplayr 452
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
453
        je      .SYN_SENT
1733 hidnplayr 454
 
2390 hidnplayr 455
        jmp     .NOT_LISTEN_OR_SYN_SENT
1733 hidnplayr 456
 
457
 
458
 
459
;-------------
460
; Passive Open
461
 
462
align 4
2555 hidnplayr 463
  .LISTEN:
1733 hidnplayr 464
 
2390 hidnplayr 465
        DEBUGF  1,"TCP state: listen\n"
1733 hidnplayr 466
 
2390 hidnplayr 467
        test    [edx + TCP_header.Flags], TH_RST        ;;; TODO: kill new socket on error
468
        jnz     .drop
1733 hidnplayr 469
 
2390 hidnplayr 470
        test    [edx + TCP_header.Flags], TH_ACK
471
        jnz     .drop_with_reset
1733 hidnplayr 472
 
2390 hidnplayr 473
        test    [edx + TCP_header.Flags], TH_SYN
474
        jz      .drop
1733 hidnplayr 475
 
476
;;; TODO: check if it's a broadcast or multicast, and drop if so
477
 
2555 hidnplayr 478
        push    dword [edi]                             ; Ipv4 source addres
2390 hidnplayr 479
        pop     [ebx + IP_SOCKET.RemoteIP]
1733 hidnplayr 480
 
2390 hidnplayr 481
        push    [edx + TCP_header.SourcePort]
482
        pop     [ebx + TCP_SOCKET.RemotePort]
1733 hidnplayr 483
 
2390 hidnplayr 484
        push    [edx + TCP_header.SequenceNumber]
485
        pop     [ebx + TCP_SOCKET.IRS]
1733 hidnplayr 486
 
2390 hidnplayr 487
        push    [TCP_sequence_num]                      ;;;;;
488
        add     [TCP_sequence_num], 64000 / 2
489
        pop     [ebx + TCP_SOCKET.ISS]
1733 hidnplayr 490
 
2390 hidnplayr 491
        push    [ebx + TCP_SOCKET.ISS]
492
        pop     [ebx + TCP_SOCKET.SND_NXT]
1733 hidnplayr 493
 
2390 hidnplayr 494
        TCP_sendseqinit ebx
495
        TCP_rcvseqinit ebx
1733 hidnplayr 496
 
2390 hidnplayr 497
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
498
        mov     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
499
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
1838 hidnplayr 500
 
2390 hidnplayr 501
        lea     eax, [ebx + STREAM_SOCKET.snd]
502
        call    SOCKET_ring_create
1733 hidnplayr 503
 
2390 hidnplayr 504
        lea     eax, [ebx + STREAM_SOCKET.rcv]
505
        call    SOCKET_ring_create
1733 hidnplayr 506
 
1838 hidnplayr 507
;;;        call    SOCKET_notify_owner
1733 hidnplayr 508
 
2390 hidnplayr 509
        jmp     .trim_then_step6
510
 
1733 hidnplayr 511
 
512
 
513
 
514
 
515
 
516
 
517
 
518
 
1838 hidnplayr 519
 
1733 hidnplayr 520
;------------
521
; Active Open
522
 
523
align 4
524
.SYN_SENT:
525
 
2390 hidnplayr 526
        DEBUGF  1,"TCP state: syn_sent\n"
1733 hidnplayr 527
 
2390 hidnplayr 528
        test    [edx + TCP_header.Flags], TH_ACK
529
        jz      @f
1733 hidnplayr 530
 
2390 hidnplayr 531
        mov     eax, [edx + TCP_header.AckNumber]
532
        cmp     eax, [ebx + TCP_SOCKET.ISS]
533
        jbe     .drop_with_reset
1733 hidnplayr 534
 
2390 hidnplayr 535
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
536
        ja      .drop_with_reset
1733 hidnplayr 537
       @@:
538
 
2390 hidnplayr 539
        test    [edx + TCP_header.Flags], TH_RST
540
        jz      @f
1733 hidnplayr 541
 
2390 hidnplayr 542
        test    [edx + TCP_header.Flags], TH_ACK
543
        jz      .drop
1733 hidnplayr 544
 
2390 hidnplayr 545
        mov     eax, ebx
546
        mov     ebx, ECONNREFUSED
547
        call    TCP_drop
1733 hidnplayr 548
 
2390 hidnplayr 549
        jmp     .drop
1733 hidnplayr 550
       @@:
551
 
2390 hidnplayr 552
        test    [edx + TCP_header.Flags], TH_SYN
553
        jz      .drop
1733 hidnplayr 554
 
555
; at this point, segment seems to be valid
556
 
2390 hidnplayr 557
        test    [edx + TCP_header.Flags], TH_ACK
558
        jz      .no_syn_ack
1733 hidnplayr 559
 
560
; now, process received SYN in response to an active open
561
 
2390 hidnplayr 562
        mov     eax, [edx + TCP_header.AckNumber]
563
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
564
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
565
        jbe     @f
566
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1733 hidnplayr 567
       @@:
568
 
569
  .no_syn_ack:
570
 
2390 hidnplayr 571
        mov     [ebx + TCP_SOCKET.timer_retransmission], 0      ; disable retransmission
1733 hidnplayr 572
 
2390 hidnplayr 573
        push    [edx + TCP_header.SequenceNumber]
574
        pop     [ebx + TCP_SOCKET.IRS]
1733 hidnplayr 575
 
2390 hidnplayr 576
        TCP_rcvseqinit ebx
1733 hidnplayr 577
 
2390 hidnplayr 578
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1733 hidnplayr 579
 
2390 hidnplayr 580
        mov     eax, [ebx + TCP_SOCKET.SND_UNA]
581
        cmp     eax, [ebx + TCP_SOCKET.ISS]
582
        jbe     .simultaneous_open
1733 hidnplayr 583
 
2390 hidnplayr 584
        test    [edx + TCP_header.Flags], TH_ACK
585
        jz      .simultaneous_open
1733 hidnplayr 586
 
2390 hidnplayr 587
        DEBUGF  1,"TCP: active open\n"
1733 hidnplayr 588
 
589
;;; TODO: update stats
590
 
591
; set socket state to connected
592
 
2390 hidnplayr 593
        mov     [ebx + SOCKET.state],1  ;;;; FIXME
1733 hidnplayr 594
 
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
 
2390 hidnplayr 820
        DEBUGF  1,"Got an RST flag"
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:
2390 hidnplayr 840
        DEBUGF  1,"Connection refused"
1733 hidnplayr 841
 
2390 hidnplayr 842
        mov     [ebx + SOCKET.errorcode], ECONNREFUSED
843
        jmp     .close
1733 hidnplayr 844
 
845
  .econnreset:
2390 hidnplayr 846
        DEBUGF  1,"Connection reset"
1733 hidnplayr 847
 
2390 hidnplayr 848
        mov     [ebx + SOCKET.errorcode], ECONNRESET
1733 hidnplayr 849
 
1831 hidnplayr 850
    .close:
2390 hidnplayr 851
        DEBUGF  1,"Closing connection"
1733 hidnplayr 852
 
2390 hidnplayr 853
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
854
        ;;; TODO: update stats
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]
971
        cmovg   eax, [ebx + TCP_SOCKET.SND_CWND]
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
 
2390 hidnplayr 1060
        DEBUGF  1,"We have an acceptable ACK of %x bytes\n", esi
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
1113
        cmovg   esi, eax
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
1205
        call    TCP_close
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