/* NicIndicateRecvPackets indicate received packet (MAC frame) to NDIS (then protocol stack) Parameters: pAdapter : pointer to adapter object created by miniport driver. ppNBSPackets : pointer to an NDIS packet to be indicated up. Return: Note: History: Created by yichen, 1/Apr/2009 IRQL: PASSIVE_LEVEL */ VOID NicIndicateRecvPackets(IN PMP_ADAPTER pAdapter,IN PPNDIS_PACKETS_OR_NBL ppNBSPackets) { NDIS_SET_PACKET_HEADER_SIZE(*ppNBSPackets, ETH_HEADER_SIZE); NDIS_SET_PACKET_STATUS(*ppNBSPackets, NDIS_STATUS_SUCCESS); NdisMIndicateReceivePacket(pAdapter->AdapterHandle, ppNBSPackets, 1); //only 1 packet indicated InterlockedIncrement64(&pAdapter->ullGoodReceives); }
NTSTATUS MPIndicatePacket(PHWT_ADAPTER Adapter, PVOID Input, ULONG InputSize, PDEV_RET Output, ULONG OutputSize, PIRP Irp) { PVOID data = NULL; NDIS_STATUS ndis_status = NDIS_STATUS_FAILURE; PNDIS_BUFFER ndis_buffer = NULL; PNDIS_PACKET ndis_packet = NULL; do { data = ExAllocatePoolWithTag(NonPagedPool, InputSize, 'tkpi'); RtlCopyMemory(data, Input, InputSize); NdisAllocateBuffer(&ndis_status, &ndis_buffer, Adapter->AllocateBufferPool, data, InputSize); if (ndis_status != NDIS_STATUS_SUCCESS) break; NdisAllocatePacket(&ndis_status, &ndis_packet, Adapter->AllocatePacketPool); if (ndis_status != NDIS_STATUS_SUCCESS) break; NdisReinitializePacket(ndis_packet); *(PVOID*)ndis_packet->MiniportReserved = data; NdisChainBufferAtBack(ndis_packet, ndis_buffer); NDIS_SET_PACKET_HEADER_SIZE(ndis_packet, sizeof(ETHERNET_HEADER)); NDIS_SET_PACKET_STATUS(ndis_packet, NDIS_STATUS_SUCCESS); NdisMIndicateReceivePacket(Adapter->AdapterHandle, &ndis_packet, 1); Output->hResult = S_OK; ndis_status = NDIS_STATUS_SUCCESS; } while(FALSE); if (ndis_status != NDIS_STATUS_SUCCESS && ndis_status != STATUS_PENDING) { if (ndis_packet) NdisFreePacket(ndis_packet); if (ndis_buffer) NdisFreeBuffer(ndis_buffer); if (data) ExFreePoolWithTag(data, 'tkpi'); } return ndis_status; }
/*----------------------------------------------------------------------------*/ PVOID kalPacketAlloc(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Size, OUT PPUINT_8 ppucData) { PNDIS_PACKET packet_p; packet_p = getPoolPacket(prGlueInfo); /* The mbuf descriptor will be created and chained to packet * in function kalPacketPut(). */ if (packet_p != NULL) { *ppucData = *(PUCHAR *) &packet_p->MiniportReservedEx[OFFSET_OF(PKT_INFO_RESERVED, pvBuf)]; NDIS_SET_PACKET_HEADER_SIZE(packet_p, 14); /* Ether header size */ } return packet_p; } /* kalPacketAlloc */
// Create a packet buffer PACKET_BUFFER *NeoNewPacketBuffer() { PACKET_BUFFER *p; NDIS_STATUS ret; // Memory allocation p = NeoZeroMalloc(sizeof(PACKET_BUFFER)); // Memory allocation for packet p->Buf = NeoMalloc(NEO_MAX_PACKET_SIZE); // Allocate the buffer pool NdisAllocateBufferPool(&ret, &p->BufferPool, 1); // Allocate the buffer NdisAllocateBuffer(&ret, &p->NdisBuffer, p->BufferPool, p->Buf, NEO_MAX_PACKET_SIZE); // Secure the packet pool NdisAllocatePacketPool(&ret, &p->PacketPool, 1, PROTOCOL_RESERVED_SIZE_IN_PACKET); // Secure the packet NdisAllocatePacket(&ret, &p->NdisPacket, p->PacketPool); NDIS_SET_PACKET_HEADER_SIZE(p->NdisPacket, NEO_PACKET_HEADER_SIZE); // Attach the buffer to the packet NdisChainBufferAtFront(p->NdisPacket, p->NdisBuffer); return p; }
/* Maps to ReceiverReceiveNetBufferList() in xennet6 */ static NTSTATUS ReceiverReceivePacket( IN PRECEIVER Receiver, OUT PNDIS_PACKET *pPacket, OUT ULONG *pTotFrags ) { struct ethhdr *eh; PNDIS_PACKET work; NDIS_STATUS stat; PNDIS_BUFFER buffer; uint16_t head_flags; UINT buffer_length; ULONG totOctets; ULONG totFrags; PMP_RFD prefixRfd; PMP_RFD headRfd; stat = ReceiverCommonReceiveRfdChain(Receiver, &head_flags, &prefixRfd, &headRfd, &totOctets, &totFrags); if (stat != NDIS_STATUS_SUCCESS) { Receiver->Common.Adapter->RxError++; goto discard; } XM_ASSERT(totFrags > 0); /* There should never be a prefix as we do not enable GSO on the receive path. */ XM_ASSERT(prefixRfd == NULL); NdisDprAllocatePacketNonInterlocked(&stat, &work, Receiver->RecvPacketPool); if (stat != NDIS_STATUS_SUCCESS) { Receiver->nRxDiscards++; goto discard; } NDIS_SET_PACKET_HEADER_SIZE(work, XENNET_PACKET_HDR_SIZE); NdisChainBufferAtFront(work, &headRfd->Mdl); /* Ick: find the ethernet and IP headers so that we can check (a) the MAC address is for us, and (b) whether to indicate RX csum offload. We rely on the fact that netback always puts the ethernet and IP headers in the same fragment. */ buffer = &headRfd->Mdl; buffer_length = buffer->ByteCount; stat = STATUS_UNSUCCESSFUL; if (buffer_length < sizeof(struct ethhdr)) { NdisDprFreePacketNonInterlocked(work); Receiver->nRxDiscards++; goto discard; } Receiver->Common.Adapter->RxGood++; eh = (struct ethhdr *)buffer->MappedSystemVa; stat = NDIS_STATUS_INVALID_PACKET; if (!MacAddressInteresting(eh->dest, Receiver->Common.Adapter)) { Receiver->Common.Adapter->MacMisdirect++; NdisDprFreePacketNonInterlocked(work); goto discard; } if (eh->proto == TPID_IPV4) { BOOLEAN needCsumFixup; NDIS_TCP_IP_CHECKSUM_PACKET_INFO CsumInfo; CsumInfo.Value = 0; needCsumFixup = (head_flags & NETRXF_csum_blank) ? TRUE : FALSE; if (head_flags & NETRXF_data_validated) { struct iphdr *ih = (struct iphdr *)(eh + 1); if (ih->proto == IPPROTO_TCP && Receiver->rx_csum_tcp_offload) { CsumInfo.Receive.NdisPacketTcpChecksumSucceeded = 1; Receiver->nRxCsumOffload++; } else if (ih->proto == IPPROTO_UDP && Receiver->rx_csum_udp_offload) { CsumInfo.Receive.NdisPacketUdpChecksumSucceeded = 1; Receiver->nRxCsumOffload++; } } if (needCsumFixup) { FixupChecksum(work); Receiver->nRxCsumFixup++; } NDIS_PER_PACKET_INFO_FROM_PACKET(work, TcpIpChecksumPacketInfo) = (PVOID)(ULONG_PTR)CsumInfo.Value; } NDIS_SET_PACKET_STATUS(work, NDIS_STATUS_SUCCESS); *pPacket = work; *pTotFrags = totFrags; return NDIS_STATUS_SUCCESS; discard: ReceiverCommonReleaseRfdChain(&Receiver->Common, prefixRfd); ReceiverCommonReleaseRfdChain(&Receiver->Common, headRfd); return stat; }
/* ************************************************************************* * DeliverFullBuffers ************************************************************************* * * Deliver received packets to the protocol. * */ VOID DeliverFullBuffers(IrDevice *thisDev) { int rcvBufIndex = thisDev->firstRcvBufIndex; DBGOUT(("==> DeliverFullBuffers")); /* * Deliver all full rcv buffers */ while (rcvBufIndex != NO_BUF_INDEX){ rcvBuffer *rcvBuf = &thisDev->rcvBufs[rcvBufIndex]; NDIS_STATUS stat; PNDIS_BUFFER packetBuf; SLOW_IR_FCS_TYPE fcs; switch (rcvBuf->state){ case STATE_FREE: case STATE_PENDING: /* * This frame was already delivered. Just go to the next one. */ break; case STATE_FULL: /* * The packet we have already has had BOFs, EOF, and * escape-sequences removed. * It contains an FCS code at the end, * which we need to verify and then remove before * delivering the frame. * We compute the FCS on the packet with the packet FCS * attached; this should produce the constant value GOOD_FCS. */ fcs = ComputeFCS(rcvBuf->dataBuf, rcvBuf->dataLen); if (fcs != GOOD_FCS){ /* * FCS Error. Drop this frame. */ DBGERR(("Bad FCS in DeliverFullBuffers 0x%x!=0x%x.", (UINT)fcs, (UINT)GOOD_FCS)); rcvBuf->state = STATE_FREE; DBGSTAT(("Dropped %d/%d packets; packet with BAD FCS (%xh!=%xh):", ++thisDev->packetsDropped, thisDev->packetsDropped + thisDev->packetsRcvd, fcs, GOOD_FCS)); DBGPRINTBUF(rcvBuf->dataBuf, rcvBuf->dataLen); break; } /* * Remove the FCS from the end of the packet. */ rcvBuf->dataLen -= SLOW_IR_FCS_SIZE; #ifdef DBG_ADD_PKT_ID if (addPktIdOn){ /* * Remove dbg packet id. */ rcvBuf->dataLen -= sizeof(USHORT); DBGOUT((" RCVing packet %xh **", (UINT)*(USHORT *)(rcvBuf->dataBuf+rcvBuf->dataLen))); } #endif /* * The packet array is set up with its NDIS_PACKET. * Now we need to allocate a single NDIS_BUFFER for the * NDIS_PACKET and set the NDIS_BUFFER to the part of dataBuf * that we want to deliver. */ NdisAllocateBuffer( &stat, &packetBuf, thisDev->bufferPoolHandle, (PVOID)rcvBuf->dataBuf, rcvBuf->dataLen); if (stat != NDIS_STATUS_SUCCESS){ DBGERR(("NdisAllocateBuffer failed")); break; } NdisChainBufferAtFront(rcvBuf->packet, packetBuf); /* * Fix up some other packet fields. */ NDIS_SET_PACKET_HEADER_SIZE(rcvBuf->packet, SLOW_IR_ADDR_SIZE + SLOW_IR_CONTROL_SIZE); DBGPKT(("Indicating rcv packet 0x%x.", (UINT)rcvBuf->packet)); DBGPRINTBUF(rcvBuf->dataBuf, rcvBuf->dataLen); /* * Indicate to the protocol that another packet is ready. * Set the rcv buffer's state to PENDING first to avoid * a race condition with NDIS's call to the return packet * handler. */ rcvBuf->state = STATE_PENDING; NdisMIndicateReceivePacket(thisDev->ndisAdapterHandle, &rcvBuf->packet, 1); stat = NDIS_GET_PACKET_STATUS(rcvBuf->packet); if (stat == NDIS_STATUS_PENDING){ /* * The packet is being delivered asynchronously. * Leave the rcv buffer's state as PENDING; we'll * get a callback when the transfer is complete. * * Do NOT step firstRcvBufIndex. * We don't really need to break out here, * but we will anyways just to make things simple. * This is ok since we get this deferred interrupt callback * for each packet anyway. It'll give the protocol a chance * to catch up. */ DBGSTAT(("Rcv Pending. Rcvd %d packets", ++thisDev->packetsRcvd)); } else { /* * If there was an error, we are dropping this packet; * otherwise, this packet was delivered synchronously. * We can free the packet buffer and make this rcv frame * available. */ NdisUnchainBufferAtFront(rcvBuf->packet, &packetBuf); if (packetBuf){ NdisFreeBuffer(packetBuf); } rcvBuf->state = STATE_FREE; if (stat == NDIS_STATUS_SUCCESS){ DBGSTAT(("Rcvd %d packets", ++thisDev->packetsRcvd)); } else { DBGSTAT(("Dropped %d/%d rcv packets. ", thisDev->packetsDropped++, thisDev->packetsDropped+thisDev->packetsRcvd)); } } break; default: /* * This should never happen. */ DBGERR(("Bad rcv buffer state in DPC")); break; } /* * Step the buffer index */ if (rcvBufIndex == thisDev->lastRcvBufIndex){ rcvBufIndex = NO_BUF_INDEX; } else { rcvBufIndex = NEXT_RCV_BUF_INDEX(rcvBufIndex); } } DBGOUT(("<== DeliverFullBuffers")); }
NDIS_STATUS NICAllocAdapter( PMP_ADAPTER *pAdapter) { PMP_ADAPTER Adapter = NULL; PNDIS_PACKET Packet; PNDIS_BUFFER Buffer; PUCHAR pTCBMem; PTCB pTCB; NDIS_STATUS Status; LONG index; DEBUGP(MP_TRACE, ("--> NICAllocAdapter\n")); PAGED_CODE(); *pAdapter = NULL; do { // // Allocate memory for adapter context // Status = NdisAllocateMemoryWithTag( &Adapter, sizeof(MP_ADAPTER), NIC_TAG); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("Failed to allocate memory for adapter context\n")); break; } // // Zero the memory block // NdisZeroMemory(Adapter, sizeof(MP_ADAPTER)); NdisInitializeListHead(&Adapter->List); // // Initialize Send & Recv listheads and corresponding // spinlocks. // //NdisInitializeListHead(&Adapter->RecvWaitList); //NdisInitializeListHead(&Adapter->SendWaitList); //NdisInitializeListHead(&Adapter->SendFreeList); NdisAllocateSpinLock(&Adapter->SendLock); //NdisInitializeListHead(&Adapter->RecvFreeList); NdisAllocateSpinLock(&Adapter->RecvLock); //allocate a packet pool NdisAllocatePacketPool( &Status, &Adapter->LdnRecvPacketPoolHandle, 1, PROTOCOL_RESERVED_SIZE_IN_PACKET); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocatePacketPool failed\n")); break; } //allocate a single packet in the pool NdisAllocatePacket( &Status, &Adapter->LdnRecvPacket, Adapter->LdnRecvPacketPoolHandle); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocatePacket failed\n")); break; } //allocate a buffer pool NdisAllocateBufferPool( &Status, &Adapter->LdnRecvBufferPoolHandle, 1); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocateBufferPool for recv buffer failed\n")); break; } //allocate a single buffer in the buffer pool NdisAllocateBuffer( &Status, &Adapter->LdnRecvPacketBuffer, Adapter->LdnRecvBufferPoolHandle, (PVOID)&Adapter->LdnRecvPacketBufferData[0], NIC_BUFFER_SIZE); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocateBuffer failed\n")); break; } //chain the buffer to the packet NdisChainBufferAtBack(Adapter->LdnRecvPacket, Adapter->LdnRecvPacketBuffer); NDIS_SET_PACKET_STATUS(Adapter->LdnRecvPacket, NDIS_STATUS_RESOURCES); NDIS_SET_PACKET_HEADER_SIZE(Adapter->LdnRecvPacket, ETH_HEADER_SIZE); /*// // Allocate lookside list for Receive Control blocks. // NdisInitializeNPagedLookasideList( &Adapter->RecvLookaside, NULL, // No Allocate function NULL, // No Free function 0, // Reserved for system use sizeof(RCB), NIC_TAG, 0); // Reserved for system use MP_SET_FLAG(Adapter, fMP_ADAPTER_RECV_LOOKASIDE); // // Allocate packet pool for receive indications // NdisAllocatePacketPool( &Status, &Adapter->RecvPacketPoolHandle, NIC_MAX_BUSY_RECVS, PROTOCOL_RESERVED_SIZE_IN_PACKET); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocatePacketPool failed\n")); break; } // // Initialize receive packets // for(index=0; index < NIC_MAX_BUSY_RECVS; index++) { // // Allocate a packet descriptor for receive packets // from a preallocated pool. // NdisAllocatePacket( &Status, &Packet, Adapter->RecvPacketPoolHandle); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocatePacket failed\n")); break; } NDIS_SET_PACKET_HEADER_SIZE(Packet, ETH_HEADER_SIZE); // // Insert it into the list of free receive packets. // NdisInterlockedInsertTailList( &Adapter->RecvFreeList, (PLIST_ENTRY)&Packet->MiniportReserved[0], &Adapter->RecvLock); } // // Allocate a huge block of memory for all TCB's // Status = NdisAllocateMemoryWithTag( &pTCBMem, sizeof(TCB) * NIC_MAX_BUSY_SENDS, NIC_TAG); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("Failed to allocate memory for TCB's\n")); break; } NdisZeroMemory(pTCBMem, sizeof(TCB) * NIC_MAX_BUSY_SENDS); Adapter->TCBMem = pTCBMem; // // Allocate a buffer pool for send buffers. // NdisAllocateBufferPool( &Status, &Adapter->SendBufferPoolHandle, NIC_MAX_BUSY_SENDS); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocateBufferPool for send buffer failed\n")); break; } // // Divide the TCBMem blob into TCBs and create a buffer // descriptor for the Data portion of the TCBs. // for(index=0; index < NIC_MAX_BUSY_SENDS; index++) { pTCB = (PTCB) pTCBMem; // // Create a buffer descriptor for the Data portion of the TCBs. // Buffer descriptors are nothing but MDLs on NT systems. // NdisAllocateBuffer( &Status, &Buffer, Adapter->SendBufferPoolHandle, (PVOID)&pTCB->Data[0], NIC_BUFFER_SIZE); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocateBuffer failed\n")); break; } // // Initialize the TCB structure. // pTCB->Buffer = Buffer; pTCB->pData = (PUCHAR) &pTCB->Data[0]; pTCB->Adapter = Adapter; NdisInterlockedInsertTailList( &Adapter->SendFreeList, &pTCB->List, &Adapter->SendLock); pTCBMem = pTCBMem + sizeof(TCB); }*/ } while(FALSE); *pAdapter = Adapter; // // In the failure case, the caller of this routine will end up // calling NICFreeAdapter to free all the successfully allocated // resources. // DEBUGP(MP_TRACE, ("<-- NICAllocAdapter\n")); return(Status); }
// Process the received packet void NeoWrite(void *buf) { UINT num, i, size; void *packet_buf; // Validate arguments if (buf == NULL) { return; } // Number of packets num = NEO_NUM_PACKET(buf); if (num > NEO_MAX_PACKET_EXCHANGE) { // Number of packets is too many return; } if (num == 0) { // No packet return; } if (ctx->Halting != FALSE) { // Halting return; } if (ctx->Opened == FALSE) { // Not connected return; } for (i = 0;i < num;i++) { PACKET_BUFFER *p = ctx->PacketBuffer[i]; size = NEO_SIZE_OF_PACKET(buf, i); if (size > NEO_MAX_PACKET_SIZE) { size = NEO_MAX_PACKET_SIZE; } if (size < NEO_PACKET_HEADER_SIZE) { size = NEO_PACKET_HEADER_SIZE; } packet_buf = NEO_ADDR_OF_PACKET(buf, i); // Buffer copy NeoCopy(p->Buf, packet_buf, size); if (g_is_win8 == false) { // Adjust the buffer size NdisAdjustBufferLength(p->NdisBuffer, size); // Set the packet information NDIS_SET_PACKET_STATUS(p->NdisPacket, NDIS_STATUS_RESOURCES); NDIS_SET_PACKET_HEADER_SIZE(p->NdisPacket, NEO_PACKET_HEADER_SIZE); } else { NdisMEthIndicateReceive(ctx->NdisMiniport, ctx, p->Buf, NEO_PACKET_HEADER_SIZE, ((UCHAR *)p->Buf) + NEO_PACKET_HEADER_SIZE, size - NEO_PACKET_HEADER_SIZE, size - NEO_PACKET_HEADER_SIZE); NdisMEthIndicateReceiveComplete(ctx->NdisMiniport); } } // Notify that packets have received ctx->Status.NumPacketRecv += num; if (g_is_win8 == false) { NdisMIndicateReceivePacket(ctx->NdisMiniport, ctx->PacketBufferArray, num); } }
void CAR6KMini::ReceiveWMIDataPacket( HTC_EVENT_INFO *evInfo) // // This function processes data from an HTC_BUFFER_RECEIVED indication // not on the WMI_CONTROL_MBOX endpoint. // { ndis_mini_buf_t *pb = (ndis_mini_buf_t *)evInfo->cookie; NDIS_STATUS Status; NDIS_PACKET *pPacket; NDIS_BUFFER *pBuffer; PBYTE pData; ULONG cbData; BOOL doDix = FALSE; USHORT etherType; SNAP_HEADER *pSnapHdr; MAC_ADDRESS *pDestAddr,*tempAddr; BOOL mcForUs = FALSE; NDIS_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV, "AR6K: +ReceiveWMIDataPacket"); if (evInfo->status != A_OK) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket Error in receiving : status = %x\n", evInfo->status); if (A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } // evInfo->actualLength is the length of the pb->data including // 2 bytes: WMI_DATA_HEADER [optional - only if HTC header is 46 00] // 14 bytes: 802.3 MAC header // 8 bytes: SNAP header (with EthType as last 2 bytes) // N bytes: payload (e.g. IP packet) pData = evInfo->buffer; cbData = evInfo->actualLength; // Remove the WMI_DATA_HDR. if (cbData < sizeof(WMI_DATA_HDR)) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket missing WMI header (%u bytes)\n", evInfo->actualLength); if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } pData += sizeof(WMI_DATA_HDR); cbData -= sizeof(WMI_DATA_HDR); if (cbData < sizeof(ETHERNET_MAC_HEADER) + sizeof(SNAP_HEADER)) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket missing MAC + SNAP (%u bytes)\n", cbData); if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } #ifdef WMM Lock(); wmi_implicit_create_pstream((wmi_t *)m_pWMI, pb, DNLINK_TRAFFIC,1); Unlock(); #endif //WMM pDestAddr=(MAC_ADDRESS *)pData; /* Apply NDIS receive filter */ if (isGrp(pDestAddr)) { if (isBcast(pDestAddr)) { if (!(m_CurrentPacketFilter & NDIS_PACKET_TYPE_BROADCAST)) { if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } } else { isMcForUs(pDestAddr,&mcForUs); if (!(m_CurrentPacketFilter & (NDIS_PACKET_TYPE_MULTICAST | NDIS_PACKET_TYPE_ALL_MULTICAST)) || !(mcForUs)) { if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } } } else { tempAddr=(MAC_ADDRESS *) m_PermanentAddress; if ((A_MACADDR_COMP(pDestAddr,tempAddr) != 0) && !(m_CurrentPacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)) { if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } } // Allocate an NDIS_PACKET from our packet pool. NdisAllocatePacket(&Status, &pPacket, m_RxPacketPool); if (NDIS_STATUS_SUCCESS != Status) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - NdisAllocatePacket failed\n"); if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } // Check for ethernetType in SNAP header for NOVELL_IPX, APPLE_TALK_ARP etc // remove 802.3 length and SNAP header if it is not of these types pSnapHdr=(SNAP_HEADER *)(pData+sizeof(ETHERNET_MAC_HEADER)); etherType=A_BE2CPU16(pSnapHdr->Type); doDix=((A_MEMCMP(pSnapHdr,&bridgeTunnel, sizeof(CAP_CONST))) == 0); if((!doDix) && ((A_MEMCMP(pSnapHdr,&vrfc1042, sizeof(CAP_CONST))) == 0)) { doDix = ((etherType != APPLE_TALK_ARP) && (etherType != NOVELL_IPX)); } // Get rid of the 802.3 length and SNAP header by copying // the 802.3 DestMACAddr and SrcMACAddr forward so they // immediately precede the EthType at the end of the SNAP header. // That gives us a DIX packet. if (doDix) { memmove(pData + sizeof(SNAP_HEADER), pData, ETHERNET_MAC_ADDRESS_LENGTH * 2); pData += sizeof(SNAP_HEADER); cbData -= sizeof(SNAP_HEADER); } // Setup the fields of NDIS_BUFFER to point to our data. pBuffer = &pb->NdisBuffer; NdisInitializeBuffer(pBuffer, pData, cbData); // Chain the NDIS_BUFFER to the start of the NDIS_PACKET NdisChainBufferAtBack(pPacket, pBuffer); NDIS_SET_PACKET_HEADER_SIZE(pPacket, sizeof(ETHERNET_MAC_HEADER)); NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_SUCCESS); #ifdef NDIS_BUS_DRIVER NDIS_PACKET *PacketArray[1]; PacketArray[0]=pPacket; NdisMIndicateReceivePacket(m_MiniportAdapterHandle, PacketArray, 1); #else // Perform the indicate on the timer thread because tying up the // SDIO receive indication thread can result in a deadlock. PLIST_ENTRY pEntry = (PLIST_ENTRY)(pPacket->MiniportReserved); Lock(); InsertTailList(&m_RxPendingPacketList, pEntry); NdisSetEvent(&m_RxPendingEvent); Unlock(); #endif done: NDIS_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV, "AR6K: -ReceiveWMIDataPacket"); }
/*+ * * AllocateAdapterMemory * * Routine Description: * * This routine allocates memory for: * * - Transmit descriptor ring * - Receive descriptor ring * - Receive buffers * - Transmit buffer * - Setup buffer * * Arguments: * * Adapter - The adapter to allocate memory for. * * Functional description * * For each allocated zone, we maintain a set of pointers: * - virtual & physical addresses of the allocated block * - virtual & physical addresses of the aligned structure (descriptor ring, buffer,...) * whithin the block * * Return Value: * * Returns FALSE if an allocation fails. * -*/ extern BOOLEAN AllocateAdapterMemory( IN PDC21X4_ADAPTER Adapter ) { PDC21X4_TRANSMIT_DESCRIPTOR TransmitDescriptor; PDC21X4_RECEIVE_DESCRIPTOR ReceiveDescriptor; NDIS_STATUS Status; PRCV_HEADER RcvHeader; PNDIS_PACKET Packet; ULONG AllocSize; PULONG AllocVa; NDIS_PHYSICAL_ADDRESS AllocPa; ULONG Va; ULONG Pa; UINT i; ULONG Offset; INT TransmitDescriptorRingSize; INT ReceiveDescriptorRingSize; Adapter->RcvHeaderSize = ((RCV_HEADER_SIZE + Adapter->CacheLineSize - 1) / Adapter->CacheLineSize) * Adapter->CacheLineSize; #if _DBG DbgPrint("Alloc Rcv_ring[%d desc.], Txm_ring[%d desc.], setup_buf[%d]...\n", Adapter->ReceiveRingSize, TRANSMIT_RING_SIZE, DC21X4_SETUP_BUFFER_SIZE ); #endif // Allocate space for transmit descriptor ring, // the receive descriptor ring and the setup buffer TransmitDescriptorRingSize = Adapter->DescriptorSize * TRANSMIT_RING_SIZE; ReceiveDescriptorRingSize = Adapter->DescriptorSize * Adapter->ReceiveRingSize; Adapter->DescriptorRing.AllocSize = TransmitDescriptorRingSize + ReceiveDescriptorRingSize + DC21X4_SETUP_BUFFER_SIZE + Adapter->CacheLineSize; NdisMAllocateSharedMemory( Adapter->MiniportAdapterHandle, Adapter->DescriptorRing.AllocSize, FALSE, // NON-CACHED (PVOID *)&Adapter->DescriptorRing.AllocVa, // virtual ... &Adapter->DescriptorRing.AllocPa // and physical address of the allocation ); // Check the allocation success if ((PVOID)Adapter->DescriptorRing.AllocVa == (PVOID)NULL) { return FALSE; } if (NdisGetPhysicalAddressHigh(Adapter->DescriptorRing.AllocPa) != 0) { return FALSE; } NdisZeroMemory ( (PVOID)(Adapter->DescriptorRing.AllocVa), (ULONG)(Adapter->DescriptorRing.AllocSize) ); // Align to the next cache line boundary AlignStructure ( &Adapter->DescriptorRing, Adapter->CacheLineSize ); Adapter->TransmitDescriptorRingVa = Adapter->DescriptorRing.Va; Adapter->TransmitDescriptorRingPa = Adapter->DescriptorRing.Pa; Offset = TransmitDescriptorRingSize; Adapter->ReceiveDescriptorRingVa = Adapter->DescriptorRing.Va + Offset; Adapter->ReceiveDescriptorRingPa = Adapter->DescriptorRing.Pa + Offset; Offset += ReceiveDescriptorRingSize; Adapter->SetupBufferVa = Adapter->DescriptorRing.Va + Offset; Adapter->SetupBufferPa = Adapter->DescriptorRing.Pa + Offset; //Initialize the setup buffer NdisZeroMemory ( (PVOID)(Adapter->SetupBufferVa), DC21X4_SETUP_BUFFER_SIZE ); // Allocate a pool of NDIS buffers NdisAllocateBufferPool( &Status, &Adapter->FlushBufferPoolHandle, ( Adapter->ReceiveRingSize + Adapter->ExtraReceiveBuffers + DC21X4_NUMBER_OF_MAX_TRANSMIT_BUFFERS + DC21X4_NUMBER_OF_MIN_TRANSMIT_BUFFERS ) ); if (Status != NDIS_STATUS_SUCCESS) { return FALSE; } // Allocate a pool of packets. #if _DBG DbgPrint("Allocate PacketPool [%d packets]\n", Adapter->ExtraReceivePackets); #endif NdisAllocatePacketPool( &Status, &Adapter->ReceivePacketPool, Adapter->ExtraReceivePackets, 0 ); if (Status != NDIS_STATUS_SUCCESS) { return FALSE; } // Allocate all of the packets out of the packet pool // and place them on a queue. for (i = 0; i < Adapter->ExtraReceivePackets; i++) { // Allocate a packet from the pool. NdisAllocatePacket( &Status, &Packet, Adapter->ReceivePacketPool ); if (Status != NDIS_STATUS_SUCCESS) { return(FALSE); } // Set the header size in the packet's Out-Of-Band information. // All other fields in the Out-Of-Band information have been // initialized to 0 by NdisAllocatePacket(). NDIS_SET_PACKET_HEADER_SIZE(Packet, ETH_HEADER_SIZE); // Place it on the receive packet free list. RCV_RESERVED(Packet)->Next = Adapter->FreePacketList; Adapter->FreePacketList = Packet; } // Clear out the free receive list of buffers. Adapter->FreeRcvList = NULL; // We allocate the receive buffers. We allocate both // the buffers for the descriptor ring and the extra // buffers and place them all on the free queue. #if _DBG DbgPrint("Allocate Receive Buffers [%d]\n", Adapter->ExtraReceiveBuffers+Adapter->ReceiveRingSize); #endif // Attempt to allocate all the receive buffer space // in one block // If it fails,allocate each buffer individually // Allocation size Adapter->RcvBufferSpace.AllocSize = ((Adapter->ExtraReceiveBuffers + Adapter->ReceiveRingSize) * (DC21X4_RECEIVE_BUFFER_SIZE + Adapter->RcvHeaderSize)) + Adapter->CacheLineSize; NdisMAllocateSharedMemory( Adapter->MiniportAdapterHandle, Adapter->RcvBufferSpace.AllocSize, TRUE, (PVOID *)&Adapter->RcvBufferSpace.AllocVa, &Adapter->RcvBufferSpace.AllocPa ); // Check the allocation success if (((PVOID)Adapter->RcvBufferSpace.AllocVa != (PVOID)NULL) && (NdisGetPhysicalAddressHigh(Adapter->RcvBufferSpace.AllocPa) == 0)) { NdisZeroMemory ( (PVOID)(Adapter->RcvBufferSpace.AllocVa), (ULONG)(Adapter->RcvBufferSpace.AllocSize) ); // Align to the next cache line boundary AlignStructure ( &Adapter->RcvBufferSpace, Adapter->CacheLineSize ); // Allocation size needed for the receive buffer AllocSize = DC21X4_RECEIVE_BUFFER_SIZE + Adapter->RcvHeaderSize; Offset=0; } else { // Allocation size needed for the receive buffer AllocSize = DC21X4_RECEIVE_BUFFER_SIZE + Adapter->RcvHeaderSize + Adapter->CacheLineSize; Adapter->RcvBufferSpace.Va=0; } for (i = 0; i < (Adapter->ExtraReceiveBuffers + Adapter->ReceiveRingSize); i++ ) { if (Adapter->RcvBufferSpace.Va != 0) { Va = Adapter->RcvBufferSpace.Va + Offset; Pa = Adapter->RcvBufferSpace.Pa + Offset; Offset += AllocSize; } else { // Allocate a receive buffer. NdisMAllocateSharedMemory( Adapter->MiniportAdapterHandle, AllocSize, TRUE, (PVOID *)&AllocVa, &AllocPa ); if (((PVOID)AllocVa == (PVOID)NULL) || (NdisGetPhysicalAddressHigh(AllocPa) != 0)) { return FALSE; } NdisZeroMemory(AllocVa, AllocSize); // Align on the cache line boundary Offset = Adapter->CacheLineSize - ((ULONG)AllocVa % Adapter->CacheLineSize); Va = (ULONG)(AllocVa) + Offset; Pa = NdisGetPhysicalAddressLow(AllocPa) + Offset; } //The receive header points to the aligned va. RcvHeader = (PRCV_HEADER)Va; RcvHeader->AllocVa = (ULONG)AllocVa; RcvHeader->AllocPa = AllocPa; RcvHeader->AllocSize = (USHORT)AllocSize; // These addresses point to the data buffer RcvHeader->Va = (ULONG)(Va + Adapter->RcvHeaderSize); RcvHeader->Pa = Pa + Adapter->RcvHeaderSize; RcvHeader->Size = DC21X4_RECEIVE_BUFFER_SIZE; #if DBG RcvHeader->Signature = 'dHxR'; #if _DBG DbgPrint( "%-3d RcvHeader: %lx, RcvBuffer: %lx/%lx, HeaderSize: %lx\n", i,RcvHeader, RcvHeader->Va, RcvHeader->Pa, Adapter->RcvHeaderSize ); #endif #endif // Allocate an NDIS flush buffer for each receive buffer. NdisAllocateBuffer( &Status, &RcvHeader->FlushBuffer, Adapter->FlushBufferPoolHandle, (PVOID)RcvHeader->Va, DC21X4_RECEIVE_BUFFER_SIZE ); if (Status != NDIS_STATUS_SUCCESS) { return FALSE; } // Grab a packet off of the free packet list and // associate it with the buffer. Packet = Adapter->FreePacketList; Adapter->FreePacketList = RCV_RESERVED(Packet)->Next; // Chain the buffer on the packet. NdisChainBufferAtFront(Packet, RcvHeader->FlushBuffer); // Save a pointer to the receive header with the packet. RCV_RESERVED(Packet)->RcvHeader = RcvHeader; // Save the packet with the receive header. RcvHeader->Packet = Packet; // Place the descriptor on the free queue. RcvHeader->Next = Adapter->FreeRcvList; Adapter->FreeRcvList = RcvHeader; Adapter->CurrentReceiveBufferCount++; } #if _DBG DbgPrint("Init Rcv ring..\n"); #endif // Assign the receive buffers to the descriptors. for (i = 0, ReceiveDescriptor = (PDC21X4_RECEIVE_DESCRIPTOR)Adapter->ReceiveDescriptorRingVa, Pa = Adapter->ReceiveDescriptorRingPa; i < Adapter->ReceiveRingSize; i++, (PCHAR)ReceiveDescriptor += Adapter->DescriptorSize, Pa += Adapter->DescriptorSize ) { // Grab a receive buffer from the free list. ASSERT(Adapter->FreeRcvList != NULL); RcvHeader = Adapter->FreeRcvList; Adapter->FreeRcvList = RcvHeader->Next; Adapter->CurrentReceiveBufferCount--; // Associate the buffer with the descriptor. ReceiveDescriptor->RcvHeader = RcvHeader; ReceiveDescriptor->FirstBufferAddress = RcvHeader->Pa; ReceiveDescriptor->Status = DESC_OWNED_BY_DC21X4; ReceiveDescriptor->Control = DC21X4_RECEIVE_BUFFER_SIZE; ReceiveDescriptor->Next = (PDC21X4_RECEIVE_DESCRIPTOR)((PCHAR)ReceiveDescriptor + Adapter->DescriptorSize); } //last descriptor of the ring (PCHAR)ReceiveDescriptor -= Adapter->DescriptorSize; ReceiveDescriptor->Control |= DC21X4_RDES_SECOND_ADDR_CHAINED; ReceiveDescriptor->SecondBufferAddress = Adapter->ReceiveDescriptorRingPa; ReceiveDescriptor->Next = (PDC21X4_RECEIVE_DESCRIPTOR)Adapter->ReceiveDescriptorRingVa; #if _DBG DbgPrint("Init Txm ring..\n"); #endif // Initialize the Transmit Descriptor ring for (i=0, TransmitDescriptor = (PDC21X4_TRANSMIT_DESCRIPTOR)Adapter->TransmitDescriptorRingVa, Pa = Adapter->TransmitDescriptorRingPa; i < TRANSMIT_RING_SIZE; i++, (PCHAR)TransmitDescriptor += Adapter->DescriptorSize, Pa += Adapter->DescriptorSize ) { TransmitDescriptor->MapTableIndex = i * NUMBER_OF_SEGMENT_PER_DESC; TransmitDescriptor->DescriptorPa = Pa; TransmitDescriptor->Next = (PDC21X4_TRANSMIT_DESCRIPTOR)((PCHAR)TransmitDescriptor + Adapter->DescriptorSize); } //last descriptor of the ring (PCHAR)TransmitDescriptor -= Adapter->DescriptorSize; TransmitDescriptor->Control = DC21X4_TDES_SECOND_ADDR_CHAINED; TransmitDescriptor->SecondBufferAddress = Adapter->TransmitDescriptorRingPa; TransmitDescriptor->Next = (PDC21X4_TRANSMIT_DESCRIPTOR)Adapter->TransmitDescriptorRingVa; // Txm buffers for (i = 0;i < DC21X4_NUMBER_OF_MAX_TRANSMIT_BUFFERS;i ++) { Adapter->MaxTransmitBuffer[i].AllocSize = DC21X4_MAX_TRANSMIT_BUFFER_SIZE + Adapter->CacheLineSize; NdisMAllocateSharedMemory( Adapter->MiniportAdapterHandle, Adapter->MaxTransmitBuffer[i].AllocSize, TRUE, // CACHED (PVOID *)&Adapter->MaxTransmitBuffer[i].AllocVa, // virtual ... &Adapter->MaxTransmitBuffer[i].AllocPa // and physical address of the buffer allocation ); // Check the allocation success if (((PVOID)Adapter->MaxTransmitBuffer[i].AllocVa == (PVOID)NULL) || (NdisGetPhysicalAddressHigh(Adapter->MaxTransmitBuffer[i].AllocPa) != 0)) { return FALSE; } // Align the buffer on the cache line boundary AlignStructure ( &Adapter->MaxTransmitBuffer[i], Adapter->CacheLineSize ); // Allocate an NDIS flush buffer for each transmit buffer NdisAllocateBuffer( &Status, &Adapter->MaxTransmitBuffer[i].FlushBuffer, Adapter->FlushBufferPoolHandle, (PVOID)Adapter->MaxTransmitBuffer[i].Va, DC21X4_MAX_TRANSMIT_BUFFER_SIZE ); if (Status != NDIS_STATUS_SUCCESS) { return FALSE; } } // Allocate the minimal packet buffers Adapter->MinTransmitBuffer[0].AllocSize = (DC21X4_NUMBER_OF_MIN_TRANSMIT_BUFFERS * DC21X4_MIN_TRANSMIT_BUFFER_SIZE) + Adapter->CacheLineSize; NdisMAllocateSharedMemory( Adapter->MiniportAdapterHandle, Adapter->MinTransmitBuffer[0].AllocSize, TRUE, // CACHED (PVOID *)&Adapter->MinTransmitBuffer[0].AllocVa, // virtual ... &Adapter->MinTransmitBuffer[0].AllocPa // and physical address of the buffer allocation ); // Check the allocation success if (((PVOID)Adapter->MinTransmitBuffer[0].AllocVa == (PVOID)NULL) || (NdisGetPhysicalAddressHigh(Adapter->MinTransmitBuffer[0].AllocPa) != 0)) { Adapter->DontUseMinTransmitBuffer = TRUE; return TRUE; } // Align the buffer on the cache line boundary AlignStructure ( &Adapter->MinTransmitBuffer[0], Adapter->CacheLineSize ); for (i = 0;i < DC21X4_NUMBER_OF_MIN_TRANSMIT_BUFFERS;i ++) { Offset = i * DC21X4_MIN_TRANSMIT_BUFFER_SIZE; Adapter->MinTransmitBuffer[i].Va = Adapter->MinTransmitBuffer[0].Va + Offset; Adapter->MinTransmitBuffer[i].Pa = Adapter->MinTransmitBuffer[0].Pa + Offset; // Allocate an NDIS flush buffer for each transmit buffer NdisAllocateBuffer( &Status, &Adapter->MinTransmitBuffer[i].FlushBuffer, Adapter->FlushBufferPoolHandle, (PVOID)Adapter->MinTransmitBuffer[i].Va, DC21X4_MIN_TRANSMIT_BUFFER_SIZE ); if (Status != NDIS_STATUS_SUCCESS) { return FALSE; } } // Allocation has completed successfully return TRUE; }
INT natpReceivePacketPassThrough( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN FLT_PKT* pFltPkt ) { PFILTER_ADAPTER pAdapt =(PFILTER_ADAPTER)ProtocolBindingContext; NDIS_STATUS Status; PNDIS_PACKET MyPacket; BOOLEAN Remaining; PNDIS_BUFFER pNewBuffer; if (NULL == pAdapt->MiniportHandle || pAdapt->natmDeviceState > NdisDeviceStateD0) return 0; NdisIMGetCurrentPacketStack(Packet, &Remaining); if (NULL == pFltPkt && Remaining){ Status = NDIS_GET_PACKET_STATUS(Packet); NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1); return Status != NDIS_STATUS_RESOURCES ? 1 : 0; } if(NULL == pFltPkt){ NdisDprAllocatePacket( &Status, &MyPacket, pAdapt->RcvPP1 ); if (Status != NDIS_STATUS_SUCCESS){ return 0; } *((PVOID*)&MyPacket->MiniportReserved) = Packet; MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; }else{ NdisDprAllocatePacket( &Status, &MyPacket, pAdapt->RcvPP2 ); if (Status != NDIS_STATUS_SUCCESS) return NDIS_STATUS_NOT_ACCEPTED; *((PVOID*)&MyPacket->MiniportReserved) = pFltPkt; NdisAllocateBuffer( &Status, &pNewBuffer, pAdapt->RcvBP, pFltPkt->pBuf, pFltPkt->uLen ); if ( Status != NDIS_STATUS_SUCCESS ){ NdisReinitializePacket (MyPacket); NdisFreePacket (MyPacket); return 0; } NdisChainBufferAtFront(MyPacket, pNewBuffer ); } NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet)); NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet); Status = NDIS_GET_PACKET_STATUS(Packet); NDIS_SET_PACKET_STATUS(MyPacket, Status); NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet)); if (Status == NDIS_STATUS_RESOURCES){ natpQueueReceivedPacket(pAdapt, MyPacket, TRUE); }else{ natpQueueReceivedPacket(pAdapt, MyPacket, FALSE); } if (Status == NDIS_STATUS_RESOURCES) NdisDprFreePacket(MyPacket); return Status != NDIS_STATUS_RESOURCES ? 1 : 0; }
NDIS_STATUS natpReceive( IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize ) { PFILTER_ADAPTER pAdapt; PNDIS_PACKET Packet; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; NDIS_STATUS PacketStatus; PNDIS_PACKET pNewPacket; ULONG nDataSize; FLT_PKT *pFltPkt; PNDIS_BUFFER pNewBuffer; pAdapt = (PFILTER_ADAPTER)ProtocolBindingContext; if ((!pAdapt->MiniportHandle) || (pAdapt->natmDeviceState > NdisDeviceStateD0)){ return NDIS_STATUS_FAILURE; } nDataSize = HeaderBufferSize + PacketSize; if ( nDataSize > MAX_ETHER_SIZE ){ return NDIS_STATUS_FAILURE; } Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext); if (NULL == Packet) return NDIS_STATUS_NOT_ACCEPTED; pFltPkt = AllocateFltPacket(); if(NULL == pFltPkt) return NDIS_STATUS_NOT_ACCEPTED; if(!natbParsePacket(Packet, pFltPkt)){ if(g_LogPktDrop) PrintFtlPkt("DROP ", pFltPkt, 0, FALSE); FreeFltPkt(pFltPkt); return NDIS_STATUS_NOT_ACCEPTED; } // // Translate // TranslatePktIncoming(&pAdapt->ctrl, pFltPkt); // // Filter // if(!FilterPkt(&pAdapt->ctrl, pFltPkt, FALSE)){ if(g_LogPktDrop) PrintFtlPkt("DROP ", pFltPkt, 0, FALSE); FreeFltPkt(pFltPkt); return NDIS_STATUS_NOT_ACCEPTED; } if(g_LogPktPass) PrintFtlPkt("PASS ", pFltPkt, 0, FALSE); if(NULL == pFltPkt->pBuf){ FreeFltPkt(pFltPkt); pFltPkt = NULL; NdisDprAllocatePacket( &Status, &pNewPacket, pAdapt->RcvPP1 ); if (Status != NDIS_STATUS_SUCCESS) { return NDIS_STATUS_NOT_ACCEPTED; } *((PVOID*)&pNewPacket->MiniportReserved) = NULL; pNewPacket->Private.Head = Packet->Private.Head; pNewPacket->Private.Tail = Packet->Private.Tail; }else{ NdisDprAllocatePacket( &Status, &pNewPacket, pAdapt->RcvPP2 ); if (Status != NDIS_STATUS_SUCCESS) return NDIS_STATUS_NOT_ACCEPTED; *((PVOID*)&pNewPacket->MiniportReserved) = pFltPkt; NdisAllocateBuffer( &Status, &pNewBuffer, pAdapt->RcvBP, pFltPkt->pBuf, pFltPkt->uLen ); if ( Status != NDIS_STATUS_SUCCESS ){ NdisReinitializePacket (pNewPacket); NdisFreePacket (pNewPacket); return NDIS_STATUS_NOT_ACCEPTED; } NdisChainBufferAtFront(pNewPacket, pNewBuffer ); } NdisGetPacketFlags(pNewPacket) = NdisGetPacketFlags(Packet); NDIS_SET_PACKET_STATUS(pNewPacket, NDIS_STATUS_RESOURCES); NDIS_SET_ORIGINAL_PACKET(pNewPacket, NDIS_GET_ORIGINAL_PACKET(Packet)); NDIS_SET_PACKET_HEADER_SIZE(pNewPacket, HeaderBufferSize); natpQueueReceivedPacket(pAdapt, pNewPacket, TRUE); natmReturnPacket( ProtocolBindingContext, pNewPacket ); return Status; }
/****************************************************************************** * * Name: AllocateRxQ() * * Description: Allocate Rx Buffer * * Arguments: PMRVDRV_ADAPTER Adapter * * Return Value: NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE * * Notes: * *****************************************************************************/ NDIS_STATUS AllocateRxQ( IN PMRVDRV_ADAPTER Adapter ) { ULONG i; NDIS_STATUS tStatus; BOOLEAN bSuccess = TRUE; PACKET_QUEUE_NODE **pNode; PNDIS_PACKET_OOB_DATA pOOB; /// Initialize rx-related variables Adapter->RxBufferPoolHandle = Adapter->RxPacketPoolHandle = NULL; // InitializeQKeeper(&Adapter->RxPacketFreeQueue); // for ( i=0; i < MRVDRV_NUM_RX_PKT_IN_QUEUE; i++ ) { Adapter->pRxBufVM[i] = NULL; Adapter->pRxBuffer[i] = NULL; Adapter->pRxPacket[i] = NULL; } /// Allocate all needed memory space do { // packet pool NdisAllocatePacketPoolEx( &tStatus, &Adapter->RxPacketPoolHandle, MRVDRV_NUM_RX_PKT_IN_QUEUE, MRVDRV_NUM_RX_PKT_IN_QUEUE, PROTOCOL_RESERVED_SIZE_IN_PACKET); if ( tStatus != NDIS_STATUS_SUCCESS ) { DBGPRINT(DBG_LOAD | DBG_ERROR, (L"Unable to allocate packet pool!\n")); return tStatus; } // buffer pool NdisAllocateBufferPool( &tStatus, &Adapter->RxBufferPoolHandle, MRVDRV_NUM_RX_PKT_IN_QUEUE); if ( tStatus != NDIS_STATUS_SUCCESS ) { DBGPRINT(DBG_LOAD | DBG_ERROR, (L"Unable to allocate buffer pool!\n")); bSuccess = FALSE; break; } // assign space to used three array for ( i=0; i < MRVDRV_NUM_RX_PKT_IN_QUEUE; i++ ) { // data payload space array tStatus = NdisAllocateMemoryWithTag( &Adapter->pRxBufVM[i], MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, MRVDRV_MEMORY_TAG); //to hide unused packet header ahead of pointer. //(ULONG)Adapter->pRxBufVM[i] += (sizeof(RxPD)+sizeof(pkt.Len)+sizeof(pkt.Type)); (ULONG)Adapter->pRxBufVM[i] += MRVDRV_ETH_RX_HIDDEN_HEADER_SIZE; if ( tStatus != NDIS_STATUS_SUCCESS ) { bSuccess = FALSE; break; } // buffer array NdisAllocateBuffer( &tStatus, &Adapter->pRxBuffer[i], Adapter->RxBufferPoolHandle, Adapter->pRxBufVM[i], (MRVDRV_ETH_RX_PACKET_BUFFER_SIZE-MRVDRV_ETH_RX_HIDDEN_HEADER_SIZE)); if ( tStatus != NDIS_STATUS_SUCCESS ) { bSuccess = FALSE; break; } // packet array NdisAllocatePacket( &tStatus, &Adapter->pRxPacket[i], Adapter->RxPacketPoolHandle); if ( tStatus != NDIS_STATUS_SUCCESS ) { bSuccess = FALSE; break; } // init OBB space pOOB = NDIS_OOB_DATA_FROM_PACKET(Adapter->pRxPacket[i]); NdisZeroMemory(pOOB, sizeof(NDIS_PACKET_OOB_DATA)); NDIS_SET_PACKET_HEADER_SIZE(Adapter->pRxPacket[i], MRVDRV_ETH_HEADER_SIZE); // chain the packet and buffer NdisChainBufferAtFront(Adapter->pRxPacket[i], Adapter->pRxBuffer[i]); // fill packet node Adapter->RxPacketQueueNode[i].pPacket = Adapter->pRxPacket[i]; pNode = (PACKET_QUEUE_NODE **)Adapter->pRxPacket[i]->MiniportReserved; *pNode = &Adapter->RxPacketQueueNode[i]; // insert to free queue InsertQNodeAtTail(&Adapter->RxPacketFreeQueue, &Adapter->RxPacketQueueNode[i]); } // end of for(;;) } while (0); if ( ! bSuccess ) { // clean up all FreeRxQ(Adapter); return NDIS_STATUS_FAILURE; } Adapter->sNumOutstandingRxPacket = 0; return NDIS_STATUS_SUCCESS; }
NDIS_STATUS PtReceive( IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize ) /*++ Routine Description: Handle receive data indicated up by the miniport below. We pass it along to the protocol above us. If the miniport below indicates packets, NDIS would more likely call us at our ReceivePacket handler. However we might be called here in certain situations even though the miniport below has indicated a receive packet, e.g. if the miniport had set packet status to NDIS_STATUS_RESOURCES. Arguments: <see DDK ref page for ProtocolReceive> Return Value: NDIS_STATUS_SUCCESS if we processed the receive successfully, NDIS_STATUS_XXX error code if we discarded it. --*/ { PADAPT pAdapt =(PADAPT)ProtocolBindingContext; PNDIS_PACKET MyPacket, Packet; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; if (!pAdapt->MiniportHandle) { Status = NDIS_STATUS_FAILURE; } else do { // // Get at the packet, if any, indicated up by the miniport below. // Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext); if (Packet != NULL) { //------------------------------WestChamber--------------------------------- BOOLEAN result=WestChamberReceiverMain(Packet,pAdapt); if(result==FALSE) { //Simply drop the packet. return NDIS_STATUS_NOT_ACCEPTED; } //------------------------------WestChamber--------------------------------- // // The miniport below did indicate up a packet. Use information // from that packet to construct a new packet to indicate up. // #ifdef NDIS51 // // NDIS 5.1 NOTE: Do not reuse the original packet in indicating // up a receive, even if there is sufficient packet stack space. // If we had to do so, we would have had to overwrite the // status field in the original packet to NDIS_STATUS_RESOURCES, // and it is not allowed for protocols to overwrite this field // in received packets. // #endif // NDIS51 // // Get a packet off the pool and indicate that up // NdisDprAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle); if (Status == NDIS_STATUS_SUCCESS) { // // Make our packet point to data from the original // packet. NOTE: this works only because we are // indicating a receive directly from the context of // our receive indication. If we need to queue this // packet and indicate it from another thread context, // we will also have to allocate a new buffer and copy // over the packet contents, OOB data and per-packet // information. This is because the packet data // is available only for the duration of this // receive indication call. // MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; // // Get the original packet (it could be the same packet as the // one received or a different one based on the number of layered // miniports below) and set it on the indicated packet so the OOB // data is visible correctly at protocols above. // NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet)); NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize); // // Copy packet flags. // NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet); // // Force protocols above to make a copy if they want to hang // on to data in this packet. This is because we are in our // Receive handler (not ReceivePacket) and we can't return a // ref count from here. // NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES); // // By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim // this packet as soon as the call to NdisMIndicateReceivePacket // returns. // NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1); // // Reclaim the indicated packet. Since we had set its status // to NDIS_STATUS_RESOURCES, we are guaranteed that protocols // above are done with it. // NdisDprFreePacket(MyPacket); break; } } else { // // The miniport below us uses the old-style (not packet) // receive indication. Fall through. // } // // Fall through if the miniport below us has either not // indicated a packet or we could not allocate one // pAdapt->IndicateRcvComplete = TRUE; switch (pAdapt->Medium) { case NdisMedium802_3: case NdisMediumWan: NdisMEthIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break; case NdisMedium802_5: NdisMTrIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break; case NdisMediumFddi: /* NdisMFddiIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); */ break; default: ASSERT(FALSE); break; } } while(FALSE); return Status; }
INT PtReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ) /*++ Routine Description: ReceivePacket handler. Called by NDIS if the miniport below supports NDIS 4.0 style receives. Re-package the buffer chain in a new packet and indicate the new packet to protocols above us. Any context for packets indicated up must be kept in the MiniportReserved field. NDIS 5.1 - packet stacking - if there is sufficient "stack space" in the packet passed to us, we can use the same packet in a receive indication. Arguments: ProtocolBindingContext - Pointer to our adapter structure. Packet - Pointer to the packet Return Value: == 0 -> We are done with the packet != 0 -> We will keep the packet and call NdisReturnPackets() this many times when done. --*/ { PADAPT pAdapt =(PADAPT)ProtocolBindingContext; NDIS_STATUS Status; PNDIS_PACKET MyPacket; BOOLEAN Remaining; //------------------------------WestChamber--------------------------------- BOOLEAN result=WestChamberReceiverMain(Packet,pAdapt); if(result==FALSE) { //Simply drop the packet. //return NDIS_STATUS_NOT_ACCEPTED; return 0; //Thanks to Albert Jin. } //------------------------------WestChamber--------------------------------- // // Drop the packet silently if the upper miniport edge isn't initialized // if (!pAdapt->MiniportHandle) { return 0; } #ifdef NDIS51 // // Check if we can reuse the same packet for indicating up. // See also: PtReceive(). // (VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining); if (Remaining) { // // We can reuse "Packet". Indicate it up and be done with it. // Status = NDIS_GET_PACKET_STATUS(Packet); NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1); return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0); } #endif // NDIS51 // // Get a packet off the pool and indicate that up // NdisDprAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle); if (Status == NDIS_STATUS_SUCCESS) { PRECV_RSVD RecvRsvd; RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved); RecvRsvd->OriginalPkt = Packet; MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; // // Get the original packet (it could be the same packet as the one // received or a different one based on the number of layered miniports // below) and set it on the indicated packet so the OOB data is visible // correctly to protocols above us. // NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet)); // // Set Packet Flags // NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet); Status = NDIS_GET_PACKET_STATUS(Packet); NDIS_SET_PACKET_STATUS(MyPacket, Status); NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet)); NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1); // // Check if we had indicated up the packet with NDIS_STATUS_RESOURCES // NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since // it might have changed! Use the value saved in the local variable. // if (Status == NDIS_STATUS_RESOURCES) { // // Our ReturnPackets handler will not be called for this packet. // We should reclaim it right here. // NdisDprFreePacket(MyPacket); } return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0); } else { // // We are out of packets. Silently drop it. // return(0); } }
/*-------------------------------------------------------------------------- ssh_interceptor_send() Sends packet either down to the network or up to the protocol. --------------------------------------------------------------------------*/ void ssh_interceptor_send(SshInterceptor interceptor, SshInterceptorPacket ip, size_t media_header_len) { SshNdisPacket packet; ULONG first_buf_len = SSH_ETHERH_HDRLEN; SshNdisIMAdapter adapter; SshCpuContext cpu_ctx; Boolean use_one_buffer = FALSE; ULONG new_value; /* Sanity checks for arguments */ SSH_ASSERT(interceptor != NULL); SSH_ASSERT(ip != NULL); SSH_ASSERT((ip->flags & SSH_PACKET_FROMADAPTER) != (ip->flags & SSH_PACKET_FROMPROTOCOL)); #ifndef _WIN32_WCE SSH_ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); #endif /* _WIN32_WCE */ cpu_ctx = &interceptor->cpu_ctx[ssh_kernel_get_cpu()]; packet = CONTAINING_RECORD(ip, SshNdisPacketStruct, ip); #ifdef DEBUG_LIGHT packet->f.flags.in_engine = 0; #endif /* DEBUG_LIGHT */ adapter = (SshNdisIMAdapter)packet->adapter_in; /* Check if adapter where the packet should be sent is different where the packet originated from */ if (adapter && (adapter->ifnum == ip->ifnum_out)) { new_value = InterlockedIncrement(&adapter->ref_count); packet->adapter_out = (SshAdapter)adapter; } else { SshAdapter gen_adapter = NULL; if (ip->ifnum_out < SSH_INTERCEPTOR_MAX_ADAPTERS) { ssh_kernel_rw_mutex_lock_read(&interceptor->adapter_lock); gen_adapter = interceptor->adapter_table[ip->ifnum_out]; if (gen_adapter) { new_value = InterlockedIncrement(&gen_adapter->ref_count); packet->adapter_out = gen_adapter; } ssh_kernel_rw_mutex_unlock_read(&interceptor->adapter_lock); } if (gen_adapter == NULL) goto free_packet; adapter = (SshNdisIMAdapter)gen_adapter; } SSH_ASSERT(new_value > 0); /* Check that active adapter found and it supports the protocol */ if (!ssh_adapter_is_enabled((SshNdisIMAdapter)adapter)) { SSH_DEBUG(SSH_D_FAIL, ("active network connection not found")); goto free_packet; } #ifndef _WIN32_WCE /* Check if packet is plain IPv4 (IPv6) and then add ethernet framing */ if (ip->protocol == SSH_PROTOCOL_IP4 || ip->protocol == SSH_PROTOCOL_IP6) { if (!ssh_wan_packet_encapsulate((SshAdapter)adapter, ip)) { SSH_DEBUG(SSH_D_FAIL, ("packet framing failed")); goto free_packet; } /* Some dial-up drivers seem to expect to receive whole packet in one NDIS buffer. */ if (ip->flags & SSH_PACKET_FROMADAPTER) use_one_buffer = TRUE; } #endif /* _WIN32_WCE */ /* Add the VLAN tagging, if any */ if (packet->vlan_tag_count > 0) { if (adapter != (SshNdisIMAdapter)packet->adapter_in) { /* Engine forwards this packet to different interface. Check whether this is VLAN/QoS enabled interface and reconstruct tagging accordingly. */ switch (adapter->options & (NDIS_MAC_OPTION_8021Q_VLAN | NDIS_MAC_OPTION_8021P_PRIORITY)) { case 0: /* Adapter doesn't support IEEE 802.1q/p; drop VLAN tag(s). */ packet->vlan_tag_count = 0; break; case NDIS_MAC_OPTION_8021P_PRIORITY: /* Adapter supports only priority (QoS) tagging. */ packet->vlan_tags[0].vlan_id = 0; packet->vlan_tag_count = 1; break; default: /* Adapter supports also VLAN. Change the VLAN ID of the first tag to the one configued to this NIC driver. */ packet->vlan_tags[0].vlan_id = adapter->vlan_id; break; } } if (packet->vlan_tag_count) { unsigned char *vlan_tags; SshUInt16 i; vlan_tags = ssh_interceptor_packet_insert(ip, SSH_ETHERH_OFS_TYPE, packet->vlan_tag_count * 4); if (vlan_tags == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Failed to add VLAN tags")); return; } for (i = 0; i < packet->vlan_tag_count; i++) { unsigned char *tag = vlan_tags + (i * 4); SSH_PUT_16BIT(tag, SSH_ETHERTYPE_VLAN); SSH_PUT_16BIT((tag + 2), (packet->vlan_tags[i].vlan_id << 4 | packet->vlan_tags[i].qos)); } } } NDIS_SET_PACKET_HEADER_SIZE(packet->np, SSH_ETHERH_HDRLEN); NDIS_SET_PACKET_STATUS(packet->np, NDIS_STATUS_SUCCESS); #ifdef _WIN32_WCE if (adapter->media == NdisMediumWan) { if (ip->flags & SSH_PACKET_FROMPROTOCOL) { if (!ssh_wan_send_to_adapter(adapter, packet, ip->protocol)) SSH_DEBUG(SSH_D_FAIL, ("Cannot send packet to WAN adapter")); } else if (ip->flags & SSH_PACKET_FROMADAPTER) { if (!ssh_wan_send_to_protocol(adapter, packet, ip->protocol)) SSH_DEBUG(SSH_D_FAIL, ("Cannot send packet to WAN protocol")); } else { SSH_DEBUG(SSH_D_ERROR, ("Dropping WAN packet without direction")); } ssh_interceptor_packet_free(&packet->ip); return; } #endif /* _WIN32_WCE */ if (ip->flags & SSH_PACKET_FROMPROTOCOL) { NDIS_STATUS status; /* Send packet to network */ NdisSetPacketFlags(packet->np, NDIS_FLAGS_DONT_LOOPBACK); if (cpu_ctx->in_packet_cb || cpu_ctx->in_route_cb || cpu_ctx->in_timeout_cb) { SSH_DEBUG(SSH_D_NICETOKNOW, ("Risk for recursive call; enqueueing packet 0x%p", packet)); #ifdef DEBUG_LIGHT packet->f.flags.in_send_queue = 1; #endif /* DEBUG_LIGHT */ if (cpu_ctx->in_packet_cb) { ssh_net_packet_enqueue(&cpu_ctx->send_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_send_queue = 1; } else if (cpu_ctx->in_route_cb) { ssh_net_packet_enqueue(&cpu_ctx->route_send_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_route_send_queue = 1; } else if (cpu_ctx->in_timeout_cb) { ssh_net_packet_enqueue( &cpu_ctx->timeout_send_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_timeout_send_queue = 1; } } else { #ifdef DEBUG_LIGHT SSH_DEBUG(SSH_D_NICETOKNOW, ("Sending packet 0x%p to underlying driver", packet)); packet->f.flags.in_miniport = 1; #endif /* DEBUG_LIGHT */ NdisSend(&status, adapter->binding_handle, packet->np); if (status != NDIS_STATUS_PENDING) { SSH_DEBUG(SSH_D_NICETOKNOW, ("Send operation completed synchronously; " "packet=0x%p, status=%@", ssh_ndis_status_render, status)); ssh_interceptor_packet_free(&packet->ip); } } } else if (ip->flags & SSH_PACKET_FROMADAPTER) { /* Packet is ready now so check packet consistency */ if (use_one_buffer) first_buf_len = packet->packet_len; else first_buf_len += adapter->lookahead_size; first_buf_len = MIN(first_buf_len, packet->packet_len); if (!ssh_packet_get_contiguous_data((SshNetDataPacket)packet, 0, first_buf_len, FALSE)) { SSH_DEBUG(SSH_D_FAIL, ("Invalid packet")); goto free_packet; } if (cpu_ctx->in_packet_cb || cpu_ctx->in_route_cb || cpu_ctx->in_timeout_cb) { SSH_DEBUG(SSH_D_NICETOKNOW, ("Risk for recursive call; enqueueing packet 0x%p", packet)); #ifdef DEBUG_LIGHT packet->f.flags.in_recv_queue = 1; #endif /* DEBUG_LIGHT */ if (cpu_ctx->in_packet_cb) { ssh_net_packet_enqueue(&cpu_ctx->recv_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_recv_queue = 1; } else if (cpu_ctx->in_route_cb) { ssh_net_packet_enqueue(&cpu_ctx->route_recv_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_route_recv_queue = 1; } else if (cpu_ctx->in_timeout_cb) { ssh_net_packet_enqueue( &cpu_ctx->timeout_recv_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_timeout_recv_queue = 1; } } else { SSH_DEBUG(SSH_D_NICETOKNOW, ("Indicating packet 0x%p to upper layers", packet)); #ifdef DEBUG_LIGHT packet->f.flags.in_protocol = 1; #endif /* DEBUG_LIGHT */ NdisMIndicateReceivePacket(adapter->handle, &packet->np, 1); } } else { SSH_NOTREACHED; } return; free_packet: /* Otherwise just drop the packet */ SSH_DEBUG(SSH_D_FAIL, ("ssh_interceptor_send(): dropping packet")); ssh_interceptor_packet_free(&packet->ip); }