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