From a5b21e16ff3a58d2262eddfffc4e8937379b016f Mon Sep 17 00:00:00 2001 From: Thomas Markwalder Date: Wed, 26 Sep 2018 11:10:16 -0400 Subject: [master] Added configuration parameter, ping-cltt-secs (v4 operation only) Merges in rt36283. --- server/dhcp.c | 304 +++++++++++++++++++++++++++++++++------------------- server/dhcpd.conf.5 | 30 ++++++ server/stables.c | 1 + 3 files changed, 225 insertions(+), 110 deletions(-) (limited to 'server') diff --git a/server/dhcp.c b/server/dhcp.c index 6f3a91f0..5af022fb 100644 --- a/server/dhcp.c +++ b/server/dhcp.c @@ -33,9 +33,15 @@ static void maybe_return_agent_options(struct packet *packet, struct option_state *options); + static int reuse_lease (struct packet* packet, struct lease* new_lease, struct lease* lease, struct lease_state *state, - int offer); + int offer, int* same_client); + +static int do_ping_check(struct packet* packet, struct lease_state* state, + struct lease* lease, TIME original_cltt, + int same_client); + #if defined(DHCPv6) && defined(DHCP4o6) static int locate_network6(struct packet *packet); #endif @@ -64,7 +70,7 @@ static int site_code_min; static int find_min_site_code(struct universe *); static isc_result_t lowest_site_code(const void *, unsigned, void *); -static const char *dhcp_type_names [] = { +static const char *dhcp_type_names [] = { "DHCPDISCOVER", "DHCPOFFER", "DHCPREQUEST", @@ -97,13 +103,13 @@ dhcp (struct packet *packet) { if (!locate_network(packet) && packet->packet_type != DHCPREQUEST && - packet->packet_type != DHCPINFORM && + packet->packet_type != DHCPINFORM && packet->packet_type != DHCPLEASEQUERY) { const char *s; char typebuf[32]; errmsg = "unknown network segment"; bad_packet: - + if (packet->packet_type > 0 && packet->packet_type <= dhcp_type_name_max) { s = dhcp_type_names[packet->packet_type - 1]; @@ -112,7 +118,7 @@ dhcp (struct packet *packet) { sprintf(typebuf, "type %d", packet->packet_type); s = typebuf; } - + #if defined(DHCPv6) && defined(DHCP4o6) if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) { log_info("DHCP4o6 %s from %s via %s: %s", s, @@ -387,7 +393,7 @@ void dhcpdiscover (packet, ms_nulltp) /* If we didn't find a lease, try to allocate one... */ if (!lease) { if (!allocate_lease (&lease, packet, - packet -> shared_network -> pools, + packet -> shared_network -> pools, &peer_has_leases)) { if (peer_has_leases) log_error ("%s: peer holds all free leases", @@ -710,7 +716,7 @@ void dhcprequest (packet, ms_nulltp, ip_lease) (packet -> raw -> ciaddr.s_addr && packet -> raw -> giaddr.s_addr) || (have_requested_addr && !packet -> raw -> ciaddr.s_addr)) { - + /* If we don't know where it came from but we do know where it claims to have come from, it didn't come from there. */ @@ -913,7 +919,7 @@ void dhcprelease (packet, ms_nulltp) /* If we found a lease, release it. */ if (lease && lease -> ends > cur_time) { release_lease (lease, packet); - } + } log_info ("%s", msgbuf); #if defined(FAILOVER_PROTOCOL) out: @@ -1167,7 +1173,7 @@ void dhcpinform (packet, ms_nulltp) relay_port = dhcp_check_relayport(packet); #endif - /* Find the subnet that the client is on. + /* Find the subnet that the client is on. * CC: Do the link selection / subnet selection */ @@ -1247,7 +1253,7 @@ void dhcpinform (packet, ms_nulltp) option_state_dereference(&options, MDL); return; } - + memset(&outgoing, 0, sizeof outgoing); memset(&raw, 0, sizeof raw); outgoing.raw = &raw; @@ -1265,8 +1271,8 @@ void dhcpinform (packet, ms_nulltp) struct lease* cip_lease = NULL; find_lease_by_ip_addr (&cip_lease, cip, MDL); - - /* Overlay with pool options if ciaddr mapped to a lease. */ + + /* Overlay with pool options if ciaddr mapped to a lease. */ if (cip_lease) { if (cip_lease->pool && cip_lease->pool->group) { execute_statements_in_scope( @@ -1281,7 +1287,7 @@ void dhcpinform (packet, ms_nulltp) lease_dereference (&cip_lease, MDL); } } - + /* Execute statements in the class scopes. */ for (i = packet->class_count; i > 0; i--) { execute_statements_in_scope(NULL, packet, NULL, NULL, @@ -1293,7 +1299,7 @@ void dhcpinform (packet, ms_nulltp) } /* - * Process host declarations during DHCPINFORM, + * Process host declarations during DHCPINFORM, * Try to find a matching host declaration by cli ID or HW addr. * * Look through the host decls for one that matches the @@ -1436,7 +1442,7 @@ void dhcpinform (packet, ms_nulltp) if (hp) host_dereference (&hp, MDL); } - + #if defined (DEBUG_INFORM_HOST) /* Hmm..: what when there is a host with a fixed-address, * that matches by hw or id, but the fixed-addresses @@ -1465,7 +1471,7 @@ void dhcpinform (packet, ms_nulltp) } /* CC: end of host entry processing.... */ - + /* Figure out the filename. */ memset (&d1, 0, sizeof d1); oc = lookup_option (&server_universe, options, SV_FILENAME); @@ -1477,7 +1483,7 @@ void dhcpinform (packet, ms_nulltp) i = d1.len; if (i >= sizeof(raw.file)) { log_info("file name longer than packet field " - "truncated - field: %lu name: %d %.*s", + "truncated - field: %lu name: %d %.*s", (unsigned long)sizeof(raw.file), i, (int)i, d1.data); i = sizeof(raw.file); @@ -1497,7 +1503,7 @@ void dhcpinform (packet, ms_nulltp) i = d1.len; if (i >= sizeof(raw.sname)) { log_info("server name longer than packet field " - "truncated - field: %lu name: %d %.*s", + "truncated - field: %lu name: %d %.*s", (unsigned long)sizeof(raw.sname), i, (int)i, d1.data); i = sizeof(raw.sname); @@ -1808,7 +1814,7 @@ void nak_lease (packet, cip, network_group) &i, 0, MDL); save_option (&dhcp_universe, options, oc); option_cache_dereference (&oc, MDL); - + #if defined(RELAY_PORT) relay_port = dhcp_check_relayport(packet); #endif @@ -2180,8 +2186,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) TIME default_lease_time; struct option_cache *oc; isc_result_t result; - TIME ping_timeout; - TIME lease_cltt; + TIME original_cltt; struct in_addr from; TIME remaining_time; struct iaddr cip; @@ -2190,18 +2195,18 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) isc_boolean_t enqueue = ISC_FALSE; #endif int use_old_lease = 0; + int same_client = 0; unsigned i, j; int s1; int ignorep; - struct timeval tv; /* If we're already acking this lease, don't do it again. */ if (lease -> state) return; /* Save original cltt for comparison later. */ - lease_cltt = lease->cltt; + original_cltt = lease->cltt; /* If the lease carries a host record, remember it. */ if (hp) @@ -2379,7 +2384,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) } while (1); } } - + /* Make sure this packet satisfies the configured minimum number of seconds. */ @@ -2493,7 +2498,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) if (host) host_dereference (&host, MDL); return; - } + } /* Drop the request if it's not allowed for this client. */ if (!offer && @@ -2511,7 +2516,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) if (host) host_dereference (&host, MDL); return; - } + } /* Drop the request if booting is specifically denied. */ oc = lookup_option (&server_universe, state -> options, @@ -2633,7 +2638,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) host_dereference (&host, MDL); return; } - + /* Use the ip address of the lease that we finally found in the database. */ lt -> ip_addr = lease -> ip_addr; @@ -2740,7 +2745,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) if (lease_time < 0 /* XXX */ || lease_time > max_lease_time) lease_time = max_lease_time; - + min_lease_time = DEFAULT_MIN_LEASE_TIME; if (min_lease_time > max_lease_time) min_lease_time = max_lease_time; @@ -2823,7 +2828,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) check_pool_threshold(packet, lease, state); /* a client requests an address which is not yet active*/ - if (lease->pool && lease->pool->valid_from && + if (lease->pool && lease->pool->valid_from && cur_time < lease->pool->valid_from) { /* NAK leases before pool activation date */ cip.len = 4; @@ -2834,7 +2839,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) if (host) host_dereference (&host, MDL); return; - + } /* CC: @@ -2852,7 +2857,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) A min-lease-time of 6 seconds effectively switches over all clients in this pool very quickly. */ - + if (lease->pool && lease->pool->valid_until) { if (cur_time >= lease->pool->valid_until) { /* NAK leases after pool expiration date */ @@ -2869,7 +2874,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) if (lease_time > remaining_time) lease_time = remaining_time; } - + if (lease_time < min_lease_time) { if (min_lease_time) lease_time = min_lease_time; @@ -3008,7 +3013,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, state->options, &lease->scope, oc, MDL)) { - + /* Record the uid, if given... */ oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_CLIENT_IDENTIFIER); @@ -3194,7 +3199,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) /* If dhcp-cache-threshold is enabled, see if "lease" can * be reused. */ - use_old_lease = reuse_lease(packet, lt, lease, state, offer); + use_old_lease = reuse_lease(packet, lt, lease, state, offer, + &same_client); if (use_old_lease == 1) { commit = 0; } @@ -3434,7 +3440,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) } /* Use the name of the host declaration if there is one - and no hostname has otherwise been provided, and if the + and no hostname has otherwise been provided, and if the use-host-decl-name flag is set. */ use_host_decl_name(packet, lease, state->options); @@ -3452,9 +3458,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) lookup_option (&server_universe, state->options, j), MDL)) { struct in_addr ia; struct hostent *h; - + memcpy (&ia, lease -> ip_addr.iabuf, 4); - + h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET); if (!h) log_error ("No hostname for %s", inet_ntoa (ia)); @@ -3501,7 +3507,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) save_option (&dhcp_universe, state -> options, oc); } - option_cache_dereference (&oc, MDL); + option_cache_dereference (&oc, MDL); } } } @@ -3560,64 +3566,134 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) /* Hang the packet off the lease state. */ packet_reference (&lease -> state -> packet, packet, MDL); - /* If this is a DHCPOFFER, ping the lease address before actually - sending the offer. */ - if (offer == DHCPOFFER && !(lease -> flags & STATIC_LEASE) && - (((cur_time - lease_cltt) > 60) || - (lease->binding_state == FTS_ABANDONED)) && - (!(oc = lookup_option (&server_universe, state -> options, - SV_PING_CHECKS)) || - evaluate_boolean_option_cache (&ignorep, packet, lease, - (struct client_state *)0, - packet -> options, - state -> options, - &lease -> scope, oc, MDL))) { - icmp_echorequest (&lease -> ip_addr); - - /* Determine whether to use configured or default ping timeout. - */ - if ((oc = lookup_option (&server_universe, state -> options, - SV_PING_TIMEOUT)) && - evaluate_option_cache (&d1, packet, lease, NULL, - packet -> options, - state -> options, - &lease -> scope, oc, MDL)) { - if (d1.len == sizeof (u_int32_t)) - ping_timeout = getULong (d1.data); - else - ping_timeout = DEFAULT_PING_TIMEOUT; - - data_string_forget (&d1, MDL); - } else - ping_timeout = DEFAULT_PING_TIMEOUT; - -#ifdef DEBUG - log_debug ("Ping timeout: %ld", (long)ping_timeout); -#endif - - /* - * Set a timeout for 'ping-timeout' seconds from NOW, including - * current microseconds. As ping-timeout defaults to 1, the - * exclusion of current microseconds causes a value somewhere - * /between/ zero and one. - */ - tv.tv_sec = cur_tv.tv_sec + ping_timeout; - tv.tv_usec = cur_tv.tv_usec; - add_timeout (&tv, lease_ping_timeout, lease, - (tvref_t)lease_reference, - (tvunref_t)lease_dereference); + /* If this is a DHCPOFFER, send a ping (if appropriate) to the + * lease address before actually we send the offer. */ + if ((offer == DHCPOFFER) && + do_ping_check(packet, state, lease, original_cltt, same_client)) { ++outstanding_pings; } else { lease->cltt = cur_time; #if defined(DELAYED_ACK) if (enqueue) delayed_ack_enqueue(lease); - else + else #endif dhcp_reply(lease); } } +/* + * \brief Sends a ping to the lease ip_addr when appropriate + * + * A ping will be sent if all of the following are true: + * + * 1. Ping checks are enabled + * 2. The lease is neither active nor static + * 3. Any of the following is true: + * a. The lease state is ABANDONED + * b. This is the first offer of this lease (CLTT = 0) + * c. The lease is being offered to a client other than its previous + * owner + * d. The lease is being offered to its previous owner and more than + * cltt-secs have elapsed since CLTT of the original lease. + * + * \param packet inbound packet received from the client + * \param state lease options state + * \param lease lease to be offered (if one) + * \param original_cltt CLTT of the original lease + * \param same_client flag indicating if the client to be offered the + * lease is its previous owner + * \return Returns 1 if ping has been sent, 0 otherwise + */ +int do_ping_check(struct packet* packet, struct lease_state* state, + struct lease* lease, TIME original_cltt, + int same_client) { + TIME ping_timeout = DEFAULT_PING_TIMEOUT; + struct option_cache *oc = NULL; + struct data_string ds; + struct timeval tv; + int ignorep; + + // Don't go any further if lease is active or static. + if (lease->binding_state == FTS_ACTIVE || lease->flags & STATIC_LEASE) { + return (0); + } + + // If pings aren't enabled, punt. + oc = lookup_option (&server_universe, state -> options, SV_PING_CHECKS); + if (oc && + !(evaluate_boolean_option_cache (&ignorep, packet, lease, + 0, packet->options, state->options, + &lease->scope, oc, MDL))) { + return (0); + } + + // If it's not the first time for the same client and not an + // abandoned lease, we need to check the cltt threshold + if (same_client && original_cltt && + lease->binding_state != FTS_ABANDONED) { + TIME cltt_secs = DEFAULT_PING_CLTT_SECS; + memset(&ds, 0, sizeof(ds)); + oc = lookup_option (&server_universe, state->options, + SV_PING_CLTT_SECS); + if (oc && + (evaluate_option_cache (&ds, packet, lease, 0, + packet->options, state->options, + &lease->scope, oc, MDL))) { + if (ds.len == sizeof (u_int32_t)) { + cltt_secs = getULong (ds.data); + } + + data_string_forget (&ds, MDL); + } + + // Punt if it is too soon. + if (cur_time - original_cltt < cltt_secs) { + return (0); + } + } + + // Send the ping. + icmp_echorequest (&lease->ip_addr); + + /* Determine whether to use configured or default ping timeout. */ + memset(&ds, 0, sizeof(ds)); + oc = lookup_option (&server_universe, state->options, SV_PING_TIMEOUT); + if (oc && + (evaluate_option_cache (&ds, packet, lease, 0, + packet->options, state->options, + &lease->scope, oc, MDL))) { + if (ds.len == sizeof (u_int32_t)) { + ping_timeout = getULong (ds.data); + } + + data_string_forget (&ds, MDL); + } + +#ifdef DEBUG + log_debug ("Pinging:%s, state: %d, same client? %s, " + " orig_cltt %s, elasped: %ld" , + piaddr(lease->ip_addr), + lease->binding_state, + (same_client ? "y" : "n"), + (original_cltt ? print_time(original_cltt) : "0"), + (original_cltt ? (long)(cur_time - original_cltt) : 0)); +#endif + + /* + * Set a timeout for 'ping-timeout' seconds from NOW, including + * current microseconds. As ping-timeout defaults to 1, the + * exclusion of current microseconds causes a value somewhere + * /between/ zero and one. + */ + tv.tv_sec = cur_tv.tv_sec + ping_timeout; + tv.tv_usec = cur_tv.tv_usec; + add_timeout (&tv, lease_ping_timeout, lease, (tvref_t)lease_reference, + (tvunref_t)lease_dereference); + return (1); +} + + #if defined(DELAYED_ACK) /* @@ -3634,7 +3710,7 @@ delayed_ack_enqueue(struct lease *lease) { struct leasequeue *q; - if (!write_lease(lease)) + if (!write_lease(lease)) return; if (free_ackqueue) { q = free_ackqueue; @@ -3650,7 +3726,7 @@ delayed_ack_enqueue(struct lease *lease) lease_reference(&q->lease, lease, MDL); q->next = ackqueue_head; ackqueue_head = q; - if (!ackqueue_tail) + if (!ackqueue_tail) ackqueue_tail = q; else q->next->prev = q; @@ -3723,7 +3799,7 @@ delayed_acks_timer(void *foo) */ /* process from bottom to retain packet order */ - for (ack = ackqueue_tail ; ack ; ack = p) { + for (ack = ackqueue_tail ; ack ; ack = p) { p = ack->prev; #if defined(FAILOVER_PROTOCOL) @@ -3762,7 +3838,7 @@ void relinquish_ackqueue(void) { struct leasequeue *q, *n; - + for (q = ackqueue_head ; q ; q = n) { n = q->next; dfree(q, MDL); @@ -3811,9 +3887,9 @@ void dhcp_reply (lease) if (sizeof raw.file > state -> filename.len) memset (&raw.file [state -> filename.len], 0, (sizeof raw.file) - state -> filename.len); - else + else log_info("file name longer than packet field " - "truncated - field: %lu name: %d %.*s", + "truncated - field: %lu name: %d %.*s", (unsigned long)sizeof(raw.file), state->filename.len, (int)state->filename.len, state->filename.data); @@ -3830,9 +3906,9 @@ void dhcp_reply (lease) if (sizeof raw.sname > state -> server_name.len) memset (&raw.sname [state -> server_name.len], 0, (sizeof raw.sname) - state -> server_name.len); - else + else log_info("server name longer than packet field " - "truncated - field: %lu name: %d %.*s", + "truncated - field: %lu name: %d %.*s", (unsigned long)sizeof(raw.sname), state->server_name.len, (int)state->server_name.len, @@ -4121,7 +4197,7 @@ int find_lease (struct lease **lp, cip.len = 4; memcpy (cip.iabuf, d1.data, cip.len); data_string_forget (&d1, MDL); - } else + } else cip.len = 0; } @@ -4828,7 +4904,7 @@ int mockup_lease (struct lease **lp, struct packet *packet, { struct lease *lease = (struct lease *)0; struct host_decl *rhp = (struct host_decl *)0; - + if (lease_allocate (&lease, MDL) != ISC_R_SUCCESS) return 0; if (host_reference (&rhp, hp, MDL) != ISC_R_SUCCESS) { @@ -4908,7 +4984,7 @@ int allocate_lease (struct lease **lp, struct packet *packet, /* * In normal operation, we never want to touch - * the peer's leases. In partner-down + * the peer's leases. In partner-down * operation, we need to be able to pick up * the peer's leases after STOS+MCLT. */ @@ -5069,7 +5145,7 @@ int permitted (packet, permit_list) !packet -> packet_type) return 1; break; - + case permit_class: for (i = 0; i < packet -> class_count; i++) { if (p -> class == packet -> classes [i]) @@ -5340,8 +5416,8 @@ get_server_source_address(struct in_addr *from, option_num = DHO_DHCP_SERVER_IDENTIFIER; oc = lookup_option(&dhcp_universe, options, option_num); if (oc != NULL) { - if (evaluate_option_cache(&d, packet, NULL, NULL, - packet->options, options, + if (evaluate_option_cache(&d, packet, NULL, NULL, + packet->options, options, &global_scope, oc, MDL)) { if (d.len == sizeof(*from)) { found = ISC_TRUE; @@ -5376,7 +5452,7 @@ get_server_source_address(struct in_addr *from, if (make_const_data(&oc->expression, (unsigned char *)a, sizeof(*a), 0, allocate, MDL)) { - option_code_hash_lookup(&oc->option, + option_code_hash_lookup(&oc->option, dhcp_universe.code_hash, &option_num, 0, MDL); save_option(&dhcp_universe, out_options, oc); @@ -5628,7 +5704,10 @@ void use_host_decl_name(struct packet* packet, * \param packet inbound packet received from the client * \param new_lease candidate new lease to associate with the client * \param lease current lease associated with the client - * \param options option state to search and update + * \param lease_state lease state to search and update + * \param offer type of DHCP response we're building + * \param[out] same_client pointer to int, that will be set to 1 if + * the two leases refer to the same client, 0 if not. Must NOT be null. * * \return 1 if the lease can be reused. */ @@ -5637,7 +5716,8 @@ reuse_lease (struct packet* packet, struct lease* new_lease, struct lease* lease, struct lease_state *state, - int offer) { + int offer, + int *same_client) { int reusable = 0; /* To even consider reuse all of the following must be true: @@ -5647,16 +5727,20 @@ reuse_lease (struct packet* packet, * 4 - the host declaration hasn't changed * 5 - the uid hasn't changed * 6 - the hardware address hasn't changed */ + + /* Check client equality separately so we can pass the result out. */ + *same_client = + (((lease->host == new_lease->host) && + (lease->uid_len == new_lease->uid_len) && + (memcmp(lease->uid, new_lease->uid, new_lease->uid_len) == 0) && + (lease->hardware_addr.hlen == new_lease->hardware_addr.hlen) && + (memcmp(&lease->hardware_addr.hbuf[0], + &new_lease->hardware_addr.hbuf[0], + lease->hardware_addr.hlen) == 0)) ? 1 : 0); + if ((lease->cannot_reuse == 0) && (lease->binding_state == FTS_ACTIVE) && - (new_lease->ddns_cb == NULL) && - (lease->host == new_lease->host) && - (lease->uid_len == new_lease->uid_len) && - (memcmp(lease->uid, new_lease->uid, lease->uid_len) == 0) && - (lease->hardware_addr.hlen == new_lease->hardware_addr.hlen) && - (memcmp(&lease->hardware_addr.hbuf[0], - &new_lease->hardware_addr.hbuf[0], - lease->hardware_addr.hlen) == 0)) { + (new_lease->ddns_cb == NULL) && *same_client) { int thresh = DEFAULT_CACHE_THRESHOLD; struct option_cache* oc = NULL; struct data_string d1; diff --git a/server/dhcpd.conf.5 b/server/dhcpd.conf.5 index 17330d4e..bd471998 100644 --- a/server/dhcpd.conf.5 +++ b/server/dhcpd.conf.5 @@ -3027,6 +3027,36 @@ checking - if its value is false, no ping check is done. .RE .PP The +.I ping-cltt-secs +statement +.RS 0.25i +.PP +.B ping-cltt-secs +.I seconds\fR\fB;\fR +.PP +The server will conduct a ping check if all the following conditions are true: +.PP +1. Ping checking is enabled. +.PP +2. The server is responding to a DISCOVER. +.PP +3. The lease to be offered is neither static nor active (i.e. still a valid +lease). +.PP +4. And any of the following are true: + a. This will be the first offer of this lease (CLTT is 0). + b. The lease is being offered to a client other than its previous owner + c. The lease is being offered to its previous owner and more than + \fBping-cltt-secs\fR have elapsed since CLTT of the original lease. + d. The lease was abandoned and the server is attempting to reclaim it. + +.PP +The \fBping-cltt-secs\fR statement allows the user to specify the amount of +time that must elaspe after CLTT before a ping check will be conducted. +The default value is sixty seconds. +.RE +.PP +The .I ping-timeout statement .RS 0.25i diff --git a/server/stables.c b/server/stables.c index 170f6da3..75847270 100644 --- a/server/stables.c +++ b/server/stables.c @@ -291,6 +291,7 @@ static struct option server_options[] = { { "release-on-roam", "f", &server_universe, SV_RELEASE_ON_ROAM, 1 }, { "local-address6", "6", &server_universe, SV_LOCAL_ADDRESS6, 1 }, { "bind-local-address6", "f", &server_universe, SV_BIND_LOCAL_ADDRESS6, 1 }, + { "ping-cltt-secs", "T", &server_universe, SV_PING_CLTT_SECS, 1 }, { NULL, NULL, NULL, 0, 0 } }; -- cgit v1.2.1