Subversion Repositories Kolibri OS

Rev

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