mirror of
https://github.com/ZeroTier/ZeroTierOne
synced 2025-07-10 15:23:06 -07:00
Tap driver basically builds in VS2012... fork of tap-windows from OpenVPN (compatible license).
This commit is contained in:
parent
b6248c7cb7
commit
e2effbd1ce
29 changed files with 6762 additions and 200 deletions
599
vsprojects/TapDriver/dhcp.c
Normal file
599
vsprojects/TapDriver/dhcp.c
Normal file
|
@ -0,0 +1,599 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
//=========================
|
||||
// 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 */
|
Loading…
Add table
Add a link
Reference in a new issue