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; }
NDIS_STATUS AllocatePacketWithBuffer( PNDIS_PACKET *NdisPacket, PCHAR Data, UINT Len ) { PNDIS_PACKET Packet; PNDIS_BUFFER Buffer; NDIS_STATUS Status; PCHAR NewData; NewData = ExAllocatePoolWithTag( NonPagedPool, Len, PACKET_BUFFER_TAG ); if( !NewData ) return NDIS_STATUS_RESOURCES; if( Data ) RtlCopyMemory(NewData, Data, Len); NdisAllocatePacket( &Status, &Packet, GlobalPacketPool ); if( Status != NDIS_STATUS_SUCCESS ) { ExFreePoolWithTag( NewData, PACKET_BUFFER_TAG ); return Status; } NdisAllocateBuffer( &Status, &Buffer, GlobalBufferPool, NewData, Len ); if( Status != NDIS_STATUS_SUCCESS ) { ExFreePoolWithTag( NewData, PACKET_BUFFER_TAG ); FreeNdisPacket( Packet ); return Status; } NdisChainBufferAtFront( Packet, Buffer ); *NdisPacket = Packet; return NDIS_STATUS_SUCCESS; }
NDIS_STATUS AllocatePacketWithBufferX( PNDIS_PACKET *NdisPacket, PCHAR Data, UINT Len, PCHAR File, UINT Line ) { PNDIS_PACKET Packet; PNDIS_BUFFER Buffer; NDIS_STATUS Status; PCHAR NewData; NewData = exAllocatePool( NonPagedPool, Len ); if( !NewData ) return NDIS_STATUS_NOT_ACCEPTED; // XXX if( Data ) RtlCopyMemory(NewData, Data, Len); NdisAllocatePacket( &Status, &Packet, GlobalPacketPool ); if( Status != NDIS_STATUS_SUCCESS ) { exFreePool( NewData ); return Status; } TrackWithTag(NDIS_PACKET_TAG, Packet, File, Line); NdisAllocateBuffer( &Status, &Buffer, GlobalBufferPool, NewData, Len ); if( Status != NDIS_STATUS_SUCCESS ) { exFreePool( NewData ); FreeNdisPacket( Packet ); } TrackWithTag(NDIS_BUFFER_TAG, Buffer, File, Line); NdisChainBufferAtFront( Packet, Buffer ); *NdisPacket = Packet; return NDIS_STATUS_SUCCESS; }
VOID IPSendComplete (PVOID Context, PNDIS_PACKET NdisPacket, NDIS_STATUS NdisStatus) /* * FUNCTION: IP datagram fragment send completion handler * ARGUMENTS: * Context = Pointer to context information (IP_INTERFACE) * Packet = Pointer to NDIS packet that was sent * NdisStatus = NDIS status of operation * NOTES: * This routine is called when an IP datagram fragment has been sent */ { PIPFRAGMENT_CONTEXT IFC = (PIPFRAGMENT_CONTEXT)Context; NTSTATUS Status; TI_DbgPrint (MAX_TRACE, ("Called. Context (0x%X) NdisPacket (0x%X) NdisStatus (0x%X)\n", Context, NdisPacket, NdisStatus)); if (NT_SUCCESS(NdisStatus) && PrepareNextFragment(IFC)) { /* A fragment was prepared for transmission, so send it */ Status = IPSendFragment(IFC->NdisPacket, IFC->NCE, IFC); if (!NT_SUCCESS(Status)) { FreeNdisPacket(IFC->NdisPacket); IFC->Complete(IFC->Context, IFC->Datagram, Status); ExFreePoolWithTag(IFC, IFC_TAG); } } else { TI_DbgPrint(MAX_TRACE, ("Calling completion handler.\n")); /* There are no more fragments to transmit, so call completion handler */ FreeNdisPacket(IFC->NdisPacket); IFC->Complete(IFC->Context, IFC->Datagram, NdisStatus); ExFreePoolWithTag(IFC, IFC_TAG); } }
VOID ARPTransmitComplete( PVOID Context, PNDIS_PACKET NdisPacket, NDIS_STATUS NdisStatus) /* * FUNCTION: ARP request transmit completion handler * ARGUMENTS: * Context = Pointer to context information (IP_INTERFACE) * Packet = Pointer to NDIS packet that was sent * NdisStatus = NDIS status of operation * NOTES: * This routine is called when an ARP request has been sent */ { TI_DbgPrint(DEBUG_ARP, ("Called.\n")); FreeNdisPacket(NdisPacket); }
void TCPPacketSendComplete(PVOID Context, PNDIS_PACKET NdisPacket, NDIS_STATUS NdisStatus) { FreeNdisPacket(NdisPacket); }
NTSTATUS SendFragments( PIP_PACKET IPPacket, PNEIGHBOR_CACHE_ENTRY NCE, UINT PathMTU, PIP_TRANSMIT_COMPLETE Complete, PVOID Context) /* * FUNCTION: Fragments and sends the first fragment of an IP datagram * ARGUMENTS: * IPPacket = Pointer to an IP packet * NCE = Pointer to NCE for first hop to destination * PathMTU = Size of Maximum Transmission Unit of path * RETURNS: * Status of operation * NOTES: * IP datagram is larger than PathMTU when this is called */ { PIPFRAGMENT_CONTEXT IFC; NDIS_STATUS NdisStatus; PVOID Data; UINT BufferSize = PathMTU, InSize; PCHAR InData; TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) NCE (0x%X) PathMTU (%d).\n", IPPacket, NCE, PathMTU)); /* Make a smaller buffer if we will only send one fragment */ GetDataPtr( IPPacket->NdisPacket, 0, &InData, &InSize ); if( InSize < BufferSize ) BufferSize = InSize; TI_DbgPrint(MAX_TRACE, ("Fragment buffer is %d bytes\n", BufferSize)); IFC = ExAllocatePoolWithTag(NonPagedPool, sizeof(IPFRAGMENT_CONTEXT), IFC_TAG); if (IFC == NULL) return STATUS_INSUFFICIENT_RESOURCES; /* Allocate NDIS packet */ NdisStatus = AllocatePacketWithBuffer ( &IFC->NdisPacket, NULL, BufferSize ); if( !NT_SUCCESS(NdisStatus) ) { ExFreePoolWithTag( IFC, IFC_TAG ); return NdisStatus; } GetDataPtr( IFC->NdisPacket, 0, (PCHAR *)&Data, &InSize ); IFC->Header = ((PCHAR)Data); IFC->Datagram = IPPacket->NdisPacket; IFC->DatagramData = ((PCHAR)IPPacket->Header) + IPPacket->HeaderSize; IFC->HeaderSize = IPPacket->HeaderSize; IFC->PathMTU = PathMTU; IFC->NCE = NCE; IFC->Position = 0; IFC->BytesLeft = IPPacket->TotalSize - IPPacket->HeaderSize; IFC->Data = (PVOID)((ULONG_PTR)IFC->Header + IPPacket->HeaderSize); IFC->Complete = Complete; IFC->Context = Context; TI_DbgPrint(MID_TRACE,("Copying header from %x to %x (%d)\n", IPPacket->Header, IFC->Header, IPPacket->HeaderSize)); RtlCopyMemory( IFC->Header, IPPacket->Header, IPPacket->HeaderSize ); /* Prepare next fragment for transmission and send it */ if (!PrepareNextFragment(IFC)) { FreeNdisPacket(IFC->NdisPacket); ExFreePoolWithTag(IFC, IFC_TAG); return NDIS_STATUS_FAILURE; } if (!NT_SUCCESS((NdisStatus = IPSendFragment(IFC->NdisPacket, NCE, IFC)))) { FreeNdisPacket(IFC->NdisPacket); ExFreePoolWithTag(IFC, IFC_TAG); } return NdisStatus; }