Annotation of embedaddon/dhcdrop/src/dhcp_functions.c, revision 1.1.1.1

1.1       misho       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>