From 1ebe2ad920bce1f9ea85c56fce469674b83c650c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 24 Apr 2015 23:31:51 -0700 Subject: NDIS6 driver with VS project to build -- builds correctly, not customized for ZT yet. --- windows/TapDriver6/txpath.c | 1168 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1168 insertions(+) create mode 100644 windows/TapDriver6/txpath.c (limited to 'windows/TapDriver6/txpath.c') diff --git a/windows/TapDriver6/txpath.c b/windows/TapDriver6/txpath.c new file mode 100644 index 00000000..6e084dfc --- /dev/null +++ b/windows/TapDriver6/txpath.c @@ -0,0 +1,1168 @@ +/* + * TAP-Windows -- A kernel driver to provide virtual tap + * device functionality on Windows. + * + * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. + * + * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., + * and is released under the GPL version 2 (see below). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// +// Include files. +// + +#include "tap.h" + +//====================================================================== +// TAP Send Path Support +//====================================================================== + +#ifdef ALLOC_PRAGMA +#pragma alloc_text( PAGE, TapDeviceRead) +#endif // ALLOC_PRAGMA + +// checksum code for ICMPv6 packet, taken from dhcp.c / udp_checksum +// see RFC 4443, 2.3, and RFC 2460, 8.1 +USHORT +icmpv6_checksum( + __in const UCHAR *buf, + __in const int len_icmpv6, + __in const UCHAR *saddr6, + __in const UCHAR *daddr6 + ) +{ + USHORT word16; + ULONG sum = 0; + int i; + + // make 16 bit words out of every two adjacent 8 bit words and + // calculate the sum of all 16 bit words + for (i = 0; i < len_icmpv6; i += 2) + { + word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_icmpv6) ? (buf[i+1] & 0xFF) : 0); + sum += word16; + } + + // add the IPv6 pseudo header which contains the IP source and destination addresses + for (i = 0; i < 16; i += 2) + { + word16 =((saddr6[i] << 8) & 0xFF00) + (saddr6[i+1] & 0xFF); + sum += word16; + } + + for (i = 0; i < 16; i += 2) + { + word16 =((daddr6[i] << 8) & 0xFF00) + (daddr6[i+1] & 0xFF); + sum += word16; + } + + // the next-header number and the length of the ICMPv6 packet + sum += (USHORT) IPPROTO_ICMPV6 + (USHORT) len_icmpv6; + + // keep only the last 16 bits of the 32 bit calculated sum and add the carries + while (sum >> 16) + sum = (sum & 0xFFFF) + (sum >> 16); + + // Take the one's complement of sum + return ((USHORT) ~sum); +} + +// check IPv6 packet for "is this an IPv6 Neighbor Solicitation that +// the tap driver needs to answer?" +// see RFC 4861 4.3 for the different cases +static IPV6ADDR IPV6_NS_TARGET_MCAST = + { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x08 }; +static IPV6ADDR IPV6_NS_TARGET_UNICAST = + { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 }; + +BOOLEAN +HandleIPv6NeighborDiscovery( + __in PTAP_ADAPTER_CONTEXT Adapter, + __in UCHAR * m_Data + ) +{ + const ETH_HEADER * e = (ETH_HEADER *) m_Data; + const IPV6HDR *ipv6 = (IPV6HDR *) (m_Data + sizeof (ETH_HEADER)); + const ICMPV6_NS * icmpv6_ns = (ICMPV6_NS *) (m_Data + sizeof (ETH_HEADER) + sizeof (IPV6HDR)); + ICMPV6_NA_PKT *na; + USHORT icmpv6_len, icmpv6_csum; + + // we don't really care about the destination MAC address here + // - it's either a multicast MAC, or the userland destination MAC + // but since the TAP driver is point-to-point, all packets are "for us" + + // IPv6 target address must be ff02::1::ff00:8 (multicast for + // initial NS) or fe80::1 (unicast for recurrent NUD) + if ( memcmp( ipv6->daddr, IPV6_NS_TARGET_MCAST, + sizeof(IPV6ADDR) ) != 0 && + memcmp( ipv6->daddr, IPV6_NS_TARGET_UNICAST, + sizeof(IPV6ADDR) ) != 0 ) + { + return FALSE; // wrong target address + } + + // IPv6 Next-Header must be ICMPv6 + if ( ipv6->nexthdr != IPPROTO_ICMPV6 ) + { + return FALSE; // wrong next-header + } + + // ICMPv6 type+code must be 135/0 for NS + if ( icmpv6_ns->type != ICMPV6_TYPE_NS || + icmpv6_ns->code != ICMPV6_CODE_0 ) + { + return FALSE; // wrong ICMPv6 type + } + + // ICMPv6 target address must be fe80::8 (magic) + if ( memcmp( icmpv6_ns->target_addr, IPV6_NS_TARGET_UNICAST, + sizeof(IPV6ADDR) ) != 0 ) + { + return FALSE; // not for us + } + + // packet identified, build magic response packet + + na = (ICMPV6_NA_PKT *) MemAlloc (sizeof (ICMPV6_NA_PKT), TRUE); + if ( !na ) return FALSE; + + //------------------------------------------------ + // Initialize Neighbour Advertisement reply packet + //------------------------------------------------ + + // ethernet header + na->eth.proto = htons(NDIS_ETH_TYPE_IPV6); + ETH_COPY_NETWORK_ADDRESS(na->eth.dest, Adapter->PermanentAddress); + ETH_COPY_NETWORK_ADDRESS(na->eth.src, Adapter->m_TapToUser.dest); + + // IPv6 header + na->ipv6.version_prio = ipv6->version_prio; + NdisMoveMemory( na->ipv6.flow_lbl, ipv6->flow_lbl, + sizeof(na->ipv6.flow_lbl) ); + icmpv6_len = sizeof(ICMPV6_NA_PKT) - sizeof(ETH_HEADER) - sizeof(IPV6HDR); + na->ipv6.payload_len = htons(icmpv6_len); + na->ipv6.nexthdr = IPPROTO_ICMPV6; + na->ipv6.hop_limit = 255; + NdisMoveMemory( na->ipv6.saddr, IPV6_NS_TARGET_UNICAST, + sizeof(IPV6ADDR) ); + NdisMoveMemory( na->ipv6.daddr, ipv6->saddr, + sizeof(IPV6ADDR) ); + + // ICMPv6 + na->icmpv6.type = ICMPV6_TYPE_NA; + na->icmpv6.code = ICMPV6_CODE_0; + na->icmpv6.checksum = 0; + na->icmpv6.rso_bits = 0x60; // Solicited + Override + NdisZeroMemory( na->icmpv6.reserved, sizeof(na->icmpv6.reserved) ); + NdisMoveMemory( na->icmpv6.target_addr, IPV6_NS_TARGET_UNICAST, + sizeof(IPV6ADDR) ); + + // ICMPv6 option "Target Link Layer Address" + na->icmpv6.opt_type = ICMPV6_OPTION_TLLA; + na->icmpv6.opt_length = ICMPV6_LENGTH_TLLA; + ETH_COPY_NETWORK_ADDRESS( na->icmpv6.target_macaddr, Adapter->m_TapToUser.dest ); + + // calculate and set checksum + icmpv6_csum = icmpv6_checksum ( + (UCHAR*) &(na->icmpv6), + icmpv6_len, + na->ipv6.saddr, + na->ipv6.daddr + ); + + na->icmpv6.checksum = htons( icmpv6_csum ); + + DUMP_PACKET ("HandleIPv6NeighborDiscovery", + (unsigned char *) na, + sizeof (ICMPV6_NA_PKT)); + + IndicateReceivePacket (Adapter, (UCHAR *) na, sizeof (ICMPV6_NA_PKT)); + + MemFree (na, sizeof (ICMPV6_NA_PKT)); + + return TRUE; // all fine +} + +//=================================================== +// Generate an ARP reply message for specific kinds +// ARP queries. +//=================================================== +BOOLEAN +ProcessARP( + __in PTAP_ADAPTER_CONTEXT Adapter, + __in const PARP_PACKET src, + __in const IPADDR adapter_ip, + __in const IPADDR ip_network, + __in const IPADDR ip_netmask, + __in const MACADDR mac + ) +{ + //----------------------------------------------- + // Is this the kind of packet we are looking for? + //----------------------------------------------- + if (src->m_Proto == htons (NDIS_ETH_TYPE_ARP) + && MAC_EQUAL (src->m_MAC_Source, Adapter->PermanentAddress) + && MAC_EQUAL (src->m_ARP_MAC_Source, Adapter->PermanentAddress) + && ETH_IS_BROADCAST(src->m_MAC_Destination) + && src->m_ARP_Operation == htons (ARP_REQUEST) + && src->m_MAC_AddressType == htons (MAC_ADDR_TYPE) + && src->m_MAC_AddressSize == sizeof (MACADDR) + && src->m_PROTO_AddressType == htons (NDIS_ETH_TYPE_IPV4) + && src->m_PROTO_AddressSize == sizeof (IPADDR) + && src->m_ARP_IP_Source == adapter_ip + && (src->m_ARP_IP_Destination & ip_netmask) == ip_network + && src->m_ARP_IP_Destination != adapter_ip) + { + ARP_PACKET *arp = (ARP_PACKET *) MemAlloc (sizeof (ARP_PACKET), TRUE); + if (arp) + { + //---------------------------------------------- + // Initialize ARP reply fields + //---------------------------------------------- + arp->m_Proto = htons (NDIS_ETH_TYPE_ARP); + arp->m_MAC_AddressType = htons (MAC_ADDR_TYPE); + arp->m_PROTO_AddressType = htons (NDIS_ETH_TYPE_IPV4); + arp->m_MAC_AddressSize = sizeof (MACADDR); + arp->m_PROTO_AddressSize = sizeof (IPADDR); + arp->m_ARP_Operation = htons (ARP_REPLY); + + //---------------------------------------------- + // ARP addresses + //---------------------------------------------- + ETH_COPY_NETWORK_ADDRESS (arp->m_MAC_Source, mac); + ETH_COPY_NETWORK_ADDRESS (arp->m_MAC_Destination, Adapter->PermanentAddress); + ETH_COPY_NETWORK_ADDRESS (arp->m_ARP_MAC_Source, mac); + ETH_COPY_NETWORK_ADDRESS (arp->m_ARP_MAC_Destination, Adapter->PermanentAddress); + arp->m_ARP_IP_Source = src->m_ARP_IP_Destination; + arp->m_ARP_IP_Destination = adapter_ip; + + DUMP_PACKET ("ProcessARP", + (unsigned char *) arp, + sizeof (ARP_PACKET)); + + IndicateReceivePacket (Adapter, (UCHAR *) arp, sizeof (ARP_PACKET)); + + MemFree (arp, sizeof (ARP_PACKET)); + } + + return TRUE; + } + else + return FALSE; +} + +//============================================================= +// CompleteIRP is normally called with an adapter -> userspace +// network packet and an IRP (Pending I/O request) from userspace. +// +// The IRP will normally represent a queued overlapped read +// operation from userspace that is in a wait state. +// +// Use the ethernet packet to satisfy the IRP. +//============================================================= + +VOID +tapCompletePendingReadIrp( + __in PIRP Irp, + __in PTAP_PACKET TapPacket + ) +{ + int offset; + int len; + NTSTATUS status = STATUS_UNSUCCESSFUL; + + ASSERT(Irp); + ASSERT(TapPacket); + + //------------------------------------------- + // While TapPacket always contains a + // full ethernet packet, including the + // ethernet header, in point-to-point mode, + // we only want to return the IPv4 + // component. + //------------------------------------------- + + if (TapPacket->m_SizeFlags & TP_TUN) + { + offset = ETHERNET_HEADER_SIZE; + len = (int) (TapPacket->m_SizeFlags & TP_SIZE_MASK) - ETHERNET_HEADER_SIZE; + } + else + { + offset = 0; + len = (TapPacket->m_SizeFlags & TP_SIZE_MASK); + } + + if (len < 0 || (int) Irp->IoStatus.Information < len) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = status = STATUS_BUFFER_OVERFLOW; + NOTE_ERROR (); + } + else + { + Irp->IoStatus.Information = len; + Irp->IoStatus.Status = status = STATUS_SUCCESS; + + // Copy packet data + NdisMoveMemory( + Irp->AssociatedIrp.SystemBuffer, + TapPacket->m_Data + offset, + len + ); + } + + // Free the TAP packet + NdisFreeMemory(TapPacket,0,0); + + // Complete the IRP + IoCompleteRequest (Irp, IO_NETWORK_INCREMENT); +} + +VOID +tapProcessSendPacketQueue( + __in PTAP_ADAPTER_CONTEXT Adapter + ) +{ + KIRQL irql; + + // Process the send packet queue + KeAcquireSpinLock(&Adapter->SendPacketQueue.QueueLock,&irql); + + while(Adapter->SendPacketQueue.Count > 0 ) + { + PIRP irp; + PTAP_PACKET tapPacket; + + // Fetch a read IRP + irp = IoCsqRemoveNextIrp( + &Adapter->PendingReadIrpQueue.CsqQueue, + NULL + ); + + if( irp == NULL ) + { + // No IRP to satisfy + break; + } + + // Fetch a queued TAP send packet + tapPacket = tapPacketRemoveHeadLocked( + &Adapter->SendPacketQueue + ); + + ASSERT(tapPacket); + + // BUGBUG!!! Investigate whether release/reacquire can cause + // out-of-order IRP completion. Also, whether user-mode can + // tolerate out-of-order packets. + + // Release packet queue lock while completing the IRP + //KeReleaseSpinLock(&Adapter->SendPacketQueue.QueueLock,irql); + + // Complete the read IRP from queued TAP send packet. + tapCompletePendingReadIrp(irp,tapPacket); + + // Reqcquire packet queue lock after completing the IRP + //KeAcquireSpinLock(&Adapter->SendPacketQueue.QueueLock,&irql); + } + + KeReleaseSpinLock(&Adapter->SendPacketQueue.QueueLock,irql); +} + +// Flush the pending send TAP packet queue. +VOID +tapFlushSendPacketQueue( + __in PTAP_ADAPTER_CONTEXT Adapter + ) +{ + KIRQL irql; + + // Process the send packet queue + KeAcquireSpinLock(&Adapter->SendPacketQueue.QueueLock,&irql); + + DEBUGP (("[TAP] tapFlushSendPacketQueue: Flushing %d TAP packets\n", + Adapter->SendPacketQueue.Count)); + + while(Adapter->SendPacketQueue.Count > 0 ) + { + PTAP_PACKET tapPacket; + + // Fetch a queued TAP send packet + tapPacket = tapPacketRemoveHeadLocked( + &Adapter->SendPacketQueue + ); + + ASSERT(tapPacket); + + // Free the TAP packet + NdisFreeMemory(tapPacket,0,0); + } + + KeReleaseSpinLock(&Adapter->SendPacketQueue.QueueLock,irql); +} + +VOID +tapAdapterTransmit( + __in PTAP_ADAPTER_CONTEXT Adapter, + __in PNET_BUFFER NetBuffer, + __in BOOLEAN DispatchLevel + ) +/*++ + +Routine Description: + + This routine is called to transmit an individual net buffer using a + style similar to the previous NDIS 5 AdapterTransmit function. + + In this implementation adapter state and NB length checks have already + been done before this function has been called. + + The net buffer will be completed by the calling routine after this + routine exits. So, under this design it is necessary to make a deep + copy of frame data in the net buffer. + + This routine creates a flat buffer copy of NB frame data. This is an + unnecessary performance bottleneck. However, the bottleneck is probably + not significant or measurable except for adapters running at 1Gbps or + greater speeds. Since this adapter is currently running at 100Mbps this + defect can be ignored. + + Runs at IRQL <= DISPATCH_LEVEL + +Arguments: + + Adapter Pointer to our adapter context + NetBuffer Pointer to the net buffer to transmit + DispatchLevel TRUE if called at IRQL == DISPATCH_LEVEL + +Return Value: + + None. + + In the Microsoft NDIS 6 architecture there is no per-packet status. + +--*/ +{ + NDIS_STATUS status; + ULONG packetLength; + PTAP_PACKET tapPacket; + PVOID packetData; + + packetLength = NET_BUFFER_DATA_LENGTH(NetBuffer); + + // Allocate TAP packet memory + tapPacket = (PTAP_PACKET )NdisAllocateMemoryWithTagPriority( + Adapter->MiniportAdapterHandle, + TAP_PACKET_SIZE (packetLength), + TAP_PACKET_TAG, + NormalPoolPriority + ); + + if(tapPacket == NULL) + { + DEBUGP (("[TAP] tapAdapterTransmit: TAP packet allocation failed\n")); + return; + } + + tapPacket->m_SizeFlags = (packetLength & TP_SIZE_MASK); + + // + // Reassemble packet contents + // -------------------------- + // NdisGetDataBuffer does most of the work. There are two cases: + // + // 1.) If the NB data was not contiguous it will copy the entire + // NB's data to m_data and return pointer to m_data. + // 2.) If the NB data was contiguous it returns a pointer to the + // first byte of the contiguous data instead of a pointer to m_Data. + // In this case the data will not have been copied to m_Data. Copy + // to m_Data will need to be done in an extra step. + // + // Case 1.) is the most likely in normal operation. + // + packetData = NdisGetDataBuffer(NetBuffer,packetLength,tapPacket->m_Data,1,0); + + if(packetData == NULL) + { + DEBUGP (("[TAP] tapAdapterTransmit: Could not get packet data\n")); + + NdisFreeMemory(tapPacket,0,0); + + return; + } + + if(packetData != tapPacket->m_Data) + { + // Packet data was contiguous and not yet copied to m_Data. + NdisMoveMemory(tapPacket->m_Data,packetData,packetLength); + } + + DUMP_PACKET ("AdapterTransmit", tapPacket->m_Data, packetLength); + + //===================================================== + // If IPv4 packet, check whether or not packet + // was truncated. + //===================================================== +#if PACKET_TRUNCATION_CHECK + IPv4PacketSizeVerify( + tapPacket->m_Data, + packetLength, + FALSE, + "TX", + &Adapter->m_TxTrunc + ); +#endif + + //===================================================== + // Are we running in DHCP server masquerade mode? + // + // If so, catch both DHCP requests and ARP queries + // to resolve the address of our virtual DHCP server. + //===================================================== + if (Adapter->m_dhcp_enabled) + { + const ETH_HEADER *eth = (ETH_HEADER *) tapPacket->m_Data; + const IPHDR *ip = (IPHDR *) (tapPacket->m_Data + sizeof (ETH_HEADER)); + const UDPHDR *udp = (UDPHDR *) (tapPacket->m_Data + sizeof (ETH_HEADER) + sizeof (IPHDR)); + + // ARP packet? + if (packetLength == sizeof (ARP_PACKET) + && eth->proto == htons (NDIS_ETH_TYPE_ARP) + && Adapter->m_dhcp_server_arp + ) + { + if (ProcessARP( + Adapter, + (PARP_PACKET) tapPacket->m_Data, + Adapter->m_dhcp_addr, + Adapter->m_dhcp_server_ip, + ~0, + Adapter->m_dhcp_server_mac) + ) + { + goto no_queue; + } + } + + // DHCP packet? + else if (packetLength >= sizeof (ETH_HEADER) + sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + && eth->proto == htons (NDIS_ETH_TYPE_IPV4) + && ip->version_len == 0x45 // IPv4, 20 byte header + && ip->protocol == IPPROTO_UDP + && udp->dest == htons (BOOTPS_PORT) + ) + { + const DHCP *dhcp = (DHCP *) (tapPacket->m_Data + + sizeof (ETH_HEADER) + + sizeof (IPHDR) + + sizeof (UDPHDR)); + + const int optlen = packetLength + - sizeof (ETH_HEADER) + - sizeof (IPHDR) + - sizeof (UDPHDR) + - sizeof (DHCP); + + if (optlen > 0) // we must have at least one DHCP option + { + if (ProcessDHCP (Adapter, eth, ip, udp, dhcp, optlen)) + { + goto no_queue; + } + } + else + { + goto no_queue; + } + } + } + + //=============================================== + // In Point-To-Point mode, check to see whether + // packet is ARP (handled) or IPv4 (sent to app). + // IPv6 packets are inspected for neighbour discovery + // (to be handled locally), and the rest is forwarded + // all other protocols are dropped + //=============================================== + if (Adapter->m_tun) + { + ETH_HEADER *e; + + e = (ETH_HEADER *) tapPacket->m_Data; + + switch (ntohs (e->proto)) + { + case NDIS_ETH_TYPE_ARP: + + // Make sure that packet is the right size for ARP. + if (packetLength != sizeof (ARP_PACKET)) + { + goto no_queue; + } + + ProcessARP ( + Adapter, + (PARP_PACKET) tapPacket->m_Data, + Adapter->m_localIP, + Adapter->m_remoteNetwork, + Adapter->m_remoteNetmask, + Adapter->m_TapToUser.dest + ); + + default: + goto no_queue; + + case NDIS_ETH_TYPE_IPV4: + + // Make sure that packet is large enough to be IPv4. + if (packetLength < (ETHERNET_HEADER_SIZE + IP_HEADER_SIZE)) + { + goto no_queue; + } + + // Only accept directed packets, not broadcasts. + if (memcmp (e, &Adapter->m_TapToUser, ETHERNET_HEADER_SIZE)) + { + goto no_queue; + } + + // Packet looks like IPv4, queue it. :-) + tapPacket->m_SizeFlags |= TP_TUN; + break; + + case NDIS_ETH_TYPE_IPV6: + // Make sure that packet is large enough to be IPv6. + if (packetLength < (ETHERNET_HEADER_SIZE + IPV6_HEADER_SIZE)) + { + goto no_queue; + } + + // Broadcasts and multicasts are handled specially + // (to be implemented) + + // Neighbor discovery packets to fe80::8 are special + // OpenVPN sets this next-hop to signal "handled by tapdrv" + if ( HandleIPv6NeighborDiscovery(Adapter,tapPacket->m_Data) ) + { + goto no_queue; + } + + // Packet looks like IPv6, queue it. :-) + tapPacket->m_SizeFlags |= TP_TUN; + } + } + + //=============================================== + // Push packet onto queue to wait for read from + // userspace. + //=============================================== + if(tapAdapterReadAndWriteReady(Adapter)) + { + tapPacketQueueInsertTail(&Adapter->SendPacketQueue,tapPacket); + } + else + { + // + // Tragedy. All this work and the packet is of no use... + // + NdisFreeMemory(tapPacket,0,0); + } + + // Return after queuing or freeing TAP packet. + return; + + // Free TAP packet without queuing. +no_queue: + if(tapPacket != NULL ) + { + NdisFreeMemory(tapPacket,0,0); + } + +exit_success: + return; +} + +VOID +tapSendNetBufferListsComplete( + __in PTAP_ADAPTER_CONTEXT Adapter, + __in PNET_BUFFER_LIST NetBufferLists, + __in NDIS_STATUS SendCompletionStatus, + __in BOOLEAN DispatchLevel + ) +{ + PNET_BUFFER_LIST currentNbl; + PNET_BUFFER_LIST nextNbl = NULL; + ULONG sendCompleteFlags = 0; + + for ( + currentNbl = NetBufferLists; + currentNbl != NULL; + currentNbl = nextNbl + ) + { + ULONG frameType; + ULONG netBufferCount; + ULONG byteCount; + + nextNbl = NET_BUFFER_LIST_NEXT_NBL(currentNbl); + + // Set NBL completion status. + NET_BUFFER_LIST_STATUS(currentNbl) = SendCompletionStatus; + + // Fetch first NBs frame type. All linked NBs will have same type. + frameType = tapGetNetBufferFrameType(NET_BUFFER_LIST_FIRST_NB(currentNbl)); + + // Fetch statistics for all NBs linked to the NB. + netBufferCount = tapGetNetBufferCountsFromNetBufferList( + currentNbl, + &byteCount + ); + + // Update statistics by frame type + if(SendCompletionStatus == NDIS_STATUS_SUCCESS) + { + switch(frameType) + { + case NDIS_PACKET_TYPE_DIRECTED: + Adapter->FramesTxDirected += netBufferCount; + Adapter->BytesTxDirected += byteCount; + break; + + case NDIS_PACKET_TYPE_BROADCAST: + Adapter->FramesTxBroadcast += netBufferCount; + Adapter->BytesTxBroadcast += byteCount; + break; + + case NDIS_PACKET_TYPE_MULTICAST: + Adapter->FramesTxMulticast += netBufferCount; + Adapter->BytesTxMulticast += byteCount; + break; + + default: + ASSERT(FALSE); + break; + } + } + else + { + // Transmit error. + Adapter->TransmitFailuresOther += netBufferCount; + } + + currentNbl = nextNbl; + } + + if(DispatchLevel) + { + sendCompleteFlags |= NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL; + } + + // Complete the NBLs + NdisMSendNetBufferListsComplete( + Adapter->MiniportAdapterHandle, + NetBufferLists, + sendCompleteFlags + ); +} + +BOOLEAN +tapNetBufferListNetBufferLengthsValid( + __in PTAP_ADAPTER_CONTEXT Adapter, + __in PNET_BUFFER_LIST NetBufferLists + ) +/*++ + +Routine Description: + + Scan all NBLs and their linked NBs for valid lengths. + + Fairly absurd to find and packets with bogus lengths, but wise + to check anyway. If ANY packet has a bogus length, then abort the + entire send. + + The only time that one might see this check fail might be during + HCK driver testing. The HKC test might send oversize packets to + determine if the miniport can gracefully deal with them. + + This check is fairly fast. Unlike NDIS 5 packets, fetching NDIS 6 + packets lengths do not require any computation. + +Arguments: + + Adapter Pointer to our adapter context + NetBufferLists Head of a list of NBLs to examine + +Return Value: + + Returns TRUE if all NBs have reasonable lengths. + Otherwise, returns FALSE. + +--*/ +{ + PNET_BUFFER_LIST currentNbl; + + currentNbl = NetBufferLists; + + while (currentNbl) + { + PNET_BUFFER_LIST nextNbl; + PNET_BUFFER currentNb; + + // Locate next NBL + nextNbl = NET_BUFFER_LIST_NEXT_NBL(currentNbl); + + // Locate first NB (aka "packet") + currentNb = NET_BUFFER_LIST_FIRST_NB(currentNbl); + + // + // Process all NBs linked to this NBL + // + while(currentNb) + { + PNET_BUFFER nextNb; + ULONG packetLength; + + // Locate next NB + nextNb = NET_BUFFER_NEXT_NB(currentNb); + + packetLength = NET_BUFFER_DATA_LENGTH(currentNb); + + // Minimum packet size is size of Ethernet plus IPv4 headers. + ASSERT(packetLength >= (ETHERNET_HEADER_SIZE + IP_HEADER_SIZE)); + + if(packetLength < (ETHERNET_HEADER_SIZE + IP_HEADER_SIZE)) + { + return FALSE; + } + + // Maximum size should be Ethernet header size plus MTU plus modest pad for + // VLAN tag. + ASSERT( packetLength <= (ETHERNET_HEADER_SIZE + VLAN_TAG_SIZE + Adapter->MtuSize)); + + if(packetLength > (ETHERNET_HEADER_SIZE + VLAN_TAG_SIZE + Adapter->MtuSize)) + { + return FALSE; + } + + // Move to next NB + currentNb = nextNb; + } + + // Move to next NBL + currentNbl = nextNbl; + } + + return TRUE; +} + +VOID +AdapterSendNetBufferLists( + __in NDIS_HANDLE MiniportAdapterContext, + __in PNET_BUFFER_LIST NetBufferLists, + __in NDIS_PORT_NUMBER PortNumber, + __in ULONG SendFlags + ) +/*++ + +Routine Description: + + Send Packet Array handler. Called by NDIS whenever a protocol + bound to our miniport sends one or more packets. + + The input packet descriptor pointers have been ordered according + to the order in which the packets should be sent over the network + by the protocol driver that set up the packet array. The NDIS + library preserves the protocol-determined ordering when it submits + each packet array to MiniportSendPackets + + As a deserialized driver, we are responsible for holding incoming send + packets in our internal queue until they can be transmitted over the + network and for preserving the protocol-determined ordering of packet + descriptors incoming to its MiniportSendPackets function. + A deserialized miniport driver must complete each incoming send packet + with NdisMSendComplete, and it cannot call NdisMSendResourcesAvailable. + + Runs at IRQL <= DISPATCH_LEVEL + +Arguments: + + MiniportAdapterContext Pointer to our adapter + NetBufferLists Head of a list of NBLs to send + PortNumber A miniport adapter port. Default is 0. + SendFlags Additional flags for the send operation + +Return Value: + + None. Write status directly into each NBL with the NET_BUFFER_LIST_STATUS + macro. + +--*/ +{ + NDIS_STATUS status; + PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext; + BOOLEAN DispatchLevel = (SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL); + PNET_BUFFER_LIST currentNbl; + BOOLEAN validNbLengths; + + UNREFERENCED_PARAMETER(NetBufferLists); + UNREFERENCED_PARAMETER(PortNumber); + UNREFERENCED_PARAMETER(SendFlags); + + ASSERT(PortNumber == 0); // Only the default port is supported + + // + // Can't process sends if TAP device is not open. + // ---------------------------------------------- + // Just perform a "lying send" and return packets as if they + // were successfully sent. + // + if(adapter->TapFileObject == NULL) + { + // + // Complete all NBLs and return if adapter not ready. + // + tapSendNetBufferListsComplete( + adapter, + NetBufferLists, + NDIS_STATUS_SUCCESS, + DispatchLevel + ); + + return; + } + + // + // Check Adapter send/receive ready state. + // + status = tapAdapterSendAndReceiveReady(adapter); + + if(status != NDIS_STATUS_SUCCESS) + { + // + // Complete all NBLs and return if adapter not ready. + // + tapSendNetBufferListsComplete( + adapter, + NetBufferLists, + status, + DispatchLevel + ); + + return; + } + + // + // Scan all NBLs and linked packets for valid lengths. + // --------------------------------------------------- + // If _ANY_ NB length is invalid, then fail the entire send operation. + // + // BUGBUG!!! Perhaps this should be less agressive. Fail only individual + // NBLs... + // + // If length check is valid, then TAP_PACKETS can be safely allocated + // and processed for all NBs being sent. + // + validNbLengths = tapNetBufferListNetBufferLengthsValid( + adapter, + NetBufferLists + ); + + if(!validNbLengths) + { + // + // Complete all NBLs and return if and NB length is invalid. + // + tapSendNetBufferListsComplete( + adapter, + NetBufferLists, + NDIS_STATUS_INVALID_LENGTH, + DispatchLevel + ); + + return; + } + + // + // Process each NBL individually + // + currentNbl = NetBufferLists; + + while (currentNbl) + { + PNET_BUFFER_LIST nextNbl; + PNET_BUFFER currentNb; + + // Locate next NBL + nextNbl = NET_BUFFER_LIST_NEXT_NBL(currentNbl); + + // Locate first NB (aka "packet") + currentNb = NET_BUFFER_LIST_FIRST_NB(currentNbl); + + // Transmit all NBs linked to this NBL + while(currentNb) + { + PNET_BUFFER nextNb; + + // Locate next NB + nextNb = NET_BUFFER_NEXT_NB(currentNb); + + // Transmit the NB + tapAdapterTransmit(adapter,currentNb,DispatchLevel); + + // Move to next NB + currentNb = nextNb; + } + + // Move to next NBL + currentNbl = nextNbl; + } + + // Complete all NBLs + tapSendNetBufferListsComplete( + adapter, + NetBufferLists, + NDIS_STATUS_SUCCESS, + DispatchLevel + ); + + // Attempt to complete pending read IRPs from pending TAP + // send packet queue. + tapProcessSendPacketQueue(adapter); +} + +VOID +AdapterCancelSend( + __in NDIS_HANDLE MiniportAdapterContext, + __in PVOID CancelId + ) +{ + PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext; + + // + // This miniport completes its sends quickly, so it isn't strictly + // neccessary to implement MiniportCancelSend. + // + // If we did implement it, we'd have to walk the Adapter->SendWaitList + // and look for any NB that points to a NBL where the CancelId matches + // NDIS_GET_NET_BUFFER_LIST_CANCEL_ID(Nbl). For any NB that so matches, + // we'd remove the NB from the SendWaitList and set the NBL's status to + // NDIS_STATUS_SEND_ABORTED, then complete the NBL. + // +} + +// IRP_MJ_READ callback. +NTSTATUS +TapDeviceRead( + PDEVICE_OBJECT DeviceObject, + PIRP Irp + ) +{ + NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success + PIO_STACK_LOCATION irpSp;// Pointer to current stack location + PTAP_ADAPTER_CONTEXT adapter = NULL; + + PAGED_CODE(); + + irpSp = IoGetCurrentIrpStackLocation( Irp ); + + // + // Fetch adapter context for this device. + // -------------------------------------- + // Adapter pointer was stashed in FsContext when handle was opened. + // + adapter = (PTAP_ADAPTER_CONTEXT )(irpSp->FileObject)->FsContext; + + ASSERT(adapter); + + // + // Sanity checks on state variables + // + if (!tapAdapterReadAndWriteReady(adapter)) + { + //DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n", + // MINIPORT_INSTANCE_ID (adapter))); + //NOTE_ERROR(); + + Irp->IoStatus.Status = ntStatus = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return ntStatus; + } + + // Save IRP-accessible copy of buffer length + Irp->IoStatus.Information = irpSp->Parameters.Read.Length; + + if (Irp->MdlAddress == NULL) + { + DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n", + MINIPORT_INSTANCE_ID (adapter))); + + NOTE_ERROR(); + Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER; + Irp->IoStatus.Information = 0; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return ntStatus; + } + + if ((Irp->AssociatedIrp.SystemBuffer + = MmGetSystemAddressForMdlSafe( + Irp->MdlAddress, + NormalPagePriority + ) ) == NULL + ) + { + DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n", + MINIPORT_INSTANCE_ID (adapter))); + + NOTE_ERROR(); + Irp->IoStatus.Status = ntStatus = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Information = 0; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return ntStatus; + } + + // BUGBUG!!! Use RemoveLock??? + + // + // Queue the IRP and return STATUS_PENDING. + // ---------------------------------------- + // Note: IoCsqInsertIrp marks the IRP pending. + // + + // BUGBUG!!! NDIS 5 implementation has IRP_QUEUE_SIZE of 16 and + // does not queue IRP if this capacity is exceeded. + // + // Is this needed??? + // + IoCsqInsertIrp(&adapter->PendingReadIrpQueue.CsqQueue, Irp, NULL); + + // Attempt to complete pending read IRPs from pending TAP + // send packet queue. + tapProcessSendPacketQueue(adapter); + + ntStatus = STATUS_PENDING; + + return ntStatus; +} + -- cgit v1.2.3 From d4c06e924d3319c43ac9e7662332811a4afe0993 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sat, 25 Apr 2015 12:21:08 -0700 Subject: Do the same modifications to the NDIS 6 code base as were done to the old 5 driver: disable all the 'tun' functionality, and add the IOCTL for querying the multicast list at Ethernet (L2) level. --- windows/TapDriver6/TapDriver6.vcxproj | 2 - windows/TapDriver6/TapDriver6.vcxproj.filters | 6 - windows/TapDriver6/adapter.h | 6 +- windows/TapDriver6/constants.h | 7 +- windows/TapDriver6/device.c | 42 +- windows/TapDriver6/dhcp.c | 710 -------------------------- windows/TapDriver6/dhcp.h | 165 ------ windows/TapDriver6/prototypes.h | 4 + windows/TapDriver6/rxpath.c | 4 +- windows/TapDriver6/tap-windows.h | 19 +- windows/TapDriver6/tap.h | 2 - windows/TapDriver6/txpath.c | 15 +- 12 files changed, 81 insertions(+), 901 deletions(-) delete mode 100644 windows/TapDriver6/dhcp.c delete mode 100644 windows/TapDriver6/dhcp.h (limited to 'windows/TapDriver6/txpath.c') diff --git a/windows/TapDriver6/TapDriver6.vcxproj b/windows/TapDriver6/TapDriver6.vcxproj index 280354ec..0216fe4c 100644 --- a/windows/TapDriver6/TapDriver6.vcxproj +++ b/windows/TapDriver6/TapDriver6.vcxproj @@ -213,7 +213,6 @@ - @@ -227,7 +226,6 @@ - diff --git a/windows/TapDriver6/TapDriver6.vcxproj.filters b/windows/TapDriver6/TapDriver6.vcxproj.filters index 9839a59c..c523ed55 100644 --- a/windows/TapDriver6/TapDriver6.vcxproj.filters +++ b/windows/TapDriver6/TapDriver6.vcxproj.filters @@ -25,9 +25,6 @@ Source Files - - Source Files - Source Files @@ -63,9 +60,6 @@ Header Files - - Header Files - Header Files diff --git a/windows/TapDriver6/adapter.h b/windows/TapDriver6/adapter.h index 4f267ec0..0ebaaea7 100644 --- a/windows/TapDriver6/adapter.h +++ b/windows/TapDriver6/adapter.h @@ -170,6 +170,7 @@ typedef struct _TAP_ADAPTER_CONTEXT #define TAP_WAIT_POLL_LOOP_TIMEOUT 3000 // 3 seconds NDIS_EVENT ReceiveNblInFlightCountZeroEvent; + /* // Info for point-to-point mode BOOLEAN m_tun; IPADDR m_localIP; @@ -178,8 +179,10 @@ typedef struct _TAP_ADAPTER_CONTEXT ETH_HEADER m_TapToUser; ETH_HEADER m_UserToTap; ETH_HEADER m_UserToTap_IPv6; // same as UserToTap but proto=ipv6 + */ - // Info for DHCP server masquerade + // Info for DHCP server masquerade + /* BOOLEAN m_dhcp_enabled; IPADDR m_dhcp_addr; ULONG m_dhcp_netmask; @@ -191,6 +194,7 @@ typedef struct _TAP_ADAPTER_CONTEXT ULONG m_dhcp_user_supplied_options_buffer_len; BOOLEAN m_dhcp_received_discover; ULONG m_dhcp_bad_requests; + */ // Multicast list. Fixed size. ULONG ulMCListSize; diff --git a/windows/TapDriver6/constants.h b/windows/TapDriver6/constants.h index 31b2d545..91a876f2 100644 --- a/windows/TapDriver6/constants.h +++ b/windows/TapDriver6/constants.h @@ -69,7 +69,8 @@ //=========================================================== #define ETHERNET_HEADER_SIZE (sizeof (ETH_HEADER)) -#define ETHERNET_MTU 1500 +//#define ETHERNET_MTU 1500 +#define ETHERNET_MTU 2800 #define ETHERNET_PACKET_SIZE (ETHERNET_MTU + ETHERNET_HEADER_SIZE) #define DEFAULT_PACKET_LOOKAHEAD (ETHERNET_PACKET_SIZE) #define VLAN_TAG_SIZE 4 @@ -108,7 +109,7 @@ #define TAP_RECV_SPEED (100ULL*MEGABITS_PER_SECOND) // Max number of multicast addresses supported in hardware -#define TAP_MAX_MCAST_LIST 32 +#define TAP_MAX_MCAST_LIST 128 #define TAP_MAX_LOOKAHEAD TAP_FRAME_MAX_DATA_SIZE #define TAP_BUFFER_SIZE TAP_MAX_FRAME_SIZE @@ -137,7 +138,7 @@ NDIS_PACKET_TYPE_PROMISCUOUS | \ NDIS_PACKET_TYPE_ALL_MULTICAST) -#define TAP_MAX_MCAST_LIST 32 // Max length of multicast address list +//#define TAP_MAX_MCAST_LIST 128 // Max length of multicast address list // // Specify a bitmask that defines optional properties of the NIC. diff --git a/windows/TapDriver6/device.c b/windows/TapDriver6/device.c index 2b7ba9b1..7367143b 100644 --- a/windows/TapDriver6/device.c +++ b/windows/TapDriver6/device.c @@ -48,6 +48,7 @@ VOID tapResetAdapterState( __in PTAP_ADAPTER_CONTEXT Adapter ) { + /* // Point-To-Point Adapter->m_tun = FALSE; Adapter->m_localIP = 0; @@ -56,8 +57,10 @@ VOID tapResetAdapterState( NdisZeroMemory (&Adapter->m_TapToUser, sizeof (Adapter->m_TapToUser)); NdisZeroMemory (&Adapter->m_UserToTap, sizeof (Adapter->m_UserToTap)); NdisZeroMemory (&Adapter->m_UserToTap_IPv6, sizeof (Adapter->m_UserToTap_IPv6)); + */ // DHCP Masq + /* Adapter->m_dhcp_enabled = FALSE; Adapter->m_dhcp_server_arp = FALSE; Adapter->m_dhcp_user_supplied_options_buffer_len = 0; @@ -68,6 +71,7 @@ VOID tapResetAdapterState( Adapter->m_dhcp_received_discover = FALSE; Adapter->m_dhcp_bad_requests = 0; NdisZeroMemory (Adapter->m_dhcp_server_mac, MACADDR_SIZE); + */ } // IRP_MJ_CREATE @@ -278,6 +282,7 @@ tapSetMediaConnectStatus( } } +/* //====================================================== // If DHCP mode is used together with tun // mode, consider the fact that the P2P remote subnet @@ -297,6 +302,7 @@ CheckIfDhcpAndTunMode ( } } } +*/ // IRP_MJ_DEVICE_CONTROL callback. NTSTATUS @@ -428,6 +434,36 @@ Return Value: } break; + // Allow ZeroTier One to get multicast memberships at the L2 level in a + // protocol-neutral manner. + case TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS: + { + if (outBufLength < TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE) { + /* output buffer too small */ + NOTE_ERROR (); + Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL; + } else { + char *out = (char *)Irp->AssociatedIrp.SystemBuffer; + char *end = out + TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE; + unsigned long i,j; + for(i=0;iulMCListSize;++i) { + if (i >= TAP_MAX_MCAST_LIST) + break; + for(j=0;j<6;++j) + *(out++) = adapter->MCList[i][j]; + if (out >= end) + break; + } + while (out < end) + *(out++) = (char)0; + Irp->IoStatus.Information = TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE; + Irp->IoStatus.Status = ntStatus = STATUS_SUCCESS; + } + break; + } + + +#if 0 case TAP_WIN_IOCTL_CONFIG_TUN: { if(inBufLength >= sizeof(IPADDR)*3) @@ -513,7 +549,9 @@ Return Value: } } break; +#endif +#if 0 case TAP_WIN_IOCTL_CONFIG_DHCP_MASQ: { if(inBufLength >= sizeof(IPADDR)*4) @@ -586,7 +624,9 @@ Return Value: } } break; +#endif +#if 0 case TAP_WIN_IOCTL_GET_INFO: { char state[16]; @@ -657,7 +697,7 @@ Return Value: // BUGBUG!!! Fail because this is not completely implemented. ntStatus = STATUS_INVALID_DEVICE_REQUEST; } - break; +#endif #if DBG case TAP_WIN_IOCTL_GET_LOG_LINE: diff --git a/windows/TapDriver6/dhcp.c b/windows/TapDriver6/dhcp.c deleted file mode 100644 index 30b22f4f..00000000 --- a/windows/TapDriver6/dhcp.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - * TAP-Windows -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., - * and is released under the GPL version 2 (see below). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "tap.h" - -//========================= -// Code to set DHCP options -//========================= - -VOID -SetDHCPOpt( - __in DHCPMsg *m, - __in void *data, - __in unsigned int len - ) -{ - if (!m->overflow) - { - if (m->optlen + len <= DHCP_OPTIONS_BUFFER_SIZE) - { - if (len) - { - NdisMoveMemory (m->msg.options + m->optlen, data, len); - m->optlen += len; - } - } - else - { - m->overflow = TRUE; - } - } -} - -VOID -SetDHCPOpt0( - __in DHCPMsg *msg, - __in int type - ) -{ - DHCPOPT0 opt; - opt.type = (UCHAR) type; - SetDHCPOpt (msg, &opt, sizeof (opt)); -} - -VOID -SetDHCPOpt8( - __in DHCPMsg *msg, - __in int type, - __in ULONG data - ) -{ - DHCPOPT8 opt; - opt.type = (UCHAR) type; - opt.len = sizeof (opt.data); - opt.data = (UCHAR) data; - SetDHCPOpt (msg, &opt, sizeof (opt)); -} - -VOID -SetDHCPOpt32( - __in DHCPMsg *msg, - __in int type, - __in ULONG data - ) -{ - DHCPOPT32 opt; - opt.type = (UCHAR) type; - opt.len = sizeof (opt.data); - opt.data = data; - SetDHCPOpt (msg, &opt, sizeof (opt)); -} - -//============== -// Checksum code -//============== - -USHORT -ip_checksum( - __in const UCHAR *buf, - __in const int len_ip_header - ) -{ - USHORT word16; - ULONG sum = 0; - int i; - - // make 16 bit words out of every two adjacent 8 bit words in the packet - // and add them up - for (i = 0; i < len_ip_header - 1; i += 2) - { - word16 = ((buf[i] << 8) & 0xFF00) + (buf[i+1] & 0xFF); - sum += (ULONG) word16; - } - - // take only 16 bits out of the 32 bit sum and add up the carries - while (sum >> 16) - { - sum = (sum & 0xFFFF) + (sum >> 16); - } - - // one's complement the result - return ((USHORT) ~sum); -} - -USHORT -udp_checksum ( - __in const UCHAR *buf, - __in const int len_udp, - __in const UCHAR *src_addr, - __in const UCHAR *dest_addr - ) -{ - USHORT word16; - ULONG sum = 0; - int i; - - // make 16 bit words out of every two adjacent 8 bit words and - // calculate the sum of all 16 bit words - for (i = 0; i < len_udp; i += 2) - { - word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_udp) ? (buf[i+1] & 0xFF) : 0); - sum += word16; - } - - // add the UDP pseudo header which contains the IP source and destination addresses - for (i = 0; i < 4; i += 2) - { - word16 =((src_addr[i] << 8) & 0xFF00) + (src_addr[i+1] & 0xFF); - sum += word16; - } - - for (i = 0; i < 4; i += 2) - { - word16 =((dest_addr[i] << 8) & 0xFF00) + (dest_addr[i+1] & 0xFF); - sum += word16; - } - - // the protocol number and the length of the UDP packet - sum += (USHORT) IPPROTO_UDP + (USHORT) len_udp; - - // keep only the last 16 bits of the 32 bit calculated sum and add the carries - while (sum >> 16) - { - sum = (sum & 0xFFFF) + (sum >> 16); - } - - // Take the one's complement of sum - return ((USHORT) ~sum); -} - -//================================ -// Set IP and UDP packet checksums -//================================ - -VOID -SetChecksumDHCPMsg( - __in DHCPMsg *m - ) -{ - // Set IP checksum - m->msg.pre.ip.check = htons (ip_checksum ((UCHAR *) &m->msg.pre.ip, sizeof (IPHDR))); - - // Set UDP Checksum - m->msg.pre.udp.check = htons (udp_checksum ((UCHAR *) &m->msg.pre.udp, - sizeof (UDPHDR) + sizeof (DHCP) + m->optlen, - (UCHAR *)&m->msg.pre.ip.saddr, - (UCHAR *)&m->msg.pre.ip.daddr)); -} - -//=================== -// DHCP message tests -//=================== - -int -GetDHCPMessageType( - __in const DHCP *dhcp, - __in const int optlen - ) -{ - const UCHAR *p = (UCHAR *) (dhcp + 1); - int i; - - for (i = 0; i < optlen; ++i) - { - const UCHAR type = p[i]; - const int room = optlen - i - 1; - - if (type == DHCP_END) // didn't find what we were looking for - return -1; - else if (type == DHCP_PAD) // no-operation - ; - else if (type == DHCP_MSG_TYPE) // what we are looking for - { - if (room >= 2) - { - if (p[i+1] == 1) // message length should be 1 - return p[i+2]; // return message type - } - return -1; - } - else // some other message - { - if (room >= 1) - { - const int len = p[i+1]; // get message length - i += (len + 1); // advance to next message - } - } - } - return -1; -} - -BOOLEAN -DHCPMessageOurs ( - __in const PTAP_ADAPTER_CONTEXT Adapter, - __in const ETH_HEADER *eth, - __in const IPHDR *ip, - __in const UDPHDR *udp, - __in const DHCP *dhcp - ) -{ - // Must be UDPv4 protocol - if (!(eth->proto == htons (NDIS_ETH_TYPE_IPV4) && ip->protocol == IPPROTO_UDP)) - { - return FALSE; - } - - // Source MAC must be our adapter - if (!MAC_EQUAL (eth->src, Adapter->CurrentAddress)) - { - return FALSE; - } - - // Dest MAC must be either broadcast or our virtual DHCP server - if (!(ETH_IS_BROADCAST(eth->dest) - || MAC_EQUAL (eth->dest, Adapter->m_dhcp_server_mac))) - { - return FALSE; - } - - // Port numbers must be correct - if (!(udp->dest == htons (BOOTPS_PORT) - && udp->source == htons (BOOTPC_PORT))) - { - return FALSE; - } - - // Hardware address must be MAC addr sized - if (!(dhcp->hlen == sizeof (MACADDR))) - { - return FALSE; - } - - // Hardware address must match our adapter - if (!MAC_EQUAL (eth->src, dhcp->chaddr)) - { - return FALSE; - } - - return TRUE; -} - - -//===================================================== -// Build all of DHCP packet except for DHCP options. -// Assume that *p has been zeroed before we are called. -//===================================================== - -VOID -BuildDHCPPre ( - __in const PTAP_ADAPTER_CONTEXT Adapter, - __inout DHCPPre *p, - __in const ETH_HEADER *eth, - __in const IPHDR *ip, - __in const UDPHDR *udp, - __in const DHCP *dhcp, - __in const int optlen, - __in const int type) -{ - // Should we broadcast or direct to a specific MAC / IP address? - const BOOLEAN broadcast = (type == DHCPNAK - || ETH_IS_BROADCAST(eth->dest)); - - // - // Build ethernet header - // - ETH_COPY_NETWORK_ADDRESS (p->eth.src, Adapter->m_dhcp_server_mac); - - if (broadcast) - { - memset(p->eth.dest,0xFF,ETH_LENGTH_OF_ADDRESS); - } - else - { - ETH_COPY_NETWORK_ADDRESS (p->eth.dest, eth->src); - } - - p->eth.proto = htons (NDIS_ETH_TYPE_IPV4); - - // - // Build IP header - // - p->ip.version_len = (4 << 4) | (sizeof (IPHDR) >> 2); - p->ip.tos = 0; - p->ip.tot_len = htons (sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen); - p->ip.id = 0; - p->ip.frag_off = 0; - p->ip.ttl = 16; - p->ip.protocol = IPPROTO_UDP; - p->ip.check = 0; - p->ip.saddr = Adapter->m_dhcp_server_ip; - - if (broadcast) - { - p->ip.daddr = ~0; - } - else - { - p->ip.daddr = Adapter->m_dhcp_addr; - } - - // - // Build UDP header - // - p->udp.source = htons (BOOTPS_PORT); - p->udp.dest = htons (BOOTPC_PORT); - p->udp.len = htons (sizeof (UDPHDR) + sizeof (DHCP) + optlen); - p->udp.check = 0; - - // Build DHCP response - - p->dhcp.op = BOOTREPLY; - p->dhcp.htype = 1; - p->dhcp.hlen = sizeof (MACADDR); - p->dhcp.hops = 0; - p->dhcp.xid = dhcp->xid; - p->dhcp.secs = 0; - p->dhcp.flags = 0; - p->dhcp.ciaddr = 0; - - if (type == DHCPNAK) - { - p->dhcp.yiaddr = 0; - } - else - { - p->dhcp.yiaddr = Adapter->m_dhcp_addr; - } - - p->dhcp.siaddr = Adapter->m_dhcp_server_ip; - p->dhcp.giaddr = 0; - ETH_COPY_NETWORK_ADDRESS (p->dhcp.chaddr, eth->src); - p->dhcp.magic = htonl (0x63825363); -} - -//============================= -// Build specific DHCP messages -//============================= - -VOID -SendDHCPMsg( - __in PTAP_ADAPTER_CONTEXT Adapter, - __in const int type, - __in const ETH_HEADER *eth, - __in const IPHDR *ip, - __in const UDPHDR *udp, - __in const DHCP *dhcp - ) -{ - DHCPMsg *pkt; - - if (!(type == DHCPOFFER || type == DHCPACK || type == DHCPNAK)) - { - DEBUGP (("[TAP] SendDHCPMsg: Bad DHCP type: %d\n", type)); - return; - } - - pkt = (DHCPMsg *) MemAlloc (sizeof (DHCPMsg), TRUE); - - if(pkt) - { - //----------------------- - // Build DHCP options - //----------------------- - - // Message Type - SetDHCPOpt8 (pkt, DHCP_MSG_TYPE, type); - - // Server ID - SetDHCPOpt32 (pkt, DHCP_SERVER_ID, Adapter->m_dhcp_server_ip); - - if (type == DHCPOFFER || type == DHCPACK) - { - // Lease Time - SetDHCPOpt32 (pkt, DHCP_LEASE_TIME, htonl (Adapter->m_dhcp_lease_time)); - - // Netmask - SetDHCPOpt32 (pkt, DHCP_NETMASK, Adapter->m_dhcp_netmask); - - // Other user-defined options - SetDHCPOpt ( - pkt, - Adapter->m_dhcp_user_supplied_options_buffer, - Adapter->m_dhcp_user_supplied_options_buffer_len); - } - - // End - SetDHCPOpt0 (pkt, DHCP_END); - - if (!DHCPMSG_OVERFLOW (pkt)) - { - // The initial part of the DHCP message (not including options) gets built here - BuildDHCPPre ( - Adapter, - &pkt->msg.pre, - eth, - ip, - udp, - dhcp, - DHCPMSG_LEN_OPT (pkt), - type); - - SetChecksumDHCPMsg (pkt); - - DUMP_PACKET ("DHCPMsg", - DHCPMSG_BUF (pkt), - DHCPMSG_LEN_FULL (pkt)); - - // Return DHCP response to kernel - IndicateReceivePacket( - Adapter, - DHCPMSG_BUF (pkt), - DHCPMSG_LEN_FULL (pkt) - ); - } - else - { - DEBUGP (("[TAP] SendDHCPMsg: DHCP buffer overflow\n")); - } - - MemFree (pkt, sizeof (DHCPMsg)); - } -} - -//=================================================================== -// Handle a BOOTPS packet produced by the local system to -// resolve the address/netmask of this adapter. -// If we are in TAP_WIN_IOCTL_CONFIG_DHCP_MASQ mode, reply -// to the message. Return TRUE if we processed the passed -// message, so that downstream stages can ignore it. -//=================================================================== - -BOOLEAN -ProcessDHCP( - __in PTAP_ADAPTER_CONTEXT Adapter, - __in const ETH_HEADER *eth, - __in const IPHDR *ip, - __in const UDPHDR *udp, - __in const DHCP *dhcp, - __in int optlen - ) -{ - int msg_type; - - // Sanity check IP header - if (!(ntohs (ip->tot_len) == sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen - && (ntohs (ip->frag_off) & IP_OFFMASK) == 0)) - { - return TRUE; - } - - // Does this message belong to us? - if (!DHCPMessageOurs (Adapter, eth, ip, udp, dhcp)) - { - return FALSE; - } - - msg_type = GetDHCPMessageType (dhcp, optlen); - - // Drop non-BOOTREQUEST messages - if (dhcp->op != BOOTREQUEST) - { - return TRUE; - } - - // Drop any messages except DHCPDISCOVER or DHCPREQUEST - if (!(msg_type == DHCPDISCOVER || msg_type == DHCPREQUEST)) - { - return TRUE; - } - - // Should we reply with DHCPOFFER, DHCPACK, or DHCPNAK? - if (msg_type == DHCPREQUEST - && ((dhcp->ciaddr && dhcp->ciaddr != Adapter->m_dhcp_addr) - || !Adapter->m_dhcp_received_discover - || Adapter->m_dhcp_bad_requests >= BAD_DHCPREQUEST_NAK_THRESHOLD)) - { - SendDHCPMsg( - Adapter, - DHCPNAK, - eth, ip, udp, dhcp - ); - } - else - { - SendDHCPMsg( - Adapter, - (msg_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK), - eth, ip, udp, dhcp - ); - } - - // Remember if we received a DHCPDISCOVER - if (msg_type == DHCPDISCOVER) - { - Adapter->m_dhcp_received_discover = TRUE; - } - - // Is this a bad DHCPREQUEST? - if (msg_type == DHCPREQUEST && dhcp->ciaddr && dhcp->ciaddr != Adapter->m_dhcp_addr) - { - ++Adapter->m_dhcp_bad_requests; - } - - return TRUE; -} - -#if DBG - -const char * - message_op_text (int op) -{ - switch (op) - { - case BOOTREQUEST: - return "BOOTREQUEST"; - - case BOOTREPLY: - return "BOOTREPLY"; - - default: - return "???"; - } -} - -const char * - message_type_text (int type) -{ - switch (type) - { - case DHCPDISCOVER: - return "DHCPDISCOVER"; - - case DHCPOFFER: - return "DHCPOFFER"; - - case DHCPREQUEST: - return "DHCPREQUEST"; - - case DHCPDECLINE: - return "DHCPDECLINE"; - - case DHCPACK: - return "DHCPACK"; - - case DHCPNAK: - return "DHCPNAK"; - - case DHCPRELEASE: - return "DHCPRELEASE"; - - case DHCPINFORM: - return "DHCPINFORM"; - - default: - return "???"; - } -} - -const char * -port_name (int port) -{ - switch (port) - { - case BOOTPS_PORT: - return "BOOTPS"; - - case BOOTPC_PORT: - return "BOOTPC"; - - default: - return "unknown"; - } -} - -VOID -DumpDHCP ( - const ETH_HEADER *eth, - const IPHDR *ip, - const UDPHDR *udp, - const DHCP *dhcp, - const int optlen - ) -{ - DEBUGP ((" %s", message_op_text (dhcp->op))); - DEBUGP ((" %s ", message_type_text (GetDHCPMessageType (dhcp, optlen)))); - PrIP (ip->saddr); - DEBUGP ((":%s[", port_name (ntohs (udp->source)))); - PrMac (eth->src); - DEBUGP (("] -> ")); - PrIP (ip->daddr); - DEBUGP ((":%s[", port_name (ntohs (udp->dest)))); - PrMac (eth->dest); - DEBUGP (("]")); - if (dhcp->ciaddr) - { - DEBUGP ((" ci=")); - PrIP (dhcp->ciaddr); - } - if (dhcp->yiaddr) - { - DEBUGP ((" yi=")); - PrIP (dhcp->yiaddr); - } - if (dhcp->siaddr) - { - DEBUGP ((" si=")); - PrIP (dhcp->siaddr); - } - if (dhcp->hlen == sizeof (MACADDR)) - { - DEBUGP ((" ch=")); - PrMac (dhcp->chaddr); - } - - DEBUGP ((" xid=0x%08x", ntohl (dhcp->xid))); - - if (ntohl (dhcp->magic) != 0x63825363) - DEBUGP ((" ma=0x%08x", ntohl (dhcp->magic))); - if (dhcp->htype != 1) - DEBUGP ((" htype=%d", dhcp->htype)); - if (dhcp->hops) - DEBUGP ((" hops=%d", dhcp->hops)); - if (ntohs (dhcp->secs)) - DEBUGP ((" secs=%d", ntohs (dhcp->secs))); - if (ntohs (dhcp->flags)) - DEBUGP ((" flags=0x%04x", ntohs (dhcp->flags))); - - // extra stuff - - if (ip->version_len != 0x45) - DEBUGP ((" vl=0x%02x", ip->version_len)); - if (ntohs (ip->tot_len) != sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen) - DEBUGP ((" tl=%d", ntohs (ip->tot_len))); - if (ntohs (udp->len) != sizeof (UDPHDR) + sizeof (DHCP) + optlen) - DEBUGP ((" ul=%d", ntohs (udp->len))); - - if (ip->tos) - DEBUGP ((" tos=0x%02x", ip->tos)); - if (ntohs (ip->id)) - DEBUGP ((" id=0x%04x", ntohs (ip->id))); - if (ntohs (ip->frag_off)) - DEBUGP ((" frag_off=0x%04x", ntohs (ip->frag_off))); - - DEBUGP ((" ttl=%d", ip->ttl)); - DEBUGP ((" ic=0x%04x [0x%04x]", ntohs (ip->check), - ip_checksum ((UCHAR*)ip, sizeof (IPHDR)))); - DEBUGP ((" uc=0x%04x [0x%04x/%d]", ntohs (udp->check), - udp_checksum ((UCHAR *) udp, - sizeof (UDPHDR) + sizeof (DHCP) + optlen, - (UCHAR *) &ip->saddr, - (UCHAR *) &ip->daddr), - optlen)); - - // Options - { - const UCHAR *opt = (UCHAR *) (dhcp + 1); - int i; - - DEBUGP ((" OPT")); - for (i = 0; i < optlen; ++i) - { - const UCHAR data = opt[i]; - DEBUGP ((".%d", data)); - } - } -} - -#endif /* DBG */ diff --git a/windows/TapDriver6/dhcp.h b/windows/TapDriver6/dhcp.h deleted file mode 100644 index b594a5e9..00000000 --- a/windows/TapDriver6/dhcp.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * TAP-Windows -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., - * and is released under the GPL version 2 (see below). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#pragma once - -#pragma pack(1) - -//=================================================== -// How many bad DHCPREQUESTs do we receive before we -// return a NAK? -// -// A bad DHCPREQUEST is defined to be one where the -// requestor doesn't know its IP address. -//=================================================== - -#define BAD_DHCPREQUEST_NAK_THRESHOLD 3 - -//============================================== -// Maximum number of DHCP options bytes supplied -//============================================== - -#define DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE 256 -#define DHCP_OPTIONS_BUFFER_SIZE 256 - -//=================================== -// UDP port numbers of DHCP messages. -//=================================== - -#define BOOTPS_PORT 67 -#define BOOTPC_PORT 68 - -//=========================== -// The DHCP message structure -//=========================== - -typedef struct { -# define BOOTREQUEST 1 -# define BOOTREPLY 2 - UCHAR op; /* message op */ - - UCHAR htype; /* hardware address type (e.g. '1' = 10Mb Ethernet) */ - UCHAR hlen; /* hardware address length (e.g. '6' for 10Mb Ethernet) */ - UCHAR hops; /* client sets to 0, may be used by relay agents */ - ULONG xid; /* transaction ID, chosen by client */ - USHORT secs; /* seconds since request process began, set by client */ - USHORT flags; - ULONG ciaddr; /* client IP address, client sets if known */ - ULONG yiaddr; /* 'your' IP address -- server's response to client */ - ULONG siaddr; /* server IP address */ - ULONG giaddr; /* relay agent IP address */ - UCHAR chaddr[16]; /* client hardware address */ - UCHAR sname[64]; /* optional server host name */ - UCHAR file[128]; /* boot file name */ - ULONG magic; /* must be 0x63825363 (network order) */ -} DHCP; - -typedef struct { - ETH_HEADER eth; - IPHDR ip; - UDPHDR udp; - DHCP dhcp; -} DHCPPre; - -typedef struct { - DHCPPre pre; - UCHAR options[DHCP_OPTIONS_BUFFER_SIZE]; -} DHCPFull; - -typedef struct { - unsigned int optlen; - BOOLEAN overflow; - DHCPFull msg; -} DHCPMsg; - -//=================== -// Macros for DHCPMSG -//=================== - -#define DHCPMSG_LEN_BASE(p) (sizeof (DHCPPre)) -#define DHCPMSG_LEN_OPT(p) ((p)->optlen) -#define DHCPMSG_LEN_FULL(p) (DHCPMSG_LEN_BASE(p) + DHCPMSG_LEN_OPT(p)) -#define DHCPMSG_BUF(p) ((UCHAR*) &(p)->msg) -#define DHCPMSG_OVERFLOW(p) ((p)->overflow) - -//======================================== -// structs to hold individual DHCP options -//======================================== - -typedef struct { - UCHAR type; -} DHCPOPT0; - -typedef struct { - UCHAR type; - UCHAR len; - UCHAR data; -} DHCPOPT8; - -typedef struct { - UCHAR type; - UCHAR len; - ULONG data; -} DHCPOPT32; - -#pragma pack() - -//================== -// DHCP Option types -//================== - -#define DHCP_MSG_TYPE 53 /* message type (u8) */ -#define DHCP_PARM_REQ 55 /* parameter request list: c1 (u8), ... */ -#define DHCP_CLIENT_ID 61 /* client ID: type (u8), i1 (u8), ... */ -#define DHCP_IP 50 /* requested IP addr (u32) */ -#define DHCP_NETMASK 1 /* subnet mask (u32) */ -#define DHCP_LEASE_TIME 51 /* lease time sec (u32) */ -#define DHCP_RENEW_TIME 58 /* renewal time sec (u32) */ -#define DHCP_REBIND_TIME 59 /* rebind time sec (u32) */ -#define DHCP_SERVER_ID 54 /* server ID: IP addr (u32) */ -#define DHCP_PAD 0 -#define DHCP_END 255 - -//==================== -// DHCP Messages types -//==================== - -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPDECLINE 4 -#define DHCPACK 5 -#define DHCPNAK 6 -#define DHCPRELEASE 7 -#define DHCPINFORM 8 - -#if DBG - -VOID -DumpDHCP (const ETH_HEADER *eth, - const IPHDR *ip, - const UDPHDR *udp, - const DHCP *dhcp, - const int optlen); - -#endif diff --git a/windows/TapDriver6/prototypes.h b/windows/TapDriver6/prototypes.h index ad70261d..a48d35e7 100644 --- a/windows/TapDriver6/prototypes.h +++ b/windows/TapDriver6/prototypes.h @@ -64,6 +64,7 @@ IndicateReceivePacket( __in const unsigned int packetLength ); +/* BOOLEAN ProcessDHCP( __in PTAP_ADAPTER_CONTEXT Adapter, @@ -73,7 +74,9 @@ ProcessDHCP( __in const DHCP *dhcp, __in int optlen ); +*/ +/* BOOLEAN ProcessARP( __in PTAP_ADAPTER_CONTEXT Adapter, @@ -83,5 +86,6 @@ ProcessARP( __in const IPADDR ip_netmask, __in const MACADDR mac ); +*/ #endif diff --git a/windows/TapDriver6/rxpath.c b/windows/TapDriver6/rxpath.c index 7415b5e4..318bc56a 100644 --- a/windows/TapDriver6/rxpath.c +++ b/windows/TapDriver6/rxpath.c @@ -432,7 +432,7 @@ TapDeviceWrite( // if(tapAdapterSendAndReceiveReady(adapter) == NDIS_STATUS_SUCCESS) { - if (!adapter->m_tun && ((irpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE)) + if (/*!adapter->m_tun &&*/ ((irpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE)) { PNET_BUFFER_LIST netBufferList; @@ -514,6 +514,7 @@ TapDeviceWrite( ntStatus = STATUS_INSUFFICIENT_RESOURCES; } } + /* else if (adapter->m_tun && ((irpSp->Parameters.Write.Length) >= IP_HEADER_SIZE)) { PETH_HEADER p_UserToTap = &adapter->m_UserToTap; @@ -637,6 +638,7 @@ TapDeviceWrite( ntStatus = STATUS_INSUFFICIENT_RESOURCES; } } + */ else { DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n", diff --git a/windows/TapDriver6/tap-windows.h b/windows/TapDriver6/tap-windows.h index d546a5b1..7e01846d 100644 --- a/windows/TapDriver6/tap-windows.h +++ b/windows/TapDriver6/tap-windows.h @@ -38,17 +38,24 @@ #define TAP_WIN_IOCTL_GET_MAC TAP_WIN_CONTROL_CODE (1, METHOD_BUFFERED) #define TAP_WIN_IOCTL_GET_VERSION TAP_WIN_CONTROL_CODE (2, METHOD_BUFFERED) #define TAP_WIN_IOCTL_GET_MTU TAP_WIN_CONTROL_CODE (3, METHOD_BUFFERED) -#define TAP_WIN_IOCTL_GET_INFO TAP_WIN_CONTROL_CODE (4, METHOD_BUFFERED) -#define TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT TAP_WIN_CONTROL_CODE (5, METHOD_BUFFERED) +//#define TAP_WIN_IOCTL_GET_INFO TAP_WIN_CONTROL_CODE (4, METHOD_BUFFERED) +//#define TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT TAP_WIN_CONTROL_CODE (5, METHOD_BUFFERED) #define TAP_WIN_IOCTL_SET_MEDIA_STATUS TAP_WIN_CONTROL_CODE (6, METHOD_BUFFERED) -#define TAP_WIN_IOCTL_CONFIG_DHCP_MASQ TAP_WIN_CONTROL_CODE (7, METHOD_BUFFERED) -#define TAP_WIN_IOCTL_GET_LOG_LINE TAP_WIN_CONTROL_CODE (8, METHOD_BUFFERED) -#define TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT TAP_WIN_CONTROL_CODE (9, METHOD_BUFFERED) +//#define TAP_WIN_IOCTL_CONFIG_DHCP_MASQ TAP_WIN_CONTROL_CODE (7, METHOD_BUFFERED) +//#define TAP_WIN_IOCTL_GET_LOG_LINE TAP_WIN_CONTROL_CODE (8, METHOD_BUFFERED) +//#define TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT TAP_WIN_CONTROL_CODE (9, METHOD_BUFFERED) /* Added in 8.2 */ /* obsoletes TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT */ -#define TAP_WIN_IOCTL_CONFIG_TUN TAP_WIN_CONTROL_CODE (10, METHOD_BUFFERED) +//#define TAP_WIN_IOCTL_CONFIG_TUN TAP_WIN_CONTROL_CODE (10, METHOD_BUFFERED) + +// Used by ZT1 to get multicast memberships at the L2 level -- Windows provides no native way to do this that I know of +#define TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS TAP_WIN_CONTROL_CODE (11, METHOD_BUFFERED) +// Must be the same as NIC_MAX_MCAST_LIST in constants.h +#define TAP_MAX_MCAST_LIST 128 +// Amount of memory that must be provided to ioctl TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS +#define TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE (TAP_MAX_MCAST_LIST * 6) /* * ================= diff --git a/windows/TapDriver6/tap.h b/windows/TapDriver6/tap.h index 61a97850..079b279f 100644 --- a/windows/TapDriver6/tap.h +++ b/windows/TapDriver6/tap.h @@ -42,10 +42,8 @@ #include "proto.h" #include "mem.h" #include "macinfo.h" -#include "dhcp.h" #include "error.h" #include "endian.h" -#include "dhcp.h" #include "types.h" #include "adapter.h" #include "device.h" diff --git a/windows/TapDriver6/txpath.c b/windows/TapDriver6/txpath.c index 6e084dfc..7993ca40 100644 --- a/windows/TapDriver6/txpath.c +++ b/windows/TapDriver6/txpath.c @@ -82,6 +82,8 @@ icmpv6_checksum( return ((USHORT) ~sum); } +/* + // check IPv6 packet for "is this an IPv6 Neighbor Solicitation that // the tap driver needs to answer?" // see RFC 4861 4.3 for the different cases @@ -267,6 +269,7 @@ ProcessARP( else return FALSE; } +*/ //============================================================= // CompleteIRP is normally called with an adapter -> userspace @@ -537,7 +540,8 @@ Return Value: // If so, catch both DHCP requests and ARP queries // to resolve the address of our virtual DHCP server. //===================================================== - if (Adapter->m_dhcp_enabled) +#if 0 + if (Adapter->m_dhcp_enabled) { const ETH_HEADER *eth = (ETH_HEADER *) tapPacket->m_Data; const IPHDR *ip = (IPHDR *) (tapPacket->m_Data + sizeof (ETH_HEADER)); @@ -594,15 +598,17 @@ Return Value: } } } +#endif - //=============================================== + //=============================================== // In Point-To-Point mode, check to see whether // packet is ARP (handled) or IPv4 (sent to app). // IPv6 packets are inspected for neighbour discovery // (to be handled locally), and the rest is forwarded // all other protocols are dropped //=============================================== - if (Adapter->m_tun) +#if 0 + if (Adapter->m_tun) { ETH_HEADER *e; @@ -669,8 +675,9 @@ Return Value: tapPacket->m_SizeFlags |= TP_TUN; } } +#endif - //=============================================== + //=============================================== // Push packet onto queue to wait for read from // userspace. //=============================================== -- cgit v1.2.3