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>