Explicitly track length in get_end_option_idx().

Rename get_options() to get_option_data() and end_options() to
get_end_option_idx().
This commit is contained in:
Nicholas J. Kain 2011-03-30 12:04:38 -04:00
parent 97978711de
commit 0e62d46f8b
4 changed files with 39 additions and 29 deletions

View File

@ -1,5 +1,5 @@
/* ifchange.c - functions to call the interface change daemon
* Time-stamp: <2011-03-30 11:33:42 nk>
* Time-stamp: <2011-03-30 12:02:55 nk>
*
* (c) 2004-2011 Nicholas J. Kain <njkain at gmail dot com>
*
@ -180,7 +180,7 @@ static void send_cmd(int sockfd, struct dhcpMessage *packet,
return;
memset(buf, '\0', sizeof buf);
optdata = get_option(packet, code, &optlen);
optdata = get_option_data(packet, code, &optlen);
if (ifchd_cmd(buf, sizeof buf, optdata, optlen, code, option_type(code),
option_name(code)) == -1)
return;

View File

@ -174,10 +174,10 @@ unsigned char *alloc_dhcp_client_id_option(unsigned char type,
return alloc_option(DHCP_CLIENT_ID, data, sizeof data);
}
// Worker function for get_option(). Optlen will be set to the length
// Worker function for get_option_data(). Optlen will be set to the length
// of the option data.
static uint8_t *do_get_option(uint8_t *buf, ssize_t buflen, int code,
char *overload, ssize_t *optlen)
static uint8_t *do_get_option_data(uint8_t *buf, ssize_t buflen, int code,
char *overload, ssize_t *optlen)
{
/* option bytes: [code][len]([data1][data2]..[dataLEN]) */
*overload = 0;
@ -221,7 +221,7 @@ static uint8_t *do_get_option(uint8_t *buf, ssize_t buflen, int code,
// Get an option with bounds checking (warning, result is not aligned)
// optlen will be equal to the length of the option data.
uint8_t *get_option(struct dhcpMessage *packet, int code, ssize_t *optlen)
uint8_t *get_option_data(struct dhcpMessage *packet, int code, ssize_t *optlen)
{
uint8_t *option, *buf;
ssize_t buflen;
@ -230,40 +230,45 @@ uint8_t *get_option(struct dhcpMessage *packet, int code, ssize_t *optlen)
buf = packet->options;
buflen = sizeof packet->options;
option = do_get_option(buf, buflen, code, &overload, optlen);
option = do_get_option_data(buf, buflen, code, &overload, optlen);
if (option)
return option;
if (overload & 1) {
parsed_ff = 1;
option = do_get_option(packet->file, sizeof packet->file,
code, &overload, optlen);
option = do_get_option_data(packet->file, sizeof packet->file,
code, &overload, optlen);
if (option)
return option;
}
if (overload & 2) {
option = do_get_option(packet->sname, sizeof packet->sname,
code, &overload, optlen);
option = do_get_option_data(packet->sname, sizeof packet->sname,
code, &overload, optlen);
if (option)
return option;
if (!parsed_ff && overload & 1)
option = do_get_option(packet->file, sizeof packet->file,
code, &overload, optlen);
option = do_get_option_data(packet->file, sizeof packet->file,
code, &overload, optlen);
}
return option;
}
/* return the position of the 'end' option */
int end_option(uint8_t *optionptr)
int get_end_option_idx(uint8_t *optbuf, size_t bufsize)
{
int i = 0;
while (i < DHCP_OPTIONS_BUFSIZE && optionptr[i] != DHCP_END) {
if (optionptr[i] != DHCP_PADDING)
i += optionptr[i + OPT_LEN] + OPT_DATA - 1;
i++;
while (i < bufsize && optbuf[i] != DHCP_END) {
if (optbuf[i] != DHCP_PADDING)
i += optbuf[i+1] + 2;
else
i++;
}
if (i < bufsize - 1)
return i;
else {
log_warning("get_end_option_idx(): did not find DHCP_END marker");
return bufsize - 1;
}
return (i < DHCP_OPTIONS_BUFSIZE - 1 ? i : DHCP_OPTIONS_BUFSIZE - 1);
}
@ -271,7 +276,8 @@ int end_option(uint8_t *optionptr)
* code, length, then data) */
int add_option_string(unsigned char *optionptr, unsigned char *string)
{
int end = end_option(optionptr);
// XXX: not real length
int end = get_end_option_idx(optionptr, DHCP_OPTIONS_BUFSIZE);
/* end position + string length + option code/length + end option */
if (end + string[OPT_LEN] + 2 + 1 >= DHCP_OPTIONS_BUFSIZE) {
@ -319,7 +325,8 @@ int add_simple_option(unsigned char *optionptr, unsigned char code,
/* checking here because it goes towards the head of the packet. */
void add_requests(struct dhcpMessage *packet)
{
int end = end_option(packet->options);
// XXX: not real length
int end = get_end_option_idx(packet->options, DHCP_OPTIONS_BUFSIZE);
int i, len = 0;
packet->options[end + OPT_CODE] = DHCP_PARAM_REQ;

View File

@ -75,8 +75,8 @@ unsigned char *alloc_option(unsigned char code, unsigned char *optdata,
unsigned char *alloc_dhcp_client_id_option(unsigned char type,
unsigned char *idstr, size_t idstrlen);
uint8_t *get_option(struct dhcpMessage *packet, int code, ssize_t *optlen);
int end_option(uint8_t *optionptr);
uint8_t *get_option_data(struct dhcpMessage *packet, int code, ssize_t *optlen);
int get_end_option_idx(uint8_t *optbuf, size_t bufsize);
int add_option_string(unsigned char *optionptr, unsigned char *string);
int add_simple_option(unsigned char *optionptr, unsigned char code, uint32_t data);

View File

@ -105,7 +105,8 @@ int raw_packet(struct dhcpMessage *payload, uint32_t source_ip,
* In order to work with those buggy servers,
* we truncate packets after end option byte.
*/
padding = DHCP_OPTIONS_BUFSIZE - 1 - end_option(packet.data.options);
padding = DHCP_OPTIONS_BUFSIZE - 1 - get_end_option_idx(packet.data.options,
DHCP_OPTIONS_BUFSIZE);
packet.ip.protocol = IPPROTO_UDP;
packet.ip.saddr = source_ip;
@ -164,7 +165,8 @@ int kernel_packet(struct dhcpMessage *payload, uint32_t source_ip,
if (connect(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1)
goto out_fd;
padding = DHCP_OPTIONS_BUFSIZE - 1 - end_option(payload->options);
padding = DHCP_OPTIONS_BUFSIZE - 1 - get_end_option_idx(payload->options,
DHCP_OPTIONS_BUFSIZE);
result = safe_write(fd, (const char *)payload, DHCP_SIZE - padding);
if (result == -1)
log_error("kernel_packet: write failed: %s", strerror(errno));
@ -210,7 +212,7 @@ static void init_selecting_packet(struct client_state_t *cs,
ssize_t optlen;
/* Must be a DHCPOFFER to one of our xid's */
if (*message == DHCPOFFER) {
if ((temp = get_option(packet, DHCP_SERVER_ID, &optlen))) {
if ((temp = get_option_data(packet, DHCP_SERVER_ID, &optlen))) {
/* Memcpy to a temp buffer to force alignment */
memcpy(&cs->serverAddr, temp, 4);
cs->xid = packet->xid;
@ -233,7 +235,7 @@ static void dhcp_ack_or_nak_packet(struct client_state_t *cs,
unsigned char *temp = NULL;
ssize_t optlen;
if (*message == DHCPACK) {
if (!(temp = get_option(packet, DHCP_LEASE_TIME, &optlen))) {
if (!(temp = get_option_data(packet, DHCP_LEASE_TIME, &optlen))) {
log_line("No lease time received, assuming 1h.");
cs->lease = 60 * 60;
} else {
@ -293,7 +295,8 @@ void handle_packet(struct client_state_t *cs)
return;
}
if ((message = get_option(&packet, DHCP_MESSAGE_TYPE, &optlen)) == NULL) {
if ((message = get_option_data(&packet, DHCP_MESSAGE_TYPE, &optlen))
== NULL) {
log_line("couldnt get option from packet -- ignoring");
return;
}