bound.c revision 985c053e83ff1a26a6ed980f86c6d19f8094d30c
/*
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* BOUND state of the DHCP client state machine.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <sys/sysmacros.h>
#include <dhcp_hostconf.h>
#include <dhcpmsg.h>
#include <stdio.h> /* snprintf */
#include "defaults.h"
#include "arp_check.h"
#include "states.h"
#include "packet.h"
#include "util.h"
#include "agent.h"
#include "interface.h"
#include "script_handler.h"
static int configure_if(struct ifslist *);
static int configure_timers(struct ifslist *);
/*
* bound_event_cb(): callback for script_start on the event EVENT_BOUND
*
* input: struct ifslist *: the interface configured
* const char *: unused
* output: int: always 1
*/
/* ARGSUSED */
static int
{
return (1);
}
/*
* dhcp_bound(): configures an interface and ifs using information contained
* in the ACK packet and sets up lease timers. before starting,
* the requested address is arped to make sure it's not in use.
*
* input: struct ifslist *: the interface to move to bound
* PKT_LIST *: the ACK packet, or NULL if it should use ifsp->if_ack
* output: int: 0 on failure, 1 on success
*/
int
{
int msg_level;
const char *noext = "lease renewed but time not extended";
/* If ack we're replacing is not the original, then free it */
/* Save the first ack as the original */
}
case ADOPTING:
/*
* if we're adopting an interface, the lease timers
* only provide an upper bound since we don't know
* from what time they are relative to. assume we
* have a lease time of at most DHCP_ADOPT_LEASE_MAX.
*/
return (0);
/*
* we have no idea when the REQUEST that generated
* this ACK was sent, but for diagnostic purposes
* we'll assume its close to the current time.
*/
/* FALLTHRU into REQUESTING/INIT_REBOOT */
case REQUESTING:
case INIT_REBOOT:
if (configure_if(ifsp) == 0)
return (0);
if (configure_timers(ifsp) == 0)
return (0);
/*
* if the state is ADOPTING, event loop has not been started
* at this time, so don't run the script.
*/
}
break;
case RENEWING:
case REBINDING:
case BOUND:
if (configure_timers(ifsp) == 0)
return (0);
/*
* if the current lease is mysteriously close to the new
* lease, warn the user. unless there's less than a minute
* left, round to the closest minute.
*/
else
} else if (minleft == 1) {
noext);
} else {
}
}
break;
case INFORM_SENT:
break;
default:
/* something is really bizarre... */
return (0);
}
}
/*
* remove any stale hostconf file that might be lying around for
* this interface. (in general, it's harmless, since we'll write a
* fresh one when we exit anyway, but just to reduce confusion..)
*/
return (1);
}
/*
* configure_timers(): configures the lease timers on an interface
*
* input: struct ifslist *: the interface to configure (with a valid if_ack)
* output: int: 1 on success, 0 on failure
*/
int
{
return (0);
}
/*
* type has already been verified as ACK. if type is not set,
* then we got a BOOTP packet. we now fetch the t1, t2, and
* lease options out of the packet into variables. they are
* returned as relative host-byte-ordered times.
*/
return (1);
}
/*
* according to RFC2131, there is no minimum lease time, but don't
*/
goto failure;
if (lease < DHCP_REBIND_MIN) {
return (1);
}
goto failure;
goto failure;
return (1);
return (0);
}
/*
* configure_if(): configures an interface with DHCP parameters from an ACK
*
* input: struct ifslist *: the interface to configure (with a valid if_ack)
* output: int: 1 on success, 0 on failure
*/
static int
{
struct sockaddr_in *sin;
int i;
/*
* if we're using DHCP, then we'll have a valid CD_SERVER_ID
* (we checked in dhcp_acknak()); set it now so that
* ifsp->if_server is valid in case we need to send_decline().
* note that we use comparisons against opts[CD_DHCP_TYPE]
* since we haven't set DHCP_IF_BOOTP yet (we don't do that
* until we're sure we want the offered address.)
*/
/* no big deal if this fails; we'll just have less diagnostics */
in_use, target_hwaddr[i]);
ifsp->if_bad_offers++;
return (0);
}
return (0);
}
/*
* bring the interface online. note that there is no optimal
* order here: it is considered bad taste (and in > solaris 7,
* likely illegal) to bring an interface up before it has an
* ip address. however, due to an apparent bug in sun fddi
* 5.0, fddi will not obtain a network routing entry unless
* the interface is brought up before it has an ip address.
* we take the lesser of the two evils; if fddi customers have
* problems, they can get a newer fddi distribution which
* fixes the problem.
*/
/* LINTED [ifr_addr is a sockaddr which will be aligned] */
} else {
"mask length is %d instead of %d, ignoring",
/*
* no legitimate IP subnet mask specified.. use best
* guess. recall that if_addr is in network order, so
* imagine it's 0x11223344: then when it is read into
* a register on x86, it becomes 0x44332211, so we
* must ntohl() it to convert it to 0x11223344 in
*/
else /* must be class d */
}
return (0);
}
return (0);
}
} else {
"broadcast address length is %d instead of %d, "
sizeof (ipaddr_t));
/*
* no legitimate IP broadcast specified. compute it
* from the IP address and netmask.
*/
}
return (0);
}
return (0);
}
/*
* the kernel will set the broadcast address for us as part of
* bringing the interface up. since experience has shown that dhcp
* servers sometimes provide a bogus broadcast address, we let the
* kernel set it so that it's guaranteed to be correct.
*
* also, note any inconsistencies and save the broadcast address the
* kernel set so that we can watch for changes to it.
*/
return (0);
}
}
/*
* add each provided router; we'll clean them up when the
* interface goes away or when our lease expires.
*/
"default router list, ignoring default routers");
ifsp->if_nrouters = 0;
}
for (i = 0; i < ifsp->if_nrouters; i++) {
sizeof (ipaddr_t));
&ifsp->if_routers[i]) == 0) {
"default router %s on %s", inet_ntoa(
continue;
}
}
}
return (0);
}
return (0);
}
/*
* we wait until here to bind if_sock_fd because it turns out
* the kernel has difficulties doing binds before interfaces
* are up (although it may work sometimes, it doesn't work all
* the time.) that's okay, because we don't use if_sock_fd
* for receiving data until we're BOUND anyway.
*/
return (0);
}
/*
* we'll be using if_sock_fd for the remainder of the lease;
* blackhole if_dlpi_fd.
*/
return (1);
}