err_t TCPSendDataCallback(struct netif *netif, struct pbuf *p, struct ip_addr *dest) { NDIS_STATUS NdisStatus; PNEIGHBOR_CACHE_ENTRY NCE; IP_PACKET Packet = { 0 }; IP_ADDRESS RemoteAddress, LocalAddress; PIPv4_HEADER Header; UINT i; struct pbuf *p1; /* The caller frees the pbuf struct */ if (((*(u8_t*)p->payload) & 0xF0) == 0x40) { Header = p->payload; LocalAddress.Type = IP_ADDRESS_V4; LocalAddress.Address.IPv4Address = Header->SrcAddr; RemoteAddress.Type = IP_ADDRESS_V4; RemoteAddress.Address.IPv4Address = Header->DstAddr; } else { return ERR_IF; } if (!(NCE = RouteGetRouteToDestination(&RemoteAddress))) { return ERR_RTE; } NdisStatus = AllocatePacketWithBuffer(&Packet.NdisPacket, NULL, p->tot_len); if (NdisStatus != NDIS_STATUS_SUCCESS) { return ERR_MEM; } GetDataPtr(Packet.NdisPacket, 0, (PCHAR*)&Packet.Header, &Packet.ContigSize); for (i = 0, p1 = p; i < p->tot_len; i += p1->len, p1 = p1->next) { ASSERT(p1); RtlCopyMemory(((PUCHAR)Packet.Header) + i, p1->payload, p1->len); } Packet.HeaderSize = sizeof(IPv4_HEADER); Packet.TotalSize = p->tot_len; Packet.SrcAddr = LocalAddress; Packet.DstAddr = RemoteAddress; if (!NT_SUCCESS(IPSendDatagram(&Packet, NCE, TCPPacketSendComplete, NULL))) { FreeNdisPacket(Packet.NdisPacket); return ERR_IF; } return 0; }
VOID ICMPTransmit( PIP_PACKET IPPacket, PIP_TRANSMIT_COMPLETE Complete, PVOID Context) /* * FUNCTION: Transmits an ICMP packet * ARGUMENTS: * NTE = Pointer to net table entry to use (NULL if don't care) * IPPacket = Pointer to IP packet to transmit */ { PNEIGHBOR_CACHE_ENTRY NCE; TI_DbgPrint(DEBUG_ICMP, ("Called.\n")); /* Calculate checksum of ICMP header and data */ ((PICMP_HEADER)IPPacket->Data)->Checksum = (USHORT) IPv4Checksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize, 0); /* Get a route to the destination address */ if ((NCE = RouteGetRouteToDestination(&IPPacket->DstAddr))) { /* Send the packet */ IPSendDatagram(IPPacket, NCE); } else { /* No route to destination (or no free resources) */ TI_DbgPrint(DEBUG_ICMP, ("No route to destination address 0x%X.\n", IPPacket->DstAddr.Address.IPv4Address)); IPPacket->Free(IPPacket); } }
NTSTATUS TCPConnect ( PCONNECTION_ENDPOINT Connection, PTDI_CONNECTION_INFORMATION ConnInfo, PTDI_CONNECTION_INFORMATION ReturnInfo, PTCP_COMPLETION_ROUTINE Complete, PVOID Context ) { NTSTATUS Status; struct ip_addr bindaddr, connaddr; IP_ADDRESS RemoteAddress; USHORT RemotePort; TA_IP_ADDRESS LocalAddress; PTDI_BUCKET Bucket; PNEIGHBOR_CACHE_ENTRY NCE; KIRQL OldIrql; TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Called\n")); Status = AddrBuildAddress ((PTRANSPORT_ADDRESS)ConnInfo->RemoteAddress, &RemoteAddress, &RemotePort); if (!NT_SUCCESS(Status)) { TI_DbgPrint(DEBUG_TCP, ("Could not AddrBuildAddress in TCPConnect\n")); return Status; } /* Freed in TCPSocketState */ TI_DbgPrint(DEBUG_TCP, ("Connecting to address %x:%x\n", RemoteAddress.Address.IPv4Address, RemotePort)); LockObject(Connection, &OldIrql); if (!Connection->AddressFile) { UnlockObject(Connection, OldIrql); return STATUS_INVALID_PARAMETER; } if (AddrIsUnspecified(&Connection->AddressFile->Address)) { if (!(NCE = RouteGetRouteToDestination(&RemoteAddress))) { UnlockObject(Connection, OldIrql); return STATUS_NETWORK_UNREACHABLE; } bindaddr.addr = NCE->Interface->Unicast.Address.IPv4Address; } else { bindaddr.addr = Connection->AddressFile->Address.Address.IPv4Address; } Status = TCPTranslateError(LibTCPBind(Connection, &bindaddr, Connection->AddressFile->Port)); if (NT_SUCCESS(Status)) { /* Check if we had an unspecified port */ if (!Connection->AddressFile->Port) { /* We did, so we need to copy back the port */ Status = TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE); if (NT_SUCCESS(Status)) { /* Allocate the port in the port bitmap */ Connection->AddressFile->Port = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port); /* This should never fail */ ASSERT(Connection->AddressFile->Port != 0xFFFF); } } if (NT_SUCCESS(Status)) { connaddr.addr = RemoteAddress.Address.IPv4Address; Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList); if (!Bucket) { UnlockObject(Connection, OldIrql); return STATUS_NO_MEMORY; } Bucket->Request.RequestNotifyObject = (PVOID)Complete; Bucket->Request.RequestContext = Context; InsertTailList( &Connection->ConnectRequest, &Bucket->Entry ); Status = TCPTranslateError(LibTCPConnect(Connection, &connaddr, RemotePort)); } } UnlockObject(Connection, OldIrql); TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Leaving. Status = 0x%x\n", Status)); return Status; }
NTSTATUS ICMPSendDatagram( PADDRESS_FILE AddrFile, PTDI_CONNECTION_INFORMATION ConnInfo, PCHAR BufferData, ULONG DataSize, PULONG DataUsed ) /* * FUNCTION: Sends an ICMP datagram to a remote address * ARGUMENTS: * Request = Pointer to TDI request * ConnInfo = Pointer to connection information * Buffer = Pointer to NDIS buffer with data * DataSize = Size in bytes of data to be sent * RETURNS: * Status of operation */ { IP_PACKET Packet; PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress; IP_ADDRESS RemoteAddress, LocalAddress; NTSTATUS Status; PNEIGHBOR_CACHE_ENTRY NCE; KIRQL OldIrql; TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n", AddrFile, ConnInfo, BufferData, DataSize)); TI_DbgPrint(MID_TRACE,("RemoteAddressTa: %x\n", RemoteAddressTa)); switch( RemoteAddressTa->Address[0].AddressType ) { case TDI_ADDRESS_TYPE_IP: RemoteAddress.Type = IP_ADDRESS_V4; RemoteAddress.Address.IPv4Address = RemoteAddressTa->Address[0].Address[0].in_addr; break; default: return STATUS_UNSUCCESSFUL; } TI_DbgPrint(MID_TRACE,("About to get route to destination\n")); LockObject(AddrFile, &OldIrql); LocalAddress = AddrFile->Address; if (AddrIsUnspecified(&LocalAddress)) { /* If the local address is unspecified (0), * then use the unicast address of the * interface we're sending over */ if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) { UnlockObject(AddrFile, OldIrql); return STATUS_NETWORK_UNREACHABLE; } LocalAddress = NCE->Interface->Unicast; } else { if(!(NCE = NBLocateNeighbor( &LocalAddress, NULL ))) { UnlockObject(AddrFile, OldIrql); return STATUS_INVALID_PARAMETER; } } Status = PrepareICMPPacket( AddrFile, NCE->Interface, &Packet, &RemoteAddress, BufferData, DataSize ); UnlockObject(AddrFile, OldIrql); if( !NT_SUCCESS(Status) ) return Status; TI_DbgPrint(MID_TRACE,("About to send datagram\n")); Status = IPSendDatagram(&Packet, NCE); if (!NT_SUCCESS(Status)) return Status; *DataUsed = DataSize; TI_DbgPrint(MID_TRACE,("Leaving\n")); return STATUS_SUCCESS; }