Remove a lot of code that we don't need from tap-windows, further winnowing down this fork of OpenVPN's tap-windows to a more minimal version that does only basic Ethernet tap functionality.

This commit is contained in:
Adam Ierymenko 2014-01-20 11:18:55 -08:00
parent 45c5b66e9e
commit a365a0e3ba
14 changed files with 2542 additions and 4462 deletions

View file

@ -261,20 +261,6 @@
<FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" /> <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="dhcp.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Vista Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Vista Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win7 Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Vista Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Vista Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win7 Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="error.c"> <ClCompile Include="error.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Vista Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Vista Debug|Win32'">true</ExcludedFromBuild>
@ -336,7 +322,6 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="config.h" /> <ClInclude Include="config.h" />
<ClInclude Include="constants.h" /> <ClInclude Include="constants.h" />
<ClInclude Include="dhcp.h" />
<ClInclude Include="endian.h" /> <ClInclude Include="endian.h" />
<ClInclude Include="error.h" /> <ClInclude Include="error.h" />
<ClInclude Include="lock.h" /> <ClInclude Include="lock.h" />

View file

@ -19,9 +19,6 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="dhcp.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="error.c"> <ClCompile Include="error.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -42,9 +39,6 @@
<ClInclude Include="constants.h"> <ClInclude Include="constants.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="dhcp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="endian.h"> <ClInclude Include="endian.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>

View file

@ -1,603 +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-2010 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
*/
#if 0
//=========================
// 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
InjectPacketDeferred (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_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 (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 && 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 */
#endif

View file

@ -1,168 +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-2010 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
*/
#if 0
#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
#endif

View file

@ -1,26 +1,26 @@
/* /*
* TAP-Windows -- A kernel driver to provide virtual tap * TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows. * device functionality on Windows.
* *
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
* *
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* and is released under the GPL version 2 (see below). * and is released under the GPL version 2 (see below).
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 * it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING included with this * along with this program (see the file COPYING included with this
* distribution); if not, write to the Free Software Foundation, Inc., * distribution); if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
//----------------- //-----------------
// DEBUGGING OUTPUT // DEBUGGING OUTPUT
@ -34,354 +34,354 @@ int g_LastErrorLineNumber;
DebugOutput g_Debug; DebugOutput g_Debug;
BOOLEAN BOOLEAN
NewlineExists (const char *str, int len) NewlineExists (const char *str, int len)
{ {
while (len-- > 0) 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; const char c = *str++;
if (c == '\n')
return TRUE;
else if (c == '\0')
break;
}
return FALSE;
}
if (remaining > 0) VOID
{ MyDebugInit (unsigned int bufsiz)
va_list args; {
NTSTATUS status; NdisZeroMemory (&g_Debug, sizeof (g_Debug));
char *end; 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;
#ifdef DBG_PRINT #ifdef DBG_PRINT
va_start (args, format); va_start (args, format);
vDbgPrintEx (DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, format, args); vDbgPrintEx (DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, format, args);
va_end (args); va_end (args);
#endif #endif
va_start (args, format); va_start (args, format);
status = RtlStringCchVPrintfExA (g_Debug.text + g_Debug.out, status = RtlStringCchVPrintfExA (g_Debug.text + g_Debug.out,
remaining, remaining,
&end, &end,
NULL, NULL,
STRSAFE_NO_TRUNCATION | STRSAFE_IGNORE_NULLS, STRSAFE_NO_TRUNCATION | STRSAFE_IGNORE_NULLS,
format, format,
args); args);
va_end (args); va_end (args);
va_start (args, format); va_start (args, format);
vDbgPrintEx(DPFLTR_IHVDRIVER_ID , 1, format, args); vDbgPrintEx(DPFLTR_IHVDRIVER_ID , 1, format, args);
va_end (args); va_end (args);
if (status == STATUS_SUCCESS) if (status == STATUS_SUCCESS)
g_Debug.out = (unsigned int) (end - g_Debug.text); g_Debug.out = (unsigned int) (end - g_Debug.text);
else else
g_Debug.error = TRUE; g_Debug.error = TRUE;
} }
else else
g_Debug.error = TRUE; g_Debug.error = TRUE;
RELEASE_MUTEX (&g_Debug.lock); RELEASE_MUTEX (&g_Debug.lock);
}
else
g_Debug.error = TRUE;
} }
else
g_Debug.error = TRUE;
}
} }
BOOLEAN BOOLEAN
GetDebugLine (char *buf, const int len) GetDebugLine (char *buf, const int len)
{ {
static const char *truncated = "[OUTPUT TRUNCATED]\n"; static const char *truncated = "[OUTPUT TRUNCATED]\n";
BOOLEAN ret = FALSE; BOOLEAN ret = FALSE;
NdisZeroMemory (buf, len); NdisZeroMemory (buf, len);
if (g_Debug.text && g_Debug.capacity > 0) if (g_Debug.text && g_Debug.capacity > 0)
{
BOOLEAN owned;
ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);
if (owned)
{ {
int i = 0; BOOLEAN owned;
ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);
if (g_Debug.error || NewlineExists (g_Debug.text + g_Debug.in, (int)g_Debug.out - (int)g_Debug.in)) if (owned)
{
while (i < (len - 1) && g_Debug.in < g_Debug.out)
{ {
const char c = g_Debug.text[g_Debug.in++]; int i = 0;
if (c == '\n')
break;
buf[i++] = c;
}
if (i < len)
buf[i] = '\0';
}
if (!i) if (g_Debug.error || NewlineExists (g_Debug.text + g_Debug.in, (int)g_Debug.out - (int)g_Debug.in))
{
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); while (i < (len - 1) && g_Debug.in < g_Debug.out)
g_Debug.out = tlen; {
const char c = g_Debug.text[g_Debug.in++];
if (c == '\n')
break;
buf[i++] = c;
}
if (i < len)
buf[i] = '\0';
} }
g_Debug.error = FALSE;
}
}
}
else
ret = TRUE;
RELEASE_MUTEX (&g_Debug.lock); if (!i)
} {
} if (g_Debug.in == g_Debug.out)
return ret; {
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 VOID
MyAssert (const unsigned char *file, int line) MyAssert (const unsigned char *file, int line)
{ {
DEBUGP (("MYASSERT failed %s/%d\n", file, line)); DEBUGP (("MYASSERT failed %s/%d\n", file, line));
KeBugCheckEx (0x0F00BABA, KeBugCheckEx (0x0F00BABA,
(ULONG_PTR) line, (ULONG_PTR) line,
(ULONG_PTR) 0, (ULONG_PTR) 0,
(ULONG_PTR) 0, (ULONG_PTR) 0,
(ULONG_PTR) 0); (ULONG_PTR) 0);
} }
VOID VOID
PrMac (const MACADDR mac) PrMac (const MACADDR mac)
{ {
DEBUGP (("%x:%x:%x:%x:%x:%x", DEBUGP (("%x:%x:%x:%x:%x:%x",
mac[0], mac[1], mac[2], mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5])); mac[3], mac[4], mac[5]));
} }
VOID VOID
PrIP (IPADDR ip_addr) PrIP (IPADDR ip_addr)
{ {
const unsigned char *ip = (const unsigned char *) &ip_addr; const unsigned char *ip = (const unsigned char *) &ip_addr;
DEBUGP (("%d.%d.%d.%d", DEBUGP (("%d.%d.%d.%d",
ip[0], ip[1], ip[2], ip[3])); ip[0], ip[1], ip[2], ip[3]));
} }
const char * const char *
PrIPProto (int proto) PrIPProto (int proto)
{ {
switch (proto) switch (proto)
{ {
case IPPROTO_UDP: case IPPROTO_UDP:
return "UDP"; return "UDP";
case IPPROTO_TCP: case IPPROTO_TCP:
return "TCP"; return "TCP";
case IPPROTO_ICMP: case IPPROTO_ICMP:
return "ICMP"; return "ICMP";
case IPPROTO_IGMP: case IPPROTO_IGMP:
return "IGMP"; return "IGMP";
default: default:
return "???"; return "???";
} }
} }
VOID VOID
DumpARP (const char *prefix, const ARP_PACKET *arp) DumpARP (const char *prefix, const ARP_PACKET *arp)
{ {
DEBUGP (("%s ARP src=", prefix)); DEBUGP (("%s ARP src=", prefix));
PrMac (arp->m_MAC_Source); PrMac (arp->m_MAC_Source);
DEBUGP ((" dest=")); DEBUGP ((" dest="));
PrMac (arp->m_MAC_Destination); PrMac (arp->m_MAC_Destination);
DEBUGP ((" OP=0x%04x", DEBUGP ((" OP=0x%04x",
(int)ntohs(arp->m_ARP_Operation))); (int)ntohs(arp->m_ARP_Operation)));
DEBUGP ((" M=0x%04x(%d)", DEBUGP ((" M=0x%04x(%d)",
(int)ntohs(arp->m_MAC_AddressType), (int)ntohs(arp->m_MAC_AddressType),
(int)arp->m_MAC_AddressSize)); (int)arp->m_MAC_AddressSize));
DEBUGP ((" P=0x%04x(%d)", DEBUGP ((" P=0x%04x(%d)",
(int)ntohs(arp->m_PROTO_AddressType), (int)ntohs(arp->m_PROTO_AddressType),
(int)arp->m_PROTO_AddressSize)); (int)arp->m_PROTO_AddressSize));
DEBUGP ((" MacSrc=")); DEBUGP ((" MacSrc="));
PrMac (arp->m_ARP_MAC_Source); PrMac (arp->m_ARP_MAC_Source);
DEBUGP ((" MacDest=")); DEBUGP ((" MacDest="));
PrMac (arp->m_ARP_MAC_Destination); PrMac (arp->m_ARP_MAC_Destination);
DEBUGP ((" IPSrc=")); DEBUGP ((" IPSrc="));
PrIP (arp->m_ARP_IP_Source); PrIP (arp->m_ARP_IP_Source);
DEBUGP ((" IPDest=")); DEBUGP ((" IPDest="));
PrIP (arp->m_ARP_IP_Destination); PrIP (arp->m_ARP_IP_Destination);
DEBUGP (("\n")); DEBUGP (("\n"));
} }
struct ethpayload { struct ethpayload {
ETH_HEADER eth; ETH_HEADER eth;
UCHAR payload[DEFAULT_PACKET_LOOKAHEAD]; UCHAR payload[DEFAULT_PACKET_LOOKAHEAD];
}; };
VOID VOID
DumpPacket2 (const char *prefix, DumpPacket2 (const char *prefix,
const ETH_HEADER *eth, const ETH_HEADER *eth,
const unsigned char *data, const unsigned char *data,
unsigned int len) unsigned int len)
{ {
struct ethpayload *ep = (struct ethpayload *) MemAlloc (sizeof (struct ethpayload), TRUE); struct ethpayload *ep = (struct ethpayload *) MemAlloc (sizeof (struct ethpayload), TRUE);
if (ep) if (ep)
{ {
if (len > DEFAULT_PACKET_LOOKAHEAD) if (len > DEFAULT_PACKET_LOOKAHEAD)
len = DEFAULT_PACKET_LOOKAHEAD; len = DEFAULT_PACKET_LOOKAHEAD;
ep->eth = *eth; ep->eth = *eth;
NdisMoveMemory (ep->payload, data, len); NdisMoveMemory (ep->payload, data, len);
DumpPacket (prefix, (unsigned char *) ep, sizeof (ETH_HEADER) + len); DumpPacket (prefix, (unsigned char *) ep, sizeof (ETH_HEADER) + len);
MemFree (ep, sizeof (struct ethpayload)); MemFree (ep, sizeof (struct ethpayload));
} }
} }
VOID VOID
DumpPacket (const char *prefix, DumpPacket (const char *prefix,
const unsigned char *data, const unsigned char *data,
unsigned int len) unsigned int len)
{ {
const ETH_HEADER *eth = (const ETH_HEADER *) data; const ETH_HEADER *eth = (const ETH_HEADER *) data;
const IPHDR *ip = (const IPHDR *) (data + sizeof (ETH_HEADER)); const IPHDR *ip = (const IPHDR *) (data + sizeof (ETH_HEADER));
if (len < 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")); DEBUGP (("%s TRUNCATED PACKET LEN=%d\n", prefix, len));
return; 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? // ARP Packet?
else if ((ntohs (ip->frag_off) & IP_OFFMASK) == 0 if (len >= sizeof (ARP_PACKET) && eth->proto == htons (ETH_P_ARP))
&& ip->protocol == IPPROTO_UDP
&& blen - hlen >= (sizeof (UDPHDR)))
{ {
const UDPHDR *udp = (UDPHDR *) (data + sizeof (ETH_HEADER) + hlen); 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);
#if 0 #if 0
// DHCP packet? // DHCP packet?
if ((udp->dest == htons (BOOTPC_PORT) || udp->dest == htons (BOOTPS_PORT)) if ((udp->dest == htons (BOOTPC_PORT) || udp->dest == htons (BOOTPS_PORT))
&& blen - hlen >= (sizeof (UDPHDR) + sizeof (DHCP))) && blen - hlen >= (sizeof (UDPHDR) + sizeof (DHCP)))
{ {
const DHCP *dhcp = (DHCP *) (data const DHCP *dhcp = (DHCP *) (data
+ hlen + hlen
+ sizeof (ETH_HEADER) + sizeof (ETH_HEADER)
+ sizeof (UDPHDR)); + sizeof (UDPHDR));
int optlen = len
- sizeof (ETH_HEADER)
- hlen
- sizeof (UDPHDR)
- sizeof (DHCP);
if (optlen < 0) int optlen = len
optlen = 0; - sizeof (ETH_HEADER)
- hlen
- sizeof (UDPHDR)
- sizeof (DHCP);
DumpDHCP (eth, ip, udp, dhcp, optlen); if (optlen < 0)
did = TRUE; optlen = 0;
}
DumpDHCP (eth, ip, udp, dhcp, optlen);
did = TRUE;
}
#endif #endif
if (!did) if (!did)
{ {
DEBUGP ((" ")); DEBUGP ((" "));
PrIP (ip->saddr); PrIP (ip->saddr);
DEBUGP ((":%d", ntohs (udp->source))); DEBUGP ((":%d", ntohs (udp->source)));
DEBUGP ((" -> ")); DEBUGP ((" -> "));
PrIP (ip->daddr); PrIP (ip->daddr);
DEBUGP ((":%d", ntohs (udp->dest))); DEBUGP ((":%d", ntohs (udp->dest)));
did = TRUE; did = TRUE;
} }
}
if (!did)
{
DEBUGP ((" ipproto=%d ", ip->protocol));
PrIP (ip->saddr);
DEBUGP ((" -> "));
PrIP (ip->daddr);
}
DEBUGP (("\n"));
return;
} }
if (!did)
{ {
DEBUGP ((" ipproto=%d ", ip->protocol)); DEBUGP (("%s ??? src=", prefix));
PrIP (ip->saddr); PrMac (eth->src);
DEBUGP ((" -> ")); DEBUGP ((" dest="));
PrIP (ip->daddr); PrMac (eth->dest);
DEBUGP ((" proto=0x%04x len=%d\n",
(int) ntohs(eth->proto),
len));
} }
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 #endif

View file

@ -1,241 +1,241 @@
/* /*
* TAP-Windows -- A kernel driver to provide virtual tap * TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows. * device functionality on Windows.
* *
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
* *
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* and is released under the GPL version 2 (see below). * and is released under the GPL version 2 (see below).
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 * it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING included with this * along with this program (see the file COPYING included with this
* distribution); if not, write to the Free Software Foundation, Inc., * distribution); if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#define INSTANCE_KEY(a) ((PVOID)((a)->m_Extension.m_TapDevice)) #define INSTANCE_KEY(a) ((PVOID)((a)->m_Extension.m_TapDevice))
#define N_INSTANCE_BUCKETS 256 #define N_INSTANCE_BUCKETS 256
typedef struct _INSTANCE { typedef struct _INSTANCE {
struct _INSTANCE *next; struct _INSTANCE *next;
TapAdapterPointer m_Adapter; TapAdapterPointer m_Adapter;
} INSTANCE; } INSTANCE;
typedef struct { typedef struct {
INSTANCE *list; INSTANCE *list;
MUTEX lock; MUTEX lock;
} INSTANCE_BUCKET; } INSTANCE_BUCKET;
typedef struct { typedef struct {
INSTANCE_BUCKET buckets[N_INSTANCE_BUCKETS]; INSTANCE_BUCKET buckets[N_INSTANCE_BUCKETS];
} INSTANCE_HASH; } INSTANCE_HASH;
INSTANCE_HASH *g_InstanceHash = NULL; INSTANCE_HASH *g_InstanceHash = NULL;
// must return a hash >= 0 and < N_INSTANCE_BUCKETS // must return a hash >= 0 and < N_INSTANCE_BUCKETS
int int
InstanceHashValue (PVOID addr) InstanceHashValue (PVOID addr)
{ {
UCHAR *p = (UCHAR *) &addr; UCHAR *p = (UCHAR *) &addr;
if (sizeof (addr) == 4) if (sizeof (addr) == 4)
return p[0] ^ p[1] ^ p[2] ^ p[3]; return p[0] ^ p[1] ^ p[2] ^ p[3];
else if (sizeof (addr) == 8) else if (sizeof (addr) == 8)
return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4] ^ p[5] ^ p[6] ^ p[7]; return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4] ^ p[5] ^ p[6] ^ p[7];
else else
{ {
MYASSERT (0); MYASSERT (0);
} }
} }
BOOLEAN BOOLEAN
InitInstanceList (VOID) InitInstanceList (VOID)
{ {
MYASSERT (g_InstanceHash == NULL); MYASSERT (g_InstanceHash == NULL);
g_InstanceHash = MemAlloc (sizeof (INSTANCE_HASH), TRUE); g_InstanceHash = MemAlloc (sizeof (INSTANCE_HASH), TRUE);
if (g_InstanceHash) if (g_InstanceHash)
{ {
int i; int i;
for (i = 0; i < N_INSTANCE_BUCKETS; ++i) for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
INIT_MUTEX (&g_InstanceHash->buckets[i].lock); INIT_MUTEX (&g_InstanceHash->buckets[i].lock);
return TRUE; return TRUE;
} }
else else
return FALSE; return FALSE;
} }
int int
NInstances (VOID) NInstances (VOID)
{ {
int i, n = 0; int i, n = 0;
if (g_InstanceHash) if (g_InstanceHash)
{
for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
{ {
BOOLEAN got_lock; for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i]; {
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock); BOOLEAN got_lock;
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
if (got_lock) if (got_lock)
{ {
INSTANCE *current; INSTANCE *current;
for (current = ib->list; current != NULL; current = current->next) for (current = ib->list; current != NULL; current = current->next)
++n; ++n;
RELEASE_MUTEX (&ib->lock); RELEASE_MUTEX (&ib->lock);
} }
else else
return -1; return -1;
}
} }
}
return n; return n;
} }
int int
InstanceMaxBucketSize (VOID) InstanceMaxBucketSize (VOID)
{ {
int i, n = 0; int i, n = 0;
if (g_InstanceHash) if (g_InstanceHash)
{
for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
{ {
BOOLEAN got_lock; for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
int bucket_size = 0; {
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i]; BOOLEAN got_lock;
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock); int bucket_size = 0;
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
if (got_lock) if (got_lock)
{ {
INSTANCE *current; INSTANCE *current;
for (current = ib->list; current != NULL; current = current->next) for (current = ib->list; current != NULL; current = current->next)
++bucket_size; ++bucket_size;
if (bucket_size > n) if (bucket_size > n)
n = bucket_size; n = bucket_size;
RELEASE_MUTEX (&ib->lock); RELEASE_MUTEX (&ib->lock);
} }
else else
return -1; return -1;
}
} }
}
return n; return n;
} }
VOID VOID
FreeInstanceList (VOID) FreeInstanceList (VOID)
{ {
if (g_InstanceHash) if (g_InstanceHash)
{ {
MYASSERT (NInstances() == 0); MYASSERT (NInstances() == 0);
MemFree (g_InstanceHash, sizeof (INSTANCE_HASH)); MemFree (g_InstanceHash, sizeof (INSTANCE_HASH));
g_InstanceHash = NULL; g_InstanceHash = NULL;
} }
} }
BOOLEAN BOOLEAN
AddAdapterToInstanceList (TapAdapterPointer p_Adapter) AddAdapterToInstanceList (TapAdapterPointer p_Adapter)
{ {
BOOLEAN got_lock; BOOLEAN got_lock;
BOOLEAN ret = FALSE; BOOLEAN ret = FALSE;
const int hash = InstanceHashValue(INSTANCE_KEY(p_Adapter)); const int hash = InstanceHashValue(INSTANCE_KEY(p_Adapter));
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[hash]; INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[hash];
DEBUGP (("[TAP] AddAdapterToInstanceList hash=%d\n", hash)); DEBUGP (("[TAP] AddAdapterToInstanceList hash=%d\n", hash));
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock); ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
if (got_lock) if (got_lock)
{
INSTANCE *i = MemAlloc (sizeof (INSTANCE), FALSE);
if (i)
{ {
MYASSERT (p_Adapter); INSTANCE *i = MemAlloc (sizeof (INSTANCE), FALSE);
i->m_Adapter = p_Adapter; if (i)
i->next = ib->list; {
ib->list = i; MYASSERT (p_Adapter);
ret = TRUE; i->m_Adapter = p_Adapter;
i->next = ib->list;
ib->list = i;
ret = TRUE;
}
RELEASE_MUTEX (&ib->lock);
} }
RELEASE_MUTEX (&ib->lock);
}
return ret; return ret;
} }
BOOLEAN BOOLEAN
RemoveAdapterFromInstanceList (TapAdapterPointer p_Adapter) RemoveAdapterFromInstanceList (TapAdapterPointer p_Adapter)
{ {
BOOLEAN got_lock; BOOLEAN got_lock;
BOOLEAN ret = FALSE; BOOLEAN ret = FALSE;
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue(INSTANCE_KEY(p_Adapter))]; INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue(INSTANCE_KEY(p_Adapter))];
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock); ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
if (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 INSTANCE *current, *prev=NULL;
{ for (current = ib->list; current != NULL; current = current->next)
if (prev) {
prev->next = current->next; if (current->m_Adapter == p_Adapter) // found match
else {
ib->list = current->next; if (prev)
MemFree (current->m_Adapter, sizeof (TapAdapter)); prev->next = current->next;
MemFree (current, sizeof (INSTANCE)); else
ret = TRUE; ib->list = current->next;
break; MemFree (current->m_Adapter, sizeof (TapAdapter));
} MemFree (current, sizeof (INSTANCE));
prev = current; ret = TRUE;
break;
}
prev = current;
}
RELEASE_MUTEX (&ib->lock);
} }
RELEASE_MUTEX (&ib->lock);
}
return ret; return ret;
} }
TapAdapterPointer TapAdapterPointer
LookupAdapterInInstanceList (PDEVICE_OBJECT p_DeviceObject) LookupAdapterInInstanceList (PDEVICE_OBJECT p_DeviceObject)
{ {
BOOLEAN got_lock; BOOLEAN got_lock;
TapAdapterPointer ret = NULL; TapAdapterPointer ret = NULL;
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue((PVOID)p_DeviceObject)]; INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue((PVOID)p_DeviceObject)];
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock); ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
if (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 INSTANCE *current, *prev=NULL;
{ for (current = ib->list; current != NULL; current = current->next)
// move it to head of list
if (prev)
{ {
prev->next = current->next; if (p_DeviceObject == INSTANCE_KEY (current->m_Adapter)) // found match
current->next = ib->list; {
ib->list = current; // 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;
} }
ret = ib->list->m_Adapter; RELEASE_MUTEX (&ib->lock);
break;
}
prev = current;
} }
RELEASE_MUTEX (&ib->lock);
}
return ret; return ret;
} }

View file

@ -1,154 +1,154 @@
/* /*
* TAP-Windows -- A kernel driver to provide virtual tap * TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows. * device functionality on Windows.
* *
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
* *
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* and is released under the GPL version 2 (see below). * and is released under the GPL version 2 (see below).
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 * it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING included with this * along with this program (see the file COPYING included with this
* distribution); if not, write to the Free Software Foundation, Inc., * distribution); if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "macinfo.h" #include "macinfo.h"
int int
HexStringToDecimalInt (const int p_Character) HexStringToDecimalInt (const int p_Character)
{ {
int l_Value = 0; int l_Value = 0;
if (p_Character >= 'A' && p_Character <= 'F') if (p_Character >= 'A' && p_Character <= 'F')
l_Value = (p_Character - 'A') + 10; l_Value = (p_Character - 'A') + 10;
else if (p_Character >= 'a' && p_Character <= 'f') else if (p_Character >= 'a' && p_Character <= 'f')
l_Value = (p_Character - 'a') + 10; l_Value = (p_Character - 'a') + 10;
else if (p_Character >= '0' && p_Character <= '9') else if (p_Character >= '0' && p_Character <= '9')
l_Value = p_Character - '0'; l_Value = p_Character - '0';
return l_Value; return l_Value;
} }
BOOLEAN BOOLEAN
ParseMAC (MACADDR dest, const char *src) ParseMAC (MACADDR dest, const char *src)
{ {
int c; int c;
int mac_index = 0; int mac_index = 0;
BOOLEAN high_digit = FALSE; BOOLEAN high_digit = FALSE;
int delim_action = 1; int delim_action = 1;
MYASSERT (src); MYASSERT (src);
MYASSERT (dest); MYASSERT (dest);
CLEAR_MAC (dest); CLEAR_MAC (dest);
while (c = *src++) while (c = *src++)
{
if (IsMacDelimiter (c))
{ {
mac_index += delim_action; if (IsMacDelimiter (c))
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); mac_index += delim_action;
high_digit = TRUE; high_digit = FALSE;
delim_action = 1; delim_action = 1;
} }
else else if (IsHexDigit (c))
{ {
dest[mac_index] = (char)(dest[mac_index] * 16 + digit); const int digit = HexStringToDecimalInt (c);
++mac_index; if (mac_index < sizeof (MACADDR))
high_digit = FALSE; {
delim_action = 0; 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
else return FALSE;
return FALSE;
} }
else
return FALSE;
}
return (mac_index + delim_action) >= sizeof (MACADDR); return (mac_index + delim_action) >= sizeof (MACADDR);
} }
/* /*
* Generate a MAC using the GUID in the adapter name. * Generate a MAC using the GUID in the adapter name.
* *
* The mac is constructed as 00:FF:xx:xx:xx:xx where * 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 * 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 * adapter name. This is similar to the Linux 2.4 tap MAC
* generator, except linux uses 32 random bits for the Xs. * generator, except linux uses 32 random bits for the Xs.
* *
* In general, this solution is reasonable for most * In general, this solution is reasonable for most
* applications except for very large bridged TAP networks, * applications except for very large bridged TAP networks,
* where the probability of address collisions becomes more * where the probability of address collisions becomes more
* than infintesimal. * than infintesimal.
* *
* Using the well-known "birthday paradox", on a 1000 node * Using the well-known "birthday paradox", on a 1000 node
* network the probability of collision would be * network the probability of collision would be
* 0.000116292153. On a 10,000 node network, the probability * 0.000116292153. On a 10,000 node network, the probability
* of collision would be 0.01157288998621678766. * of collision would be 0.01157288998621678766.
*/ */
VOID GenerateRandomMac (MACADDR mac, const unsigned char *adapter_name) VOID GenerateRandomMac (MACADDR mac, const unsigned char *adapter_name)
{ {
unsigned const char *cp = adapter_name; unsigned const char *cp = adapter_name;
unsigned char c; unsigned char c;
unsigned int i = 2; unsigned int i = 2;
unsigned int byte = 0; unsigned int byte = 0;
int brace = 0; int brace = 0;
int state = 0; int state = 0;
CLEAR_MAC (mac); CLEAR_MAC (mac);
mac[0] = 0x00; mac[0] = 0x00;
mac[1] = 0xFF; mac[1] = 0xFF;
while (c = *cp++) while (c = *cp++)
{
if (i >= sizeof (MACADDR))
break;
if (c == '{')
brace = 1;
if (IsHexDigit (c) && brace)
{ {
const unsigned int digit = HexStringToDecimalInt (c); if (i >= sizeof (MACADDR))
if (state) break;
{ if (c == '{')
byte <<= 4; brace = 1;
byte |= digit; if (IsHexDigit (c) && brace)
mac[i++] = (unsigned char) byte; {
state = 0; const unsigned int digit = HexStringToDecimalInt (c);
} if (state)
else {
{ byte <<= 4;
byte = digit; byte |= digit;
state = 1; mac[i++] = (unsigned char) byte;
} state = 0;
}
else
{
byte = digit;
state = 1;
}
}
} }
}
} }
VOID GenerateRelatedMAC (MACADDR dest, const MACADDR src, const int delta) VOID GenerateRelatedMAC (MACADDR dest, const MACADDR src, const int delta)
{ {
COPY_MAC (dest, src); COPY_MAC (dest, src);
dest[2] += (UCHAR) delta; dest[2] += (UCHAR) delta;
} }

View file

@ -1,183 +1,183 @@
/* /*
* TAP-Windows -- A kernel driver to provide virtual tap * TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows. * device functionality on Windows.
* *
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
* *
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* and is released under the GPL version 2 (see below). * and is released under the GPL version 2 (see below).
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 * it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING included with this * along with this program (see the file COPYING included with this
* distribution); if not, write to the Free Software Foundation, Inc., * distribution); if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
//------------------ //------------------
// Memory Management // Memory Management
//------------------ //------------------
PVOID PVOID
MemAlloc (ULONG p_Size, BOOLEAN zero) MemAlloc (ULONG p_Size, BOOLEAN zero)
{ {
PVOID l_Return = NULL; PVOID l_Return = NULL;
if (p_Size) if (p_Size)
{ {
__try __try
{ {
if (NdisAllocateMemoryWithTag (&l_Return, p_Size, 'APAT') if (NdisAllocateMemoryWithTag (&l_Return, p_Size, 'APAT')
== NDIS_STATUS_SUCCESS) == NDIS_STATUS_SUCCESS)
{ {
if (zero) if (zero)
NdisZeroMemory (l_Return, p_Size); NdisZeroMemory (l_Return, p_Size);
} }
else else
l_Return = NULL; l_Return = NULL;
} }
__except (EXCEPTION_EXECUTE_HANDLER) __except (EXCEPTION_EXECUTE_HANDLER)
{ {
l_Return = NULL; l_Return = NULL;
} }
} }
return l_Return; return l_Return;
} }
VOID VOID
MemFree (PVOID p_Addr, ULONG p_Size) MemFree (PVOID p_Addr, ULONG p_Size)
{ {
if (p_Addr && p_Size) if (p_Addr && p_Size)
{ {
__try __try
{ {
#if DBG #if DBG
NdisZeroMemory (p_Addr, p_Size); NdisZeroMemory (p_Addr, p_Size);
#endif #endif
NdisFreeMemory (p_Addr, p_Size, 0); NdisFreeMemory (p_Addr, p_Size, 0);
} }
__except (EXCEPTION_EXECUTE_HANDLER) __except (EXCEPTION_EXECUTE_HANDLER)
{ {
} }
} }
} }
/* /*
* Circular queue management routines. * Circular queue management routines.
*/ */
#define QUEUE_BYTE_ALLOCATION(size) \ #define QUEUE_BYTE_ALLOCATION(size) \
(sizeof (Queue) + (size * sizeof (PVOID))) (sizeof (Queue) + (size * sizeof (PVOID)))
#define QUEUE_ADD_INDEX(var, inc) \ #define QUEUE_ADD_INDEX(var, inc) \
{ \ { \
var += inc; \ var += inc; \
if (var >= q->capacity) \ if (var >= q->capacity) \
var -= q->capacity; \ var -= q->capacity; \
MYASSERT (var < q->capacity); \ MYASSERT (var < q->capacity); \
} }
#define QUEUE_SANITY_CHECK() \ #define QUEUE_SANITY_CHECK() \
MYASSERT (q != NULL && q->base < q->capacity && q->size <= q->capacity) MYASSERT (q != NULL && q->base < q->capacity && q->size <= q->capacity)
#define QueueCount(q) (q->size) #define QueueCount(q) (q->size)
#define UPDATE_MAX_SIZE() \ #define UPDATE_MAX_SIZE() \
{ \ { \
if (q->size > q->max_size) \ if (q->size > q->max_size) \
q->max_size = q->size; \ q->max_size = q->size; \
} }
Queue * Queue *
QueueInit (ULONG capacity) QueueInit (ULONG capacity)
{ {
Queue *q; Queue *q;
MYASSERT (capacity > 0); MYASSERT (capacity > 0);
q = (Queue *) MemAlloc (QUEUE_BYTE_ALLOCATION (capacity), TRUE); q = (Queue *) MemAlloc (QUEUE_BYTE_ALLOCATION (capacity), TRUE);
if (!q) if (!q)
return NULL; return NULL;
q->base = q->size = 0; q->base = q->size = 0;
q->capacity = capacity; q->capacity = capacity;
q->max_size = 0; q->max_size = 0;
return q; return q;
} }
VOID VOID
QueueFree (Queue *q) QueueFree (Queue *q)
{ {
if (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; QUEUE_SANITY_CHECK ();
--q->size; MemFree (q, QUEUE_BYTE_ALLOCATION (q->capacity));
} }
else }
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--)
{ {
q->data[dest] = q->data[src]; if (item == q->data[src])
QUEUE_ADD_INDEX (dest, 1); {
++n;
--q->size;
}
else
{
q->data[dest] = q->data[src];
QUEUE_ADD_INDEX (dest, 1);
}
QUEUE_ADD_INDEX (src, 1);
} }
QUEUE_ADD_INDEX (src, 1); if (n)
} return item;
if (n) else
return item; return NULL;
else
return NULL;
} }
#undef QUEUE_BYTE_ALLOCATION #undef QUEUE_BYTE_ALLOCATION

View file

@ -1,26 +1,26 @@
/* /*
* TAP-Windows -- A kernel driver to provide virtual tap * TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows. * device functionality on Windows.
* *
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
* *
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* and is released under the GPL version 2 (see below). * and is released under the GPL version 2 (see below).
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 * it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING included with this * along with this program (see the file COPYING included with this
* distribution); if not, write to the Free Software Foundation, Inc., * distribution); if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
//============================================================ //============================================================
// MAC address, Ethernet header, and ARP // MAC address, Ethernet header, and ARP
@ -40,11 +40,11 @@ typedef unsigned char IPV6ADDR [16];
//----------------- //-----------------
typedef struct { typedef struct {
MACADDR addr; MACADDR addr;
} ETH_ADDR; } ETH_ADDR;
typedef struct { typedef struct {
ETH_ADDR list[NIC_MAX_MCAST_LIST]; ETH_ADDR list[NIC_MAX_MCAST_LIST];
} MC_LIST; } MC_LIST;
//---------------- //----------------
@ -53,13 +53,13 @@ typedef struct {
typedef struct typedef struct
{ {
MACADDR dest; /* destination eth addr */ MACADDR dest; /* destination eth addr */
MACADDR src; /* source ether addr */ MACADDR src; /* source ether addr */
# define ETH_P_IP 0x0800 /* IPv4 protocol */ # define ETH_P_IP 0x0800 /* IPv4 protocol */
# define ETH_P_IPV6 0x86DD /* IPv6 protocol */ # define ETH_P_IPV6 0x86DD /* IPv6 protocol */
# define ETH_P_ARP 0x0806 /* ARP protocol */ # define ETH_P_ARP 0x0806 /* ARP protocol */
USHORT proto; /* packet type ID field */ USHORT proto; /* packet type ID field */
} ETH_HEADER, *PETH_HEADER; } ETH_HEADER, *PETH_HEADER;
//---------------- //----------------
@ -67,27 +67,27 @@ typedef struct
//---------------- //----------------
typedef struct typedef struct
{ {
MACADDR m_MAC_Destination; // Reverse these two MACADDR m_MAC_Destination; // Reverse these two
MACADDR m_MAC_Source; // to answer ARP requests MACADDR m_MAC_Source; // to answer ARP requests
USHORT m_Proto; // 0x0806 USHORT m_Proto; // 0x0806
# define MAC_ADDR_TYPE 0x0001 # define MAC_ADDR_TYPE 0x0001
USHORT m_MAC_AddressType; // 0x0001 USHORT m_MAC_AddressType; // 0x0001
USHORT m_PROTO_AddressType; // 0x0800 USHORT m_PROTO_AddressType; // 0x0800
UCHAR m_MAC_AddressSize; // 0x06 UCHAR m_MAC_AddressSize; // 0x06
UCHAR m_PROTO_AddressSize; // 0x04 UCHAR m_PROTO_AddressSize; // 0x04
# define ARP_REQUEST 0x0001 # define ARP_REQUEST 0x0001
# define ARP_REPLY 0x0002 # define ARP_REPLY 0x0002
USHORT m_ARP_Operation; // 0x0001 for ARP request, 0x0002 for ARP reply USHORT m_ARP_Operation; // 0x0001 for ARP request, 0x0002 for ARP reply
MACADDR m_ARP_MAC_Source; MACADDR m_ARP_MAC_Source;
IPADDR m_ARP_IP_Source; IPADDR m_ARP_IP_Source;
MACADDR m_ARP_MAC_Destination; MACADDR m_ARP_MAC_Destination;
IPADDR m_ARP_IP_Destination; IPADDR m_ARP_IP_Destination;
} }
ARP_PACKET, *PARP_PACKET; ARP_PACKET, *PARP_PACKET;
//---------- //----------
@ -97,27 +97,27 @@ ARP_PACKET, *PARP_PACKET;
typedef struct { typedef struct {
# define IPH_GET_VER(v) (((v) >> 4) & 0x0F) # define IPH_GET_VER(v) (((v) >> 4) & 0x0F)
# define IPH_GET_LEN(v) (((v) & 0x0F) << 2) # define IPH_GET_LEN(v) (((v) & 0x0F) << 2)
UCHAR version_len; UCHAR version_len;
UCHAR tos; UCHAR tos;
USHORT tot_len; USHORT tot_len;
USHORT id; USHORT id;
# define IP_OFFMASK 0x1fff # define IP_OFFMASK 0x1fff
USHORT frag_off; USHORT frag_off;
UCHAR ttl; UCHAR ttl;
# define IPPROTO_UDP 17 /* UDP protocol */ # define IPPROTO_UDP 17 /* UDP protocol */
# define IPPROTO_TCP 6 /* TCP protocol */ # define IPPROTO_TCP 6 /* TCP protocol */
# define IPPROTO_ICMP 1 /* ICMP protocol */ # define IPPROTO_ICMP 1 /* ICMP protocol */
# define IPPROTO_IGMP 2 /* IGMP protocol */ # define IPPROTO_IGMP 2 /* IGMP protocol */
UCHAR protocol; UCHAR protocol;
USHORT check; USHORT check;
ULONG saddr; ULONG saddr;
ULONG daddr; ULONG daddr;
/* The options start here. */ /* The options start here. */
} IPHDR; } IPHDR;
//----------- //-----------
@ -125,10 +125,10 @@ typedef struct {
//----------- //-----------
typedef struct { typedef struct {
USHORT source; USHORT source;
USHORT dest; USHORT dest;
USHORT len; USHORT len;
USHORT check; USHORT check;
} UDPHDR; } UDPHDR;
//-------------------------- //--------------------------
@ -136,13 +136,13 @@ typedef struct {
//-------------------------- //--------------------------
typedef struct { typedef struct {
USHORT source; /* source port */ USHORT source; /* source port */
USHORT dest; /* destination port */ USHORT dest; /* destination port */
ULONG seq; /* sequence number */ ULONG seq; /* sequence number */
ULONG ack_seq; /* acknowledgement number */ ULONG ack_seq; /* acknowledgement number */
# define TCPH_GET_DOFF(d) (((d) & 0xF0) >> 2) # define TCPH_GET_DOFF(d) (((d) & 0xF0) >> 2)
UCHAR doff_res; UCHAR doff_res;
# define TCPH_FIN_MASK (1<<0) # define TCPH_FIN_MASK (1<<0)
# define TCPH_SYN_MASK (1<<1) # define TCPH_SYN_MASK (1<<1)
@ -152,11 +152,11 @@ typedef struct {
# define TCPH_URG_MASK (1<<5) # define TCPH_URG_MASK (1<<5)
# define TCPH_ECE_MASK (1<<6) # define TCPH_ECE_MASK (1<<6)
# define TCPH_CWR_MASK (1<<7) # define TCPH_CWR_MASK (1<<7)
UCHAR flags; UCHAR flags;
USHORT window; USHORT window;
USHORT check; USHORT check;
USHORT urg_ptr; USHORT urg_ptr;
} TCPHDR; } TCPHDR;
#define TCPOPT_EOL 0 #define TCPOPT_EOL 0
@ -169,14 +169,14 @@ typedef struct {
//------------ //------------
typedef struct { typedef struct {
UCHAR version_prio; UCHAR version_prio;
UCHAR flow_lbl[3]; UCHAR flow_lbl[3];
USHORT payload_len; USHORT payload_len;
# define IPPROTO_ICMPV6 0x3a /* ICMP protocol v6 */ # define IPPROTO_ICMPV6 0x3a /* ICMP protocol v6 */
UCHAR nexthdr; UCHAR nexthdr;
UCHAR hop_limit; UCHAR hop_limit;
IPV6ADDR saddr; IPV6ADDR saddr;
IPV6ADDR daddr; IPV6ADDR daddr;
} IPV6HDR; } IPV6HDR;
//-------------------------------------------- //--------------------------------------------
@ -186,39 +186,39 @@ typedef struct {
// Neighbor Solictiation - RFC 4861, 4.3 // Neighbor Solictiation - RFC 4861, 4.3
// (this is just the ICMPv6 part of the packet) // (this is just the ICMPv6 part of the packet)
typedef struct { typedef struct {
UCHAR type; UCHAR type;
# define ICMPV6_TYPE_NS 135 // neighbour solicitation # define ICMPV6_TYPE_NS 135 // neighbour solicitation
UCHAR code; UCHAR code;
# define ICMPV6_CODE_0 0 // no specific sub-code for NS/NA # define ICMPV6_CODE_0 0 // no specific sub-code for NS/NA
USHORT checksum; USHORT checksum;
ULONG reserved; ULONG reserved;
IPV6ADDR target_addr; IPV6ADDR target_addr;
} ICMPV6_NS; } ICMPV6_NS;
// Neighbor Advertisement - RFC 4861, 4.4 + 4.6/4.6.1 // Neighbor Advertisement - RFC 4861, 4.4 + 4.6/4.6.1
// (this is just the ICMPv6 payload) // (this is just the ICMPv6 payload)
typedef struct { typedef struct {
UCHAR type; UCHAR type;
# define ICMPV6_TYPE_NA 136 // neighbour advertisement # define ICMPV6_TYPE_NA 136 // neighbour advertisement
UCHAR code; UCHAR code;
# define ICMPV6_CODE_0 0 // no specific sub-code for NS/NA # define ICMPV6_CODE_0 0 // no specific sub-code for NS/NA
USHORT checksum; USHORT checksum;
UCHAR rso_bits; // Router(0), Solicited(2), Ovrrd(4) UCHAR rso_bits; // Router(0), Solicited(2), Ovrrd(4)
UCHAR reserved[3]; UCHAR reserved[3];
IPV6ADDR target_addr; IPV6ADDR target_addr;
// always include "Target Link-layer Address" option (RFC 4861 4.6.1) // always include "Target Link-layer Address" option (RFC 4861 4.6.1)
UCHAR opt_type; UCHAR opt_type;
#define ICMPV6_OPTION_TLLA 2 #define ICMPV6_OPTION_TLLA 2
UCHAR opt_length; UCHAR opt_length;
#define ICMPV6_LENGTH_TLLA 1 // multiplied by 8 -> 1 = 8 bytes #define ICMPV6_LENGTH_TLLA 1 // multiplied by 8 -> 1 = 8 bytes
MACADDR target_macaddr; MACADDR target_macaddr;
} ICMPV6_NA; } ICMPV6_NA;
// this is the complete packet with Ethernet and IPv6 headers // this is the complete packet with Ethernet and IPv6 headers
typedef struct { typedef struct {
ETH_HEADER eth; ETH_HEADER eth;
IPV6HDR ipv6; IPV6HDR ipv6;
ICMPV6_NA icmpv6; ICMPV6_NA icmpv6;
} ICMPV6_NA_PKT; } ICMPV6_NA_PKT;
#pragma pack() #pragma pack()

View file

@ -200,44 +200,6 @@ VOID CheckIfDhcpAndTunMode
VOID HookDispatchFunctions(); VOID HookDispatchFunctions();
#if ENABLE_NONADMIN
#if defined(DDKVER_MAJOR) && 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 struct WIN2K_NDIS_MINIPORT_BLOCK
{ {
unsigned char opaque[16]; unsigned char opaque[16];

View file

@ -33,22 +33,11 @@
#define TAP_WIN_CONTROL_CODE(request,method) \ #define TAP_WIN_CONTROL_CODE(request,method) \
CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
/* Present in 8.1 */
#define TAP_WIN_IOCTL_GET_MAC TAP_WIN_CONTROL_CODE (1, METHOD_BUFFERED) #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_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_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_SET_MEDIA_STATUS TAP_WIN_CONTROL_CODE (6, 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_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)
/* /*
* ================= * =================

File diff suppressed because it is too large Load diff

View file

@ -83,11 +83,13 @@ typedef struct _TapExtension
BOOLEAN m_TapIsRunning; BOOLEAN m_TapIsRunning;
BOOLEAN m_CalledTapDeviceFreeResources; BOOLEAN m_CalledTapDeviceFreeResources;
#if 0
// DPC queue for deferred packet injection // DPC queue for deferred packet injection
BOOLEAN m_InjectDpcInitialized; BOOLEAN m_InjectDpcInitialized;
KDPC m_InjectDpc; KDPC m_InjectDpc;
NDIS_SPIN_LOCK m_InjectLock; NDIS_SPIN_LOCK m_InjectLock;
Queue *m_InjectQueue; Queue *m_InjectQueue;
#endif
} }
TapExtension, *TapExtensionPointer; TapExtension, *TapExtensionPointer;
@ -101,6 +103,7 @@ typedef struct _TapPacket
} }
TapPacket, *TapPacketPointer; TapPacket, *TapPacketPointer;
#if 0
typedef struct _InjectPacket typedef struct _InjectPacket
{ {
# define INJECT_PACKET_SIZE(data_size) (sizeof (InjectPacket) + (data_size)) # define INJECT_PACKET_SIZE(data_size) (sizeof (InjectPacket) + (data_size))
@ -109,6 +112,7 @@ typedef struct _InjectPacket
UCHAR m_Data []; // m_Data must be the last struct member UCHAR m_Data []; // m_Data must be the last struct member
} }
InjectPacket, *InjectPacketPointer; InjectPacket, *InjectPacketPointer;
#endif
typedef struct _TapAdapter typedef struct _TapAdapter
{ {
@ -136,33 +140,6 @@ typedef struct _TapAdapter
// Adapter power state // Adapter power state
char m_DeviceState; char m_DeviceState;
#if 0
// 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;
ETH_HEADER m_UserToTap_IPv6; // same as UserToTap but proto=ipv6
MACADDR m_MAC_Broadcast;
#endif
#if 0
// 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;
#endif
// Help to tear down the adapter by keeping // Help to tear down the adapter by keeping
// some state information on allocated // some state information on allocated
// resources. // resources.

View file

@ -95,7 +95,7 @@
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>wsock32.lib;ws2_32.lib;iphlpapi.lib;rpcrt4.lib;$(SolutionDir)\ext\bin\libcrypto\win32-vs2012\libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>wsock32.lib;ws2_32.lib;winhttp.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
@ -109,7 +109,7 @@
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>wsock32.lib;ws2_32.lib;iphlpapi.lib;rpcrt4.lib;$(SolutionDir)\ext\bin\libcrypto\win64-vs2012\libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>wsock32.lib;ws2_32.lib;winhttp.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
@ -127,7 +127,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>wsock32.lib;ws2_32.lib;iphlpapi.lib;rpcrt4.lib;$(SolutionDir)\ext\bin\libcrypto\win32-vs2012\libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>wsock32.lib;ws2_32.lib;winhttp.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
@ -145,7 +145,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>wsock32.lib;ws2_32.lib;iphlpapi.lib;rpcrt4.lib;$(SolutionDir)\ext\bin\libcrypto\win64-vs2012\libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>wsock32.lib;ws2_32.lib;winhttp.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>