]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
[master] Add use-host-decl-names support to BOOTP
authorThomas Markwalder <tmark@isc.org>
Mon, 27 Oct 2014 19:51:36 +0000 (15:51 -0400)
committerThomas Markwalder <tmark@isc.org>
Mon, 27 Oct 2014 19:51:36 +0000 (15:51 -0400)
    Merges in rt36233.

.gitignore
RELNOTES
common/options.c
common/tree.c
includes/dhcpd.h
server/bootp.c
server/dhcp.c

index a238dcd5e8752fe33eab7ef2ff261d49dc3ffcd7..18d4580a15d7b43fc6896391aa79d93e8355986d 100644 (file)
@@ -4,3 +4,27 @@ doc/html
 .deps
 Makefile
 autom4te.cache
+client/dhclient
+client/tests/
+common/tests/alloc_unittest
+common/tests/dns_unittest
+common/tests/misc_unittest
+config.log
+config.report
+config.status
+dhcpctl/cltest
+dhcpctl/omshell
+doc/devel/doxyfile
+dst/libdst.a
+includes/.dhcpd.h.swp
+includes/stamp-h1
+omapip/svtest
+relay/dhcrelay
+server/dhcpd
+server/tests/dhcpd_unittests
+server/tests/hash_unittests
+server/tests/legacy_unittests
+server/tests/load_bal_unittests
+server/tests/test-suite.log
+tests/libt_api.a
+minires/libres.a
index e74fff126e55bb4b9d08bdeee63dcdfa991ce2f7..b999d111f92b9fb7d56335d02d461ec9d8e29874 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -103,11 +103,15 @@ by Eric Young (eay@cryptsoft.com).
   [ISC-Bus #24216]
   [ISC-Bus #25587]
 
+- Added support of the configuration parameter, use-host-decl-names, to
+  BOOTP request handling.
+  [ISC-Bugs #36233]
+
                        Changes since 4.1-ESV-R10rc1
 
 - None
 
-                       Changes since 4.1-ESV-R10b1
+                       Changes since 4.3.1b1
 
 - Modify the linux and openwrt dhclient scripts to process information
   from a stateless request.  Thanks to Jiri Popelka at Red Hat for the
index db8d8071df9d7e18dd1edb3dae209fc5a48baef0..140a1aea0d0d44705ff389adb37fba34829c0b7b 100644 (file)
@@ -43,17 +43,11 @@ static int prepare_option_buffer(struct universe *universe, struct buffer *bp,
                                 struct option_cache **opp);
 
 /* Parse all available options out of the specified packet. */
-
+/* Note, the caller is responsible for allocating packet->options. */
 int parse_options (packet)
        struct packet *packet;
 {
-       struct option_cache *op = (struct option_cache *)0;
-
-       /* Allocate a new option state. */
-       if (!option_state_allocate (&packet -> options, MDL)) {
-               packet -> options_valid = 0;
-               return 0;
-       }
+       struct option_cache *op = NULL;
 
        /* If we don't see the magic cookie, there's nothing to parse. */
        if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
@@ -3790,12 +3784,15 @@ void do_packet (interface, packet, len, from_port, from, hfrom)
                return;
        }
 
+       /* Allocate packet->options now so it is non-null for all packets */
+       decoded_packet->options_valid = 0;
+       if (!option_state_allocate (&decoded_packet->options, MDL)) {
+               return;
+       }
+
        /* If there's an option buffer, try to parse it. */
        if (decoded_packet->packet_length >= DHCP_FIXED_NON_UDP + 4) {
                if (!parse_options(decoded_packet)) {
-                       if (decoded_packet->options)
-                               option_state_dereference
-                                       (&decoded_packet->options, MDL);
                        packet_dereference (&decoded_packet, MDL);
                        return;
                }
index ef3e309158c11f349dfc2efa55c924b391e32476..838dbcaa8487583b130c6ecfdad0f67038fc0c02 100644 (file)
@@ -2900,9 +2900,16 @@ int evaluate_option_cache (result, packet, lease, client_state,
                                         oc -> expression, file, line);
 }
 
-/* Evaluate an option cache and extract a boolean from the result,
-   returning the boolean.   Return false if there is no data. */
-
+/* Evaluate an option cache and extract a boolean from the result.
+ * The boolean option cache is actually a trinary value where:
+ *
+ *     0 = return 0, ignore parameter 0 (also the case for no data)
+ *     1 = return 1, ignore parameter 0
+ *     2 = return 0, ignore parameter 1
+ *
+ * This supports both classic boolean flags on/off as well as the
+ * allow/deny/ignore keywords
+*/
 int evaluate_boolean_option_cache (ignorep, packet,
                                   lease, client_state, in_options,
                                   cfg_options, scope, oc, file, line)
@@ -2917,36 +2924,35 @@ int evaluate_boolean_option_cache (ignorep, packet,
        const char *file;
        int line;
 {
-       struct data_string ds;
-       int result;
+       int result = 0;
+       if (ignorep)
+               *ignorep = 0;
 
-       /* So that we can be called with option_lookup as an argument. */
-       if (!oc || !in_options)
-               return 0;
-       
-       memset (&ds, 0, sizeof ds);
-       if (!evaluate_option_cache (&ds, packet,
-                                   lease, client_state, in_options,
-                                   cfg_options, scope, oc, file, line))
-               return 0;
+       /* Only attempt to evaluate if option_cache is not null. This permits
+        * us to be called with option_lookup() as an argument. */
+       if (oc && in_options) {
+               struct data_string ds;
+
+               memset(&ds, 0, sizeof ds);
+               if (evaluate_option_cache(&ds, packet,
+                                         lease, client_state, in_options,
+                                         cfg_options, scope, oc, file,
+                                         line)) {
+                       /* We have a value for the option set result and
+                        * ignore parameter accordingly. */
+                       if (ds.len) {
+                               if (ds.data[0] == 1)
+                                       result = 1;
+                               else if ((ds.data[0] == 2) && (ignorep != NULL))
+                                       *ignorep = 1;
+                       }
 
-       /* The boolean option cache is actually a trinary value.  Zero is
-        * off, one is on, and 2 is 'ignore'.
-        */
-       if (ds.len) {
-               result = ds.data [0];
-               if (result == 2) {
-                       result = 0;
-                       if (ignorep != NULL)
-                               *ignorep = 1;
-               } else if (ignorep != NULL)
-                       *ignorep = 0;
-       } else
-               result = 0;
-       data_string_forget (&ds, MDL);
-       return result;
+                       data_string_forget(&ds, MDL);
+               }
+       }
+
+       return (result);
 }
-               
 
 /* Evaluate a boolean expression and return the result of the evaluation,
    or FALSE if it failed. */
index fed7b595ac521e5c0c688621e738838506217fdd..97b0951d1643cfdc6096b58de50fabbfbae131a0 100644 (file)
@@ -2010,7 +2010,8 @@ isc_result_t get_client_id(struct packet *, struct data_string *);
 void dhcpv6(struct packet *);
 
 /* bootp.c */
-void bootp (struct packet *);
+void bootp(struct packet *);
+void use_host_decl_name(struct packet *, struct lease* , struct option_state *);
 
 /* memory.c */
 extern int (*group_write_hook) (struct group_object *);
index d6dd96a27745fffedbc31bb54fc638b3248bc1f3..7397cec1e15fe92e4c764989a110db1d8807e561 100644 (file)
@@ -180,21 +180,21 @@ void bootp (packet)
        
        /* Drop the request if it's not allowed for this client. */
        if ((oc = lookup_option (&server_universe, options, SV_ALLOW_BOOTP)) &&
-           !evaluate_boolean_option_cache (&ignorep, packet, lease,
-                                           (struct client_state *)0,
-                                           packet -> options, options,
-                                           &lease -> scope, oc, MDL)) {
+           !evaluate_boolean_option_cache(&ignorep, packet, lease,
+                                          NULL,
+                                          packet->options, options,
+                                          &lease->scope, oc, MDL)) {
                if (!ignorep)
                        log_info ("%s: bootp disallowed", msgbuf);
                goto out;
        } 
 
-       if ((oc = lookup_option (&server_universe,
+       if ((oc = lookup_option(&server_universe,
                                 options, SV_ALLOW_BOOTING)) &&
-           !evaluate_boolean_option_cache (&ignorep, packet, lease,
-                                           (struct client_state *)0,
-                                           packet -> options, options,
-                                           &lease -> scope, oc, MDL)) {
+           !evaluate_boolean_option_cache(&ignorep, packet, lease,
+                                          NULL,
+                                          packet->options, options,
+                                          &lease->scope, oc, MDL)) {
                if (!ignorep)
                        log_info ("%s: booting disallowed", msgbuf);
                goto out;
@@ -207,20 +207,26 @@ void bootp (packet)
 
        /* If we didn't get a known vendor magic number on the way in,
           just copy the input options to the output. */
-       if (!packet -> options_valid &&
-           !(evaluate_boolean_option_cache
-             (&ignorep, packet, lease, (struct client_state *)0,
-              packet -> options, options, &lease -> scope,
-              lookup_option (&server_universe, options,
-                             SV_ALWAYS_REPLY_RFC1048), MDL))) {
-               memcpy (outgoing.raw -> options,
-                       packet -> raw -> options, DHCP_MAX_OPTION_LEN);
-               outgoing.packet_length = BOOTP_MIN_LEN;
+       i = SV_ALWAYS_REPLY_RFC1048;
+       if (!packet->options_valid &&
+           !(evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
+                                           packet->options, options,
+                                           &lease->scope,
+                                           lookup_option (&server_universe,
+                                                          options, i), MDL))) {
+               if (packet->packet_length > DHCP_FIXED_NON_UDP) {
+                       memcpy(outgoing.raw->options, packet->raw->options,
+                       packet->packet_length - DHCP_FIXED_NON_UDP);
+               }
+
+               outgoing.packet_length =
+                       (packet->packet_length < BOOTP_MIN_LEN)
+                                              ? BOOTP_MIN_LEN
+                                              : packet->packet_length;
        } else {
 
                /* Use the subnet mask from the subnet declaration if no other
                   mask has been provided. */
-
                oc = (struct option_cache *)0;
                i = DHO_SUBNET_MASK;
                if (!lookup_option (&dhcp_universe, options, i)) {
@@ -240,6 +246,11 @@ void bootp (packet)
                        }
                }
 
+               /* If use-host-decl-names is enabled and there is a hostname
+                * defined in the host delcartion, send it back in hostname
+                * option */
+               use_host_decl_name(packet, lease, options);
+
                /* Pack the options into the buffer.  Unlike DHCP, we
                   can't pack options into the filename and server
                   name buffers. */
index 08b67d744c254149607df39236752be743c5e910..0b0f632209650606695c42a2e12ecbd3b7ca52c8 100644 (file)
@@ -2732,33 +2732,10 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                }
        }
 
-       /* Use the hostname from the host declaration if there is one
+       /* Use the name of the host declaration if there is one
           and no hostname has otherwise been provided, and if the 
           use-host-decl-name flag is set. */
-       i = DHO_HOST_NAME;
-       j = SV_USE_HOST_DECL_NAMES;
-       if (!lookup_option (&dhcp_universe, state -> options, i) &&
-           lease -> host && lease -> host -> name &&
-           (evaluate_boolean_option_cache
-            (&ignorep, packet, lease, (struct client_state *)0,
-             packet -> options, state -> options, &lease -> scope,
-             lookup_option (&server_universe, state -> options, j), MDL))) {
-               oc = (struct option_cache *)0;
-               if (option_cache_allocate (&oc, MDL)) {
-                       if (make_const_data (&oc -> expression,
-                                            ((unsigned char *)
-                                             lease -> host -> name),
-                                            strlen (lease -> host -> name),
-                                            1, 0, MDL)) {
-                               option_code_hash_lookup(&oc->option,
-                                                       dhcp_universe.code_hash,
-                                                       &i, 0, MDL);
-                               save_option (&dhcp_universe,
-                                            state -> options, oc);
-                       }
-                       option_cache_dereference (&oc, MDL);
-               }
-       }
+       use_host_decl_name(packet, lease, state->options);
 
        /* If we don't have a hostname yet, and we've been asked to do
           a reverse lookup to find the hostname, do it. */
@@ -4538,3 +4515,43 @@ lowest_site_code(const void *key, unsigned len, void *object)
        return ISC_R_SUCCESS;
 }
 
+/*!
+ * \brief Adds hostname option when use-host-decl-names is enabled.
+ *
+ * Constructs a hostname option from the name of the host declaration if
+ * there is one and no hostname has otherwise been provided and the
+ * use-host-decl-names flag is set, then adds the new option to the given
+ * option_state.  This funciton is used for both bootp and dhcp.
+ *
+ * \param packet inbound packet received from the client
+ * \param lease lease associated with the client
+ * \param options option state to search and update
+ */
+void use_host_decl_name(struct packet* packet,
+                       struct lease *lease,
+                       struct option_state *options) {
+       unsigned int ocode = SV_USE_HOST_DECL_NAMES;
+        if ((lease->host && lease->host->name) &&
+           !lookup_option(&dhcp_universe, options, DHO_HOST_NAME) &&
+            (evaluate_boolean_option_cache(NULL, packet, lease, NULL,
+                                          packet->options, options,
+                                          &lease->scope,
+                                          lookup_option(&server_universe,
+                                                        options, ocode),
+                                          MDL))) {
+               struct option_cache *oc = NULL;
+                if (option_cache_allocate (&oc, MDL)) {
+                        if (make_const_data(&oc -> expression,
+                                            ((unsigned char*)lease->host->name),
+                                            strlen(lease->host->name),
+                                           1, 0, MDL)) {
+                               ocode = DHO_HOST_NAME;
+                                option_code_hash_lookup(&oc->option,
+                                                        dhcp_universe.code_hash,
+                                                        &ocode, 0, MDL);
+                                save_option(&dhcp_universe, options, oc);
+                        }
+                        option_cache_dereference(&oc, MDL);
+                }
+        }
+}