diff options
author | Alberto Gonzalez Iniesta <agi@inittab.org> | 2012-11-05 16:28:09 +0100 |
---|---|---|
committer | Alberto Gonzalez Iniesta <agi@inittab.org> | 2012-11-05 16:28:09 +0100 |
commit | 8dd0350e1607aa30f7a043c8d5ec7a7eeb874115 (patch) | |
tree | 566d0620eb693320cb121dfd93a5675fa704a30b /tap-win32/dhcp.c | |
parent | 349cfa7acb95abe865209a28e417ec74b56f9bba (diff) |
Imported Upstream version 2.3_rc1
Diffstat (limited to 'tap-win32/dhcp.c')
-rwxr-xr-x | tap-win32/dhcp.c | 599 |
1 files changed, 0 insertions, 599 deletions
diff --git a/tap-win32/dhcp.c b/tap-win32/dhcp.c deleted file mode 100755 index 3891d42..0000000 --- a/tap-win32/dhcp.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * TAP-Win32/TAP-Win64 -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-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_IOCTL_CONFIG_DHCP_MASQ mode, reply -// to the message. Return TRUE if we processed the passed -// message, so that downstream stages can ignore it. -//=================================================================== - -BOOLEAN -ProcessDHCP (TapAdapterPointer p_Adapter, - const ETH_HEADER *eth, - const IPHDR *ip, - const UDPHDR *udp, - const DHCP *dhcp, - int optlen) -{ - int msg_type; - - // Sanity check IP header - if (!(ntohs (ip->tot_len) == sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen - && (ntohs (ip->frag_off) & IP_OFFMASK) == 0)) - return TRUE; - - // Does this message belong to us? - if (!DHCPMessageOurs (p_Adapter, eth, ip, udp, dhcp)) - return FALSE; - - msg_type = GetDHCPMessageType (dhcp, optlen); - - // Drop non-BOOTREQUEST messages - if (dhcp->op != BOOTREQUEST) - return TRUE; - - // Drop any messages except DHCPDISCOVER or DHCPREQUEST - if (!(msg_type == DHCPDISCOVER || msg_type == DHCPREQUEST)) - return TRUE; - - // Should we reply with DHCPOFFER, DHCPACK, or DHCPNAK? - if (msg_type == DHCPREQUEST - && ((dhcp->ciaddr && dhcp->ciaddr != p_Adapter->m_dhcp_addr) - || !p_Adapter->m_dhcp_received_discover - || p_Adapter->m_dhcp_bad_requests >= BAD_DHCPREQUEST_NAK_THRESHOLD)) - SendDHCPMsg (p_Adapter, - DHCPNAK, - eth, ip, udp, dhcp); - else - SendDHCPMsg (p_Adapter, - (msg_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK), - eth, ip, udp, dhcp); - - // Remember if we received a DHCPDISCOVER - if (msg_type == DHCPDISCOVER) - p_Adapter->m_dhcp_received_discover = TRUE; - - // Is this a bad DHCPREQUEST? - if (msg_type == DHCPREQUEST && dhcp->ciaddr != p_Adapter->m_dhcp_addr) - ++p_Adapter->m_dhcp_bad_requests; - - return TRUE; -} - -#if DBG - -const char * -message_op_text (int op) -{ - switch (op) - { - case BOOTREQUEST: - return "BOOTREQUEST"; - case BOOTREPLY: - return "BOOTREPLY"; - default: - return "???"; - } -} - -const char * -message_type_text (int type) -{ - switch (type) - { - case DHCPDISCOVER: - return "DHCPDISCOVER"; - case DHCPOFFER: - return "DHCPOFFER"; - case DHCPREQUEST: - return "DHCPREQUEST"; - case DHCPDECLINE: - return "DHCPDECLINE"; - case DHCPACK: - return "DHCPACK"; - case DHCPNAK: - return "DHCPNAK"; - case DHCPRELEASE: - return "DHCPRELEASE"; - case DHCPINFORM: - return "DHCPINFORM"; - default: - return "???"; - } -} - -const char * -port_name (int port) -{ - switch (port) - { - case BOOTPS_PORT: - return "BOOTPS"; - case BOOTPC_PORT: - return "BOOTPC"; - default: - return "unknown"; - } -} - -VOID -DumpDHCP (const ETH_HEADER *eth, - const IPHDR *ip, - const UDPHDR *udp, - const DHCP *dhcp, - const int optlen) -{ - DEBUGP ((" %s", message_op_text (dhcp->op))); - DEBUGP ((" %s ", message_type_text (GetDHCPMessageType (dhcp, optlen)))); - PrIP (ip->saddr); - DEBUGP ((":%s[", port_name (ntohs (udp->source)))); - PrMac (eth->src); - DEBUGP (("] -> ")); - PrIP (ip->daddr); - DEBUGP ((":%s[", port_name (ntohs (udp->dest)))); - PrMac (eth->dest); - DEBUGP (("]")); - if (dhcp->ciaddr) - { - DEBUGP ((" ci=")); - PrIP (dhcp->ciaddr); - } - if (dhcp->yiaddr) - { - DEBUGP ((" yi=")); - PrIP (dhcp->yiaddr); - } - if (dhcp->siaddr) - { - DEBUGP ((" si=")); - PrIP (dhcp->siaddr); - } - if (dhcp->hlen == sizeof (MACADDR)) - { - DEBUGP ((" ch=")); - PrMac (dhcp->chaddr); - } - - DEBUGP ((" xid=0x%08x", ntohl (dhcp->xid))); - - if (ntohl (dhcp->magic) != 0x63825363) - DEBUGP ((" ma=0x%08x", ntohl (dhcp->magic))); - if (dhcp->htype != 1) - DEBUGP ((" htype=%d", dhcp->htype)); - if (dhcp->hops) - DEBUGP ((" hops=%d", dhcp->hops)); - if (ntohs (dhcp->secs)) - DEBUGP ((" secs=%d", ntohs (dhcp->secs))); - if (ntohs (dhcp->flags)) - DEBUGP ((" flags=0x%04x", ntohs (dhcp->flags))); - - // extra stuff - - if (ip->version_len != 0x45) - DEBUGP ((" vl=0x%02x", ip->version_len)); - if (ntohs (ip->tot_len) != sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen) - DEBUGP ((" tl=%d", ntohs (ip->tot_len))); - if (ntohs (udp->len) != sizeof (UDPHDR) + sizeof (DHCP) + optlen) - DEBUGP ((" ul=%d", ntohs (udp->len))); - - if (ip->tos) - DEBUGP ((" tos=0x%02x", ip->tos)); - if (ntohs (ip->id)) - DEBUGP ((" id=0x%04x", ntohs (ip->id))); - if (ntohs (ip->frag_off)) - DEBUGP ((" frag_off=0x%04x", ntohs (ip->frag_off))); - - DEBUGP ((" ttl=%d", ip->ttl)); - DEBUGP ((" ic=0x%04x [0x%04x]", ntohs (ip->check), - ip_checksum ((UCHAR*)ip, sizeof (IPHDR)))); - DEBUGP ((" uc=0x%04x [0x%04x/%d]", ntohs (udp->check), - udp_checksum ((UCHAR *) udp, - sizeof (UDPHDR) + sizeof (DHCP) + optlen, - (UCHAR *) &ip->saddr, - (UCHAR *) &ip->daddr), - optlen)); - - // Options - { - const UCHAR *opt = (UCHAR *) (dhcp + 1); - int i; - - DEBUGP ((" OPT")); - for (i = 0; i < optlen; ++i) - { - const UCHAR data = opt[i]; - DEBUGP ((".%d", data)); - } - } -} - -#endif /* DBG */ |