Author: zhu Date: Fri Jul 8 17:52:42 2016 New Revision: 71865 URL: http://svn.reactos.org/svn/reactos?rev=71865&view=rev Log: Structural, style, correctness fixes.
Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c?rev=71865&r1=71864&r2=71865&view=diff ============================================================================== --- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c [iso-8859-1] Fri Jul 8 17:52:42 2016 @@ -14,12 +14,12 @@ typedef struct { - LIST_ENTRY ListEntry; - TDI_ADDRESS_IP RemoteAddress; - PIRP Irp; - PVOID Buffer; - ULONG BufferLength; - PTDI_CONNECTION_INFORMATION ReturnInfo; + LIST_ENTRY ListEntry; + TDI_ADDRESS_IP RemoteAddress; + PIRP Irp; + PVOID Buffer; + ULONG BufferLength; + PTDI_CONNECTION_INFORMATION ReturnInfo; } RECEIVE_DATAGRAM_REQUEST; /* The pool tags we will use for all of our allocation */ @@ -33,6 +33,8 @@ static LIST_ENTRY AddressListHead; /* implementation in testing */ +/* Must already hold the Context->RequestListLock */ +/* Context should be in ->FileObject->FsContext */ NTSTATUS PrepareIrpForCancel( PIRP Irp, @@ -44,7 +46,6 @@ PIO_STACK_LOCATION IrpSp; PTCP_CONTEXT Context; PTCP_REQUEST Request; - KIRQL OldIrql; NTSTATUS Status; DPRINT1("Prepare for cancel\n"); @@ -67,10 +68,8 @@ Request->CancelMode = CancelMode; Request->PendingMode = PendingMode; - KeAcquireSpinLock(&Context->RequestListLock, &OldIrql); IoSetCancelRoutine(Irp, CancelRoutine); InsertTailList(&Context->RequestListHead, &Request->ListEntry); - KeReleaseSpinLock(&Context->RequestListLock, OldIrql); Status = STATUS_SUCCESS; DPRINT1("Prepared for cancel\n"); @@ -143,6 +142,7 @@ { AddressFile->lwip_tcp_pcb = NULL; } + tcp_arg(Context->lwip_tcp_pcb, NULL); tcp_abort(Context->lwip_tcp_pcb); InterlockedDecrement(&PcbCount); DPRINT1("\n PCB Count: %d\n", PcbCount); @@ -207,8 +207,8 @@ void TcpIpInitializeAddresses(void) { - KeInitializeSpinLock(&AddressListLock); - InitializeListHead(&AddressListHead); + KeInitializeSpinLock(&AddressListLock); + InitializeListHead(&AddressListHead); PcbCount = 0; } @@ -216,9 +216,9 @@ static BOOLEAN AddrIsUnspecified( - _In_ PTDI_ADDRESS_IP Address) -{ - return ((Address->in_addr == 0) || (Address->in_addr == 0xFFFFFFFF)); + _In_ PTDI_ADDRESS_IP Address) +{ + return ((Address->in_addr == 0) || (Address->in_addr == 0xFFFFFFFF)); } /* Implementation in testing */ @@ -231,8 +231,8 @@ PTCP_CONTEXT Context; PTCP_REQUEST Request; PLIST_ENTRY Head; - PLIST_ENTRY HeadNest; - PLIST_ENTRY EntryNest; + PLIST_ENTRY RequestHead; + PLIST_ENTRY RequestEntry; PLIST_ENTRY Entry; PLIST_ENTRY Temp; PIRP Irp; @@ -267,11 +267,23 @@ Status = STATUS_ADDRESS_CLOSED; + if (!arg) + { + DPRINT1("We did the cancelling ourselves, no need to worry about deallocations\n"); + return; + } + + /* This switch relies on UCHAR Type being the first member in + _ADDRESS_FILE + _TCP_CONTEXT + This works assuming the compiler never adds padding before the first struct member + */ + DPRINT1("Type: %08x\n", *((UCHAR*)arg)); switch (*((UCHAR*)arg)) { case TDI_TRANSPORT_ADDRESS_FILE : AddressFile = (PADDRESS_FILE)arg; - DPRINT1("AddressFile at %08x\n", AddressFile); + DPRINT1("AddressFile at %p\n", AddressFile); KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql); Head = &AddressFile->ContextListHead; @@ -281,11 +293,11 @@ Context = CONTAINING_RECORD(Entry, TCP_CONTEXT, ListEntry); KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock); - HeadNest = &Context->RequestListHead; - EntryNest = HeadNest->Flink; - while (EntryNest != HeadNest) + RequestHead = &Context->RequestListHead; + RequestEntry = RequestHead->Flink; + while (RequestEntry != RequestHead) { - Request = CONTAINING_RECORD(EntryNest, TCP_REQUEST, ListEntry); + Request = CONTAINING_RECORD(RequestEntry, TCP_REQUEST, ListEntry); Irp = Request->PendingIrp; if (Irp) { @@ -298,16 +310,17 @@ Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); } - Temp = EntryNest->Flink; - RemoveEntryList(EntryNest); + Temp = RequestEntry->Flink; + RemoveEntryList(RequestEntry); ExFreePoolWithTag(Request, TAG_TCP_REQUEST); - EntryNest = Temp; + RequestEntry = Temp; } KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock); if (Context->lwip_tcp_pcb != AddressFile->lwip_tcp_pcb) { + tcp_arg(Context->lwip_tcp_pcb, NULL); tcp_abort(Context->lwip_tcp_pcb); InterlockedDecrement(&PcbCount); DPRINT1("\n PCB Count\n", PcbCount); @@ -324,14 +337,14 @@ return; case TDI_CONNECTION_FILE : Context = (PTCP_CONTEXT)arg; - DPRINT1("AddressFile at %08x\n", Context->AddressFile); + DPRINT1("AddressFile at %p\n", Context->AddressFile); KeAcquireSpinLock(&Context->RequestListLock, &OldIrql); - HeadNest = &Context->RequestListHead; - EntryNest = HeadNest->Flink; - while (EntryNest != HeadNest) + RequestHead = &Context->RequestListHead; + RequestEntry = RequestHead->Flink; + while (RequestEntry != RequestHead) { - Request = CONTAINING_RECORD(EntryNest, TCP_REQUEST, ListEntry); + Request = CONTAINING_RECORD(RequestEntry, TCP_REQUEST, ListEntry); Irp = Request->PendingIrp; if (Irp) { @@ -344,10 +357,10 @@ Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); } - Temp = EntryNest->Flink; - RemoveEntryList(EntryNest); + Temp = RequestEntry->Flink; + RemoveEntryList(RequestEntry); ExFreePoolWithTag(Request, TAG_TCP_REQUEST); - EntryNest = Temp; + RequestEntry = Temp; } KeReleaseSpinLock(&Context->RequestListLock, OldIrql); @@ -361,7 +374,7 @@ return; default : - DPRINT1("Invalid argument: %08x\n", arg); + DPRINT1("Invalid argument: %p\n", arg); return; } } @@ -369,96 +382,96 @@ static BOOLEAN ReceiveDatagram( - ADDRESS_FILE* AddressFile, - struct pbuf *p, - ip_addr_t *addr, - u16_t port) -{ - KIRQL OldIrql; - LIST_ENTRY* ListEntry; - RECEIVE_DATAGRAM_REQUEST* Request; - ip_addr_t RequestAddr; - BOOLEAN Result = FALSE; - - NT_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); - - DPRINT1("Receiving datagram for addr 0x%08x on port %u.\n", ip4_addr_get_u32(addr), port); - - /* Block any cancellation that could occur */ - KeAcquireSpinLock(&AddressFile->RequestLock, &OldIrql); - - ListEntry = AddressFile->RequestListHead.Flink; - while (ListEntry != &AddressFile->RequestListHead) - { - Request = CONTAINING_RECORD(ListEntry, RECEIVE_DATAGRAM_REQUEST, ListEntry); - ListEntry = ListEntry->Flink; - - ip4_addr_set_u32(&RequestAddr, Request->RemoteAddress.in_addr); - - if ((RequestAddr.addr == IPADDR_ANY) || - (ip_addr_cmp(&RequestAddr, addr) && - ((Request->RemoteAddress.sin_port == lwip_htons(port)) || !port))) - { - PTA_IP_ADDRESS ReturnAddress; - PIRP Irp; - - DPRINT1("Found a corresponding IRP.\n"); - - Irp = Request->Irp; - - /* We found a request for this one */ - IoSetCancelRoutine(Irp, NULL); - RemoveEntryList(&Request->ListEntry); - Result = TRUE; - - KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); - - /* In case of UDP, lwip provides a pbuf directly pointing to the data. - * In other case, we must skip the IP header */ - Irp->IoStatus.Information = pbuf_copy_partial( - p, - Request->Buffer, - Request->BufferLength, - 0); - ReturnAddress = Request->ReturnInfo->RemoteAddress; - ReturnAddress->Address->AddressLength = TDI_ADDRESS_LENGTH_IP; - ReturnAddress->Address->AddressType = TDI_ADDRESS_TYPE_IP; - ReturnAddress->Address->Address->sin_port = lwip_htons(port); - ReturnAddress->Address->Address->in_addr = ip4_addr_get_u32(addr); - RtlZeroMemory(ReturnAddress->Address->Address->sin_zero, - sizeof(ReturnAddress->Address->Address->sin_zero)); - - if (Request->BufferLength < p->tot_len) - Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; - else - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); - - ExFreePoolWithTag(Request, TAG_DGRAM_REQST); - - /* Start again from the beginning */ - KeAcquireSpinLock(&AddressFile->RequestLock, &OldIrql); - } - } - - KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); - - return Result; + ADDRESS_FILE* AddressFile, + struct pbuf *p, + ip_addr_t *addr, + u16_t port) +{ + KIRQL OldIrql; + LIST_ENTRY* ListEntry; + RECEIVE_DATAGRAM_REQUEST* Request; + ip_addr_t RequestAddr; + BOOLEAN Result = FALSE; + + NT_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); + + DPRINT1("Receiving datagram for addr 0x%08x on port %u.\n", ip4_addr_get_u32(addr), port); + + /* Block any cancellation that could occur */ + KeAcquireSpinLock(&AddressFile->RequestLock, &OldIrql); + + ListEntry = AddressFile->RequestListHead.Flink; + while (ListEntry != &AddressFile->RequestListHead) + { + Request = CONTAINING_RECORD(ListEntry, RECEIVE_DATAGRAM_REQUEST, ListEntry); + ListEntry = ListEntry->Flink; + + ip4_addr_set_u32(&RequestAddr, Request->RemoteAddress.in_addr); + + if ((RequestAddr.addr == IPADDR_ANY) || + (ip_addr_cmp(&RequestAddr, addr) && + ((Request->RemoteAddress.sin_port == lwip_htons(port)) || !port))) + { + PTA_IP_ADDRESS ReturnAddress; + PIRP Irp; + + DPRINT1("Found a corresponding IRP.\n"); + + Irp = Request->Irp; + + /* We found a request for this one */ + IoSetCancelRoutine(Irp, NULL); + RemoveEntryList(&Request->ListEntry); + Result = TRUE; + + KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); + + /* In case of UDP, lwip provides a pbuf directly pointing to the data. + * In other case, we must skip the IP header */ + Irp->IoStatus.Information = pbuf_copy_partial( + p, + Request->Buffer, + Request->BufferLength, + 0); + ReturnAddress = Request->ReturnInfo->RemoteAddress; + ReturnAddress->Address->AddressLength = TDI_ADDRESS_LENGTH_IP; + ReturnAddress->Address->AddressType = TDI_ADDRESS_TYPE_IP; + ReturnAddress->Address->Address->sin_port = lwip_htons(port); + ReturnAddress->Address->Address->in_addr = ip4_addr_get_u32(addr); + RtlZeroMemory(ReturnAddress->Address->Address->sin_zero, + sizeof(ReturnAddress->Address->Address->sin_zero)); + + if (Request->BufferLength < p->tot_len) + Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + else + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + + ExFreePoolWithTag(Request, TAG_DGRAM_REQST); + + /* Start again from the beginning */ + KeAcquireSpinLock(&AddressFile->RequestLock, &OldIrql); + } + } + + KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); + + return Result; } static void lwip_udp_ReceiveDatagram_callback( - void *arg, - struct udp_pcb *pcb, - struct pbuf *p, - ip_addr_t *addr, - u16_t port) -{ - UNREFERENCED_PARAMETER(pcb); - - ReceiveDatagram(arg, p, addr, port); - pbuf_free(p); + void *arg, + struct udp_pcb *pcb, + struct pbuf *p, + ip_addr_t *addr, + u16_t port) +{ + UNREFERENCED_PARAMETER(pcb); + + ReceiveDatagram(arg, p, addr, port); + pbuf_free(p); } /* implementation in testing */ @@ -491,8 +504,7 @@ Context = CONTAINING_RECORD(Entry, TCP_CONTEXT, ListEntry); if (Context->TcpState == TCP_STATE_LISTENING) { - KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql); - KeAcquireSpinLock(&Context->RequestListLock, &OldIrql); + KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock); Context->lwip_tcp_pcb = newpcb; InterlockedIncrement(&PcbCount); @@ -504,14 +516,34 @@ Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry); Irp = Request->PendingIrp; - IrpSp = IoGetCurrentIrpStackLocation(Irp); - if (!Irp || IrpSp->MinorFunction != TDI_LISTEN) + if (!Irp) { DPRINT1("Received accept callback for cancelled TDI_LISTEN\n"); RemoveEntryList(Entry); - Entry = Entry->Flink; ExFreePoolWithTag(Request, TAG_TCP_REQUEST); - KeReleaseSpinLock(&Context->RequestListLock, OldIrql); + KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock); + KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql); + return ERR_ABRT; + } + IrpSp = IoGetCurrentIrpStackLocation(Irp); + if (IrpSp->MinorFunction != TDI_LISTEN) + { + DPRINT1("The IRP is not a listening request, something is seriously wrong\n"); + /* this should maybe clean out the entire context, + since this should never happen */ + RemoveEntryList(Entry); + + KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock); + KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql); + + ExFreePoolWithTag(Request, TAG_TCP_REQUEST); + + Irp->IoStatus.Status = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + IoSetCancelRoutine(Irp, NULL); + + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + return ERR_ABRT; } @@ -520,7 +552,8 @@ IoSetCancelRoutine(Irp, NULL); Irp->Cancel = FALSE; - KeReleaseSpinLock(&Context->RequestListLock, OldIrql); + KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock); + KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); @@ -622,11 +655,6 @@ IrpSp = IoGetCurrentIrpStackLocation(Irp); RequestInfo = (PTDI_REQUEST_KERNEL_SEND)&IrpSp->Parameters; lwip_err = tcp_write(Context->lwip_tcp_pcb, Buffer, RequestInfo->SendLength, 0); - PrepareIrpForCancel( - Irp, - CancelRequestRoutine, - TCP_REQUEST_CANCEL_MODE_PRESERVE, - TCP_REQUEST_PENDING_SEND); break; } Entry = Entry->Flink; @@ -662,6 +690,7 @@ UCHAR *CurrentSrceLocation; PLIST_ENTRY Head; PLIST_ENTRY Entry; + PLIST_ENTRY NextEntry; NTSTATUS Status; err_t lwip_err; @@ -692,9 +721,10 @@ DPRINT1("Request Fetched. Points to %08x\n", Request); if (!Request->PendingIrp) { DPRINT1("IRP pointer dereferenced\n"); + NextEntry = Entry->Flink; RemoveEntryList(Entry); DPRINT1("Entry removed\n"); - Entry = Entry->Flink; + Entry = NextEntry; ExFreePoolWithTag(Request, TAG_TCP_REQUEST); continue; } @@ -718,6 +748,7 @@ if (Context->lwip_tcp_pcb != tpcb) { DPRINT1("Receive tcp_pcb mismatch\n"); + tcp_arg(tpcb, NULL); tcp_abort(tpcb); InterlockedDecrement(&PcbCount); DPRINT1("\n PCB Count\n", PcbCount); @@ -795,14 +826,16 @@ tcp_recv(tpcb, lwip_tcp_receive_callback); break; } + Entry = Entry->Flink; } lwip_err = ERR_OK; BAD: RemoveEntryList(&Request->ListEntry); + + KeReleaseSpinLock(&Context->RequestListLock, OldIrql); + ExFreePoolWithTag(Request, TAG_TCP_REQUEST); - - KeReleaseSpinLock(&Context->RequestListLock, OldIrql); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = CopiedLength; @@ -814,46 +847,46 @@ static u8_t lwip_raw_ReceiveDatagram_callback( - void *arg, - struct raw_pcb *pcb, - struct pbuf *p, - ip_addr_t *addr) -{ - BOOLEAN Result; - ADDRESS_FILE* AddressFile = arg; - - UNREFERENCED_PARAMETER(pcb); - - /* If this is for ICMP, only process the "echo received" packets. - * The rest is processed by lwip. */ - if (AddressFile->Protocol == IPPROTO_ICMP) - { - /* See icmp_input */ - s16_t hlen; - struct ip_hdr *iphdr; - - iphdr = (struct ip_hdr *)p->payload; - hlen = IPH_HL(iphdr) * 4; - - /* Adjust the pbuf to skip the IP header */ - if (pbuf_header(p, -hlen)) - return FALSE; - - if (*((u8_t*)p->payload) != ICMP_ER) - { - pbuf_header(p, hlen); - return FALSE; - } - - pbuf_header(p, hlen); - } - - Result = ReceiveDatagram(arg, p, addr, 0); - - if (Result) - pbuf_free(p); - - return Result; + void *arg, + struct raw_pcb *pcb, + struct pbuf *p, + ip_addr_t *addr) +{ + BOOLEAN Result; + ADDRESS_FILE* AddressFile = arg; + + UNREFERENCED_PARAMETER(pcb); + + /* If this is for ICMP, only process the "echo received" packets. + * The rest is processed by lwip. */ + if (AddressFile->Protocol == IPPROTO_ICMP) + { + /* See icmp_input */ + s16_t hlen; + struct ip_hdr *iphdr; + + iphdr = (struct ip_hdr *)p->payload; + hlen = IPH_HL(iphdr) * 4; + + /* Adjust the pbuf to skip the IP header */ + if (pbuf_header(p, -hlen)) + return FALSE; + + if (*((u8_t*)p->payload) != ICMP_ER) + { + pbuf_header(p, hlen); + return FALSE; + } + + pbuf_header(p, hlen); + } + + Result = ReceiveDatagram(arg, p, addr, 0); + + if (Result) + pbuf_free(p); + + return Result; } /* implementation in testing */ @@ -877,24 +910,20 @@ Context = (PTCP_CONTEXT)arg; KeAcquireSpinLock(&Context->RequestListLock, &OldIrql); Head = &Context->RequestListHead; - Entry = Head->Flink; - if (Head == Entry) + if (IsListEmpty(Head)) { DPRINT1("Request list is empty\n"); KeReleaseSpinLock(&Context->RequestListLock, OldIrql); return ERR_ARG; } + Entry = RemoveHeadList(Head); + KeReleaseSpinLock(&Context->RequestListLock, OldIrql); Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry); Irp = Request->PendingIrp; if (!Irp) { DPRINT1("Callback on cancelled IRP\n"); - - RemoveEntryList(&Request->ListEntry); ExFreePoolWithTag(Request, TAG_TCP_REQUEST); - - KeReleaseSpinLock(&Request->Context->RequestListLock, OldIrql); - return ERR_ABRT; } IoSetCancelRoutine(Irp, NULL); @@ -910,11 +939,7 @@ lwip_err = ERR_OK; FINISH: - - RemoveEntryList(&Request->ListEntry); ExFreePoolWithTag(Request, TAG_TCP_REQUEST); - - KeReleaseSpinLock(&Context->RequestListLock, OldIrql); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); @@ -925,176 +950,178 @@ /* implementation in testing */ NTSTATUS TcpIpCreateAddress( - _Inout_ PIRP Irp, - _In_ PTDI_ADDRESS_IP Address, - _In_ IPPROTO Protocol + _Inout_ PIRP Irp, + _In_ PTDI_ADDRESS_IP Address, + _In_ IPPROTO Protocol ) { - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - PADDRESS_FILE AddressFile; - LIST_ENTRY* ListEntry; - KIRQL OldIrql; - - USHORT Port = 1; - - /* See if this port is already taken, and find a free one if needed. */ - KeAcquireSpinLock(&AddressListLock, &OldIrql); + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PADDRESS_FILE AddressFile; + LIST_ENTRY* ListEntry; + KIRQL OldIrql; + + USHORT Port = 1; + + /* See if this port is already taken, and find a free one if needed. */ + KeAcquireSpinLock(&AddressListLock, &OldIrql); DPRINT1("Search through used ports\n"); - ListEntry = AddressListHead.Flink; - while (ListEntry != &AddressListHead) - { - AddressFile = CONTAINING_RECORD(ListEntry, ADDRESS_FILE, ListEntry); - - if (Address->sin_port) - { - if ((AddressFile->Protocol == Protocol) && - (AddressFile->Address.sin_port == Address->sin_port)) - { - if (IrpSp->Parameters.Create.ShareAccess) - { - /* Good, we found the shared address we were looking for */ - InterlockedIncrement(&AddressFile->RefCount); - KeReleaseSpinLock(&AddressListLock, OldIrql); - goto Success; - } - - KeReleaseSpinLock(&AddressListLock, OldIrql); - return STATUS_ADDRESS_ALREADY_EXISTS; - } - } - else if ((AddressFile->Address.sin_port == lwip_htons(Port)) - && AddressFile->Protocol == Protocol) - { - Port++; - if (Port == 0) - { - /* Oh no. Already 65535 ports occupied! */ - DPRINT1("No more free ports for protocol %d!\n", Protocol); - KeReleaseSpinLock(&AddressListLock, OldIrql); - return STATUS_TOO_MANY_ADDRESSES; - } - - /* We must start anew to check again the previous entries in the list */ - ListEntry = &AddressListHead; - } - ListEntry = ListEntry->Flink; - } + ListEntry = AddressListHead.Flink; + while (ListEntry != &AddressListHead) + { + AddressFile = CONTAINING_RECORD(ListEntry, ADDRESS_FILE, ListEntry); + + if (Address->sin_port) + { + if ((AddressFile->Protocol == Protocol) && + (AddressFile->Address.sin_port == Address->sin_port)) + { + if (IrpSp->Parameters.Create.ShareAccess) + { + /* Good, we found the shared address we were looking for */ + InterlockedIncrement(&AddressFile->RefCount); + DPRINT1("RefCount increment to %d\n", AddressFile->RefCount); + KeReleaseSpinLock(&AddressListLock, OldIrql); + goto Success; + } + + KeReleaseSpinLock(&AddressListLock, OldIrql); + DPRINT1("Address taken\n"); + return STATUS_ADDRESS_ALREADY_EXISTS; + } + } + else if ((AddressFile->Address.sin_port == lwip_htons(Port)) + && AddressFile->Protocol == Protocol) + { + Port++; + if (Port == 0) + { + /* Oh no. Already 65535 ports occupied! */ + DPRINT1("No more free ports for protocol %d!\n", Protocol); + KeReleaseSpinLock(&AddressListLock, OldIrql); + return STATUS_TOO_MANY_ADDRESSES; + } + + /* We must start anew to check again the previous entries in the list */ + ListEntry = &AddressListHead; + } + ListEntry = ListEntry->Flink; + } DPRINT1("Find local interface for address\n"); - if (!AddrIsUnspecified(Address)) - { - /* Find the local interface for this address */ - struct netif* lwip_netif = netif_list; - ip_addr_t IpAddr; - - ip4_addr_set_u32(&IpAddr, Address->in_addr); - while (lwip_netif) - { + if (!AddrIsUnspecified(Address)) + { + /* Find the local interface for this address */ + struct netif* lwip_netif = netif_list; + ip_addr_t IpAddr; + + 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; - } - lwip_netif = lwip_netif->next; - } - - if (!lwip_netif) - { - DPRINT1("Cound not find an interface for address 0x%08x\n", AddressFile->Address.in_addr); - KeReleaseSpinLock(&AddressListLock, OldIrql); - return STATUS_INVALID_ADDRESS; - } - } + if (ip_addr_cmp(&IpAddr, &lwip_netif->ip_addr)) + { + break; + } + lwip_netif = lwip_netif->next; + } + + if (!lwip_netif) + { + DPRINT1("Cound not find an interface for address 0x%08x\n", AddressFile->Address.in_addr); + KeReleaseSpinLock(&AddressListLock, OldIrql); + return STATUS_INVALID_ADDRESS; + } + } DPRINT1("Allocate address file\n"); - /* Allocate our new address file */ - AddressFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(*AddressFile), TAG_ADDRESS_FILE); - if (!AddressFile) - { + /* Allocate our new address file */ + AddressFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(*AddressFile), TAG_ADDRESS_FILE); + if (!AddressFile) + { KeReleaseSpinLock(&AddressListLock, OldIrql); - return STATUS_NO_MEMORY; - } - - RtlZeroMemory(AddressFile, sizeof(*AddressFile)); + return STATUS_NO_MEMORY; + } + + RtlZeroMemory(AddressFile, sizeof(*AddressFile)); AddressFile->Type = TDI_TRANSPORT_ADDRESS_FILE; - AddressFile->RefCount = 1; - RtlCopyMemory(&AddressFile->Address, Address, sizeof(*Address)); - AddressFile->Protocol = Protocol; - if (!Address->sin_port) - AddressFile->Address.sin_port = lwip_htons(Port); - - /* Initialize the datagram request stuff */ - KeInitializeSpinLock(&AddressFile->RequestLock); - InitializeListHead(&AddressFile->RequestListHead); + AddressFile->RefCount = 1; + RtlCopyMemory(&AddressFile->Address, Address, sizeof(*Address)); + AddressFile->Protocol = Protocol; + if (!Address->sin_port) + AddressFile->Address.sin_port = lwip_htons(Port); + + /* Initialize the datagram request stuff */ + KeInitializeSpinLock(&AddressFile->RequestLock); + InitializeListHead(&AddressFile->RequestListHead); DPRINT1("Protocol-dependent operations\n"); - /* Give it an entity ID and open a PCB if needed. */ - switch (Protocol) - { - case IPPROTO_TCP: + /* Give it an entity ID and open a PCB if needed. */ + switch (Protocol) + { + case IPPROTO_TCP: { ip_addr_t IpAddr; - ip4_addr_set_u32(&IpAddr, AddressFile->Address.in_addr); - InsertEntityInstance(CO_TL_ENTITY, &AddressFile->Instance); + ip4_addr_set_u32(&IpAddr, AddressFile->Address.in_addr); + InsertEntityInstance(CO_TL_ENTITY, &AddressFile->Instance); AddressFile->ContextCount = 0; AddressFile->lwip_tcp_pcb = tcp_new(); InterlockedIncrement(&PcbCount); DPRINT1("\n PCB Count: %d\n", PcbCount); tcp_arg(AddressFile->lwip_tcp_pcb, AddressFile); tcp_err(AddressFile->lwip_tcp_pcb, lwip_tcp_err_callback); - break; - } - case IPPROTO_UDP: - { - ip_addr_t IpAddr; - ip4_addr_set_u32(&IpAddr, AddressFile->Address.in_addr); - InsertEntityInstance(CL_TL_ENTITY, &AddressFile->Instance); - AddressFile->lwip_udp_pcb = udp_new(); - udp_bind(AddressFile->lwip_udp_pcb, &IpAddr, lwip_ntohs(AddressFile->Address.sin_port)); - ip_set_option(AddressFile->lwip_udp_pcb, SOF_BROADCAST); - /* Register our recv handler to lwip */ - udp_recv( - AddressFile->lwip_udp_pcb, - lwip_udp_ReceiveDatagram_callback, - AddressFile); - break; - } - default: - { - ip_addr_t IpAddr; - ip4_addr_set_u32(&IpAddr, AddressFile->Address.in_addr); - if (Protocol == IPPROTO_ICMP) - InsertEntityInstance(ER_ENTITY, &AddressFile->Instance); - else - InsertEntityInstance(CL_TL_ENTITY, &AddressFile->Instance); - AddressFile->lwip_raw_pcb = raw_new(Protocol); - raw_bind(AddressFile->lwip_raw_pcb, &IpAddr); - ip_set_option(AddressFile->lwip_raw_pcb, SOF_BROADCAST); - /* Register our recv handler for lwip */ - raw_recv( - AddressFile->lwip_raw_pcb, - lwip_raw_ReceiveDatagram_callback, - AddressFile); - break; - } - } + break; + } + case IPPROTO_UDP: + { + ip_addr_t IpAddr; + ip4_addr_set_u32(&IpAddr, AddressFile->Address.in_addr); + InsertEntityInstance(CL_TL_ENTITY, &AddressFile->Instance); + AddressFile->lwip_udp_pcb = udp_new(); + udp_bind(AddressFile->lwip_udp_pcb, &IpAddr, lwip_ntohs(AddressFile->Address.sin_port)); + ip_set_option(AddressFile->lwip_udp_pcb, SOF_BROADCAST); + /* Register our recv handler to lwip */ + udp_recv( + AddressFile->lwip_udp_pcb, + lwip_udp_ReceiveDatagram_callback, + AddressFile); + break; + } + default: + { + ip_addr_t IpAddr; + ip4_addr_set_u32(&IpAddr, AddressFile->Address.in_addr); + if (Protocol == IPPROTO_ICMP) + InsertEntityInstance(ER_ENTITY, &AddressFile->Instance); + else + InsertEntityInstance(CL_TL_ENTITY, &AddressFile->Instance); + AddressFile->lwip_raw_pcb = raw_new(Protocol); + raw_bind(AddressFile->lwip_raw_pcb, &IpAddr); + ip_set_option(AddressFile->lwip_raw_pcb, SOF_BROADCAST); + /* Register our recv handler for lwip */ + raw_recv( + AddressFile->lwip_raw_pcb, + lwip_raw_ReceiveDatagram_callback, + AddressFile); + break; + } + } DPRINT1("Insert into address list\n"); - /* Insert it into the list. */ - InsertTailList(&AddressListHead, &AddressFile->ListEntry); - KeReleaseSpinLock(&AddressListLock, OldIrql); + /* Insert it into the list. */ + InsertTailList(&AddressListHead, &AddressFile->ListEntry); + KeReleaseSpinLock(&AddressListLock, OldIrql); Success: - IrpSp->FileObject->FsContext = AddressFile; - IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE; - - return STATUS_SUCCESS; + IrpSp->FileObject->FsContext = AddressFile; + IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE; + + return STATUS_SUCCESS; } /* implementation in testing */ @@ -1138,25 +1165,27 @@ /* implementation in testing */ NTSTATUS TcpIpCloseAddress( - _Inout_ ADDRESS_FILE* AddressFile + _Inout_ ADDRESS_FILE* AddressFile ) { - KIRQL OldIrql; + KIRQL OldIrql; + NTSTATUS Status; err_t lwip_err; - /* Lock the global address list */ - KeAcquireSpinLock(&AddressListLock, &OldIrql); - - if (InterlockedDecrement(&AddressFile->RefCount) != 0) - { - /* There are still some open handles for this address */ - DPRINT1("TcpIpCloseAddress on address with open handles\n"); - KeReleaseSpinLock(&AddressListLock, OldIrql); - return STATUS_SUCCESS; - } - - /* remove the lwip pcb */ + /* Lock the global address list */ + KeAcquireSpinLock(&AddressListLock, &OldIrql); + + InterlockedDecrement(&AddressFile->RefCount); + if (AddressFile->RefCount != 0) + { + /* There are still some open handles for this address */ + DPRINT1("TcpIpCloseAddress on address with %d open handles\n", AddressFile->RefCount); + KeReleaseSpinLock(&AddressListLock, OldIrql); + return STATUS_SUCCESS; + } + + /* remove the lwip pcb */ switch (AddressFile->Protocol) { case IPPROTO_UDP : @@ -1166,6 +1195,7 @@ if (AddressFile->ContextCount != 0) { DPRINT1("Calling close on TCP address with open contexts\n"); + // Should never happen due to how callers are written. KeReleaseSpinLock(&AddressListLock, OldIrql); return STATUS_INVALID_PARAMETER; } @@ -1177,6 +1207,7 @@ } else { + tcp_arg(AddressFile->lwip_tcp_pcb, NULL); tcp_abort(AddressFile->lwip_tcp_pcb); lwip_err = ERR_OK; } @@ -1185,29 +1216,35 @@ if (lwip_err != ERR_OK) { DPRINT1("lwIP tcp_close error: %d", lwip_err); - KeReleaseSpinLock(&AddressListLock, OldIrql); - return STATUS_UNSUCCESSFUL; + // TODO: better return code + Status = STATUS_UNSUCCESSFUL; } + Status = STATUS_SUCCESS; + break; } break; case IPPROTO_RAW : raw_remove(AddressFile->lwip_raw_pcb); + Status = STATUS_SUCCESS; break; default : DPRINT1("Unknown protocol\n"); - KeReleaseSpinLock(&AddressListLock, OldIrql); - return STATUS_INVALID_ADDRESS; - } - - /* Remove from the list and free the structure */ - RemoveEntryList(&AddressFile->ListEntry); - KeReleaseSpinLock(&AddressListLock, OldIrql); - - RemoveEntityInstance(&AddressFile->Instance); - - ExFreePoolWithTag(AddressFile, TAG_ADDRESS_FILE); - - return STATUS_SUCCESS; + // Should never happen due to how callers are written. + // This case is particularly bad since we don't know what needs + // to be deallocated at all. + Status = STATUS_INVALID_ADDRESS; + break; + } + + /* Remove from the list and free the structure */ + RemoveEntryList(&AddressFile->ListEntry); + KeReleaseSpinLock(&AddressListLock, OldIrql); + + RemoveEntityInstance(&AddressFile->Instance); + + ExFreePoolWithTag(AddressFile, TAG_ADDRESS_FILE); + + return Status; } /* implementation in testing */ @@ -1218,6 +1255,7 @@ err_t lwip_err; PLIST_ENTRY Head; PLIST_ENTRY Entry; + PADDRESS_FILE AddressFile; PTCP_REQUEST Request; PIRP Irp; PIO_STACK_LOCATION IrpSp; @@ -1229,7 +1267,7 @@ DPRINT1("Invalid protocol\n"); return STATUS_INVALID_PARAMETER; } - if (Context->AddressFile) + if (!(Context->TcpState & TCP_STATE_DISASSOCIATED)) { DPRINT1("Context retains association\n"); return STATUS_UNSUCCESSFUL; @@ -1245,6 +1283,7 @@ } else { + tcp_arg(Context->lwip_tcp_pcb, NULL); tcp_abort(Context->lwip_tcp_pcb); lwip_err = ERR_OK; } @@ -1284,7 +1323,16 @@ KeReleaseSpinLock(&Context->RequestListLock, OldIrql); + AddressFile = Context->AddressFile; + ExFreePoolWithTag(Context, TAG_TCP_CONTEXT); + + if (AddressFile->ContextCount == 0) + { + DPRINT1("Closing Address File at %p from TcpIpCloseContext on Context at %p\n", + AddressFile, Context); + return TcpIpCloseAddress(AddressFile); + } return STATUS_SUCCESS; } @@ -1292,73 +1340,73 @@ static NTSTATUS ExtractAddressFromList( - _In_ PTRANSPORT_ADDRESS AddressList, - _Out_ PTDI_ADDRESS_IP Address) -{ - PTA_ADDRESS CurrentAddress; - INT i; - - CurrentAddress = &AddressList->Address[0]; - - /* We can only use IP addresses. Search the list until we find one */ - for (i = 0; i < AddressList->TAAddressCount; i++) - { - if (CurrentAddress->AddressType == TDI_ADDRESS_TYPE_IP) - { - if (CurrentAddress->AddressLength == TDI_ADDRESS_LENGTH_IP) - { - /* This is an IPv4 address */ - RtlCopyMemory(Address, &CurrentAddress->Address[0], CurrentAddress->AddressLength); - return STATUS_SUCCESS; - } - } - CurrentAddress = (PTA_ADDRESS)&CurrentAddress->Address[CurrentAddress->AddressLength]; - } - return STATUS_INVALID_ADDRESS; + _In_ PTRANSPORT_ADDRESS AddressList, + _Out_ PTDI_ADDRESS_IP Address) +{ + PTA_ADDRESS CurrentAddress; + INT i; + + CurrentAddress = &AddressList->Address[0]; + + /* We can only use IP addresses. Search the list until we find one */ + for (i = 0; i < AddressList->TAAddressCount; i++) + { + if (CurrentAddress->AddressType == TDI_ADDRESS_TYPE_IP) + { + if (CurrentAddress->AddressLength == TDI_ADDRESS_LENGTH_IP) + { + /* This is an IPv4 address */ + RtlCopyMemory(Address, &CurrentAddress->Address[0], CurrentAddress->AddressLength); + return STATUS_SUCCESS; + } + } + CurrentAddress = (PTA_ADDRESS)&CurrentAddress->Address[CurrentAddress->AddressLength]; + } + return STATUS_INVALID_ADDRESS; } static VOID NTAPI CancelReceiveDatagram( - _Inout_ struct _DEVICE_OBJECT* DeviceObject, - _Inout_ _IRQL_uses_cancel_ struct _IRP *Irp) -{ - PIO_STACK_LOCATION IrpSp; - ADDRESS_FILE* AddressFile; - RECEIVE_DATAGRAM_REQUEST* Request; - LIST_ENTRY* ListEntry; - KIRQL OldIrql; - - IoReleaseCancelSpinLock(Irp->CancelIrql); - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - AddressFile = IrpSp->FileObject->FsContext; - - /* Find this IRP in the list of requests */ - KeAcquireSpinLock(&AddressFile->RequestLock, &OldIrql); - ListEntry = AddressFile->RequestListHead.Flink; - while (ListEntry != &AddressFile->RequestListHead) - { - Request = CONTAINING_RECORD(ListEntry, RECEIVE_DATAGRAM_REQUEST, ListEntry); - if (Request->Irp == Irp) - break; - ListEntry = ListEntry->Flink; - } - - /* We must have found it */ - NT_ASSERT(ListEntry != &AddressFile->RequestListHead); - - RemoveEntryList(&Request->ListEntry); - - Irp->IoStatus.Status = STATUS_CANCELLED; - Irp->IoStatus.Information = 0; - - KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); - - IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); - - ExFreePoolWithTag(Request, TAG_DGRAM_REQST); + _Inout_ struct _DEVICE_OBJECT* DeviceObject, + _Inout_ _IRQL_uses_cancel_ struct _IRP *Irp) +{ + PIO_STACK_LOCATION IrpSp; + ADDRESS_FILE* AddressFile; + RECEIVE_DATAGRAM_REQUEST* Request; + LIST_ENTRY* ListEntry; + KIRQL OldIrql; + + IoReleaseCancelSpinLock(Irp->CancelIrql); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + AddressFile = IrpSp->FileObject->FsContext; + + /* Find this IRP in the list of requests */ + KeAcquireSpinLock(&AddressFile->RequestLock, &OldIrql); + ListEntry = AddressFile->RequestListHead.Flink; + while (ListEntry != &AddressFile->RequestListHead) + { + Request = CONTAINING_RECORD(ListEntry, RECEIVE_DATAGRAM_REQUEST, ListEntry); + if (Request->Irp == Irp) + break; + ListEntry = ListEntry->Flink; + } + + /* We must have found it */ + NT_ASSERT(ListEntry != &AddressFile->RequestListHead); + + RemoveEntryList(&Request->ListEntry); + + KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); + + Irp->IoStatus.Status = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + + ExFreePoolWithTag(Request, TAG_DGRAM_REQST); } /* implementation in testing */ @@ -1370,6 +1418,7 @@ PTCP_CONTEXT Context; PTDI_REQUEST_KERNEL_CONNECT Parameters; PTRANSPORT_ADDRESS RemoteTransportAddress; + KIRQL OldIrql; struct sockaddr *SocketAddressRemote; struct sockaddr_in *SocketAddressInRemote; @@ -1412,10 +1461,13 @@ Context->lwip_tcp_pcb->local_ip, Context->lwip_tcp_pcb->local_port); + DPRINT1("Call into lwIP tcp_connect(). Context at %p, pcb at %p\n", + Context, Context->lwip_tcp_pcb); lwip_err = tcp_connect(Context->lwip_tcp_pcb, (ip_addr_t *)&SocketAddressInRemote->sin_addr.s_addr, SocketAddressInRemote->sin_port, lwip_tcp_connected_callback); + DPRINT1("Return from lwIP tcp_connect()\n"); switch (lwip_err) { case (ERR_VAL) : @@ -1454,6 +1506,7 @@ } case (ERR_OK) : { + KeAcquireSpinLock(&Context->RequestListLock, &OldIrql); PrepareIrpForCancel( Irp, CancelRequestRoutine, @@ -1461,6 +1514,7 @@ TCP_REQUEST_PENDING_GENERAL); tcp_arg(Context->lwip_tcp_pcb, Context); Context->TcpState = TCP_STATE_CONNECTING; + KeReleaseSpinLock(&Context->RequestListLock, OldIrql); return STATUS_PENDING; } default : @@ -1662,12 +1716,13 @@ if (Request->PendingIrp) { IrpSp = IoGetCurrentIrpStackLocation(Request->PendingIrp); - DPRINT1("Pending IRP Control Code: %08x\n", IrpSp->MinorFunction); + DPRINT1("Pending IRP MonorFunction: %08x\n", IrpSp->MinorFunction); } else { DPRINT1("IRP is NULL\n"); } + Entry = Entry->Flink; } } KeReleaseSpinLock(&Context->RequestListLock, OldIrql); @@ -1675,13 +1730,8 @@ KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql); RemoveEntryList(&Context->ListEntry); AddressFile->ContextCount--; - Context->AddressFile = NULL; + Context->TcpState |= TCP_STATE_DISASSOCIATED; KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql); - - if (AddressFile->ContextCount == 0) - { - return TcpIpCloseAddress(AddressFile); - } return STATUS_SUCCESS; } @@ -1738,12 +1788,14 @@ } KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql); + KeAcquireSpinLock(&Context->RequestListLock, &OldIrql); PrepareIrpForCancel( Irp, CancelRequestRoutine, TCP_REQUEST_CANCEL_MODE_CLOSE, TCP_REQUEST_PENDING_GENERAL); Context->TcpState = TCP_STATE_LISTENING; + KeReleaseSpinLock(&Context->RequestListLock, OldIrql); return STATUS_PENDING; } @@ -1861,10 +1913,11 @@ { PIO_STACK_LOCATION IrpSp; PTCP_CONTEXT Context; + KIRQL OldIrql; PTDI_REQUEST_KERNEL_RECEIVE RequestInfo; - DPRINT1("Receive IRP Address: %08x\n", Irp); + DPRINT1("Receive IRP Address: %p\n", Irp); IrpSp = IoGetCurrentIrpStackLocation(Irp); @@ -1880,6 +1933,8 @@ { RequestInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&IrpSp->Parameters; DPRINT1("\n Request Length = %d\n", RequestInfo->ReceiveLength); + + KeAcquireSpinLock(&Context->RequestListLock, &OldIrql); PrepareIrpForCancel( Irp, @@ -1894,6 +1949,7 @@ Context->TcpState |= TCP_STATE_RECEIVING; } + KeReleaseSpinLock(&Context->RequestListLock, OldIrql); return STATUS_PENDING; } DPRINT1("Invalid TCP state: %d\n", Context->TcpState); @@ -1903,275 +1959,275 @@ NTSTATUS TcpIpReceiveDatagram( - _Inout_ PIRP Irp) -{ - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - ADDRESS_FILE *AddressFile; - RECEIVE_DATAGRAM_REQUEST* Request = NULL; - PTDI_REQUEST_KERNEL_RECEIVEDG RequestInfo; - NTSTATUS Status; - - /* Check this is really an address file */ - if ((ULONG_PTR)IrpSp->FileObject->FsContext2 != TDI_TRANSPORT_ADDRESS_FILE) - { - Status = STATUS_FILE_INVALID; - goto Failure; - } - - /* Get the address file */ - AddressFile = IrpSp->FileObject->FsContext; - - if (AddressFile->Protocol == IPPROTO_TCP) - { - /* TCP has no such thing as datagrams */ - DPRINT1("Received TDI_RECEIVE_DATAGRAM for a TCP adress file.\n"); - Status = STATUS_INVALID_ADDRESS; - goto Failure; - } - - /* Queue the request */ - Request = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Request), TAG_DGRAM_REQST); - if (!Request) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Failure; - } - RtlZeroMemory(Request, sizeof(*Request)); - Request->Irp = Irp; - - /* Get details about what we should be receiving */ - RequestInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&IrpSp->Parameters; - - /* Get the address */ - if (RequestInfo->ReceiveDatagramInformation->RemoteAddressLength != 0) - { - Status = ExtractAddressFromList( - RequestInfo->ReceiveDatagramInformation->RemoteAddress, - &Request->RemoteAddress); - if (!NT_SUCCESS(Status)) - goto Failure; - } - - DPRINT1("Queuing datagram receive on address 0x%08x, port %u.\n", - Request->RemoteAddress.in_addr, Request->RemoteAddress.sin_port); - - /* Get the buffer */ - Request->Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); - Request->BufferLength = MmGetMdlByteCount(Irp->MdlAddress); - - Request->ReturnInfo = RequestInfo->ReturnDatagramInformation; - - /* Mark pending */ - Irp->IoStatus.Status = STATUS_PENDING; - IoMarkIrpPending(Irp); - IoSetCancelRoutine(Irp, CancelReceiveDatagram); - - /* We're ready to go */ - ExInterlockedInsertTailList( - &AddressFile->RequestListHead, - &Request->ListEntry, - &AddressFile->RequestLock); - - return STATUS_PENDING; + _Inout_ PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + ADDRESS_FILE *AddressFile; + RECEIVE_DATAGRAM_REQUEST* Request = NULL; + PTDI_REQUEST_KERNEL_RECEIVEDG RequestInfo; + NTSTATUS Status; + + /* Check this is really an address file */ + if ((ULONG_PTR)IrpSp->FileObject->FsContext2 != TDI_TRANSPORT_ADDRESS_FILE) + { + Status = STATUS_FILE_INVALID; + goto Failure; + } + + /* Get the address file */ + AddressFile = IrpSp->FileObject->FsContext; + + if (AddressFile->Protocol == IPPROTO_TCP) + { + /* TCP has no such thing as datagrams */ + DPRINT1("Received TDI_RECEIVE_DATAGRAM for a TCP adress file.\n"); + Status = STATUS_INVALID_ADDRESS; + goto Failure; + } + + /* Queue the request */ + Request = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Request), TAG_DGRAM_REQST); + if (!Request) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Failure; + } + RtlZeroMemory(Request, sizeof(*Request)); + Request->Irp = Irp; + + /* Get details about what we should be receiving */ + RequestInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&IrpSp->Parameters; + + /* Get the address */ + if (RequestInfo->ReceiveDatagramInformation->RemoteAddressLength != 0) + { + Status = ExtractAddressFromList( + RequestInfo->ReceiveDatagramInformation->RemoteAddress, + &Request->RemoteAddress); + if (!NT_SUCCESS(Status)) + goto Failure; + } + + DPRINT1("Queuing datagram receive on address 0x%08x, port %u.\n", + Request->RemoteAddress.in_addr, Request->RemoteAddress.sin_port); + + /* Get the buffer */ + Request->Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + Request->BufferLength = MmGetMdlByteCount(Irp->MdlAddress); + + Request->ReturnInfo = RequestInfo->ReturnDatagramInformation; + + /* Mark pending */ + Irp->IoStatus.Status = STATUS_PENDING; + IoMarkIrpPending(Irp); + IoSetCancelRoutine(Irp, CancelReceiveDatagram); + + /* We're ready to go */ + ExInterlockedInsertTailList( + &AddressFile->RequestListHead, + &Request->ListEntry, + &AddressFile->RequestLock); + + return STATUS_PENDING; Failure: - if (Request) - ExFreePoolWithTag(Request, TAG_DGRAM_REQST); - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); - return Status; + if (Request) + ExFreePoolWithTag(Request, TAG_DGRAM_REQST); + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + return Status; } NTSTATUS TcpIpSendDatagram( - _Inout_ PIRP Irp) -{ - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - ADDRESS_FILE *AddressFile; - PTDI_REQUEST_KERNEL_SENDDG RequestInfo; - NTSTATUS Status; - ip_addr_t IpAddr; - u16_t Port; - PVOID Buffer; - ULONG BufferLength; - struct pbuf* p = NULL; - err_t lwip_error; - - /* Check this is really an address file */ - if ((ULONG_PTR)IrpSp->FileObject->FsContext2 != TDI_TRANSPORT_ADDRESS_FILE) - { - Status = STATUS_FILE_INVALID; - goto Finish; - } - - /* Get the address file */ - AddressFile = IrpSp->FileObject->FsContext; - - if (AddressFile->Protocol == IPPROTO_TCP) - { - /* TCP has no such thing as datagrams */ - DPRINT1("Received TDI_SEND_DATAGRAM for a TCP adress file.\n"); - Status = STATUS_INVALID_ADDRESS; - goto Finish; - } - - /* Get details about what we should be receiving */ - RequestInfo = (PTDI_REQUEST_KERNEL_SENDDG)&IrpSp->Parameters; - - /* Get the address */ - if (RequestInfo->SendDatagramInformation->RemoteAddressLength != 0) - { - TDI_ADDRESS_IP Address; - Status = ExtractAddressFromList( - RequestInfo->SendDatagramInformation->RemoteAddress, - &Address); - if (!NT_SUCCESS(Status)) - goto Finish; - ip4_addr_set_u32(&IpAddr, Address.in_addr); - Port = lwip_ntohs(Address.sin_port); - } - else - { - ip_addr_set_any(&IpAddr); - Port = 0; - } - - DPRINT1("Sending datagram to address 0x%08x, port %u\n", ip4_addr_get_u32(&IpAddr), lwip_ntohs(Port)); - - /* Get the buffer */ - Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); - BufferLength = MmGetMdlByteCount(Irp->MdlAddress); - p = pbuf_alloc(PBUF_RAW, BufferLength, PBUF_REF); - if (!p) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Finish; - } - p->payload = Buffer; - - /* Send it for real */ - switch (AddressFile->Protocol) - { - case IPPROTO_UDP: - if (((ip4_addr_get_u32(&IpAddr) == IPADDR_ANY) || - (ip4_addr_get_u32(&IpAddr) == IPADDR_BROADCAST)) && - (Port == 67) && (AddressFile->Address.in_addr == 0)) - { - struct netif* lwip_netif = netif_list; - - /* - * This is a DHCP packet for an address file with address 0.0.0.0. - * Try to find an ethernet interface with no address set, - * and send the packet through it. - */ - while (lwip_netif != NULL) - { - if (ip4_addr_get_u32(&lwip_netif->ip_addr) == 0) - break; - lwip_netif = lwip_netif->next; - } - - if (lwip_netif == NULL) - { - /* Do a regular send. (This will most likely fail) */ - lwip_error = udp_sendto(AddressFile->lwip_udp_pcb, p, &IpAddr, Port); - } - else - { - /* We found an interface with address being 0.0.0.0 */ - lwip_error = udp_sendto_if(AddressFile->lwip_udp_pcb, p, &IpAddr, Port, lwip_netif); - } - } - else - { - lwip_error = udp_sendto(AddressFile->lwip_udp_pcb, p, &IpAddr, Port); - } - break; - default: - lwip_error = raw_sendto(AddressFile->lwip_raw_pcb, p, &IpAddr); - break; - } - - switch (lwip_error) - { - case ERR_OK: - Status = STATUS_SUCCESS; - Irp->IoStatus.Information = BufferLength; - break; - case ERR_MEM: - case ERR_BUF: - DPRINT1("Received ERR_MEM from lwip.\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - break; - case ERR_RTE: - DPRINT1("Received ERR_RTE from lwip.\n"); - Status = STATUS_INVALID_ADDRESS; - break; - case ERR_VAL: - DPRINT1("Received ERR_VAL from lwip.\n"); - Status = STATUS_INVALID_PARAMETER; - break; - default: - DPRINT1("Received error %d from lwip.\n", lwip_error); - Status = STATUS_UNEXPECTED_NETWORK_ERROR; - } + _Inout_ PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + ADDRESS_FILE *AddressFile; + PTDI_REQUEST_KERNEL_SENDDG RequestInfo; + NTSTATUS Status; + ip_addr_t IpAddr; + u16_t Port; + PVOID Buffer; + ULONG BufferLength; + struct pbuf* p = NULL; + err_t lwip_error; + + /* Check this is really an address file */ + if ((ULONG_PTR)IrpSp->FileObject->FsContext2 != TDI_TRANSPORT_ADDRESS_FILE) + { + Status = STATUS_FILE_INVALID; + goto Finish; + } + + /* Get the address file */ + AddressFile = IrpSp->FileObject->FsContext; + + if (AddressFile->Protocol == IPPROTO_TCP) + { + /* TCP has no such thing as datagrams */ + DPRINT1("Received TDI_SEND_DATAGRAM for a TCP adress file.\n"); + Status = STATUS_INVALID_ADDRESS; + goto Finish; + } + + /* Get details about what we should be receiving */ + RequestInfo = (PTDI_REQUEST_KERNEL_SENDDG)&IrpSp->Parameters; + + /* Get the address */ + if (RequestInfo->SendDatagramInformation->RemoteAddressLength != 0) + { + TDI_ADDRESS_IP Address; + Status = ExtractAddressFromList( + RequestInfo->SendDatagramInformation->RemoteAddress, + &Address); + if (!NT_SUCCESS(Status)) + goto Finish; + ip4_addr_set_u32(&IpAddr, Address.in_addr); + Port = lwip_ntohs(Address.sin_port); + } + else + { + ip_addr_set_any(&IpAddr); + Port = 0; + } + + DPRINT1("Sending datagram to address 0x%08x, port %u\n", ip4_addr_get_u32(&IpAddr), lwip_ntohs(Port)); + + /* Get the buffer */ + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + BufferLength = MmGetMdlByteCount(Irp->MdlAddress); + p = pbuf_alloc(PBUF_RAW, BufferLength, PBUF_REF); + if (!p) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Finish; + } + p->payload = Buffer; + + /* Send it for real */ + switch (AddressFile->Protocol) + { + case IPPROTO_UDP: + if (((ip4_addr_get_u32(&IpAddr) == IPADDR_ANY) || + (ip4_addr_get_u32(&IpAddr) == IPADDR_BROADCAST)) && + (Port == 67) && (AddressFile->Address.in_addr == 0)) + { + struct netif* lwip_netif = netif_list; + + /* + * This is a DHCP packet for an address file with address 0.0.0.0. + * Try to find an ethernet interface with no address set, + * and send the packet through it. + */ + while (lwip_netif != NULL) + { + if (ip4_addr_get_u32(&lwip_netif->ip_addr) == 0) + break; + lwip_netif = lwip_netif->next; + } + + if (lwip_netif == NULL) + { + /* Do a regular send. (This will most likely fail) */ + lwip_error = udp_sendto(AddressFile->lwip_udp_pcb, p, &IpAddr, Port); + } + else + { + /* We found an interface with address being 0.0.0.0 */ + lwip_error = udp_sendto_if(AddressFile->lwip_udp_pcb, p, &IpAddr, Port, lwip_netif); + } + } + else + { + lwip_error = udp_sendto(AddressFile->lwip_udp_pcb, p, &IpAddr, Port); + } + break; + default: + lwip_error = raw_sendto(AddressFile->lwip_raw_pcb, p, &IpAddr); + break; + } + + switch (lwip_error) + { + case ERR_OK: + Status = STATUS_SUCCESS; + Irp->IoStatus.Information = BufferLength; + break; + case ERR_MEM: + case ERR_BUF: + DPRINT1("Received ERR_MEM from lwip.\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + case ERR_RTE: + DPRINT1("Received ERR_RTE from lwip.\n"); + Status = STATUS_INVALID_ADDRESS; + break; + case ERR_VAL: + DPRINT1("Received ERR_VAL from lwip.\n"); + Status = STATUS_INVALID_PARAMETER; + break; + default: + DPRINT1("Received error %d from lwip.\n", lwip_error); + Status = STATUS_UNEXPECTED_NETWORK_ERROR; + } Finish: - if (p) - pbuf_free(p); - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); - return Status; + if (p) + pbuf_free(p); + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + return Status; } NTSTATUS AddressSetIpDontFragment( - _In_ TDIEntityID ID, - _In_ PVOID InBuffer, - _In_ ULONG BufferSize) -{ - /* Silently ignore. - * lwip doesn't have such thing, and already tries to fragment data as less as possible */ - return STATUS_SUCCESS; + _In_ TDIEntityID ID, + _In_ PVOID InBuffer, + _In_ ULONG BufferSize) +{ + /* Silently ignore. + * lwip doesn't have such thing, and already tries to fragment data as less as possible */ + return STATUS_SUCCESS; } NTSTATUS AddressSetTtl( - _In_ TDIEntityID ID, - _In_ PVOID InBuffer, - _In_ ULONG BufferSize) -{ - ADDRESS_FILE* AddressFile; - TCPIP_INSTANCE* Instance; - NTSTATUS Status; - ULONG Value; - - if (BufferSize < sizeof(ULONG)) - return STATUS_BUFFER_TOO_SMALL; - - /* Get the address file */ - Status = GetInstance(ID, &Instance); - if (!NT_SUCCESS(Status)) - return Status; - - AddressFile = CONTAINING_RECORD(Instance, ADDRESS_FILE, Instance); - - /* Get the value */ - Value = *((ULONG*)InBuffer); - - switch (AddressFile->Protocol) - { - case IPPROTO_TCP: - DPRINT1("TCP not supported yet.\n"); - break; - case IPPROTO_UDP: - AddressFile->lwip_udp_pcb->ttl = Value; - break; - default: - AddressFile->lwip_raw_pcb->ttl = Value; - break; - } - - return STATUS_SUCCESS; -} + _In_ TDIEntityID ID, + _In_ PVOID InBuffer, + _In_ ULONG BufferSize) +{ + ADDRESS_FILE* AddressFile; + TCPIP_INSTANCE* Instance; + NTSTATUS Status; + ULONG Value; + + if (BufferSize < sizeof(ULONG)) + return STATUS_BUFFER_TOO_SMALL; + + /* Get the address file */ + Status = GetInstance(ID, &Instance); + if (!NT_SUCCESS(Status)) + return Status; + + AddressFile = CONTAINING_RECORD(Instance, ADDRESS_FILE, Instance); + + /* Get the value */ + Value = *((ULONG*)InBuffer); + + switch (AddressFile->Protocol) + { + case IPPROTO_TCP: + DPRINT1("TCP not supported yet.\n"); + break; + case IPPROTO_UDP: + AddressFile->lwip_udp_pcb->ttl = Value; + break; + default: + AddressFile->lwip_raw_pcb->ttl = Value; + break; + } + + return STATUS_SUCCESS; +} Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h?rev=71865&r1=71864&r2=71865&view=diff ============================================================================== --- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h [iso-8859-1] Fri Jul 8 17:52:42 2016 @@ -9,18 +9,19 @@ #define TCP_REQUEST_PENDING_SEND 1 #define TCP_REQUEST_PENDING_RECEIVE 2 -#define TCP_STATE_CREATED 0x1 << 0 -#define TCP_STATE_BOUND 0x1 << 1 -#define TCP_STATE_LISTENING 0x1 << 2 -#define TCP_STATE_ACCEPTED 0x1 << 3 -#define TCP_STATE_RECEIVING 0x1 << 4 -#define TCP_STATE_ABORTED 0x1 << 5 -#define TCP_STATE_CONNECTING 0x1 << 6 -#define TCP_STATE_CONNECTED 0x1 << 7 -#define TCP_STATE_SENDING 0x1 << 8 +#define TCP_STATE_CREATED 0x1 << 0 +#define TCP_STATE_BOUND 0x1 << 1 +#define TCP_STATE_LISTENING 0x1 << 2 +#define TCP_STATE_ACCEPTED 0x1 << 3 +#define TCP_STATE_RECEIVING 0x1 << 4 +#define TCP_STATE_ABORTED 0x1 << 5 +#define TCP_STATE_CONNECTING 0x1 << 6 +#define TCP_STATE_CONNECTED 0x1 << 7 +#define TCP_STATE_SENDING 0x1 << 8 +#define TCP_STATE_DISASSOCIATED 0x1 << 9 typedef struct _ADDRESS_FILE { - UCHAR Type; + UCHAR Type; // must be the first member LIST_ENTRY ListEntry; LONG RefCount; LONG ContextCount; @@ -46,7 +47,7 @@ } ADDRESS_FILE, *PADDRESS_FILE; typedef struct _TCP_CONTEXT { - UCHAR Type; + UCHAR Type; // must be the first member LIST_ENTRY ListEntry; PADDRESS_FILE AddressFile; IPPROTO Protocol; Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c?rev=71865&r1=71864&r2=71865&view=diff ============================================================================== --- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c [iso-8859-1] Fri Jul 8 17:52:42 2016 @@ -360,7 +360,6 @@ { case TDI_TRANSPORT_ADDRESS_FILE: DPRINT1("TCPIP Close Transport Address\n"); - if (!IrpSp->FileObject->FsContext) { DPRINT1("TCPIP: Got a close request without a file to close!\n");