Remove DEBUG_MEMORY guard and always free memory and resources.

Remove all atexit(3) and exit(3) calls, instead exiting via the eloop.
This commit is contained in:
Roy Marples 2014-02-04 14:39:26 +00:00
parent 47ecfbd002
commit a9d78def54
22 changed files with 359 additions and 365 deletions

50
auth.c
View File

@ -78,7 +78,16 @@ void
dhcp_auth_reset(struct authstate *state)
{
state->replay = 0;
if (state->token) {
free(state->token->key);
free(state->token->realm);
free(state->token);
state->token = NULL;
}
if (state->reconf) {
free(state->reconf->key);
free(state->reconf->realm);
free(state->reconf);
state->reconf = NULL;
}
@ -270,7 +279,11 @@ dhcp_auth_validate(struct authstate *state, const struct auth *auth,
gottoken:
/* First message from the server */
if (state->token && state->token != t) {
if (state->token &&
(state->token->secretid != t->secretid ||
state->token->realm_len != t->realm_len ||
memcmp(state->token->realm, t->realm, t->realm_len)))
{
errno = EPERM;
return NULL;
}
@ -317,7 +330,40 @@ gottoken:
finish:
/* If we got here then authentication passed */
state->replay = replay;
state->token = t;
if (state->token == NULL) {
/* We cannot just save a pointer because a reconfigure will
* recreate the token list. So we duplicate it. */
state->token = malloc(sizeof(*state->token));
if (state->token) {
state->token->secretid = t->secretid;
state->token->key = malloc(t->key_len);
if (state->token->key) {
state->token->key_len = t->key_len;
memcpy(state->token->key, t->key, t->key_len);
} else {
free(state->token);
state->token = NULL;
}
if (t->realm) {
state->token->realm = malloc(t->realm_len);
if (state->token->realm) {
state->token->realm_len = t->realm_len;
memcpy(state->token->realm, t->realm,
t->realm_len);
} else {
free(state->token->key);
free(state->token);
state->token = NULL;
}
} else {
state->token->realm = NULL;
state->token->realm_len = 0;
}
}
/* If we cannot save the token, we must invalidate */
if (state->token == NULL)
return NULL;
}
return t;
}

2
auth.h
View File

@ -67,7 +67,7 @@ struct auth {
struct authstate {
uint64_t replay;
const struct token *token;
struct token *token;
struct token *reconf;
};

View File

@ -64,18 +64,6 @@ static char hostname_buffer[HOSTNAME_MAX_LEN + 1];
int clock_monotonic;
static char *lbuf;
static size_t lbuf_len;
#ifdef DEBUG_MEMORY
static char lbuf_set;
#endif
#ifdef DEBUG_MEMORY
static void
free_lbuf(void)
{
free(lbuf);
lbuf = NULL;
}
#endif
/* Handy routine to read very long lines in text files.
* This means we read the whole line and avoid any nasty buffer overflows.
@ -88,13 +76,6 @@ get_line(FILE * __restrict fp)
char *p;
ssize_t bytes;
#ifdef DEBUG_MEMORY
if (lbuf_set == 0) {
atexit(free_lbuf);
lbuf_set = 1;
}
#endif
do {
bytes = getline(&lbuf, &lbuf_len, fp);
if (bytes == -1)
@ -107,6 +88,14 @@ get_line(FILE * __restrict fp)
return p;
}
void
get_line_free(void)
{
free(lbuf);
lbuf_len = 0;
}
int
set_cloexec(int fd)
{

View File

@ -102,6 +102,7 @@
int set_cloexec(int);
int set_nonblock(int);
char *get_line(FILE * __restrict);
void get_line_free(void);
const char *get_hostname(int);
extern int clock_monotonic;
int get_monotonic(struct timeval *);

9
configure vendored
View File

@ -293,21 +293,16 @@ for x in $INCLUDEDIR; do
echo "CPPFLAGS+= -I$x" >>$CONFIG_MK
done
if [ -n "$DEBUG" -a "$DEBUG" != no -a "$DEBUG" != false ]; then
echo "Enabling memory debugging"
echo "CPPFLAGS+= -DDEBUG_MEMORY" >>$CONFIG_MK
echo "CFLAGS+= -g" >>$CONFIG_MK
elif [ -z "$DEBUG" -a -f .fslckout ]; then
if [ -z "$DEBUG" -a -f .fslckout ]; then
printf "Found fossil checkout ... "
DEBUG=yes
echo "CFLAGS+= -g" >>$CONFIG_MK
else
DEBUG=no
fi
if [ "$DEBUG" != no -a "$DEBUG" != false ]; then
echo "Adding debugging CFLAGS"
cat <<EOF >>$CONFIG_MK
CFLAGS+= -Wall -Wextra -Wimplicit -Wshadow -Wformat=2
CFLAGS+= -g -Wall -Wextra -Wimplicit -Wshadow -Wformat=2
CFLAGS+= -Wmissing-prototypes -Wmissing-declarations
CFLAGS+= -Wmissing-noreturn -Wmissing-format-attribute
CFLAGS+= -Wredundant-decls -Wnested-externs

View File

@ -48,21 +48,6 @@ static char *argvp[255];
static struct sockaddr_un sun;
struct fd_list *control_fds = NULL;
#ifdef DEBUG_MEMORY
static void
cleanup(void)
{
struct fd_list *f;
f = control_fds;
while (f) {
control_fds = f->next;
free(f);
f = control_fds;
}
}
#endif
static void
control_remove(void *arg)
{
@ -201,9 +186,6 @@ control_open(void)
if ((len = make_sock()) == -1)
return -1;
#ifdef DEBUG_MEMORY
atexit(cleanup);
#endif
return connect(fd, (struct sockaddr *)&sun, len);
}

7
dev.c
View File

@ -63,11 +63,12 @@ dev_listening(void)
}
void
dev_stop(void)
dev_stop(int stop)
{
if (dev) {
syslog(LOG_DEBUG, "dev: unloaded %s", dev->name);
if (stop)
syslog(LOG_DEBUG, "dev: unloaded %s", dev->name);
dev->stop();
free(dev);
dev = NULL;
@ -168,7 +169,7 @@ dev_start(const char *plugin)
if (fd != -1) {
if (eloop_event_add(fd, dev_handle_data, NULL) == -1) {
syslog(LOG_ERR, "%s: eloop_event_add: %m", __func__);
dev_stop();
dev_stop(1);
return -1;
}
}

2
dev.h
View File

@ -48,7 +48,7 @@ int dev_init(struct dev *, const struct dev_dhcpcd *);
int dev_initialized(const char *);
int dev_listening(void);
int dev_start(const char *);
void dev_stop(void);
void dev_stop(int);
#else
#define dev_initialized(a) 1
#define dev_listening() 0

73
dhcp.c
View File

@ -143,16 +143,6 @@ dhcp_printoptions(void)
printf("%03d %s\n", opt->option, opt->var);
}
#ifdef DEBUG_MEMORY
static void
dhcp_cleanup(void)
{
free(packet);
free(opt_buffer);
}
#endif
#define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL)
static const uint8_t *
get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len)
@ -1816,7 +1806,8 @@ dhcp_bind(void *arg)
if (options & DHCPCD_TEST) {
state->reason = "TEST";
script_runreason(iface, state->reason);
exit(EXIT_SUCCESS);
eloop_exit(EXIT_SUCCESS);
return;
}
if (state->reason == NULL) {
if (state->old) {
@ -1842,13 +1833,14 @@ dhcp_bind(void *arg)
iface->name, lease->renewaltime, lease->rebindtime);
}
ipv4_applyaddr(iface);
daemonise();
if (!ipv4ll)
arp_close(iface);
state->state = DHS_BOUND;
if (ifo->options & DHCPCD_ARP) {
state->claims = 0;
arp_announce(iface);
if (daemonise() == 0) {
if (!ipv4ll)
arp_close(iface);
state->state = DHS_BOUND;
if (ifo->options & DHCPCD_ARP) {
state->claims = 0;
arp_announce(iface);
}
}
}
@ -2065,24 +2057,6 @@ dhcp_drop(struct interface *ifp, const char *reason)
state->old = NULL;
state->lease.addr.s_addr = 0;
ifp->options->options &= ~ DHCPCD_CSR_WARNED;
state->auth.token = NULL;
state->auth.replay = 0;
free(state->auth.reconf);
state->auth.reconf = NULL;
/* If we don't have any more DHCP enabled interfaces,
* close the global socket */
if (ifaces) {
TAILQ_FOREACH(ifp, ifaces, next) {
if (D_STATE(ifp))
break;
}
}
if (ifp == NULL && udp_fd != -1) {
close(udp_fd);
eloop_event_delete(udp_fd);
udp_fd = -1;
}
}
static void
@ -2373,7 +2347,8 @@ dhcp_handledhcp(struct interface *iface, struct dhcp_message **dhcpp,
state->offer = NULL;
state->reason = "TEST";
script_runreason(iface, state->reason);
exit(EXIT_SUCCESS);
eloop_exit(EXIT_SUCCESS);
return;
}
eloop_timeout_delete(send_discover, iface);
/* We don't request BOOTP addresses */
@ -2618,9 +2593,6 @@ dhcp_open(struct interface *ifp)
syslog(LOG_ERR, "%s: %m", __func__);
return -1;
}
#ifdef DEBUG_MEMORY
atexit(dhcp_cleanup);
#endif
}
state = D_STATE(ifp);
@ -2705,6 +2677,27 @@ dhcp_free(struct interface *ifp)
free(state);
ifp->if_data[IF_DATA_DHCP] = NULL;
}
/* If we don't have any more DHCP enabled interfaces,
* close the global socket and release resources */
if (ifaces) {
TAILQ_FOREACH(ifp, ifaces, next) {
if (D_STATE(ifp))
break;
}
}
if (ifp == NULL) {
if (udp_fd != -1) {
close(udp_fd);
eloop_event_delete(udp_fd);
udp_fd = -1;
}
free(packet);
free(opt_buffer);
packet = NULL;
opt_buffer = NULL;
}
}
static int

39
dhcp6.c
View File

@ -131,17 +131,6 @@ static const char * const dhcp6_statuses[] = {
"Use Multicast"
};
#if DEBUG_MEMORY
static void
dhcp6_cleanup(void)
{
free(sndbuf);
free(rcvbuf);
free(status);
}
#endif
void
dhcp6_printoptions(void)
{
@ -157,10 +146,6 @@ dhcp6_init(void)
{
int len;
#if DEBUG_MEMORY
atexit(dhcp6_cleanup);
#endif
len = CMSG_SPACE(sizeof(struct in6_pktinfo));
sndbuf = calloc(1, len);
if (sndbuf == NULL)
@ -2481,10 +2466,7 @@ recv:
(ifp->options->options & DHCPCD_INFORM &&
!(options & DHCPCD_MASTER)))
{
#ifdef DEBUG_MEMORY
dhcp6_free(ifp);
#endif
exit(EXIT_SUCCESS);
eloop_exit(EXIT_SUCCESS);
}
}
@ -2708,23 +2690,30 @@ dhcp6_freedrop(struct interface *ifp, int drop, const char *reason)
free(state->recv);
free(state->new);
free(state->old);
free(state->auth.reconf);
free(state);
ifp->if_data[IF_DATA_DHCP6] = NULL;
}
/* If we don't have any more DHCP6 enabled interfaces,
* close the global socket */
* close the global socketo and release resources */
if (ifaces) {
TAILQ_FOREACH(ifp, ifaces, next) {
if (D6_STATE(ifp))
break;
}
}
if (ifp == NULL && sock != -1) {
close(sock);
eloop_event_delete(sock);
sock = -1;
if (ifp == NULL) {
if (sock != -1) {
close(sock);
eloop_event_delete(sock);
sock = -1;
}
free(sndbuf);
free(rcvbuf);
free(status);
sndbuf = NULL;
rcvbuf = NULL;
status = NULL;
}
}

203
dhcpcd.c
View File

@ -87,7 +87,6 @@ const int handle_sigs[] = {
};
static char *cffile;
static char *pidfile;
static int linkfd = -1;
static char **ifv;
static int ifc;
@ -95,7 +94,7 @@ static char **margv;
static int margc;
static pid_t
read_pid(void)
read_pid(const char *pidfile)
{
FILE *fp;
pid_t pid;
@ -162,46 +161,6 @@ free_globals(void)
free(vivso);
}
static void
cleanup(void)
{
#ifdef DEBUG_MEMORY
struct interface *ifp;
free(duid);
free_options(if_options);
if (ifaces) {
while ((ifp = TAILQ_FIRST(ifaces))) {
TAILQ_REMOVE(ifaces, ifp, next);
free_interface(ifp);
}
free(ifaces);
}
free_globals();
#endif
if (!(options & DHCPCD_FORKED))
dev_stop();
if (linkfd != -1)
close(linkfd);
if (pidfd > -1) {
if (options & DHCPCD_MASTER) {
if (control_stop() == -1)
syslog(LOG_ERR, "control_stop: %m");
}
close(pidfd);
unlink(pidfile);
}
#ifdef DEBUG_MEMORY
free(pidfile);
#endif
if (options & DHCPCD_STARTED && !(options & DHCPCD_FORKED))
syslog(LOG_INFO, "exited");
}
/* ARGSUSED */
static void
handle_exit_timeout(__unused void *arg)
@ -217,9 +176,9 @@ handle_exit_timeout(__unused void *arg)
options &=
~(DHCPCD_WAITIP | DHCPCD_WAITIP4 | DHCPCD_WAITIP6);
daemonise();
return;
} else
exit(EXIT_FAILURE);
eloop_exit(EXIT_FAILURE);
return;
}
options &= ~DHCPCD_TIMEOUT_IPV4LL;
timeout = (PROBE_NUM * PROBE_MAX) + (PROBE_WAIT * 2);
@ -231,6 +190,7 @@ pid_t
daemonise(void)
{
#ifdef THERE_IS_NO_FORK
errno = ENOSYS;
return -1;
#else
pid_t pid;
@ -297,7 +257,8 @@ daemonise(void)
close(pidfd);
pidfd = -1;
options |= DHCPCD_FORKED;
exit(EXIT_SUCCESS);
eloop_exit(EXIT_SUCCESS);
return pid;
}
options |= DHCPCD_DAEMONISED;
return pid;
@ -333,7 +294,7 @@ stop_interface(struct interface *ifp)
script_runreason(ifp, "DEPARTED");
free_interface(ifp);
if (!(options & (DHCPCD_MASTER | DHCPCD_TEST)))
exit(EXIT_FAILURE);
eloop_exit(EXIT_FAILURE);
}
static void
@ -904,23 +865,22 @@ handle_signal(int sig, siginfo_t *siginfo, __unused void *context)
return;
}
if (options & DHCPCD_TEST)
exit(EXIT_FAILURE);
/* As drop_dhcp could re-arrange the order, we do it like this. */
for (;;) {
/* Be sane and drop the last config first */
ifp = TAILQ_LAST(ifaces, if_head);
if (ifp == NULL)
break;
if (do_release) {
ifp->options->options |= DHCPCD_RELEASE;
ifp->options->options &= ~DHCPCD_PERSISTENT;
if (!(options & DHCPCD_TEST)) {
/* drop_dhcp could change the order, so we do it like this. */
for (;;) {
/* Be sane and drop the last config first */
ifp = TAILQ_LAST(ifaces, if_head);
if (ifp == NULL)
break;
if (do_release) {
ifp->options->options |= DHCPCD_RELEASE;
ifp->options->options &= ~DHCPCD_PERSISTENT;
}
ifp->options->options |= DHCPCD_EXITING;
stop_interface(ifp);
}
ifp->options->options |= DHCPCD_EXITING;
stop_interface(ifp);
}
exit(EXIT_FAILURE);
eloop_exit(EXIT_FAILURE);
}
int
@ -1093,15 +1053,17 @@ signal_init(void (*func)(int, siginfo_t *, void *), sigset_t *oldset)
int
main(int argc, char **argv)
{
char *pidfile;
struct interface *ifp;
uint16_t family = 0;
int opt, oi = 0, sig = 0, i, control_fd;
int opt, oi = 0, sig = 0, i;
size_t len;
pid_t pid;
struct timespec ts;
struct utsname utn;
const char *platform;
pidfile = NULL;
closefrom(3);
openlog(PACKAGE, LOG_PERROR | LOG_PID, LOG_DAEMON);
setlogmask(LOG_UPTO(LOG_INFO));
@ -1110,10 +1072,10 @@ main(int argc, char **argv)
if (argc > 1) {
if (strcmp(argv[1], "--help") == 0) {
usage();
exit(EXIT_SUCCESS);
return EXIT_SUCCESS;
} else if (strcmp(argv[1], "--version") == 0) {
printf(""PACKAGE" "VERSION"\n%s\n", dhcpcd_copyright);
exit(EXIT_SUCCESS);
return EXIT_SUCCESS;
}
}
@ -1163,7 +1125,7 @@ main(int argc, char **argv)
break;
case '?':
usage();
exit(EXIT_FAILURE);
goto exit_failure;
}
}
@ -1174,7 +1136,7 @@ main(int argc, char **argv)
if (opt != 1) {
if (opt == 0)
usage();
exit(EXIT_FAILURE);
goto exit_failure;
}
if (i == 3) {
printf("Interface options:\n");
@ -1191,10 +1153,7 @@ main(int argc, char **argv)
dhcp6_printoptions();
}
#endif
#ifdef DEBUG_MEMORY
cleanup();
#endif
exit(EXIT_SUCCESS);
goto exit_success;
}
options = if_options->options;
if (i != 0) {
@ -1229,7 +1188,7 @@ main(int argc, char **argv)
pidfile = malloc(len);
if (pidfile == NULL) {
syslog(LOG_ERR, "%s: %m", __func__);
exit(EXIT_FAILURE);
goto exit_failure;
}
if (optind == argc - 1)
snprintf(pidfile, len, PIDFILE, "-", argv[optind]);
@ -1241,30 +1200,29 @@ main(int argc, char **argv)
if (chdir("/") == -1)
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);
goto exit_failure;
}
if (dhcp_dump(argv[optind]) == -1)
exit(EXIT_FAILURE);
exit(EXIT_SUCCESS);
goto exit_failure;
goto exit_success;
}
if (!(options & (DHCPCD_MASTER | DHCPCD_TEST))) {
control_fd = control_open();
if (control_fd != -1) {
if ((i = control_open()) != -1) {
syslog(LOG_INFO,
"sending commands to master dhcpcd process");
i = control_send(argc, argv);
if (i > 0) {
len = control_send(argc, argv);
close(i);
if (len > 0) {
syslog(LOG_DEBUG, "send OK");
exit(EXIT_SUCCESS);
goto exit_success;
} else {
syslog(LOG_ERR, "failed to send commands");
exit(EXIT_FAILURE);
goto exit_failure;
}
} else {
if (errno != ENOENT)
@ -1277,7 +1235,7 @@ main(int argc, char **argv)
PACKAGE " will not work correctly unless run as root");
if (sig != 0) {
pid = read_pid();
pid = read_pid(pidfile);
if (pid != 0)
syslog(LOG_INFO, "sending signal %d to pid %d",
sig, pid);
@ -1286,36 +1244,36 @@ main(int argc, char **argv)
syslog(LOG_ERR, ""PACKAGE" not running");
if (pid != 0 && errno != ESRCH) {
syslog(LOG_ERR, "kill: %m");
exit(EXIT_FAILURE);
goto exit_failure;
}
unlink(pidfile);
if (sig != SIGALRM)
exit(EXIT_FAILURE);
goto exit_failure;
} else {
if (sig == SIGALRM || sig == SIGUSR1)
exit(EXIT_SUCCESS);
goto exit_success;
/* Spin until it exits */
syslog(LOG_INFO, "waiting for pid %d to exit", pid);
ts.tv_sec = 0;
ts.tv_nsec = 100000000; /* 10th of a second */
for(i = 0; i < 100; i++) {
nanosleep(&ts, NULL);
if (read_pid() == 0)
exit(EXIT_SUCCESS);
if (read_pid(pidfile) == 0)
goto exit_success;
}
syslog(LOG_ERR, "pid %d failed to exit", pid);
exit(EXIT_FAILURE);
goto exit_failure;
}
}
if (!(options & DHCPCD_TEST)) {
if ((pid = read_pid()) > 0 &&
if ((pid = read_pid(pidfile)) > 0 &&
kill(pid, 0) == 0)
{
syslog(LOG_ERR, ""PACKAGE
" already running on pid %d (%s)",
pid, pidfile);
exit(EXIT_FAILURE);
goto exit_failure;
}
/* Ensure we have the needed directories */
@ -1332,10 +1290,10 @@ main(int argc, char **argv)
* runs on an interface */
if (flock(pidfd, LOCK_EX | LOCK_NB) == -1) {
syslog(LOG_ERR, "flock `%s': %m", pidfile);
exit(EXIT_FAILURE);
goto exit_failure;
}
if (set_cloexec(pidfd) == -1)
exit(EXIT_FAILURE);
goto exit_failure;
writepid(pidfd, getpid());
}
}
@ -1343,14 +1301,10 @@ main(int argc, char **argv)
syslog(LOG_INFO, "version " VERSION " starting");
options |= DHCPCD_STARTED;
#ifdef DEBUG_MEMORY
eloop_init();
#endif
/* Save signal mask, block and redirect signals to our handler */
if (signal_init(handle_signal, &dhcpcd_sigset) == -1) {
syslog(LOG_ERR, "signal_setup: %m");
exit(EXIT_FAILURE);
goto exit_failure;
}
if (options & DHCPCD_MASTER) {
@ -1360,7 +1314,7 @@ main(int argc, char **argv)
if (open_sockets() == -1) {
syslog(LOG_ERR, "open_sockets: %m");
exit(EXIT_FAILURE);
goto exit_failure;
}
#if 0
@ -1407,11 +1361,11 @@ main(int argc, char **argv)
if (ifc == 0)
syslog(LOG_ERR, "no valid interfaces found");
else
exit(EXIT_FAILURE);
goto exit_failure;
if (!(options & DHCPCD_LINK)) {
syslog(LOG_ERR,
"aborting as link detection is disabled");
exit(EXIT_FAILURE);
goto exit_failure;
}
}
@ -1470,6 +1424,51 @@ main(int argc, char **argv)
eloop_timeout_add_sec(0, start_interface, ifp);
}
eloop_start(&dhcpcd_sigset);
exit(EXIT_SUCCESS);
i = eloop_start(&dhcpcd_sigset);
goto exit1;
exit_success:
i = EXIT_SUCCESS;
goto exit1;
exit_failure:
i = EXIT_FAILURE;
exit1:
if (ifaces) {
while ((ifp = TAILQ_FIRST(ifaces))) {
TAILQ_REMOVE(ifaces, ifp, next);
free_interface(ifp);
}
free(ifaces);
}
free(duid);
free_options(if_options);
free_globals();
restore_kernel_ra();
ipv4_free(NULL);
ipv6_free(NULL);
if_free();
get_line_free();
dev_stop(options & DHCPCD_DAEMONISED);
if (linkfd != -1) {
close(linkfd);
linkfd = -1;
}
if (pidfd > -1) {
if (options & DHCPCD_MASTER) {
if (control_stop() == -1)
syslog(LOG_ERR, "control_stop: %m");
}
close(pidfd);
unlink(pidfile);
pidfd = -1;
}
free(pidfile);
if (options & DHCPCD_STARTED && !(options & DHCPCD_FORKED))
syslog(LOG_INFO, "exited");
return i;
}

84
eloop.c
View File

@ -1,6 +1,6 @@
/*
* dhcpcd - DHCP client daemon
* Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* Copyright (c) 2006-2014 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@ -74,6 +74,9 @@ static void *volatile timeout0_arg;
static struct pollfd *fds;
static size_t fds_len;
static int eloop_exitnow;
static int eloop_exitcode;
static void
eloop_event_setup_fds(void)
{
@ -94,6 +97,7 @@ int
eloop_event_add(int fd, void (*callback)(void *), void *arg)
{
struct event *e;
struct pollfd *nfds;
/* We should only have one callback monitoring the fd */
TAILQ_FOREACH(e, &events, next) {
@ -119,13 +123,16 @@ eloop_event_add(int fd, void (*callback)(void *), void *arg)
events_len++;
if (events_len > fds_len) {
fds_len += 5;
free(fds);
fds = malloc(sizeof(*fds) * fds_len);
if (fds == NULL) {
nfds = malloc(sizeof(*fds) * (fds_len + 5));
if (nfds == NULL) {
syslog(LOG_ERR, "%s: %m", __func__);
free(e);
events_len--;
TAILQ_INSERT_TAIL(&free_events, e, next);
return -1;
}
fds_len += 5;
free(fds);
fds = nfds;
}
/* Now populate the structure and add it to the list */
@ -292,44 +299,15 @@ eloop_q_timeout_delete(int queue, void (*callback)(void *), void *arg)
}
}
#ifdef DEBUG_MEMORY
/* Define this to free all malloced memory.
* Normally we don't do this as the OS will do it for us at exit,
* but it's handy for debugging other leaks in valgrind. */
static void
eloop_cleanup(void)
{
struct event *e;
struct timeout *t;
while ((e = TAILQ_FIRST(&events))) {
TAILQ_REMOVE(&events, e, next);
free(e);
}
while ((e = TAILQ_FIRST(&free_events))) {
TAILQ_REMOVE(&free_events, e, next);
free(e);
}
while ((t = TAILQ_FIRST(&timeouts))) {
TAILQ_REMOVE(&timeouts, t, next);
free(t);
}
while ((t = TAILQ_FIRST(&free_timeouts))) {
TAILQ_REMOVE(&free_timeouts, t, next);
free(t);
}
free(fds);
}
void
eloop_init(void)
eloop_exit(int code)
{
atexit(eloop_cleanup);
eloop_exitcode = code;
eloop_exitnow = 1;
}
#endif
__dead void
int
eloop_start(const sigset_t *sigmask)
{
int n;
@ -339,7 +317,11 @@ eloop_start(const sigset_t *sigmask)
struct timespec ts, *tsp;
void (*t0)(void *);
eloop_exitcode = EXIT_FAILURE;
for (;;) {
if (eloop_exitnow)
break;
/* Run all timeouts first */
if (timeout0) {
t0 = timeout0;
@ -364,7 +346,7 @@ eloop_start(const sigset_t *sigmask)
if (tsp == NULL && events_len == 0) {
syslog(LOG_ERR, "nothing to do");
exit(EXIT_FAILURE);
break;
}
n = pollts(fds, events_len, tsp, sigmask);
@ -372,7 +354,7 @@ eloop_start(const sigset_t *sigmask)
if (errno == EAGAIN || errno == EINTR)
continue;
syslog(LOG_ERR, "poll: %m");
exit(EXIT_FAILURE);
break;
}
/* Process any triggered events. */
@ -388,4 +370,26 @@ eloop_start(const sigset_t *sigmask)
}
}
}
/* Release our malloced resources */
while ((e = TAILQ_FIRST(&events))) {
TAILQ_REMOVE(&events, e, next);
free(e);
}
while ((e = TAILQ_FIRST(&free_events))) {
TAILQ_REMOVE(&free_events, e, next);
free(e);
}
while ((t = TAILQ_FIRST(&timeouts))) {
TAILQ_REMOVE(&timeouts, t, next);
free(t);
}
while ((t = TAILQ_FIRST(&free_timeouts))) {
TAILQ_REMOVE(&free_timeouts, t, next);
free(t);
}
free(fds);
fds_len = 0;
return eloop_exitcode;
}

View File

@ -1,6 +1,6 @@
/*
* dhcpcd - DHCP client daemon
* Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
* Copyright (c) 2006-2014 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@ -34,6 +34,10 @@
#define ELOOP_QUEUE 1
#endif
/* EXIT_FAILURE is a non zero value and EXIT_SUCCESS is zero.
* To add a CONTINUE definition, simply do the opposite of EXIT_FAILURE. */
#define ELOOP_CONTINUE -EXIT_FAILURE
#define eloop_timeout_add_tv(a, b, c) \
eloop_q_timeout_add_tv(ELOOP_QUEUE, a, b, c)
#define eloop_timeout_add_sec(a, b, c) \
@ -52,6 +56,7 @@ int eloop_timeout_add_now(void (*)(void *), void *);
void eloop_q_timeout_delete(int, void (*)(void *), void *);
void eloop_q_timeouts_delete(int, void *, void (*)(void *), ...);
void eloop_init(void);
void eloop_start(const sigset_t *);
void eloop_exit(int);
int eloop_start(const sigset_t *);
#endif

View File

@ -102,14 +102,19 @@ if_conf(__unused struct interface *iface)
return 0;
}
#ifdef DEBUG_MEMORY
static void
cleanup(void)
void
if_free(void)
{
free(link_buf);
if (r_fd != -1) {
close(r_fd);
r_fd = -1;
}
if (link_buflen) {
free(link_buf);
link_buflen = 0;
}
}
#endif
int
open_sockets(void)
@ -128,11 +133,6 @@ open_link_socket(void)
{
int fd;
#ifdef DEBUG_MEMORY
if (link_buf == NULL)
atexit(cleanup);
#endif
fd = socket(PF_ROUTE, SOCK_RAW, 0);
if (fd != -1) {
set_cloexec(fd);

View File

@ -112,6 +112,16 @@ if_conf(struct interface *iface)
return 0;
}
void
if_free(void)
{
if (sock_fd != -1) {
close(sock_fd);
sock_fd = -1;
}
}
/* XXX work out Virtal Interface Masters */
int
if_vimaster(__unused const char *ifname)

29
ipv4.c
View File

@ -169,15 +169,6 @@ ipv4_freeroutes(struct rt_head *rts)
}
}
#ifdef DEBUG_MEMORY
static void
ipv4_cleanup()
{
ipv4_freeroutes(routes);
}
#endif
int
ipv4_init(void)
{
@ -187,9 +178,6 @@ ipv4_init(void)
if (routes == NULL)
return -1;
TAILQ_INIT(routes);
#ifdef DEBUG_MEMORY
atexit(ipv4_cleanup);
#endif
}
return 0;
}
@ -776,12 +764,17 @@ ipv4_free(struct interface *ifp)
struct ipv4_state *state;
struct ipv4_addr *addr;
state = IPV4_STATE(ifp);
if (state) {
while ((addr = TAILQ_FIRST(&state->addrs))) {
TAILQ_REMOVE(&state->addrs, addr, next);
free(addr);
if (ifp) {
state = IPV4_STATE(ifp);
if (state) {
while ((addr = TAILQ_FIRST(&state->addrs))) {
TAILQ_REMOVE(&state->addrs, addr, next);
free(addr);
}
free(state);
}
free(state);
} else {
ipv4_freeroutes(routes);
routes = NULL;
}
}

45
ipv6.c
View File

@ -74,20 +74,6 @@
static struct rt6head *routes;
#ifdef DEBUG_MEMORY
static void
ipv6_cleanup()
{
struct rt6 *rt;
while ((rt = TAILQ_FIRST(routes))) {
TAILQ_REMOVE(routes, rt, next);
free(rt);
}
free(routes);
}
#endif
int
ipv6_init(void)
{
@ -97,9 +83,6 @@ ipv6_init(void)
if (routes == NULL)
return -1;
TAILQ_INIT(routes);
#ifdef DEBUG_MEMORY
atexit(ipv6_cleanup);
#endif
}
return 0;
}
@ -659,16 +642,28 @@ ipv6_free(struct interface *ifp)
{
struct ipv6_state *state;
struct ipv6_addr_l *ap;
struct rt6 *rt;
ipv6_free_ll_callbacks(ifp);
state = IPV6_STATE(ifp);
if (state) {
while ((ap = TAILQ_FIRST(&state->addrs))) {
TAILQ_REMOVE(&state->addrs, ap, next);
free(ap);
if (ifp) {
ipv6_free_ll_callbacks(ifp);
state = IPV6_STATE(ifp);
if (state) {
while ((ap = TAILQ_FIRST(&state->addrs))) {
TAILQ_REMOVE(&state->addrs, ap, next);
free(ap);
}
free(state);
ifp->if_data[IF_DATA_IPV6] = NULL;
}
} else {
if (routes) {
while ((rt = TAILQ_FIRST(routes))) {
TAILQ_REMOVE(routes, rt, next);
free(rt);
}
free(routes);
routes = NULL;
}
free(state);
ifp->if_data[IF_DATA_IPV6] = NULL;
}
}

View File

@ -180,16 +180,6 @@ static void ipv6nd_handledata(void *arg);
memset(filterp, 0xff, sizeof(struct icmp6_filter));
#endif
#if DEBUG_MEMORY
static void
ipv6nd_cleanup(void)
{
free(sndbuf);
free(rcvbuf);
}
#endif
static int
ipv6nd_open(void)
{
@ -230,9 +220,6 @@ ipv6nd_open(void)
goto eexit;
set_cloexec(sock);
#if DEBUG_MEMORY
atexit(ipv6nd_cleanup);
#endif
len = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));
sndbuf = calloc(1, len);
@ -465,11 +452,12 @@ ipv6nd_free(struct interface *ifp)
ssize_t n;
state = RS_STATE(ifp);
if (state) {
free(state->rs);
free(state);
ifp->if_data[IF_DATA_IPV6ND] = NULL;
}
if (state == NULL)
return 0;
free(state->rs);
free(state);
ifp->if_data[IF_DATA_IPV6ND] = NULL;
n = 0;
TAILQ_FOREACH_SAFE(rap, &ipv6_routers, next, ran) {
if (rap->iface == ifp) {
@ -477,6 +465,25 @@ ipv6nd_free(struct interface *ifp)
n++;
}
}
/* If we don't have any more IPv6 enabled interfaces,
* close the global socket and release resources */
TAILQ_FOREACH(ifp, ifaces, next) {
if (RS_STATE(ifp))
break;
}
if (ifp == NULL) {
if (sock != -1) {
close(sock);
eloop_event_delete(sock);
sock = -1;
}
free(sndbuf);
free(rcvbuf);
sndbuf = NULL;
rcvbuf = NULL;
}
return n;
}
@ -1031,8 +1038,10 @@ handle_flag:
if (rap->lifetime && new_data)
syslog(LOG_DEBUG, "%s: No DHCPv6 instruction in RA",
ifp->name);
if (options & DHCPCD_TEST)
exit(EXIT_SUCCESS);
if (options & DHCPCD_TEST) {
eloop_exit(EXIT_SUCCESS);
return;
}
}
/* Expire should be called last as the rap object could be destroyed */
@ -1292,6 +1301,7 @@ ipv6nd_drop(struct interface *ifp)
script_runreason(ifp, "ROUTERADVERT");
}
}
static void
ipv6nd_unreachable(void *arg)
{

1
net.h
View File

@ -103,6 +103,7 @@ int do_mtu(const char *, short int);
int up_interface(struct interface *);
int if_conf(struct interface *);
int if_init(struct interface *);
void if_free(void);
int open_link_socket(void);
int manage_link(int);

View File

@ -89,7 +89,7 @@ inet6_sysctl(int code, int val, int action)
return val;
}
static void
void
restore_kernel_ra(void)
{
@ -121,7 +121,7 @@ ipv6_ra_flush(void)
int
check_ipv6(const char *ifname, int own)
{
static int set_restore = 0, global_ra = 0;
static int global_ra = 0;
int ra;
/* BSD doesn't support these values per iface, so just return
@ -141,10 +141,6 @@ check_ipv6(const char *ifname, int own)
syslog(LOG_ERR, "IPV6CTL_ACCEPT_RTADV: %m");
return ra;
}
if (!set_restore) {
set_restore = 1;
atexit(restore_kernel_ra);
}
ra = 0;
/* Flush the kernel knowledge of advertised routers

View File

@ -145,51 +145,36 @@ write_path(const char *path, const char *val)
static const char *prefix = "/proc/sys/net/ipv6/conf";
static void
void
restore_kernel_ra(void)
{
char path[256];
#ifndef DEBUG_MEMORY
if (options & DHCPCD_FORKED)
return;
#endif
for (nrestore--; nrestore >= 0; nrestore--) {
#ifdef DEBUG_MEMORY
if (!(options & DHCPCD_FORKED)) {
#endif
syslog(LOG_INFO, "%s: restoring Kernel IPv6 RA support",
restore[nrestore]);
snprintf(path, sizeof(path), "%s/%s/accept_ra",
prefix, restore[nrestore]);
if (write_path(path, "1") == -1 && errno != ENOENT)
syslog(LOG_ERR, "write_path: %s: %m", path);
#ifdef DEBUG_MEMORY
syslog(LOG_INFO, "%s: restoring Kernel IPv6 RA support",
restore[nrestore]);
snprintf(path, sizeof(path), "%s/%s/accept_ra",
prefix, restore[nrestore]);
if (write_path(path, "1") == -1 && errno != ENOENT)
syslog(LOG_ERR, "write_path: %s: %m", path);
}
free(restore[nrestore]);
#endif
}
#ifdef DEBUG_MEMORY
free(restore);
#endif
}
int
check_ipv6(const char *ifname, int own)
{
static int ipv6_checked = 0;
int ra, ex, i;
int ra, i;
char path[256], *p, **nrest;
if (ifname == NULL) {
if (ipv6_checked)
return 1;
ipv6_checked = 1;
if (ifname == NULL)
ifname = "all";
ex = 1;
} else
ex = 0;
snprintf(path, sizeof(path), "%s/%s/autoconf", prefix, ifname);
i = check_proc_int(path);
@ -232,8 +217,6 @@ check_ipv6(const char *ifname, int own)
restore[nrestore++] = p;
}
if (ex)
atexit(restore_kernel_ra);
}
return ra;

View File

@ -32,8 +32,10 @@ char *hardware_platform(void);
#ifdef INET6
int check_ipv6(const char *, int);
int ipv6_dadtransmits(const char *);
void restore_kernel_ra(void);
#else
#define check_ipv6(a, b) -1
#define restore_kernel_ra(a)
#endif
#endif