Print this page
7388 Support DHCP Client FQDN. Allow IAID/DUID for all v4.


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.

  24  */
  25 
  26 #include <string.h>
  27 #include <sys/types.h>
  28 #include <stdlib.h>
  29 #include <dhcpmsg.h>
  30 #include <stddef.h>
  31 #include <assert.h>
  32 #include <search.h>
  33 #include <alloca.h>
  34 #include <limits.h>
  35 #include <stropts.h>
  36 #include <netinet/dhcp6.h>
  37 #include <arpa/inet.h>
  38 #include <sys/sysmacros.h>
  39 #include <sys/sockio.h>
  40 #include <inet/ip6_asp.h>
  41 
  42 #include "states.h"
  43 #include "interface.h"


 396                 (void) memcpy(opt, &optval, sizeof (optval));
 397                 return (B_TRUE);
 398         }
 399 }
 400 
 401 /*
 402  * add_pkt_opt(): adds an option to a dhcp_pkt_t
 403  *
 404  *   input: dhcp_pkt_t *: the packet to add the option to
 405  *          uint_t: the type of option being added
 406  *          const void *: the value of that option
 407  *          uint_t: the length of the value of the option
 408  *  output: void *: pointer to the option that was added, or NULL on failure.
 409  */
 410 
 411 void *
 412 add_pkt_opt(dhcp_pkt_t *dpkt, uint_t opt_type, const void *opt_val,
 413     uint_t opt_len)
 414 {
 415         uchar_t         *raw_pkt;
 416         int             req_len;
 417         void            *optr;
 418 
 419         raw_pkt = (uchar_t *)dpkt->pkt;
 420         optr = raw_pkt + dpkt->pkt_cur_len;
 421         if (dpkt->pkt_isv6) {
 422                 dhcpv6_option_t d6o;
 423 
 424                 req_len = opt_len + sizeof (d6o);
 425 
 426                 if (dpkt->pkt_cur_len + req_len > dpkt->pkt_max_len) {
 427                         dhcpmsg(MSG_WARNING,
 428                             "add_pkt_opt: not enough room for v6 option %u in "
 429                             "packet (%u + %u > %u)", opt_type,
 430                             dpkt->pkt_cur_len, req_len, dpkt->pkt_max_len);
 431                         return (NULL);
 432                 }
 433                 d6o.d6o_code = htons(opt_type);
 434                 d6o.d6o_len = htons(opt_len);
 435                 (void) memcpy(&raw_pkt[dpkt->pkt_cur_len], &d6o, sizeof (d6o));
 436                 dpkt->pkt_cur_len += sizeof (d6o);
 437                 if (opt_len > 0) {
 438                         (void) memcpy(&raw_pkt[dpkt->pkt_cur_len], opt_val,
 439                             opt_len);
 440                         dpkt->pkt_cur_len += opt_len;
 441                 }
 442         } else {
 443                 req_len = opt_len + 2; /* + 2 for code & length bytes */
 444 
 445                 /* CD_END and CD_PAD options don't have a length field */
 446                 if (opt_type == CD_END || opt_type == CD_PAD) {
 447                         req_len = 1;
 448                 } else if (opt_val == NULL) {
 449                         dhcpmsg(MSG_ERROR, "add_pkt_opt: option type %d is "
 450                             "missing required value", opt_type);
 451                         return (NULL);
 452                 }
 453 
 454                 if ((dpkt->pkt_cur_len + req_len) > dpkt->pkt_max_len) {
 455                         dhcpmsg(MSG_WARNING,
 456                             "add_pkt_opt: not enough room for v4 option %u in "
 457                             "packet", opt_type);
 458                         return (NULL);
 459                 }

 460 
 461                 raw_pkt[dpkt->pkt_cur_len++] = opt_type;


 462 
 463                 if (req_len > 1) {
 464                         raw_pkt[dpkt->pkt_cur_len++] = opt_len;
 465                         if (opt_len > 0) {
 466                                 (void) memcpy(&raw_pkt[dpkt->pkt_cur_len],
 467                                     opt_val, opt_len);
 468                                 dpkt->pkt_cur_len += opt_len;


































 469                         }
 470                 }





 471         }
 472         return (optr);

 473 }
 474 
 475 /*
 476  * add_pkt_subopt(): adds an option to a dhcp_pkt_t option.  DHCPv6-specific,
 477  *                   but could be extended to IPv4 DHCP if necessary.  Assumes
 478  *                   that if the parent isn't a top-level option, the caller
 479  *                   will adjust any upper-level options recursively using
 480  *                   update_v6opt_len.
 481  *
 482  *   input: dhcp_pkt_t *: the packet to add the suboption to
 483  *          dhcpv6_option_t *: the start of the option to that should contain
 484  *                             it (parent)
 485  *          uint_t: the type of suboption being added
 486  *          const void *: the value of that option
 487  *          uint_t: the length of the value of the option
 488  *  output: void *: pointer to the suboption that was added, or NULL on
 489  *                  failure.
 490  */
 491 
 492 void *




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
  25  */
  26 
  27 #include <string.h>
  28 #include <sys/types.h>
  29 #include <stdlib.h>
  30 #include <dhcpmsg.h>
  31 #include <stddef.h>
  32 #include <assert.h>
  33 #include <search.h>
  34 #include <alloca.h>
  35 #include <limits.h>
  36 #include <stropts.h>
  37 #include <netinet/dhcp6.h>
  38 #include <arpa/inet.h>
  39 #include <sys/sysmacros.h>
  40 #include <sys/sockio.h>
  41 #include <inet/ip6_asp.h>
  42 
  43 #include "states.h"
  44 #include "interface.h"


 397                 (void) memcpy(opt, &optval, sizeof (optval));
 398                 return (B_TRUE);
 399         }
 400 }
 401 
 402 /*
 403  * add_pkt_opt(): adds an option to a dhcp_pkt_t
 404  *
 405  *   input: dhcp_pkt_t *: the packet to add the option to
 406  *          uint_t: the type of option being added
 407  *          const void *: the value of that option
 408  *          uint_t: the length of the value of the option
 409  *  output: void *: pointer to the option that was added, or NULL on failure.
 410  */
 411 
 412 void *
 413 add_pkt_opt(dhcp_pkt_t *dpkt, uint_t opt_type, const void *opt_val,
 414     uint_t opt_len)
 415 {
 416         uchar_t         *raw_pkt;
 417         size_t          req_len;
 418         void            *optr;
 419 
 420         raw_pkt = (uchar_t *)dpkt->pkt;
 421         optr = raw_pkt + dpkt->pkt_cur_len;
 422         if (dpkt->pkt_isv6) {
 423                 req_len = opt_len + sizeof (dhcpv6_option_t);
 424 


 425                 if (dpkt->pkt_cur_len + req_len > dpkt->pkt_max_len) {
 426                         dhcpmsg(MSG_WARNING,
 427                             "add_pkt_opt: not enough room for v6 option %u in "
 428                             "packet (%u + %u > %u)", opt_type,
 429                             dpkt->pkt_cur_len, req_len, dpkt->pkt_max_len);
 430                         return (NULL);
 431                 }









 432         } else {
 433                 req_len = opt_len + DHCP_OPT_META_LEN;
 434 
 435                 /* CD_END and CD_PAD options don't have a length field */
 436                 if (opt_type == CD_END || opt_type == CD_PAD) {
 437                         req_len = 1;
 438                 } else if (opt_val == NULL) {
 439                         dhcpmsg(MSG_ERROR, "add_pkt_opt: option type %d is "
 440                             "missing required value", opt_type);
 441                         return (NULL);
 442                 }
 443 
 444                 if ((dpkt->pkt_cur_len + req_len) > dpkt->pkt_max_len) {
 445                         dhcpmsg(MSG_WARNING,
 446                             "add_pkt_opt: not enough room for v4 option %u in "
 447                             "packet", opt_type);
 448                         return (NULL);
 449                 }
 450         }
 451 
 452         req_len = encode_dhcp_opt(&raw_pkt[dpkt->pkt_cur_len], dpkt->pkt_isv6,
 453             opt_type, opt_val, opt_len);
 454         dpkt->pkt_cur_len += req_len;
 455 
 456         return (optr);
 457 }
 458 
 459 /*
 460  * encode_dhcp_opt(): sets the fields of an allocated DHCP option buffer
 461  *
 462  *   input: void *: the buffer allocated for enough space for
 463  *                      (DHCPv6) dhcpv6_option_t and value, or for (DHCPv4) opt_type +
 464  *                      length + value (length/value are skipped for CD_END or
 465  *                      CD_PAD);
 466  *          boolean_t: a value indicating whether DHCPv6 or not;
 467  *          uint_t: the type of option being added;
 468  *          const void *: the value of that option;
 469  *          uint_t: the length of the value of the option
 470  *  output: size_t: the number of bytes written starting at opt.
 471  */
 472 
 473 size_t
 474 encode_dhcp_opt(void *dopt, boolean_t isv6, uint_t opt_type,
 475     const void *opt_val, uint_t opt_len)
 476 {
 477         boolean_t do_copy_value = B_FALSE;
 478         size_t res_len = 0;
 479         uint8_t *pval;
 480 
 481         if (isv6) {
 482                 dhcpv6_option_t d6o;
 483                 d6o.d6o_code = htons(opt_type);
 484                 d6o.d6o_len = htons(opt_len);
 485                 (void) memcpy(dopt, &d6o, sizeof (d6o));
 486                 res_len += sizeof (d6o);
 487 
 488                 do_copy_value = B_TRUE;
 489         } else {
 490                 pval = (uint8_t *)dopt;
 491                 pval[res_len++] = opt_type;
 492 
 493                 if (opt_type != CD_END && opt_type != CD_PAD) {
 494                         pval[res_len++] = opt_len;
 495                         do_copy_value = B_TRUE;
 496                 }
 497         }
 498 
 499         pval = (uint8_t *)dopt + res_len;
 500         if (do_copy_value && opt_len > 0) {
 501                 (void) memcpy(pval, opt_val, opt_len);
 502                 res_len += opt_len;
 503         }
 504 
 505         return (res_len);
 506 }
 507 
 508 /*
 509  * add_pkt_subopt(): adds an option to a dhcp_pkt_t option.  DHCPv6-specific,
 510  *                   but could be extended to IPv4 DHCP if necessary.  Assumes
 511  *                   that if the parent isn't a top-level option, the caller
 512  *                   will adjust any upper-level options recursively using
 513  *                   update_v6opt_len.
 514  *
 515  *   input: dhcp_pkt_t *: the packet to add the suboption to
 516  *          dhcpv6_option_t *: the start of the option to that should contain
 517  *                             it (parent)
 518  *          uint_t: the type of suboption being added
 519  *          const void *: the value of that option
 520  *          uint_t: the length of the value of the option
 521  *  output: void *: pointer to the suboption that was added, or NULL on
 522  *                  failure.
 523  */
 524 
 525 void *