Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
9
;;                                                                 ;;
10
;;    Based on the code of 4.4BSD                                  ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
17
$Revision: 3407 $
18
 
19
;-----------------------------------------------------------------
20
;
21
; TCP_input:
22
;
23
;       Add a segment to the incoming TCP queue
24
;
25
;  IN:  [esp] = ptr to buffer
26
;       [esp+4] = buffer size (dont care)
27
;       ebx = ptr to device struct
28
;       ecx = segment size
29
;       esi = ptr to TCP segment
30
;       edi = ptr to ipv4 source address, followed by ipv4 dest address
31
;
32
;  OUT: /
33
;
34
;-----------------------------------------------------------------
35
 
36
align 4
37
TCP_input:
38
 
39
; record the current time
40
        mov     eax, [timer_ticks]      ; in 1/100 seconds
41
        mov     [esp + 4], eax
42
 
43
        push    ebx ecx esi edi         ; mind the order
44
        mov     esi, esp
45
 
46
        pushf
47
        cli
48
        add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail
49
        popf
50
 
51
        add     esp, sizeof.TCP_queue_entry
52
 
3644 hidnplayr 53
        call    NET_ptr_to_num4
54
        inc     [TCP_segments_rx + edi]
55
 
3545 hidnplayr 56
        xor     edx, edx
57
        mov     eax, [TCP_input_event]
58
        mov     ebx, [eax + EVENT.id]
59
        xor     esi, esi
60
        call    raise_event
61
 
62
        ret
63
 
64
  .fail:
65
        popf
3556 hidnplayr 66
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n"
3545 hidnplayr 67
 
3644 hidnplayr 68
        call    NET_ptr_to_num4
69
        inc     [TCP_segments_missed + edi]
3545 hidnplayr 70
 
71
        add     esp, sizeof.TCP_queue_entry - 8
3861 hidnplayr 72
        call    NET_packet_free
3545 hidnplayr 73
        add     esp, 4
74
 
75
        ret
76
 
77
 
78
 
79
 
80
align 4
4339 hidnplayr 81
proc TCP_process_input
3545 hidnplayr 82
 
4339 hidnplayr 83
locals
84
        dataoffset      dd ?
85
endl
86
 
3545 hidnplayr 87
        xor     esi, esi
88
        mov     ecx, MANUAL_DESTROY
89
        call    create_event
90
        mov     [TCP_input_event], eax
91
 
92
  .wait:
93
        mov     eax, [TCP_input_event]
94
        mov     ebx, [eax + EVENT.id]
95
        call    wait_event
96
 
97
  .loop:
98
        get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait
99
 
100
        push    [esi + TCP_queue_entry.timestamp]
101
        push    [esi + TCP_queue_entry.buffer_ptr]
102
 
103
        mov     ebx, [esi + TCP_queue_entry.device_ptr]
104
        mov     ecx, [esi + TCP_queue_entry.segment_size]
105
        mov     edi, [esi + TCP_queue_entry.ip_ptr]                     ; ptr to ipv4 source address, followed by ipv4 destination address
106
        mov     esi, [esi + TCP_queue_entry.segment_ptr]                ; change esi last
107
 
3556 hidnplayr 108
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
3545 hidnplayr 109
 
110
        mov     edx, esi
111
 
112
        cmp     ebx, LOOPBACK_DEVICE
113
        je      .checksum_ok
114
 
115
; re-calculate the checksum (if not already done by hw)
116
;        test    [ebx + NET_DEVICE.hwacc], HWACC_TCP_IPv4_IN
117
;        jnz     .checksum_ok
118
 
119
        push    ecx esi
120
        pushw   [esi + TCP_header.Checksum]
121
        mov     [esi + TCP_header.Checksum], 0
122
        TCP_checksum (edi), (edi+4)
123
        pop     cx                      ; previous checksum
124
        cmp     cx, dx
125
        pop     edx ecx
126
        jne     .drop_no_socket
127
  .checksum_ok:
128
 
129
; Verify the data offset
4339 hidnplayr 130
        movzx   eax, [edx + TCP_header.DataOffset]
131
        and     al, 0xf0                        ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
132
        shr     al, 2
133
        cmp     al, sizeof.TCP_header           ; Now see if it's at least the size of a standard TCP header
134
        jb      .drop_no_socket                 ; If not, drop the packet
135
        mov     [dataoffset], eax
3545 hidnplayr 136
 
137
        sub     ecx, eax                                                ; substract TCP header size from total segment size
138
        jb      .drop_no_socket                                         ; If total segment size is less then the advertised header size, drop packet
3556 hidnplayr 139
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx
3545 hidnplayr 140
 
141
;-------------------------------------------
142
; Convert Big-endian values to little endian
143
 
144
        ntohd   [edx + TCP_header.SequenceNumber]
145
        ntohd   [edx + TCP_header.AckNumber]
146
 
147
        ntohw   [edx + TCP_header.Window]
148
        ntohw   [edx + TCP_header.UrgentPointer]
149
 
150
;------------------------
151
; Find the socket pointer
152
 
153
; IP Packet TCP Destination Port = local Port
154
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
155
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
156
 
157
  .findpcb:
3647 hidnplayr 158
        pusha
159
        mov     ecx, socket_mutex
160
        call    mutex_lock
161
        popa
162
 
3545 hidnplayr 163
        mov     ebx, net_sockets
164
        mov     si, [edx + TCP_header.DestinationPort]
165
 
166
  .socket_loop:
167
        mov     ebx, [ebx + SOCKET.NextPtr]
168
        or      ebx, ebx
3647 hidnplayr 169
        jz      .no_socket ;respond_seg_reset
3545 hidnplayr 170
 
171
        cmp     [ebx + SOCKET.Domain], AF_INET4
172
        jne     .socket_loop
173
 
174
        cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
175
        jne     .socket_loop
176
 
177
        cmp     [ebx + TCP_SOCKET.LocalPort], si
178
        jne     .socket_loop
179
 
180
        mov     eax, [ebx + IP_SOCKET.RemoteIP]
181
        cmp     eax, [edi]                              ; Ipv4 source address
182
        je      @f
183
        test    eax, eax
184
        jnz     .socket_loop
185
       @@:
186
 
187
        mov     ax, [ebx + TCP_SOCKET.RemotePort]
188
        cmp     [edx + TCP_header.SourcePort], ax
189
        je      .found_socket
190
        test    ax, ax
191
        jnz     .socket_loop
192
  .found_socket:                                        ; ebx now contains the socketpointer
3647 hidnplayr 193
        pusha
194
        mov     ecx, socket_mutex
195
        call    mutex_unlock
196
        popa
197
 
3556 hidnplayr 198
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
3545 hidnplayr 199
 
200
;----------------------------
201
; Check if socket isnt closed
202
 
203
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
204
        je      .drop_no_socket
205
 
206
;----------------
207
; Lock the socket
208
 
209
        pusha
210
        lea     ecx, [ebx + SOCKET.mutex]
211
        call    mutex_lock
212
        popa
213
 
3556 hidnplayr 214
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: socket locked\n"
3545 hidnplayr 215
 
216
;---------------------------
217
; disable all temporary bits
218
 
219
        mov     [ebx + TCP_SOCKET.temp_bits], 0
220
 
221
;---------------------------------------
222
; unscale the window into a 32 bit value
223
 
224
        movzx   eax, [edx + TCP_header.Window]
225
        push    ecx
226
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
227
        shl     eax, cl
228
        mov     dword [edx + TCP_header.Window], eax    ; word after window is checksum, we dont need checksum anymore
229
        pop     ecx
230
 
231
;---------------------------------------
232
; Are we accepting incoming connections?
233
 
234
        test    [ebx + SOCKET.options], SO_ACCEPTCON
235
        jz      .no_accept
236
 
3556 hidnplayr 237
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Accepting new connection\n"
3545 hidnplayr 238
 
239
        pusha
240
        lea     ecx, [ebx + SOCKET.mutex]
241
        call    mutex_unlock
242
        popa
243
 
244
        push    ecx edx esi edi         ;;;
245
        call    SOCKET_fork
246
        pop     edi esi edx ecx
247
 
248
        test    eax, eax
249
        jz      .drop_no_socket
250
 
251
        mov     ebx, eax
252
 
253
        mov     [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET        ;;; FIXME: should we take over bits from previous socket?
254
 
255
        push    dword [edi + 4]                         ; Ipv4 destination addres
256
        pop     [ebx + IP_SOCKET.LocalIP]
257
 
258
        push    [edx + TCP_header.DestinationPort]
259
        pop     [ebx + TCP_SOCKET.LocalPort]
260
 
261
        mov     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
262
  .no_accept:
263
 
264
 
265
;-------------------------------------
266
; Reset idle timer and keepalive timer
267
 
268
        mov     [ebx + TCP_SOCKET.t_idle], 0
269
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
3600 hidnplayr 270
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
3545 hidnplayr 271
 
272
;--------------------
273
; Process TCP options
274
 
4339 hidnplayr 275
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
276
;;;        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
277
;;;        jz      .not_uni_xfer                           ; also no header prediction
278
 
3545 hidnplayr 279
        push    ecx
280
 
4339 hidnplayr 281
        mov     ecx, [dataoffset]
3545 hidnplayr 282
        cmp     ecx, sizeof.TCP_header                  ; Does header contain any options?
283
        je      .no_options
284
 
3556 hidnplayr 285
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n"
3545 hidnplayr 286
 
287
        add     ecx, edx
288
        lea     esi, [edx + sizeof.TCP_header]
289
 
290
  .opt_loop:
291
        cmp     esi, ecx                        ; are we scanning outside of header?
292
        jae     .no_options
293
        lodsb
294
        cmp     al, TCP_OPT_EOL                 ; end of option list?
295
        je      .no_options
296
        cmp     al, TCP_OPT_NOP
297
        je      .opt_loop
298
        cmp     al, TCP_OPT_MAXSEG
299
        je      .opt_maxseg
300
        cmp     al, TCP_OPT_WINDOW
301
        je      .opt_window
302
        cmp     al, TCP_OPT_SACK_PERMIT
303
        je      .opt_sack_permit
304
;        cmp     al, TCP_OPT_SACK
305
;        je      .opt_sack
306
        cmp     al, TCP_OPT_TIMESTAMP
307
        je      .opt_timestamp
3556 hidnplayr 308
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: unknown option:%u\n", al
3545 hidnplayr 309
        jmp     .no_options                     ; If we reach here, some unknown options were received, skip them all!
310
 
311
  .opt_maxseg:
312
        lodsb
313
        cmp     al, 4
314
        jne     .no_options                     ; error occured, ignore all options!
315
 
316
        test    [edx + TCP_header.Flags], TH_SYN
317
        jz      @f
318
 
4339 hidnplayr 319
        xor     eax, eax
3545 hidnplayr 320
        lodsw
321
        rol     ax, 8
4339 hidnplayr 322
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", eax
3545 hidnplayr 323
        call    TCP_mss
324
       @@:
325
        jmp     .opt_loop
326
 
327
 
328
  .opt_window:
329
        lodsb
330
        cmp     al, 3
331
        jne     .no_options
332
 
333
        test    [edx + TCP_header.Flags], TH_SYN
334
        jz      @f
335
 
3556 hidnplayr 336
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
3545 hidnplayr 337
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
338
 
339
        lodsb
340
        mov     [ebx + TCP_SOCKET.SND_SCALE], al
341
        ;;;;; TODO
342
 
343
       @@:
344
        jmp     .opt_loop
345
 
346
 
347
  .opt_sack_permit:
348
        lodsb
349
        cmp     al, 2
350
        jne     .no_options
351
 
352
        test    [edx + TCP_header.Flags], TH_SYN
353
        jz      @f
354
 
3556 hidnplayr 355
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Selective Acknowledgement permitted\n"
3545 hidnplayr 356
        or      [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT
357
 
358
       @@:
359
        jmp     .opt_loop
360
 
361
 
362
  .opt_timestamp:
363
        lodsb
364
        cmp     al, 10                          ; length must be 10
365
        jne     .no_options
366
 
3556 hidnplayr 367
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got timestamp option\n"
3545 hidnplayr 368
 
369
        test    [edx + TCP_header.Flags], TH_SYN
370
        jz      @f
371
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
372
       @@:
373
 
374
        lodsd
375
        mov     [ebx + TCP_SOCKET.ts_val], eax
376
        lodsd                                   ; timestamp echo reply
377
        mov     [ebx + TCP_SOCKET.ts_ecr], eax
378
        or      [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
379
 
380
        ; Since we have a timestamp, lets do the paws test right away!
381
 
382
        test    [edx + TCP_header.Flags], TH_RST
383
        jnz     .no_paws
384
 
385
        mov     eax, [ebx + TCP_SOCKET.ts_recent]
386
        test    eax, eax
387
        jz      .no_paws
388
        cmp     eax, [ebx + TCP_SOCKET.ts_val]
389
        jge     .no_paws
390
 
3556 hidnplayr 391
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: PAWS: detected an old segment\n"
3545 hidnplayr 392
 
393
        mov     eax, [esp+4+4]                          ; tcp_now
394
        sub     eax, [ebx + TCP_SOCKET.ts_recent_age]
395
 
396
        pop     ecx
397
        cmp     eax, TCP_PAWS_IDLE
398
        jle     .drop_after_ack                         ; TODO: update stats
399
        push    ecx
400
 
401
        mov     [ebx + TCP_SOCKET.ts_recent], 0         ; timestamp was invalid, fix it.
402
  .no_paws:
403
        jmp     .opt_loop
404
 
405
  .no_options:
406
 
407
        pop     ecx
408
 
409
;-----------------------------------------------------------------------
410
; Time to do some header prediction (Original Principle by Van Jacobson)
411
 
412
; There are two common cases for an uni-directional data transfer.
413
;
414
; General rule: the packets has no control flags, is in-sequence,
415
;   window width didnt change and we're not retransmitting.
416
;
417
; Second rules:
418
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
419
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
420
;
421
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
422
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
423
 
424
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
425
        jnz     .not_uni_xfer
426
 
427
        test    [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
428
        jnz     .not_uni_xfer
429
 
430
        test    [edx + TCP_header.Flags], TH_ACK
431
        jz      .not_uni_xfer
432
 
433
        mov     eax, [edx + TCP_header.SequenceNumber]
434
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
435
        jne     .not_uni_xfer
436
 
437
        mov     eax, dword [edx + TCP_header.Window]
438
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
439
        jne     .not_uni_xfer
440
 
441
        mov     eax, [ebx + TCP_SOCKET.SND_NXT]
442
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
443
        jne     .not_uni_xfer
444
 
445
;---------------------------------------
446
; check if we are sender in the uni-xfer
447
 
448
; If the following 4 conditions are all true, this segment is a pure ACK.
449
;
450
; - The segment contains no data.
451
        test    ecx, ecx
452
        jnz     .not_sender
453
 
454
; - The congestion window is greater than or equal to the current send window.
455
;     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.
456
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
457
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
458
        jb      .not_uni_xfer
459
 
460
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
461
        mov     eax, [edx + TCP_header.AckNumber]
462
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
463
        ja      .not_uni_xfer
464
 
465
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
466
        sub     eax, [ebx + TCP_SOCKET.SND_UNA]
467
        jbe     .not_uni_xfer
468
 
3556 hidnplayr 469
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are sender\n"
3545 hidnplayr 470
 
471
;---------------------------------
472
; Packet is a pure ACK, process it
473
 
474
; Delete acknowledged bytes from send buffer
475
        pusha
476
        mov     ecx, eax
477
        lea     eax, [ebx + STREAM_SOCKET.snd]
478
        call    SOCKET_ring_free
479
        popa
480
 
481
; Update RTT estimators
482
 
483
        test    [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
484
        jz      .no_timestamp_rtt
485
        mov     eax, [esp + 4]                          ; timestamp when this segment was received
486
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
487
        inc     eax
488
        call    TCP_xmit_timer
489
        jmp     .rtt_done
490
 
491
  .no_timestamp_rtt:
492
        cmp     [ebx + TCP_SOCKET.t_rtt], 0
493
        je      .rtt_done
494
        mov     eax, [edx + TCP_header.AckNumber]
495
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
496
        jbe     .rtt_done
497
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
498
        call    TCP_xmit_timer
499
 
500
  .rtt_done:
501
 
502
; update window pointers
503
        mov     eax, [edx + TCP_header.AckNumber]
504
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
505
 
506
; Stop retransmit timer
3600 hidnplayr 507
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
3545 hidnplayr 508
 
509
; Unlock the socket
510
        pusha
511
        lea     ecx, [ebx + SOCKET.mutex]
512
        call    mutex_unlock
513
        popa
514
 
515
; Awaken waiting processes
516
        mov     eax, ebx
517
        call    SOCKET_notify
518
 
519
; Generate more output
520
        call    TCP_output
521
 
522
        jmp     .drop_no_socket
523
 
524
;-------------------------------------------------
525
; maybe we are the receiver in the uni-xfer then..
526
 
527
  .not_sender:
528
; - The amount of data in the segment is greater than 0 (data count is in ecx)
529
 
530
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
531
        mov     eax, [edx + TCP_header.AckNumber]
532
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
533
        jne     .not_uni_xfer
534
 
535
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
536
 
537
;;; TODO
538
 
539
;       jnz     .not_uni_xfer
540
 
541
; Complete processing of received data
542
 
3556 hidnplayr 543
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx
3545 hidnplayr 544
 
545
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
546
 
4339 hidnplayr 547
        mov     esi, [dataoffset]
3545 hidnplayr 548
        add     esi, edx
549
        lea     eax, [ebx + STREAM_SOCKET.rcv]
550
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
551
 
552
        mov     eax, ebx
553
        call    SOCKET_notify
554
 
555
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK   ; Set delayed ack flag
556
 
557
        jmp     .drop
558
 
559
;--------------------------------------------------
560
; Header prediction failed, do it the slow way
561
 
562
  .not_uni_xfer:
563
 
3556 hidnplayr 564
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n"
3545 hidnplayr 565
 
566
; Calculate receive window size
567
 
568
        push    edx
569
        mov     eax, SOCKETBUFFSIZE
570
        sub     eax, [ebx + STREAM_SOCKET.rcv.size]
571
        mov     edx, [ebx + TCP_SOCKET.RCV_ADV]
572
        sub     edx, [ebx + TCP_SOCKET.RCV_NXT]
573
        cmp     eax, edx
574
        jg      @f
575
        mov     eax, edx
576
       @@:
3556 hidnplayr 577
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Receive window size=%d\n", eax
3545 hidnplayr 578
        mov     [ebx + TCP_SOCKET.RCV_WND], eax
579
        pop     edx
580
 
581
; If we are in listen or syn_sent state, go to that specific code right away
582
 
583
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
584
        je      .LISTEN
585
 
586
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
587
        je      .SYN_SENT
588
 
589
;----------------------------
590
; trim any data not in window
591
 
4339 hidnplayr 592
; 1. Check for duplicate data at beginning of segment
3545 hidnplayr 593
 
4339 hidnplayr 594
; Calculate number of bytes we need to drop
3545 hidnplayr 595
        mov     eax, [ebx + TCP_SOCKET.RCV_NXT]
596
        sub     eax, [edx + TCP_header.SequenceNumber]
597
        jle     .no_duplicate
598
 
3556 hidnplayr 599
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes duplicate data!\n", eax
3545 hidnplayr 600
 
601
        test    [edx + TCP_header.Flags], TH_SYN
602
        jz      .no_dup_syn
603
 
3556 hidnplayr 604
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: got duplicate syn\n"
3545 hidnplayr 605
 
606
        and     [edx + TCP_header.Flags], not (TH_SYN)
607
        inc     [edx + TCP_header.SequenceNumber]
608
 
609
        cmp     [edx + TCP_header.UrgentPointer], 1
610
        jbe     @f
611
        dec     [edx + TCP_header.UrgentPointer]
612
        jmp     .dup_syn
613
       @@:
614
        and     [edx + TCP_header.Flags], not (TH_URG)
615
  .dup_syn:
616
        dec     eax
617
  .no_dup_syn:
618
 
4339 hidnplayr 619
; 2. Check for entire duplicate segment
3545 hidnplayr 620
        cmp     eax, ecx                ; eax holds number of bytes to drop, ecx is data size
621
        jb      .duplicate
622
        jnz     @f
623
        test    [edx + TCP_header.Flags], TH_FIN
624
        jnz     .duplicate
625
       @@:
626
 
627
; Any valid FIN must be to the left of the window.
628
; At this point the FIN must be out of sequence or a duplicate, drop it
629
        and     [edx + TCP_header.Flags], not TH_FIN
630
 
631
; send an ACK and resynchronize and drop any data.
632
; But keep on processing for RST or ACK
633
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
634
        mov     eax, ecx
635
 
4339 hidnplayr 636
;;; TODO: update stats
637
 
3545 hidnplayr 638
;-----------------------------------------------
639
; Remove duplicate data and update urgent offset
640
 
641
  .duplicate:
4339 hidnplayr 642
        DEBUGF  1,  "TCP_input: trimming duplicate data\n"
643
 
644
; Trim data from left side of window
645
        add     [dataoffset], eax
3545 hidnplayr 646
        add     [edx + TCP_header.SequenceNumber], eax
647
        sub     ecx, eax
648
 
649
        sub     [edx + TCP_header.UrgentPointer], ax
650
        jg      @f
651
        and     [edx + TCP_header.Flags], not (TH_URG)
652
        mov     [edx + TCP_header.UrgentPointer], 0
653
       @@:
654
 
655
;--------------------------------------------------
4339 hidnplayr 656
; Handle data that arrives after process terminates
3545 hidnplayr 657
 
658
  .no_duplicate:
4339 hidnplayr 659
        cmp     [ebx + SOCKET.PID], 0                   ;;; TODO: use socket flags instead??
3545 hidnplayr 660
        jne     .not_terminated
661
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
662
        jbe     .not_terminated
663
        test    ecx, ecx
664
        jz      .not_terminated
665
 
666
        mov     eax, ebx
667
        call    TCP_close
4339 hidnplayr 668
;;; TODO: update stats
3545 hidnplayr 669
        jmp     .respond_seg_reset
670
 
671
;----------------------------------------
4339 hidnplayr 672
; Remove data beyond right edge of window
3545 hidnplayr 673
 
674
  .not_terminated:
675
        mov     eax, [edx + TCP_header.SequenceNumber]
676
        add     eax, ecx
677
        sub     eax, [ebx + TCP_SOCKET.RCV_NXT]
678
        sub     eax, [ebx + TCP_SOCKET.RCV_WND]         ; eax now holds the number of bytes to drop
679
        jle     .no_excess_data
680
 
3556 hidnplayr 681
        DEBUGF  DEBUG_NETWORK_VERBOSE, "%d bytes beyond right edge of window\n", eax
3545 hidnplayr 682
 
683
;;; TODO: update stats
684
        cmp     eax, ecx
685
        jl      .dont_drop_all
686
; If a new connection request is received while in TIME_WAIT, drop the old connection and start over,
687
; if the sequence numbers are above the previous ones
688
 
689
        test    [edx + TCP_header.Flags], TH_SYN
690
        jz      .no_new_request
691
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
692
        jne     .no_new_request
693
;        mov     edx, [ebx + TCP_SOCKET.RCV_NXT]
694
;        cmp     edx, [edx + TCP_header.SequenceNumber]
695
;        add     edx, 64000      ; TCP_ISSINCR   FIXME
696
        mov     eax, ebx
697
        call    TCP_close
698
        jmp     .findpcb        ; FIXME: skip code for unscaling window, ...
699
  .no_new_request:
700
 
4339 hidnplayr 701
; If window is closed, we can only take segments at window edge, and have to drop data and PUSH from
3545 hidnplayr 702
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
703
 
704
        cmp     [ebx + TCP_SOCKET.RCV_WND], 0
705
        jne     .drop_after_ack
4339 hidnplayr 706
        mov     esi, [edx + TCP_header.SequenceNumber]
707
        cmp     esi, [ebx + TCP_SOCKET.RCV_NXT]
3545 hidnplayr 708
        jne     .drop_after_ack
709
 
710
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
711
;;; TODO: update stats
712
  .dont_drop_all:
713
;;; TODO: update stats
4339 hidnplayr 714
        DEBUGF  1, "Trimming %u bytes from the right of the window\n"
715
        sub     ecx, eax        ; remove data from the right side of window (decrease data length)
3545 hidnplayr 716
        and     [ebx + TCP_SOCKET.t_flags], not (TH_PUSH or TH_FIN)
717
  .no_excess_data:
718
 
719
;-----------------
4339 hidnplayr 720
; Record timestamp
3545 hidnplayr 721
 
722
; If last ACK falls within this segments sequence numbers, record its timestamp
723
        test    [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
724
        jz      .no_timestamp
725
        mov     eax, [ebx + TCP_SOCKET.last_ack_sent]
726
        sub     eax, [edx + TCP_header.SequenceNumber]
727
        jb      .no_timestamp
728
        test    [ebx + TCP_header.Flags], TH_SYN or TH_FIN      ; syn and fin occupy one byte
729
        jz      @f
730
        dec     eax
731
       @@:
732
        sub     eax, ecx
733
        jae     .no_timestamp
734
 
3556 hidnplayr 735
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Recording timestamp\n"
3545 hidnplayr 736
 
737
        mov     eax, [esp + 4]                                  ; tcp_now
738
        mov     [ebx + TCP_SOCKET.ts_recent_age], eax
739
        mov     eax, [ebx + TCP_SOCKET.ts_val]
740
        mov     [ebx + TCP_SOCKET.ts_recent], eax
741
  .no_timestamp:
742
 
743
;------------------
744
; Process RST flags
745
 
746
        test    [edx + TCP_header.Flags], TH_RST
747
        jz      .no_rst
748
 
3556 hidnplayr 749
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got an RST flag\n"
3545 hidnplayr 750
 
751
        mov     eax, [ebx + TCP_SOCKET.t_state]
752
        shl     eax, 2
753
        jmp     dword [eax + .rst_sw_list]
754
 
755
  .rst_sw_list:
756
        dd      .no_rst         ; TCPS_CLOSED
757
        dd      .no_rst         ; TCPS_LISTEN
758
        dd      .no_rst         ; TCPS_SYN_SENT
759
        dd      .econnrefused   ; TCPS_SYN_RECEIVED
760
        dd      .econnreset     ; TCPS_ESTABLISHED
761
        dd      .econnreset     ; TCPS_CLOSE_WAIT
762
        dd      .econnreset     ; TCPS_FIN_WAIT_1
763
        dd      .rst_close      ; TCPS_CLOSING
764
        dd      .rst_close      ; TCPS_LAST_ACK
765
        dd      .econnreset     ; TCPS_FIN_WAIT_2
766
        dd      .rst_close      ; TCPS_TIMED_WAIT
767
 
768
  .econnrefused:
3556 hidnplayr 769
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Connection refused\n"
3545 hidnplayr 770
 
771
        mov     [ebx + SOCKET.errorcode], ECONNREFUSED
772
        jmp     .close
773
 
774
  .econnreset:
3556 hidnplayr 775
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n"
3545 hidnplayr 776
 
777
        mov     [ebx + SOCKET.errorcode], ECONNRESET
778
 
779
  .close:
3556 hidnplayr 780
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Closing connection\n"
3545 hidnplayr 781
 
782
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
783
;;; TODO: update stats (tcp drops)
784
        mov     eax, ebx
785
        call    TCP_close
786
        jmp     .drop_no_socket
787
 
788
  .rst_close:
3556 hidnplayr 789
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n"
3545 hidnplayr 790
 
791
        mov     eax, ebx
792
        call    TCP_close
793
        jmp     .drop_no_socket
794
 
795
  .no_rst:
796
 
797
;--------------------------------------
798
; handle SYN-full and ACK-less segments
799
 
800
        test    [edx + TCP_header.Flags], TH_SYN
801
        jz      .not_syn_full
802
 
803
        mov     eax, ebx
804
        mov     ebx, ECONNRESET
805
        call    TCP_drop
806
        jmp     .drop_with_reset
807
  .not_syn_full:
808
 
809
;---------------
810
; ACK processing
811
 
812
        test    [edx + TCP_header.Flags], TH_ACK
813
        jz      .drop
814
 
815
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
816
        jb      .ack_processed                                  ; states: closed, listen, syn_sent
817
        ja      .no_syn_rcv                                     ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
818
 
3556 hidnplayr 819
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_received\n"
3545 hidnplayr 820
 
821
        mov     eax, [edx + TCP_header.AckNumber]
822
        cmp     [ebx + TCP_SOCKET.SND_UNA], eax
823
        ja      .drop_with_reset
824
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
825
        ja      .drop_with_reset
826
 
827
;;; TODO: update stats
828
 
829
        mov     eax, ebx
830
        call    SOCKET_is_connected
831
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
832
 
833
; Do window scaling?
834
 
835
        test    [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
836
        jz      @f
837
        test    [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
838
        jz      @f
839
 
840
        push    word [ebx + TCP_SOCKET.requested_s_scale]       ; Set send and receive scale factors to the received values
841
        pop     word [ebx + TCP_SOCKET.SND_SCALE]
842
       @@:
843
 
844
;;; TODO: call TCP_reassemble
845
 
846
        mov     eax, [edx + TCP_header.SequenceNumber]
847
        dec     eax
848
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
849
 
850
  .no_syn_rcv:
851
 
852
;-------------------------
853
; check for duplicate ACKs
854
 
855
        mov     eax, [edx + TCP_header.AckNumber]
856
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
857
        ja      .not_dup_ack
858
 
859
        test    ecx, ecx
860
        jnz     .reset_dupacks
861
 
862
        mov     eax, dword [edx + TCP_header.Window]
863
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
864
        jne     .reset_dupacks
865
 
3556 hidnplayr 866
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n"
3545 hidnplayr 867
 
868
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
869
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
870
; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet.
871
 
3600 hidnplayr 872
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
873
        jz      @f
3545 hidnplayr 874
 
875
        mov     eax, [edx + TCP_header.AckNumber]
876
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
877
        je      .dup_ack
878
 
879
       @@:
880
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
881
        jmp     .not_dup_ack
882
 
883
  .dup_ack:
884
        inc     [ebx + TCP_SOCKET.t_dupacks]
885
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
886
        jne     .no_re_xmit
887
 
888
        push    [ebx + TCP_SOCKET.SND_NXT]              ; >>>>
889
 
890
        mov     eax, [ebx + TCP_SOCKET.SND_WND]
891
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
4296 hidnplayr 892
        jbe     @f
893
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
894
  @@:
3545 hidnplayr 895
        shr     eax, 1
896
        push    edx
897
        xor     edx, edx
898
        div     [ebx + TCP_SOCKET.t_maxseg]
899
        cmp     eax, 2
900
        ja      @f
901
        xor     eax, eax
902
        mov     al, 2
903
       @@:
904
        mul     [ebx + TCP_SOCKET.t_maxseg]
905
        pop     edx
906
        mov     [ebx + TCP_SOCKET.SND_SSTHRESH], eax
907
 
3600 hidnplayr 908
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; turn off retransmission timer
3545 hidnplayr 909
        mov     [ebx + TCP_SOCKET.t_rtt], 0
910
        mov     eax, [edx + TCP_header.AckNumber]
911
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
912
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
913
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
914
 
915
; Unlock the socket
916
        push    ebx
917
        lea     ecx, [ebx + SOCKET.mutex]
918
        call    mutex_unlock
919
 
920
; retransmit missing segment
921
        mov     eax, [esp]
922
        call    TCP_output
923
 
924
; Lock the socket again
925
        mov     ecx, [esp]
926
        add     ecx, SOCKET.mutex
927
        call    mutex_lock
3711 clevermous 928
        pop     ebx
3545 hidnplayr 929
 
930
; Continue processing
931
        xor     edx, edx
932
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
933
        mul     [ebx + TCP_SOCKET.t_dupacks]
934
        add     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
935
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
936
 
937
        pop     eax                                     ; <<<<
938
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
939
        jb      @f
940
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
941
       @@:
942
 
943
        jmp     .drop
944
 
945
 
946
  .no_re_xmit:
947
        jbe     .not_dup_ack
948
 
3556 hidnplayr 949
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n"
3545 hidnplayr 950
 
951
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
952
        add     [ebx + TCP_SOCKET.SND_CWND], eax
953
 
954
; Unlock the socket
955
        push    ebx
956
        lea     ecx, [ebx + SOCKET.mutex]
957
        call    mutex_unlock
958
 
959
; retransmit missing segment
960
        mov     eax, [esp]
961
        call    TCP_output
962
 
963
; Lock the socket again
964
        mov     ecx, [esp]
965
        add     ecx, SOCKET.mutex
966
        call    mutex_lock
967
        pop     ebx
968
 
969
        jmp     .drop
970
 
971
 
972
  .not_dup_ack:
973
 
974
;-------------------------------------------------
975
; If the congestion window was inflated to account
976
; for the other side's cached packets, retract it
977
 
978
        mov     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
979
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
980
        ja      @f
981
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
982
        jbe     @f
983
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
984
       @@:
985
 
986
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
987
 
988
        mov     eax, [edx + TCP_header.AckNumber]
989
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
990
        jbe     @f
991
 
992
        ;;; TODO: update stats
993
        jmp     .drop_after_ack
994
 
995
       @@:
996
 
997
        mov     edi, [edx + TCP_header.AckNumber]
998
        sub     edi, [ebx + TCP_SOCKET.SND_UNA]         ; now we got the number of acked bytes in edi
999
 
1000
        ;;; TODO: update stats
1001
 
3556 hidnplayr 1002
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi
3545 hidnplayr 1003
 
1004
;------------------------------------------
1005
; RTT measurements and retransmission timer  (912-926)
1006
 
1007
; If we have a timestamp, update smoothed RTT
1008
 
1009
        test    [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
1010
        jz      .timestamp_not_present
1011
        mov     eax, [esp+4]
1012
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
1013
        inc     eax
1014
        call    TCP_xmit_timer
1015
        jmp     .rtt_done_
1016
 
1017
; If no timestamp but transmit timer is running and timed sequence number was acked,
1018
; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff
1019
; (Phil Karn's retransmit algo)
1020
; Recompute the initial retransmit timer
1021
 
1022
  .timestamp_not_present:
1023
        mov     eax, [edx + TCP_header.AckNumber]
1024
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
1025
        jbe     .rtt_done_
1026
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1027
        test    eax, eax
1028
        jz      .rtt_done_
1029
        call    TCP_xmit_timer
1030
 
1031
  .rtt_done_:
1032
 
1033
; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist)
1034
; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value.
1035
 
1036
        mov     eax, [ebx + TCP_SOCKET.SND_MAX]
1037
        cmp     eax, [edx + TCP_header.AckNumber]
1038
        jne     .more_data
3600 hidnplayr 1039
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
3545 hidnplayr 1040
        or      [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
1041
        jmp     .no_restart
1042
  .more_data:
3600 hidnplayr 1043
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
1044
        jnz     .no_restart
3545 hidnplayr 1045
 
1046
        mov     eax, [ebx + TCP_SOCKET.t_rxtcur]
1047
        mov     [ebx + TCP_SOCKET.timer_retransmission], eax
3600 hidnplayr 1048
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
3545 hidnplayr 1049
  .no_restart:
1050
 
1051
 
1052
;-------------------------------------------
1053
; Open congestion window in response to ACKs
1054
 
1055
        mov     esi, [ebx + TCP_SOCKET.SND_CWND]
1056
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1057
 
1058
        cmp     esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
1059
        jbe     @f
1060
        push    edx
1061
        push    eax
1062
        mul     eax
1063
        div     esi
1064
        pop     edx
1065
        shr     edx, 3
1066
        add     eax, edx
1067
        pop     edx
1068
       @@:
1069
 
1070
        add     esi, eax
1071
 
1072
        push    ecx
1073
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
1074
        mov     eax, TCP_max_win
1075
        shl     eax, cl
1076
        pop     ecx
1077
 
1078
        cmp     esi, eax
4296 hidnplayr 1079
        jbe     @f
1080
        mov     esi, eax
1081
  @@:
3545 hidnplayr 1082
        mov     [ebx + TCP_SOCKET.SND_CWND], esi
1083
 
1084
;------------------------------------------
1085
; Remove acknowledged data from send buffer
1086
 
1087
        cmp     edi, [ebx + STREAM_SOCKET.snd.size]
1088
        jbe     .finiacked
1089
 
1090
        push    ecx edx ebx
1091
        mov     ecx, [ebx + STREAM_SOCKET.snd.size]
1092
        lea     eax, [ebx + STREAM_SOCKET.snd]
1093
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1094
        call    SOCKET_ring_free
1095
        pop     ebx edx ecx
1096
 
3556 hidnplayr 1097
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n"
3545 hidnplayr 1098
        stc
1099
 
1100
        jmp     .wakeup
1101
 
1102
  .finiacked:
1103
 
1104
        push    ecx edx ebx
1105
        mov     ecx, edi
1106
        lea     eax, [ebx + STREAM_SOCKET.snd]
1107
        call    SOCKET_ring_free
1108
        pop     ebx
1109
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1110
        pop     edx ecx
1111
 
3556 hidnplayr 1112
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n"
3545 hidnplayr 1113
        clc
1114
 
1115
;----------------------------------------
1116
; Wake up process waiting on send buffer
1117
 
1118
  .wakeup:
1119
 
1120
        pushf                   ; Keep the flags (Carry flag)
1121
        mov     eax, ebx
1122
        call    SOCKET_notify
1123
 
1124
; Update TCPS
1125
 
1126
        mov     eax, [edx + TCP_header.AckNumber]
1127
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1128
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1129
        jb      @f
1130
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1131
       @@:
1132
 
1133
        popf
1134
 
1135
; General ACK handling complete
1136
; Now do the state-specific ones
1137
; Carry flag is set when our FIN is acked
1138
 
1139
        mov     eax, [ebx + TCP_SOCKET.t_state]
1140
        jmp     dword [eax*4 + .ACK_sw_list]
1141
 
1142
  .ACK_sw_list:
1143
        dd      .ack_processed  ; TCPS_CLOSED
1144
        dd      .ack_processed  ; TCPS_LISTEN
1145
        dd      .ack_processed  ; TCPS_SYN_SENT
1146
        dd      .ack_processed  ; TCPS_SYN_RECEIVED
1147
        dd      .ack_processed  ; TCPS_ESTABLISHED
1148
        dd      .ack_processed  ; TCPS_CLOSE_WAIT
1149
        dd      .ack_fw1        ; TCPS_FIN_WAIT_1
1150
        dd      .ack_c          ; TCPS_CLOSING
1151
        dd      .ack_la         ; TCPS_LAST_ACK
1152
        dd      .ack_processed  ; TCPS_FIN_WAIT_2
1153
        dd      .ack_tw         ; TCPS_TIMED_WAIT
1154
 
1155
 
1156
  .ack_fw1:
1157
        jnc     .ack_processed
1158
 
1159
        test    [ebx + SOCKET.state], SS_CANTRCVMORE
1160
        jnz     @f
1161
        mov     eax, ebx
1162
        call    SOCKET_is_disconnected
1163
        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
3600 hidnplayr 1164
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
3545 hidnplayr 1165
       @@:
1166
        mov     [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1167
        jmp     .ack_processed
1168
 
1169
  .ack_c:
1170
        jnc     .ack_processed
1171
 
1172
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1173
        mov     eax, ebx
1174
        call    TCP_cancel_timers
1175
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
3600 hidnplayr 1176
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
3545 hidnplayr 1177
        mov     eax, ebx
1178
        call    SOCKET_is_disconnected
1179
        jmp     .ack_processed
1180
 
1181
  .ack_la:
1182
        jnc     .ack_processed
1183
 
3652 hidnplayr 1184
        push    ebx
1185
        lea     ecx, [ebx + SOCKET.mutex]
1186
        call    mutex_unlock
1187
        pop     ebx
1188
 
1189
        push    ebx
3545 hidnplayr 1190
        mov     eax, ebx
1191
        call    TCP_disconnect
3652 hidnplayr 1192
        pop     ebx
3545 hidnplayr 1193
 
3652 hidnplayr 1194
        jmp     .destroy_new_socket
1195
 
3545 hidnplayr 1196
  .ack_tw:
1197
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
3600 hidnplayr 1198
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
3545 hidnplayr 1199
        jmp     .drop_after_ack
1200
 
1201
  .reset_dupacks:               ; We got a new ACK, reset duplicate ACK counter
1202
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
1203
        jmp     .ack_processed
1204
 
1205
;-------
1206
; LISTEN
1207
 
1208
align 4
1209
  .LISTEN:
1210
 
3556 hidnplayr 1211
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n"
3545 hidnplayr 1212
 
1213
        test    [edx + TCP_header.Flags], TH_RST
1214
        jnz     .drop
1215
 
1216
        test    [edx + TCP_header.Flags], TH_ACK
1217
        jnz     .drop_with_reset
1218
 
1219
        test    [edx + TCP_header.Flags], TH_SYN
1220
        jz      .drop
1221
 
1222
;;; TODO: check if it's a broadcast or multicast, and drop if so
1223
 
1224
        push    dword [edi]                             ; Ipv4 source addres
1225
        pop     [ebx + IP_SOCKET.RemoteIP]
1226
 
1227
        push    [edx + TCP_header.SourcePort]
1228
        pop     [ebx + TCP_SOCKET.RemotePort]
1229
 
1230
        push    [edx + TCP_header.SequenceNumber]
1231
        pop     [ebx + TCP_SOCKET.IRS]
1232
 
1233
        mov     eax, [TCP_sequence_num]
1234
        add     [TCP_sequence_num], 64000 / 2
1235
        mov     [ebx + TCP_SOCKET.ISS], eax
1236
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1237
 
1238
        TCP_sendseqinit ebx
1239
        TCP_rcvseqinit ebx
1240
 
1241
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1242
        mov     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1243
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
3600 hidnplayr 1244
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
3545 hidnplayr 1245
 
1246
        lea     eax, [ebx + STREAM_SOCKET.snd]
1247
        call    SOCKET_ring_create
1248
 
1249
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1250
        call    SOCKET_ring_create
1251
 
1252
        and     [ebx + TCP_SOCKET.temp_bits], not TCP_BIT_DROPSOCKET
1253
 
3674 hidnplayr 1254
        pusha
1255
        mov     eax, ebx
1256
        call    SOCKET_notify
1257
        popa
3545 hidnplayr 1258
 
1259
        jmp     .trim_then_step6
1260
 
1261
;------------
1262
; Active Open
1263
 
1264
align 4
1265
  .SYN_SENT:
1266
 
3556 hidnplayr 1267
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n"
3545 hidnplayr 1268
 
1269
        test    [edx + TCP_header.Flags], TH_ACK
1270
        jz      @f
1271
 
1272
        mov     eax, [edx + TCP_header.AckNumber]
1273
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1274
        jbe     .drop_with_reset
1275
 
1276
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
1277
        ja      .drop_with_reset
1278
       @@:
1279
 
1280
        test    [edx + TCP_header.Flags], TH_RST
1281
        jz      @f
1282
 
1283
        test    [edx + TCP_header.Flags], TH_ACK
1284
        jz      .drop
1285
 
1286
        mov     eax, ebx
1287
        mov     ebx, ECONNREFUSED
1288
        call    TCP_drop
1289
 
1290
        jmp     .drop
1291
       @@:
1292
 
1293
        test    [edx + TCP_header.Flags], TH_SYN
1294
        jz      .drop
1295
 
1296
; at this point, segment seems to be valid
1297
 
1298
        test    [edx + TCP_header.Flags], TH_ACK
1299
        jz      .no_syn_ack
1300
 
1301
; now, process received SYN in response to an active open
1302
 
1303
        mov     eax, [edx + TCP_header.AckNumber]
1304
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1305
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1306
        jbe     @f
1307
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1308
       @@:
1309
 
1310
  .no_syn_ack:
3600 hidnplayr 1311
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; disable retransmission timer
3545 hidnplayr 1312
 
1313
        push    [edx + TCP_header.SequenceNumber]
1314
        pop     [ebx + TCP_SOCKET.IRS]
1315
 
1316
        TCP_rcvseqinit ebx
1317
 
1318
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1319
 
1320
        mov     eax, [ebx + TCP_SOCKET.SND_UNA]
1321
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1322
        jbe     .simultaneous_open
1323
 
1324
        test    [edx + TCP_header.Flags], TH_ACK
1325
        jz      .simultaneous_open
1326
 
3556 hidnplayr 1327
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n"
3545 hidnplayr 1328
 
1329
;;; TODO: update stats
1330
 
1331
; set socket state to connected
3674 hidnplayr 1332
        push    eax
1333
        mov     eax, ebx
1334
        call    SOCKET_is_connected
1335
        pop     eax
3545 hidnplayr 1336
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1337
 
1338
; Do window scaling on this connection ?
1339
        mov     eax, [ebx + TCP_SOCKET.t_flags]
1340
        and     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1341
        cmp     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1342
        jne     .no_scaling
1343
 
1344
        mov     ax, word [ebx + TCP_SOCKET.requested_s_scale]
1345
        mov     word [ebx + TCP_SOCKET.SND_SCALE], ax
1346
  .no_scaling:
1347
 
1348
;;; TODO: reassemble packets queue
1349
 
1350
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1351
        test    eax, eax
1352
        je      .trim_then_step6
1353
        call    TCP_xmit_timer
1354
        jmp     .trim_then_step6
1355
 
1356
  .simultaneous_open:
1357
 
3556 hidnplayr 1358
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n"
3545 hidnplayr 1359
; We have received a syn but no ACK, so we are having a simultaneous open..
1360
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1361
 
1362
;-------------------------------------
1363
; Common processing for receipt of SYN
1364
 
1365
  .trim_then_step6:
1366
 
1367
        inc     [edx + TCP_header.SequenceNumber]
1368
 
4339 hidnplayr 1369
; Drop any received data that doesnt fit in the receive window.
1370
        cmp     ecx, [ebx + TCP_SOCKET.RCV_WND]
1371
        jbe     .dont_trim
3545 hidnplayr 1372
 
4339 hidnplayr 1373
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: received data does not fit in window, trimming %u bytes\n", eax
1374
        mov     ecx, [ebx + TCP_SOCKET.RCV_WND]
1375
        and     [edx + TCP_header.Flags], not (TH_FIN)
1376
;;; TODO: update stats
1377
 
1378
  .dont_trim:
1379
 
3545 hidnplayr 1380
        mov     eax, [edx + TCP_header.SequenceNumber]
1381
        mov     [ebx + TCP_SOCKET.RCV_UP], eax
1382
        dec     eax
1383
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
1384
 
1385
;-------
1386
; step 6
1387
 
1388
  .ack_processed:
1389
 
3556 hidnplayr 1390
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n"
3545 hidnplayr 1391
 
1392
;----------------------------------------------
1393
; check if we need to update window information
1394
 
1395
        test    [edx + TCP_header.Flags], TH_ACK
1396
        jz      .no_window_update
1397
 
1398
        mov     eax, [ebx + TCP_SOCKET.SND_WL1]
1399
        cmp     eax, [edx + TCP_header.SequenceNumber]
1400
        jb      .update_window
1401
        ja      @f
1402
 
1403
        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1404
        cmp     eax, [edx + TCP_header.AckNumber]
1405
        jb      .update_window
1406
        ja      .no_window_update
1407
       @@:
1408
 
1409
        mov     eax, dword [edx + TCP_header.Window]
1410
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1411
        jbe     .no_window_update
1412
 
1413
  .update_window:
1414
 
1415
;;; TODO: update stats (Keep track of pure window updates)
1416
 
1417
        mov     eax, dword [edx + TCP_header.Window]
1418
        cmp     eax, [ebx + TCP_SOCKET.max_sndwnd]
1419
        jbe     @f
1420
        mov     [ebx + TCP_SOCKET.max_sndwnd], eax
1421
       @@:
1422
        mov     [ebx + TCP_SOCKET.SND_WND], eax
1423
 
3556 hidnplayr 1424
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax
3545 hidnplayr 1425
 
1426
        push    [edx + TCP_header.SequenceNumber]
1427
        pop     [ebx + TCP_SOCKET.SND_WL1]
1428
 
1429
        push    [edx + TCP_header.AckNumber]
1430
        pop     [ebx + TCP_SOCKET.SND_WL2]
1431
 
1432
        or      [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
1433
 
1434
  .no_window_update:
1435
 
1436
;-----------------
1437
; process URG flag
1438
 
1439
        test    [edx + TCP_header.Flags], TH_URG
1440
        jz      .not_urgent
1441
 
1442
        cmp     [edx + TCP_header.UrgentPointer], 0
1443
        jz      .not_urgent
1444
 
1445
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1446
        je      .not_urgent
1447
 
1448
; Ignore bogus urgent offsets
1449
 
1450
        movzx   eax, [edx + TCP_header.UrgentPointer]
1451
        add     eax, [ebx + STREAM_SOCKET.rcv.size]
1452
        cmp     eax, SOCKET_MAXDATA
1453
        jbe     .not_urgent
1454
 
1455
        mov     [edx + TCP_header.UrgentPointer], 0
1456
        and     [edx + TCP_header.Flags], not (TH_URG)
1457
        jmp     .do_data
1458
 
1459
  .not_urgent:
1460
 
1461
; processing of received urgent pointer
1462
 
1463
        ;;; TODO (1051-1093)
1464
 
1465
 
1466
;---------------------------------------
1467
; process the data in the segment (1094)
1468
 
1469
  .do_data:
1470
 
1471
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1472
        jae     .final_processing
1473
 
1474
        test    [edx + TCP_header.Flags], TH_FIN
1475
        jnz     @f
1476
 
1477
        test    ecx, ecx
3756 hidnplayr 1478
        jz      .final_processing
3545 hidnplayr 1479
       @@:
1480
 
1481
; The segment is in order?
1482
        mov     eax, [edx + TCP_header.SequenceNumber]
1483
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
1484
        jne     .out_of_order
1485
 
1486
; The reassembly queue is empty?
1487
        cmp     [ebx + TCP_SOCKET.seg_next], 0
1488
        jne     .out_of_order
1489
 
1490
; The connection is established?
1491
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1492
        jne     .out_of_order
1493
 
1494
; Ok, lets do this..  Set delayed ACK flag and copy data into socket buffer
1495
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK
1496
 
1497
        pusha
4339 hidnplayr 1498
        mov     esi, [dataoffset]
3545 hidnplayr 1499
        add     esi, edx
1500
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1501
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
1502
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
1503
        popa
1504
 
1505
; Wake up the sleeping process
1506
        mov     eax, ebx
1507
        call    SOCKET_notify
1508
 
1509
        jmp     .data_done
1510
 
1511
  .out_of_order:
4339 hidnplayr 1512
        DEBUGF  DEBUG_NETWORK_VERBOSE,  "TCP data is out of order!\nSequencenumber is %u, we expected %u.\n", \
1513
        [edx + TCP_header.SequenceNumber], [ebx + TCP_SOCKET.RCV_NXT]
3545 hidnplayr 1514
 
1515
; Uh-oh, some data is out of order, lets call TCP reassemble for help
1516
 
1517
        call    TCP_reassemble
1518
 
4339 hidnplayr 1519
; Generate ACK immediately, to let the other end know that a segment was received out of order,
1520
; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm.
3545 hidnplayr 1521
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1522
 
1523
  .data_done:
1524
 
1525
;---------------
1526
; FIN processing
1527
 
1528
        test    [edx + TCP_header.Flags], TH_FIN
1529
        jz      .final_processing
1530
 
3556 hidnplayr 1531
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n"
3545 hidnplayr 1532
 
1533
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1534
        jae     .not_first_fin
1535
 
3556 hidnplayr 1536
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n"
3545 hidnplayr 1537
 
1538
        mov     eax, ebx
1539
        call    SOCKET_cant_recv_more
1540
 
1541
        mov     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1542
        inc     [ebx + TCP_SOCKET.RCV_NXT]
1543
 
1544
  .not_first_fin:
1545
        mov     eax, [ebx + TCP_SOCKET.t_state]
1546
        shl     eax, 2
1547
        jmp     dword [eax + .FIN_sw_list]
1548
 
1549
  .FIN_sw_list:
1550
        dd      .final_processing       ; TCPS_CLOSED
1551
        dd      .final_processing       ; TCPS_LISTEN
1552
        dd      .final_processing       ; TCPS_SYN_SENT
1553
        dd      .fin_syn_est            ; TCPS_SYN_RECEIVED
1554
        dd      .fin_syn_est            ; TCPS_ESTABLISHED
1555
        dd      .final_processing       ; TCPS_CLOSE_WAIT
1556
        dd      .fin_wait1              ; TCPS_FIN_WAIT_1
1557
        dd      .final_processing       ; TCPS_CLOSING
1558
        dd      .final_processing       ; TCPS_LAST_ACK
1559
        dd      .fin_wait2              ; TCPS_FIN_WAIT_2
1560
        dd      .fin_timed              ; TCPS_TIMED_WAIT
1561
 
1562
  .fin_syn_est:
1563
 
1564
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1565
        jmp     .final_processing
1566
 
1567
  .fin_wait1:
1568
 
1569
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1570
        jmp     .final_processing
1571
 
1572
  .fin_wait2:
1573
 
1574
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1575
        mov     eax, ebx
1576
        call    TCP_cancel_timers
1577
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
3600 hidnplayr 1578
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
3545 hidnplayr 1579
        call    SOCKET_is_disconnected
1580
        jmp     .final_processing
1581
 
1582
  .fin_timed:
1583
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
3600 hidnplayr 1584
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
3545 hidnplayr 1585
        jmp     .final_processing
1586
 
1587
 
1588
  .drop_after_ack:
3556 hidnplayr 1589
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n"
3545 hidnplayr 1590
 
1591
        push    edx ebx
1592
        lea     ecx, [ebx + SOCKET.mutex]
1593
        call    mutex_unlock
1594
        pop     eax edx
1595
 
1596
        test    [edx + TCP_header.Flags], TH_RST
1597
        jnz     .dumpit
1598
 
1599
        or      [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1600
        jmp     .need_output
1601
 
1602
  .drop_with_reset:
3556 hidnplayr 1603
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n"
3545 hidnplayr 1604
 
1605
        push    ebx edx
1606
        lea     ecx, [ebx + SOCKET.mutex]
1607
        call    mutex_unlock
1608
        pop     edx ebx
1609
 
1610
        test    [edx + TCP_header.Flags], TH_RST
1611
        jnz     .dumpit
1612
 
1613
        ;;; if its a multicast/broadcast, also drop
1614
 
1615
        test    [edx + TCP_header.Flags], TH_ACK
1616
        jnz     .respond_ack
1617
 
1618
        test    [edx + TCP_header.Flags], TH_SYN
1619
        jnz     .respond_syn
1620
        jmp     .dumpit
1621
 
1622
;-----------------
1623
; Final processing
1624
 
1625
  .final_processing:
3556 hidnplayr 1626
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
3545 hidnplayr 1627
 
1628
        push    ebx
1629
        lea     ecx, [ebx + SOCKET.mutex]
1630
        call    mutex_unlock
1631
        pop     eax
1632
 
1633
        test    [eax + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
1634
        jnz     .need_output
1635
 
1636
        test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1637
        jz      .dumpit
3556 hidnplayr 1638
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
3545 hidnplayr 1639
 
1640
  .need_output:
3556 hidnplayr 1641
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
3545 hidnplayr 1642
        call    TCP_output
1643
 
1644
  .dumpit:
3556 hidnplayr 1645
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
3545 hidnplayr 1646
 
3861 hidnplayr 1647
        call    NET_packet_free
3545 hidnplayr 1648
        add     esp, 4
1649
        jmp     .loop
1650
 
1651
;---------
1652
; Respond
1653
 
1654
  .respond_ack:
1655
        push    ebx
1656
        mov     cl, TH_RST
1657
        call    TCP_respond
1658
        pop     ebx
1659
        jmp     .destroy_new_socket
1660
 
1661
  .respond_syn:
1662
        push    ebx
1663
        mov     cl, TH_RST + TH_ACK
1664
        call    TCP_respond
1665
        pop     ebx
1666
        jmp     .destroy_new_socket
1667
 
3647 hidnplayr 1668
  .no_socket:
1669
 
1670
        pusha
1671
        mov     ecx, socket_mutex
1672
        call    mutex_unlock
1673
        popa
1674
 
3545 hidnplayr 1675
  .respond_seg_reset:
1676
        test    [edx + TCP_header.Flags], TH_RST
1677
        jnz     .drop_no_socket
1678
 
1679
        ;;; TODO: if its a multicast/broadcast, also drop
1680
 
1681
        test    [edx + TCP_header.Flags], TH_ACK
1682
        jnz     .respond_seg_ack
1683
 
1684
        test    [edx + TCP_header.Flags], TH_SYN
1685
        jnz     .respond_seg_syn
1686
 
1687
        jmp     .drop_no_socket
1688
 
1689
  .respond_seg_ack:
1690
        mov     cl, TH_RST
1691
        call    TCP_respond_segment
1692
        jmp     .drop_no_socket
1693
 
1694
  .respond_seg_syn:
1695
        mov     cl, TH_RST + TH_ACK
1696
        call    TCP_respond_segment
1697
        jmp     .drop_no_socket
1698
 
1699
;-----
1700
; Drop
1701
 
1702
  .drop:
3556 hidnplayr 1703
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n"
3545 hidnplayr 1704
 
1705
        pusha
1706
        lea     ecx, [ebx + SOCKET.mutex]
1707
        call    mutex_unlock
1708
        popa
1709
 
1710
  .destroy_new_socket:
1711
        test    [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET
1712
        jz      .drop_no_socket
1713
 
1714
        mov     eax, ebx
1715
        call    SOCKET_free
1716
 
1717
  .drop_no_socket:
3556 hidnplayr 1718
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n"
3545 hidnplayr 1719
 
3861 hidnplayr 1720
        call    NET_packet_free
3545 hidnplayr 1721
        add     esp, 4
1722
        jmp     .loop
4339 hidnplayr 1723
 
1724
endp