On Wed, 09 Jul 2014 20:40:36 +0200 (CEST)
YASUOKA Masahiko <[email protected]> wrote:
> On Wed, 9 Jul 2014 19:08:09 +0200
> Kenneth Westerback <[email protected]> wrote:
>> On 9 July 2014 16:26, YASUOKA Masahiko <[email protected]> wrote:
>>> This diff fixes dhcpinform to work without lease.
>>>
>>> ok?
>>>
>>> Fix dhcpinform to work without lease.
>>>
>>> Diff from Yuuichi Someya.
>> 
>> This seems to be a large chunk of code duplication. Was it not be
>> possible to have dhcpinform() create a lease and then simply call the
>> normal ack_lease() function to send out the information?
> 
> Just creating a lease and calling ack_lease() doesn't comply with RFC
> 2131.  So creating a fake lease and adding some "if" switches to
> ack_lease() is required.  And I didn't think it's better.

I did it actually, seems better :)

How about this?

Fix DHCPINFORM not to lookup the lease database, not to fill the
yiaddr field and not to include the lease time parameters.

Index: usr.sbin/dhcpd/dhcp.c
===================================================================
RCS file: /disk/cvs/openbsd/src/usr.sbin/dhcpd/dhcp.c,v
retrieving revision 1.36
diff -u -p -r1.36 dhcp.c
--- usr.sbin/dhcpd/dhcp.c       5 Apr 2013 19:31:36 -0000       1.36
+++ usr.sbin/dhcpd/dhcp.c       11 Jul 2014 15:10:27 -0000
@@ -500,7 +500,7 @@ dhcpdecline(struct packet *packet)
 void
 dhcpinform(struct packet *packet)
 {
-       struct lease *lease;
+       struct lease lease;
        struct iaddr cip;
        struct subnet *subnet;
 
@@ -509,9 +509,17 @@ dhcpinform(struct packet *packet)
         * not all clients are standards compliant.
         */
        cip.len = 4;
-       if (packet->raw->ciaddr.s_addr)
+       if (packet->raw->ciaddr.s_addr) {
+               if (memcmp(&packet->raw->ciaddr.s_addr,
+                   packet->client_addr.iabuf, 4) == 0) {
+                       note("DHCPINFORM from %s but ciaddr %s is not "
+                           "consitent with actual address",
+                           piaddr(packet->client_addr),
+                           inet_ntoa(packet->raw->ciaddr));
+                       return;
+               }
                memcpy(cip.iabuf, &packet->raw->ciaddr.s_addr, 4);
-       else
+       } else
                memcpy(cip.iabuf, &packet->client_addr.iabuf, 4);
 
        note("DHCPINFORM from %s", piaddr(cip));
@@ -528,28 +536,21 @@ dhcpinform(struct packet *packet)
                return;
        }
 
-       lease = find_lease(packet, subnet->shared_network, 0);
-       if (!lease) {
-               note("DHCPINFORM packet from %s but no lease present",
-                   print_hw_addr(packet->raw->htype, packet->raw->hlen,
-                   packet->raw->chaddr));
-               return;
-       }
-
-       /* If this subnet won't boot unknown clients, ignore the
-          request. */
-       if (!lease->host &&
-           !lease->subnet->group->boot_unknown_clients) {
-               note("Ignoring unknown client %s",
-                   print_hw_addr(packet->raw->htype, packet->raw->hlen,
-                   packet->raw->chaddr));
-       } else if (lease->host && !lease->host->group->allow_booting) {
-               note("Declining to boot client %s",
-                   lease->host->name ? lease->host->name :
-                   print_hw_addr(packet->raw->htype, packet->raw->hlen,
-                   packet->raw->chaddr));
-       } else
-               ack_lease(packet, lease, DHCPACK, 0);
+       /* Use a fake lease entry */
+       memset(&lease, 0, sizeof(lease));
+       lease.subnet = subnet;
+       lease.shared_network = subnet->shared_network;
+
+       if (packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len)
+               lease.host = find_hosts_by_uid(
+                   packet->options[DHO_DHCP_CLIENT_IDENTIFIER].data,
+                   packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len);
+
+       lease.starts = lease.timestamp = lease.ends = MIN_TIME;
+       lease.flags = INFORM_NOLEASE;
+       ack_lease(packet, &lease, DHCPACK, 0);
+       if (lease.state != NULL)
+               free_lease_state(lease.state, "ack_lease");
 }
 
 void
@@ -881,7 +882,7 @@ ack_lease(struct packet *packet, struct 
        lt.shared_network = lease->shared_network;
 
        /* Don't call supersede_lease on a mocked-up lease. */
-       if (lease->flags & STATIC_LEASE) {
+       if (lease->flags & (STATIC_LEASE | INFORM_NOLEASE)) {
                /* Copy the hardware address into the static lease
                   structure. */
                lease->hardware_addr.hlen = packet->raw->hlen;
@@ -1043,6 +1044,42 @@ ack_lease(struct packet *packet, struct 
                        memcpy(state->from.iabuf, state->options[i]->value,
                            state->from.len);
                }
+               /* If we used the vendor class the client specified, we
+                  have to return it. */
+               if (vendor_class) {
+                       i = DHO_DHCP_CLASS_IDENTIFIER;
+                       state->options[i] =
+                               new_tree_cache("class-identifier");
+                       state->options[i]->flags = TC_TEMPORARY;
+                       state->options[i]->value =
+                               (unsigned char *)vendor_class->name;
+                       state->options[i]->len =
+                               strlen(vendor_class->name);
+                       state->options[i]->buf_size =
+                               state->options[i]->len;
+                       state->options[i]->timeout = -1;
+                       state->options[i]->tree = NULL;
+               }
+
+               /* If we used the user class the client specified, we
+                  have to return it. */
+               if (user_class) {
+                       i = DHO_DHCP_USER_CLASS_ID;
+                       state->options[i] = new_tree_cache("user-class");
+                       state->options[i]->flags = TC_TEMPORARY;
+                       state->options[i]->value =
+                               (unsigned char *)user_class->name;
+                       state->options[i]->len =
+                               strlen(user_class->name);
+                       state->options[i]->buf_size =
+                               state->options[i]->len;
+                       state->options[i]->timeout = -1;
+                       state->options[i]->tree = NULL;
+               }
+       }
+
+       /* for DHCPINFORM, don't include lease time parameters */
+       if (state->offer && (lease->flags & INFORM_NOLEASE) == 0) {
 
                /* Sanity check the lease time. */
                if ((state->offered_expiry - cur_time) < 15)
@@ -1093,39 +1130,6 @@ ack_lease(struct packet *packet, struct 
                state->options[i]->buf_size = sizeof state->rebind;
                state->options[i]->timeout = -1;
                state->options[i]->tree = NULL;
-
-               /* If we used the vendor class the client specified, we
-                  have to return it. */
-               if (vendor_class) {
-                       i = DHO_DHCP_CLASS_IDENTIFIER;
-                       state->options[i] =
-                               new_tree_cache("class-identifier");
-                       state->options[i]->flags = TC_TEMPORARY;
-                       state->options[i]->value =
-                               (unsigned char *)vendor_class->name;
-                       state->options[i]->len =
-                               strlen(vendor_class->name);
-                       state->options[i]->buf_size =
-                               state->options[i]->len;
-                       state->options[i]->timeout = -1;
-                       state->options[i]->tree = NULL;
-               }
-
-               /* If we used the user class the client specified, we
-                  have to return it. */
-               if (user_class) {
-                       i = DHO_DHCP_USER_CLASS_ID;
-                       state->options[i] = new_tree_cache("user-class");
-                       state->options[i]->flags = TC_TEMPORARY;
-                       state->options[i]->value =
-                               (unsigned char *)user_class->name;
-                       state->options[i]->len =
-                               strlen(user_class->name);
-                       state->options[i]->buf_size =
-                               state->options[i]->len;
-                       state->options[i]->timeout = -1;
-                       state->options[i]->tree = NULL;
-               }
        }
 
        /* Use the subnet mask from the subnet declaration if no other
@@ -1280,7 +1284,8 @@ dhcp_reply(struct lease *lease)
        }
 
        memcpy(&raw.ciaddr, &state->ciaddr, sizeof raw.ciaddr);
-       memcpy(&raw.yiaddr, lease->ip_addr.iabuf, 4);
+       if ((lease->flags & INFORM_NOLEASE) == 0)
+               memcpy(&raw.yiaddr, lease->ip_addr.iabuf, 4);
 
        /* Figure out the address of the next server. */
        if (lease->host && lease->host->group->next_server.len)
Index: usr.sbin/dhcpd/dhcpd.h
===================================================================
RCS file: /disk/cvs/openbsd/src/usr.sbin/dhcpd/dhcpd.h,v
retrieving revision 1.50
diff -u -p -r1.50 dhcpd.h
--- usr.sbin/dhcpd/dhcpd.h      7 May 2014 13:20:47 -0000       1.50
+++ usr.sbin/dhcpd/dhcpd.h      11 Jul 2014 15:10:28 -0000
@@ -180,6 +180,7 @@ struct lease {
 #define EPHEMERAL_FLAGS                (BOOTP_LEASE)
 #define MS_NULL_TERMINATION    8
 #define ABANDONED_LEASE                16
+#define INFORM_NOLEASE         32
 
        struct lease_state *state;
        u_int8_t releasing;

Reply via email to