Diff for /embedaddon/dhcp/common/options.c between versions 1.1 and 1.1.1.1

version 1.1, 2012/02/21 22:30:18 version 1.1.1.1, 2012/10/09 09:06:54
Line 3 Line 3
    DHCP options parsing and reassembly. */     DHCP options parsing and reassembly. */
   
 /*  /*
 * Copyright (c) 2004-2011 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium   * Copyright (c) 1995-2003 by Internet Software Consortium
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
Line 1677  const char *pretty_print_option (option, data, len, em Line 1677  const char *pretty_print_option (option, data, len, em
         const unsigned char *dp = data;          const unsigned char *dp = data;
         char comma;          char comma;
         unsigned long tval;          unsigned long tval;
           isc_boolean_t a_array = ISC_FALSE;
           int len_used;
   
         if (emit_commas)          if (emit_commas)
                 comma = ',';                  comma = ',';
Line 1701  const char *pretty_print_option (option, data, len, em Line 1703  const char *pretty_print_option (option, data, len, em
                 fmtbuf [l] = option -> format [i];                  fmtbuf [l] = option -> format [i];
                 switch (option -> format [i]) {                  switch (option -> format [i]) {
                       case 'a':                        case 'a':
                           a_array = ISC_TRUE;
                           /* Fall through */
                       case 'A':                        case 'A':
                         --numelem;                          --numelem;
                         fmtbuf [l] = 0;                          fmtbuf [l] = 0;
Line 1729  const char *pretty_print_option (option, data, len, em Line 1733  const char *pretty_print_option (option, data, len, em
                                 hunksize++;                                  hunksize++;
                                 comma = ':';                                  comma = ':';
                                 numhunk = 0;                                  numhunk = 0;
                                   a_array = ISC_TRUE;
                                   hunkinc = 1;
                         }                          }
                         fmtbuf [l + 1] = 0;                          fmtbuf [l + 1] = 0;
                         break;                          break;
Line 1822  const char *pretty_print_option (option, data, len, em Line 1828  const char *pretty_print_option (option, data, len, em
                       len - hunksize);                        len - hunksize);
   
         /* If this is an array, compute its size. */          /* If this is an array, compute its size. */
        if (!numhunk)        if (numhunk == 0) {
                numhunk = len / hunksize;                if (a_array == ISC_TRUE) {
        /* See if we got an exact number of hunks. */                        /*
        if (numhunk > 0 && numhunk * hunksize < len)                         * It is an 'a' type array - we repeat the
                log_error ("%s: %d extra bytes at end of array\n",                         * last format type.  A binary string for 'X'
                      option -> name,                         * is also like this.  hunkinc is the size
                      len - numhunk * hunksize);                         * of the last format type and we add 1 to
                          * cover the entire first record.
                          */
                         numhunk = ((len - hunksize) / hunkinc) + 1;
                         len_used = hunksize + ((numhunk - 1) * hunkinc);
                 } else {
                         /*
                          * It is an 'A' type array - we repeat the
                          * entire record
                          */
                         numhunk = len / hunksize;
                         len_used = numhunk * hunksize;
                 }
   
                   /* See if we got an exact number of hunks. */
                   if (len_used < len) {
                           log_error ("%s: %d extra bytes at end of array\n",
                                      option -> name,
                                      len - len_used);
                   }
           }
   
   
         /* A one-hunk array prints the same as a single hunk. */          /* A one-hunk array prints the same as a single hunk. */
         if (numhunk < 0)          if (numhunk < 0)
                 numhunk = 1;                  numhunk = 1;
   
         /* Cycle through the array (or hunk) printing the data. */          /* Cycle through the array (or hunk) printing the data. */
         for (i = 0; i < numhunk; i++) {          for (i = 0; i < numhunk; i++) {
                for (j = 0; j < numelem; j++) {                if ((a_array == ISC_TRUE) && (i != 0) && (numelem > 0)) {
                         /*
                          * For 'a' type of arrays we repeat
                          * only the last format character
                          * We should never hit the case of numelem == 0
                          * but let's include the check to be safe.
                          */
                         j = numelem - 1;
                 } else {
                         /*
                          * for other types of arrays or the first
                          * time through for 'a' types, we go through
                          * the entire set of format characters.
                          */
                         j = 0;
                 }
 
                 for (; j < numelem; j++) {
                         switch (fmtbuf [j]) {                          switch (fmtbuf [j]) {
                               case 't':                                case 't':
                                 /* endbuf-1 leaves room for NULL. */                                  /* endbuf-1 leaves room for NULL. */
Line 2353  prepare_option_buffer(struct universe *universe, struc Line 2397  prepare_option_buffer(struct universe *universe, struc
   
         /* And let go of our references. */          /* And let go of our references. */
       cleanup:        cleanup:
           if (lbp != NULL)
                   buffer_dereference(&lbp, MDL);
         option_dereference(&option, MDL);          option_dereference(&option, MDL);
   
        return 1;        return status;
 }  }
   
 static void  static void
Line 3748  void do_packet (interface, packet, len, from_port, fro Line 3794  void do_packet (interface, packet, len, from_port, fro
                         data_string_forget (&dp, MDL);                          data_string_forget (&dp, MDL);
                 }                  }
         }          }
                   
         if (decoded_packet -> packet_type)  
                 dhcp (decoded_packet);  
         else  
                 bootp (decoded_packet);  
   
           if (validate_packet(decoded_packet) != 0) {
                   if (decoded_packet->packet_type)
                           dhcp(decoded_packet);
                   else
                           bootp(decoded_packet);
           }
   
         /* If the caller kept the packet, they'll have upped the refcnt. */          /* If the caller kept the packet, they'll have upped the refcnt. */
         packet_dereference (&decoded_packet, MDL);          packet_dereference (&decoded_packet, MDL);
   
Line 3839  do_packet6(struct interface_info *interface, const cha Line 3887  do_packet6(struct interface_info *interface, const cha
         msg_type = packet[0];          msg_type = packet[0];
         if ((msg_type == DHCPV6_RELAY_FORW) ||           if ((msg_type == DHCPV6_RELAY_FORW) || 
             (msg_type == DHCPV6_RELAY_REPL)) {              (msg_type == DHCPV6_RELAY_REPL)) {
                   int relaylen = (int)(offsetof(struct dhcpv6_relay_packet, options));
                 relay = (const struct dhcpv6_relay_packet *)packet;                  relay = (const struct dhcpv6_relay_packet *)packet;
                 decoded_packet->dhcpv6_msg_type = relay->msg_type;                  decoded_packet->dhcpv6_msg_type = relay->msg_type;
   
Line 3850  do_packet6(struct interface_info *interface, const cha Line 3899  do_packet6(struct interface_info *interface, const cha
                        relay->peer_address, sizeof(relay->peer_address));                         relay->peer_address, sizeof(relay->peer_address));
   
                 if (!parse_option_buffer(decoded_packet->options,                   if (!parse_option_buffer(decoded_packet->options, 
                                         relay->options, len-sizeof(*relay),                                          relay->options, len - relaylen, 
                                          &dhcpv6_universe)) {                                           &dhcpv6_universe)) {
                         /* no logging here, as parse_option_buffer() logs all                          /* no logging here, as parse_option_buffer() logs all
                            cases where it fails */                             cases where it fails */
Line 3858  do_packet6(struct interface_info *interface, const cha Line 3907  do_packet6(struct interface_info *interface, const cha
                         return;                          return;
                 }                  }
         } else {          } else {
                   int msglen = (int)(offsetof(struct dhcpv6_packet, options));
                 msg = (const struct dhcpv6_packet *)packet;                  msg = (const struct dhcpv6_packet *)packet;
                 decoded_packet->dhcpv6_msg_type = msg->msg_type;                  decoded_packet->dhcpv6_msg_type = msg->msg_type;
   
Line 3867  do_packet6(struct interface_info *interface, const cha Line 3917  do_packet6(struct interface_info *interface, const cha
                        sizeof(decoded_packet->dhcpv6_transaction_id));                         sizeof(decoded_packet->dhcpv6_transaction_id));
   
                 if (!parse_option_buffer(decoded_packet->options,                   if (!parse_option_buffer(decoded_packet->options, 
                                         msg->options, len-sizeof(*msg),                                          msg->options, len - msglen, 
                                          &dhcpv6_universe)) {                                           &dhcpv6_universe)) {
                         /* no logging here, as parse_option_buffer() logs all                          /* no logging here, as parse_option_buffer() logs all
                            cases where it fails */                             cases where it fails */
Line 4070  add_option(struct option_state *options, Line 4120  add_option(struct option_state *options,
         return 1;          return 1;
 }  }
   
   /**
    *  Checks if received BOOTP/DHCPv4 packet is sane
    *
    * @param packet received, decoded packet
    *
    * @return 1 if packet is sane, 0 if it is not
    */
   int validate_packet(struct packet *packet)
   {
           struct option_cache *oc = NULL;
   
           oc = lookup_option (&dhcp_universe, packet->options,
                               DHO_DHCP_CLIENT_IDENTIFIER);
           if (oc) {
                   /* Let's check if client-identifier is sane */
                   if (oc->data.len == 0) {
                           log_debug("Dropped DHCPv4 packet with zero-length client-id");
                           return (0);
   
                   } else if (oc->data.len == 1) {
                           /*
                            * RFC2132, section 9.14 states that minimum length of client-id
                            * is 2.  We will allow single-character client-ids for now (for
                            * backwards compatibility), but warn the user that support for
                            * this is against the standard.
                            */
                           log_debug("Accepted DHCPv4 packet with one-character client-id - "
                                   "a future version of ISC DHCP will reject this");
                   }
           } else {
                   /* 
                    * If hlen is 0 we don't have any identifier, we warn the user
                    * but continue processing the packet as we can.
                    */
                   if (packet->raw->hlen == 0) {
                           log_debug("Received DHCPv4 packet without client-id"
                                     " option and empty hlen field.");
                   }
           }
   
           /* @todo: Add checks for other received options */
   
           return (1);
   }

Removed from v.1.1  
changed lines
  Added in v.1.1.1.1


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>