Subversion Repositories Kolibri OS

Rev

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