diff options
Diffstat (limited to 'dhcp.c')
-rw-r--r-- | dhcp.c | 183 |
1 files changed, 0 insertions, 183 deletions
@@ -1,183 +0,0 @@ -/* - * OpenVPN -- An application to securely tunnel IP networks - * over a single TCP/UDP port, with support for SSL/TLS-based - * session authentication and key exchange, - * packet encryption, packet authentication, and - * packet compression. - * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "syshead.h" - -#include "dhcp.h" -#include "socket.h" -#include "error.h" - -#include "memdbg.h" - -static int -get_dhcp_message_type (const struct dhcp *dhcp, const int optlen) -{ - const uint8_t *p = (uint8_t *) (dhcp + 1); - int i; - - for (i = 0; i < optlen; ++i) - { - const uint8_t type = p[i]; - const int room = optlen - i; - 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 >= 3) - { - if (p[i+1] == 1) /* option length should be 1 */ - return p[i+2]; /* return message type */ - } - return -1; - } - else /* some other option */ - { - if (room >= 2) - { - const int len = p[i+1]; /* get option length */ - i += (len + 1); /* advance to next option */ - } - } - } - return -1; -} - -static in_addr_t -do_extract (struct dhcp *dhcp, const int optlen) -{ - uint8_t *p = (uint8_t *) (dhcp + 1); - int i; - in_addr_t ret = 0; - - for (i = 0; i < optlen; ++i) - { - const uint8_t type = p[i]; - const int room = optlen - i; - if (type == DHCP_END) - break; - else if (type == DHCP_PAD) - ; - else if (type == DHCP_ROUTER) - { - if (room >= 2) - { - const int len = p[i+1]; /* get option length */ - if (len <= (room-2)) - { - if (!ret && len >= 4 && (len & 3) == 0) - { - memcpy (&ret, p+i+2, 4); /* get router IP address */ - ret = ntohl (ret); - } - memset (p+i, DHCP_PAD, len+2); /* delete the router option by padding it out */ - } - i += (len + 1); /* advance to next option */ - } - } - else /* some other option */ - { - if (room >= 2) - { - const int len = p[i+1]; /* get option length */ - i += (len + 1); /* advance to next option */ - } - } - } - return ret; -} - -static uint16_t -udp_checksum (const uint8_t *buf, - const int len_udp, - const uint8_t *src_addr, - const uint8_t *dest_addr) -{ - uint16_t word16; - uint32_t 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 += (uint16_t) OPENVPN_IPPROTO_UDP + (uint16_t) 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 ((uint16_t) ~sum); -} - -in_addr_t -dhcp_extract_router_msg (struct buffer *ipbuf) -{ - struct dhcp_full *df = (struct dhcp_full *) BPTR (ipbuf); - const int optlen = BLEN (ipbuf) - (sizeof (struct openvpn_iphdr) + sizeof (struct openvpn_udphdr) + sizeof (struct dhcp)); - - if (optlen >= 0 - && df->ip.protocol == OPENVPN_IPPROTO_UDP - && df->udp.source == htons (BOOTPS_PORT) - && df->udp.dest == htons (BOOTPC_PORT) - && df->dhcp.op == BOOTREPLY - && get_dhcp_message_type (&df->dhcp, optlen) == DHCPACK) - { - /* get the router IP address while padding out all DHCP router options */ - const in_addr_t ret = do_extract (&df->dhcp, optlen); - - /* recompute the UDP checksum */ - df->udp.check = htons (udp_checksum ((uint8_t *) &df->udp, - sizeof (struct openvpn_udphdr) + sizeof (struct dhcp) + optlen, - (uint8_t *)&df->ip.saddr, - (uint8_t *)&df->ip.daddr)); - - if (ret) - { - struct gc_arena gc = gc_new (); - msg (D_ROUTE, "Extracted DHCP router address: %s", print_in_addr_t (ret, 0, &gc)); - gc_free (&gc); - } - - return ret; - } - else - return 0; -} |