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:
parent
97978711de
commit
0e62d46f8b
@ -1,5 +1,5 @@
|
|||||||
/* ifchange.c - functions to call the interface change daemon
|
/* 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>
|
* (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;
|
return;
|
||||||
|
|
||||||
memset(buf, '\0', sizeof buf);
|
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),
|
if (ifchd_cmd(buf, sizeof buf, optdata, optlen, code, option_type(code),
|
||||||
option_name(code)) == -1)
|
option_name(code)) == -1)
|
||||||
return;
|
return;
|
||||||
|
@ -174,10 +174,10 @@ unsigned char *alloc_dhcp_client_id_option(unsigned char type,
|
|||||||
return alloc_option(DHCP_CLIENT_ID, data, sizeof data);
|
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.
|
// of the option data.
|
||||||
static uint8_t *do_get_option(uint8_t *buf, ssize_t buflen, int code,
|
static uint8_t *do_get_option_data(uint8_t *buf, ssize_t buflen, int code,
|
||||||
char *overload, ssize_t *optlen)
|
char *overload, ssize_t *optlen)
|
||||||
{
|
{
|
||||||
/* option bytes: [code][len]([data1][data2]..[dataLEN]) */
|
/* option bytes: [code][len]([data1][data2]..[dataLEN]) */
|
||||||
*overload = 0;
|
*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)
|
// Get an option with bounds checking (warning, result is not aligned)
|
||||||
// optlen will be equal to the length of the option data.
|
// 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;
|
uint8_t *option, *buf;
|
||||||
ssize_t buflen;
|
ssize_t buflen;
|
||||||
@ -230,40 +230,45 @@ uint8_t *get_option(struct dhcpMessage *packet, int code, ssize_t *optlen)
|
|||||||
buf = packet->options;
|
buf = packet->options;
|
||||||
buflen = sizeof 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)
|
if (option)
|
||||||
return option;
|
return option;
|
||||||
|
|
||||||
if (overload & 1) {
|
if (overload & 1) {
|
||||||
parsed_ff = 1;
|
parsed_ff = 1;
|
||||||
option = do_get_option(packet->file, sizeof packet->file,
|
option = do_get_option_data(packet->file, sizeof packet->file,
|
||||||
code, &overload, optlen);
|
code, &overload, optlen);
|
||||||
if (option)
|
if (option)
|
||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
if (overload & 2) {
|
if (overload & 2) {
|
||||||
option = do_get_option(packet->sname, sizeof packet->sname,
|
option = do_get_option_data(packet->sname, sizeof packet->sname,
|
||||||
code, &overload, optlen);
|
code, &overload, optlen);
|
||||||
if (option)
|
if (option)
|
||||||
return option;
|
return option;
|
||||||
if (!parsed_ff && overload & 1)
|
if (!parsed_ff && overload & 1)
|
||||||
option = do_get_option(packet->file, sizeof packet->file,
|
option = do_get_option_data(packet->file, sizeof packet->file,
|
||||||
code, &overload, optlen);
|
code, &overload, optlen);
|
||||||
}
|
}
|
||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the position of the 'end' 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;
|
int i = 0;
|
||||||
|
while (i < bufsize && optbuf[i] != DHCP_END) {
|
||||||
while (i < DHCP_OPTIONS_BUFSIZE && optionptr[i] != DHCP_END) {
|
if (optbuf[i] != DHCP_PADDING)
|
||||||
if (optionptr[i] != DHCP_PADDING)
|
i += optbuf[i+1] + 2;
|
||||||
i += optionptr[i + OPT_LEN] + OPT_DATA - 1;
|
else
|
||||||
i++;
|
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) */
|
* code, length, then data) */
|
||||||
int add_option_string(unsigned char *optionptr, unsigned char *string)
|
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 */
|
/* end position + string length + option code/length + end option */
|
||||||
if (end + string[OPT_LEN] + 2 + 1 >= DHCP_OPTIONS_BUFSIZE) {
|
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. */
|
/* checking here because it goes towards the head of the packet. */
|
||||||
void add_requests(struct dhcpMessage *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;
|
int i, len = 0;
|
||||||
|
|
||||||
packet->options[end + OPT_CODE] = DHCP_PARAM_REQ;
|
packet->options[end + OPT_CODE] = DHCP_PARAM_REQ;
|
||||||
|
@ -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 *alloc_dhcp_client_id_option(unsigned char type,
|
||||||
unsigned char *idstr, size_t idstrlen);
|
unsigned char *idstr, size_t idstrlen);
|
||||||
|
|
||||||
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);
|
||||||
int end_option(uint8_t *optionptr);
|
int get_end_option_idx(uint8_t *optbuf, size_t bufsize);
|
||||||
int add_option_string(unsigned char *optionptr, unsigned char *string);
|
int add_option_string(unsigned char *optionptr, unsigned char *string);
|
||||||
int add_simple_option(unsigned char *optionptr, unsigned char code, uint32_t data);
|
int add_simple_option(unsigned char *optionptr, unsigned char code, uint32_t data);
|
||||||
|
|
||||||
|
@ -105,7 +105,8 @@ int raw_packet(struct dhcpMessage *payload, uint32_t source_ip,
|
|||||||
* In order to work with those buggy servers,
|
* In order to work with those buggy servers,
|
||||||
* we truncate packets after end option byte.
|
* 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.protocol = IPPROTO_UDP;
|
||||||
packet.ip.saddr = source_ip;
|
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)
|
if (connect(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1)
|
||||||
goto out_fd;
|
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);
|
result = safe_write(fd, (const char *)payload, DHCP_SIZE - padding);
|
||||||
if (result == -1)
|
if (result == -1)
|
||||||
log_error("kernel_packet: write failed: %s", strerror(errno));
|
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;
|
ssize_t optlen;
|
||||||
/* Must be a DHCPOFFER to one of our xid's */
|
/* Must be a DHCPOFFER to one of our xid's */
|
||||||
if (*message == DHCPOFFER) {
|
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 to a temp buffer to force alignment */
|
||||||
memcpy(&cs->serverAddr, temp, 4);
|
memcpy(&cs->serverAddr, temp, 4);
|
||||||
cs->xid = packet->xid;
|
cs->xid = packet->xid;
|
||||||
@ -233,7 +235,7 @@ static void dhcp_ack_or_nak_packet(struct client_state_t *cs,
|
|||||||
unsigned char *temp = NULL;
|
unsigned char *temp = NULL;
|
||||||
ssize_t optlen;
|
ssize_t optlen;
|
||||||
if (*message == DHCPACK) {
|
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.");
|
log_line("No lease time received, assuming 1h.");
|
||||||
cs->lease = 60 * 60;
|
cs->lease = 60 * 60;
|
||||||
} else {
|
} else {
|
||||||
@ -293,7 +295,8 @@ void handle_packet(struct client_state_t *cs)
|
|||||||
return;
|
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");
|
log_line("couldnt get option from packet -- ignoring");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user