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/t... ============================================================================== --- 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/t... ============================================================================== --- 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/t... ============================================================================== --- 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/t... ============================================================================== --- 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>