[Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/handhelds/apps/AccessPointWindows/802_15_4_AP/tap-win32 MAKEFILE, NONE, 1.1 SOURCES.in, NONE, 1.1 common.h, NONE, 1.1 common.h.23570$, NONE, 1.1 constants.h, NONE, 1.1 dhcp.c, NONE, 1.1 dhcp.h, NONE, 1.1 endian.h, NONE, 1.1 error.c, NONE, 1.1 error.h, NONE, 1.1 hexdump.c, NONE, 1.1 hexdump.h, NONE, 1.1 instance.c, NONE, 1.1 lock.h, NONE, 1.1 macinfo.c, NONE, 1.1 macinfo.h, NONE, 1.1 mem.c, NONE, 1.1 proto.h, NONE, 1.1 prototypes.h, NONE, 1.1 resource.rc, NONE, 1.1 tapdrvr.c, NONE, 1.1 types.h, NONE, 1.1

steve ayer ayer1 at users.sourceforge.net
Fri Aug 29 08:24:33 PDT 2008


Update of /cvsroot/tinyos/tinyos-1.x/contrib/handhelds/apps/AccessPointWindows/802_15_4_AP/tap-win32
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv22785/AccessPointWindows/802_15_4_AP/tap-win32

Added Files:
	MAKEFILE SOURCES.in common.h common.h.$$$ constants.h dhcp.c 
	dhcp.h endian.h error.c error.h hexdump.c hexdump.h instance.c 
	lock.h macinfo.c macinfo.h mem.c proto.h prototypes.h 
	resource.rc tapdrvr.c types.h 
Log Message:

first check-in of catalin caranfil's windows version of the 802.15.4
access point s/w suite written by andrew christian.


--- NEW FILE: MAKEFILE ---
#
# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
# file to this component.  This file merely indirects to the real make file
# that is shared by all the components of NT OS/2
#
!INCLUDE $(NTMAKEENV)\makefile.def

--- NEW FILE: SOURCES.in ---
# Build TAP-Win32 driver.
# Build Command: build -cef

MAJORCOMP=ntos
MINORCOMP=ndis

TARGETNAME=@@PRODUCT_TAP_ID@@
TARGETTYPE=DRIVER
TARGETPATH=.
TARGETLIBS=$(DDK_LIB_PATH)\ndis.lib $(DDK_LIB_PATH)\ntstrsafe.lib
INCLUDES=$(DDK_INCLUDE_PATH)

# The TAP version numbers here must be >=
# TAP_WIN32_MIN_x values defined in
# config-win32.h
C_DEFINES=
C_DEFINES=$(C_DEFINES) -DTAP_DRIVER_MAJOR_VERSION=@@PRODUCT_TAP_MAJOR_VER@@
C_DEFINES=$(C_DEFINES) -DTAP_DRIVER_MINOR_VERSION=@@PRODUCT_TAP_MINOR_VER@@

# Produce the same symbolic information for both free & checked builds.
# This will allow us to perform full source-level debugging on both
# builds without affecting the free build's performance.
!IF "$(DDKBUILDENV)" != "chk"
NTDEBUGTYPE=both
USE_PDB=1
!ELSE
NTDEBUGTYPE=both
USE_PDB=1
!ENDIF

# Set compiler optimizations:
# /Ox - Full optimization enabled
# /Os - favor speed over size when optimizing
# /Od - Disable all optimizations
# /Oi - Enable optimization for intrinsic functions
# /Fc - Generate mixed assembler/source code files
#
# For both checked and free builds, make sure that any intrinsic
# functions are compiled correctly. To do this, ensure that /Oi
# is selected for both free and checked builds. There is a bug in
# VC++ 6.0 (at least through SP4) where, if you specify any
# intrinsic functions in your code with "#pragma intrinsic" but
# you don't have the /Oi optimization enabled, neither a call
# to the function, nor the intrinsic inline version of the function
# will end up in your object code. This bug only applies to free
# builds, but just to be safe we'll make sure that the flag is
# enabled for all builds.

!IF "$(DDKBUILDENV)" != "chk"
MSC_OPTIMIZATION=/Ox /Oi /Fc
!ELSE
MSC_OPTIMIZATION=/Od /Oi /Fc
!ENDIF

# Generate a linker map file just in case we need one for debugging
LINKER_FLAGS=$(LINKER_FLAGS) /MAP /MAPINFO:EXPORTS /MAPINFO:LINES

# Generate a browser information file for use in IDE development
#BROWSER_INFO=1
#BROWSERFILE=$(TARGETNAME).BSC -n

# Abort compilation on warnings by adding /WX
MSC_WARNING_LEVEL=/W3

SOURCES=tapdrvr.c resource.rc

--- NEW FILE: common.h ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

//===============================================
// This file is included both by OpenVPN and
// the TAP-Win32 driver and contains definitions
// common to both.
//===============================================

//#include "../autodefs/defs.h"

//=============
// TAP IOCTLs
//=============

#define TAP_CONTROL_CODE(request,method) \
  CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)

// Present in 8.1

#define TAP_IOCTL_GET_MAC               TAP_CONTROL_CODE (1, METHOD_BUFFERED)
#define TAP_IOCTL_GET_VERSION           TAP_CONTROL_CODE (2, METHOD_BUFFERED)
#define TAP_IOCTL_GET_MTU               TAP_CONTROL_CODE (3, METHOD_BUFFERED)
#define TAP_IOCTL_GET_INFO              TAP_CONTROL_CODE (4, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
#define TAP_IOCTL_SET_MEDIA_STATUS      TAP_CONTROL_CODE (6, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_DHCP_MASQ      TAP_CONTROL_CODE (7, METHOD_BUFFERED)
#define TAP_IOCTL_GET_LOG_LINE          TAP_CONTROL_CODE (8, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_DHCP_SET_OPT   TAP_CONTROL_CODE (9, METHOD_BUFFERED)

// Added in 8.2

/* obsoletes TAP_IOCTL_CONFIG_POINT_TO_POINT */
#define TAP_IOCTL_CONFIG_TUN            TAP_CONTROL_CODE (10, METHOD_BUFFERED)

//=================
// Registry keys
//=================

#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"

#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"

//======================
// Filesystem prefixes
//======================

#define USERMODEDEVICEDIR "\\\\.\\Global\\"
#define SYSDEVICEDIR      "\\Device\\"
#define USERDEVICEDIR     "\\DosDevices\\Global\\"
#define TAPSUFFIX         ".tap"

//=========================================================
// TAP_COMPONENT_ID -- This string defines the TAP driver
// type -- different component IDs can reside in the system
// simultaneously.
//=========================================================

#define TAP_COMPONENT_ID PRODUCT_TAP_ID

--- NEW FILE: common.h.$$$ ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

//===============================================
// This file is included both by OpenVPN and
// the TAP-Win32 driver and contains definitions
// common to both.
//===============================================

#include "../autodefs/defs.h"

//=============
// TAP IOCTLs
//=============

#define TAP_CONTROL_CODE(request,method) \
  CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)

// Present in 8.1

#define TAP_IOCTL_GET_MAC               TAP_CONTROL_CODE (1, METHOD_BUFFERED)
#define TAP_IOCTL_GET_VERSION           TAP_CONTROL_CODE (2, METHOD_BUFFERED)
#define TAP_IOCTL_GET_MTU               TAP_CONTROL_CODE (3, METHOD_BUFFERED)
#define TAP_IOCTL_GET_INFO              TAP_CONTROL_CODE (4, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
#define TAP_IOCTL_SET_MEDIA_STATUS      TAP_CONTROL_CODE (6, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_DHCP_MASQ      TAP_CONTROL_CODE (7, METHOD_BUFFERED)
#define TAP_IOCTL_GET_LOG_LINE          TAP_CONTROL_CODE (8, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_DHCP_SET_OPT   TAP_CONTROL_CODE (9, METHOD_BUFFERED)

// Added in 8.2

/* obsoletes TAP_IOCTL_CONFIG_POINT_TO_POINT */
#define TAP_IOCTL_CONFIG_TUN            TAP_CONTROL_CODE (10, METHOD_BUFFERED)

//=================
// Registry keys
//=================

#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"

#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"

//======================
// Filesystem prefixes
//======================

#define USERMODEDEVICEDIR "\\\\.\\Global\\"
#define SYSDEVICEDIR      "\\Device\\"
#define USERDEVICEDIR     "\\DosDevices\\Global\\"
#define TAPSUFFIX         ".tap"

//=========================================================
// TAP_COMPONENT_ID -- This string defines the TAP driver
// type -- different component IDs can reside in the system
// simultaneously.
//=========================================================

#define TAP_COMPONENT_ID PRODUCT_TAP_ID

--- NEW FILE: constants.h ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

//====================================================================
//                        Product and Version public settings
//====================================================================

#define PRODUCT_STRING PRODUCT_TAP_DEVICE_DESCRIPTION

#define TAP_NDIS_MAJOR_VERSION 5
#define TAP_NDIS_MINOR_VERSION 0

//===========================================================
// Driver constants
//===========================================================

#define ETHERNET_HEADER_SIZE     (sizeof (ETH_HEADER))
#define ETHERNET_MTU             1500
#define ETHERNET_PACKET_SIZE     (ETHERNET_MTU + ETHERNET_HEADER_SIZE)
#define DEFAULT_PACKET_LOOKAHEAD (ETHERNET_PACKET_SIZE)

#define NIC_MAX_MCAST_LIST 32  // Max length of multicast address list

#define MINIMUM_MTU 576        // USE TCP Minimum MTU
#define MAXIMUM_MTU 65536      // IP maximum MTU

#define PACKET_QUEUE_SIZE   64 // tap -> userspace queue size
#define IRP_QUEUE_SIZE      16 // max number of simultaneous i/o operations from userspace

#define TAP_LITTLE_ENDIAN      // affects ntohs, htonl, etc. functions

--- NEW FILE: dhcp.c ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

//=========================
// Code to set DHCP options
//=========================

VOID
SetDHCPOpt (DHCPMsg *m, void *data, 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 (DHCPMsg *msg, int type)
{
  DHCPOPT0 opt;
  opt.type = (UCHAR) type;
  SetDHCPOpt (msg, &opt, sizeof (opt));
}

VOID
SetDHCPOpt8 (DHCPMsg *msg, int type, ULONG data)
{
  DHCPOPT8 opt;
  opt.type = (UCHAR) type;
  opt.len = sizeof (opt.data);
  opt.data = (UCHAR) data;
  SetDHCPOpt (msg, &opt, sizeof (opt));
}

VOID
SetDHCPOpt32 (DHCPMsg *msg, int type, 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 (const UCHAR *buf, 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 (const UCHAR *buf,
	      const int len_udp,
	      const UCHAR *src_addr,
	      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 (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 (const DHCP *dhcp, 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 (const TapAdapterPointer p_Adapter,
		 const ETH_HEADER *eth,
		 const IPHDR *ip,
		 const UDPHDR *udp,
		 const DHCP *dhcp)
{
  // Must be UDPv4 protocol
  if (!(eth->proto == htons (ETH_P_IP) && ip->protocol == IPPROTO_UDP))
    return FALSE;

  // Source MAC must be our adapter
  if (!MAC_EQUAL (eth->src, p_Adapter->m_MAC))
    return FALSE;

  // Dest MAC must be either broadcast or our virtual DHCP server
  if (!(MAC_EQUAL (eth->dest, p_Adapter->m_MAC_Broadcast)
	|| MAC_EQUAL (eth->dest, p_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 (const TapAdapterPointer a,
	      DHCPPre *p,
	      const ETH_HEADER *eth,
	      const IPHDR *ip,
	      const UDPHDR *udp,
	      const DHCP *dhcp,
	      const int optlen,
	      const int type)
{
  // Should we broadcast or direct to a specific MAC / IP address?
  const BOOLEAN broadcast = (type == DHCPNAK
			     || MAC_EQUAL (eth->dest, a->m_MAC_Broadcast));
  // Build ethernet header

  COPY_MAC (p->eth.src, a->m_dhcp_server_mac);

  if (broadcast)
    COPY_MAC (p->eth.dest, a->m_MAC_Broadcast);
  else
    COPY_MAC (p->eth.dest, eth->src);

  p->eth.proto = htons (ETH_P_IP);

  // 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 = a->m_dhcp_server_ip;

  if (broadcast)
    p->ip.daddr = ~0;
  else
    p->ip.daddr = a->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 = a->m_dhcp_addr;

  p->dhcp.siaddr = a->m_dhcp_server_ip;
  p->dhcp.giaddr = 0;
  COPY_MAC (p->dhcp.chaddr, eth->src);
  p->dhcp.magic = htonl (0x63825363);
}
//=============================
// Build specific DHCP messages
//=============================

VOID
SendDHCPMsg (const TapAdapterPointer a,
	     const int type,
	     const ETH_HEADER *eth,
	     const IPHDR *ip,
	     const UDPHDR *udp,
	     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, a->m_dhcp_server_ip);

      if (type == DHCPOFFER || type == DHCPACK)
	{
	  // Lease Time
	  SetDHCPOpt32 (pkt, DHCP_LEASE_TIME, htonl (a->m_dhcp_lease_time));

	  // Netmask
	  SetDHCPOpt32 (pkt, DHCP_NETMASK, a->m_dhcp_netmask);

	  // Other user-defined options
	  SetDHCPOpt (pkt,
		      a->m_dhcp_user_supplied_options_buffer,
		      a->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 (a,
			&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
	  InjectPacket (a,
			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_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 (TapAdapterPointer p_Adapter,
	     const ETH_HEADER *eth,
	     const IPHDR *ip,
	     const UDPHDR *udp,
	     const DHCP *dhcp,
	     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 (p_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 != p_Adapter->m_dhcp_addr)
	  || !p_Adapter->m_dhcp_received_discover
	  || p_Adapter->m_dhcp_bad_requests >= BAD_DHCPREQUEST_NAK_THRESHOLD))
    SendDHCPMsg (p_Adapter,
		 DHCPNAK,
		 eth, ip, udp, dhcp);
  else
    SendDHCPMsg (p_Adapter,
		 (msg_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK),
		 eth, ip, udp, dhcp);

  // Remember if we received a DHCPDISCOVER
  if (msg_type == DHCPDISCOVER)
    p_Adapter->m_dhcp_received_discover = TRUE;

  // Is this a bad DHCPREQUEST?
  if (msg_type == DHCPREQUEST && dhcp->ciaddr != p_Adapter->m_dhcp_addr)
    ++p_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 */

--- NEW FILE: dhcp.h ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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 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

--- NEW FILE: endian.h ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

#ifdef TAP_LITTLE_ENDIAN
#define ntohs(x) RtlUshortByteSwap(x)
#define htons(x) RtlUshortByteSwap(x)
#define ntohl(x) RtlUlongByteSwap(x)
#define htonl(x) RtlUlongByteSwap(x)
#else
#define ntohs(x) ((USHORT)(x))
#define htons(x) ((USHORT)(x))
#define ntohl(x) ((ULONG)(x))
#define htonl(x) ((ULONG)(x))
#endif

--- NEW FILE: error.c ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

//-----------------
// DEBUGGING OUTPUT
//-----------------

const char *g_LastErrorFilename;
int g_LastErrorLineNumber;

#if DBG

DebugOutput g_Debug;

BOOLEAN
NewlineExists (const char *str, int len)
{
  while (len-- > 0)
    {
      const char c = *str++;
      if (c == '\n')
	return TRUE;
      else if (c == '\0')
	break;
    }
  return FALSE;
}

VOID
MyDebugInit (unsigned int bufsiz)
{
  NdisZeroMemory (&g_Debug, sizeof (g_Debug));
  g_Debug.text = (char *) MemAlloc (bufsiz, FALSE);
  if (g_Debug.text)
    g_Debug.capacity = bufsiz;
}

VOID
MyDebugFree ()
{
  if (g_Debug.text)
    MemFree (g_Debug.text, g_Debug.capacity);
  NdisZeroMemory (&g_Debug, sizeof (g_Debug));
}

VOID
MyDebugPrint (const unsigned char* format, ...)
{
  if (g_Debug.text && g_Debug.capacity > 0 && CAN_WE_PRINT)
    {
      BOOLEAN owned;
      ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);
      if (owned)
	{
	  const int remaining = (int)g_Debug.capacity - (int)g_Debug.out;

	  if (remaining > 0)
	    {
	      va_list args;
	      NTSTATUS status;
	      char *end;

	      va_start (args, format);
	      status = RtlStringCchVPrintfExA (g_Debug.text + g_Debug.out,
					       remaining,
					       &end,
					       NULL,
					       STRSAFE_NO_TRUNCATION | STRSAFE_IGNORE_NULLS,
					       format,
					       args);
	      va_end (args);

	      if (status == STATUS_SUCCESS)
		g_Debug.out = (unsigned int) (end - g_Debug.text);
	      else
		g_Debug.error = TRUE;
	    }
	  else
	    g_Debug.error = TRUE;

	  RELEASE_MUTEX (&g_Debug.lock);
	}
      else
	g_Debug.error = TRUE;
    }
}

BOOLEAN
GetDebugLine (char *buf, const int len)
{
  static const char *truncated = "[OUTPUT TRUNCATED]\n";
  BOOLEAN ret = FALSE;

  NdisZeroMemory (buf, len);

  if (g_Debug.text && g_Debug.capacity > 0)
    {
      BOOLEAN owned;
      ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);
      if (owned)
	{
	  int i = 0;

	  if (g_Debug.error || NewlineExists (g_Debug.text + g_Debug.in, (int)g_Debug.out - (int)g_Debug.in))
	    {
	      while (i < (len - 1) && g_Debug.in < g_Debug.out)
		{
		  const char c = g_Debug.text[g_Debug.in++];
		  if (c == '\n')
		    break;
		  buf[i++] = c;
		}
	      if (i < len)
		buf[i] = '\0';
	    }

	  if (!i)
	    {
	      if (g_Debug.in == g_Debug.out)
		{
		  g_Debug.in = g_Debug.out = 0;
		  if (g_Debug.error)
		    {
		      const unsigned int tlen = strlen (truncated);
		      if (tlen < g_Debug.capacity)
			{
			  NdisMoveMemory (g_Debug.text, truncated, tlen+1);
			  g_Debug.out = tlen;
			}
		      g_Debug.error = FALSE;
		    }
		}
	    }
	  else
	    ret = TRUE;

	  RELEASE_MUTEX (&g_Debug.lock);
	}      
    }
  return ret;
}

VOID
MyAssert (const unsigned char *file, int line)
{
      DEBUGP (("MYASSERT failed %s/%d\n", file, line));
      KeBugCheckEx (0x0F00BABA,
		    (ULONG_PTR) line,
		    (ULONG_PTR) 0,
		    (ULONG_PTR) 0,
		    (ULONG_PTR) 0);
}

VOID
PrMac (const MACADDR mac)
{
  DEBUGP (("%x:%x:%x:%x:%x:%x",
	    mac[0], mac[1], mac[2],
	    mac[3], mac[4], mac[5]));
}

VOID
PrIP (IPADDR ip_addr)
{
  const unsigned char *ip = (const unsigned char *) &ip_addr;

  DEBUGP (("%d.%d.%d.%d",
	    ip[0], ip[1], ip[2], ip[3]));
}

const char *
PrIPProto (int proto)
{
  switch (proto)
    {
    case IPPROTO_UDP:
      return "UDP";
    case IPPROTO_TCP:
      return "TCP";
    case IPPROTO_ICMP:
      return "ICMP";
    case IPPROTO_IGMP:
      return "IGMP";
    default:
      return "???";
    }
}

VOID
DumpARP (const char *prefix, const ARP_PACKET *arp)
{
  DEBUGP (("%s ARP src=", prefix));
  PrMac (arp->m_MAC_Source);
  DEBUGP ((" dest="));
  PrMac (arp->m_MAC_Destination);
  DEBUGP ((" OP=0x%04x",
	    (int)ntohs(arp->m_ARP_Operation)));
  DEBUGP ((" M=0x%04x(%d)",
	    (int)ntohs(arp->m_MAC_AddressType),
	    (int)arp->m_MAC_AddressSize));
  DEBUGP ((" P=0x%04x(%d)",
	    (int)ntohs(arp->m_PROTO_AddressType),
	    (int)arp->m_PROTO_AddressSize));

  DEBUGP ((" MacSrc="));
  PrMac (arp->m_ARP_MAC_Source);
  DEBUGP ((" MacDest="));
  PrMac (arp->m_ARP_MAC_Destination);

  DEBUGP ((" IPSrc="));
  PrIP (arp->m_ARP_IP_Source);
  DEBUGP ((" IPDest="));
  PrIP (arp->m_ARP_IP_Destination);

  DEBUGP (("\n"));
}

struct ethpayload {
  ETH_HEADER eth;
  UCHAR payload[DEFAULT_PACKET_LOOKAHEAD];
};

VOID
DumpPacket2 (const char *prefix,
	     const ETH_HEADER *eth,
	     const unsigned char *data,
	     unsigned int len)
{
  struct ethpayload *ep = (struct ethpayload *) MemAlloc (sizeof (struct ethpayload), TRUE);
  if (ep)
    {
      if (len > DEFAULT_PACKET_LOOKAHEAD)
	len = DEFAULT_PACKET_LOOKAHEAD;
      ep->eth = *eth;
      NdisMoveMemory (ep->payload, data, len);
      DumpPacket (prefix, (unsigned char *) ep, sizeof (ETH_HEADER) + len);
      MemFree (ep, sizeof (struct ethpayload));
    }
}

VOID
DumpPacket (const char *prefix,
	    const unsigned char *data,
	    unsigned int len)
{
  const ETH_HEADER *eth = (const ETH_HEADER *) data;
  const IPHDR *ip = (const IPHDR *) (data + sizeof (ETH_HEADER));

  if (len < sizeof (ETH_HEADER))
    {
      DEBUGP (("%s TRUNCATED PACKET LEN=%d\n", prefix, len));
      return;
    }

  // ARP Packet?
  if (len >= sizeof (ARP_PACKET) && eth->proto == htons (ETH_P_ARP))
    {
      DumpARP (prefix, (const ARP_PACKET *) data);
      return;
    }

  // IPv4 packet?
  if (len >= (sizeof (IPHDR) + sizeof (ETH_HEADER))
      && eth->proto == htons (ETH_P_IP)
      && IPH_GET_VER (ip->version_len) == 4)
    {
      const int hlen = IPH_GET_LEN (ip->version_len);
      const int blen = len - sizeof (ETH_HEADER);
      BOOLEAN did = FALSE;

      DEBUGP (("%s IPv4 %s[%d]", prefix, PrIPProto (ip->protocol), len));

      if (!(ntohs (ip->tot_len) == blen && hlen <= blen))
	{
	  DEBUGP ((" XXX"));
	  return;
	}
      
      // TCP packet?
      if (ip->protocol == IPPROTO_TCP
	  && blen - hlen >= (sizeof (TCPHDR)))
	{
	  const TCPHDR *tcp = (TCPHDR *) (data + sizeof (ETH_HEADER) + hlen);
	  DEBUGP ((" "));
	  PrIP (ip->saddr);
	  DEBUGP ((":%d", ntohs (tcp->source)));
	  DEBUGP ((" -> "));
	  PrIP (ip->daddr);
	  DEBUGP ((":%d", ntohs (tcp->dest)));
	  did = TRUE;
	}

      // UDP packet?
      else if ((ntohs (ip->frag_off) & IP_OFFMASK) == 0
	       && ip->protocol == IPPROTO_UDP
	       && blen - hlen >= (sizeof (UDPHDR)))
	{
	  const UDPHDR *udp = (UDPHDR *) (data + sizeof (ETH_HEADER) + hlen);
	  
	  // DHCP packet?
	  if ((udp->dest == htons (BOOTPC_PORT) || udp->dest == htons (BOOTPS_PORT))
	      && blen - hlen >= (sizeof (UDPHDR) + sizeof (DHCP)))
	    {
	      const DHCP *dhcp = (DHCP *) (data
					   + hlen
					   + sizeof (ETH_HEADER)
					   + sizeof (UDPHDR));
	      
	      int optlen = len
		- sizeof (ETH_HEADER)
		- hlen
		- sizeof (UDPHDR)
		- sizeof (DHCP);

	      if (optlen < 0)
		optlen = 0;

	      DumpDHCP (eth, ip, udp, dhcp, optlen);
	      did = TRUE;
	    }

	  if (!did)
	    {
	      DEBUGP ((" "));
	      PrIP (ip->saddr);
	      DEBUGP ((":%d", ntohs (udp->source)));
	      DEBUGP ((" -> "));
	      PrIP (ip->daddr);
	      DEBUGP ((":%d", ntohs (udp->dest)));
	      did = TRUE;
	    }
	}

      if (!did)
	{
	  DEBUGP ((" ipproto=%d ", ip->protocol));
	  PrIP (ip->saddr);
	  DEBUGP ((" -> "));
	  PrIP (ip->daddr);
	}

      DEBUGP (("\n"));
      return;
    }

  {
    DEBUGP (("%s ??? src=", prefix));
    PrMac (eth->src);
    DEBUGP ((" dest="));
    PrMac (eth->dest);
    DEBUGP ((" proto=0x%04x len=%d\n",
	      (int) ntohs(eth->proto),
	      len));
  }
}

#endif

--- NEW FILE: error.h ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

//-----------------
// DEBUGGING OUTPUT
//-----------------

#define NOTE_ERROR() \
{ \
  g_LastErrorFilename = __FILE__; \
  g_LastErrorLineNumber = __LINE__; \
}

#if DBG

typedef struct {
  unsigned int in;
  unsigned int out;
  unsigned int capacity;
  char *text;
  BOOLEAN error;
  MUTEX lock;
} DebugOutput;

VOID MyDebugPrint (const unsigned char* format, ...);

VOID MyAssert (const unsigned char *file, int line);

VOID DumpPacket (const char *prefix,
		 const unsigned char *data,
		 unsigned int len);

VOID DumpPacket2 (const char *prefix,
		  const ETH_HEADER *eth,
		  const unsigned char *data,
		  unsigned int len);

#define CAN_WE_PRINT (DEBUGP_AT_DISPATCH || KeGetCurrentIrql () < DISPATCH_LEVEL)

#if ALSO_DBGPRINT
#define DEBUGP(fmt) { MyDebugPrint fmt; if (CAN_WE_PRINT) DbgPrint fmt; }
#else
#define DEBUGP(fmt) { MyDebugPrint fmt; }
#endif

#define MYASSERT(exp) \
{ \
  if (!(exp)) \
    { \
      MyAssert(__FILE__, __LINE__); \
    } \
}

#define DUMP_PACKET(prefix, data, len) \
  DumpPacket (prefix, data, len)

#define DUMP_PACKET2(prefix, eth, data, len) \
  DumpPacket2 (prefix, eth, data, len)

#else 

#define DEBUGP(fmt)
#define MYASSERT(exp)
#define DUMP_PACKET(prefix, data, len)
#define DUMP_PACKET2(prefix, eth, data, len)

#endif

--- NEW FILE: hexdump.c ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

#ifdef __cplusplus
extern "C" {
#endif

#include "hexdump.h"

#ifndef NDIS_MINIPORT_DRIVER

VOID (*DbgMessage)(char *p_Format, ...) = DisplayDebugString;

VOID DisplayDebugString (char *p_Format, ...)
   {
    static char l_Buffer [4096];

    va_list l_ArgumentList; 
    va_start (l_ArgumentList, p_Format); 
    vsprintf (l_Buffer, p_Format, l_ArgumentList); 
    va_end (l_ArgumentList); 

    OutputDebugStringA (l_Buffer);
   }

#endif

VOID HexDump (unsigned char *p_Buffer, unsigned long p_Size)
   {
    unsigned long l_Index, l_Idx;
    unsigned char l_Row [17];

    for (l_Index = l_Row [16] = 0; l_Index < p_Size || l_Index % 16; ++l_Index)
       {
        if (l_Index % 16 == 0)
	  DEBUGP (("%05x   ", l_Index));
        DEBUGP (("%02x ", l_Row [l_Index % 16] = (l_Index < p_Size ? p_Buffer [l_Index] : 0)));
        l_Row [l_Index % 16] = IfPrint (l_Row [l_Index % 16]);
        if ((l_Index + 1) % 16 == 0)
	  DEBUGP (("   %s\n", l_Row));
       }

    DEBUGP (("\n"));
   }

#ifdef __cplusplus
}
#endif

--- NEW FILE: hexdump.h ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

#ifndef HEXDUMP_DEFINED
#define HEXDUMP_DEFINED

#ifdef __cplusplus
extern "C" {
#endif

//=====================================================================================
//                                   Debug Routines
//=====================================================================================

#ifndef NDIS_MINIPORT_DRIVER
#   include <stdio.h>
#   include <ctype.h>
#   include <windows.h>
#   include <winnt.h>
#   include <memory.h>

#   ifndef DEBUGP
#      define DEBUGP(fmt) { DbgMessage fmt; }
#   endif

    extern VOID (*DbgMessage)(char *p_Format, ...);

    VOID DisplayDebugString (char *p_Format, ...);
#endif

//===================================================================================
//                              Reporting / Debugging
//===================================================================================
#define IfPrint(c) (c >= 32 && c < 127 ? c : '.')

VOID HexDump (unsigned char *p_Buffer, unsigned long p_Size);

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: instance.c ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

#define INSTANCE_KEY(a) ((PVOID)((a)->m_Extension.m_TapDevice))

#define N_INSTANCE_BUCKETS 256

typedef struct _INSTANCE {
  struct _INSTANCE *next;
  TapAdapterPointer m_Adapter;
} INSTANCE;

typedef struct {
  INSTANCE *list;
  MUTEX lock;
} INSTANCE_BUCKET;

typedef struct {
  INSTANCE_BUCKET buckets[N_INSTANCE_BUCKETS];
} INSTANCE_HASH;

INSTANCE_HASH *g_InstanceHash = NULL;

// must return a hash >= 0 and < N_INSTANCE_BUCKETS
int
InstanceHashValue (PVOID addr)
{
  UCHAR *p = (UCHAR *) &addr;

  if (sizeof (addr) == 4)
    return p[0] ^ p[1] ^ p[2] ^ p[3];
  else if (sizeof (addr) == 8)
    return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4] ^ p[5] ^ p[6] ^ p[7];
  else
    {
      MYASSERT (0);
    }
}

BOOLEAN
InitInstanceList (VOID)
{
  MYASSERT (g_InstanceHash == NULL);
  g_InstanceHash = MemAlloc (sizeof (INSTANCE_HASH), TRUE);
  if (g_InstanceHash)
    {
      int i;
      for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
	INIT_MUTEX (&g_InstanceHash->buckets[i].lock);
      return TRUE;
    }
  else
    return FALSE;
}

int
NInstances (VOID)
{
  int i, n = 0;

  if (g_InstanceHash)
    {
      for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
	{
	  BOOLEAN got_lock;
	  INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
	  ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);

	  if (got_lock)
	    {
	      INSTANCE *current;
	      for (current = ib->list; current != NULL; current = current->next)
		++n;
	      RELEASE_MUTEX (&ib->lock);
	    }
	  else
	    return -1;
	}
    }

  return n;
}

int
InstanceMaxBucketSize (VOID)
{
  int i, n = 0;

  if (g_InstanceHash)
    {
      for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
	{
	  BOOLEAN got_lock;
	  int bucket_size = 0;
	  INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
	  ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);

	  if (got_lock)
	    {
	      INSTANCE *current;
	      for (current = ib->list; current != NULL; current = current->next)
		  ++bucket_size;
	      if (bucket_size > n)
		n = bucket_size;
	      RELEASE_MUTEX (&ib->lock);
	    }
	  else
	    return -1;
	}
    }

  return n;
}

VOID
FreeInstanceList (VOID)
{
  if (g_InstanceHash)
    {
      MYASSERT (NInstances() == 0);
      MemFree (g_InstanceHash, sizeof (INSTANCE_HASH));
      g_InstanceHash = NULL;
    }
}

BOOLEAN
AddAdapterToInstanceList (TapAdapterPointer p_Adapter)
{
  BOOLEAN got_lock;
  BOOLEAN ret = FALSE;
  const int hash = InstanceHashValue(INSTANCE_KEY(p_Adapter));
  INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[hash];

  DEBUGP (("[TAP] AddAdapterToInstanceList hash=%d\n", hash));

  ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);

  if (got_lock)
    {
      INSTANCE *i = MemAlloc (sizeof (INSTANCE), FALSE);
      if (i)
	{
	  MYASSERT (p_Adapter);
	  i->m_Adapter = p_Adapter;
	  i->next = ib->list;
	  ib->list = i;
	  ret = TRUE;
	}
      RELEASE_MUTEX (&ib->lock);
    }

  return ret;
}

BOOLEAN
RemoveAdapterFromInstanceList (TapAdapterPointer p_Adapter)
{
  BOOLEAN got_lock;
  BOOLEAN ret = FALSE;
  INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue(INSTANCE_KEY(p_Adapter))];

  ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);

  if (got_lock)
    {
      INSTANCE *current, *prev=NULL;
      for (current = ib->list; current != NULL; current = current->next)
	{
	  if (current->m_Adapter == p_Adapter) // found match
	    {
	      if (prev)
		prev->next = current->next;
	      else
		ib->list = current->next;
	      MemFree (current->m_Adapter, sizeof (TapAdapter));
	      MemFree (current, sizeof (INSTANCE));
	      ret = TRUE;
	      break;
	    }
	  prev = current;
	}
      RELEASE_MUTEX (&ib->lock);
    }

  return ret;
}

TapAdapterPointer
LookupAdapterInInstanceList (PDEVICE_OBJECT p_DeviceObject)
{
  BOOLEAN got_lock;
  TapAdapterPointer ret = NULL;
  INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue((PVOID)p_DeviceObject)];

  ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);

  if (got_lock)
    {
      INSTANCE *current, *prev=NULL;
      for (current = ib->list; current != NULL; current = current->next)
	{
	  if (p_DeviceObject == INSTANCE_KEY (current->m_Adapter)) // found match
	    {
	      // move it to head of list
	      if (prev)
		{
		  prev->next = current->next;
		  current->next = ib->list;
		  ib->list = current;
		}
	      ret = ib->list->m_Adapter;
	      break;
	    }
	  prev = current;
	}
      RELEASE_MUTEX (&ib->lock);
    }

  return ret;
}

--- NEW FILE: lock.h ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

typedef struct
{
  volatile long count;
} MUTEX;

#define MUTEX_SLEEP_TIME  10000 // microseconds

#define INIT_MUTEX(m) { (m)->count = 0; }

#define ACQUIRE_MUTEX_BLOCKING(m)                         \
{                                                         \
    while (NdisInterlockedIncrement (&((m)->count)) != 1) \
    {                                                     \
        NdisInterlockedDecrement(&((m)->count));          \
        NdisMSleep(MUTEX_SLEEP_TIME);                     \
    }                                                     \
}

#define RELEASE_MUTEX(m)                                  \
{                                                         \
        NdisInterlockedDecrement(&((m)->count));          \
}

#define ACQUIRE_MUTEX_NONBLOCKING(m, result)              \
{                                                         \
    if (NdisInterlockedIncrement (&((m)->count)) != 1)    \
    {                                                     \
        NdisInterlockedDecrement(&((m)->count));          \
        result = FALSE;                                   \
    }                                                     \
    else                                                  \
    {                                                     \
	result = TRUE;                                    \
    }                                                     \
}

#define ACQUIRE_MUTEX_ADAPTIVE(m, result)                 \
{                                                         \
    result = TRUE;                                        \
    while (NdisInterlockedIncrement (&((m)->count)) != 1) \
    {                                                     \
        NdisInterlockedDecrement(&((m)->count));          \
        if (KeGetCurrentIrql () < DISPATCH_LEVEL)         \
            NdisMSleep(MUTEX_SLEEP_TIME);                 \
        else                                              \
        {                                                 \
	    result = FALSE;                               \
	    break;                                        \
        }                                                 \
    }                                                     \
}

--- NEW FILE: macinfo.c ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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 "macinfo.h"

int
HexStringToDecimalInt (const int p_Character)
{
  int l_Value = 0;

  if (p_Character >= 'A' && p_Character <= 'F')
    l_Value = (p_Character - 'A') + 10;
  else if (p_Character >= 'a' && p_Character <= 'f')
    l_Value = (p_Character - 'a') + 10;
  else if (p_Character >= '0' && p_Character <= '9')
    l_Value = p_Character - '0';

  return l_Value;
}

BOOLEAN
ParseMAC (MACADDR dest, const char *src)
{
  int c;
  int mac_index = 0;
  BOOLEAN high_digit = FALSE;
  int delim_action = 1;

  MYASSERT (src);
  MYASSERT (dest);

  CLEAR_MAC (dest);

  while (c = *src++)
    {
      if (IsMacDelimiter (c))
	{
	  mac_index += delim_action;
	  high_digit = FALSE;
	  delim_action = 1;
	}
      else if (IsHexDigit (c))
	{
	  const int digit = HexStringToDecimalInt (c);
	  if (mac_index < sizeof (MACADDR))
	    {
	      if (!high_digit)
		{
		  dest[mac_index] = (char)(digit);
		  high_digit = TRUE;
		  delim_action = 1;
		}
	      else
		{
		  dest[mac_index] = (char)(dest[mac_index] * 16 + digit);
		  ++mac_index;
		  high_digit = FALSE;
		  delim_action = 0;
		}
	    }
	  else
	    return FALSE;
	}
      else
	return FALSE;
    }

  return (mac_index + delim_action) >= sizeof (MACADDR);
}

/*
 * Generate a MAC using the GUID in the adapter name.
 *
 * The mac is constructed as 00:FF:xx:xx:xx:xx where
 * the Xs are taken from the first 32 bits of the GUID in the
 * adapter name.  This is similar to the Linux 2.4 tap MAC
 * generator, except linux uses 32 random bits for the Xs.
 *
 * In general, this solution is reasonable for most
 * applications except for very large bridged TAP networks,
 * where the probability of address collisions becomes more
 * than infintesimal.
 *
 * Using the well-known "birthday paradox", on a 1000 node
 * network the probability of collision would be
 * 0.000116292153.  On a 10,000 node network, the probability
 * of collision would be 0.01157288998621678766.
 */

VOID GenerateRandomMac (MACADDR mac, const unsigned char *adapter_name)
{
  unsigned const char *cp = adapter_name;
  unsigned char c;
  unsigned int i = 2;
  unsigned int byte = 0;
  int brace = 0;
  int state = 0;

  CLEAR_MAC (mac);

  mac[0] = 0x00;
  mac[1] = 0xFF;

  while (c = *cp++)
    {
      if (i >= sizeof (MACADDR))
	break;
      if (c == '{')
	brace = 1;
      if (IsHexDigit (c) && brace)
	{
	  const unsigned int digit = HexStringToDecimalInt (c);
	  if (state)
	    {
	      byte <<= 4;
	      byte |= digit;
	      mac[i++] = (unsigned char) byte;
	      state = 0;
	    }
	  else
	    {
	      byte = digit;
	      state = 1;
	    }
	}
    }
}

VOID GenerateRelatedMAC (MACADDR dest, const MACADDR src, const int delta)
{
  COPY_MAC (dest, src);
  dest[2] += (UCHAR) delta;
}

--- NEW FILE: macinfo.h ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

#ifndef MacInfoDefined
#define MacInfoDefined

//===================================================================================
//                                      Macros
//===================================================================================
#define IsMacDelimiter(a) (a == ':' || a == '-' || a == '.')
#define IsHexDigit(c) ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))

#define COPY_MAC(dest, src) NdisMoveMemory ((dest), (src), sizeof (MACADDR))
#define CLEAR_MAC(dest)     NdisZeroMemory ((dest), sizeof (MACADDR))
#define MAC_EQUAL(a,b)      (memcmp ((a), (b), sizeof (MACADDR)) == 0)

#endif

--- NEW FILE: mem.c ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

//------------------
// Memory Management
//------------------

PVOID
MemAlloc (ULONG p_Size, BOOLEAN zero)
{
  PVOID l_Return = NULL;

  if (p_Size)
    {
      __try
      {
	if (NdisAllocateMemoryWithTag (&l_Return, p_Size, 'APAT')
	    == NDIS_STATUS_SUCCESS)
	  {
	    if (zero)
	      NdisZeroMemory (l_Return, p_Size);
	  }
	else
	  l_Return = NULL;
      }
      __except (EXCEPTION_EXECUTE_HANDLER)
      {
	l_Return = NULL;
      }
    }

  return l_Return;
}

VOID
MemFree (PVOID p_Addr, ULONG p_Size)
{
  if (p_Addr && p_Size)
    {
      __try
      {
#if DBG
	NdisZeroMemory (p_Addr, p_Size);
#endif
	NdisFreeMemory (p_Addr, p_Size, 0);
      }
      __except (EXCEPTION_EXECUTE_HANDLER)
      {
      }
    }
}

/*
 * Circular queue management routines.
 */

#define QUEUE_BYTE_ALLOCATION(size) \
  (sizeof (Queue) + (size * sizeof (PVOID)))

#define QUEUE_ADD_INDEX(var, inc) \
{ \
  var += inc; \
  if (var >= q->capacity) \
    var -= q->capacity; \
  MYASSERT (var < q->capacity); \
}

#define QUEUE_SANITY_CHECK() \
  MYASSERT (q != NULL && q->base < q->capacity && q->size <= q->capacity)

#define QueueCount(q) (q->size)

#define UPDATE_MAX_SIZE() \
{ \
  if (q->size > q->max_size) \
    q->max_size = q->size; \
}

Queue *
QueueInit (ULONG capacity)
{
  Queue *q;

  MYASSERT (capacity > 0);
  q = (Queue *) MemAlloc (QUEUE_BYTE_ALLOCATION (capacity), TRUE);
  if (!q)
    return NULL;

  q->base = q->size = 0;
  q->capacity = capacity;
  q->max_size = 0;
  return q;
}

VOID
QueueFree (Queue *q)
{
  if (q)
    {
      QUEUE_SANITY_CHECK ();
      MemFree (q, QUEUE_BYTE_ALLOCATION (q->capacity));
    }
}

PVOID
QueuePush (Queue *q, PVOID item)
{
  ULONG dest;
  QUEUE_SANITY_CHECK ();
  if (q->size == q->capacity)
    return NULL;
  dest = q->base;
  QUEUE_ADD_INDEX (dest, q->size);
  q->data[dest] = item;
  ++q->size;
  UPDATE_MAX_SIZE();
  return item;
}

PVOID
QueuePop (Queue *q)
{
  ULONG oldbase;
  QUEUE_SANITY_CHECK ();
  if (!q->size)
    return NULL;
  oldbase = q->base;
  QUEUE_ADD_INDEX (q->base, 1);
  --q->size;
  UPDATE_MAX_SIZE();
  return q->data[oldbase];
}

PVOID
QueueExtract (Queue *q, PVOID item)
{
  ULONG src, dest, count, n;
  QUEUE_SANITY_CHECK ();
  n = 0;
  src = dest = q->base;
  count = q->size;
  while (count--)
    {
      if (item == q->data[src])
	{
	  ++n;
	  --q->size;
	}
      else
	{
	  q->data[dest] = q->data[src];
	  QUEUE_ADD_INDEX (dest, 1);	  
	}
      QUEUE_ADD_INDEX (src, 1);
    }
  if (n)
    return item;
  else
    return NULL;
}

#undef QUEUE_BYTE_ALLOCATION
#undef QUEUE_ADD_INDEX
#undef QUEUE_SANITY_CHECK
#undef UPDATE_MAX_SIZE

--- NEW FILE: proto.h ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

//============================================================
// MAC address, Ethernet header, and ARP
//============================================================

#pragma pack(1)

#define IP_HEADER_SIZE 20

typedef unsigned char MACADDR [6];
typedef unsigned long IPADDR;

//-----------------
// Ethernet address
//-----------------

typedef struct {
  MACADDR addr;
} ETH_ADDR;

typedef struct {
  ETH_ADDR list[NIC_MAX_MCAST_LIST];
} MC_LIST;

//----------------
// Ethernet header
//----------------

typedef struct
{
  MACADDR dest;               /* destination eth addr	*/
  MACADDR src;                /* source ether addr	*/

# define ETH_P_IP		0x0800    /* IPv4 protocol */
# define ETH_P_IP_host	0x0008
# define ETH_P_ARP		0x0806    /* ARP protocol */
# define ETH_P_ARP_host	0x0608
  USHORT proto;               /* packet type ID field	*/
} ETH_HEADER, *PETH_HEADER;

//----------------
// ARP packet
//----------------

typedef struct
   {
    MACADDR        m_MAC_Destination;        // Reverse these two
    MACADDR        m_MAC_Source;             // to answer ARP requests
    USHORT         m_Proto;                  // 0x0806

#   define MAC_ADDR_TYPE		0x0001
#   define MAC_ADDR_TYPE_host	0x0100
    USHORT         m_MAC_AddressType;        // 0x0001

    USHORT         m_PROTO_AddressType;      // 0x0800
    UCHAR          m_MAC_AddressSize;        // 0x06
    UCHAR          m_PROTO_AddressSize;      // 0x04

#   define ARP_REQUEST			0x0001
#   define ARP_REQUEST_host		0x0100
#   define ARP_REPLY			0x0002
#   define ARP_REPLY_host		0x0200
    USHORT         m_ARP_Operation;          // 0x0001 for ARP request, 0x0002 for ARP reply

    MACADDR        m_ARP_MAC_Source;
    IPADDR         m_ARP_IP_Source;
    MACADDR        m_ARP_MAC_Destination;
    IPADDR         m_ARP_IP_Destination;
   }
ARP_PACKET, *PARP_PACKET;

//----------
// IP Header
//----------

typedef struct {
# define IPH_GET_VER(v) (((v) >> 4) & 0x0F)
# define IPH_GET_LEN(v) (((v) & 0x0F) << 2)
  UCHAR    version_len;

  UCHAR    tos;
  USHORT   tot_len;
  USHORT   id;

# define IP_OFFMASK 0x1fff
  USHORT   frag_off;

  UCHAR    ttl;

# define IPPROTO_UDP  17  /* UDP protocol */
# define IPPROTO_TCP   6  /* TCP protocol */
# define IPPROTO_ICMP  1  /* ICMP protocol */
# define IPPROTO_IGMP  2  /* IGMP protocol */
  UCHAR    protocol;

  USHORT   check;
  ULONG    saddr;
  ULONG    daddr;
  /* The options start here. */
} IPHDR;

//-----------
// UDP header
//-----------

typedef struct {
  USHORT   source;
  USHORT   dest;
  USHORT   len;
  USHORT   check;
} UDPHDR;

//--------------------------
// TCP header, per RFC 793.
//--------------------------

typedef struct {
  USHORT      source;    /* source port */
  USHORT      dest;      /* destination port */
  ULONG       seq;       /* sequence number */
  ULONG       ack_seq;   /* acknowledgement number */

# define TCPH_GET_DOFF(d) (((d) & 0xF0) >> 2)
  UCHAR       doff_res;

# define TCPH_FIN_MASK (1<<0)
# define TCPH_SYN_MASK (1<<1)
# define TCPH_RST_MASK (1<<2)
# define TCPH_PSH_MASK (1<<3)
# define TCPH_ACK_MASK (1<<4)
# define TCPH_URG_MASK (1<<5)
# define TCPH_ECE_MASK (1<<6)
# define TCPH_CWR_MASK (1<<7)
  UCHAR       flags;

  USHORT      window;
  USHORT      check;
  USHORT      urg_ptr;
} TCPHDR;

#define	TCPOPT_EOL     0
#define	TCPOPT_NOP     1
#define	TCPOPT_MAXSEG  2
#define TCPOLEN_MAXSEG 4

#pragma pack()

--- NEW FILE: prototypes.h ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

#ifndef TAP_PROTOTYPES_DEFINED
#define TAP_PROTOTYPES_DEFINED

NTSTATUS DriverEntry
   (
    IN PDRIVER_OBJECT p_DriverObject,
    IN PUNICODE_STRING p_RegistryPath
   );

VOID TapDriverUnload
   (
    IN PDRIVER_OBJECT p_DriverObject
   );

NDIS_STATUS AdapterCreate
   (
    OUT PNDIS_STATUS p_ErrorStatus,
    OUT PUINT p_MediaIndex,
    IN PNDIS_MEDIUM p_Media,
    IN UINT p_MediaCount,
    IN NDIS_HANDLE p_AdapterHandle,
    IN NDIS_HANDLE p_ConfigurationHandle
   );

VOID AdapterHalt
   (
    IN NDIS_HANDLE p_AdapterContext
   );

VOID AdapterFreeResources
   (
    TapAdapterPointer p_Adapter
   );

NDIS_STATUS AdapterReset
   (
    OUT PBOOLEAN p_AddressingReset,
    IN NDIS_HANDLE p_AdapterContext
   );

NDIS_STATUS AdapterQuery
   (
    IN NDIS_HANDLE p_AdapterContext,
    IN NDIS_OID p_OID,
    IN PVOID p_Buffer,
    IN ULONG p_BufferLength,
    OUT PULONG p_BytesWritten,
    OUT PULONG p_BytesNeeded
   );

NDIS_STATUS AdapterModify
   (
    IN NDIS_HANDLE p_AdapterContext,
    IN NDIS_OID p_OID,
    IN PVOID p_Buffer,
    IN ULONG p_BufferLength,
    OUT PULONG p_BytesRead,
    OUT PULONG p_BytesNeeded
   );

NDIS_STATUS AdapterTransmit
   (
    IN NDIS_HANDLE p_AdapterContext,
    IN PNDIS_PACKET p_Packet,
    IN UINT p_Flags
   );

NDIS_STATUS AdapterReceive
   (
    OUT PNDIS_PACKET p_Packet,
    OUT PUINT p_Transferred,
    IN NDIS_HANDLE p_AdapterContext,
    IN NDIS_HANDLE p_ReceiveContext,
    IN UINT p_Offset,
    IN UINT p_ToTransfer
   );

NTSTATUS TapDeviceHook
   (
    IN PDEVICE_OBJECT p_DeviceObject,
    IN PIRP p_IRP
   );

NDIS_STATUS CreateTapDevice
   (
    TapExtensionPointer p_Extension,
    const char *p_Name
   );

VOID DestroyTapDevice
   (
    TapExtensionPointer p_Extension
   );

VOID TapDeviceFreeResources
   (
    TapExtensionPointer p_Extension
    );

NTSTATUS CompleteIRP
   (
    IN PIRP p_IRP,
    IN TapPacketPointer p_PacketBuffer,
    IN CCHAR PriorityBoost
   );

VOID CancelIRPCallback
   (
    IN PDEVICE_OBJECT p_DeviceObject,
    IN PIRP p_IRP
   );

VOID CancelIRP
   (
    TapExtensionPointer p_Extension,
    IN PIRP p_IRP,
    BOOLEAN callback
   );

VOID FlushQueues
   (
    TapExtensionPointer p_Extension
   );

VOID ResetTapAdapterState
   (
    TapAdapterPointer p_Adapter
   );

BOOLEAN ProcessARP
   (
    TapAdapterPointer p_Adapter,
    const PARP_PACKET src,
    const IPADDR adapter_ip,
    const IPADDR ip_network,
    const IPADDR ip_netmask,
    const MACADDR mac
   );

VOID SetMediaStatus
   (
    TapAdapterPointer p_Adapter,
    BOOLEAN state
   );

VOID InjectPacket
   (
    TapAdapterPointer p_Adapter,
    UCHAR *packet,
    const unsigned int len
   );

VOID CheckIfDhcpAndTunMode
   (
    TapAdapterPointer p_Adapter
   );

VOID HookDispatchFunctions();

#if ENABLE_NONADMIN

#if DDKVER_MAJOR < 5600
/*
 * Better solution for use on Vista DDK, but possibly not compatible with
 * earlier DDKs:
 *
 * Eliminate the definition of SECURITY_DESCRIPTOR (and even ZwSetSecurityObject),
 * and at the top of tapdrv.c change:
 *
 * #include <ndis.h>
 * #include <ntstrsafe.h>
 * #include <ntddk.h>
 *
 * To
 *
 * #include <ntifs.h>
 * #include <ndis.h>
 * #include <ntstrsafe.h>
 */
typedef struct _SECURITY_DESCRIPTOR {
  unsigned char opaque[64];
} SECURITY_DESCRIPTOR;

NTSYSAPI
NTSTATUS
NTAPI
ZwSetSecurityObject (
  IN HANDLE  Handle,
  IN SECURITY_INFORMATION  SecurityInformation,
  IN PSECURITY_DESCRIPTOR  SecurityDescriptor);

#endif

VOID AllowNonAdmin (TapExtensionPointer p_Extension);

#endif

struct WIN2K_NDIS_MINIPORT_BLOCK
{
  unsigned char  opaque[16];
  UNICODE_STRING MiniportName;       // how mini-port refers to us
};

#if PACKET_TRUNCATION_CHECK

VOID IPv4PacketSizeVerify
   (
    const UCHAR *data,
    ULONG length,
    BOOLEAN tun,
    const char *prefix,
    LONG *counter
   );

#endif

#endif

--- NEW FILE: resource.rc ---
#include <windows.h>
#include <ntverp.h>

/* get VERSION */
#include "../config-win32.h"
#include "common.h"

/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR
 * and VER_INTERNALNAME_STR must be defined before including COMMON.VER
 * The strings don't need a '\0', since common.ver has them.
 */

#define	VER_FILETYPE	VFT_DRV
/* possible values:		VFT_UNKNOWN
				VFT_APP
				VFT_DLL
				VFT_DRV
				VFT_FONT
				VFT_VXD
				VFT_STATIC_LIB
*/
#define	VER_FILESUBTYPE	VFT2_DRV_NETWORK
/* possible values		VFT2_UNKNOWN
				VFT2_DRV_PRINTER
				VFT2_DRV_KEYBOARD
				VFT2_DRV_LANGUAGE
				VFT2_DRV_DISPLAY
				VFT2_DRV_MOUSE
				VFT2_DRV_NETWORK
				VFT2_DRV_SYSTEM
				VFT2_DRV_INSTALLABLE
				VFT2_DRV_SOUND
				VFT2_DRV_COMM
*/

#define VER_COMPANYNAME_STR         "The OpenVPN Project"
#define VER_FILEDESCRIPTION_STR     "TAP-Win32 Virtual Network Driver"
#define VER_ORIGINALFILENAME_STR    TAP_COMPONENT_ID ".sys"
#define VER_LEGALCOPYRIGHT_YEARS    "2003-2006"
#define VER_LEGALCOPYRIGHT_STR      "OpenVPN Solutions LLC and Damion K. Wilson"


#define VER_PRODUCTNAME_STR         VER_FILEDESCRIPTION_STR
#define VER_PRODUCTVERSION	    TAP_DRIVER_MAJOR_VERSION,00,00,TAP_DRIVER_MINOR_VERSION

#define XSTR(s) STR(s)
#define STR(s) #s

#define VSTRING VERSION " " XSTR(TAP_DRIVER_MAJOR_VERSION) "/" XSTR(TAP_DRIVER_MINOR_VERSION)

#ifdef DBG
#define VER_PRODUCTVERSION_STR      VSTRING " (DEBUG)"
#else
#define VER_PRODUCTVERSION_STR      VSTRING
#endif

#define VER_INTERNALNAME_STR        VER_ORIGINALFILENAME_STR

#include "common.ver"

--- NEW FILE: tapdrvr.c ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
[...2829 lines suppressed...]
      else
	return;
    }

  if (len >= sizeof (IPHDR))
    {
      const int totlen = ntohs (ip->tot_len);

      DEBUGP (("[TAP] IPv4PacketSizeVerify %s len=%d totlen=%d\n", prefix, len, totlen));

      if (len != totlen)
	++(*counter);
    }
}

#endif

//======================================================================
//                                    End of Source
//======================================================================

--- NEW FILE: types.h ---
/*
 *  TAP-Win32/TAP-Win64 -- 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-2007 OpenVPN Solutions LLC,
 *  and is released under the GPL version 2 (see below), however due
 *  to the extra costs of supporting Windows Vista, OpenVPN Solutions
 *  LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
 *  license for versions 9.1 and higher prior to the official release of
 *  OpenVPN 2.1.
 *
 *  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
 */

#ifndef TAP_TYPES_DEFINED
#define TAP_TYPES_DEFINED

typedef struct _Queue
{
  ULONG base;
  ULONG size;
  ULONG capacity;
  ULONG max_size;
  PVOID data[];
} Queue;

typedef struct _TapAdapter;
typedef struct _TapPacket;

typedef union _TapAdapterQuery
{
  NDIS_HARDWARE_STATUS m_HardwareStatus;
  NDIS_MEDIUM m_Medium;
  NDIS_PHYSICAL_MEDIUM m_PhysicalMedium;
  UCHAR m_MacAddress [6];
  UCHAR m_Buffer [256];
  ULONG m_Long;
  USHORT m_Short;
  UCHAR m_Byte;
}
TapAdapterQuery, *TapAdapterQueryPointer;

typedef struct _TapExtension
{
  // TAP device object and packet queues
  Queue *m_PacketQueue, *m_IrpQueue;
  PDEVICE_OBJECT m_TapDevice;
  NDIS_HANDLE m_TapDeviceHandle;
  ULONG m_TapOpens;

  // Used to lock packet queues
  NDIS_SPIN_LOCK m_QueueLock;
  BOOLEAN m_AllocatedSpinlocks;

  // Used to bracket open/close
  // state changes.
  MUTEX m_OpenCloseMutex;

  // True if device has been permanently halted
  BOOLEAN m_Halt;

  // TAP device name
  unsigned char *m_TapName;
  UNICODE_STRING m_UnicodeLinkName;
  BOOLEAN m_CreatedUnicodeLinkName;

  // Used for device status ioctl only
  const char *m_LastErrorFilename;
  int m_LastErrorLineNumber;
  LONG m_NumTapOpens;

  // Flags
  BOOLEAN m_TapIsRunning;
  BOOLEAN m_CalledTapDeviceFreeResources;
}
TapExtension, *TapExtensionPointer;

typedef struct _TapPacket
   {
#   define TAP_PACKET_SIZE(data_size) (sizeof (TapPacket) + (data_size))
#   define TP_TUN 0x80000000
#   define TP_SIZE_MASK      (~TP_TUN)
    ULONG m_SizeFlags;
    UCHAR m_Data []; // m_Data must be the last struct member
   }
TapPacket, *TapPacketPointer;

typedef struct _TapAdapter
{
# define NAME(a) ((a)->m_NameAnsi.Buffer)
  ANSI_STRING m_NameAnsi;
  MACADDR m_MAC;
  BOOLEAN m_InterfaceIsRunning;
  NDIS_HANDLE m_MiniportAdapterHandle;
  LONG m_Rx, m_Tx, m_RxErr, m_TxErr;
#if PACKET_TRUNCATION_CHECK
  LONG m_RxTrunc, m_TxTrunc;
#endif
  NDIS_MEDIUM m_Medium;
  ULONG m_Lookahead;
  ULONG m_MTU;

  // TRUE if adapter should always be
  // "connected" even when device node
  // is not open by a userspace process.
  BOOLEAN m_MediaStateAlwaysConnected;

  // TRUE if device is "connected"
  BOOLEAN m_MediaState;

  // Adapter power state
  char m_DeviceState;

  // Info for point-to-point mode
  BOOLEAN m_tun;
  IPADDR m_localIP;
  IPADDR m_remoteNetwork;
  IPADDR m_remoteNetmask;
  ETH_HEADER m_TapToUser;
  ETH_HEADER m_UserToTap;
  MACADDR m_MAC_Broadcast;

  // Used for DHCP server masquerade
  BOOLEAN m_dhcp_enabled;
  IPADDR m_dhcp_addr;
  ULONG m_dhcp_netmask;
  IPADDR m_dhcp_server_ip;
  BOOLEAN m_dhcp_server_arp;
  MACADDR m_dhcp_server_mac;
  ULONG m_dhcp_lease_time;
  UCHAR m_dhcp_user_supplied_options_buffer[DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE];
  ULONG m_dhcp_user_supplied_options_buffer_len;
  BOOLEAN m_dhcp_received_discover;
  ULONG m_dhcp_bad_requests;

  // Help to tear down the adapter by keeping
  // some state information on allocated
  // resources.
  BOOLEAN m_CalledAdapterFreeResources;
  BOOLEAN m_RegisteredAdapterShutdownHandler;

  // Multicast list info
  NDIS_SPIN_LOCK m_MCLock;
  BOOLEAN m_MCLockAllocated;
  ULONG m_MCListSize;
  MC_LIST m_MCList;

  // Information on the TAP device
  TapExtension m_Extension;
} TapAdapter, *TapAdapterPointer;

#endif



More information about the Tinyos-contrib-commits mailing list