2011-03-31 01:27:01 +05:30
|
|
|
/* options.c - DHCP options handling
|
|
|
|
*
|
2017-01-12 17:00:44 +05:30
|
|
|
* Copyright (c) 2004-2017 Nicholas J. Kain <njkain at gmail dot com>
|
2011-07-25 12:00:57 +05:30
|
|
|
* All rights reserved.
|
2011-03-31 01:27:01 +05:30
|
|
|
*
|
2011-07-25 12:00:57 +05:30
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
2011-03-31 01:27:01 +05:30
|
|
|
*
|
2011-07-25 12:00:57 +05:30
|
|
|
* - Redistributions of source code must retain the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer.
|
2011-03-31 01:27:01 +05:30
|
|
|
*
|
2011-07-25 12:00:57 +05:30
|
|
|
* - Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
|
|
* and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
2010-11-12 14:32:18 +05:30
|
|
|
*/
|
2010-11-13 01:03:17 +05:30
|
|
|
|
2010-11-12 14:32:18 +05:30
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2011-09-02 11:42:51 +05:30
|
|
|
#include <arpa/inet.h>
|
2014-03-31 02:32:48 +05:30
|
|
|
#include "nk/log.h"
|
2010-11-12 14:32:18 +05:30
|
|
|
|
|
|
|
#include "options.h"
|
2011-03-30 16:35:00 +05:30
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
static int do_overload_value(const uint8_t *buf, ssize_t blen, int overload)
|
2010-11-12 14:32:18 +05:30
|
|
|
{
|
2011-07-27 17:09:45 +05:30
|
|
|
ssize_t i = 0;
|
|
|
|
while (i < blen) {
|
|
|
|
if (buf[i] == DCODE_PADDING) {
|
|
|
|
++i;
|
2011-03-31 02:05:23 +05:30
|
|
|
continue;
|
|
|
|
}
|
2011-07-27 17:09:45 +05:30
|
|
|
if (buf[i] == DCODE_END)
|
|
|
|
break;
|
|
|
|
if (i >= blen - 2)
|
|
|
|
break;
|
|
|
|
if (buf[i] == DCODE_OVERLOAD) {
|
|
|
|
if (buf[i+1] == 1) {
|
|
|
|
overload |= buf[i+2];
|
|
|
|
i += 3;
|
|
|
|
continue;
|
|
|
|
}
|
2011-03-31 02:05:23 +05:30
|
|
|
}
|
2011-07-27 17:09:45 +05:30
|
|
|
i += buf[i+1] + 2;
|
|
|
|
}
|
|
|
|
return overload;
|
|
|
|
}
|
2011-03-31 02:05:23 +05:30
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
static int overload_value(const struct dhcpmsg * const packet)
|
2011-07-27 17:09:45 +05:30
|
|
|
{
|
|
|
|
int ol = do_overload_value(packet->options, sizeof packet->options, 0);
|
|
|
|
if (ol & 1 && ol & 2)
|
|
|
|
return ol;
|
|
|
|
if (ol & 1) {
|
|
|
|
ol |= do_overload_value(packet->file, sizeof packet->file, ol);
|
|
|
|
return ol;
|
|
|
|
}
|
|
|
|
if (ol & 2) {
|
|
|
|
ol |= do_overload_value(packet->sname, sizeof packet->sname, ol);
|
|
|
|
return ol;
|
|
|
|
}
|
|
|
|
return ol; // ol == 0
|
|
|
|
}
|
2011-03-31 02:05:23 +05:30
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
static void do_get_dhcp_opt(const uint8_t *sbuf, ssize_t slen, uint8_t code,
|
|
|
|
uint8_t *dbuf, ssize_t dlen, ssize_t *didx)
|
2011-07-27 17:09:45 +05:30
|
|
|
{
|
|
|
|
ssize_t i = 0;
|
|
|
|
while (i < slen) {
|
|
|
|
if (sbuf[i] == DCODE_PADDING) {
|
|
|
|
++i;
|
|
|
|
continue;
|
2011-03-31 02:05:23 +05:30
|
|
|
}
|
2011-07-27 17:09:45 +05:30
|
|
|
if (sbuf[i] == DCODE_END)
|
|
|
|
break;
|
|
|
|
if (i >= slen - 2)
|
|
|
|
break;
|
2014-03-12 23:00:55 +05:30
|
|
|
ssize_t soptsiz = sbuf[i+1];
|
2011-07-27 17:09:45 +05:30
|
|
|
if (sbuf[i] == code) {
|
2014-05-11 07:02:15 +05:30
|
|
|
if (dlen - *didx < soptsiz)
|
|
|
|
return;
|
2014-03-12 23:00:55 +05:30
|
|
|
if (slen - i - 2 < soptsiz)
|
2014-05-11 07:02:15 +05:30
|
|
|
return;
|
|
|
|
memcpy(dbuf + *didx, sbuf+i+2, soptsiz);
|
|
|
|
*didx += soptsiz;
|
2011-03-31 02:05:23 +05:30
|
|
|
}
|
2014-03-12 23:00:55 +05:30
|
|
|
i += soptsiz + 2;
|
2011-03-31 02:05:23 +05:30
|
|
|
}
|
2010-11-12 14:32:18 +05:30
|
|
|
}
|
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
ssize_t get_dhcp_opt(const struct dhcpmsg * const packet, uint8_t code,
|
|
|
|
uint8_t *dbuf, ssize_t dlen)
|
2011-03-30 19:05:17 +05:30
|
|
|
{
|
2011-07-27 17:09:45 +05:30
|
|
|
int ol = overload_value(packet);
|
2014-05-11 07:02:15 +05:30
|
|
|
ssize_t didx = 0;
|
|
|
|
do_get_dhcp_opt(packet->options, sizeof packet->options, code,
|
|
|
|
dbuf, dlen, &didx);
|
2011-07-27 17:09:45 +05:30
|
|
|
if (ol & 1)
|
2014-05-11 07:02:15 +05:30
|
|
|
do_get_dhcp_opt(packet->file, sizeof packet->file, code,
|
|
|
|
dbuf, dlen, &didx);
|
2011-07-27 17:09:45 +05:30
|
|
|
if (ol & 2)
|
2014-05-11 07:02:15 +05:30
|
|
|
do_get_dhcp_opt(packet->sname, sizeof packet->sname, code,
|
|
|
|
dbuf, dlen, &didx);
|
2011-07-27 17:09:45 +05:30
|
|
|
return didx;
|
2011-03-30 19:05:17 +05:30
|
|
|
}
|
|
|
|
|
2011-06-28 00:49:54 +05:30
|
|
|
// return the position of the 'end' option
|
2015-02-14 12:44:30 +05:30
|
|
|
ssize_t get_end_option_idx(const struct dhcpmsg * const packet)
|
2010-11-12 14:32:18 +05:30
|
|
|
{
|
2011-06-28 00:49:54 +05:30
|
|
|
for (size_t i = 0; i < sizeof packet->options; ++i) {
|
2011-07-25 12:41:47 +05:30
|
|
|
if (packet->options[i] == DCODE_END)
|
2011-03-31 02:05:23 +05:30
|
|
|
return i;
|
2011-07-25 12:41:47 +05:30
|
|
|
if (packet->options[i] == DCODE_PADDING)
|
2011-03-31 02:05:23 +05:30
|
|
|
continue;
|
2014-03-18 11:08:58 +05:30
|
|
|
if (i + 1 >= sizeof packet->options)
|
|
|
|
break;
|
|
|
|
i += packet->options[i+1] + 1;
|
2011-03-31 02:05:23 +05:30
|
|
|
}
|
2011-07-25 12:41:47 +05:30
|
|
|
log_warning("get_end_option_idx: Did not find DCODE_END marker.");
|
2011-03-31 02:05:23 +05:30
|
|
|
return -1;
|
2010-11-12 14:32:18 +05:30
|
|
|
}
|
|
|
|
|
2011-07-26 16:13:12 +05:30
|
|
|
static inline size_t sizeof_option_str(uint8_t code, size_t datalen)
|
2011-07-26 15:54:30 +05:30
|
|
|
{
|
|
|
|
if (code == DCODE_PADDING || code == DCODE_END)
|
|
|
|
return 1;
|
|
|
|
return 2 + datalen;
|
|
|
|
}
|
|
|
|
|
2011-07-26 16:13:12 +05:30
|
|
|
// Add a raw data string to the options. It will take a binary string suitable
|
|
|
|
// for use with eg memcpy() and will append it to the options[] field of
|
|
|
|
// a dhcp packet with the requested option code and proper length specifier.
|
2015-02-14 12:44:30 +05:30
|
|
|
size_t add_option_string(struct dhcpmsg *packet, uint8_t code,
|
|
|
|
const char * const str, size_t slen)
|
2010-11-12 14:32:18 +05:30
|
|
|
{
|
2011-07-26 16:13:12 +05:30
|
|
|
size_t len = sizeof_option_str(code, slen);
|
2011-07-02 13:18:08 +05:30
|
|
|
if (slen > 255 || len != slen + 2) {
|
|
|
|
log_warning("add_option_string: Length checks failed.");
|
|
|
|
return 0;
|
|
|
|
}
|
2011-03-31 02:05:23 +05:30
|
|
|
|
2011-07-02 14:15:11 +05:30
|
|
|
ssize_t end = get_end_option_idx(packet);
|
2014-03-11 04:30:08 +05:30
|
|
|
if (end < 0) {
|
2011-07-25 12:41:47 +05:30
|
|
|
log_warning("add_option_string: Buffer has no DCODE_END marker.");
|
2011-03-31 02:05:23 +05:30
|
|
|
return 0;
|
|
|
|
}
|
2011-07-02 13:18:08 +05:30
|
|
|
if (end + len >= sizeof packet->options) {
|
2011-07-12 09:21:55 +05:30
|
|
|
log_warning("add_option_string: No space for option 0x%02x.", code);
|
2011-03-31 02:05:23 +05:30
|
|
|
return 0;
|
|
|
|
}
|
2011-07-02 13:18:08 +05:30
|
|
|
packet->options[end] = code;
|
|
|
|
packet->options[end+1] = slen;
|
|
|
|
memcpy(packet->options + end + 2, str, slen);
|
2011-07-25 12:41:47 +05:30
|
|
|
packet->options[end+len] = DCODE_END;
|
2011-07-02 13:18:08 +05:30
|
|
|
return len;
|
2010-11-12 14:32:18 +05:30
|
|
|
}
|
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
static ssize_t add_option_check(struct dhcpmsg *packet, uint8_t code,
|
2011-07-02 14:15:11 +05:30
|
|
|
uint8_t rlen)
|
2010-11-12 14:32:18 +05:30
|
|
|
{
|
2011-07-02 14:15:11 +05:30
|
|
|
ssize_t end = get_end_option_idx(packet);
|
2014-03-11 04:30:08 +05:30
|
|
|
if (end < 0) {
|
2011-07-25 12:41:47 +05:30
|
|
|
log_warning("add_u%01u_option: Buffer has no DCODE_END marker.", rlen*8);
|
2011-07-02 14:15:11 +05:30
|
|
|
return -1;
|
2011-03-31 02:05:23 +05:30
|
|
|
}
|
2014-03-11 04:30:08 +05:30
|
|
|
if ((size_t)end + 2 + rlen >= sizeof packet->options) {
|
2011-07-12 09:21:55 +05:30
|
|
|
log_warning("add_u%01u_option: No space for option 0x%02x.",
|
2011-07-02 14:15:11 +05:30
|
|
|
rlen*8, code);
|
|
|
|
return -1;
|
2011-07-02 13:18:08 +05:30
|
|
|
}
|
2011-07-02 14:15:11 +05:30
|
|
|
return end;
|
|
|
|
}
|
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
static size_t add_u8_option(struct dhcpmsg *packet, uint8_t code, uint8_t data)
|
2011-07-02 14:15:11 +05:30
|
|
|
{
|
|
|
|
ssize_t end = add_option_check(packet, code, 1);
|
|
|
|
if (end < 0)
|
|
|
|
return 0;
|
|
|
|
packet->options[end] = code;
|
|
|
|
packet->options[end+1] = 1;
|
|
|
|
packet->options[end+2] = data;
|
2011-07-25 12:41:47 +05:30
|
|
|
packet->options[end+3] = DCODE_END;
|
2011-07-02 14:15:11 +05:30
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
2014-03-18 11:21:58 +05:30
|
|
|
#ifndef NDHS_BUILD
|
2011-07-02 14:15:11 +05:30
|
|
|
// Data should be in network byte order.
|
2015-02-14 12:44:30 +05:30
|
|
|
static size_t add_u16_option(struct dhcpmsg *packet, uint8_t code,
|
2011-07-26 09:04:32 +05:30
|
|
|
uint16_t data)
|
2011-07-02 14:15:11 +05:30
|
|
|
{
|
|
|
|
ssize_t end = add_option_check(packet, code, 2);
|
|
|
|
if (end < 0)
|
|
|
|
return 0;
|
|
|
|
uint8_t *dp = (uint8_t *)&data;
|
|
|
|
packet->options[end] = code;
|
|
|
|
packet->options[end+1] = 2;
|
|
|
|
packet->options[end+2] = dp[0];
|
|
|
|
packet->options[end+3] = dp[1];
|
2011-07-25 12:41:47 +05:30
|
|
|
packet->options[end+4] = DCODE_END;
|
2011-07-02 14:15:11 +05:30
|
|
|
return 4;
|
|
|
|
}
|
2014-03-18 11:21:58 +05:30
|
|
|
#endif
|
2011-07-02 14:15:11 +05:30
|
|
|
|
|
|
|
// Data should be in network byte order.
|
2015-02-14 12:44:30 +05:30
|
|
|
size_t add_u32_option(struct dhcpmsg *packet, uint8_t code, uint32_t data)
|
2011-07-02 14:15:11 +05:30
|
|
|
{
|
|
|
|
ssize_t end = add_option_check(packet, code, 4);
|
|
|
|
if (end < 0)
|
|
|
|
return 0;
|
|
|
|
uint8_t *dp = (uint8_t *)&data;
|
2011-07-02 13:18:08 +05:30
|
|
|
packet->options[end] = code;
|
2011-07-02 14:15:11 +05:30
|
|
|
packet->options[end+1] = 4;
|
|
|
|
packet->options[end+2] = dp[0];
|
|
|
|
packet->options[end+3] = dp[1];
|
|
|
|
packet->options[end+4] = dp[2];
|
|
|
|
packet->options[end+5] = dp[3];
|
2011-07-25 12:41:47 +05:30
|
|
|
packet->options[end+6] = DCODE_END;
|
2011-07-02 14:15:11 +05:30
|
|
|
return 6;
|
2010-11-12 14:32:18 +05:30
|
|
|
}
|
|
|
|
|
2011-07-26 16:13:12 +05:30
|
|
|
// Add a parameter request list for stubborn DHCP servers
|
2015-02-14 12:44:30 +05:30
|
|
|
size_t add_option_request_list(struct dhcpmsg *packet)
|
2011-03-30 16:56:42 +05:30
|
|
|
{
|
2011-07-26 11:28:05 +05:30
|
|
|
static const uint8_t reqdata[] = {
|
|
|
|
DCODE_SUBNET, DCODE_ROUTER, DCODE_DNS, DCODE_HOSTNAME, DCODE_DOMAIN,
|
|
|
|
DCODE_BROADCAST,
|
|
|
|
};
|
|
|
|
return add_option_string(packet, DCODE_PARAM_REQ,
|
|
|
|
(char *)reqdata, sizeof reqdata);
|
2011-07-01 21:07:13 +05:30
|
|
|
}
|
|
|
|
|
2014-03-19 15:30:45 +05:30
|
|
|
#ifdef NDHS_BUILD
|
2015-02-14 12:44:30 +05:30
|
|
|
size_t add_option_domain_name(struct dhcpmsg *packet, const char * const dom,
|
|
|
|
size_t domlen)
|
2011-09-02 11:42:51 +05:30
|
|
|
{
|
|
|
|
return add_option_string(packet, DCODE_DOMAIN, dom, domlen);
|
|
|
|
}
|
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
void add_option_subnet_mask(struct dhcpmsg *packet, uint32_t subnet)
|
2011-09-02 11:42:51 +05:30
|
|
|
{
|
|
|
|
add_u32_option(packet, DCODE_SUBNET, subnet);
|
|
|
|
}
|
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
void add_option_broadcast(struct dhcpmsg *packet, uint32_t bc)
|
2011-09-02 11:42:51 +05:30
|
|
|
{
|
|
|
|
add_u32_option(packet, DCODE_BROADCAST, bc);
|
|
|
|
}
|
2014-03-19 15:30:45 +05:30
|
|
|
#endif
|
2011-09-02 11:42:51 +05:30
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
void add_option_msgtype(struct dhcpmsg *packet, uint8_t type)
|
2011-07-26 09:04:32 +05:30
|
|
|
{
|
|
|
|
add_u8_option(packet, DCODE_MSGTYPE, type);
|
|
|
|
}
|
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
void add_option_reqip(struct dhcpmsg *packet, uint32_t ip)
|
2011-07-26 09:04:32 +05:30
|
|
|
{
|
|
|
|
add_u32_option(packet, DCODE_REQIP, ip);
|
|
|
|
}
|
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
void add_option_serverid(struct dhcpmsg *packet, uint32_t sid)
|
2011-07-26 09:04:32 +05:30
|
|
|
{
|
2011-09-02 11:42:51 +05:30
|
|
|
add_u32_option(packet, DCODE_SERVER_ID, sid);
|
2011-07-26 09:04:32 +05:30
|
|
|
}
|
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
void add_option_clientid(struct dhcpmsg *packet, const char * const clientid,
|
2014-03-18 13:08:32 +05:30
|
|
|
size_t clen)
|
2014-03-18 12:43:51 +05:30
|
|
|
{
|
|
|
|
add_option_string(packet, DCODE_CLIENT_ID, clientid, clen);
|
|
|
|
}
|
|
|
|
|
2011-09-02 11:42:51 +05:30
|
|
|
#ifndef NDHS_BUILD
|
2015-02-14 12:44:30 +05:30
|
|
|
void add_option_maxsize(struct dhcpmsg *packet)
|
2011-07-26 09:04:32 +05:30
|
|
|
{
|
2011-09-02 11:42:51 +05:30
|
|
|
add_u16_option(packet, DCODE_MAX_SIZE,
|
|
|
|
htons(sizeof(struct ip_udp_dhcp_packet)));
|
2011-07-26 09:04:32 +05:30
|
|
|
}
|
|
|
|
|
2015-02-20 14:28:25 +05:30
|
|
|
void add_option_vendor(struct dhcpmsg *packet, const char * const vendor,
|
|
|
|
size_t vsize)
|
2011-07-26 09:18:35 +05:30
|
|
|
{
|
2015-02-20 14:28:25 +05:30
|
|
|
if (vsize)
|
|
|
|
add_option_string(packet, DCODE_VENDOR, vendor, vsize);
|
2011-07-26 09:18:35 +05:30
|
|
|
}
|
|
|
|
|
2015-02-20 14:28:25 +05:30
|
|
|
void add_option_hostname(struct dhcpmsg *packet, const char * const hostname,
|
|
|
|
size_t hsize)
|
2011-07-26 09:18:35 +05:30
|
|
|
{
|
2015-02-20 14:28:25 +05:30
|
|
|
if (hsize)
|
|
|
|
add_option_string(packet, DCODE_HOSTNAME, hostname, hsize);
|
2011-07-26 09:18:35 +05:30
|
|
|
}
|
2011-09-02 11:42:51 +05:30
|
|
|
#endif
|
2011-07-26 09:18:35 +05:30
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
uint32_t get_option_router(const struct dhcpmsg * const packet)
|
2011-07-26 10:34:59 +05:30
|
|
|
{
|
|
|
|
ssize_t ol;
|
|
|
|
uint32_t ret = 0;
|
2011-07-27 17:09:45 +05:30
|
|
|
uint8_t buf[MAX_DOPT_SIZE];
|
|
|
|
ol = get_dhcp_opt(packet, DCODE_ROUTER, buf, sizeof buf);
|
2011-07-26 10:34:59 +05:30
|
|
|
if (ol == sizeof ret)
|
2011-07-27 17:09:45 +05:30
|
|
|
memcpy(&ret, buf, sizeof ret);
|
2011-07-26 10:34:59 +05:30
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
uint8_t get_option_msgtype(const struct dhcpmsg * const packet)
|
2011-07-26 10:34:59 +05:30
|
|
|
{
|
|
|
|
ssize_t ol;
|
|
|
|
uint8_t ret = 0;
|
2011-07-27 17:09:45 +05:30
|
|
|
uint8_t buf[MAX_DOPT_SIZE];
|
|
|
|
ol = get_dhcp_opt(packet, DCODE_MSGTYPE, buf, sizeof buf);
|
|
|
|
if (ol == sizeof ret)
|
|
|
|
ret = buf[0];
|
2011-07-26 10:34:59 +05:30
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
uint32_t get_option_serverid(const struct dhcpmsg *const packet, int *found)
|
2011-07-26 10:34:59 +05:30
|
|
|
{
|
|
|
|
ssize_t ol;
|
|
|
|
uint32_t ret = 0;
|
2011-07-27 17:09:45 +05:30
|
|
|
uint8_t buf[MAX_DOPT_SIZE];
|
2011-07-26 10:34:59 +05:30
|
|
|
*found = 0;
|
2011-07-27 17:09:45 +05:30
|
|
|
ol = get_dhcp_opt(packet, DCODE_SERVER_ID, buf, sizeof buf);
|
2011-07-26 10:34:59 +05:30
|
|
|
if (ol == sizeof ret) {
|
|
|
|
*found = 1;
|
2011-07-27 17:09:45 +05:30
|
|
|
memcpy(&ret, buf, sizeof ret);
|
2011-07-26 10:34:59 +05:30
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-02-14 12:44:30 +05:30
|
|
|
uint32_t get_option_leasetime(const struct dhcpmsg * const packet)
|
2011-07-26 10:34:59 +05:30
|
|
|
{
|
|
|
|
ssize_t ol;
|
|
|
|
uint32_t ret = 0;
|
2011-07-27 17:09:45 +05:30
|
|
|
uint8_t buf[MAX_DOPT_SIZE];
|
|
|
|
ol = get_dhcp_opt(packet, DCODE_LEASET, buf, sizeof buf);
|
2011-07-26 10:34:59 +05:30
|
|
|
if (ol == sizeof ret) {
|
2011-07-27 17:09:45 +05:30
|
|
|
memcpy(&ret, buf, sizeof ret);
|
2011-07-26 10:34:59 +05:30
|
|
|
ret = ntohl(ret);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2014-03-18 12:43:51 +05:30
|
|
|
|
|
|
|
// Returned buffer is not nul-terminated.
|
2015-02-14 12:44:30 +05:30
|
|
|
size_t get_option_clientid(const struct dhcpmsg * const packet, char *cbuf,
|
|
|
|
size_t clen)
|
2014-03-18 12:43:51 +05:30
|
|
|
{
|
|
|
|
if (clen < 1)
|
|
|
|
return 0;
|
|
|
|
ssize_t ol = get_dhcp_opt(packet, DCODE_CLIENT_ID,
|
|
|
|
(uint8_t *)cbuf, clen);
|
|
|
|
return ol > 0 ? ol : 0;
|
|
|
|
}
|
2015-02-14 12:44:30 +05:30
|
|
|
|