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
|
||||
* 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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user