From d4c06e924d3319c43ac9e7662332811a4afe0993 Mon Sep 17 00:00:00 2001
From: Adam Ierymenko <adam.ierymenko@zerotier.com>
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

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 @@
   <ItemGroup>
     <ClCompile Include="adapter.c" />
     <ClCompile Include="device.c" />
-    <ClCompile Include="dhcp.c" />
     <ClCompile Include="error.c" />
     <ClCompile Include="macinfo.c" />
     <ClCompile Include="mem.c" />
@@ -227,7 +226,6 @@
     <ClInclude Include="config.h" />
     <ClInclude Include="constants.h" />
     <ClInclude Include="device.h" />
-    <ClInclude Include="dhcp.h" />
     <ClInclude Include="endian.h" />
     <ClInclude Include="error.h" />
     <ClInclude Include="hexdump.h" />
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 @@
     <ClCompile Include="device.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="dhcp.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="error.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -63,9 +60,6 @@
     <ClInclude Include="device.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="dhcp.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="endian.h">
       <Filter>Header Files</Filter>
     </ClInclude>
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;i<adapter->ulMCListSize;++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