Commit ca85a282 authored by Simon Kelley's avatar Simon Kelley

Allow T1 and T2 DHCPv4 options to be set.

parent 585840b0
...@@ -118,6 +118,9 @@ version 2.73 ...@@ -118,6 +118,9 @@ version 2.73
Check IPv4-mapped IPv6 addresses when --stop-rebind Check IPv4-mapped IPv6 addresses when --stop-rebind
is active. Thanks to Jordan Milne for spotting this. 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 version 2.72
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
......
...@@ -345,6 +345,14 @@ ...@@ -345,6 +345,14 @@
# Ask client to poll for option changes every six hours. (RFC4242) # Ask client to poll for option changes every six hours. (RFC4242)
#dhcp-option=option6:information-refresh-time,6h #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 # Set the NTP time server address to be the same machine as
# is running dnsmasq # is running dnsmasq
#dhcp-option=42,0.0.0.0 #dhcp-option=42,0.0.0.0
......
...@@ -545,8 +545,8 @@ static const struct opttab_t { ...@@ -545,8 +545,8 @@ static const struct opttab_t {
{ "parameter-request", 55, OT_INTERNAL }, { "parameter-request", 55, OT_INTERNAL },
{ "message", 56, OT_INTERNAL }, { "message", 56, OT_INTERNAL },
{ "max-message-size", 57, OT_INTERNAL }, { "max-message-size", 57, OT_INTERNAL },
{ "T1", 58, OT_INTERNAL | OT_TIME}, { "T1", 58, OT_TIME},
{ "T2", 59, OT_INTERNAL | OT_TIME}, { "T2", 59, OT_TIME},
{ "vendor-class", 60, 0 }, { "vendor-class", 60, 0 },
{ "client-id", 61, OT_INTERNAL }, { "client-id", 61, OT_INTERNAL },
{ "nis+-domain", 64, OT_NAME }, { "nis+-domain", 64, OT_NAME },
......
...@@ -52,7 +52,9 @@ static void do_options(struct dhcp_context *context, ...@@ -52,7 +52,9 @@ static void do_options(struct dhcp_context *context,
int null_term, int pxearch, int null_term, int pxearch,
unsigned char *uuid, unsigned char *uuid,
int vendor_class_len, 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); 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, ...@@ -610,7 +612,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
clear_packet(mess, end); clear_packet(mess, end);
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr), 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, ...@@ -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_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
option_put(mess, end, OPTION_LEASE_TIME, 4, time); option_put(mess, end, OPTION_LEASE_TIME, 4, time);
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */ /* 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), 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); 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, ...@@ -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_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_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
option_put(mess, end, OPTION_LEASE_TIME, 4, time); 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), 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); 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, ...@@ -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), 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 */ *is_inform = 1; /* handle reply differently */
return dhcp_packet_size(mess, agent_id, real_end); return dhcp_packet_size(mess, agent_id, real_end);
...@@ -2137,7 +2127,9 @@ static void do_options(struct dhcp_context *context, ...@@ -2137,7 +2127,9 @@ static void do_options(struct dhcp_context *context,
int null_term, int pxe_arch, int null_term, int pxe_arch,
unsigned char *uuid, unsigned char *uuid,
int vendor_class_len, 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_opt *opt, *config_opts = daemon->dhcp_opts;
struct dhcp_boot *boot; struct dhcp_boot *boot;
...@@ -2262,6 +2254,41 @@ static void do_options(struct dhcp_context *context, ...@@ -2262,6 +2254,41 @@ static void do_options(struct dhcp_context *context,
if (subnet_addr.s_addr) if (subnet_addr.s_addr)
option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(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 */ /* replies to DHCPINFORM may not have a valid context */
if (context) if (context)
{ {
...@@ -2356,12 +2383,14 @@ static void do_options(struct dhcp_context *context, ...@@ -2356,12 +2383,14 @@ static void do_options(struct dhcp_context *context,
if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno)) if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
continue; continue;
/* prohibit some used-internally options */ /* prohibit some used-internally options. T1 and T2 already handled. */
if (optno == OPTION_CLIENT_FQDN || if (optno == OPTION_CLIENT_FQDN ||
optno == OPTION_MAXMESSAGE || optno == OPTION_MAXMESSAGE ||
optno == OPTION_OVERLOAD || optno == OPTION_OVERLOAD ||
optno == OPTION_PAD || optno == OPTION_PAD ||
optno == OPTION_END) optno == OPTION_END ||
optno == OPTION_T1 ||
optno == OPTION_T2)
continue; continue;
if (optno == OPTION_SNAME && done_server) if (optno == OPTION_SNAME && done_server)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment