Subversion Repositories Kolibri OS

Rev

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

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