]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Allow T1 and T2 DHCPv4 options to be set.
authorSimon Kelley <simon@thekelleys.org.uk>
Wed, 13 May 2015 21:33:04 +0000 (22:33 +0100)
committerSimon Kelley <simon@thekelleys.org.uk>
Wed, 13 May 2015 21:33:04 +0000 (22:33 +0100)
CHANGELOG
dnsmasq.conf.example
src/dhcp-common.c
src/rfc2131.c

index 94a521f996e20755f449fc4c95dbed68beae92d1..ef39a415788b7b865f02a0284d9772778da1990f 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -118,6 +118,9 @@ version 2.73
            Check IPv4-mapped IPv6 addresses when --stop-rebind
            is active. Thanks to Jordan Milne for spotting this.
 
+           Allow DHCPv4 options T1 and T2 to be set using --dhcp-option.
+           Thanks to Kevin Benton for patches and work on this.
+
        
 version 2.72
             Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
index 67be99acb028d8db296311fe962adcaf5ff92d20..1ae11dfb53585ce80d8ef3cd0ec13b8e00faf4f7 100644 (file)
 # Ask client to poll for option changes every six hours. (RFC4242)
 #dhcp-option=option6:information-refresh-time,6h
 
+# Set option 58 client renewal time (T1). Defaults to half of the
+# lease time if not specified. (RFC2132)
+#dhcp-option=option:T1:1m
+
+# Set option 59 rebinding time (T2). Defaults to 7/8 of the
+# lease time if not specified. (RFC2132)
+#dhcp-option=option:T2:2m
+
 # Set the NTP time server address to be the same machine as
 # is running dnsmasq
 #dhcp-option=42,0.0.0.0
index ce115202a6469e875efc9152dae43283b2302560..bc48f41a14d79e9a0d19617dbbf1271d226ba555 100644 (file)
@@ -545,8 +545,8 @@ static const struct opttab_t {
   { "parameter-request", 55, OT_INTERNAL },
   { "message", 56, OT_INTERNAL },
   { "max-message-size", 57, OT_INTERNAL },
-  { "T1", 58, OT_INTERNAL | OT_TIME},
-  { "T2", 59, OT_INTERNAL | OT_TIME},
+  { "T1", 58, OT_TIME},
+  { "T2", 59, OT_TIME},
   { "vendor-class", 60, 0 },
   { "client-id", 61, OT_INTERNAL },
   { "nis+-domain", 64, OT_NAME },
index 55526443dc8471fdfadee41438d8e5ac0e33be6c..a10e499ef76839f9b5694f80eece8cb2c47f7860 100644 (file)
@@ -52,7 +52,9 @@ static void do_options(struct dhcp_context *context,
                       int null_term, int pxearch,
                       unsigned char *uuid,
                       int vendor_class_len,
-                      time_t now);
+                      time_t now,
+                      unsigned int lease_time,
+                      unsigned short fuzz);
 
 
 static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt); 
@@ -610,7 +612,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
              
              clear_packet(mess, end);
              do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr), 
-                        netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now);
+                        netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now, 0xffffffff, 0);
            }
        }
       
@@ -1042,13 +1044,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
       option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
       option_put(mess, end, OPTION_LEASE_TIME, 4, time);
       /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
-      if (time != 0xffffffff)
-       {
-         option_put(mess, end, OPTION_T1, 4, (time/2));
-         option_put(mess, end, OPTION_T2, 4, (time*7)/8);
-       }
       do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr), 
-                netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
+                netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
       
       return dhcp_packet_size(mess, agent_id, real_end);
       
@@ -1367,15 +1364,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
          option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
          option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
          option_put(mess, end, OPTION_LEASE_TIME, 4, time);
-         if (time != 0xffffffff)
-           {
-             while (fuzz > (time/16))
-               fuzz = fuzz/2; 
-             option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
-             option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
-           }
          do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr), 
-                    netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
+                    netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
        }
 
       return dhcp_packet_size(mess, agent_id, real_end); 
@@ -1440,7 +1430,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
        }
 
       do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
-                netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
+                netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, 0xffffffff, 0);
       
       *is_inform = 1; /* handle reply differently */
       return dhcp_packet_size(mess, agent_id, real_end); 
@@ -2137,7 +2127,9 @@ static void do_options(struct dhcp_context *context,
                       int null_term, int pxe_arch,
                       unsigned char *uuid,
                       int vendor_class_len,
-                      time_t now)
+                      time_t now,
+                      unsigned int lease_time,
+                      unsigned short fuzz)
 {
   struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
   struct dhcp_boot *boot;
@@ -2261,7 +2253,42 @@ static void do_options(struct dhcp_context *context,
   /* rfc3011 says this doesn't need to be in the requested options list. */
   if (subnet_addr.s_addr)
     option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
-  
+   
+  if (lease_time != 0xffffffff)
+    { 
+      unsigned int t1val = lease_time/2; 
+      unsigned int t2val = (lease_time*7)/8;
+      unsigned int hval;
+      
+      /* If set by user, sanity check, so not longer than lease. */
+      if ((opt = option_find2(OPTION_T1)))
+       {
+         hval = ntohl(*((unsigned int *)opt->val));
+         if (hval < lease_time && hval > 2)
+           t1val = hval;
+       }
+
+       if ((opt = option_find2(OPTION_T2)))
+       {
+         hval = ntohl(*((unsigned int *)opt->val));
+         if (hval < lease_time && hval > 2)
+           t2val = hval;
+       }
+                 
+       while (fuzz > (t1val/8))
+        fuzz = fuzz/2;
+        
+       t1val -= fuzz;
+       t2val -= fuzz;
+       
+       /* ensure T1 is still < T2 */
+       if (t2val <= t1val)
+        t1val = t2val - 1; 
+
+       option_put(mess, end, OPTION_T1, 4, t1val);
+       option_put(mess, end, OPTION_T2, 4, t2val);
+    }
+
   /* replies to DHCPINFORM may not have a valid context */
   if (context)
     {
@@ -2356,12 +2383,14 @@ static void do_options(struct dhcp_context *context,
       if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
        continue;
       
-      /* prohibit some used-internally options */
+      /* prohibit some used-internally options. T1 and T2 already handled. */
       if (optno == OPTION_CLIENT_FQDN ||
          optno == OPTION_MAXMESSAGE ||
          optno == OPTION_OVERLOAD ||
          optno == OPTION_PAD ||
-         optno == OPTION_END)
+         optno == OPTION_END ||
+         optno == OPTION_T1 ||
+         optno == OPTION_T2)
        continue;
 
       if (optno == OPTION_SNAME && done_server)