2 added + 21 modified, total 23 files
reactos
diff -u -r1.220 -r1.221
--- ChangeLog 25 Feb 2004 20:27:56 -0000 1.220
+++ ChangeLog 4 Mar 2004 20:45:38 -0000 1.221
@@ -1,3 +1,53 @@
+2004-03-04 Casper S. Hornstrup <chorns@users.sourceforge.net>
+
+ * drivers/net/tcpip/tcpip/i386: New directory.
+ * drivers/net/tcpip/tcpip/i386/checksum.S: New file.
+ * drivers/net/tcpip/notes.txt: New file.
+ * drivers/net/afd/afd/dispatch.c (AfdDispCompleteListen): Signal ACCEPT
+ network event.
+ (AfdDispEventSelect): Reference event handle.
+ * drivers/net/afd/afd/tdi.c (TdiListen): Remove unused event.
+ Move Iosb and RequestConnectionInfo to AFD_LISTEN_REQUEST structure.
+ * drivers/net/afd/include/afd.h (AFDFCB): Replace EventObjects with
+ EventObject of type PKEVENT.
+ * drivers/net/tcpip/makefile (ARCH_OBJECTS): New variable.
+ (TARGET_OBJECTS): Add ARCH_OBJECTS.
+ * drivers/net/tcpip/include/address.h (AddrCloneAddress): New prototype.
+ * drivers/net/tcpip/include/checksum.h (ChecksumFold, csum_partial): New
+ prototype.
+ (TCPv4Checksum): New macro.
+ (CorrectChecksum): Rename to IPv4CorrectChecksum.
+ (TCPv4CorrectChecksum): New macro.
+ * drivers/net/tcpip/include/ip.h (IPv4_DF_MASK): New constant.
+ * drivers/net/tcpip/include/tcp.h (TCP_XXX): Correct constants.
+ (TCPCreateSegment, TCPFreeSegment, TCPAddSegment): Prototype.
+ * drivers/net/tcpip/include/titypes.h (TCP_SEND_REQUEST): Add SequenceNumber
+ and AckNumber.
+ (TCP_SEGMENT): New structure.
+ (CONNECTION_ENDPOINT): Add ListenRequest and ReceivedSegments.
+ * drivers/net/tcpip/network/transmit.c (SendFragments): Release memory
+ for Data on failure.
+ * drivers/net/tcpip/tcpip/address.c (AddrCloneAddress): New function.
+ * drivers/net/tcpip/tcpip/checksum.c (ChecksumFold): Factor out folding
+ from ChecksumCompute.
+ * drivers/net/tcpip/tcpip/dispatch.c (DispTdiListen): Support asynchronous
+ operation.
+ * drivers/net/tcpip/tcpip/fileobjs.c (FileOpenAddress): Don't cast to
+ PTDI_ADDRESS_IP.
+ Initialize ReceivedSegments.
+ * drivers/net/tcpip/tcpip/routines.c (DisplayIPHeader): New function.
+ (DisplayIPPacket): Call DisplayIPHeader().
+ (DisplayTCPHeader): Change format strings.
+ * drivers/net/tcpip/transport/tcp/tcp.c (IPIdentification,
+ TCPSegmentList): Add.
+ (TCPCreateSegment, TCPFreeSegment, TCPAddSegment,
+ TCPBuildAndTransmitSendRequest2, TCPiSelectISS, TCPiReceiveListen,
+ TCPiReceiveSynSent, TCPiReceiveSynReceived, TCPiReceiveData): New
+ function.
+ (TCPiBuildPacket): Build segment.
+ (TCPStartup): Initialize TCPSegmentList.
+ (TCPShutdown): Cleanup TCPSegmentList.
+
2004-02-25 Casper S. Hornstrup <chorns@users.sourceforge.net>
* drivers/net/tcpip/datalink/loopback.c: Reformat.
reactos/drivers/net/afd/afd
diff -u -r1.10 -r1.11
--- dispatch.c 10 Feb 2004 17:12:41 -0000 1.10
+++ dispatch.c 4 Mar 2004 20:45:38 -0000 1.11
@@ -139,9 +139,25 @@
{
PAFD_LISTEN_REQUEST ListenRequest = (PAFD_LISTEN_REQUEST) Context;
- AFD_DbgPrint(MAX_TRACE, ("Called. ListenRequest (0x%X).\n", ListenRequest));
+ /* FIXME: Protect ListenRequest->Fcb->ListenRequestQueue */
+ RemoveEntryList(&ListenRequest->ListEntry);
- AFD_DbgPrint(MAX_TRACE, ("Fcb (0x%X).\n", ListenRequest->Fcb));
+ AFD_DbgPrint(MAX_TRACE, ("Completed ListenRequest at (0x%X).\n", ListenRequest));
+
+ if (NT_SUCCESS(ListenRequest->Iosb.Status))
+ {
+ if (ListenRequest->Fcb->EventObject != NULL)
+ {
+ /* FIXME: Protect ListenRequest->Fcb */
+ ListenRequest->Fcb->NetworkEvents.lNetworkEvents |= FD_ACCEPT;
+ ListenRequest->Fcb->NetworkEvents.iErrorCode[FD_ACCEPT_BIT] = NO_ERROR;
+ KeSetEvent(ListenRequest->Fcb->EventObject, EVENT_INCREMENT, FALSE);
+ }
+ }
+
+ ExFreePool(ListenRequest->RequestConnectionInfo);
+ ListenRequest->RequestConnectionInfo = NULL;
+ ExFreePool(ListenRequest);
return STATUS_SUCCESS;
}
@@ -197,14 +213,14 @@
if (NT_SUCCESS(Status))
{
- ListenRequest = ExAllocateFromNPagedLookasideList(&ListenRequestLookasideList);
+ ListenRequest = ExAllocateFromNPagedLookasideList(&ListenRequestLookasideList);
if (ListenRequest != NULL)
{
ListenRequest->Fcb = FCB;
/* FIXME: Protect ListenRequestQueue */
InsertTailList(&FCB->ListenRequestQueue, &ListenRequest->ListEntry);
- Status = TdiListen(FCB->TdiConnectionObject, AfdDispCompleteListen, ListenRequest);
+ Status = TdiListen(ListenRequest, AfdDispCompleteListen, ListenRequest);
if ((Status == STATUS_PENDING) || NT_SUCCESS(Status))
{
if (Status != STATUS_PENDING)
@@ -630,8 +646,8 @@
UINT OutputBufferLength;
PFILE_REQUEST_EVENTSELECT Request;
PFILE_REPLY_EVENTSELECT Reply;
+ PKEVENT Event;
PAFDFCB FCB;
- ULONG i;
InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
@@ -644,20 +660,32 @@
Request = (PFILE_REQUEST_EVENTSELECT)Irp->AssociatedIrp.SystemBuffer;
Reply = (PFILE_REPLY_EVENTSELECT)Irp->AssociatedIrp.SystemBuffer;
- FCB->NetworkEvents.lNetworkEvents = Request->lNetworkEvents;
- for (i = 0; i < FD_MAX_EVENTS; i++) {
- if ((Request->lNetworkEvents & (1 << i)) > 0) {
- FCB->EventObjects[i] = Request->hEventObject;
- } else {
- /* The effect of any previous call to this function is cancelled */
- FCB->EventObjects[i] = (WSAEVENT)0;
- }
- }
+ /* FIXME: Need to ObDereferenceObject(FCB->EventObject) this somewhere */
+ Status = ObReferenceObjectByHandle(
+ Request->hEventObject,
+ 0,
+ ExEventObjectType,
+ UserMode,
+ (PVOID*)&Event,
+ NULL);
+ if (NT_SUCCESS(Status)) {
+ FCB->NetworkEvents.lNetworkEvents = Request->lNetworkEvents;
+ FCB->EventObject = Event;
+ Reply->Status = NO_ERROR;
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ AFD_DbgPrint(MID_TRACE, ("Bad event handle (0x%X).\n", Status));
- Reply->Status = NO_ERROR;
- Status = STATUS_SUCCESS;
- } else
+ Reply->Status = WSAEINVAL;
+ Status = STATUS_SUCCESS;
+ }
+ }
+ else
+ {
Status = STATUS_INVALID_PARAMETER;
+ }
AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
reactos/drivers/net/afd/afd
diff -u -r1.11 -r1.12
--- tdi.c 2 Mar 2004 18:18:13 -0000 1.11
+++ tdi.c 4 Mar 2004 20:45:38 -0000 1.12
@@ -199,6 +199,7 @@
EaInfo->EaValueLength = sizeof(TA_IP_ADDRESS);
Address = (PTA_IP_ADDRESS)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH + 1); /* 0-terminated */
TdiBuildAddressIPv4(Address, Name);
+
Status = TdiOpenDevice(DeviceName,
EaLength,
EaInfo,
@@ -414,13 +415,13 @@
NTSTATUS TdiListen(
- PFILE_OBJECT ConnectionObject,
+ PAFD_LISTEN_REQUEST ListenRequest,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
/*
* FUNCTION: Listen on a connection endpoint for a connection request from a remote peer
* ARGUMENTS:
- * ConnectionObject = Pointer to connection endpoint file object
+ * ListenRequest = Pointer to listen request object
* CompletionRoutine = Routine to be called when IRP is completed
* CompletionContext = Context for CompletionRoutine
* RETURNS:
@@ -428,35 +429,34 @@
* May return STATUS_PENDING
*/
{
- PTDI_CONNECTION_INFORMATION RequestConnectionInfo;
- //PTDI_CONNECTION_INFORMATION ReturnConnectionInfo;
+ PFILE_OBJECT ConnectionObject;
PDEVICE_OBJECT DeviceObject;
- IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
- KEVENT Event;
PIRP Irp;
AFD_DbgPrint(MAX_TRACE, ("Called\n"));
+ ConnectionObject = ListenRequest->Fcb->TdiConnectionObject;
assert(ConnectionObject);
DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
- Status = TdiBuildNullConnectionInfo(&RequestConnectionInfo, TDI_ADDRESS_TYPE_IP);
+ Status = TdiBuildNullConnectionInfo(&ListenRequest->RequestConnectionInfo,
+ TDI_ADDRESS_TYPE_IP);
if (!NT_SUCCESS(Status))
- return Status;
-
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ return Status;
Irp = TdiBuildInternalDeviceControlIrp(TDI_LISTEN, /* Sub function */
DeviceObject, /* Device object */
ConnectionObject, /* File object */
- &Event, /* Event */
- &Iosb); /* Status */
- if (!Irp) {
- ExFreePool(RequestConnectionInfo);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ NULL, /* Event */
+ &ListenRequest->Iosb); /* Status */
+ if (Irp == NULL)
+ {
+ ExFreePool(ListenRequest->RequestConnectionInfo);
+ ListenRequest->RequestConnectionInfo = NULL;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
TdiBuildListen(Irp, /* IRP */
DeviceObject, /* Device object */
@@ -464,13 +464,10 @@
CompletionRoutine, /* Completion routine */
CompletionContext, /* Completion routine context */
0, /* Flags */
- RequestConnectionInfo, /* Request connection information */
+ ListenRequest->RequestConnectionInfo, /* Request connection information */
NULL /* ReturnConnectionInfo */); /* Return connection information */
- Status = TdiCall(Irp, DeviceObject, NULL /* Don't wait for completion */, &Iosb);
-
- ExFreePool(RequestConnectionInfo);
- //ExFreePool(ReturnConnectionInfo);
+ Status = TdiCall(Irp, DeviceObject, NULL /* Don't wait for completion */, &ListenRequest->Iosb);
return Status;
}
reactos/drivers/net/afd/include
diff -u -r1.14 -r1.15
--- afd.h 2 Mar 2004 18:18:13 -0000 1.14
+++ afd.h 4 Mar 2004 20:45:38 -0000 1.15
@@ -75,7 +75,7 @@
LIST_ENTRY ListenRequestQueue;
/* For WSAEventSelect() */
WSANETWORKEVENTS NetworkEvents;
- WSAEVENT EventObjects[FD_MAX_EVENTS];
+ PKEVENT EventObject;
} AFDFCB, *PAFDFCB;
/* Socket states */
@@ -99,6 +99,8 @@
typedef struct _AFD_LISTEN_REQUEST {
LIST_ENTRY ListEntry;
PAFDFCB Fcb;
+ PTDI_CONNECTION_INFORMATION RequestConnectionInfo;
+ IO_STATUS_BLOCK Iosb;
} AFD_LISTEN_REQUEST, *PAFD_LISTEN_REQUEST;
typedef struct IPSNMP_INFO {
@@ -363,7 +365,7 @@
PFILE_OBJECT ConnectionObject);
NTSTATUS TdiListen(
- PFILE_OBJECT ConnectionObject,
+ PAFD_LISTEN_REQUEST Request,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext);
reactos/drivers/net/tcpip
diff -N notes.txt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ notes.txt 4 Mar 2004 20:45:38 -0000 1.1
@@ -0,0 +1,27 @@
+
+RFC 791 - Internet Protocol
+http://www.faqs.org/rfcs/rfc791.html
+
+RFC 792 - Internet Control Message Protocol
+http://www.faqs.org/rfcs/rfc792.html
+
+RFC 793 - Transmission Control Protocol
+http://www.faqs.org/rfcs/rfc793.html
+
+RFC 826 - Ethernet Address Resolution Protocol
+http://www.faqs.org/rfcs/rfc826.html
+
+RFC 1122 - Requirements for Internet Hosts - Communication Layers
+http://www.faqs.org/rfcs/rfc1122.html
+
+RFC 1123 - Requirements for Internet Hosts - Application and Support
+http://www.faqs.org/rfcs/rfc1123.html
+
+RFC 2398 - Some Testing Tools for TCP Implementors
+http://www.faqs.org/rfcs/rfc2398.html
+
+RFC 2525 - Known TCP Implementation Problems
+http://www.faqs.org/rfcs/rfc2525.html
+
+RFC 2581 - TCP Congestion Control
+http://www.faqs.org/rfcs/rfc2581.html
\ No newline at end of file
reactos/drivers/net/tcpip
diff -u -r1.15 -r1.16
--- makefile 2 Mar 2004 18:18:14 -0000 1.15
+++ makefile 4 Mar 2004 20:45:38 -0000 1.16
@@ -1,4 +1,4 @@
-# $Id: makefile,v 1.15 2004/03/02 18:18:14 navaraf Exp $
+# $Id: makefile,v 1.16 2004/03/04 20:45:38 chorns Exp $
PATH_TO_TOP = ../../..
@@ -34,6 +34,7 @@
transport/tcp/tcp_input.o transport/tcp/tcp_ipv4.o \
transport/tcp/tcp_output.o transport/tcp/tcp_timer.o
UDP_OBJECTS = transport/udp/udp.o
+ARCH_OBJECTS = tcpip/i386/checksum.o
TARGET_OBJECTS = \
$(TCPIP_OBJECTS) \
@@ -42,7 +43,8 @@
$(DATAGRAM_OBJECTS) \
$(RAWIP_OBJECTS) \
$(TCP_OBJECTS) \
- $(UDP_OBJECTS)
+ $(UDP_OBJECTS) \
+ $(ARCH_OBJECTS)
include $(PATH_TO_TOP)/rules.mak
reactos/drivers/net/tcpip/include
diff -u -r1.6 -r1.7
--- address.h 2 Mar 2004 18:18:14 -0000 1.6
+++ address.h 4 Mar 2004 20:45:38 -0000 1.7
@@ -61,6 +61,9 @@
PIP_ADDRESS AddrBuildIPv4(
IPv4_RAW_ADDRESS Address);
+PIP_ADDRESS AddrCloneAddress(
+ PIP_ADDRESS Address);
+
PADDRESS_ENTRY AddrLocateADEv4(
IPv4_RAW_ADDRESS Address);
reactos/drivers/net/tcpip/include
diff -u -r1.2 -r1.3
--- checksum.h 2 Aug 2000 00:21:35 -0000 1.2
+++ checksum.h 4 Mar 2004 20:45:38 -0000 1.3
@@ -8,20 +8,39 @@
#define __CHECKSUM_H
+ULONG ChecksumFold(
+ ULONG Sum);
+
ULONG ChecksumCompute(
PVOID Data,
UINT Count,
ULONG Seed);
-#define IPv4Checksum(Data, Count, Seed)(ChecksumCompute(Data, Count, Seed))
+unsigned int
+csum_partial(
+ const unsigned char * buff,
+ int len,
+ unsigned int sum);
+
+#define IPv4Checksum(Data, Count, Seed)(~ChecksumFold(ChecksumCompute(Data, Count, Seed)))
+#define TCPv4Checksum(Data, Count, Seed)(~ChecksumFold(csum_partial(Data, Count, Seed)))
+//#define TCPv4Checksum(Data, Count, Seed)(~ChecksumFold(ChecksumCompute(Data, Count, Seed)))
/*
* Macro to check for a correct checksum
- * BOOLEAN CorrectChecksum(PVOID Data, UINT Count)
+ * BOOLEAN IPv4CorrectChecksum(PVOID Data, UINT Count)
*/
-#define CorrectChecksum(Data, Count) \
+#define IPv4CorrectChecksum(Data, Count) \
(BOOLEAN)(IPv4Checksum(Data, Count, 0) == DH2N(0x0000FFFF))
-#endif /* __CHECKSUM_H */
+/*
+ * Macro to check for a correct checksum
+ * BOOLEAN TCPv4CorrectChecksum(PTCPv4_PSEUDO_HEADER TcpPseudoHeader,
+ * PVOID Data, UINT Count)
+ */
+#define TCPv4CorrectChecksum(TcpPseudoHeader, Data, Count) \
+ (BOOLEAN)(TCPv4Checksum(Data, Count, \
+ TCPv4Checksum(TcpPseudoHeader, sizeof(TCPv4_PSEUDO_HEADER), \
+ 0)) == DH2N(0x0000FFFF))
-/* EOF */
+#endif /* __CHECKSUM_H */
reactos/drivers/net/tcpip/include
diff -u -r1.8 -r1.9
--- ip.h 2 Mar 2004 18:18:14 -0000 1.8
+++ ip.h 4 Mar 2004 20:45:38 -0000 1.9
@@ -49,8 +49,9 @@
IPv4_RAW_ADDRESS DstAddr; /* Destination Address */
} IPv4_HEADER, *PIPv4_HEADER;
-#define IPv4_FRAGOFS_MASK 0x1FFF
-#define IPv4_MF_MASK 0x2000
+#define IPv4_FRAGOFS_MASK 0x1FFF /* Fragment offset mask (host byte order) */
+#define IPv4_MF_MASK 0x2000 /* More fragments (host byte order) */
+#define IPv4_DF_MASK 0x4000 /* Don't fragment (host byte order) */
#define IPv4_MAX_HEADER_SIZE 60
/* Packet completion handler prototype */
@@ -60,7 +61,7 @@
NDIS_STATUS NdisStatus);
/* Structure for an IP packet */
-typedef struct IP_PACKET {
+typedef struct _IP_PACKET {
DEFINE_TAG
ULONG RefCount; /* Reference count for this object */
OBJECT_FREE_ROUTINE Free; /* Routine used to free resources for the object */
@@ -81,7 +82,7 @@
/* Packet context */
-typedef struct PACKET_CONTEXT {
+typedef struct _PACKET_CONTEXT {
PACKET_COMPLETION_ROUTINE Complete; /* Transport level completion handler */
PVOID Context; /* Context information for handler */
PACKET_COMPLETION_ROUTINE DLComplete; /* Data link level completion handler. Also
reactos/drivers/net/tcpip/include
diff -u -r1.4 -r1.5
--- tcp.h 25 Dec 2003 14:06:14 -0000 1.4
+++ tcp.h 4 Mar 2004 20:45:38 -0000 1.5
@@ -7,27 +7,26 @@
#ifndef __TCP_H
#define __TCP_H
-
/* TCPv4 header structure */
-typedef struct TCP_HEADER {
- USHORT SourcePort; /* Source port */
- USHORT DestPort; /* Destination port */
- USHORT SeqNum; /* Sequence number */
- USHORT AckNum; /* Acknowledgment number */
- UCHAR DataOfs; /* Data offset (leftmost 4 bits) */
- UCHAR Flags; /* Control bits (rightmost 6 bits) */
- USHORT Window; /* Maximum acceptable receive window */
- USHORT Checksum; /* Checksum of segment */
- USHORT Urgent; /* Pointer to urgent data */
-} __attribute__((packed)) TCP_HEADER, *PTCP_HEADER;
+typedef struct TCPv4_HEADER {
+ USHORT SourcePort; /* Source port */
+ USHORT DestinationPort; /* Destination port */
+ ULONG SequenceNumber; /* Sequence number */
+ ULONG AckNumber; /* Acknowledgement number */
+ UCHAR DataOffset; /* Data offset; 32-bit words (leftmost 4 bits) */
+ UCHAR Flags; /* Control bits (rightmost 6 bits) */
+ USHORT Window; /* Maximum acceptable receive window */
+ USHORT Checksum; /* Checksum of segment */
+ USHORT Urgent; /* Pointer to urgent data */
+} __attribute__((packed)) TCPv4_HEADER, *PTCPv4_HEADER;
/* TCPv4 header flags */
-#define TCP_URG 0x04
-#define TCP_ACK 0x08
-#define TCP_PSH 0x10
-#define TCP_RST 0x20
-#define TCP_SYN 0x40
-#define TCP_FIN 0x80
+#define TCP_URG 0x20
+#define TCP_ACK 0x10
+#define TCP_PSH 0x08
+#define TCP_RST 0x04
+#define TCP_SYN 0x02
+#define TCP_FIN 0x01
#define TCPOPT_END_OF_LIST 0x0
@@ -38,13 +37,13 @@
/* TCPv4 pseudo header */
-typedef struct TCP_PSEUDO_HEADER {
- ULONG SourceAddress; /* Source address */
- ULONG DestAddress; /* Destination address */
- UCHAR Zero; /* Reserved */
- UCHAR Protocol; /* Protocol */
- USHORT TCPLength; /* Size of TCP segment */
-} __attribute__((packed)) TCP_PSEUDO_HEADER, *PTCP_PSEUDO_HEADER;
+typedef struct TCPv4_PSEUDO_HEADER {
+ ULONG SourceAddress; /* Source address */
+ ULONG DestinationAddress; /* Destination address */
+ UCHAR Zero; /* Reserved */
+ UCHAR Protocol; /* Protocol */
+ USHORT TCPLength; /* Size of TCP segment */
+} __attribute__((packed)) TCPv4_PSEUDO_HEADER, *PTCPv4_PSEUDO_HEADER;
/* Retransmission timeout constants */
@@ -72,6 +71,18 @@
#define SRF_FIN TCP_FIN
+PTCP_SEGMENT TCPCreateSegment(
+ PIP_PACKET IPPacket,
+ ULONG SequenceNumber,
+ ULONG SegmentLength);
+
+VOID TCPFreeSegment(
+ PTCP_SEGMENT Segment);
+
+VOID TCPAddSegment(
+ PCONNECTION_ENDPOINT Connection,
+ PTCP_SEGMENT Segment);
+
inline NTSTATUS TCPBuildSendRequest(
PTCP_SEND_REQUEST *SendRequest,
PDATAGRAM_SEND_REQUEST *DGSendRequest,
@@ -113,5 +124,3 @@
VOID);
#endif /* __TCP_H */
-
-/* EOF */
reactos/drivers/net/tcpip/include
diff -u -r1.5 -r1.6
--- titypes.h 2 Feb 2004 21:02:48 -0000 1.5
+++ titypes.h 4 Mar 2004 20:45:38 -0000 1.6
@@ -266,6 +266,8 @@
PVOID Context; /* Pointer to context information */
PVOID ProtocolContext; /* Protocol specific context */
ULONG Flags; /* Protocol specific flags */
+ ULONG SequenceNumber; /* Sequence number (network byte order) */
+ ULONG AckNumber; /* Acknowledgement number (network byte order) */
} TCP_SEND_REQUEST, *PTCP_SEND_REQUEST;
#define InitializeTCPSendRequest( \
@@ -296,6 +298,15 @@
} CONNECTION_STATE, *PCONNECTION_STATE;
+/* Structure for an TCP segment */
+typedef struct _TCP_SEGMENT {
+ LIST_ENTRY ListEntry;
+ PIP_PACKET IPPacket; /* Pointer to IP packet */
+ ULONG SequenceNumber; /* Sequence number of first byte in segment */
+ ULONG Length; /* Number of bytes in segment */
+} TCP_SEGMENT, *PTCP_SEGMENT;
+
+
/* Transport connection context structure A.K.A. Transmission Control Block
(TCB) in TCP terminology. The FileObject->FsContext2 field holds a pointer
to this structure */
@@ -324,14 +335,21 @@
ULONG SendISS; /* Initial send sequence number */
/* Receive sequence variables */
- ULONG RecvNext; /* Sequence number of last data block received */
- ULONG RecvWindow; /* Maximum allowed number of octets in a segment */
- ULONG RecvUrgentPointer; /* Sequence number of start of urgent data */
- ULONG RecvIRS; /* Initial receive sequence number */
+ ULONG ReceiveNext; /* Sequence number of last data block received */
+ ULONG ReceiveWindow; /* Maximum allowed number of octets in a segment */
+ ULONG ReceiveUrgentPointer; /* Sequence number of start of urgent data */
+ ULONG ReceiveIRS; /* Initial receive sequence number */
/* Statistics for computing the retransmission timeout */
ULONG TimestampSend; /* Timestamp when sending a segment */
ULONG TimestampAck; /* Timestamp when receiving acknowledgment */
+
+ /* Requests */
+ PTDI_REQUEST ListenRequest; /* Queued listen request */
+
+ /* Queues */
+ LIST_ENTRY ReceivedSegments;
+
} CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT;
reactos/drivers/net/tcpip/network
diff -u -r1.6 -r1.7
--- icmp.c 4 Jul 2001 20:40:23 -0000 1.6
+++ icmp.c 4 Mar 2004 20:45:39 -0000 1.7
@@ -182,7 +182,7 @@
TI_DbgPrint(DEBUG_ICMP, ("Checksum (0x%X).\n", ICMPHeader->Checksum));
/* Checksum ICMP header and data */
- if (!CorrectChecksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize)) {
+ if (!IPv4CorrectChecksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize)) {
TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum.\n"));
/* Discard packet */
return;
reactos/drivers/net/tcpip/network
diff -u -r1.7 -r1.8
--- receive.c 10 Nov 2002 13:52:13 -0000 1.7
+++ receive.c 4 Mar 2004 20:45:39 -0000 1.8
@@ -552,7 +552,7 @@
}
/* Checksum IPv4 header */
- if (!CorrectChecksum(IPPacket->Header, IPPacket->HeaderSize)) {
+ if (!IPv4CorrectChecksum(IPPacket->Header, IPPacket->HeaderSize)) {
TI_DbgPrint(MIN_TRACE, ("Datagram received with bad checksum. Checksum field (0x%X)\n",
WN2H(((PIPv4_HEADER)IPPacket->Header)->Checksum)));
/* Discard packet */
reactos/drivers/net/tcpip/network
diff -u -r1.7 -r1.8
--- transmit.c 24 Sep 2002 15:10:35 -0000 1.7
+++ transmit.c 4 Mar 2004 20:45:39 -0000 1.8
@@ -104,13 +104,13 @@
IPPacket, NCE, PathMTU));
IFC = ExAllocatePool(NonPagedPool, sizeof(IPFRAGMENT_CONTEXT));
- if (!IFC)
+ if (IFC == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
/* We allocate a buffer for a PathMTU sized packet and reuse
it for all fragments */
Data = ExAllocatePool(NonPagedPool, MaxLLHeaderSize + PathMTU);
- if (!IFC->Header) {
+ if (Data == NULL) {
ExFreePool(IFC);
return STATUS_INSUFFICIENT_RESOURCES;
}
@@ -118,7 +118,7 @@
/* Allocate NDIS packet */
NdisAllocatePacket(&NdisStatus, &IFC->NdisPacket, GlobalPacketPool);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
- //ExFreePool(Data); // RobD - why are we trying to free this here?, not allocated yet!
+ ExFreePool(Data);
ExFreePool(IFC);
return STATUS_INSUFFICIENT_RESOURCES;
}
reactos/drivers/net/tcpip/tcpip
diff -u -r1.9 -r1.10
--- address.c 2 Mar 2004 18:18:14 -0000 1.9
+++ address.c 4 Mar 2004 20:45:39 -0000 1.10
@@ -289,7 +289,7 @@
/*
* FUNCTION: Build an IPv4 style address
* ARGUMENTS:
- * Address = Raw IPv4 address
+ * Address = Raw IPv4 address (network byte order)
* RETURNS:
* Pointer to IP address structure, NULL if there was not enough free
* non-paged memory
@@ -300,7 +300,7 @@
PIP_ADDRESS IPAddress;
IPAddress = ExAllocatePool(NonPagedPool, sizeof(IP_ADDRESS));
- if (IPAddress) {
+ if (IPAddress != NULL) {
IPAddress->RefCount = 1;
IPAddress->Type = IP_ADDRESS_V4;
IPAddress->Address.IPv4Address = Address;
@@ -312,6 +312,29 @@
/*
+ * FUNCTION: Clone an IP address
+ * ARGUMENTS:
+ * IPAddress = Pointer to IP address
+ * RETURNS:
+ * Pointer to new IP address structure, NULL if there was not enough free
+ * non-paged memory
+ */
+PIP_ADDRESS AddrCloneAddress(
+ PIP_ADDRESS Address)
+{
+ if (Address->Type == IP_ADDRESS_V4)
+ {
+ return AddrBuildIPv4(Address->Address.IPv4Address);
+ }
+ else
+ {
+ TI_DbgPrint(MIN_TRACE, ("Cannot clone IPv6 address.\n"));
+ return NULL;
+ }
+}
+
+
+/*
* FUNCTION: Locates and returns an address entry using IPv4 adress as argument
* ARGUMENTS:
* Address = Raw IPv4 address
reactos/drivers/net/tcpip/tcpip
diff -u -r1.2 -r1.3
--- checksum.c 2 Aug 2000 00:21:36 -0000 1.2
+++ checksum.c 4 Mar 2004 20:45:39 -0000 1.3
@@ -12,10 +12,22 @@
#include <checksum.h>
+ULONG ChecksumFold(
+ ULONG Sum)
+{
+ /* Fold 32-bit sum to 16 bits */
+ while (Sum >> 16)
+ {
+ Sum = (Sum & 0xFFFF) + (Sum >> 16);
+ }
+
+ return Sum;
+}
+
ULONG ChecksumCompute(
- PVOID Data,
- UINT Count,
- ULONG Seed)
+ PVOID Data,
+ UINT Count,
+ ULONG Seed)
/*
* FUNCTION: Calculate checksum of a buffer
* ARGUMENTS:
@@ -26,25 +38,20 @@
* Checksum of buffer
*/
{
- /* FIXME: This should be done in assembler */
+ register ULONG Sum = Seed;
- register ULONG Sum = Seed;
-
- while (Count > 1) {
- Sum += *(PUSHORT)Data;
- Count -= 2;
- (ULONG_PTR)Data += 2;
+ while (Count > 1)
+ {
+ Sum += *(PUSHORT)Data;
+ Count -= 2;
+ (ULONG_PTR)Data += 2;
}
- /* Add left-over byte, if any */
- if (Count > 0)
- Sum += *(PUCHAR)Data;
-
- /* Fold 32-bit sum to 16 bits */
- while (Sum >> 16)
- Sum = (Sum & 0xFFFF) + (Sum >> 16);
+ /* Add left-over byte, if any */
+ if (Count > 0)
+ {
+ Sum += *(PUCHAR)Data;
+ }
- return ~Sum;
+ return Sum;
}
-
-/* EOF */
reactos/drivers/net/tcpip/tcpip
diff -u -r1.8 -r1.9
--- dispatch.c 2 Mar 2004 18:18:14 -0000 1.8
+++ dispatch.c 4 Mar 2004 20:45:39 -0000 1.9
@@ -529,8 +529,9 @@
PTDI_REQUEST_KERNEL Parameters;
PTRANSPORT_CONTEXT TranContext;
PIO_STACK_LOCATION IrpSp;
- TDI_REQUEST Request;
+ PTDI_REQUEST Request;
NTSTATUS Status;
+ KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@@ -539,28 +540,51 @@
/* Get associated connection endpoint file object. Quit if none exists */
TranContext = IrpSp->FileObject->FsContext;
- if (!TranContext) {
- TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
- return STATUS_INVALID_CONNECTION;
- }
+ if (TranContext == NULL)
+ {
+ TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
+ return STATUS_INVALID_CONNECTION;
+ }
Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
- if (!Connection) {
- TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
- return STATUS_INVALID_CONNECTION;
- }
+ if (Connection == NULL)
+ {
+ TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
+ return STATUS_INVALID_CONNECTION;
+ }
Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
- /* Initialize a connect request */
- Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
- Request.RequestNotifyObject = DispDataRequestComplete;
- Request.RequestContext = Irp;
-
- Status = TCPListen(
- &Request,
- Parameters->RequestConnectionInformation,
- Parameters->ReturnConnectionInformation);
+ /* Initialize a listen request */
+ Request = (PTDI_REQUEST) ExAllocatePool(NonPagedPool, sizeof(TDI_REQUEST));
+ if (Request == NULL)
+ {
+ return STATUS_NO_MEMORY;
+ }
+
+ Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
+ if (NT_SUCCESS(Status))
+ {
+ Request->Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
+ Request->RequestNotifyObject = DispDataRequestComplete;
+ Request->RequestContext = Irp;
+
+ Status = TCPListen(
+ Request,
+ Parameters->RequestConnectionInformation,
+ Parameters->ReturnConnectionInformation);
+ if (Status != STATUS_PENDING)
+ {
+ IoAcquireCancelSpinLock(&OldIrql);
+ IoSetCancelRoutine(Irp, NULL);
+ IoReleaseCancelSpinLock(OldIrql);
+ }
+ }
+
+ if (Status != STATUS_PENDING)
+ {
+ ExFreePool(Request);
+ }
return Status;
}
reactos/drivers/net/tcpip/tcpip
diff -u -r1.10 -r1.11
--- fileobjs.c 7 Feb 2004 12:03:11 -0000 1.10
+++ fileobjs.c 4 Mar 2004 20:45:39 -0000 1.11
@@ -296,13 +296,13 @@
switch (Protocol) {
case IPPROTO_TCP:
/* FIXME: If specified port is 0, a port is chosen dynamically */
- AddrFile->Port = ((PTDI_ADDRESS_IP)Address->Address)->sin_port;
+ AddrFile->Port = Address->Address[0].Address[0].sin_port;
AddrFile->Send = TCPSendDatagram;
break;
case IPPROTO_UDP:
/* FIXME: If specified port is 0, a port is chosen dynamically */
- AddrFile->Port = ((PTDI_ADDRESS_IP)Address->Address)->sin_port;
+ AddrFile->Port = Address->Address[0].Address[0].sin_port;
AddrFile->Send = UDPSendDatagram;
break;
@@ -449,6 +449,9 @@
/* Save client context pointer */
Connection->ClientContext = ClientContext;
+ /* Initialize receive queue */
+ InitializeListHead(&Connection->ReceivedSegments);
+
/* Return connection endpoint file object */
Request->Handle.ConnectionContext = Connection;
reactos/drivers/net/tcpip/tcpip
diff -u -r1.10 -r1.11
--- routines.c 2 Mar 2004 18:18:14 -0000 1.10
+++ routines.c 4 Mar 2004 20:45:39 -0000 1.11
@@ -480,6 +480,33 @@
#ifdef DBG
+static VOID DisplayIPHeader(
+ PUCHAR Header,
+ UINT Length)
+{
+ /* FIXME: IPv4 only */
+ PIPv4_HEADER IPHeader = (PIPv4_HEADER)Header;
+
+ DbgPrint("IPv4 header:\n");
+ DbgPrint("VerIHL: 0x%x (version 0x%x, length %d 32-bit words)\n",
+ IPHeader->VerIHL, (IPHeader->VerIHL & 0xF0) >> 4, IPHeader->VerIHL & 0x0F);
+ DbgPrint(" Tos: %d\n", IPHeader->Tos);
+ DbgPrint(" TotalLength: %d\n", WN2H(IPHeader->TotalLength));
+ DbgPrint(" Id: %d\n", WN2H(IPHeader->Id));
+ DbgPrint(" FlagsFragOfs: 0x%x (offset 0x%x)\n", WN2H(IPHeader->FlagsFragOfs), WN2H(IPHeader->FlagsFragOfs) & IPv4_FRAGOFS_MASK);
+ if ((WN2H(IPHeader->FlagsFragOfs) & IPv4_DF_MASK) > 0) DbgPrint(" IPv4_DF - Don't fragment\n");
+ if ((WN2H(IPHeader->FlagsFragOfs) & IPv4_MF_MASK) > 0) DbgPrint(" IPv4_MF - More fragments\n");
+ DbgPrint(" Ttl: %d\n", IPHeader->Ttl);
+ DbgPrint(" Protocol: %d\n", IPHeader->Protocol);
+ DbgPrint(" Checksum: 0x%x\n", WN2H(IPHeader->Checksum));
+ DbgPrint(" SrcAddr: %d.%d.%d.%d\n",
+ ((IPHeader->SrcAddr >> 0) & 0xFF), ((IPHeader->SrcAddr >> 8) & 0xFF),
+ ((IPHeader->SrcAddr >> 16) & 0xFF), ((IPHeader->SrcAddr >> 24) & 0xFF));
+ DbgPrint(" DstAddr: %d.%d.%d.%d\n",
+ ((IPHeader->DstAddr >> 0) & 0xFF), ((IPHeader->DstAddr >> 8) & 0xFF),
+ ((IPHeader->DstAddr >> 16) & 0xFF), ((IPHeader->DstAddr >> 24) & 0xFF));
+}
+
VOID DisplayIPPacket(
PIP_PACKET IPPacket)
{
@@ -488,6 +515,7 @@
UINT Length;
PNDIS_BUFFER Buffer;
PNDIS_BUFFER NextBuffer;
+ PUCHAR CharBuffer;
if ((DebugTraceLevel & (DEBUG_BUFFER | DEBUG_IP)) != (DEBUG_BUFFER | DEBUG_IP)) {
return;
@@ -528,6 +556,19 @@
}
DbgPrint("\n");
}
+
+ if (IPPacket->NdisPacket) {
+ NdisQueryPacket(IPPacket->NdisPacket, NULL, NULL, NULL, &Length);
+ Length -= MaxLLHeaderSize;
+ CharBuffer = ExAllocatePool(NonPagedPool, Length);
+ Length = CopyPacketToBuffer(CharBuffer, IPPacket->NdisPacket, MaxLLHeaderSize, Length);
+ DisplayIPHeader(CharBuffer, Length);
+ ExFreePool(CharBuffer);
+ } else {
+ CharBuffer = IPPacket->Header;
+ Length = IPPacket->ContigSize;
+ DisplayIPHeader(CharBuffer, Length);
+ }
}
@@ -537,32 +578,31 @@
{
/* FIXME: IPv4 only */
PIPv4_HEADER IPHeader = (PIPv4_HEADER)Header;
- PTCP_HEADER TCPHeader;
+ PTCPv4_HEADER TCPHeader;
if (IPHeader->Protocol != IPPROTO_TCP) {
DbgPrint("This is not a TCP datagram. Protocol is %d\n", IPHeader->Protocol);
return;
}
- DbgPrint("VerIHL: 0x%x\n", IPHeader->VerIHL);
- TCPHeader = (PTCP_HEADER)((PUCHAR)IPHeader + (IPHeader->VerIHL & 0x0F) * 4);
+ TCPHeader = (PTCPv4_HEADER)((PUCHAR)IPHeader + (IPHeader->VerIHL & 0x0F) * 4);
DbgPrint("TCP header:\n");
DbgPrint(" SourcePort: %d\n", WN2H(TCPHeader->SourcePort));
- DbgPrint(" DestPort: %d\n", WN2H(TCPHeader->DestPort));
- DbgPrint(" SeqNum: %d\n", WN2H(TCPHeader->SeqNum));
- DbgPrint(" AckNum: %d\n", WN2H(TCPHeader->AckNum));
- DbgPrint(" DataOfs: %d (%d)\n", TCPHeader->DataOfs, TCPHeader->DataOfs & 0x0F);
+ DbgPrint(" DestinationPort: %d\n", WN2H(TCPHeader->DestinationPort));
+ DbgPrint(" SequenceNumber: 0x%x\n", DN2H(TCPHeader->SequenceNumber));
+ DbgPrint(" AckNumber: 0x%x\n", DN2H(TCPHeader->AckNumber));
+ DbgPrint(" DataOffset: 0x%x (0x%x) 32-bit words\n", TCPHeader->DataOffset, TCPHeader->DataOffset >> 4);
DbgPrint(" Flags: 0x%x (0x%x)\n", TCPHeader->Flags, TCPHeader->Flags & 0x3F);
if ((TCPHeader->Flags & TCP_URG) > 0) DbgPrint(" TCP_URG - Urgent Pointer field significant\n");
- if ((TCPHeader->Flags & TCP_ACK) > 0) DbgPrint(" TCP_ACK - Acknowledgment field significant\n");
+ if ((TCPHeader->Flags & TCP_ACK) > 0) DbgPrint(" TCP_ACK - Acknowledgement field significant\n");
if ((TCPHeader->Flags & TCP_PSH) > 0) DbgPrint(" TCP_PSH - Push Function\n");
if ((TCPHeader->Flags & TCP_RST) > 0) DbgPrint(" TCP_RST - Reset the connection\n");
if ((TCPHeader->Flags & TCP_SYN) > 0) DbgPrint(" TCP_SYN - Synchronize sequence numbers\n");
if ((TCPHeader->Flags & TCP_FIN) > 0) DbgPrint(" TCP_FIN - No more data from sender\n");
- DbgPrint(" Window: %d\n", WN2H(TCPHeader->Window));
- DbgPrint(" Checksum: %d\n", WN2H(TCPHeader->Checksum));
- DbgPrint(" Urgent: %d\n", WN2H(TCPHeader->Urgent));
+ DbgPrint(" Window: 0x%x\n", WN2H(TCPHeader->Window));
+ DbgPrint(" Checksum: 0x%x\n", WN2H(TCPHeader->Checksum));
+ DbgPrint(" Urgent: 0x%x\n", WN2H(TCPHeader->Urgent));
}
@@ -592,8 +632,9 @@
if (IPPacket->NdisPacket) {
NdisQueryPacket(IPPacket->NdisPacket, NULL, NULL, NULL, &Length);
+ Length -= MaxLLHeaderSize;
Buffer = ExAllocatePool(NonPagedPool, Length);
- Length = CopyPacketToBuffer(Buffer, IPPacket->NdisPacket, 0, Length);
+ Length = CopyPacketToBuffer(Buffer, IPPacket->NdisPacket, MaxLLHeaderSize, Length);
DisplayTCPHeader(Buffer, Length);
ExFreePool(Buffer);
} else {
reactos/drivers/net/tcpip/tcpip/i386
diff -N checksum.S
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ checksum.S 4 Mar 2004 20:45:39 -0000 1.1
@@ -0,0 +1,249 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IP/TCP/UDP checksumming routines
+ *
+ * Authors: Jorge Cwik, <jorge@laser.satlink.net>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Tom May, <ftom@netcom.com>
+ * Pentium Pro/II routines:
+ * Alexander Kjeldaas <astor@guardian.no>
+ * Finn Arne Gangstad <finnag@guardian.no>
+ * Lots of code moved from tcp.c and ip.c; see those files
+ * for more names.
+ *
+ * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ * handling.
+ * Andi Kleen, add zeroing on error
+ * converted to pure assembler
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+ */
+
+.text
+.align 4
+.globl _csum_partial
+
+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
+
+ /*
+ * Experiments with Ethernet and SLIP connections show that buff
+ * is aligned on either a 2-byte or 4-byte boundary. We get at
+ * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+ * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+ * alignment for the unrolled loop.
+ */
+_csum_partial:
+ pushl %esi
+ pushl %ebx
+ movl 20(%esp),%eax # Function arg: unsigned int sum
+ movl 16(%esp),%ecx # Function arg: int len
+ movl 12(%esp),%esi # Function arg: unsigned char *buff
+ testl $3, %esi # Check alignment.
+ jz 2f # Jump if alignment is ok.
+ testl $1, %esi # Check alignment.
+ jz 10f # Jump if alignment is boundary of 2bytes.
+
+ # buf is odd
+ dec %ecx
+ jl 8f
+ movzbl (%esi), %ebx
+ adcl %ebx, %eax
+ roll $8, %eax
+ inc %esi
+ testl $2, %esi
+ jz 2f
+10:
+ subl $2, %ecx # Alignment uses up two bytes.
+ jae 1f # Jump if we had at least two bytes.
+ addl $2, %ecx # ecx was < 2. Deal with it.
+ jmp 4f
+1: movw (%esi), %bx
+ addl $2, %esi
+ addw %bx, %ax
+ adcl $0, %eax
+2:
+ movl %ecx, %edx
+ shrl $5, %ecx
+ jz 2f
+ testl %esi, %esi
+1: movl (%esi), %ebx
+ adcl %ebx, %eax
+ movl 4(%esi), %ebx
+ adcl %ebx, %eax
+ movl 8(%esi), %ebx
+ adcl %ebx, %eax
+ movl 12(%esi), %ebx
+ adcl %ebx, %eax
+ movl 16(%esi), %ebx
+ adcl %ebx, %eax
+ movl 20(%esi), %ebx
+ adcl %ebx, %eax
+ movl 24(%esi), %ebx
+ adcl %ebx, %eax
+ movl 28(%esi), %ebx
+ adcl %ebx, %eax
+ lea 32(%esi), %esi
+ dec %ecx
+ jne 1b
+ adcl $0, %eax
+2: movl %edx, %ecx
+ andl $0x1c, %edx
+ je 4f
+ shrl $2, %edx # This clears CF
+3: adcl (%esi), %eax
+ lea 4(%esi), %esi
+ dec %edx
+ jne 3b
+ adcl $0, %eax
+4: andl $3, %ecx
+ jz 7f
+ cmpl $2, %ecx
+ jb 5f
+ movw (%esi),%cx
+ leal 2(%esi),%esi
+ je 6f
+ shll $16,%ecx
+5: movb (%esi),%cl
+6: addl %ecx,%eax
+ adcl $0, %eax
+7:
+ testl $1, 12(%esp)
+ jz 8f
+ roll $8, %eax
+8:
+ popl %ebx
+ popl %esi
+ ret
+
+#else
+
+/* Version for PentiumII/PPro */
+
+csum_partial:
+ pushl %esi
+ pushl %ebx
+ movl 20(%esp),%eax # Function arg: unsigned int sum
+ movl 16(%esp),%ecx # Function arg: int len
+ movl 12(%esp),%esi # Function arg: const unsigned char *buf
+
+ testl $3, %esi
+ jnz 25f
+10:
+ movl %ecx, %edx
+ movl %ecx, %ebx
+ andl $0x7c, %ebx
+ shrl $7, %ecx
+ addl %ebx,%esi
+ shrl $2, %ebx
+ negl %ebx
+ lea 45f(%ebx,%ebx,2), %ebx
+ testl %esi, %esi
+ jmp *%ebx
+
+ # Handle 2-byte-aligned regions
+20: addw (%esi), %ax
+ lea 2(%esi), %esi
+ adcl $0, %eax
+ jmp 10b
+25:
+ testl $1, %esi
+ jz 30f
+ # buf is odd
+ dec %ecx
+ jl 90f
+ movzbl (%esi), %ebx
+ addl %ebx, %eax
+ adcl $0, %eax
+ roll $8, %eax
+ inc %esi
+ testl $2, %esi
+ jz 10b
+
+30: subl $2, %ecx
+ ja 20b
+ je 32f
+ addl $2, %ecx
+ jz 80f
+ movzbl (%esi),%ebx # csumming 1 byte, 2-aligned
+ addl %ebx, %eax
+ adcl $0, %eax
+ jmp 80f
+32:
+ addw (%esi), %ax # csumming 2 bytes, 2-aligned
+ adcl $0, %eax
+ jmp 80f
+
+40:
+ addl -128(%esi), %eax
+ adcl -124(%esi), %eax
+ adcl -120(%esi), %eax
+ adcl -116(%esi), %eax
+ adcl -112(%esi), %eax
+ adcl -108(%esi), %eax
+ adcl -104(%esi), %eax
+ adcl -100(%esi), %eax
+ adcl -96(%esi), %eax
+ adcl -92(%esi), %eax
+ adcl -88(%esi), %eax
+ adcl -84(%esi), %eax
+ adcl -80(%esi), %eax
+ adcl -76(%esi), %eax
+ adcl -72(%esi), %eax
+ adcl -68(%esi), %eax
+ adcl -64(%esi), %eax
+ adcl -60(%esi), %eax
+ adcl -56(%esi), %eax
+ adcl -52(%esi), %eax
+ adcl -48(%esi), %eax
+ adcl -44(%esi), %eax
+ adcl -40(%esi), %eax
+ adcl -36(%esi), %eax
+ adcl -32(%esi), %eax
+ adcl -28(%esi), %eax
+ adcl -24(%esi), %eax
+ adcl -20(%esi), %eax
+ adcl -16(%esi), %eax
+ adcl -12(%esi), %eax
+ adcl -8(%esi), %eax
+ adcl -4(%esi), %eax
+45:
+ lea 128(%esi), %esi
+ adcl $0, %eax
+ dec %ecx
+ jge 40b
+ movl %edx, %ecx
+50: andl $3, %ecx
+ jz 80f
+
+ # Handle the last 1-3 bytes without jumping
+ notl %ecx # 1->2, 2->1, 3->0, higher bits are masked
+ movl $0xffffff,%ebx # by the shll and shrl instructions
+ shll $3,%ecx
+ shrl %cl,%ebx
+ andl -128(%esi),%ebx # esi is 4-aligned so should be ok
+ addl %ebx,%eax
+ adcl $0,%eax
+80:
+ testl $1, 12(%esp)
+ jz 90f
+ roll $8, %eax
+90:
+ popl %ebx
+ popl %esi
+ ret
+
+#endif
reactos/drivers/net/tcpip/transport/tcp
diff -u -r1.8 -r1.9
--- tcp.c 10 Feb 2004 17:12:41 -0000 1.8
+++ tcp.c 4 Mar 2004 20:45:39 -0000 1.9
@@ -12,36 +12,159 @@
#include <pool.h>
#include <address.h>
#include <datagram.h>
+#include <checksum.h>
#include <routines.h>
static BOOLEAN TCPInitialized = FALSE;
+static LONG IPIdentification = 0;
+static NPAGED_LOOKASIDE_LIST TCPSegmentList;
+
+
+PTCP_SEGMENT TCPCreateSegment(
+ PIP_PACKET IPPacket,
+ ULONG SequenceNumber,
+ ULONG SegmentLength)
+/*
+ * FUNCTION: Creates a TCP segment object
+ * ARGUMENTS:
+ * IPPacket = Pointer to IP packet containing segment data
+ * SequenceNumber = Sequence number of first byte in the segment
+ * SegmentLength = Number of bytes in the segment
+ * RETURNS:
+ * Pointer to the created TCP segment. NULL if there was not enough free resources.
+ */
+{
+ PTCP_SEGMENT Segment;
+
+ ASSERT(IPPacket);
+
+ Segment = ExAllocateFromNPagedLookasideList(&TCPSegmentList);
+ if (Segment == NULL)
+ return NULL;
+
+ Segment->IPPacket = IPPacket;
+ Segment->SequenceNumber = SequenceNumber;
+ Segment->Length = SegmentLength;
+
+ TI_DbgPrint(DEBUG_TCP, ("Created TCP segment (SequenceNumber %d, Length %d)\n",
+ Segment->SequenceNumber, Segment->Length));
+
+ return Segment;
+}
+
+
+VOID TCPFreeSegment(
+ PTCP_SEGMENT Segment)
+/*
+ * FUNCTION: Frees a TCP segment object
+ * ARGUMENTS:
+ * Segment = Pointer to an TCP segment structure
+ */
+{
+ ASSERT(Segment);
+
+ ExFreeToNPagedLookasideList(&TCPSegmentList, Segment);
+}
+
+
+VOID TCPAddSegment(
+ PCONNECTION_ENDPOINT Connection,
+ PTCP_SEGMENT Segment)
+/*
+ * FUNCTION: Adds a TCP segment object to the receive queue of a connection
+ * ARGUMENTS:
+ * Connection = Pointer to connection endpoint
+ * Segment = Pointer to TCP segment object
+ * RETURNS:
+ * Nothing.
+ */
+{
+ PLIST_ENTRY CurrentEntry;
+ PLIST_ENTRY NextEntry;
+ PTCP_SEGMENT Current;
+
+ ASSERT(Connection);
+ ASSERT(Segment);
+
+ /* FIXME: Handle sequence number wraparound */
+
+ /* If all segments arrive in-order then all segments will be put last in the
+ receive queue when they arrive */
+
+ if (IsListEmpty(&Connection->ReceivedSegments))
+ {
+ /* This is the first segment received since the connection was created
+ or since all data is delivered to the client */
+ InsertTailList(&Connection->ReceivedSegments, &Segment->ListEntry);
+ return;
+ }
+
+ CurrentEntry = Connection->ReceivedSegments.Blink;
+ Current = CONTAINING_RECORD(CurrentEntry, TCP_SEGMENT, ListEntry);
+ if (Segment->SequenceNumber >= Current->SequenceNumber)
+ {
+ /* This segment has the highest sequence number yet received since the
+ connection was created */
+ InsertTailList(&Connection->ReceivedSegments, &Segment->ListEntry);
+ return;
+ }
+
+
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Cannot handle segments that arrive out-of-order.\n"));
+
+#if 0
+ do
+ {
+ if (SequenceNumber + Length...)
+ {
+ }
+
+ CurrentEntry = CurrentEntry->Blink;
+ Current = CONTAINING_RECORD(CurrentEntry, TCP_SEGMENT, ListEntry);
+ }
+ while (CurrentEntry != &Connection->ReceivedSegments);
+#endif
+}
NTSTATUS TCPiAddHeaderIPv4(
PDATAGRAM_SEND_REQUEST SendRequest,
+ PCONNECTION_ENDPOINT Connection,
PIP_ADDRESS LocalAddress,
USHORT LocalPort,
- PIP_PACKET IPPacket)
+ PIP_PACKET IPPacket,
+ PTCPv4_HEADER *pTcpHeader,
+ PULONG pTcpHeaderLength)
/*
* FUNCTION: Adds an IPv4 and TCP header to an IP packet
* ARGUMENTS:
- * SendRequest = Pointer to send request
- * LocalAddress = Pointer to our local address
- * LocalPort = The port we send this segment from
- * IPPacket = Pointer to IP packet
+ * SendRequest = Pointer to send request
+ * Connection = Pointer to connection endpoint
+ * LocalAddress = Pointer to our local address
+ * LocalPort = The port we send this segment from
+ * IPPacket = Pointer to IP packet
+ * TcpHeader = Address of pointer to TCPv4 header (out)
+ * pTcpHeaderLength = Address of buffer for length of TCP header
* RETURNS:
* Status of operation
*/
{
PIPv4_HEADER IPHeader;
- PTCP_HEADER TCPHeader;
+ PTCPv4_HEADER TCPHeader;
PVOID Header;
ULONG BufferSize;
NDIS_STATUS NdisStatus;
PNDIS_BUFFER HeaderBuffer;
+ PTCP_SEND_REQUEST TcpSendRequest = (PTCP_SEND_REQUEST)SendRequest->Context;
+
+ ASSERT(SendRequest);
+ ASSERT(Connection);
+ ASSERT(LocalAddress);
+ ASSERT(IPPacket);
+ ASSERT(pTcpHeader);
- BufferSize = MaxLLHeaderSize + sizeof(IPv4_HEADER) + sizeof(TCP_HEADER);
+ BufferSize = MaxLLHeaderSize + sizeof(IPv4_HEADER) + sizeof(TCPv4_HEADER);
Header = ExAllocatePool(NonPagedPool, BufferSize);
if (!Header)
return STATUS_INSUFFICIENT_RESOURCES;
@@ -61,7 +184,8 @@
/* Chain header at front of NDIS packet */
NdisChainBufferAtFront(IPPacket->NdisPacket, HeaderBuffer);
-
+
+ IPPacket->ContigSize = BufferSize;
IPPacket->Header = (PVOID)((ULONG_PTR)Header + MaxLLHeaderSize);
IPPacket->HeaderSize = 20;
@@ -74,7 +198,7 @@
/* Length of header and data */
IPHeader->TotalLength = WH2N((USHORT)IPPacket->TotalSize);
/* Identification */
- IPHeader->Id = 0;
+ IPHeader->Id = WH2N((USHORT)InterlockedIncrement(&IPIdentification));
/* One fragment at offset 0 */
IPHeader->FlagsFragOfs = 0;
/* Time-to-Live is 128 */
@@ -89,18 +213,23 @@
IPHeader->DstAddr = SendRequest->RemoteAddress->Address.IPv4Address;
/* Build TCP header */
- TCPHeader = (PTCP_HEADER)((ULONG_PTR)IPHeader + sizeof(IPv4_HEADER));
+ TCPHeader = (PTCPv4_HEADER)((ULONG_PTR)IPHeader + sizeof(IPv4_HEADER));
/* Port values are already big-endian values */
- TCPHeader->SourcePort = LocalPort;
- TCPHeader->DestPort = SendRequest->RemotePort;
- TCPHeader->SeqNum = 0;
- TCPHeader->AckNum = 0;
- TCPHeader->DataOfs = 0;
- TCPHeader->Flags = SendRequest->Flags;
- TCPHeader->Window = 0;
+ TCPHeader->SourcePort = LocalPort;
+ TCPHeader->DestinationPort = SendRequest->RemotePort;
+ /* TcpSendRequest->SequenceNumber is already a big-endian value */
+ TCPHeader->SequenceNumber = TcpSendRequest->SequenceNumber;
+ /* TcpSendRequest->AckNumber is already a big-endian value */
+ TCPHeader->AckNumber = ((SendRequest->Flags & SRF_ACK) > 0) ? TcpSendRequest->AckNumber : 0;
+ TCPHeader->DataOffset = (sizeof(TCPv4_HEADER) / 4) << 4;
+ TCPHeader->Flags = SendRequest->Flags;
+ TCPHeader->Window = 0;
/* FIXME: Calculate TCP checksum and put it in TCP header */
- TCPHeader->Checksum = 0;
- TCPHeader->Urgent = 0;
+ TCPHeader->Checksum = 0;
+ TCPHeader->Urgent = 0;
+
+ *pTcpHeader = TCPHeader;
+ *pTcpHeaderLength = sizeof(TCPv4_HEADER);
return STATUS_SUCCESS;
}
@@ -121,7 +250,7 @@
* RETURNS:
* Status of operation
* NOTES:
- * The ProcotolContext field in the send request structure (pointed to
+ * The Context field in the send request structure (pointed to
* by the Context field) contains a pointer to the CONNECTION_ENDPOINT
* structure for the connection
*/
@@ -129,19 +258,32 @@
NTSTATUS Status;
PIP_PACKET Packet;
NDIS_STATUS NdisStatus;
- PDATAGRAM_SEND_REQUEST SendRequest = (PDATAGRAM_SEND_REQUEST)Context;
+ PDATAGRAM_SEND_REQUEST SendRequest;
+ PCONNECTION_ENDPOINT Connection;
+ ULONG Checksum;
+ TCPv4_PSEUDO_HEADER TcpPseudoHeader;
+ PTCPv4_HEADER TcpHeader;
+ ULONG TcpHeaderLength;
+
+ ASSERT(LocalAddress);
+ ASSERT(IPPacket);
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
+ SendRequest = (PDATAGRAM_SEND_REQUEST)Context;
+ ASSERT(SendRequest);
+ Connection = (PCONNECTION_ENDPOINT)SendRequest->Context;
+ ASSERT(Connection);
+
/* Prepare packet */
- /* FIXME: Assumes IPv4*/
+ /* FIXME: Assumes IPv4 */
Packet = IPCreatePacket(IP_ADDRESS_V4);
- if (!Packet)
+ if (Packet == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
Packet->TotalSize = sizeof(IPv4_HEADER) +
- sizeof(TCP_HEADER) +
+ sizeof(TCPv4_HEADER) +
SendRequest->BufferSize;
/* Allocate NDIS packet */
@@ -153,7 +295,8 @@
switch (SendRequest->RemoteAddress->Type) {
case IP_ADDRESS_V4:
- Status = TCPiAddHeaderIPv4(SendRequest, LocalAddress, LocalPort, Packet);
+ Status = TCPiAddHeaderIPv4(SendRequest, Connection, LocalAddress,
+ LocalPort, Packet, &TcpHeader, &TcpHeaderLength);
break;
case IP_ADDRESS_V6:
/* FIXME: Support IPv6 */
@@ -169,10 +312,40 @@
return Status;
}
- /* Chain data after header */
- NdisChainBufferAtBack(Packet->NdisPacket, SendRequest->Buffer);
+ /* Build pseudo TCP header which is used to prevent misrouted segments */
+ TcpPseudoHeader.SourceAddress = LocalAddress->Address.IPv4Address;
+ TcpPseudoHeader.DestinationAddress = SendRequest->RemoteAddress->Address.IPv4Address;
+ TcpPseudoHeader.Zero = 0;
+ TcpPseudoHeader.Protocol = IPPROTO_TCP;
+ /* Length of TCP header and segment data */
+ TcpPseudoHeader.TCPLength = WH2N(TcpHeaderLength + SendRequest->BufferSize);
+ Checksum = TCPv4Checksum((PUCHAR)&TcpPseudoHeader, sizeof(TCPv4_PSEUDO_HEADER), 0);
+
+ /* Add checksum for TCP header */
+ Checksum = TCPv4Checksum((PUCHAR)TcpHeader, TcpHeaderLength, ~Checksum);
+
+ /* Chain data after header if it exists */
+ if (SendRequest->Buffer != NULL)
+ {
+ PVOID Data;
+ UINT Size;
+ PNDIS_BUFFER NdisBuffer = SendRequest->Buffer;
+ NdisChainBufferAtBack(Packet->NdisPacket, NdisBuffer);
+ /* Add checksum for segment data */
+ /* FIXME: Verify that there is no problem for chained buffers with an odd length */
+ while (NdisBuffer != NULL)
+ {
+ NdisQueryBuffer(NdisBuffer, &Data, &Size);
+ DbgPrint("Checksum7:(%d bytes)\n", Size);
+ Checksum = TCPv4Checksum(Data, Size, ~Checksum);
+ NdisGetNextBuffer(NdisBuffer, &NdisBuffer);
+ }
+ }
- //DISPLAY_IP_PACKET(Packet);
+ TcpHeader->Checksum = Checksum;
+ DbgPrint("Checksum8: (0x%x)\n", Checksum);
+
+ DISPLAY_TCP_PACKET(Packet);
*IPPacket = Packet;
@@ -196,14 +369,19 @@
PVOID CompleteContext;
PTCP_SEND_REQUEST SendRequest = (PTCP_SEND_REQUEST)Context;
+ TI_DbgPrint(MAX_TRACE, ("Called.\n"));
+
Complete = SendRequest->Complete;
CompleteContext = SendRequest->Context;
ExFreePool(SendRequest);
- TI_DbgPrint(MAX_TRACE, ("Calling completion routine.\n"));
+ if (Complete != NULL)
+ {
+ TI_DbgPrint(MAX_TRACE, ("Calling completion routine.\n"));
- /* Call upper level completion routine */
- (*Complete)(CompleteContext, Status, Count);
+ /* Call upper level completion routine */
+ (*Complete)(CompleteContext, Status, Count);
+ }
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
}
@@ -237,7 +415,7 @@
* Connection = Connection endpoint
* Complete = Completion routine
* Context = Pointer to context information
- * Buffer = Pointer to NDIS buffer to send
+ * Buffer = Pointer to NDIS buffer to send (optional)
* BufferSize = Size of Buffer
* Flags = Protocol specific flags
* RETURNS:
@@ -247,6 +425,9 @@
PDATAGRAM_SEND_REQUEST DGSendReq;
NTSTATUS Status;
+ ASSERT(SendRequest);
+ ASSERT(Connection);
+
Status = BuildTCPSendRequest(
SendRequest,
Complete,
@@ -261,7 +442,8 @@
Connection->RemotePort, /* Port of remote peer */
Buffer, /* Buffer */
BufferSize, /* Size of buffer */
- TCPiSendRequestComplete, /* Completion function */
+ (DATAGRAM_COMPLETION_ROUTINE)
+ TCPiSendRequestComplete, /* Completion function */
*SendRequest, /* Context for completion function */
TCPiBuildPacket, /* Packet build function */
Flags); /* Protocol specific flags */
@@ -288,9 +470,9 @@
* FUNCTION: Allocates and intializes a TCP send request
* ARGUMENTS:
* Connection = Connection endpoint
- * Complete = Completion routine
+ * Complete = Completion routine (optional)
* Context = Pointer to context information
- * Buffer = Pointer to NDIS buffer to send
+ * Buffer = Pointer to NDIS buffer to send (optional)
* BufferSize = Size of Buffer
* Flags = Protocol specific flags
* RETURNS:
@@ -301,6 +483,67 @@
PTCP_SEND_REQUEST TCPSendRequest;
NTSTATUS Status;
+ ASSERT(Connection);
+
+ TI_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ Status = TCPBuildSendRequest(
+ &TCPSendRequest,
+ &DGSendRequest,
+ Connection, /* Connection endpoint */
+ Complete, /* Completion routine */
+ Context, /* Completion routine context */
+ Buffer, /* Buffer */
+ BufferSize, /* Size of buffer */
+ Flags); /* Protocol specific flags */
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ Status = DGTransmit(
+ Connection->AddressFile,
+ DGSendRequest);
+ if (!NT_SUCCESS(Status)) {
+ ExFreePool(DGSendRequest);
+ ExFreePool(TCPSendRequest);
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+inline NTSTATUS TCPBuildAndTransmitSendRequest2(
+ PCONNECTION_ENDPOINT Connection,
+ DATAGRAM_COMPLETION_ROUTINE Complete,
+ PVOID Context,
+ PNDIS_BUFFER Buffer,
+ DWORD BufferSize,
+ ULONG Flags,
+ ULONG SequenceNumber,
+ ULONG AckNumber)
+/*
+ * FUNCTION: Allocates and intializes a TCP send request
+ * ARGUMENTS:
+ * Connection = Connection endpoint
+ * Complete = Completion routine (optional)
+ * Context = Pointer to context information
+ * Buffer = Pointer to NDIS buffer to send
+ * BufferSize = Size of Buffer
+ * Flags = Protocol specific flags
+ * SequenceNumber = Sequence number (host byte order)
+ * AckNumber = Acknowledgement number (host byte order)
+ * RETURNS:
+ * Status of operation
+ */
+{
+ PDATAGRAM_SEND_REQUEST DGSendRequest;
+ PTCP_SEND_REQUEST TCPSendRequest;
+ NTSTATUS Status;
+
+ ASSERT(Connection);
+
+ TI_DbgPrint(MAX_TRACE, ("Called.\n"));
+
Status = TCPBuildSendRequest(
&TCPSendRequest,
&DGSendRequest,
@@ -313,6 +556,10 @@
if (!NT_SUCCESS(Status))
return Status;
+ /* Set extra information and convert to network byte order if necessary */
+ TCPSendRequest->SequenceNumber = DH2N(SequenceNumber);
+ TCPSendRequest->AckNumber = DH2N(AckNumber);
+
Status = DGTransmit(
Connection->AddressFile,
DGSendRequest);
@@ -335,7 +582,7 @@
* ARGUMENTS:
* Request = Pointer to TDI request
* ConnInfo = Pointer to connection information
- * ReturnInfo = Pointer to structure for return information
+ * ReturnInfo = Pointer to structure for return information (optional)
* RETURNS:
* Status of operation
* NOTES:
@@ -353,6 +600,9 @@
PVOID DataBuffer;
ULONG Size;
+ ASSERT(Request);
+ ASSERT(ConnInfo);
+
TI_DbgPrint(MID_TRACE, ("Called.\n"));
Connection = Request->Handle.ConnectionContext;
@@ -427,7 +677,7 @@
* ARGUMENTS:
* Request = Pointer to TDI request
* ConnInfo = Pointer to connection information
- * ReturnInfo = Pointer to structure for return information
+ * ReturnInfo = Pointer to structure for return information (optional)
* RETURNS:
* Status of operation
* NOTES:
@@ -441,6 +691,9 @@
NTSTATUS Status;
KIRQL OldIrql;
+ ASSERT(Request);
+ ASSERT(ConnInfo);
+
TI_DbgPrint(MID_TRACE, ("Called.\n"));
Connection = Request->Handle.ConnectionContext;
@@ -453,8 +706,9 @@
return STATUS_UNSUCCESSFUL;
}
- Connection->LocalAddress = Connection->AddressFile->ADE->Address;
- Connection->LocalPort = Connection->AddressFile->Port;
+ Connection->LocalAddress = Connection->AddressFile->ADE->Address;
+ Connection->LocalPort = Connection->AddressFile->Port;
+ Connection->ListenRequest = Request;
TI_DbgPrint(MIN_TRACE, ("Connection->LocalAddress (%s).\n", A2S(Connection->LocalAddress)));
TI_DbgPrint(MIN_TRACE, ("Connection->LocalPort (%d).\n", Connection->LocalPort));
@@ -488,209 +742,535 @@
* Status of operation
*/
{
+ ASSERT(Request);
+ ASSERT(ConnInfo);
+ ASSERT(Buffer);
+
return STATUS_SUCCESS;
}
-static VOID TCPiReceive(
+static inline ULONG TCPiSelectISS(
+ PCONNECTION_ENDPOINT Connection)
+{
+ ASSERT(Connection);
+
+ TI_DbgPrint(MIN_TRACE, ("Select ISS.\n"));
+ return 0x10000;
+}
+
+
+static inline VOID TCPiReceiveListen(
PADDRESS_FILE AddrFile,
PIP_PACKET IPPacket,
- PTCP_HEADER TCPHeader)
+ PTCPv4_HEADER TCPHeader)
{
- register CONNECTION_STATE State;
+ ASSERT(AddrFile);
+ ASSERT(IPPacket);
+ ASSERT(TCPHeader);
- if (AddrFile->Connection == NULL || AddrFile->Connection->State == ctClosed)
+ /* FIXME: Protect AddrFile->Connection */
+
+ if ((TCPHeader->Flags & TCP_RST) > 0)
{
- if ((TCPHeader->Flags & TCP_RST) == 0)
- {
- /* FIXME: Send RST
- * If the ACK bit is off, sequence number zero is used,
- *
- * <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
- *
- * If the ACK bit is on,
- *
- * <SEQ=SEG.ACK><CTL=RST>
- */
- TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
- }
+ /* Discard */
+ TI_DbgPrint(DEBUG_TCP, ("Discard.\n"));
return;
}
- if (AddrFile->Connection->State == ctListen)
+ if ((TCPHeader->Flags & TCP_ACK) > 0)
{
- if ((TCPHeader->Flags & TCP_RST) > 0)
+ /* FIXME: Send RST (if no RST)
+ <SEQ=SEG.ACK><CTL=RST> */
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+ return;
+ }
+
+ if ((TCPHeader->Flags & TCP_SYN) > 0)
+ {
+ PCONNECTION_ENDPOINT Connection = AddrFile->Connection;
+ register UCHAR DelayedControls;
+ register NTSTATUS Status;
+
+ /* FIXME: If the SEG.PRC is greater than the TCB.PRC then if allowed by
+ the user and the system set TCB.PRC<-SEG.PRC, if not allowed
+ send a reset and return. */
+ if (FALSE)
{
- /* Discard */
+ /* FIXME: Send RST (if no RST)
+ * <SEQ=SEG.ACK><CTL=RST>
+ */
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
return;
}
- if ((TCPHeader->Flags & TCP_ACK) > 0)
+ /* Set RCV.NXT to SEG.SEQ+1, IRS is set to SEG.SEQ and any other
+ control or text should be queued for processing later. ISS
+ should be selected and a SYN segment sent of the form:
+
+ <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
+
+ SND.NXT is set to ISS+1 and SND.UNA to ISS. The connection
+ state should be changed to SYN-RECEIVED. Note that any other
+ incoming control or data (combined with SYN) will be processed
+ in the SYN-RECEIVED state, but processing of SYN and ACK should
+ not be repeated. If the listen was not fully specified (i.e.,
+ the foreign socket was not fully specified), then the
+ unspecified fields should be filled in now.
+ */
+ TI_DbgPrint(DEBUG_TCP, ("Go to ctSynReceived connection state.\n"));
+
+ Connection->RemotePort = TCPHeader->SourcePort;
+ /* FIXME: IPv4 only */
+ Connection->RemoteAddress = AddrCloneAddress(&IPPacket->SrcAddr);
+ if (Connection->RemoteAddress == NULL)
{
- /* FIXME: Send RST
- <SEQ=SEG.ACK><CTL=RST> */
+ /* FIXME: Send RST (if no RST)
+ * <SEQ=SEG.ACK><CTL=RST>
+ */
TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
return;
}
- if ((TCPHeader->Flags & TCP_SYN) > 0)
+ Connection->ReceiveNext = DN2H(TCPHeader->SequenceNumber) + 1;
+ Connection->ReceiveIRS = DN2H(TCPHeader->SequenceNumber);
+ Connection->State = ctSynReceived;
+
+ Connection->SendISS = TCPiSelectISS(Connection);
+ Connection->SendNext = Connection->SendISS + 1;
+ Connection->SendUnacknowledged = Connection->SendISS;
+
+ DelayedControls = TCPHeader->Flags & (~(TCP_SYN | TCP_ACK));
+ if (DelayedControls > 0)
{
- /* FIXME: If the SEG.PRC is greater than the TCB.PRC then if allowed by
- the user and the system set TCB.PRC<-SEG.PRC, if not allowed
- send a reset and return. */
- if (FALSE)
- {
- /* FIXME: Send RST
- * <SEQ=SEG.ACK><CTL=RST>
- */
- TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
- return;
- }
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Queue controls (0x%x) for later processing.\n", DelayedControls));
+ }
- /* Set RCV.NXT to SEG.SEQ+1, IRS is set to SEG.SEQ and any other
- control or text should be queued for processing later. ISS
- should be selected and a SYN segment sent of the form:
+ TI_DbgPrint(MIN_TRACE, ("IPPacket->HeaderSize: %d\n", IPPacket->HeaderSize));
+ TI_DbgPrint(MIN_TRACE, ("TCPHeader->DataOffset: %d\n", TCPHeader->DataOffset));
+ TI_DbgPrint(MIN_TRACE, ("IPPacket->TotalSize: %d\n", IPPacket->TotalSize));
- <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
+ if (IPPacket->HeaderSize + (TCPHeader->DataOffset & 0x0F) > IPPacket->TotalSize)
+ {
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Queue segment data (%d bytes) for later processing.\n",
+ (IPPacket->HeaderSize + (TCPHeader->DataOffset & 0x0F)) - IPPacket->TotalSize));
+ }
- SND.NXT is set to ISS+1 and SND.UNA to ISS. The connection
- state should be changed to SYN-RECEIVED. Note that any other
- incoming control or data (combined with SYN) will be processed
- in the SYN-RECEIVED state, but processing of SYN and ACK should
- not be repeated. If the listen was not fully specified (i.e.,
- the foreign socket was not fully specified), then the
- unspecified fields should be filled in now.
- */
- TI_DbgPrint(MIN_TRACE, ("FIXME: Go to ctSynReceived connection state.\n"));
+ /* Issue SYN/ACK segment */
+ Status = TCPBuildAndTransmitSendRequest2(
+ Connection, /* Connection endpoint */
+ NULL, /* Completion routine */
+ NULL, /* Completion routine context */
+ NULL, /* Buffer */
+ 0, /* Size of buffer */
+ SRF_SYN | SRF_ACK, /* Protocol specific flags */
+ Connection->SendISS, /* Sequence number */
+ Connection->ReceiveNext); /* Acknowledgement number */
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: Send RST (if no RST)
+ * <SEQ=SEG.ACK><CTL=RST>
+ */
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
return;
}
- /* Discard the segment as it is invalid */
+ ASSERT(Connection->ListenRequest != NULL);
+
+ TI_DbgPrint(DEBUG_TCP, ("Completing listen request at %p.\n", Connection->ListenRequest));
+
+ /* Complete the listen request */
+ (*((DATAGRAM_COMPLETION_ROUTINE)Connection->ListenRequest->RequestNotifyObject))(
+ Connection->ListenRequest->RequestContext,
+ STATUS_SUCCESS,
+ 0);
return;
}
- if (AddrFile->Connection->State == ctSynSent)
+ /* Discard the segment as it is invalid */
+ TI_DbgPrint(DEBUG_TCP, ("Discard.\n"));
+}
+
+
+static inline VOID TCPiReceiveSynSent(
+ PADDRESS_FILE AddrFile,
+ PIP_PACKET IPPacket,
+ PTCPv4_HEADER TCPHeader)
+{
+ ASSERT(AddrFile);
+ ASSERT(IPPacket);
+ ASSERT(TCPHeader);
+
+ /* FIXME: Protect AddrFile->Connection */
+
+ if ((TCPHeader->Flags & TCP_ACK) > 0)
+ {
+ /* FIXME: If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send a reset (unless
+ the RST bit is set, if so drop the segment and return)
+ <SEQ=SEG.ACK><CTL=RST> */
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+ return;
+ }
+
+ /* FIXME: If SND.UNA =< SEG.ACK =< SND.NXT then the ACK is acceptable. */
+
+ if ((TCPHeader->Flags & TCP_RST) > 0)
+ {
+ if (TRUE /* ACK is acceptable */)
+ {
+ AddrFile->Connection->State = ctClosed;
+ /* FIXME: Signal client */
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Signal client.\n"));
+ }
+ else
+ {
+ /* Discard segment */
+ TI_DbgPrint(DEBUG_TCP, ("Discard.\n"));
+ }
+ return;
+ }
+
+ /* FIXME: If the security/compartment in the segment does not exactly
+ match the security/compartment in the TCB */
+ if (FALSE)
{
if ((TCPHeader->Flags & TCP_ACK) > 0)
{
- /* FIXME: If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send a reset (unless
- the RST bit is set, if so drop the segment and return)
- <SEQ=SEG.ACK><CTL=RST> */
+ /* FIXME: Send RST (if no RST)
+ <SEQ=SEG.ACK><CTL=RST> */
TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
- return;
}
-
- /* FIXME: If SND.UNA =< SEG.ACK =< SND.NXT then the ACK is acceptable. */
-
- if ((TCPHeader->Flags & TCP_RST) > 0)
+ else
{
- if (TRUE /* ACK is acceptable */)
- {
- AddrFile->Connection->State = ctClosed;
- /* FIXME: Signal client */
- TI_DbgPrint(MIN_TRACE, ("FIXME: Signal client.\n"));
- }
- else
- {
- /* Discard segment */
- }
- return;
+ /* FIXME: Send RST (if no RST)
+ <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK> */
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
}
+ return;
+ }
- /* FIXME: If the security/compartment in the segment does not exactly
- match the security/compartment in the TCB */
+ if ((TCPHeader->Flags & TCP_ACK) > 0)
+ {
+ /* FIXME: If the precedence in the segment does not match the precedence in the TCB */
if (FALSE)
{
- if ((TCPHeader->Flags & TCP_ACK) > 0)
+ /* FIXME: Send RST (if no RST)
+ <SEQ=SEG.ACK><CTL=RST> */
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+ return;
+ }
+ else
+ {
+ /* FIXME: If the precedence in the segment is higher than the precedence
+ in the TCB then if allowed by the user and the system raise
+ the precedence in the TCB to that in the segment, if not
+ allowed to raise the prec then send a reset. */
+ if (FALSE)
{
- /* FIXME: Send RST
- <SEQ=SEG.ACK><CTL=RST> */
+ /* FIXME: Send RST (if no RST)
+ <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK> */
TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+ return;
}
else
{
- /* FIXME: Send RST
- <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK> */
- TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+ /* Continue */
}
- return;
}
+ TI_DbgPrint(MIN_TRACE, ("?.\n"));
+ return; /* ??? */
+ }
- if ((TCPHeader->Flags & TCP_ACK) > 0)
+ /* The ACK is ok, or there is no ACK, and it the segment did not contain a RST */
+
+ if ((TCPHeader->Flags & TCP_SYN) > 0)
+ {
+ /* FIXME: The security/compartment and precedence are acceptable */
+ if (TRUE)
{
- /* FIXME: If the precedence in the segment does not match the precedence in the TCB */
- if (FALSE)
+ PCONNECTION_ENDPOINT Connection = AddrFile->Connection;
+ register NTSTATUS Status;
+
+ /* FIXME: RCV.NXT is set to SEG.SEQ+1, IRS is set to
+ SEG.SEQ. SND.UNA should be advanced to equal SEG.ACK (if there
+ is an ACK), and any segments on the retransmission queue which
+ are thereby acknowledged should be removed.
+
+ If SND.UNA > ISS (our SYN has been ACKed), change the connection
+ state to ESTABLISHED, form an ACK segment
+
+ <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
+
+ Data or controls which were queued for
+ transmission may be included. If there are other controls or
+ text in the segment then continue processing at the sixth step
+ below where the URG bit is checked, otherwise return.
+
+ Otherwise enter SYN-RECEIVED, form a SYN,ACK segment
+
+ <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
+
+ and send it. If there are other controls or text in the
+ segment, queue them for processing after the ESTABLISHED state
+ has been reached, return. */
+
+ Connection->ReceiveNext = DN2H(TCPHeader->SequenceNumber) + 1;
+ Connection->ReceiveIRS = DN2H(TCPHeader->SequenceNumber);
+
+ if ((TCPHeader->Flags & TCP_ACK) > 0)
{
- /* FIXME: Send RST
- <SEQ=SEG.ACK><CTL=RST> */
- TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
- return;
+ /* FIXME: Remove any outstanding segments on the retransmission queue that is acknowledged by this */
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Maybe remove outstanding segments on the retransmission queue.\n"));
+ Connection->SendUnacknowledged = TCPHeader->AckNumber;
}
- else
+
+ if (Connection->SendUnacknowledged > Connection->SendISS)
{
- /* FIXME: If the precedence in the segment is higher than the precedence
- in the TCB then if allowed by the user and the system raise
- the precedence in the TCB to that in the segment, if not
- allowed to raise the prec then send a reset. */
- if (FALSE)
+ TI_DbgPrint(DEBUG_TCP, ("Go to ctEstablished connection state.\n"));
+ Connection->State = ctEstablished;
+
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Controls or segment data queued for transmission may be sent.\n"));
+
+ /* Issue ACK segment */
+ Status = TCPBuildAndTransmitSendRequest2(
+ Connection, /* Connection endpoint */
+ NULL, /* Completion routine */
+ NULL, /* Completion routine context */
+ NULL, /* Buffer */
+ 0, /* Size of buffer */
+ SRF_ACK, /* Protocol specific flags */
+ Connection->SendNext, /* Sequence number */
+ Connection->ReceiveNext); /* Acknowledgement number */
+ if (!NT_SUCCESS(Status))
{
- /* FIXME: Send RST
- <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK> */
+ /* FIXME: Send RST (if no RST)
+ * <SEQ=SEG.ACK><CTL=RST>
+ */
TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
return;
}
- else
+ }
+ else
+ {
+ TI_DbgPrint(MIN_TRACE, ("Go to ctSynReceived connection state.\n"));
+ Connection->State = ctSynReceived;
+
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Controls or segment data queued for transmission may be sent.\n"));
+
+ /* Issue SYN/ACK segment */
+ Status = TCPBuildAndTransmitSendRequest2(
+ Connection, /* Connection endpoint */
+ NULL, /* Completion routine */
+ NULL, /* Completion routine context */
+ NULL, /* Buffer */
+ 0, /* Size of buffer */
+ SRF_SYN | SRF_ACK, /* Protocol specific flags */
+ Connection->SendISS, /* Sequence number */
+ Connection->ReceiveNext); /* Acknowledgement number */
+ if (!NT_SUCCESS(Status))
{
- /* Continue */
+ /* FIXME: Send RST (if no RST)
+ * <SEQ=SEG.ACK><CTL=RST>
+ */
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+ return;
}
}
- return;
}
+ else
+ {
+ /* FIXME: What happens here? */
+ }
+ }
- /* The ACK is ok, or there is no ACK, and it the segment did not contain a RST */
+ /* FIXME: Send RST (if no RST)
+ <SEQ=SEG.ACK><CTL=RST> */
+ TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+}
- if ((TCPHeader->Flags & TCP_SYN) > 0)
- {
- /* FIXME: The security/compartment and precedence are acceptable */
- if (TRUE)
- {
- /* FIXME: RCV.NXT is set to SEG.SEQ+1, IRS is set to
- SEG.SEQ. SND.UNA should be advanced to equal SEG.ACK (if there
- is an ACK), and any segments on the retransmission queue which
- are thereby acknowledged should be removed.
+/*
+ * Returns TRUE if processing should be continued, FALSE if not
+ */
+static inline BOOLEAN TCPiReceiveSynReceived(
+ PADDRESS_FILE AddrFile,
+ PIP_PACKET IPPacket,
+ PTCPv4_HEADER TCPHeader)
+{
+ PCONNECTION_ENDPOINT Connection = AddrFile->Connection;
- If SND.UNA > ISS (our SYN has been ACKed), change the connection
- state to ESTABLISHED, form an ACK segment
+ ASSERT(AddrFile);
+ ASSERT(IPPacket);
+ ASSERT(TCPHeader);
- <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
+ /* FIXME: Protect AddrFile->Connection */
- Data or controls which were queued for
- transmission may be included. If there are other controls or
- text in the segment then continue processing at the sixth step
- below where the URG bit is checked, otherwise return.
+ /* FIXME: If SND.UNA =< SEG.ACK =< SND.NXT then enter ESTABLISHED state
+ and continue processing.
- Otherwise enter SYN-RECEIVED, form a SYN,ACK segment
+ If the segment acknowledgment is not acceptable, form a
[truncated at 1000 lines; 460 more skipped]
reactos/lib/msafd/include
diff -u -r1.6 -r1.7
--- msafd.h 2 Mar 2004 18:18:15 -0000 1.6
+++ msafd.h 4 Mar 2004 20:45:39 -0000 1.7
@@ -18,6 +18,13 @@
#include <afd/shared.h>
#include <debug.h>
+/*typedef _MSAFD_LISTEN_REQUEST
+{
+ LIST_ENTRY ListEntry;
+ HANDLE Socket;
+} MSAFD_LISTEN_REQUEST, *PMSAFD_LISTEN_REQUEST;*/
+
+
extern HANDLE GlobalHeap;
extern WSPUPCALLTABLE Upcalls;
extern LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
reactos/lib/msafd/misc
diff -u -r1.11 -r1.12
--- dllmain.c 10 Feb 2004 17:12:41 -0000 1.11
+++ dllmain.c 4 Mar 2004 20:45:39 -0000 1.12
@@ -23,6 +23,9 @@
/* To make the linker happy */
VOID STDCALL KeBugCheck (ULONG BugCheckCode) {}
+/* FIXME: Protect me */
+static LIST_ENTRY MsAfdListenRequests; /* Queue of listen reqests */
+
HANDLE GlobalHeap;
WSPUPCALLTABLE Upcalls;
@@ -358,6 +361,7 @@
* 0, or SOCKET_ERROR if the socket could not be bound
*/
{
+ //PAFD_LISTEN_REQUEST MsafdRequest;
FILE_REQUEST_LISTEN Request;
FILE_REPLY_LISTEN Reply;
IO_STATUS_BLOCK Iosb;
@@ -365,28 +369,38 @@
AFD_DbgPrint(MAX_TRACE, ("s (0x%X) backlog (%d).\n", s, backlog));
+/* MsafdRequest = (PMSAFD_LISTEN_REQUEST)HeapAlloc(
+ GlobalHeap, 0, sizeof(MSAFD_LISTEN_REQUEST));
+ if (MsafdRequest == NULL)
+ {
+ AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+ *lpErrno = WSAENOBUFS;
+ return SOCKET_ERROR;
+ }*/
+
Request.Backlog = backlog;
Status = NtDeviceIoControlFile(
(HANDLE)s,
NULL,
- NULL,
- NULL,
- &Iosb,
- IOCTL_AFD_LISTEN,
- &Request,
- sizeof(FILE_REQUEST_LISTEN),
- &Reply,
- sizeof(FILE_REPLY_LISTEN));
- if (Status == STATUS_PENDING) {
- AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
- /* FIXME: Wait only for blocking sockets */
- Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL);
- }
-
- if (!NT_SUCCESS(Status)) {
+ NULL,
+ NULL,
+ &Iosb,
+ IOCTL_AFD_LISTEN,
+ &Request,
+ sizeof(FILE_REQUEST_LISTEN),
+ &Reply,
+ sizeof(FILE_REPLY_LISTEN));
+ if (Status == STATUS_PENDING)
+ {
+ //AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
+ //InsertTailList(&MsAfdListenRequests, &MsafdRequest->ListEntry);
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ //HeapFree(GlobalHeap, 0, MsafdRequest);
*lpErrno = Reply.Status;
- return SOCKET_ERROR;
+ return SOCKET_ERROR;
}
return 0;
@@ -841,10 +855,13 @@
*/
{
HMODULE hWS2_32;
- INT Status;
+ NTSTATUS Status;
+ INT Error;
AFD_DbgPrint(MAX_TRACE, ("wVersionRequested (0x%X) \n", wVersionRequested));
+ Status = NO_ERROR;
+
EnterCriticalSection(&InitCriticalSection);
Upcalls = UpcallTable;
@@ -859,17 +876,22 @@
lpWPUCompleteOverlappedRequest = (LPWPUCOMPLETEOVERLAPPEDREQUEST)
GetProcAddress(hWS2_32, "WPUCompleteOverlappedRequest");
if (lpWPUCompleteOverlappedRequest != NULL) {
- Status = NO_ERROR;
StartupCount++;
+ } else {
+ AFD_DbgPrint(MIN_TRACE, ("GetProcAddress() failed for WPUCompleteOverlappedRequest\n"));
+ CloseCommandChannel();
+ Error = WSASYSNOTREADY;
}
} else {
AFD_DbgPrint(MIN_TRACE, ("GetModuleHandle() failed for ws2_32.dll\n"));
+ CloseCommandChannel();
+ Error = WSASYSNOTREADY;
}
} else {
AFD_DbgPrint(MIN_TRACE, ("Cannot open afd.sys\n"));
+ Error = WSASYSNOTREADY;
}
} else {
- Status = NO_ERROR;
StartupCount++;
}
@@ -969,6 +991,8 @@
InitializeCriticalSection(&InitCriticalSection);
+ InitializeListHead(&MsAfdListenRequests);
+
GlobalHeap = GetProcessHeap();
CreateHelperDLLDatabase();
CVSspam 0.2.8