Import dhcpcd-5.2.8 with the following changes from 5.2.4

* Use dynamically sized buffers for reading kernel link events
* Use the active link address
* Added option to dump a lease to stdout
* TEST mode now works correctly if an old lease is NAKed
* routes with the gateway = leased ip are now treated as host routes
This commit is contained in:
roy 2010-10-07 14:35:56 +00:00
parent b5a696dfa9
commit ada0026e42
19 changed files with 423 additions and 196 deletions

View File

@ -551,6 +551,21 @@ get_routes(const struct interface *iface)
iface->name, &iface->state->options->options);
}
/* Some DHCP servers add set host routes by setting the gateway
* to the assinged IP address. This differs from our notion of a host route
* where the gateway is the destination address, so we fix it. */
static struct rt *
massage_host_routes(struct rt *rt, const struct interface *iface)
{
struct rt *r;
for (r = rt; r; r = r->next)
if (r->gate.s_addr == iface->addr.s_addr &&
r->net.s_addr == INADDR_BROADCAST)
r->gate.s_addr = r->dest.s_addr;
return rt;
}
static struct rt *
add_destination_route(struct rt *rt, const struct interface *iface)
{
@ -629,6 +644,7 @@ build_routes(void)
if (ifp->state->new == NULL)
continue;
dnr = get_routes(ifp);
dnr = massage_host_routes(dnr, ifp);
dnr = add_subnet_route(dnr, ifp);
dnr = add_router_host_route(dnr, ifp);
dnr = add_destination_route(dnr, ifp);

View File

@ -28,7 +28,7 @@
#define CONFIG_H
#define PACKAGE "dhcpcd"
#define VERSION "5.2.4"
#define VERSION "5.2.8"
#ifndef CONFIG
# define CONFIG SYSCONFDIR "/" PACKAGE ".conf"

View File

@ -1052,7 +1052,7 @@ write_lease(const struct interface *iface, const struct dhcp_message *dhcp)
syslog(LOG_DEBUG, "%s: writing lease `%s'",
iface->name, iface->leasefile);
fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0400);
fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0444);
if (fd == -1) {
syslog(LOG_ERR, "%s: open: %m", iface->name);
return -1;

View File

@ -0,0 +1,5 @@
# Just echo our DHCP options we have
if [ "$reason" = "DUMP" ]; then
set | sed -ne 's/^new_//p' | sort
fi

View File

@ -4,7 +4,7 @@ mtu_dir="$state_dir/mtu"
if [ "$reason" = PREINIT -a -e "$mtu_dir/$interface" ]; then
rm "$mtu_dir/$interface"
elif [ "$reason" != TEST -a -n "$new_interface_mtu" ]; then
elif [ -n "$new_interface_mtu" ] && $if_up; then
# The smalled MTU dhcpcd can work with is 576
if [ "$new_interface_mtu" -ge 576 ]; then
if ifconfig "$interface" mtu "$new_interface_mtu"; then
@ -16,10 +16,12 @@ elif [ "$reason" != TEST -a -n "$new_interface_mtu" ]; then
fi
fi
fi
elif [ "$reason" != TEST -a -e "$mtu_dir/$interface" ]; then
# No MTU in this state, so restore the prior MTU
mtu=$(cat "$mtu_dir/$interface")
syslog info "$interface: MTU restored to $mtu"
ifconfig "$interface" mtu "$mtu"
rm "$mtu_dir/$interface"
elif [ -e "$mtu_dir/$interface" ]; then
if $if_up || $if_down; then
# No MTU in this state, so restore the prior MTU
mtu=$(cat "$mtu_dir/$interface")
syslog info "$interface: MTU restored to $mtu"
ifconfig "$interface" mtu "$mtu"
rm "$mtu_dir/$interface"
fi
fi

View File

@ -119,7 +119,8 @@ remove_resolv_conf()
fi
}
case "$reason" in
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC) add_resolv_conf;;
PREINIT|EXPIRE|FAIL|IPV4LL|NAK|NOCARRIER|RELEASE|STOP) remove_resolv_conf;;
esac
if $if_up; then
add_resolv_conf
elif $if_down; then
remove_resolv_conf
fi

View File

@ -29,6 +29,6 @@ set_hostname()
fi
}
case "$reason" in
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC) set_hostname;;
esac
if $if_up; then
set_hostname
fi

View File

@ -29,6 +29,6 @@ set_hostname()
fi
}
case "$reason" in
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC) set_hostname;;
esac
if $if_up; then
set_hostname
fi

View File

@ -8,14 +8,12 @@
# NTP_CONF=/usr/pkg/etc/ntpd.conf
# to use openntpd from pkgsrc instead of the system provided ntp.
# Detect OpenRC or BSD rc
# Distributions may want to just have their command here instead of this
if type rc-service >/dev/null 2>&1 && rc-service --exists ntpd; then
ntpd_restart_cmd="rc-service ntpd -- -Ds restart"
elif [ -x /etc/rc.d/ntpd ]; then
ntpd_restart_cmd="/etc/rc.d/ntpd status >/dev/null 2>&1 && /etc/rc.d/ntpd restart"
elif [ -x /usr/local/etc/rc.d/ntpd ]; then
ntpd_restart_cmd="/usr/local/etc/rc.d/ntpd status >/dev/null 2>&1 && /usr/local/etc/rc.d/ntpd restart"
: ${ntpd_restart_cmd:="service_condcommand ntpd restart || service_condcommand ntp restart"}
if type invoke-rc.d >/dev/null 2>&1; then
# Debian has a seperate file for DHCP config to avoid stamping on
# the master.
[ -e /var/lib/ntp ] || mkdir /var/lib/ntp
: ${NTP_DHCP_CONF:=/var/lib/ntp/ntp.conf.dhcp}
fi
ntp_conf_dir="$state_dir/ntp.conf"
@ -48,14 +46,21 @@ build_ntp_conf()
# Merge our config into ntp.conf
[ -e "$cf" ] && rm -f "$cf"
[ -d "$ntp_conf_dir" ] || mkdir -p "$ntp_conf_dir"
if [ -e "$ntp_conf" ]; then
if [ -n "$NTP_DHCP_CONF" ]; then
cp "$ntp_conf" "$cf"
ntp_conf="$NTP_DHCP_CONF"
elif [ -e "$ntp_conf" ]; then
remove_markers "$signature_base" "$signature_base_end" \
"$ntp_conf" > "$cf"
fi
if [ -n "$servers" ]; then
echo "$signature_base${header:+ $from }$header" >> "$cf"
printf "$search$servers" >> "$cf"
echo "$signature_base_end${header:+ $from }$header" >> "$cf"
else
[ -e "$ntp_conf" ] || return
fi
# If we changed anything, restart ntpd
@ -86,7 +91,8 @@ remove_ntp_conf()
build_ntp_conf
}
case "$reason" in
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC) add_ntp_conf add;;
PREINIT|EXPIRE|FAIL|IPV4LL|NAK|NOCARRIER|RELEASE|STOP) remove_ntp_conf del;;
esac
if $if_up; then
add_ntp_conf add
elif $if_down; then
remove_ntp_conf del
fi

View File

@ -1,15 +1,8 @@
# Sample dhcpcd hook for ypbind
# This script is only suitable for the Linux version.
# Distributions may want to just have their command here instead of this
if [ -x /etc/rc.d/ypbind ]; then
ypbind_restart_cmd="/etc/rc.d/ypbind restart"
ypbind_stop_cmd="/etc/rc.d/ypbind stop"
elif [ -x /usr/local/etc/rc.d/ypbind ]; then
ypbind_restart_cmd="/usr/local/etc/rc.d/ypbind restart"
ypbind_stop_cmd="/usr/local/etc/rc.d/ypbind stop"
fi
: ${ypbind_restart_cmd:="service_command ypbind restart"}
: ${ypbind_stop_cmd:="service_condcommand ypbind stop"}
ypbind_dir="$state_dir/ypbind"
best_domain()
@ -70,17 +63,12 @@ restore_yp_binding()
fi
}
case "$reason" in
PREINIT)
if [ "$reason" = PREINIT ]; then
rm -f "$ypbind_dir/$interface"
;;
TEST)
;;
*)
else if $if_up || $if_down; then
if [ -n "$new_nis_domain" ]; then
make_yp_binding
elif [ -n "$old_nis_domain" ]; then
restore_yp_binding
fi
;;
esac
fi

View File

@ -1,4 +1,4 @@
.\" Copyright (c) 2006-2009 Roy Marples
.\" Copyright (c) 2006-2010 Roy Marples
.\" All rights reserved
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd March 23, 2009
.Dd August 24, 2010
.Dt DHCPCD-RUN-HOOKS 8 SMM
.Os
.Sh NAME
@ -110,11 +110,14 @@ means it cannot work as a DHCP or ZeroConf client.
Static configuration and DHCP INFORM is still allowed.
.It Dv STOP
dhcpcd stopped running on the interface.
.iT Dv DUMP
dhcpcd has been asked to dump the last lease for the interface.
.It Dv TEST
dhcpcd received an OFFER from a DHCP server but will not configure the
interface.
This is primarily used to test the variables are filled correctly for the
script to process them.
.El
.Sh FILES
When

View File

@ -9,6 +9,13 @@ signature_base_end="# End of dhcpcd"
signature_end="$signature_base_end $from $interface"
state_dir=/var/run/dhcpcd
if_up=false
if_down=false
case "$reason" in
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC) if_up=true;;
PREINIT|EXPIRE|FAIL|IPV4LL|NAK|NOCARRIER|RELEASE|STOP) if_down=true;;
esac
# Ensure that all arguments are unique
uniqify()
{
@ -91,17 +98,19 @@ remove_markers()
# If different, replace first with second otherwise remove second
change_file()
{
if type cmp >/dev/null 2>&1; then
cmp -s "$1" "$2"
elif type diff >/dev/null 2>&1; then
diff -q "$1" "$2" >/dev/null
else
# Hopefully we're only working on small text files ...
[ "$(cat "$1")" = "$(cat "$2")" ]
fi
if [ $? -eq 0 ]; then
rm -f "$2"
return 1
if [ -e "$1" ]; then
if type cmp >/dev/null 2>&1; then
cmp -s "$1" "$2"
elif type diff >/dev/null 2>&1; then
diff -q "$1" "$2" >/dev/null
else
# Hopefully we're only working on small text files ...
[ "$(cat "$1")" = "$(cat "$2")" ]
fi
if [ $? -eq 0 ]; then
rm -f "$2"
return 1
fi
fi
cat "$2" > "$1"
rm -f "$2"
@ -131,13 +140,40 @@ syslog()
local lvl="$1"
[ -n "$lvl" ] && shift
if [ -n "$@" ]; then
if [ -n "$*" ]; then
if type logger >/dev/null 2>&1; then
logger -t dhcpcd -p daemon."$lvl" -s "$@"
logger -t dhcpcd -p daemon."$lvl" -s "$*"
fi
fi
}
# Check a system service exists
service_exists()
{
@SERVICEEXISTS@
}
# Send a command to a system service
service_cmd()
{
@SERVICECMD@
}
# Send a command to a system service if it is running
service_status()
{
@SERVICESTATUS@
}
# Handy macros for our hooks
service_command()
{
service_exists $1 && service_cmd $1 $2
}
service_condcommand()
{
service_exists $1 && service_status $1 && service_cmd $1 $2
}
# We source each script into this one so that scripts run earlier can
# remove variables from the environment so later scripts don't see them.

View File

@ -88,6 +88,7 @@ char **ifdv = NULL;
static char **margv;
static int margc;
static struct if_options *if_options;
static char **ifv;
static int ifc;
static char *cffile;
@ -161,6 +162,8 @@ cleanup(void)
struct interface *iface;
int i;
free_options(if_options);
while (ifaces) {
iface = ifaces;
ifaces = iface->next;
@ -197,8 +200,13 @@ handle_exit_timeout(_unused void *arg)
int timeout;
syslog(LOG_ERR, "timed out");
if (!(options & DHCPCD_TIMEOUT_IPV4LL))
exit(EXIT_FAILURE);
if (!(options & DHCPCD_TIMEOUT_IPV4LL)) {
if (options & DHCPCD_MASTER) {
daemonise();
return;
} else
exit(EXIT_FAILURE);
}
options &= ~DHCPCD_TIMEOUT_IPV4LL;
timeout = (PROBE_NUM * PROBE_MAX) + PROBE_WAIT + 1;
syslog(LOG_WARNING, "allowing %d seconds for IPv4LL timeout", timeout);
@ -1083,6 +1091,7 @@ start_interface(void *arg)
struct stat st;
struct timeval now;
uint32_t l;
int nolease;
handle_carrier(iface->name);
if (iface->carrier == LINK_DOWN) {
@ -1090,6 +1099,9 @@ start_interface(void *arg)
return;
}
/* We don't want to read the old lease if we NAK an old test */
nolease = iface->state->offer && options & DHCPCD_TEST;
iface->start_uptime = uptime();
free(iface->state->offer);
iface->state->offer = NULL;
@ -1128,7 +1140,7 @@ start_interface(void *arg)
start_inform(iface);
return;
}
} else
} else if (!nolease)
iface->state->offer = read_lease(iface);
if (iface->state->offer) {
get_lease(&iface->state->lease, iface->state->offer);
@ -1324,71 +1336,8 @@ handle_link(_unused void *arg)
syslog(LOG_ERR, "manage_link: %m");
}
/* ARGSUSED */
static void
handle_signal(_unused void *arg)
{
struct interface *iface, *ifl;
int sig = signal_read();
int do_release = 0;
switch (sig) {
case SIGINT:
syslog(LOG_INFO, "received SIGINT, stopping");
break;
case SIGTERM:
syslog(LOG_INFO, "received SIGTERM, stopping");
break;
case SIGALRM:
syslog(LOG_INFO, "received SIGALRM, rebinding lease");
for (iface = ifaces; iface; iface = iface->next)
start_interface(iface);
return;
case SIGHUP:
syslog(LOG_INFO, "received SIGHUP, releasing lease");
do_release = 1;
break;
case SIGUSR1:
syslog(LOG_INFO, "received SIGUSR, reconfiguring");
for (iface = ifaces; iface; iface = iface->next)
if (iface->state->new)
configure(iface);
return;
case SIGPIPE:
syslog(LOG_WARNING, "received SIGPIPE");
return;
default:
syslog(LOG_ERR,
"received signal %d, but don't know what to do with it",
sig);
return;
}
if (options & DHCPCD_TEST)
exit(EXIT_FAILURE);
/* As drop_config could re-arrange the order, we do it like this. */
for (;;) {
/* Be sane and drop the last config first */
ifl = NULL;
for (iface = ifaces; iface; iface = iface->next) {
if (iface->next == NULL)
break;
ifl = iface;
}
if (iface == NULL)
break;
if (iface->carrier != LINK_DOWN &&
(do_release ||
iface->state->options->options & DHCPCD_RELEASE))
send_release(iface);
stop_interface(iface);
}
exit(EXIT_FAILURE);
}
static void
reconf_reboot(struct interface *iface, int argc, char **argv)
if_reboot(struct interface *iface, int argc, char **argv)
{
const struct if_options *ifo;
int opt;
@ -1411,10 +1360,148 @@ reconf_reboot(struct interface *iface, int argc, char **argv)
start_interface(iface);
}
static void
reconf_reboot(int action, int argc, char **argv, int oi)
{
struct interface *ifl, *ifn, *ifp, *ifs, *ift;
ifs = discover_interfaces(argc - oi, argv + oi);
if (ifs == NULL)
return;
/* Remove any old interfaces */
if (ifaces) {
for (ifl = NULL; ifl != ifaces;) {
/* Work our way backwards */
for (ifp = ifaces; ifp; ifp = ifp->next)
if (ifp->next == ifl) {
ifl = ifp;
break;
}
for (ifn = ifs; ifn; ifn = ifn->next)
if (strcmp(ifn->name, ifp->name) == 0)
break;
if (ifn == NULL) {
ifl = ifp->next;
stop_interface(ifp);
}
}
}
for (ifp = ifs; ifp && (ift = ifp->next, 1); ifp = ift) {
ifl = NULL;
for (ifn = ifaces; ifn; ifn = ifn->next) {
if (strcmp(ifn->name, ifp->name) == 0)
break;
ifl = ifn;
}
if (ifn) {
if (action)
if_reboot(ifn, argc, argv);
else if (ifn->state->new)
configure(ifn);
free_interface(ifp);
} else {
ifp->next = NULL;
init_state(ifp, argc, argv);
start_interface(ifp);
if (ifl)
ifl->next = ifp;
else
ifaces = ifp;
}
}
sort_interfaces();
}
/* ARGSUSED */
static void
handle_signal(_unused void *arg)
{
struct interface *ifp, *ifl;
struct if_options *ifo;
int sig = signal_read();
int do_release, do_rebind, i;
do_rebind = do_release = 0;
switch (sig) {
case SIGINT:
syslog(LOG_INFO, "received SIGINT, stopping");
break;
case SIGTERM:
syslog(LOG_INFO, "received SIGTERM, stopping");
break;
case SIGALRM:
syslog(LOG_INFO, "received SIGALRM, rebinding");
for (i = 0; i < ifac; i++)
free(ifav[i]);
free(ifav);
ifav = NULL;
ifac = 0;
for (i = 0; i < ifdc; i++)
free(ifdv[i]);
free(ifdv);
ifdc = 0;
ifdv = NULL;
ifo = read_config(cffile, NULL, NULL, NULL);
add_options(ifo, margc, margv);
/* We need to preserve these two options. */
if (options & DHCPCD_MASTER)
ifo->options |= DHCPCD_MASTER;
if (options & DHCPCD_DAEMONISED)
ifo->options |= DHCPCD_DAEMONISED;
options = ifo->options;
free_options(ifo);
reconf_reboot(1, 0, NULL, 0);
return;
case SIGHUP:
syslog(LOG_INFO, "received SIGHUP, releasing");
do_release = 1;
break;
case SIGUSR1:
syslog(LOG_INFO, "received SIGUSR, reconfiguring");
for (ifp = ifaces; ifp; ifp = ifp->next)
if (ifp->state->new)
configure(ifp);
return;
case SIGPIPE:
syslog(LOG_WARNING, "received SIGPIPE");
return;
default:
syslog(LOG_ERR,
"received signal %d, but don't know what to do with it",
sig);
return;
}
if (options & DHCPCD_TEST)
exit(EXIT_FAILURE);
/* As drop_config could re-arrange the order, we do it like this. */
for (;;) {
/* Be sane and drop the last config first */
ifl = NULL;
for (ifp = ifaces; ifp; ifp = ifp->next) {
if (ifp->next == NULL)
break;
ifl = ifp;
}
if (ifp == NULL)
break;
if (ifp->carrier != LINK_DOWN &&
(do_release ||
ifp->state->options->options & DHCPCD_RELEASE))
send_release(ifp);
stop_interface(ifp);
}
exit(EXIT_FAILURE);
}
int
handle_args(struct fd_list *fd, int argc, char **argv)
{
struct interface *ifs, *ifp, *ifl, *ifn, *ift;
struct interface *ifp;
int do_exit = 0, do_release = 0, do_reboot = 0, do_reconf = 0;
int opt, oi = 0;
ssize_t len;
@ -1537,32 +1624,7 @@ handle_args(struct fd_list *fd, int argc, char **argv)
return 0;
}
if ((ifs = discover_interfaces(argc - optind, argv + optind))) {
for (ifp = ifs; ifp && (ift = ifp->next, 1); ifp = ift) {
ifl = NULL;
for (ifn = ifaces; ifn; ifn = ifn->next) {
if (strcmp(ifn->name, ifp->name) == 0)
break;
ifl = ifn;
}
if (ifn) {
if (do_reboot)
reconf_reboot(ifn, argc, argv);
else if (do_reconf && ifn->state->new)
configure(ifn);
free_interface(ifp);
} else {
ifp->next = NULL;
init_state(ifp, argc, argv);
start_interface(ifp);
if (ifl)
ifl->next = ifp;
else
ifaces = ifp;
}
}
sort_interfaces();
}
reconf_reboot(do_reboot, argc, argv, optind);
return 0;
}
@ -1608,7 +1670,6 @@ close_sockets(struct interface *iface)
int
main(int argc, char **argv)
{
struct if_options *ifo;
struct interface *iface;
int opt, oi = 0, signal_fd, sig = 0, i, control_fd;
size_t len;
@ -1652,6 +1713,9 @@ main(int argc, char **argv)
case 'T':
i = 1;
break;
case 'U':
i = 2;
break;
case 'V':
print_options();
exit(EXIT_SUCCESS);
@ -1663,16 +1727,20 @@ main(int argc, char **argv)
margv = argv;
margc = argc;
ifo = read_config(cffile, NULL, NULL, NULL);
opt = add_options(ifo, argc, argv);
if_options = read_config(cffile, NULL, NULL, NULL);
opt = add_options(if_options, argc, argv);
if (opt != 1) {
if (opt == 0)
usage();
exit(EXIT_FAILURE);
}
options = ifo->options;
options = if_options->options;
if (i != 0) {
options |= DHCPCD_TEST | DHCPCD_PERSISTENT;
if (i == 1)
options |= DHCPCD_TEST;
else
options |= DHCPCD_DUMPLEASE;
options |= DHCPCD_PERSISTENT;
options &= ~DHCPCD_DAEMONISE;
}
@ -1685,7 +1753,7 @@ main(int argc, char **argv)
if (options & DHCPCD_QUIET)
close(STDERR_FILENO);
if (!(options & DHCPCD_TEST)) {
if (!(options & (DHCPCD_TEST | DHCPCD_DUMPLEASE))) {
/* If we have any other args, we should run as a single dhcpcd
* instance for that interface. */
len = strlen(PIDFILE) + IF_NAMESIZE + 2;
@ -1702,6 +1770,36 @@ main(int argc, char **argv)
syslog(LOG_ERR, "chdir `/': %m");
atexit(cleanup);
if (options & DHCPCD_DUMPLEASE) {
if (optind != argc - 1) {
syslog(LOG_ERR, "dumplease requires an interface");
exit(EXIT_FAILURE);
}
ifaces = iface = xzalloc(sizeof(*iface));
strlcpy(iface->name, argv[optind], sizeof(iface->name));
snprintf(iface->leasefile, sizeof(iface->leasefile),
LEASEFILE, iface->name);
iface->state = xzalloc(sizeof(*iface->state));
iface->state->options = xzalloc(sizeof(*iface->state->options));
strlcpy(iface->state->options->script, if_options->script,
sizeof(iface->state->options->script));
iface->state->new = read_lease(iface);
if (iface->state->new == NULL && errno == ENOENT) {
strlcpy(iface->leasefile, argv[optind],
sizeof(iface->leasefile));
iface->state->new = read_lease(iface);
}
if (iface->state->new == NULL) {
if (errno == ENOENT)
syslog(LOG_ERR, "%s: no lease to dump",
iface->name);
exit(EXIT_FAILURE);
}
iface->state->reason = "DUMP";
run_script(iface);
exit(EXIT_SUCCESS);
}
if (!(options & (DHCPCD_MASTER | DHCPCD_TEST))) {
control_fd = open_control();
if (control_fd != -1) {
@ -1812,7 +1910,7 @@ main(int argc, char **argv)
syslog(LOG_ERR, "init_socket: %m");
exit(EXIT_FAILURE);
}
if (ifo->options & DHCPCD_LINK) {
if (if_options->options & DHCPCD_LINK) {
linkfd = open_link_socket();
if (linkfd == -1)
syslog(LOG_ERR, "open_link_socket: %m");
@ -1884,14 +1982,15 @@ main(int argc, char **argv)
{
syslog(LOG_WARNING, "no interfaces have a carrier");
daemonise();
} else if (ifo->timeout > 0) {
} else if (if_options->timeout > 0) {
if (options & DHCPCD_IPV4LL)
options |= DHCPCD_TIMEOUT_IPV4LL;
add_timeout_sec(ifo->timeout, handle_exit_timeout,
NULL);
add_timeout_sec(if_options->timeout,
handle_exit_timeout, NULL);
}
}
free_options(ifo);
free_options(if_options);
if_options = NULL;
sort_interfaces();
for (iface = ifaces; iface; iface = iface->next)

View File

@ -51,6 +51,7 @@ static struct timeout {
struct timeval when;
void (*callback)(void *);
void *arg;
int queue;
struct timeout *next;
} *timeouts;
static struct timeout *free_timeouts;
@ -109,7 +110,8 @@ delete_event(int fd)
}
void
add_timeout_tv(const struct timeval *when, void (*callback)(void *), void *arg)
add_q_timeout_tv(int queue,
const struct timeval *when, void (*callback)(void *), void *arg)
{
struct timeval w;
struct timeout *t, *tt = NULL;
@ -147,6 +149,7 @@ add_timeout_tv(const struct timeval *when, void (*callback)(void *), void *arg)
t->when.tv_usec = w.tv_usec;
t->callback = callback;
t->arg = arg;
t->queue = queue;
/* The timeout list should be in chronological order,
* soonest first.
@ -168,28 +171,30 @@ add_timeout_tv(const struct timeval *when, void (*callback)(void *), void *arg)
}
void
add_timeout_sec(time_t when, void (*callback)(void *), void *arg)
add_q_timeout_sec(int queue, time_t when, void (*callback)(void *), void *arg)
{
struct timeval tv;
tv.tv_sec = when;
tv.tv_usec = 0;
add_timeout_tv(&tv, callback, arg);
add_q_timeout_tv(queue, &tv, callback, arg);
}
/* This deletes all timeouts for the interface EXCEPT for ones with the
* callbacks given. Handy for deleting everything apart from the expire
* timeout. */
void
delete_timeouts(void *arg, void (*callback)(void *), ...)
static void
v_delete_q_timeouts(int queue, void *arg, void (*callback)(void *), va_list v)
{
struct timeout *t, *tt, *last = NULL;
va_list va;
void (*f)(void *);
for (t = timeouts; t && (tt = t->next, 1); t = tt) {
if (t->arg == arg && t->callback != callback) {
va_start(va, callback);
if (t->queue == queue && t->arg == arg &&
t->callback != callback)
{
va_copy(va, v);
while ((f = va_arg(va, void (*)(void *))))
if (f == t->callback)
break;
@ -209,12 +214,32 @@ delete_timeouts(void *arg, void (*callback)(void *), ...)
}
void
delete_timeout(void (*callback)(void *), void *arg)
delete_q_timeouts(int queue, void *arg, void (*callback)(void *), ...)
{
va_list va;
va_start(va, callback);
v_delete_q_timeouts(queue, arg, callback, va);
va_end(va);
}
void
delete_timeouts( void *arg, void (*callback)(void *), ...)
{
va_list va;
va_start(va, callback);
v_delete_q_timeouts(0, arg, callback, va);
va_end(va);
}
void
delete_q_timeout(int queue, void (*callback)(void *), void *arg)
{
struct timeout *t, *tt, *last = NULL;
for (t = timeouts; t && (tt = t->next, 1); t = tt) {
if (t->arg == arg &&
if (t->queue == queue && t->arg == arg &&
(!callback || t->callback == callback))
{
if (last)

View File

@ -30,11 +30,17 @@
#include <time.h>
#define add_timeout_tv(a, b, c) add_q_timeout_tv(0, a, b, c)
#define add_timeout_sec(a, b, c) add_q_timeout_sec(0, a, b, c)
#define delete_timeout(a, b) delete_q_timeout(0, a, b)
void add_event(int fd, void (*)(void *), void *);
void delete_event(int fd);
void add_timeout_sec(time_t, void (*)(void *), void *);
void add_timeout_tv(const struct timeval *, void (*)(void *), void *);
void delete_timeout(void (*)(void *), void *);
void add_q_timeout_sec(int queue, time_t, void (*)(void *), void *);
void add_q_timeout_tv(int queue, const struct timeval *, void (*)(void *),
void *);
void delete_q_timeout(int, void (*)(void *), void *);
void delete_q_timeouts(int, void *, void (*)(void *), ...);
void delete_timeouts(void *, void (*)(void *), ...);
void start_eloop(void);

View File

@ -71,6 +71,8 @@
(((struct sockaddr_in *)(void *)sa)->sin_addr).s_addr : 0
static int r_fd = -1;
static char *link_buf;
static ssize_t link_buflen;
int
if_init(_unused struct interface *iface)
@ -302,11 +304,10 @@ get_addrs(int type, char *cp, struct sockaddr **sa)
}
}
#define BUFFER_LEN 2048
int
manage_link(int fd)
{
char buffer[2048], *p, *e, *cp;
char *p, *e, *cp;
char ifname[IF_NAMESIZE];
ssize_t bytes;
struct rt_msghdr *rtm;
@ -315,9 +316,19 @@ manage_link(int fd)
struct ifa_msghdr *ifam;
struct rt rt;
struct sockaddr *sa, *rti_info[RTAX_MAX];
int len;
for (;;) {
bytes = read(fd, buffer, BUFFER_LEN);
if (ioctl(fd, FIONREAD, &len) == -1)
return -1;
if (link_buflen < len) {
p = realloc(link_buf, len);
if (p == NULL)
return -1;
link_buf = p;
link_buflen = len;
}
bytes = read(fd, link_buf, link_buflen);
if (bytes == -1) {
if (errno == EAGAIN)
return 0;
@ -325,8 +336,8 @@ manage_link(int fd)
continue;
return -1;
}
e = buffer + bytes;
for (p = buffer; p < e; p += rtm->rtm_msglen) {
e = link_buf + bytes;
for (p = link_buf; p < e; p += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)(void *)p;
switch(rtm->rtm_type) {
case RTM_IFANNOUNCE:

View File

@ -95,6 +95,7 @@ const struct option cf_options[] = {
{"require", required_argument, NULL, 'Q'},
{"static", required_argument, NULL, 'S'},
{"test", no_argument, NULL, 'T'},
{"dumplease", no_argument, NULL, 'U'},
{"variables", no_argument, NULL, 'V'},
{"whitelist", required_argument, NULL, 'W'},
{"blacklist", required_argument, NULL, 'X'},
@ -336,7 +337,8 @@ parse_option(struct if_options *ifo, int opt, const char *arg)
case 'g': /* FALLTHROUGH */
case 'n': /* FALLTHROUGH */
case 'x': /* FALLTHROUGH */
case 'T': /* We need to handle non interface options */
case 'T': /* FALLTHROUGH */
case 'U': /* We need to handle non interface options */
break;
case 'b':
ifo->options |= DHCPCD_BACKGROUND;
@ -524,9 +526,7 @@ parse_option(struct if_options *ifo, int opt, const char *arg)
}
break;
case 'z':
/* We only set this if we haven't got any interfaces */
if (!ifaces)
ifav = splitv(&ifac, ifav, arg);
ifav = splitv(&ifac, ifav, arg);
break;
case 'A':
ifo->options &= ~DHCPCD_ARP;
@ -712,9 +712,7 @@ parse_option(struct if_options *ifo, int opt, const char *arg)
ifo->blacklist[ifo->blacklist_len++] = addr2.s_addr;
break;
case 'Z':
/* We only set this if we haven't got any interfaces */
if (!ifaces)
ifdv = splitv(&ifdc, ifdv, arg);
ifdv = splitv(&ifdc, ifdv, arg);
break;
case O_ARPING:
if (parse_addr(&addr, NULL, arg) != 0)
@ -849,8 +847,7 @@ read_config(const char *file,
}
if (skip)
continue;
if (parse_config_line(ifo, option, line) != 1)
break;
parse_config_line(ifo, option, line);
}
fclose(f);

View File

@ -37,7 +37,7 @@
/* Don't set any optional arguments here so we retain POSIX
* compatibility with getopt */
#define IF_OPTS "bc:de:f:gh:i:kl:m:no:pqr:s:t:u:v:wxy:z:ABC:DEF:GHI:JKLO:Q:S:TVW:X:Z:"
#define IF_OPTS "bc:de:f:gh:i:kl:m:no:pqr:s:t:u:v:wxy:z:ABC:DEF:GHI:JKLO:Q:S:TUVW:X:Z:"
#define DEFAULT_TIMEOUT 30
#define DEFAULT_REBOOT 10
@ -76,6 +76,7 @@
#define DHCPCD_CSR_WARNED (1 << 27)
#define DHCPCD_XID_HWADDR (1 << 28)
#define DHCPCD_BROADCAST (1 << 29)
#define DHCPCD_DUMPLEASE (1 << 30)
extern const struct option cf_options[];

View File

@ -322,6 +322,15 @@ discover_interfaces(int argc, char * const *argv)
#endif
#ifdef AF_LINK
const struct sockaddr_dl *sdl;
#ifdef IFLR_ACTIVE
struct if_laddrreq iflr;
int socket_aflink;
socket_aflink = socket(AF_LINK, SOCK_DGRAM, 0);
if (socket_aflink == -1)
return NULL;
memset(&iflr, 0, sizeof(iflr));
#endif
#elif AF_PACKET
const struct sockaddr_ll *sll;
#endif
@ -409,6 +418,23 @@ discover_interfaces(int argc, char * const *argv)
} else if (ifa->ifa_addr != NULL) {
#ifdef AF_LINK
sdl = (const struct sockaddr_dl *)(void *)ifa->ifa_addr;
#ifdef IFLR_ACTIVE
/* We need to check for active address */
strlcpy(iflr.iflr_name, ifp->name,
sizeof(iflr.iflr_name));
memcpy(&iflr.addr, ifa->ifa_addr,
MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr)));
iflr.flags = IFLR_PREFIX;
iflr.prefixlen = sdl->sdl_alen * NBBY;
if (ioctl(socket_aflink, SIOCGLIFADDR, &iflr) == -1 ||
!(iflr.flags & IFLR_ACTIVE))
{
free_interface(ifp);
continue;
}
#endif
switch(sdl->sdl_type) {
case IFT_ETHER:
ifp->family = ARPHRD_ETHER;
@ -464,6 +490,11 @@ discover_interfaces(int argc, char * const *argv)
ifl = ifp;
}
freeifaddrs(ifaddrs);
#ifdef IFLR_ACTIVE
close(socket_aflink);
#endif
return ifs;
}