阅读:1713回复:3
passthru在不同网卡上运行,具然不兼容
基于passthru做了个内核的端口转发程序,功能是如果指定IP连接到本机端口A,修改数据包目的端口到B,数据发送时,做相反处理
在本人的Realtek RTL8168/8111网卡,和朋友的一个intel网卡上测试成功,今天又测试,网卡类型是HP的XXX型号, 可以建立连接,但是安装此驱动的服务器能建立连接接收数据,不能发送数据,驱动调试,发现捕捉到数据包,成功修改,可就是 带PUSH标志的也就是携带发送数据的TCP包不能出去,ACK这些,用在三步握手的数据包,可以正常通信 本人不服,改用IOCTL_IP_SET_FIREWALL_HOOK方式过滤修改数据包,结果具然跟NDIS的passthru测试结果一样,有些机器成功,有些不能 在passthru里,我修改了PtReceive, PtReceiveComplete里的数据包,,发送例程里,我修改了MpSend, MpSendPackets,尽管我知道这两个只会调用后者,但能拦的地方全拦了 我先直接修改packet链表指向的缓冲区,后来就复制一份修改,效果一样,都不行............. TCP.检验和绝对计算正确.....不是这的原因,可是这情况,郁闷一星期了.....能建立连接,服务器只能接收,不能发送给对方..... 高手请指点迷津. 由于接收正常,我只帖发送时的修改主过程,大大们分析下原因.郁闷的要死了 do { ULONG TotalPacketLength; PVOID MemoryVA; PNDIS_BUFFER PktBuffer = NULL; NdisAcquireSpinLock(&pAdapt->Lock); // // If the below miniport is going to low power state, stop sending down any packet. // if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisAllocatePacket(&Status, &MyPacket, pAdapt->SendPacketPoolHandle); ////////////////////////////////////////////////////////////////////////// // add if(Status != NDIS_STATUS_SUCCESS) { return ; } NdisQueryPacket(Packet, NULL, NULL, NULL, &TotalPacketLength); Status = NdisAllocateMemory(&MemoryVA, TotalPacketLength, 0, HighestAcceptableMax); if(Status == NDIS_STATUS_FAILURE) { // Release the memory NdisFreeMemory(MemoryVA, TotalPacketLength, //Maybe add a checksum length 0); return ; } NdisAllocateBuffer(&Status, &PktBuffer,pAdapt->SendPacketPoolHandle, MemoryVA, TotalPacketLength);//Maybe add a checksum length CopyPktToBuf(Packet, MemoryVA); NdisChainBufferAtBack(MyPacket, PktBuffer); // BEGIN_PTEX_FILTER // // 调用修改封包的函数 // FltDirectProcessPacket(MemoryVA, TotalPacketLength, TRUE); // END_PTEX_FILTER ////////////////////////////////////////////////////////////////////////// if (Status == NDIS_STATUS_SUCCESS) { PSEND_RSVD SendRsvd; PNDIS_PACKET_EXTENSION Old, New; SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); SendRsvd->OriginalPkt = Packet; MyPacket->Private.Flags = NdisGetPacketFlags(Packet); // MyPacket->Private.Head = Packet->Private.Head; // MyPacket->Private.Tail = Packet->Private.Tail; NdisSetPacketFlags(MyPacket, NDIS_FLAGS_DONT_LOOPBACK); Old = NDIS_PACKET_EXTENSION_FROM_PACKET(Packet); New = NDIS_PACKET_EXTENSION_FROM_PACKET(MyPacket); New->NdisPacketInfo[TcpIpChecksumPacketInfo] = Old->NdisPacketInfo[TcpIpChecksumPacketInfo]; New->NdisPacketInfo[IpSecPacketInfo] = Old->NdisPacketInfo[IpSecPacketInfo]; New->NdisPacketInfo[TcpLargeSendPacketInfo] = Old->NdisPacketInfo[TcpLargeSendPacketInfo]; New->NdisPacketInfo[ClassificationHandlePacketInfo] = Old->NdisPacketInfo[ClassificationHandlePacketInfo]; New->NdisPacketInfo[Ieee8021pPriority] = Old->NdisPacketInfo[Ieee8021pPriority]; #ifdef WIN9X // // Work around the fact that NDIS does not initialize this // to FALSE on Win9x. // MyPacket->Private.ValidCounts = FALSE; #endif // WIN9X // // Copy the OOB data from the original packet to the new // packet. // NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket), NDIS_OOB_DATA_FROM_PACKET(Packet), sizeof(NDIS_PACKET_OOB_DATA)); // // Copy relevant parts of the per packet info into the new packet // #ifndef WIN9X NdisIMCopySendPerPacketInfo(MyPacket, Packet); #endif // // Copy the Media specific information // NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, &MediaSpecificInfo, &MediaSpecificInfoSize); if (MediaSpecificInfo || MediaSpecificInfoSize) { NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket, MediaSpecificInfo, MediaSpecificInfoSize); } NdisSend(&Status, pAdapt->BindingHandle, MyPacket); if (Status != NDIS_STATUS_PENDING) { #ifndef WIN9X NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket); #endif NdisUnchainBufferAtBack(MyPacket,&PktBuffer); NdisFreeBuffer(PktBuffer); NdisFreeMemory(MemoryVA, TotalPacketLength, //Maybe add a checksum length 0); NdisFreePacket(MyPacket); ADAPT_DECR_PENDING_SENDS(pAdapt); } } else { // // The driver cannot allocate a packet. // ADAPT_DECR_PENDING_SENDS(pAdapt); } } while (FALSE); |
|
沙发#
发布于:2009-03-27 20:33
兄弟们帮帮忙啊...这问题已经郁闷了我一星期了
|
|
板凳#
发布于:2009-03-28 00:31
用driverstudio又做了一个,结果还是一样,哭啊,具体代码如下
BOOLEAN FltDirectProcessPacket(PVOID pPacketContent, UINT nPacketLength, BOOLEAN bIncludeETHdr) { ////////////////////////////////////////////////////////////////////////// // modify it struct libnet_ip_hdr * iph_p = NULL; struct libnet_tcp_hdr * tcph = NULL; BOOLEAN isPacketModify = FALSE; // 没有设置端口映射 if (0 == KernelPortMap.IpAddr) { return isPacketModify; } T.Trace(__FUNCTION__"\n"); // 不是IP协议 if (bIncludeETHdr && 0x8 != ((struct libnet_ethernet_hdr *)pPacketContent)->ether_type) { return isPacketModify; } if (nPacketLength < LIBNET_IP_H) { return isPacketModify; } iph_p = bIncludeETHdr ? (struct libnet_ip_hdr *)((char *)pPacketContent + sizeof(struct libnet_ethernet_hdr)) : (struct libnet_ip_hdr *)pPacketContent; if (IPPROTO_TCP != iph_p->ip_p) { return isPacketModify; } tcph = (struct libnet_tcp_hdr *)((char *)iph_p + (iph_p->ip_hl << 2)); // 防止溢出 if (nPacketLength < (LIBNET_IP_H + LIBNET_TCP_H)) { return isPacketModify; } if (/*iph_p->ip_src.s_addr == KernelPortMap.IpAddr && */tcph->th_dport == KernelPortMap.OrgPort) { T.Trace("libnet_do_checksum\n"); tcph->th_dport = KernelPortMap.MapPort; libnet_do_checksum((u_char *)iph_p, IPPROTO_TCP, ntohs(iph_p->ip_len) - LIBNET_TCP_H); isPacketModify = TRUE; } if (/*iph_p->ip_dst.s_addr == KernelPortMap.IpAddr && */tcph->th_sport == KernelPortMap.MapPort) { T.Trace("libnet_do_checksum\n"); tcph->th_sport = KernelPortMap.OrgPort; libnet_do_checksum((u_char *)iph_p, IPPROTO_TCP, ntohs(iph_p->ip_len) - LIBNET_TCP_H); isPacketModify = TRUE; } return isPacketModify; } VOID FltProcessPackage(KNdisPacket& Packet) { T.Trace(__FUNCTION__"\n"); UINT nTotalLength = Packet.QueryTotalLength(); PUCHAR lpPacket = new UCHAR[nTotalLength]; if (!lpPacket) return; UINT nBufCnt = Packet.QueryBufferCount(); KNdisBuffer ndisBuffer = Packet.QueryFirstBuffer(); UINT offset = 0; for(UINT i = 0; i < nBufCnt; i++) { if (ndisBuffer.IsValid()) { PUCHAR src = (PUCHAR)ndisBuffer.Address(); UINT len = ndisBuffer.Length(); NdisMoveMemory(lpPacket + offset, src, len); offset = offset + len; ndisBuffer = ndisBuffer.GetNext(); } } // 如果修改了 if (FltDirectProcessPacket(lpPacket, nTotalLength, TRUE)) { ndisBuffer = Packet.QueryFirstBuffer(); offset = 0; for(UINT i = 0; i < nBufCnt; i++) { if(ndisBuffer.IsValid()) { PUCHAR src = (PUCHAR)ndisBuffer.Address(); UINT len = ndisBuffer.Length(); NdisMoveMemory(src, lpPacket + offset, len); offset = offset + len; ndisBuffer = ndisBuffer.GetNext(); } } } delete lpPacket; } ////////////////////////////////////////////////////////////////////// // Constructor kpmAdapter::kpmAdapter() { // TODO: initialize your private data members // Do NOT call any NDIS functions in here. Defer to Initialize() m_BufferPool.Initialize(8); KernelPortMap.IpAddr = inet_addr("192.168.1.100"); KernelPortMap.OrgPort = htons(81); KernelPortMap.MapPort = htons(82); } ////////////////////////////////////////////////////////////////////// // Destructor kpmAdapter::~kpmAdapter() { // TODO: deallocate all the resources allocated in constructor/Initialize() // } //////////////////////////////////////////////////////////////////// // NDIS callback handlers //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// // kpmAdapter::OnInitialize // // The framework calls this method when a new virtual NIC represented // by the kpmAdapter is created. At this time the binding to the // underlying real NIC is completed already. Most of the glue work has // been done by the framework, so this method could just return // NDIS_STATUS_SUCCESS to grant the creation of the filter. Or, it might // inspect the underlying medium type (Medium) and/or set-up // some private config parameters from the Registry (Config) before // returning. // // Parameters: // Medium // Reference to the KNdisMedium object which has a medium type // selected for the underlying binding by the real NIC // Config // Reference to miniport's KNdisConfig object used to query various // configuration parameters // // Return // NDIS_STATUS_SUCCESS Proceed with the creation of the filter // NDIS_STATUS_XXXXXXX Error. The framework rolls back and fails the // miniport initialization. // IRQL: // PASSIVE_LEVEL // Return Mode: // Synchronous // NDIS_STATUS kpmAdapter::OnInitialize(const KNdisMedium& Medium, KNdisConfig& Config) { T.Trace(__FUNCTION__" %s at %ws\n", Medium.Text(), GetBoundDeviceName()); UNREFERENCED_PARAMETER(Config); return NDIS_STATUS_SUCCESS; } //////////////////////////////////////////////////////////////////// // kpmAdapter::OnHalt // // Either virtual NIC or underlying binding is being destroyed by NDIS // Not much can we do here. // VOID kpmAdapter::OnHalt() { T.Trace(__FUNCTION__"\n"); // TODO: deinit private members } //////////////////////////////////////////////////////////////////// // kpmAdapter::OnSend // // Intercepts the upper-layer send. Here's where the filtering in // the outgoing direction takes place. The filter is given a chance // to examine the original packet submitted by a protocol (Original) // and copy or modify or just drop it. The framework supplies a fresh // packet descriptor (Repackaged) good for passing one packet down // the binding. A filter that needs more packets (e.g. it implements // some sort of repacketization) has to maintiain an internal packet // pool and implement the OnSendComplete() handler. // // In LBFO case, the filter can choose forwarding the packet over // an other filter's instance binding from the bundle of adapter instances. // // // Parameters: // Original - Original packet descriptor supplied by NDIS // Repackaged - Framework-provided descriptor for repackaging // Returns: // The return value determines the behaviour of the framework after // OnSend() is returned: // NDIS_STATUS_SUCCESS Requests the framework to forward the // Repackaged packet down the binding // NDIS_STATUS_NOT_ACCEPTED Send nothing. Release resources and Return NDIS_STATUS_SUCCESS to NDIS // NDIS_STATUS_PENDING Do nothing, Recycle nothing. Return NDIS_STATUS_PENDING to NDIS // NDIS_STATUS_XXX Do nothing. Retutn this status to NDIS. // // NOTE: The Repackaged initiallly describes a packet with no chained buffers. // It is OK to return NDIS_STATUS_SUCCESS and leave the Repackaged empty. // This would mean the packet has been successfully "consumed" by the filter. // // KNOWN PROBLEM: Currently, one can't chain user-allocated buffers to the // repackaged descriptor. I.e. only "in-place" modifications are possible // Use a private packet/buffer pools and ForwardDown() if needed. // NDIS_STATUS kpmAdapter::OnSend(const KNdisPacket& Original, KNdisPacket& Repackaged) { T.Trace(__FUNCTION__" %u bytes\n", Original.QueryTotalLength()); NDIS_STATUS Status = NDIS_STATUS_SUCCESS; // TODO: Filter based on packet's content, e.g. // HEADER* Content = (HEADER*) Original.QueryFirstBuffer(); // . . . // This implementation simply points the Repackaged to the buffers of the // Original and returns. Repackaged.CloneDown(Original); FltProcessPackage(Repackaged); return Status; } //////////////////////////////////////////////////////////////////// // kpmAdapter::OnReceive // // Intercetpts lower-layer receive. Here's where the filtering in // the incoming direction takes place. The filter is given a chance // to examine the original packet indicated by the real NIC (Original) // and copy or modify or just drop it. The framework supplies a fresh // packet descriptor (Repackaged) good for passing one packet up to the // protocols. A filter that needs more packets (e.g. it implements // some sort of repacketization) has to maintiain an internal packet // pool and implement the OnReturnPacket() handler. // // Parameters: // Original - Original packet descriptor from the underlying NIC // Repackaged - Framework-provided descriptor for repackaging // Returns: // The return value determines the behaviour of the framework after // OnReceive() is returned: // NDIS_STATUS_SUCCESS Requests the framework to forward the // Repackaged packet up to the protocols // NDIS_STATUS_NOT_ACCEPTED Forward nothing. Release resources and Return NDIS_STATUS_SUCCESS to NDIS // NDIS_STATUS_XXX Do nothing. Retutn this status to NDIS. // // NOTE: The Repackaged initiallly describes a packet with no chained buffers. // It is OK to return NDIS_STATUS_SUCCESS and leave the Repackaged empty. // This would mean the packet has been successfully "consumed" by the filter. // // KNOWN PROBLEM: Currently, one can't chain user-allocated buffers to the // repackaged descriptor. I.e. only "in-place" modifications are possible // Use a private packet/buffer pools and ForwardUp() when needed. // NDIS_STATUS kpmAdapter::OnReceive(const KNdisPacket& Original, KNdisPacket& Repackaged) { T.Trace(__FUNCTION__" %u bytes\n", Original.QueryTotalLength()); // TODO: Filter based on packet's content, e.g. // HEADER* Content = (HEADER*) Original.QueryFirstBuffer(); // . . . // This implementation simply points the Repackaged to the buffers of the // Original and forwards it over the binding. Repackaged.CloneUp(Original); FltProcessPackage(Repackaged); return NDIS_STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////// // kpmAdapter::OnReceive (partial) // // Parameters: // PacketToAccept - Non-initialized packet descriptor // HeaderBuffer - Header pointer // HeaderBufferSize - Header size being indicated // LookAheadBuffer - Lookahead buffer pointer // LookaheadBufferSize - Lookahead size being indicated // PacketSize - Total packet size (not including the header) // Returns: // The return value determines the behaviour of the framework after // OnReceive() is returned: // NDIS_STATUS_SUCCESS Requests the framework to forward the // Repackaged packet up to the protocols // NDIS_STATUS_NOT_ACCEPTED Forward nothing. Release resources and Return NDIS_STATUS_SUCCESS to NDIS // NDIS_STATUS_XXX Do nothing. Retutn this status to NDIS. // Comments: // The framework calls this version of OnReceive() when the underlying real NIC miniport // uses partial receive packet indications (e.g., see discussion on KNdisLookahead). // Non-bus mastering NIC miniports may use this form of packet indication. // If the client is interested in looking into the remainder of the packet, it could // assign the supplied empty PacketToAccept to a real packet descriptor allocated from a // private packet pool. Then the framework would attempt to TransferData into supplied // packet and call the filter's OnTransferComplete() method. NDIS_STATUS kpmAdapter::OnReceive( IN OUT KNdisPartialPacket& PacketToAccept, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookaheadBufferSize, IN UINT PacketSize) { T.Trace(__FUNCTION__" Partial %u/%u%/%u bytes\n", HeaderBufferSize, LookaheadBufferSize, PacketSize); UNREFERENCED_PARAMETER(PacketToAccept); if(0x8 == ((struct libnet_ethernet_hdr *)HeaderBuffer)->ether_type) //is ip packet { FltDirectProcessPacket(LookAheadBuffer, LookaheadBufferSize, FALSE); } return NDIS_STATUS_SUCCESS; } |
|
地板#
发布于:2009-03-29 00:35
同问,,
狂顶作者。。。。。cool者 顶你。 |
|