Author: zhu
Date: Wed Jun 8 19:26:53 2016
New Revision: 71594
URL:
http://svn.reactos.org/svn/reactos?rev=71594&view=rev
Log:
TCP handshake working in driver and properly reported up to user programs. The port is not
closed properly, however.
Modified:
branches/GSoC_2016/lwIP/drivers/network/tcpip/address.c
branches/GSoC_2016/lwIP/drivers/network/tcpip/address.h
branches/GSoC_2016/lwIP/drivers/network/tcpip/main.c
branches/GSoC_2016/lwIP/drivers/network/tcpip/precomp.h
Modified: branches/GSoC_2016/lwIP/drivers/network/tcpip/address.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP/drivers/network/…
==============================================================================
--- branches/GSoC_2016/lwIP/drivers/network/tcpip/address.c [iso-8859-1] (original)
+++ branches/GSoC_2016/lwIP/drivers/network/tcpip/address.c [iso-8859-1] Wed Jun 8
19:26:53 2016
@@ -142,6 +142,24 @@
}
static
+err_t
+lwip_tcp_accept_callback(
+ void *arg,
+ struct tcp_pcb *newpcb,
+ err_t err)
+{
+ PIRP Irp;
+
+ DPRINT1("lwIP TCP Accept Callback\n");
+
+ Irp = (PIRP)arg;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
+
+ return ERR_OK;
+}
+
+static
u8_t
lwip_raw_ReceiveDatagram_callback(
void *arg,
@@ -184,6 +202,24 @@
pbuf_free(p);
return Result;
+}
+
+static
+err_t
+lwip_tcp_Connected_callback(
+ void *arg,
+ struct tcp_pcb *tpcb,
+ err_t err)
+{
+ PIRP Irp;
+
+ DPRINT1("lwIP TCP Connected Callback\n");
+
+ Irp = (PIRP)arg;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
+
+ return ERR_OK;
}
NTSTATUS
@@ -248,9 +284,10 @@
struct netif* lwip_netif = netif_list;
ip_addr_t IpAddr;
- ip4_addr_set_u32(&IpAddr, AddressFile->Address.in_addr);
+ ip4_addr_set_u32(&IpAddr, Address->in_addr);
while (lwip_netif)
{
+ DPRINT1("Comparing against address %lx\n", lwip_netif->ip_addr.addr);
if (ip_addr_cmp(&IpAddr, &lwip_netif->ip_addr))
{
break;
@@ -260,7 +297,7 @@
if (!lwip_netif)
{
- DPRINT1("Cound not find an interface for address 0x08x\n",
AddressFile->Address.in_addr);
+ DPRINT1("Cound not find an interface for address 0x%08x\n",
AddressFile->Address.in_addr);
KeReleaseSpinLock(&AddressListLock, OldIrql);
return STATUS_INVALID_ADDRESS;
}
@@ -288,8 +325,13 @@
switch (Protocol)
{
case IPPROTO_TCP:
+ {
+ ip_addr_t IpAddr;
+ ip4_addr_set_u32(&IpAddr, AddressFile->Address.in_addr);
InsertEntityInstance(CO_TL_ENTITY, &AddressFile->Instance);
- break;
+ AddressFile->lwip_tcp_pcb = tcp_new();
+ break;
+ }
case IPPROTO_UDP:
{
ip_addr_t IpAddr;
@@ -441,6 +483,301 @@
ExFreePoolWithTag(Request, TAG_ADDRESS_FILE);
}
+/* implementation in testing */
+NTSTATUS
+TcpIpConnect(
+ _Inout_ PIRP Irp)
+{
+ PIO_STACK_LOCATION IrpSp;
+ ADDRESS_FILE *AddressFile;
+ PTDI_REQUEST_KERNEL_CONNECT Parameters;
+ PTRANSPORT_ADDRESS RemoteTransportAddress;
+
+ struct sockaddr *SocketAddressRemote;
+ struct sockaddr_in *SocketAddressInRemote;
+
+ err_t lwip_err;
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ /* Check this is really a connection file */
+ if ((ULONG_PTR)IrpSp->FileObject->FsContext2 != TDI_TRANSPORT_ADDRESS_FILE)
+ {
+ DPRINT1("File object not an address file\n");
+ return STATUS_FILE_INVALID;
+ }
+
+ AddressFile = IrpSp->FileObject->FsContext;
+ if (AddressFile->Protocol != IPPROTO_TCP)
+ {
+ DPRINT1("Received TDI_CONNECT for a non-TCP protocol\n");
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ Parameters = (PTDI_REQUEST_KERNEL_CONNECT)&IrpSp->Parameters;
+
+ RemoteTransportAddress = Parameters->RequestConnectionInformation->RemoteAddress;
+
+ SocketAddressRemote = (struct sockaddr *)&RemoteTransportAddress->Address[0];
+ SocketAddressInRemote = (struct sockaddr_in *)&SocketAddressRemote->sa_data;
+
+ DPRINT1("\n Remote Address\n Address: %08x\n Port: %04x\n",
+ SocketAddressInRemote->sin_addr.s_addr,
+ SocketAddressInRemote->sin_port);
+ DPRINT1("\n Local Address\n Address: %08x\n Port: %04x\n",
+ AddressFile->lwip_tcp_pcb->local_ip,
+ AddressFile->lwip_tcp_pcb->local_port);
+
+ lwip_err = tcp_connect(AddressFile->lwip_tcp_pcb,
+ (ip_addr_t *)&SocketAddressInRemote->sin_addr.s_addr,
+ SocketAddressInRemote->sin_port,
+ lwip_tcp_Connected_callback);
+ DPRINT1("lwip error %d\n", lwip_err);
+ switch (lwip_err)
+ {
+ case (ERR_VAL) :
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+ case (ERR_ISCONN) :
+ {
+ return STATUS_CONNECTION_ACTIVE;
+ }
+ case (ERR_RTE) :
+ {
+ /* several errors look right here */
+ return STATUS_NETWORK_UNREACHABLE;
+ }
+ case (ERR_BUF) :
+ {
+ /* use correct error once NDIS errors are included
+ this return value means local port unavailable */
+ return STATUS_ADDRESS_ALREADY_EXISTS;
+ }
+ case (ERR_USE) :
+ {
+ /* STATUS_CONNECTION_ACTIVE maybe? */
+ return STATUS_ADDRESS_ALREADY_EXISTS;
+ }
+ case (ERR_MEM) :
+ {
+ return STATUS_NO_MEMORY;
+ }
+ case (ERR_OK) :
+ {
+ DPRINT1("lwip ERR_OK\n");
+ tcp_arg(AddressFile->lwip_tcp_pcb, Irp);
+ break;
+ }
+ default :
+ {
+ /* unknown return value */
+ DPRINT1("lwip unknown return code\n");
+ return STATUS_NOT_IMPLEMENTED;
+ }
+ }
+
+ return STATUS_PENDING;
+}
+
+/* Implementation in testing */
+NTSTATUS
+TcpIpAssociateAddress(
+ _Inout_ PIRP Irp)
+{
+ PIO_STACK_LOCATION IrpSp;
+ ADDRESS_FILE *AddressFile;
+ ADDRESS_FILE *BindTo;
+ PTDI_REQUEST_KERNEL_ASSOCIATE RequestInfo;
+ PFILE_OBJECT FileObject;
+
+ err_t lwip_err;
+ NTSTATUS Status;
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ /* Check this is really an address file */
+ if ((ULONG_PTR)IrpSp->FileObject->FsContext2 != TDI_TRANSPORT_ADDRESS_FILE)
+ {
+ return STATUS_FILE_INVALID;
+ }
+
+ /* Get address file */
+ AddressFile = IrpSp->FileObject->FsContext;
+
+ if (AddressFile->Protocol != IPPROTO_TCP)
+ {
+ DPRINT1("Received TDI_ASSOCIATE_ADDRESS for a non-TCP protocol\n");
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ RequestInfo = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters;
+
+ Status = ObReferenceObjectByHandle(
+ RequestInfo->AddressHandle,
+ 0,
+ *IoFileObjectType,
+ KernelMode,
+ (PVOID*)&FileObject,
+ NULL);
+ if (Status != STATUS_SUCCESS)
+ {
+ DPRINT1("Reference by handle failed with status 0x%08x\n", Status);
+ return Status;
+ }
+
+ if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE)
+ {
+ DPRINT1("File object is not an address file\n");
+ ObDereferenceObject(FileObject);
+ return STATUS_INVALID_PARAMETER;
+ }
+ BindTo = FileObject->FsContext;
+ if (BindTo->Protocol != IPPROTO_TCP)
+ {
+ DPRINT1("TCP socket association with non-TCP handle\n");
+ ObDereferenceObject(FileObject);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ DPRINT1("\n TDI Address\n Port: %04x\n Address: %08x\n",
+ BindTo->Address.sin_port,
+ BindTo->Address.in_addr);
+
+ /* Finally calling into lwip to perform socket bind */
+ lwip_err = tcp_bind(
+ AddressFile->lwip_tcp_pcb,
+ (ip_addr_t *)&BindTo->Address.in_addr,
+ BindTo->Address.sin_port);
+
+ DPRINT1("lwip error %d\n TCP PCB:\n Local Address: %08x\n Local Port: %04x\n
Remote Address: %08x\n Remote Port: %04x\n",
+ lwip_err,
+ AddressFile->lwip_tcp_pcb->local_ip,
+ AddressFile->lwip_tcp_pcb->local_port,
+ AddressFile->lwip_tcp_pcb->remote_ip,
+ AddressFile->lwip_tcp_pcb->remote_port);
+ if (lwip_err != ERR_OK)
+ {
+ switch (lwip_err)
+ {
+ case (ERR_BUF) :
+ {
+ /* Not actually sure which error I should return here
+ ERR_BUF means the port is already taken
+ fix when I figure out how to use NDIS errors */
+ Status = STATUS_ADDRESS_ALREADY_EXISTS;
+ goto LEAVE;
+ }
+ case (ERR_VAL) :
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto LEAVE;
+ }
+ case (ERR_USE) :
+ {
+ Status = STATUS_ADDRESS_ALREADY_EXISTS;
+ goto LEAVE;
+ }
+ default :
+ {
+ break;
+ }
+ }
+ }
+ ip_set_option(AddressFile->lwip_tcp_pcb, SOF_BROADCAST);
+
+ Status = STATUS_SUCCESS;
+LEAVE:
+ return Status;
+}
+
+
+/* Implementation in testing */
+NTSTATUS
+TcpIpDisassociateAddress(
+ _Inout_ PIRP Irp)
+{
+ PIO_STACK_LOCATION IrpSp;
+ ADDRESS_FILE *AddressFile;
+
+ err_t lwip_err;
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ if ((ULONG)IrpSp->FileObject->FsContext2 != TDI_TRANSPORT_ADDRESS_FILE)
+ {
+ return STATUS_FILE_INVALID;
+ }
+
+ AddressFile = IrpSp->FileObject->FsContext;
+
+ if (AddressFile->Protocol != IPPROTO_TCP)
+ {
+ DPRINT1("Received TDI_DISASSOCIATE_ADDRESS for non-TCP protocol\n");
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ lwip_err = tcp_close(AddressFile->lwip_tcp_pcb);
+ switch (lwip_err)
+ {
+ case ERR_MEM :
+ return STATUS_NO_MEMORY;
+ case ERR_OK :
+ break;
+ default :
+ DPRINT1("Unexpected lwIP error\n");
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/* Implementation in testing */
+NTSTATUS
+TcpIpListen(
+ _Inout_ PIRP Irp)
+{
+ PIO_STACK_LOCATION IrpSp;
+ ADDRESS_FILE *AddressFile;
+
+ struct tcp_pcb *lpcb;
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ /* Check this is really an address file */
+ if ((ULONG_PTR)IrpSp->FileObject->FsContext2 != TDI_TRANSPORT_ADDRESS_FILE)
+ {
+ return STATUS_FILE_INVALID;
+ }
+
+ /* Get address file */
+ AddressFile = IrpSp->FileObject->FsContext;
+ if (AddressFile->Protocol != IPPROTO_TCP)
+ {
+ DPRINT1("Received TDI_LISTEN for a non-TCP protocol\n");
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ /* Call down into lwip to initiate a listen */
+ lpcb = tcp_listen(AddressFile->lwip_tcp_pcb);
+ DPRINT1("lwip tcp_listen returned\n");
+ if (lpcb == NULL)
+ {
+ /* tcp_listen returning NULL can mean
+ either INVALID_ADDRESS or NO_MEMORY
+ if SO_REUSE is enabled in lwip options */
+ DPRINT1("lwip tcp_listen error\n");
+ return STATUS_NO_MEMORY;
+ }
+ else
+ {
+ AddressFile->lwip_tcp_pcb = lpcb;
+ }
+
+ tcp_accept(AddressFile->lwip_tcp_pcb, lwip_tcp_accept_callback);
+ tcp_arg(AddressFile->lwip_tcp_pcb, Irp);
+
+ return STATUS_PENDING;
+}
NTSTATUS
TcpIpReceiveDatagram(
Modified: branches/GSoC_2016/lwIP/drivers/network/tcpip/address.h
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP/drivers/network/…
==============================================================================
--- branches/GSoC_2016/lwIP/drivers/network/tcpip/address.h [iso-8859-1] (original)
+++ branches/GSoC_2016/lwIP/drivers/network/tcpip/address.h [iso-8859-1] Wed Jun 8
19:26:53 2016
@@ -14,6 +14,7 @@
{
struct raw_pcb* lwip_raw_pcb;
struct udp_pcb* lwip_udp_pcb;
+ struct tcp_pcb* lwip_tcp_pcb;
};
} ADDRESS_FILE;
@@ -31,6 +32,25 @@
TcpIpCloseAddress(
_Inout_ ADDRESS_FILE* AddressFile
);
+
+NTSTATUS
+TcpIpConnect(
+ _Inout_ PIRP Irp
+);
+
+NTSTATUS
+TcpIpAssociateAddress(
+ _Inout_ PIRP Irp
+);
+
+NTSTATUS
+TcpIpDisassociateAddress(
+ _Inout_ PIRP Irp
+);
+
+NTSTATUS
+TcpIpListen(
+ _Inout_ PIRP Irp);
NTSTATUS
TcpIpReceiveDatagram(
Modified: branches/GSoC_2016/lwIP/drivers/network/tcpip/main.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP/drivers/network/…
==============================================================================
--- branches/GSoC_2016/lwIP/drivers/network/tcpip/main.c [iso-8859-1] (original)
+++ branches/GSoC_2016/lwIP/drivers/network/tcpip/main.c [iso-8859-1] Wed Jun 8 19:26:53
2016
@@ -7,7 +7,7 @@
#include "precomp.h"
-#define NDEBUG
+//#define NDEBUG
#include <debug.h>
/* DriverEntry, DriverUnload and dispatch routines declaration */
@@ -264,14 +264,30 @@
}
case TDI_CONNECTION_CONTEXT_LENGTH:
+ {
+ PTA_IP_ADDRESS Address;
+
if (strncmp(&FileInfo->EaName[0], TdiConnectionContext,
TDI_CONNECTION_CONTEXT_LENGTH) != 0)
{
DPRINT1("TCPIP: Should maybe open file %*s.\n",
FileInfo->EaNameLength, &FileInfo->EaName[0]);
return STATUS_INVALID_PARAMETER;
}
DPRINT1("Should create a connection!\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
+
+ Address = (PTA_IP_ADDRESS)(&FileInfo->EaName[FileInfo->EaNameLength + 1]);
+
+ /* Get the protocol this address will be created for. */
+ Protocol = ProtocolFromIrp(DeviceObject, IrpSp);
+ if (Protocol == (IPPROTO)-1)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quickie;
+ }
+
+ /* All good. */
+ Status = TcpIpCreateAddress(Irp, &Address->Address[0].Address[0], Protocol);
+ break;
+ }
default:
DPRINT1("TCPIP: Should open file %*s.\n",
FileInfo->EaNameLength, &FileInfo->EaName[0]);
@@ -372,14 +388,14 @@
break;
case TDI_LISTEN:
- DPRINT1("TCPIP: TDI_LISTEN!\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
+ DPRINT1("TCPIP: TDI_LISTEN!\n");
+ Status = TcpIpListen(Irp);
+ break;
case TDI_CONNECT:
DPRINT1("TCPIP: TDI_CONNECT!\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
+ Status = TcpIpConnect(Irp);
+ break;
case TDI_DISCONNECT:
DPRINT1("TCPIP: TDI_DISCONNECT!\n");
@@ -387,13 +403,13 @@
break;
case TDI_ASSOCIATE_ADDRESS:
- DPRINT1("TCPIP: TDI_ASSOCIATE_ADDRESS!\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
+ DPRINT1("TCPIP: TDI_ASSOCIATE_ADDRESS\n");
+ Status = TcpIpAssociateAddress(Irp);
+ break;
case TDI_DISASSOCIATE_ADDRESS:
DPRINT1("TCPIP: TDI_DISASSOCIATE_ADDRESS!\n");
- Status = STATUS_NOT_IMPLEMENTED;
+ Status = TcpIpDisassociateAddress(Irp);
break;
case TDI_QUERY_INFORMATION:
@@ -474,7 +490,7 @@
break;
}
- DPRINT("TCPIP dispatched with status 0x%08x.\n", Status);
+ //DPRINT("TCPIP dispatched with status 0x%08x.\n", Status);
Irp->IoStatus.Status = Status;
if (Status == STATUS_PENDING)
Modified: branches/GSoC_2016/lwIP/drivers/network/tcpip/precomp.h
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP/drivers/network/…
==============================================================================
--- branches/GSoC_2016/lwIP/drivers/network/tcpip/precomp.h [iso-8859-1] (original)
+++ branches/GSoC_2016/lwIP/drivers/network/tcpip/precomp.h [iso-8859-1] Wed Jun 8
19:26:53 2016
@@ -23,6 +23,7 @@
#include <lwip/raw.h>
#include <lwip/snmp.h>
#include <lwip/tcpip.h>
+#include <lwip/tcp.h>
#include <lwip/udp.h>
#include <netif/etharp.h>