/* * @implemented */ NTSTATUS NTAPI RtlIpv4AddressToStringExA(IN struct in_addr *Address, IN USHORT Port, OUT PCHAR AddressString, IN OUT PULONG AddressStringLength) { CHAR Buffer[IPV4_ADDR_STRING_MAX_LEN+IPV4_PORT_STRING_MAX_LEN]; ULONG Length; if (!Address || !AddressString || !AddressStringLength) return STATUS_INVALID_PARAMETER; Length = sprintf(Buffer, "%u.%u.%u.%u", Address->S_un.S_un_b.s_b1, Address->S_un.S_un_b.s_b2, Address->S_un.S_un_b.s_b3, Address->S_un.S_un_b.s_b4); if (Port) Length += sprintf(Buffer + Length, ":%u", WN2H(Port)); if (*AddressStringLength > Length) { *AddressStringLength = Length + 1; strcpy(AddressString, Buffer); return STATUS_SUCCESS; } *AddressStringLength = Length + 1; return STATUS_INVALID_PARAMETER; }
/* * @implemented */ INT WSAAPI WSANtohs(IN SOCKET s, IN USHORT netshort, OUT USHORT FAR* lphostshort) { INT ErrorCode; PWSSOCKET Socket; DPRINT("WSANtohs: %p, %lx, %p\n", s, netshort, lphostshort); /* Check for WSAStartup */ if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS) { /* Make sure we got a parameter */ if (!lphostshort) { /* Fail */ SetLastError(WSAEFAULT); return SOCKET_ERROR; } /* Get the Socket Context */ if ((Socket = WsSockGetSocket(s))) { /* Check which byte order to use */ if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder == LITTLEENDIAN) { /* No conversion needed */ *lphostshort = netshort; } else { /* Use a swap */ *lphostshort = WN2H(netshort); } /* Dereference the socket */ WsSockDereference(Socket); /* Return success */ return ERROR_SUCCESS; } else { /* Set the error code */ ErrorCode = WSAENOTSOCK; } } /* Return with error */ SetLastError(ErrorCode); return SOCKET_ERROR; }
/* * FUNCTION: Open an address file object * ARGUMENTS: * Request = Pointer to TDI request structure for this request * Address = Pointer to address to be opened * Protocol = Protocol on which to open the address * Shared = Specifies if the address is opened for shared access * Options = Pointer to option buffer * RETURNS: * Status of operation */ NTSTATUS FileOpenAddress( PTDI_REQUEST Request, PTA_IP_ADDRESS Address, USHORT Protocol, BOOLEAN Shared, PVOID Options) { PADDRESS_FILE AddrFile; TI_DbgPrint(MID_TRACE, ("Called (Proto %d).\n", Protocol)); /* If it's shared and has a port specified, look for a match */ if ((Shared != FALSE) && (Address->Address[0].Address[0].sin_port != 0)) { AddrFile = AddrFindShared(NULL, Address->Address[0].Address[0].sin_port, Protocol); if (AddrFile != NULL) { Request->Handle.AddressHandle = AddrFile; return STATUS_SUCCESS; } } AddrFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(ADDRESS_FILE), ADDR_FILE_TAG); if (!AddrFile) { TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(AddrFile, sizeof(ADDRESS_FILE)); AddrFile->RefCount = 1; AddrFile->Free = AddrFileFree; AddrFile->Sharers = 1; /* Set our default options */ AddrFile->TTL = 128; AddrFile->DF = 0; AddrFile->BCast = 1; AddrFile->HeaderIncl = 1; /* Make sure address is a local unicast address or 0 */ /* FIXME: IPv4 only */ AddrFile->Family = Address->Address[0].AddressType; AddrFile->Address.Address.IPv4Address = Address->Address[0].Address[0].in_addr; AddrFile->Address.Type = IP_ADDRESS_V4; if (!AddrIsUnspecified(&AddrFile->Address) && !AddrLocateInterface(&AddrFile->Address)) { TI_DbgPrint(MIN_TRACE, ("Non-local address given (0x%X).\n", A2S(&AddrFile->Address))); ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG); return STATUS_INVALID_ADDRESS; } TI_DbgPrint(MID_TRACE, ("Opening address %s for communication (P=%d U=%d).\n", A2S(&AddrFile->Address), Protocol, IPPROTO_UDP)); /* Protocol specific handling */ switch (Protocol) { case IPPROTO_TCP: if (Address->Address[0].Address[0].sin_port) { /* The client specified an explicit port so we force a bind to this */ AddrFile->Port = TCPAllocatePort(Address->Address[0].Address[0].sin_port); /* Check for bind success */ if (AddrFile->Port == 0xffff) { ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG); return STATUS_ADDRESS_ALREADY_EXISTS; } /* Sanity check */ ASSERT(Address->Address[0].Address[0].sin_port == AddrFile->Port); } else if (!AddrIsUnspecified(&AddrFile->Address)) { /* The client is trying to bind to a local address so allocate a port now too */ AddrFile->Port = TCPAllocatePort(0); /* Check for bind success */ if (AddrFile->Port == 0xffff) { ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG); return STATUS_ADDRESS_ALREADY_EXISTS; } } else { /* The client wants an unspecified port with an unspecified address so we wait to see what the TCP library gives us */ AddrFile->Port = 0; } AddEntity(CO_TL_ENTITY, AddrFile, CO_TL_TCP); AddrFile->Send = NULL; /* TCPSendData */ break; case IPPROTO_UDP: TI_DbgPrint(MID_TRACE,("Allocating udp port\n")); AddrFile->Port = UDPAllocatePort(Address->Address[0].Address[0].sin_port); if ((Address->Address[0].Address[0].sin_port && AddrFile->Port != Address->Address[0].Address[0].sin_port) || AddrFile->Port == 0xffff) { ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG); return STATUS_ADDRESS_ALREADY_EXISTS; } TI_DbgPrint(MID_TRACE,("Setting port %d (wanted %d)\n", AddrFile->Port, Address->Address[0].Address[0].sin_port)); AddEntity(CL_TL_ENTITY, AddrFile, CL_TL_UDP); AddrFile->Send = UDPSendDatagram; break; case IPPROTO_ICMP: AddrFile->Port = 0; AddrFile->Send = ICMPSendDatagram; /* FIXME: Verify this */ AddEntity(ER_ENTITY, AddrFile, ER_ICMP); break; default: /* Use raw IP for all other protocols */ AddrFile->Port = 0; AddrFile->Send = RawIPSendDatagram; /* FIXME: Verify this */ AddEntity(CL_TL_ENTITY, AddrFile, 0); break; } TI_DbgPrint(MID_TRACE, ("IP protocol number for address file object is %d.\n", Protocol)); TI_DbgPrint(MID_TRACE, ("Port number for address file object is %d.\n", WN2H(AddrFile->Port))); /* Set protocol */ AddrFile->Protocol = Protocol; /* Initialize receive and transmit queues */ InitializeListHead(&AddrFile->ReceiveQueue); InitializeListHead(&AddrFile->TransmitQueue); /* Initialize spin lock that protects the address file object */ KeInitializeSpinLock(&AddrFile->Lock); /* Return address file object */ Request->Handle.AddressHandle = AddrFile; /* Add address file to global list */ ExInterlockedInsertTailList( &AddressFileListHead, &AddrFile->ListEntry, &AddressFileListLock); TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); return STATUS_SUCCESS; }
/* * FUNCTION: Searches through address file entries to find next match * ARGUMENTS: * SearchContext = Pointer to search context * RETURNS: * Pointer to referenced address file, NULL if none was found */ PADDRESS_FILE AddrSearchNext( PAF_SEARCH SearchContext) { PLIST_ENTRY CurrentEntry; PIP_ADDRESS IPAddress; KIRQL OldIrql; PADDRESS_FILE Current = NULL; BOOLEAN Found = FALSE; PADDRESS_FILE StartingAddrFile; TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql); if (SearchContext->Next == &AddressFileListHead) { TcpipReleaseSpinLock(&AddressFileListLock, OldIrql); return NULL; } /* Save this pointer so we can dereference it later */ StartingAddrFile = CONTAINING_RECORD(SearchContext->Next, ADDRESS_FILE, ListEntry); CurrentEntry = SearchContext->Next; while (CurrentEntry != &AddressFileListHead) { Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_FILE, ListEntry); IPAddress = &Current->Address; TI_DbgPrint(DEBUG_ADDRFILE, ("Comparing: ((%d, %d, %s), (%d, %d, %s)).\n", WN2H(Current->Port), Current->Protocol, A2S(IPAddress), WN2H(SearchContext->Port), SearchContext->Protocol, A2S(SearchContext->Address))); /* See if this address matches the search criteria */ if ((Current->Port == SearchContext->Port) && (Current->Protocol == SearchContext->Protocol) && (AddrReceiveMatch(IPAddress, SearchContext->Address))) { /* We've found a match */ Found = TRUE; break; } CurrentEntry = CurrentEntry->Flink; } if (Found) { SearchContext->Next = CurrentEntry->Flink; if (SearchContext->Next != &AddressFileListHead) { /* Reference the next address file to prevent the link from disappearing behind our back */ ReferenceObject(CONTAINING_RECORD(SearchContext->Next, ADDRESS_FILE, ListEntry)); } /* Reference the returned address file before dereferencing the starting * address file because it may be that Current == StartingAddrFile */ ReferenceObject(Current); } else Current = NULL; DereferenceObject(StartingAddrFile); TcpipReleaseSpinLock(&AddressFileListLock, OldIrql); return Current; }
VOID LogActiveObjects(VOID) { #ifdef LOG_OBJECTS PLIST_ENTRY CurrentEntry; KIRQL OldIrql; PADDRESS_FILE AddrFile; PCONNECTION_ENDPOINT Conn; DbgPrint("----------- TCP/IP Active Object Dump -------------\n"); TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql); CurrentEntry = AddressFileListHead.Flink; while (CurrentEntry != &AddressFileListHead) { AddrFile = CONTAINING_RECORD(CurrentEntry, ADDRESS_FILE, ListEntry); DbgPrint("Address File (%s, %d, %d) @ 0x%p | Ref count: %d | Sharers: %d\n", A2S(&AddrFile->Address), WN2H(AddrFile->Port), AddrFile->Protocol, AddrFile, AddrFile->RefCount, AddrFile->Sharers); DbgPrint("\tListener: "); if (AddrFile->Listener == NULL) DbgPrint("<None>\n"); else DbgPrint("0x%p\n", AddrFile->Listener); DbgPrint("\tAssociated endpoints: "); if (AddrFile->Connection == NULL) DbgPrint("<None>\n"); else { Conn = AddrFile->Connection; while (Conn) { DbgPrint("0x%p ", Conn); Conn = Conn->Next; } DbgPrint("\n"); } CurrentEntry = CurrentEntry->Flink; } TcpipReleaseSpinLock(&AddressFileListLock, OldIrql); TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql); CurrentEntry = ConnectionEndpointListHead.Flink; while (CurrentEntry != &ConnectionEndpointListHead) { Conn = CONTAINING_RECORD(CurrentEntry, CONNECTION_ENDPOINT, ListEntry); DbgPrint("Connection @ 0x%p | Ref count: %d\n", Conn, Conn->RefCount); DbgPrint("\tPCB: "); if (Conn->SocketContext == NULL) DbgPrint("<None>\n"); else { DbgPrint("0x%p\n", Conn->SocketContext); LibTCPDumpPcb(Conn->SocketContext); } DbgPrint("\tPacket queue status: %s\n", IsListEmpty(&Conn->PacketQueue) ? "Empty" : "Not Empty"); DbgPrint("\tRequest lists: Connect: %s | Recv: %s | Send: %s | Shutdown: %s | Listen: %s\n", IsListEmpty(&Conn->ConnectRequest) ? "Empty" : "Not Empty", IsListEmpty(&Conn->ReceiveRequest) ? "Empty" : "Not Empty", IsListEmpty(&Conn->SendRequest) ? "Empty" : "Not Empty", IsListEmpty(&Conn->ShutdownRequest) ? "Empty" : "Not Empty", IsListEmpty(&Conn->ListenRequest) ? "Empty" : "Not Empty"); DbgPrint("\tSend shutdown: %s\n", Conn->SendShutdown ? "Yes" : "No"); DbgPrint("\tReceive shutdown: %s\n", Conn->ReceiveShutdown ? "Yes" : "No"); if (Conn->ReceiveShutdown) DbgPrint("\tReceive shutdown status: 0x%x\n", Conn->ReceiveShutdownStatus); DbgPrint("\tClosing: %s\n", Conn->Closing ? "Yes" : "No"); CurrentEntry = CurrentEntry->Flink; } TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql); DbgPrint("---------------------------------------------------\n"); #endif }
/* * @implemented */ USHORT WSAAPI ntohs(IN USHORT netshort) { return WN2H(netshort); }
unsigned short L2PNet_ntohs( unsigned short netshort ) { return WN2H(netshort); }
VOID ARPReceive( PVOID Context, PIP_PACKET Packet) /* * FUNCTION: Receives an ARP packet * ARGUMENTS: * Context = Pointer to context information (IP_INTERFACE) * Packet = Pointer to packet */ { PARP_HEADER Header; IP_ADDRESS SrcAddress; IP_ADDRESS DstAddress; PCHAR SenderHWAddress, SenderProtoAddress, TargetProtoAddress; PNEIGHBOR_CACHE_ENTRY NCE; PNDIS_PACKET NdisPacket; PIP_INTERFACE Interface = (PIP_INTERFACE)Context; ULONG BytesCopied, DataSize; PCHAR DataBuffer; PAGED_CODE(); TI_DbgPrint(DEBUG_ARP, ("Called.\n")); Packet->Header = ExAllocatePoolWithTag(PagedPool, sizeof(ARP_HEADER), PACKET_BUFFER_TAG); if (!Packet->Header) { TI_DbgPrint(DEBUG_ARP, ("Unable to allocate header buffer\n")); Packet->Free(Packet); return; } Packet->MappedHeader = FALSE; BytesCopied = CopyPacketToBuffer((PCHAR)Packet->Header, Packet->NdisPacket, Packet->Position, sizeof(ARP_HEADER)); if (BytesCopied != sizeof(ARP_HEADER)) { TI_DbgPrint(DEBUG_ARP, ("Unable to copy in header buffer\n")); Packet->Free(Packet); return; } Header = (PARP_HEADER)Packet->Header; /* FIXME: Ethernet only */ if (WN2H(Header->HWType) != 1) { TI_DbgPrint(DEBUG_ARP, ("Unknown ARP hardware type (0x%X).\n", WN2H(Header->HWType))); Packet->Free(Packet); return; } /* Check protocol type */ if (Header->ProtoType != ETYPE_IPv4) { TI_DbgPrint(DEBUG_ARP, ("Unknown ARP protocol type (0x%X).\n", WN2H(Header->ProtoType))); Packet->Free(Packet); return; } DataSize = (2 * Header->HWAddrLen) + (2 * Header->ProtoAddrLen); DataBuffer = ExAllocatePool(PagedPool, DataSize); if (!DataBuffer) { TI_DbgPrint(DEBUG_ARP, ("Unable to allocate data buffer\n")); Packet->Free(Packet); return; } BytesCopied = CopyPacketToBuffer(DataBuffer, Packet->NdisPacket, Packet->Position + sizeof(ARP_HEADER), DataSize); if (BytesCopied != DataSize) { TI_DbgPrint(DEBUG_ARP, ("Unable to copy in data buffer\n")); ExFreePool(DataBuffer); Packet->Free(Packet); return; } SenderHWAddress = (PVOID)(DataBuffer); SenderProtoAddress = (PVOID)(SenderHWAddress + Header->HWAddrLen); TargetProtoAddress = (PVOID)(SenderProtoAddress + Header->ProtoAddrLen + Header->HWAddrLen); AddrInitIPv4(&DstAddress, *((PULONG)TargetProtoAddress)); if (!AddrIsEqual(&DstAddress, &Interface->Unicast)) { ExFreePool(DataBuffer); Packet->Free(Packet); return; } AddrInitIPv4(&SrcAddress, *((PULONG)SenderProtoAddress)); /* Check if we know the sender */ NCE = NBLocateNeighbor(&SrcAddress, Interface); if (NCE) { /* We know the sender. Update the hardware address and state in our neighbor address cache */ NBUpdateNeighbor(NCE, SenderHWAddress, 0); } else { /* The packet had our protocol address as target. The sender may want to communicate with us soon, so add his address to our address cache */ NBAddNeighbor(Interface, &SrcAddress, SenderHWAddress, Header->HWAddrLen, 0, ARP_COMPLETE_TIMEOUT); } if (Header->Opcode != ARP_OPCODE_REQUEST) { ExFreePool(DataBuffer); Packet->Free(Packet); return; } /* This is a request for our address. Swap the addresses and send an ARP reply back to the sender */ NdisPacket = PrepareARPPacket( Interface, Header->HWType, /* Hardware type */ Header->ProtoType, /* Protocol type */ (UCHAR)Interface->AddressLength, /* Hardware address length */ (UCHAR)Header->ProtoAddrLen, /* Protocol address length */ Interface->Address, /* Sender's (local) hardware address */ &Interface->Unicast.Address.IPv4Address,/* Sender's (local) protocol address */ SenderHWAddress, /* Target's (remote) hardware address */ SenderProtoAddress, /* Target's (remote) protocol address */ ARP_OPCODE_REPLY); /* ARP reply */ if (NdisPacket) { PC(NdisPacket)->DLComplete = ARPTransmitComplete; (*Interface->Transmit)(Interface->Context, NdisPacket, 0, SenderHWAddress, LAN_PROTO_ARP); } ExFreePool(DataBuffer); Packet->Free(Packet); }
BOOLEAN ARPTransmit(PIP_ADDRESS Address, PVOID LinkAddress, PIP_INTERFACE Interface) /* * FUNCTION: Creates an ARP request and transmits it on a network * ARGUMENTS: * Address = Pointer to IP address to resolve * RETURNS: * TRUE if the request was successfully sent, FALSE if not */ { PNDIS_PACKET NdisPacket; UCHAR ProtoAddrLen; USHORT ProtoType; TI_DbgPrint(DEBUG_ARP, ("Called.\n")); /* If Address is NULL then the caller wants an * gratuitous ARP packet sent */ if (!Address) Address = &Interface->Unicast; switch (Address->Type) { case IP_ADDRESS_V4: ProtoType = (USHORT)ETYPE_IPv4; /* IPv4 */ ProtoAddrLen = 4; /* Length of IPv4 address */ break; case IP_ADDRESS_V6: ProtoType = (USHORT)ETYPE_IPv6; /* IPv6 */ ProtoAddrLen = 16; /* Length of IPv6 address */ break; default: TI_DbgPrint(DEBUG_ARP,("Bad Address Type %x\n", Address->Type)); DbgBreakPoint(); /* Should not happen */ return FALSE; } NdisPacket = PrepareARPPacket( Interface, WN2H(0x0001), /* FIXME: Ethernet only */ ProtoType, /* Protocol type */ (UCHAR)Interface->AddressLength, /* Hardware address length */ (UCHAR)ProtoAddrLen, /* Protocol address length */ Interface->Address, /* Sender's (local) hardware address */ &Interface->Unicast.Address.IPv4Address,/* Sender's (local) protocol address */ LinkAddress, /* Target's (remote) hardware address */ &Address->Address.IPv4Address, /* Target's (remote) protocol address */ ARP_OPCODE_REQUEST); /* ARP request */ if( !NdisPacket ) return FALSE; ASSERT_KM_POINTER(NdisPacket); ASSERT_KM_POINTER(PC(NdisPacket)); PC(NdisPacket)->DLComplete = ARPTransmitComplete; TI_DbgPrint(DEBUG_ARP,("Sending ARP Packet\n")); (*Interface->Transmit)(Interface->Context, NdisPacket, 0, NULL, LAN_PROTO_ARP); return TRUE; }