Print this page
7388 Support DHCP Client FQDN. Allow IAID/DUID for all v4.
*** 19,28 ****
--- 19,29 ----
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
*/
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
*** 411,448 ****
void *
add_pkt_opt(dhcp_pkt_t *dpkt, uint_t opt_type, const void *opt_val,
uint_t opt_len)
{
uchar_t *raw_pkt;
! int req_len;
void *optr;
raw_pkt = (uchar_t *)dpkt->pkt;
optr = raw_pkt + dpkt->pkt_cur_len;
if (dpkt->pkt_isv6) {
! dhcpv6_option_t d6o;
- req_len = opt_len + sizeof (d6o);
-
if (dpkt->pkt_cur_len + req_len > dpkt->pkt_max_len) {
dhcpmsg(MSG_WARNING,
"add_pkt_opt: not enough room for v6 option %u in "
"packet (%u + %u > %u)", opt_type,
dpkt->pkt_cur_len, req_len, dpkt->pkt_max_len);
return (NULL);
}
- d6o.d6o_code = htons(opt_type);
- d6o.d6o_len = htons(opt_len);
- (void) memcpy(&raw_pkt[dpkt->pkt_cur_len], &d6o, sizeof (d6o));
- dpkt->pkt_cur_len += sizeof (d6o);
- if (opt_len > 0) {
- (void) memcpy(&raw_pkt[dpkt->pkt_cur_len], opt_val,
- opt_len);
- dpkt->pkt_cur_len += opt_len;
- }
} else {
! req_len = opt_len + 2; /* + 2 for code & length bytes */
/* CD_END and CD_PAD options don't have a length field */
if (opt_type == CD_END || opt_type == CD_PAD) {
req_len = 1;
} else if (opt_val == NULL) {
--- 412,438 ----
void *
add_pkt_opt(dhcp_pkt_t *dpkt, uint_t opt_type, const void *opt_val,
uint_t opt_len)
{
uchar_t *raw_pkt;
! size_t req_len;
void *optr;
raw_pkt = (uchar_t *)dpkt->pkt;
optr = raw_pkt + dpkt->pkt_cur_len;
if (dpkt->pkt_isv6) {
! req_len = opt_len + sizeof (dhcpv6_option_t);
if (dpkt->pkt_cur_len + req_len > dpkt->pkt_max_len) {
dhcpmsg(MSG_WARNING,
"add_pkt_opt: not enough room for v6 option %u in "
"packet (%u + %u > %u)", opt_type,
dpkt->pkt_cur_len, req_len, dpkt->pkt_max_len);
return (NULL);
}
} else {
! req_len = opt_len + DHCP_OPT_META_LEN;
/* CD_END and CD_PAD options don't have a length field */
if (opt_type == CD_END || opt_type == CD_PAD) {
req_len = 1;
} else if (opt_val == NULL) {
*** 455,477 ****
dhcpmsg(MSG_WARNING,
"add_pkt_opt: not enough room for v4 option %u in "
"packet", opt_type);
return (NULL);
}
! raw_pkt[dpkt->pkt_cur_len++] = opt_type;
! if (req_len > 1) {
! raw_pkt[dpkt->pkt_cur_len++] = opt_len;
! if (opt_len > 0) {
! (void) memcpy(&raw_pkt[dpkt->pkt_cur_len],
! opt_val, opt_len);
! dpkt->pkt_cur_len += opt_len;
}
}
}
! return (optr);
}
/*
* add_pkt_subopt(): adds an option to a dhcp_pkt_t option. DHCPv6-specific,
* but could be extended to IPv4 DHCP if necessary. Assumes
--- 445,510 ----
dhcpmsg(MSG_WARNING,
"add_pkt_opt: not enough room for v4 option %u in "
"packet", opt_type);
return (NULL);
}
+ }
! req_len = encode_dhcp_opt(&raw_pkt[dpkt->pkt_cur_len], dpkt->pkt_isv6,
! opt_type, opt_val, opt_len);
! dpkt->pkt_cur_len += req_len;
! return (optr);
! }
!
! /*
! * encode_dhcp_opt(): sets the fields of an allocated DHCP option buffer
! *
! * input: void *: the buffer allocated for enough space for
! * (DHCPv6) dhcpv6_option_t and value, or for (DHCPv4) opt_type +
! * length + value (length/value are skipped for CD_END or
! * CD_PAD);
! * boolean_t: a value indicating whether DHCPv6 or not;
! * uint_t: the type of option being added;
! * const void *: the value of that option;
! * uint_t: the length of the value of the option
! * output: size_t: the number of bytes written starting at opt.
! */
!
! size_t
! encode_dhcp_opt(void *dopt, boolean_t isv6, uint_t opt_type,
! const void *opt_val, uint_t opt_len)
! {
! boolean_t do_copy_value = B_FALSE;
! size_t res_len = 0;
! uint8_t *pval;
!
! if (isv6) {
! dhcpv6_option_t d6o;
! d6o.d6o_code = htons(opt_type);
! d6o.d6o_len = htons(opt_len);
! (void) memcpy(dopt, &d6o, sizeof (d6o));
! res_len += sizeof (d6o);
!
! do_copy_value = B_TRUE;
! } else {
! pval = (uint8_t *)dopt;
! pval[res_len++] = opt_type;
!
! if (opt_type != CD_END && opt_type != CD_PAD) {
! pval[res_len++] = opt_len;
! do_copy_value = B_TRUE;
}
}
+
+ pval = (uint8_t *)dopt + res_len;
+ if (do_copy_value && opt_len > 0) {
+ (void) memcpy(pval, opt_val, opt_len);
+ res_len += opt_len;
}
!
! return (res_len);
}
/*
* add_pkt_subopt(): adds an option to a dhcp_pkt_t option. DHCPv6-specific,
* but could be extended to IPv4 DHCP if necessary. Assumes