mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-31 06:15:55 +00:00
merge 17500
This commit is contained in:
3
RELNOTES
3
RELNOTES
@@ -83,6 +83,9 @@ work on other platforms. Please report any problems and suggested fixes to
|
||||
on the DHCPv6 ORO. This resolves a bug where VSIO options were placed
|
||||
in IA_NA encapsulated options fields.
|
||||
|
||||
- Integrated client with stateless, temporary address and prefix delegation
|
||||
support.
|
||||
|
||||
Changes since 4.0.0 (new features)
|
||||
|
||||
- Added DHCPv6 rapid commit support.
|
||||
|
962
client/dhc6.c
962
client/dhc6.c
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
.\" $Id: dhclient.8,v 1.27 2008/01/24 02:43:04 each Exp $
|
||||
.\" $Id: dhclient.8,v 1.28 2008/05/23 13:56:07 fdupont Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2004,2007-2008 by Internet Systems Consortium, Inc. ("ISC")
|
||||
.\" Copyright (c) 1996-2003 by Internet Software Consortium
|
||||
@@ -35,6 +35,27 @@ dhclient - Dynamic Host Configuration Protocol Client
|
||||
.B -6
|
||||
]
|
||||
[
|
||||
.B -S
|
||||
]
|
||||
[
|
||||
.B -N
|
||||
[
|
||||
.B -N...
|
||||
]
|
||||
]
|
||||
[
|
||||
.B -T
|
||||
[
|
||||
.B -T...
|
||||
]
|
||||
]
|
||||
[
|
||||
.B -P
|
||||
[
|
||||
.B -P...
|
||||
]
|
||||
]
|
||||
[
|
||||
.B -p
|
||||
.I port
|
||||
]
|
||||
@@ -53,8 +74,7 @@ dhclient - Dynamic Host Configuration Protocol Client
|
||||
]
|
||||
[
|
||||
.B -r
|
||||
]
|
||||
[
|
||||
|
|
||||
.B -x
|
||||
]
|
||||
[
|
||||
@@ -123,7 +143,23 @@ DHCPv4 protocol to obtain an IPv4 address and configuration parameters.
|
||||
.PP
|
||||
If given the -6 command line argument, dhclient will use the DHCPv6
|
||||
protocol to obtain whatever IPv6 addresses are available along with
|
||||
configuration parameters. Information-request is not yet supported.
|
||||
configuration parameters. But with
|
||||
.B -S
|
||||
it uses Information-request to get only (i.e., without address)
|
||||
stateless configuration parameters.
|
||||
.PP
|
||||
The default DHCPv6 behavior is modified too with
|
||||
.B -T
|
||||
which asks for IPv6 temporary addresses, one set per
|
||||
.B -T
|
||||
flag.
|
||||
.B -P
|
||||
enables the IPv6 prefix delegation.
|
||||
As temporary addresses or prefix delegation disables the normal
|
||||
address query,
|
||||
.B -N
|
||||
restores it. Note it is not recommended to mix queries of different types
|
||||
together, or even to share the lease file between them.
|
||||
.PP
|
||||
If given the --version command line argument, dhclient will print its
|
||||
version number and exit.
|
||||
@@ -198,6 +234,7 @@ the server transmit these messages to some other address. This can
|
||||
be specified with the
|
||||
.B -s
|
||||
flag, followed by the IP address or domain name of the destination.
|
||||
This feature is not supported by DHCPv6.
|
||||
.PP
|
||||
For testing purposes, the giaddr field of all packets that the client
|
||||
sends can be set using the
|
||||
|
@@ -76,11 +76,14 @@ int onetry=0;
|
||||
int quiet = 1;
|
||||
int nowait = 0;
|
||||
int stateless = 0;
|
||||
int wanted_ia_na = -1; /* the absolute value is the real one. */
|
||||
int wanted_ia_ta = 0;
|
||||
int wanted_ia_pd = 0;
|
||||
char *mockup_relay = NULL;
|
||||
|
||||
void run_stateless(int exit_mode);
|
||||
|
||||
static void usage PROTO ((void));
|
||||
static void usage(void);
|
||||
|
||||
static isc_result_t write_duid(struct data_string *duid);
|
||||
|
||||
@@ -91,7 +94,7 @@ main(int argc, char **argv) {
|
||||
struct interface_info *ip;
|
||||
struct client_state *client;
|
||||
unsigned seed;
|
||||
char *server = (char *)0;
|
||||
char *server = NULL;
|
||||
isc_result_t status;
|
||||
int exit_mode = 0;
|
||||
int release_mode = 0;
|
||||
@@ -226,13 +229,46 @@ main(int argc, char **argv) {
|
||||
tmp->next = client_env;
|
||||
client_env = tmp;
|
||||
client_env_count++;
|
||||
#ifdef DHCPv6
|
||||
} else if (!strcmp(argv[i], "-S")) {
|
||||
if (local_family_set && (local_family == AF_INET)) {
|
||||
usage();
|
||||
}
|
||||
local_family_set = 1;
|
||||
local_family = AF_INET6;
|
||||
wanted_ia_na = 0;
|
||||
stateless = 1;
|
||||
} else if (!strcmp(argv[i], "-N")) {
|
||||
if (local_family_set && (local_family == AF_INET)) {
|
||||
usage();
|
||||
}
|
||||
local_family_set = 1;
|
||||
local_family = AF_INET6;
|
||||
if (wanted_ia_na < 0) {
|
||||
wanted_ia_na = 0;
|
||||
}
|
||||
wanted_ia_na++;
|
||||
} else if (!strcmp(argv[i], "-T")) {
|
||||
if (local_family_set && (local_family == AF_INET)) {
|
||||
usage();
|
||||
}
|
||||
local_family_set = 1;
|
||||
local_family = AF_INET6;
|
||||
if (wanted_ia_na < 0) {
|
||||
wanted_ia_na = 0;
|
||||
}
|
||||
wanted_ia_ta++;
|
||||
} else if (!strcmp(argv[i], "-P")) {
|
||||
if (local_family_set && (local_family == AF_INET)) {
|
||||
usage();
|
||||
}
|
||||
local_family_set = 1;
|
||||
local_family = AF_INET6;
|
||||
if (wanted_ia_na < 0) {
|
||||
wanted_ia_na = 0;
|
||||
}
|
||||
wanted_ia_pd++;
|
||||
#endif /* DHCPv6 */
|
||||
} else if (!strcmp(argv[i], "-v")) {
|
||||
quiet = 0;
|
||||
} else if (!strcmp(argv[i], "--version")) {
|
||||
@@ -243,7 +279,8 @@ main(int argc, char **argv) {
|
||||
} else if (interfaces_requested < 0) {
|
||||
usage();
|
||||
} else {
|
||||
struct interface_info *tmp = (struct interface_info *)0;
|
||||
struct interface_info *tmp = NULL;
|
||||
|
||||
status = interface_allocate(&tmp, MDL);
|
||||
if (status != ISC_R_SUCCESS)
|
||||
log_fatal("Can't record interface %s:%s",
|
||||
@@ -263,6 +300,15 @@ main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (wanted_ia_na < 0) {
|
||||
wanted_ia_na = 1;
|
||||
}
|
||||
|
||||
/* Support only one (requested) interface for Prefix Delegation. */
|
||||
if (wanted_ia_pd && (interfaces_requested != 1)) {
|
||||
usage();
|
||||
}
|
||||
|
||||
if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
|
||||
path_dhclient_conf = s;
|
||||
}
|
||||
@@ -382,7 +428,9 @@ main(int argc, char **argv) {
|
||||
|
||||
/* Stateless special case. */
|
||||
if (stateless) {
|
||||
if (release_mode || (interfaces_requested != 1)) {
|
||||
if (release_mode || (wanted_ia_na > 0) ||
|
||||
wanted_ia_ta || wanted_ia_pd ||
|
||||
(interfaces_requested != 1)) {
|
||||
usage();
|
||||
}
|
||||
run_stateless(exit_mode);
|
||||
@@ -404,17 +452,22 @@ main(int argc, char **argv) {
|
||||
/* XXX */
|
||||
/* config_counter(&snd_counter, &rcv_counter); */
|
||||
|
||||
/* If no broadcast interfaces were discovered, call the script
|
||||
and tell it so. */
|
||||
/*
|
||||
* If no broadcast interfaces were discovered, call the script
|
||||
* and tell it so.
|
||||
*/
|
||||
if (!interfaces) {
|
||||
/* Call dhclient-script with the NBI flag, in case somebody
|
||||
cares. */
|
||||
script_init ((struct client_state *)0, "NBI",
|
||||
(struct string_list *)0);
|
||||
script_go ((struct client_state *)0);
|
||||
/*
|
||||
* Call dhclient-script with the NBI flag,
|
||||
* in case somebody cares.
|
||||
*/
|
||||
script_init(NULL, "NBI", NULL);
|
||||
script_go(NULL);
|
||||
|
||||
/* If we haven't been asked to persist, waiting for new
|
||||
interfaces, then just exit. */
|
||||
/*
|
||||
* If we haven't been asked to persist, waiting for new
|
||||
* interfaces, then just exit.
|
||||
*/
|
||||
if (!persist) {
|
||||
/* Nothing more to do. */
|
||||
log_info("No broadcast interfaces found - exiting.");
|
||||
@@ -423,8 +476,10 @@ main(int argc, char **argv) {
|
||||
} else if (!release_mode && !exit_mode) {
|
||||
/* Call the script with the list of interfaces. */
|
||||
for (ip = interfaces; ip; ip = ip->next) {
|
||||
/* If interfaces were specified, don't configure
|
||||
interfaces that weren't specified! */
|
||||
/*
|
||||
* If interfaces were specified, don't configure
|
||||
* interfaces that weren't specified!
|
||||
*/
|
||||
if ((interfaces_requested > 0) &&
|
||||
((ip->flags & (INTERFACE_REQUESTED |
|
||||
INTERFACE_AUTOMATIC)) !=
|
||||
@@ -543,7 +598,7 @@ main(int argc, char **argv) {
|
||||
|
||||
/* Start up a listener for the object management API protocol. */
|
||||
if (top_level_config.omapi_port != -1) {
|
||||
listener = (omapi_object_t *)0;
|
||||
listener = NULL;
|
||||
result = omapi_generic_new(&listener, MDL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
log_fatal("Can't allocate new generic object: %s\n",
|
||||
@@ -596,7 +651,7 @@ static void usage ()
|
||||
|
||||
log_error("Usage: dhclient %s %s",
|
||||
#ifdef DHCPv6
|
||||
"[-4|-6] [-S1dvrx] [-nw] [-p <port>]",
|
||||
"[-4|-6] [-SNTP1dvrx] [-nw] [-p <port>]",
|
||||
#else /* DHCPv6 */
|
||||
"[-1dvrx] [-nw] [-p <port>]",
|
||||
#endif /* DHCPv6 */
|
||||
@@ -608,6 +663,7 @@ static void usage ()
|
||||
|
||||
void run_stateless(int exit_mode)
|
||||
{
|
||||
#ifdef DHCPv6
|
||||
struct client_state *client;
|
||||
omapi_object_t *listener;
|
||||
isc_result_t result;
|
||||
@@ -647,7 +703,7 @@ void run_stateless(int exit_mode)
|
||||
|
||||
/* Start up a listener for the object management API protocol. */
|
||||
if (top_level_config.omapi_port != -1) {
|
||||
listener = (omapi_object_t *)0;
|
||||
listener = NULL;
|
||||
result = omapi_generic_new(&listener, MDL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
log_fatal("Can't allocate new generic object: %s\n",
|
||||
@@ -685,6 +741,7 @@ void run_stateless(int exit_mode)
|
||||
dispatch();
|
||||
|
||||
/*NOTREACHED*/
|
||||
#endif /* DHCPv6 */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -766,20 +823,24 @@ void state_reboot (cpp)
|
||||
/* We are in the rebooting state. */
|
||||
client -> state = S_REBOOTING;
|
||||
|
||||
/* make_request doesn't initialize xid because it normally comes
|
||||
from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
|
||||
so pick an xid now. */
|
||||
/*
|
||||
* make_request doesn't initialize xid because it normally comes
|
||||
* from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
|
||||
* so pick an xid now.
|
||||
*/
|
||||
client -> xid = random ();
|
||||
|
||||
/* Make a DHCPREQUEST packet, and set appropriate per-interface
|
||||
flags. */
|
||||
/*
|
||||
* Make a DHCPREQUEST packet, and set
|
||||
* appropriate per-interface flags.
|
||||
*/
|
||||
make_request (client, client -> active);
|
||||
client -> destination = iaddr_broadcast;
|
||||
client -> first_sending = cur_time;
|
||||
client -> interval = client -> config -> initial_interval;
|
||||
|
||||
/* Zap the medium list... */
|
||||
client -> medium = (struct string_list *)0;
|
||||
client -> medium = NULL;
|
||||
|
||||
/* Send out the first DHCPREQUEST packet. */
|
||||
send_request (client);
|
||||
@@ -809,8 +870,10 @@ void state_init (cpp)
|
||||
send_discover (client);
|
||||
}
|
||||
|
||||
/* state_selecting is called when one or more DHCPOFFER packets have been
|
||||
received and a configurable period of time has passed. */
|
||||
/*
|
||||
* state_selecting is called when one or more DHCPOFFER packets have been
|
||||
* received and a configurable period of time has passed.
|
||||
*/
|
||||
|
||||
void state_selecting (cpp)
|
||||
void *cpp;
|
||||
@@ -821,31 +884,39 @@ void state_selecting (cpp)
|
||||
|
||||
ASSERT_STATE(state, S_SELECTING);
|
||||
|
||||
/* Cancel state_selecting and send_discover timeouts, since either
|
||||
one could have got us here. */
|
||||
/*
|
||||
* Cancel state_selecting and send_discover timeouts, since either
|
||||
* one could have got us here.
|
||||
*/
|
||||
cancel_timeout (state_selecting, client);
|
||||
cancel_timeout (send_discover, client);
|
||||
|
||||
/* We have received one or more DHCPOFFER packets. Currently,
|
||||
the only criterion by which we judge leases is whether or
|
||||
not we get a response when we arp for them. */
|
||||
picked = (struct client_lease *)0;
|
||||
/*
|
||||
* We have received one or more DHCPOFFER packets. Currently,
|
||||
* the only criterion by which we judge leases is whether or
|
||||
* not we get a response when we arp for them.
|
||||
*/
|
||||
picked = NULL;
|
||||
for (lp = client -> offered_leases; lp; lp = next) {
|
||||
next = lp -> next;
|
||||
|
||||
/* Check to see if we got an ARPREPLY for the address
|
||||
in this particular lease. */
|
||||
/*
|
||||
* Check to see if we got an ARPREPLY for the address
|
||||
* in this particular lease.
|
||||
*/
|
||||
if (!picked) {
|
||||
picked = lp;
|
||||
picked -> next = (struct client_lease *)0;
|
||||
picked -> next = NULL;
|
||||
} else {
|
||||
destroy_client_lease (lp);
|
||||
}
|
||||
}
|
||||
client -> offered_leases = (struct client_lease *)0;
|
||||
client -> offered_leases = NULL;
|
||||
|
||||
/* If we just tossed all the leases we were offered, go back
|
||||
to square one. */
|
||||
/*
|
||||
* If we just tossed all the leases we were offered, go back
|
||||
* to square one.
|
||||
*/
|
||||
if (!picked) {
|
||||
client -> state = S_INIT;
|
||||
state_init (client);
|
||||
|
@@ -242,6 +242,12 @@ if [ ${reason} = PREINIT6 ] ; then
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
||||
if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then
|
||||
echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix}
|
||||
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
||||
if [ ${reason} = BOUND6 ] ; then
|
||||
if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
|
||||
exit_with_hooks 2;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $Id: freebsd,v 1.21 2008/01/16 23:02:10 dhankins Exp $
|
||||
# $Id: freebsd,v 1.22 2008/05/23 13:56:07 fdupont Exp $
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
@@ -306,6 +306,12 @@ if [ ${reason} = PREINIT6 ] ; then
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
||||
if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then
|
||||
echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix}
|
||||
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
||||
if [ ${reason} = BOUND6 ] ; then
|
||||
if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
|
||||
exit_with_hooks 2;
|
||||
@@ -332,13 +338,11 @@ if [ ${reason} = RENEW6 ] || [ ${reason} = REBIND6 ] ; then
|
||||
fi
|
||||
|
||||
if [ ${reason} = DEPREF6 ] ; then
|
||||
if [ x${new_ip6_prefixlen} = x ] ; then
|
||||
if [ x${new_ip6_address} = x ] ; then
|
||||
exit_with_hooks 2;
|
||||
fi
|
||||
|
||||
# XXX:
|
||||
# There doesn't appear to be a way to update an addr to indicate
|
||||
# preference.
|
||||
ifconfig ${interface} inet6 ${new_ip6_address} deprecated
|
||||
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
@@ -243,6 +243,12 @@ if [ ${reason} = PREINIT6 ] ; then
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
||||
if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then
|
||||
echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix}
|
||||
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
||||
if [ ${reason} = BOUND6 ] ; then
|
||||
if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
|
||||
exit_with_hooks 2;
|
||||
@@ -274,10 +280,8 @@ if [ ${reason} = DEPREF6 ] ; then
|
||||
exit_with_hooks 2;
|
||||
fi
|
||||
|
||||
# There doesn't appear to be a way to update an addr to indicate
|
||||
# preference.
|
||||
# ${ip} -f inet6 addr ??? ${new_ip6_address}/${new_ip6_prefixlen} \
|
||||
# dev ${interface} scope global deprecated?
|
||||
${ip} -f inet6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \
|
||||
dev ${interface} scope global preferred_lft 0
|
||||
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
@@ -242,6 +242,12 @@ if [ ${reason} = PREINIT6 ] ; then
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
||||
if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then
|
||||
echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix}
|
||||
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
||||
if [ ${reason} = BOUND6 ] ; then
|
||||
if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
|
||||
exit_with_hooks 2;
|
||||
|
@@ -242,6 +242,12 @@ if [ ${reason} = PREINIT6 ] ; then
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
||||
if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then
|
||||
echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix}
|
||||
|
||||
exit_with_hooks 0
|
||||
fi
|
||||
|
||||
if [ ${reason} = BOUND6 ] ; then
|
||||
if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
|
||||
exit_with_hooks 2;
|
||||
|
@@ -2441,6 +2441,10 @@ char *piaddrcidr(const struct iaddr *, unsigned int);
|
||||
/* dhclient.c */
|
||||
extern int nowait;
|
||||
|
||||
extern int wanted_ia_na;
|
||||
extern int wanted_ia_ta;
|
||||
extern int wanted_ia_pd;
|
||||
|
||||
extern const char *path_dhclient_conf;
|
||||
extern const char *path_dhclient_db;
|
||||
extern const char *path_dhclient_pid;
|
||||
|
Reference in New Issue
Block a user