File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcdrop / src / dhcp_functions.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:25:35 2012 UTC (13 years, 4 months ago) by misho
Branches: dhcdrop, MAIN
CVS tags: v0_5, HEAD
dhcdrop

    1: /*
    2:  * dhcdrop_functions.c
    3:  *
    4:  *  Created on: 30.07.2009
    5:  *	Copyright (C) 2009 by Chebotarev Roman <roma@ultranet.ru>
    6:  *
    7:  *	This program is free software; you can redistribute it and/or modify
    8:  *	it under the terms of the GNU General Public License as published by
    9:  *	the Free Software Foundation; either version 2 of the License.
   10:  *
   11:  *	This program is distributed in the hope that it will be useful,
   12:  *	but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14:  *	GNU General Public License for more details.
   15:  *
   16:  *	You should have received a copy of the GNU General Public License
   17:  *	along with this program; if not, write to the Free Software
   18:  *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19:  */
   20: 
   21: #include "common_includes.h"
   22: #include "dhcp.h"
   23: #include "net.h"
   24: #include "dhcdrop_types.h"
   25: #include "dhcp_functions.h"
   26: 
   27: const uint8_t magic_cookie[] = {99, 130, 83, 99};
   28: 
   29: uint16_t make_dhcp_req	/* Return length of field DHCP-options */
   30:     (
   31:         struct  dhcp_packet * dhcp_data,	/* Pointer to structure of DHCP packet. Can't be NULL*/
   32:         const uint8_t message_type,			/* DHCPDISCOVER, DHCPREQUEST... */
   33:         const uint8_t * ether_src_addr,		/* Ethernet address of pseudo client. Can't be NULL */
   34:         const uint32_t server_address,	/* NULL for DHCPDISCOVER */
   35:         const uint32_t cl_ip_addr,		/* NULL for DHCPDISCOVER */
   36:         const int xid,							/* XID for DHCP transaction */
   37:         const struct config_params * config		/* Pointer to structure of programm configuration */
   38:     )
   39: {
   40: 	uint8_t *p_dhcp_opt;
   41:     bzero(dhcp_data, sizeof(struct dhcp_packet));
   42:     /* Fill common options */
   43:     dhcp_data->op = BOOTREQUEST;
   44:     dhcp_data->htype = HTYPE_ETHER;
   45:     dhcp_data->hlen = ETH_ALEN;
   46:     dhcp_data->flags = config->broadcast ? htons(BOOTP_BROADCAST) : 0;
   47:     dhcp_data->xid = (xid)? xid : rand();						/* If xid == 0 create new xid */
   48:     memcpy(dhcp_data->chaddr, ether_src_addr, ETH_ALEN);
   49: 
   50:     /*Fill dhcp-options field*/
   51:     p_dhcp_opt = dhcp_data->options;
   52: 
   53:     /*Start DHCP options*/
   54:     memcpy(p_dhcp_opt, magic_cookie, sizeof(magic_cookie));
   55:     p_dhcp_opt += sizeof(magic_cookie);
   56: 
   57:     /*Create DHCP-message type*/
   58:     *p_dhcp_opt++ = DHO_DHCP_MESSAGE_TYPE;
   59:     *p_dhcp_opt++ = 1;
   60: 
   61:     *p_dhcp_opt++ = message_type;
   62: 
   63:     if(message_type == DHCPREQUEST)
   64:     {
   65:         *p_dhcp_opt++ = DHO_DHCP_REQUESTED_ADDRESS;
   66:         *p_dhcp_opt++ = sizeof(cl_ip_addr);
   67:         memcpy(p_dhcp_opt, &cl_ip_addr, sizeof(cl_ip_addr));
   68:         p_dhcp_opt += sizeof(cl_ip_addr);
   69:     }
   70:     else if(message_type == DHCPRELEASE)
   71:     	dhcp_data->ciaddr.s_addr = cl_ip_addr;
   72: 
   73:     if((message_type == DHCPREQUEST) ||
   74:     		(message_type == DHCPRELEASE))
   75:     {
   76:         /*Create parametr "server identifier"*/
   77:         *p_dhcp_opt++ = DHO_DHCP_SERVER_IDENTIFIER;
   78:         *p_dhcp_opt++ = sizeof(server_address);
   79:         memcpy(p_dhcp_opt, &server_address, sizeof(server_address));
   80:         p_dhcp_opt += sizeof(server_address);
   81:     }
   82: 
   83:     if(message_type != DHCPRELEASE)
   84:     {
   85: 		/*Create parametrs request list*/
   86: 		*p_dhcp_opt++ = DHO_DHCP_PARAMETER_REQUEST_LIST;
   87: 		*p_dhcp_opt++ = 3;
   88: 		*p_dhcp_opt++ = DHO_DOMAIN_NAME_SERVERS;
   89: 		*p_dhcp_opt++ = DHO_ROUTERS;
   90: 		*p_dhcp_opt++ = DHO_SUBNET_MASK;
   91: 
   92: 		/*Create parametr "hostname"*/
   93: 		*p_dhcp_opt++ = DHO_HOST_NAME;
   94: 		*p_dhcp_opt++ = strlen(config->client_hostname);
   95: 		memcpy(p_dhcp_opt, config->client_hostname, strlen(config->client_hostname));
   96: 		p_dhcp_opt += strlen(config->client_hostname);
   97: 
   98: 		/*Create parametr "dhcp-client name" (Vendor-Class)*/
   99: 		*p_dhcp_opt++ = DHO_VENDOR_CLASS_IDENTIFIER;
  100: 		*p_dhcp_opt++ = strlen(config->dhcp_client);
  101: 		memcpy(p_dhcp_opt, config->dhcp_client, strlen(config->dhcp_client));
  102: 		p_dhcp_opt += strlen(config->dhcp_client);
  103:     }
  104: 
  105:     /*Create client-ID option*/
  106:     *p_dhcp_opt++ = DHO_DHCP_CLIENT_IDENTIFIER;
  107:     *p_dhcp_opt++ = 1 + ETH_ALEN;			/* Length HW-type + ETHER_ADDR_LEN == 7 */
  108:     *p_dhcp_opt++ = HTYPE_ETHER;
  109:     memcpy(p_dhcp_opt, ether_src_addr, ETH_ALEN);
  110:     p_dhcp_opt += ETH_ALEN;
  111: 
  112:     /*End options*/
  113:     *p_dhcp_opt++ = DHO_END;
  114: 
  115:     return  p_dhcp_opt - dhcp_data->options;
  116: }
  117: 
  118: 
  119: uint16_t set_dhcp_type(const struct dhcp_packet *request, const uint16_t new_type)
  120: {
  121:     uint8_t *option = (uint8_t *)request + sizeof (struct dhcp_packet) - DHCP_OPTION_LEN;
  122:     const uint8_t * opt_end = (const uint8_t *)request + sizeof(struct dhcp_packet);
  123:     uint8_t old_type;
  124:     if(memcmp(option, magic_cookie, sizeof(magic_cookie)))  /* Exit if magic_cookie not found - */
  125:             return -1;
  126:     option += sizeof(magic_cookie);							 /* Start options field */
  127:     while((option < opt_end) && (*option != 255))
  128:     {
  129: 		if(*option == DHO_DHCP_MESSAGE_TYPE)
  130:         {
  131: 			old_type = *(option + 2);
  132:             *(option + 2) = new_type;
  133:             return old_type;
  134:         }
  135:         else option += *(option + 1) + 2;
  136:     }
  137:     return 0;
  138: }
  139: 
  140: int get_dhcp_option(const struct dhcp_packet *request, const uint16_t packet_len,
  141:                         const int req_option, void * option_value, int value_size)
  142: {
  143:     /* Calculate start address for field "options" in DHCP packet */
  144:     uint8_t *option = (uint8_t *)request + sizeof (struct dhcp_packet) - DHCP_OPTION_LEN;
  145:     /* End options equal end packet */
  146:     const uint8_t * opt_end = (const uint8_t *)request + packet_len;
  147:     /* Check "Magic cookie" in first 4 bytes options-field */
  148:     if(memcmp(option, magic_cookie, sizeof(magic_cookie)))
  149:         return -1;
  150:     option += sizeof(magic_cookie);
  151:     int opt_len;
  152: 
  153:     while((option < opt_end) && (*option != DHO_END))
  154:     {
  155:     	opt_len = *(option + 1);
  156:         if((option + opt_len) > opt_end)
  157:         {
  158:             printf("\nWARNING! Invalid value in DHCP-option length. Attempting DoS?\n");
  159:             return -1;
  160:         }
  161: 
  162:         if(*option == req_option)
  163:         {
  164:             if(opt_len > value_size)
  165:             {
  166:             	printf("\nWARNING! Option's length is more than was expected (opcode: %d opt_len: %d > expected_len: %d). Attempting DoS?\n",
  167:             			*option, opt_len, value_size);
  168:             	return -1;
  169:             }
  170: 
  171:             memcpy(option_value, option + 2, opt_len);
  172:             return *(option + 1);
  173:         }
  174:         else option += *(option + 1) + 2;
  175:     }
  176:     return 0;
  177: }
  178: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>