renew.c revision d04ccbb3f3163ae5962a8b7465d9796bff6ca434
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <time.h>
#include <libinetutil.h>
#include <dhcpmsg.h>
#include <string.h>
#include "packet.h"
#include "agent.h"
#include "script_handler.h"
#include "interface.h"
#include "states.h"
#include "util.h"
/*
* Number of seconds to wait for a retry if the user is interacting with the
* daemon.
*/
#define RETRY_DELAY 10
/*
* If the renew timer fires within this number of seconds of the rebind timer,
* then skip renew. This prevents us from sending back-to-back renew and
* rebind messages -- a pointless activity.
*/
#define TOO_CLOSE 2
/*
* dhcp_renew(): attempts to renew a DHCP lease on expiration of the T1 timer.
*
* input: iu_tq_t *: unused
* void *: the lease to renew (dhcp_lease_t)
* output: void
*
* notes: The primary expense involved with DHCP (like most UDP protocols) is
* with the generation and handling of packets, not the contents of
* those packets. Thus, we try to reduce the number of packets that
* are sent. It would be nice to just renew all leases here (each one
* added has trivial added overhead), but the DHCPv6 RFC doesn't
* explicitly allow that behavior. Rather than having that argument,
* we settle for ones that are close in expiry to the one that fired.
* For v4, we repeatedly reschedule the T1 timer to do the
* retransmissions. For v6, we rely on the common timer computation
* in packet.c.
*/
/* ARGSUSED */
void
{
return;
}
/*
* Sanity check: don't send packets if we're past T2, or if we're
* extremely close.
*/
return;
}
/*
* If there isn't an async event pending, or if we can cancel the one
* that's there, then try to renew by sending an extension request. If
* that fails, we'll try again when the next timer fires.
*/
!dhcp_extending(dsmp)) {
/*
* Try again in RETRY_DELAY seconds; user command
* should be gone.
*/
dhcp_renew)) {
"reschedule renewal around user command "
"on %s; will wait for rebind",
}
} else {
}
}
}
/*
* dhcp_rebind(): attempts to renew a DHCP lease from the REBINDING state (T2
* timer expiry).
*
* input: iu_tq_t *: unused
* void *: the lease to renew
* output: void
* notes: For v4, we repeatedly reschedule the T2 timer to do the
* retransmissions. For v6, we rely on the common timer computation
* in packet.c.
*/
/* ARGSUSED */
void
{
int nlifs;
return;
}
/*
* Sanity check: don't send packets if we've already expired on all of
* the addresses. We compute the maximum expiration time here, because
* it won't matter for v4 (there's only one lease) and for v6 we need
* to know when the last lease ages away.
*/
some_valid = B_TRUE;
}
}
if (!some_valid) {
return;
}
/*
* This is our first venture into the REBINDING state, so reset the
* server address. We know the renew timer has already been cancelled
* (or we wouldn't be here).
*/
} else {
&dsmp->dsm_server);
}
/* {Bound,Renew}->rebind transitions cannot fail */
/*
* If there isn't an async event pending, or if we can cancel the one
* that's there, then try to rebind by sending an extension request.
* If that fails, we'll clean up when the lease expires.
*/
!dhcp_extending(dsmp)) {
/*
* Try again in RETRY_DELAY seconds; user command
* should be gone.
*/
dhcp_rebind)) {
"reschedule rebind around user command on "
}
} else {
}
}
}
/*
* dhcp_finish_expire(): finish expiration of a lease after the user script
* runs. If this is the last lease, then restart DHCP.
* The caller has a reference to the LIF, which will be
* dropped.
*
* input: dhcp_smach_t *: the state machine to be restarted
* void *: logical interface that has expired
* output: int: always 1
*/
static int
{
/* If some valid leases remain, then drive on */
"dhcp_finish_expire: some leases remain on %s",
return (1);
}
/*
* in the case where the lease is less than DHCP_REBIND_MIN
* seconds, we will never enter dhcp_renew() and thus the packet
* counters will not be reset. in that case, reset them here.
*/
dsmp->dsm_bad_offers = 0;
dsmp->dsm_received = 0;
}
/* reset_smach() in dhcp_selecting() will clean up any leftover state */
return (1);
}
/*
* dhcp_deprecate(): deprecates an address on a given logical interface when
* the preferred lifetime expires.
*
* input: iu_tq_t *: unused
* void *: the logical interface whose lease is expiring
* output: void
*/
/* ARGSUSED */
void
{
}
/*
* dhcp_expire(): expires a lease on a given logical interface and, if there
* are no more leases, restarts DHCP.
*
* input: iu_tq_t *: unused
* void *: the logical interface whose lease has expired
* output: void
*/
/* ARGSUSED */
void
{
const char *event;
return;
}
if (!async_cancel(dsmp)) {
"dhcp_expire: cannot cancel current asynchronous command "
/*
* Try to schedule ourselves for callback. We're really
* situation-critical here; there's not much hope for us if
* this fails.
*/
return;
"to get called back, proceeding...");
}
/*
* Determine if this state machine has any non-expired LIFs left in it.
* If it doesn't, then this is an "expire" event. Otherwise, if some
* valid leases remain, it's a "loss" event. The SOMEEXP case can
* occur only with DHCPv6.
*/
event = EVENT_LOSS6;
else
/*
* just march on if this fails; at worst someone will be able
* to async_start() while we're actually busy with our own
* asynchronous transaction. better than not having a lease.
*/
}
/*
* extend a lease on a given state machine
*
* input: dhcp_smach_t *: the state machine to send the message from
* output: boolean_t: B_TRUE if the extension request was sent
*/
{
/*
* We change state here because this function is also called when
* adopting a lease and on demand by the user.
*/
dsmp->dsm_bad_offers = 0;
dsmp->dsm_received = 0;
/* Bound->renew can't fail */
}
/*
* a server ID, as we still think our server might be
* reachable.
*/
} else {
}
/*
* Loop over the leases, and add an IA_NA for each and an
* IAADDR for each address.
*/
}
}
/* Add required Option Request option */
} else {
/* assemble the DHCPREQUEST message. */
/*
* The max dhcp message size option is set to the interface
* max, minus the size of the udp and ip headers.
*/
/*
* dsm_reqhost was set for this state machine in
* dhcp_selecting() if the REQUEST_HOSTNAME option was set and
* a host name was found.
*/
}
}
}
/*
* stop_extending(): decides when to stop retransmitting v4 REQUEST or v6
* T2 is soon approaching.
*
* input: dhcp_smach_t *: the state machine REQUESTs are being sent from
* unsigned int: the number of REQUESTs sent so far
* output: boolean_t: B_TRUE if retransmissions should stop
*/
/* ARGSUSED */
static boolean_t
{
/*
* If we're renewing and rebind time is soon approaching, then don't
* schedule
*/
t2 = 0;
}
return (B_TRUE);
}
}
/*
* Note that returning B_TRUE cancels both this transmission and the
* one that would occur at dsm_send_timeout, and that for v4 we cut the
* time in half for each retransmission. Thus we check here against
* half of the minimum.
*/
return (B_TRUE);
}
/* Otherwise, w stop only when the next timer (rebind, expire) fires */
return (B_FALSE);
}