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>