Annotation of embedaddon/dhcdrop/src/dhcp_functions.c, revision 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>