Compile and work on OSX/Darwin.
If we have no fork then we re-exec ourselves with --daemonised.
Improved the build system so we automatically detect if we need
librt or libresolv and if fork() works or not.
Move back to using librt for clock_gettime on Linux systems.
+Many thanks to Michael Durrant for testing the below changes.
+Compile and work on OSX/Darwin.
+If we have no fork then we re-exec ourselves with --daemonised.
+Improved the build system so we automatically detect if we need
+librt or libresolv and if fork() works or not.
+Move back to using librt for clock_gettime on Linux systems.
+
dhcpcd-3.1.5
Fix the flushing of addresses on BSD systems.
Rework get_time so that we don't link to librt on Linux.
Take special note of ENABLE_DUID and unset it if the target media is
volatile, like say a LiveCD.
-Darwin users should edit the Makefile and enable dhcpcd_LIBS = -lresolv
-
Then just make; make install
man dhcpcd for command line options
# Should work for both GNU make and BSD make
-VERSION = 3.1.5
-CFLAGS ?= -O2 -pipe
+# NOTE: I really don't like autotools, but we do need to work a few things out
+# such as the need to link to libresolv and/or librt so please forgive the
+# embedded code :)
-# Saying that, this function only works with GNU Make :/
-check_gcc=$(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; \
- then echo "$(1)"; else echo "$(2)"; fi)
+VERSION = 3.1.6_pre6
+CFLAGS += -O2 -pipe
+
+INSTALL ?= install
+DESTDIR =
+SBINDIR = $(DESTDIR)/sbin
+MANDIR = $(DESTDIR)/usr/share/man
+LIBDIR = $(DESTDIR)/var/lib
+
+SBIN_TARGETS = dhcpcd
+MAN8_TARGETS = dhcpcd.8
+TARGET = $(SBIN_TARGETS)
-# Luckily we can do this more long winded thing with pmake used by the BSDs
-WEXTRA != for x in -Wdeclaration-after-statement -Wsequence-point -Wextra ; do \
+# Work out if we need -lresolv or not
+_LIBRESOLV_SH = printf '\#include <netinet/in.h>\n\#include <resolv.h>\nint main (void) { return (res_init ()); }\n' > .res_init.c; \
+ if $(CC) .res_init.c -o .res_init >/dev/null 2>&1 ; then \
+ echo ""; \
+ elif $(CC) .res_init.c -lresolv -o .res_init >/dev/null 2>&1 ; then \
+ echo "-lresolv"; \
+ else \
+ echo "Cannot work out how to get res_init to link" >&2; \
+ exit 1; \
+ fi; \
+ rm -f .res_init.c .res_init
+_LIBRESOLV != $(_LIBRESOLV_SH)
+LIBRESOLV = $(_LIBRESOLV)$(shell $(_LIBRESOLV_SH))
+
+# Work out if we need -lrt or not
+_LIBRT_SH = printf '\#include <time.h>\nint main (void) { struct timespec ts; return (clock_gettime (CLOCK_MONOTONIC, &ts)); }\n' > .clock_gettime.c; \
+ if $(CC) .clock_gettime.c -o .clock_gettime >/dev/null 2>&1; then \
+ echo ""; \
+ elif $(CC) .clock_gettime.c -lrt -o .clock_gettime >/dev/null 2>&1 ; then \
+ echo "-lrt"; \
+ else \
+ echo "Cannot work out how to get clock_gettime to link" >&2; \
+ exit 1; \
+ fi; \
+ rm -f .clock_gettime.c .clock_gettime
+_LIBRT != $(_LIBRT_SH)
+LIBRT = $(_LIBRT)$(shell $(_LIBRT_SH))
+
+# Work out if our fork() works or not
+_HAVE_FORK_SH = printf '\#include <stdlib.h>\n\#include <unistd.h>\nint main (void) { pid_t pid = fork(); if (pid == -1) exit (-1); exit (0); }\n' > .fork.c; \
+ $(CC) .fork.c -o .fork >/dev/null 2>&1; \
+ if ./.fork; then \
+ echo ""; \
+ else \
+ echo "-DTHERE_IS_NO_FORK"; \
+ fi; \
+ rm -f .fork.c .fork
+_HAVE_FORK != $(_HAVE_FORK_SH)
+HAVE_FORK = $(_HAVE_FORK)$(shell $(_HAVE_FORK_SH))
+
+# pmake check for extra cflags
+WEXTRA != for x in -Wdeclaration-after-statement -Wsequence-point -Wextra; do \
if $(CC) -Wdeclaration-after-statement -S -o /dev/null -xc /dev/null >/dev/null 2>&1; \
then echo -n "$$x "; fi \
done
+# gmake function for similar, but called below
+check_gcc=$(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; \
+ then echo "$(1)"; else echo "$(2)"; fi)
+
# Loads of nice flags to ensure our code is good
# IMPORTANT: We should be using c99 instead of gnu99 but for some reason
# generic linux headers as of 2.6.19 don't allow this in asm/types.h
# have buggy headers from time to time, so you may need to comment this out
#CFLAGS += -Werror
-# We define _BSD_SOURCE as GNU supports BSD too - which is nice :)
-CDEFS = -D_BSD_SOURCE
-
-INSTALL ?= install
-DESTDIR =
-SBINDIR = $(DESTDIR)/sbin
-MANDIR = $(DESTDIR)/usr/share/man
-LIBDIR = $(DESTDIR)/var/lib
-
-SBIN_TARGETS = dhcpcd
-MAN8_TARGETS = dhcpcd.8
-TARGET = $(SBIN_TARGETS)
+all: $(TARGET)
dhcpcd_H = version.h
dhcpcd_OBJS = arp.o client.o common.o configure.o dhcp.o dhcpcd.o duid.o \
info.o interface.o ipv4ll.o logger.o signals.o socket.o
-# Darwin needs this, but we have no way of detecting this atm
-#LIBRESOLV = -lresolv
+$(dhcpcd_OBJS):
+ $(CC) $(HAVE_FORK) $(CFLAGS) -c $*.c
-dhcpcd: $(dhcpcd_H) $(dhcpcd_OBJS)
- $(CC) $(LDFLAGS) $(dhcpcd_OBJS) $(LIBRESOLV) -o dhcpcd
+dhcpcd: $(dhcpcd_H) .depend $(dhcpcd_OBJS)
+ $(CC) $(LDFLAGS) $(dhcpcd_OBJS) $(LIBRESOLV) $(LIBRT) -o dhcpcd
version.h:
echo '#define VERSION "$(VERSION)"' > version.h
-$(dhcpcd_OBJS):
- $(CC) $(CDEFS) $(CFLAGS) -c $*.c
+.PHONY: clean install dist
-all: $(TARGET)
+# We always need to have a .depend file as not all make implentations can work
+# with each others way of optionally including a file
+clean:
+ echo > .depend
+ touch -r Makefile .depend
+ rm -f $(TARGET) $(dhcpcd_H) *.o *~ *.core *.bz2
install: $(TARGET)
$(INSTALL) -m 0755 -d $(SBINDIR)
$(INSTALL) -m 0644 $(MAN8_TARGETS) $(MANDIR)/man8
$(INSTALL) -m 0755 -d $(LIBDIR)
-clean:
- rm -f $(TARGET) $(dhcpcd_H) *.o *~ *.core *.bz2
-
dist:
$(INSTALL) -m 0755 -d /tmp/dhcpcd-$(VERSION)
cp -RPp . /tmp/dhcpcd-$(VERSION)
tar cvjpf dhcpcd-$(VERSION).tar.bz2 -C /tmp dhcpcd-$(VERSION)
rm -rf /tmp/dhcpcd-$(VERSION)
ls -l dhcpcd-$(VERSION).tar.bz2
+
+# Sucky, but I cannot find a way of optional including the .depend file
+# that works for all make implementations :/
+include .depend
+_DEPS != ls *.c *.h
+.depend: $(dhcpcd_H) $(_DEPS)$(wildcard *.c *.h)
+ $(CC) $(CPPFLAGS) -MM *.c > .depend
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#ifdef __linux__
+# define _BSD_SOURCE
# define _XOPEN_SOURCE 500 /* needed for pwrite */
#endif
# include "info.h"
#endif
+#ifdef THERE_IS_NO_FORK
+# ifndef ENABLE_INFO
+# error "Non MMU requires ENABLE_INFO to work"
+# endif
+#endif
+
/* We need this for our maximum timeout as FreeBSD's select cannot handle
any higher than this. Is there a better way of working this out? */
#define SELECT_MAX 100000000
}
#define DROP_CONFIG { \
- if (! options->persistent) \
+ if (! persistent) \
configure (options, iface, dhcp, false); \
free_dhcp (dhcp); \
memset (dhcp, 0, sizeof (dhcp_t)); \
}
-static bool daemonise (int *pidfd)
+static pid_t daemonise (int *pidfd)
{
- char pid[16];
+ pid_t pid;
+ char spid[16];
+#ifndef THERE_IS_NO_FORK
logger (LOG_DEBUG, "forking to background");
-
- if (daemon (0, 0) == -1) {
- logger (LOG_ERR, "daemon: %s", strerror (errno));
- return (false);
+ if ((pid = fork()) == -1) {
+ logger (LOG_ERR, "fork: %s", strerror (errno));
+ exit (EXIT_FAILURE);
}
- if (ftruncate (*pidfd, 0) == -1) {
- logger (LOG_ERR, "ftruncate: %s", strerror (errno));
- return (false);
+ setsid ();
+ close_fds ();
+#else
+ char **argv;
+ int i;
+
+ logger (LOG_INFO, "forking to background");
+
+ /* We need to add --daemonise to our options */
+ argv = xmalloc (sizeof (char *) * (dhcpcd_argc + 2));
+ for (i = 0; i < dhcpcd_argc; i++)
+ argv[i] = dhcpcd_argv[i];
+ argv[i] = (char *) "--daemonised";
+ argv[i + 1] = NULL;
+
+ switch (pid = vfork ()) {
+ case -1:
+ logger (LOG_ERR, "vfork: %s", strerror (errno));
+ _exit (EXIT_FAILURE);
+ case 0:
+ execvp (dhcpcd, argv);
+ logger (LOG_ERR, "execl `%s': %s", dhcpcd, strerror (errno));
+ _exit (EXIT_FAILURE);
}
- snprintf (pid, sizeof (pid), "%u", getpid());
- if (pwrite (*pidfd, pid, strlen(pid), 0) != (ssize_t) strlen (pid)) {
- logger (LOG_ERR, "pwrite: %s", strerror (errno));
- return (false);
+ free (argv);
+#endif
+
+ if (pid != 0) {
+ if (ftruncate (*pidfd, 0) == -1) {
+ logger (LOG_ERR, "ftruncate: %s", strerror (errno));
+ } else {
+ snprintf (spid, sizeof (spid), "%u", pid);
+ if (pwrite (*pidfd, spid, strlen (spid), 0) != (ssize_t) strlen (spid))
+ logger (LOG_ERR, "pwrite: %s", strerror (errno));
+ }
}
-
- return (true);
+
+ return (pid);
}
#ifdef ENABLE_INFO
static bool get_old_lease (const options_t *options, interface_t *iface,
- dhcp_t *dhcp, long *timeout)
+ dhcp_t *dhcp, time_t *timeout)
{
struct timeval tv;
unsigned int offset = 0;
int state = STATE_INIT;
struct timeval tv;
int xid = 0;
- long timeout = 0;
+ time_t timeout = 0;
fd_set rset;
int maxfd;
int retval;
dhcp_t *dhcp;
int type = DHCP_DISCOVER;
int last_type = DHCP_DISCOVER;
- bool daemonised = false;
- unsigned long start = 0;
- unsigned long last_send = 0;
+ bool daemonised = options->daemonised;
+ bool persistent = options->persistent;
+ time_t start = 0;
+ time_t last_send = 0;
int sig;
unsigned char *buffer = NULL;
int buffer_len = 0;
memset (dhcp, 0, sizeof (dhcp_t));
if (options->request_address.s_addr == 0 &&
- (options->doinform || options->dorequest))
+ (options->doinform || options->dorequest || options->daemonised))
{
#ifdef ENABLE_INFO
if (! get_old_lease (options, iface, dhcp, NULL))
free (dhcp);
return (-1);
}
+
+#ifdef THERE_IS_NO_FORK
+ if (options->daemonised) {
+ state = STATE_BOUND;
+ timeout = dhcp->renewaltime;
+ iface->previous_address = dhcp->address;
+ iface->previous_netmask = dhcp->netmask;
+
+ /* FIXME: Some routes may not be added for whatever reason.
+ * This is especially true on BSD platforms where we can only
+ * have one default route. */
+ if (dhcp->routes) {
+ route_t *droute;
+ route_t *iroute;
+
+ free_route (iface->previous_routes);
+
+ iroute = iface->previous_routes = xmalloc (sizeof (route_t));
+ for (droute = dhcp->routes; droute; droute = droute->next) {
+ memcpy (iroute, droute, sizeof (route_t));
+ if (droute->next) {
+ iroute->next = xmalloc (sizeof (route_t));
+ iroute = iroute->next;
+ }
+ }
+ }
+ }
+#endif
+
} else {
dhcp->address = options->request_address;
dhcp->netmask = options->request_netmask;
After all, we ARE a DHCP client whose job it is to configure the
interface. We only do this on start, so persistent addresses can be added
afterwards by the user if needed. */
- if (! options->test) {
+ if (! options->test && ! options->daemonised) {
if (! options->doinform)
flush_addresses (iface->name);
else {
SEND_MESSAGE (last_type);
logger (LOG_DEBUG, "waiting on select for %ld seconds",
- timeout);
+ (unsigned long) timeout);
/* If we're waiting for a reply, then we re-send the last
DHCP request periodically in-case of a bad line */
retval = 0;
state = STATE_BOUND;
if (! daemonised && options->daemonise) {
- if ((daemonise (pidfd)) == -1) {
- retval = EXIT_FAILURE;
- goto eexit;
+ switch (daemonise (pidfd)) {
+ case -1:
+ retval = EXIT_FAILURE;
+ goto eexit;
+ case 0:
+ daemonised = true;
+ break;
+ default:
+ persistent = true;
+ retval = EXIT_SUCCESS;
+ goto eexit;
}
- daemonised = true;
}
timeout = dhcp->renewaltime;
xid = 0;
- if (configure (options, iface, dhcp, true) == -1 && ! daemonised) {
+ if (configure (options, iface, dhcp, true) == -1 &&
+ ! daemonised)
+ {
retval = EXIT_FAILURE;
goto eexit;
}
if (! daemonised && options->daemonise) {
- if ((daemonise (pidfd)) == -1 ) {
- retval = EXIT_FAILURE;
- goto eexit;
+ switch (daemonise (pidfd)) {
+ case -1:
+ retval = EXIT_FAILURE;
+ goto eexit;
+ case 0:
+ daemonised = true;
+ break;
+ default:
+ persistent = true;
+ retval = EXIT_SUCCESS;
+ goto eexit;
}
- daemonised = true;
}
} else if (type == DHCP_OFFER)
logger (LOG_INFO, "got subsequent offer of %s, ignoring ",
free (dhcp);
if (iface) {
- if (iface->previous_routes)
- free_route (iface->previous_routes);
+ free_route (iface->previous_routes);
free (iface);
}
*pidfd = -1;
}
- logger (LOG_INFO, "exiting");
-
- /* Unlink our pidfile */
- unlink (options->pidfile);
+ if (daemonised)
+ unlink (options->pidfile);
return retval;
}
#include <sys/time.h>
#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
+#include <unistd.h>
#include "common.h"
#include "logger.h"
/* OK, this should be in dhcpcd.c
* It's here to make dhcpcd more readable */
#ifdef __linux__
-#include <fcntl.h>
-#include <unistd.h>
-void srandomdev (void) {
+void srandomdev (void)
+{
int fd;
unsigned long seed;
fd = open ("/dev/urandom", 0);
- if (fd == -1 || read (fd, &seed, sizeof(seed)) == -1) {
+ if (fd == -1 || read (fd, &seed, sizeof (seed)) == -1) {
logger (LOG_WARNING, "Could not load seed from /dev/urandom: %s",
strerror (errno));
seed = time (0);
if (! n) {
if (size)
*dst = '\0';
- while (*src++)
- ;
+ while (*src++);
}
return (src - s - 1);
# endif
#endif
-/* This requires us to link to rt on glibc, so we use sysinfo instead */
-#ifdef __linux__
-#include <sys/sysinfo.h>
-/* Avoid clock_gettime as it requires librt on Linux */
-#undef CLOCK_MONOTONIC
-long uptime (void)
-{
- struct sysinfo info;
-
- sysinfo (&info);
- return info.uptime;
-}
-#elif CLOCK_MONOTONIC
-long uptime (void)
-{
- struct timespec tp;
-
- if (clock_gettime (CLOCK_MONOTONIC, &tp) == -1) {
- logger (LOG_ERR, "clock_gettime: %s", strerror (errno));
- return -1;
- }
-
- return tp.tv_sec;
-}
-#else
-/* Darwin doesn't appear to have an uptime, so try and make one ourselves */
-long uptime (void)
+/* Close our fd's */
+void close_fds (void)
{
- struct timeval tv;
- static long start = 0;
+ int fd;
- if (gettimeofday (&tv, NULL) == -1) {
- logger (LOG_ERR, "gettimeofday: %s", strerror (errno));
- return -1;
+ if ((fd = open ("/dev/null", O_RDWR)) == -1) {
+ logger (LOG_ERR, "open `/dev/null': %s", strerror (errno));
+ return;
}
- if (start == 0)
- start = tv.tv_sec;
-
- return tv.tv_sec - start;
+ dup2 (fd, fileno (stdin));
+ dup2 (fd, fileno (stdout));
+ dup2 (fd, fileno (stderr));
+ if (fd > 2)
+ close (fd);
}
-#endif
/* Handy function to get the time.
* We only care about time advancements, not the actual time itself
* Which is why we use CLOCK_MONOTONIC, but it is not available on all
* platforms.
*/
-#ifdef CLOCK_MONOTONIC
int get_time (struct timeval *tp)
{
+#ifdef CLOCK_MONOTONIC
struct timespec ts;
if (clock_gettime (CLOCK_MONOTONIC, &ts) == -1) {
tp->tv_sec = ts.tv_sec;
tp->tv_usec = ts.tv_nsec / 1000;
return (0);
-}
#else
-int get_time (struct timeval *tp)
-{
if (gettimeofday (tp, NULL) == -1) {
logger (LOG_ERR, "gettimeofday: %s", strerror (errno));
return (-1);
}
return (0);
-}
#endif
+}
+
+time_t uptime (void)
+{
+ struct timeval tp;
+
+ if (get_time (&tp) == -1)
+ return (-1);
+
+ return (tp.tv_sec);
+}
void *xmalloc (size_t s)
{
void srandomdev (void);
#endif
+void close_fds (void);
int get_time (struct timeval *tp);
-long uptime (void);
+time_t uptime (void);
void *xmalloc (size_t size);
char *xstrdup (const char *str);
* See RFC 3315 for details on this. */
#define ENABLE_DUID
+/* Some systems do not have a working fork.
+ * The Makefile will attempt to work it out, but if it fails to feel free to
+ * define it here. */
+// #define THERE_IS_NO_FORK
+
/* Packname name and pathname definitions.
* NOTE: The service restart commands are Gentoo specific and will
* probably need to be adapted for your OS. */
#include <netinet/in.h>
#ifdef __linux__
-#include <netinet/ether.h>
+# include <netinet/ether.h>
#endif
#include <string.h>
#include <errno.h>
#include "configure.h"
#include "dhcp.h"
#ifdef ENABLE_INFO
-#include "info.h"
+# include "info.h"
#endif
#include "interface.h"
#include "dhcpcd.h"
while (va_arg (va, char *) != NULL)
n++;
va_end (va);
- argv = alloca ((n + 1) * sizeof (*argv));
- if (argv == NULL) {
- errno = ENOMEM;
- return (-1);
- }
+ argv = xmalloc (sizeof (char *) * (n + 2));
va_start (va, args);
n = 2;
logger (LOG_ERR, "error executing \"%s\": %s",
cmd, strerror (errno));
_exit (0);
- } else if (pid == -1)
+ } else if (pid == -1) {
logger (LOG_ERR, "vfork: %s", strerror (errno));
+ free (argv);
+ return (-1);
+ }
+ free (argv);
return (0);
}
unsigned long l;
struct in_addr from;
struct in_addr to;
- long up = uptime() - iface->start_uptime;
+ time_t up = uptime() - iface->start_uptime;
uint32_t ul;
uint16_t sz;
unsigned int message_length;
case ARPHRD_IEEE1394:
case ARPHRD_INFINIBAND:
if (message.ciaddr == 0)
- message.flags = htons (BROADCAST_FLAG);
+ message.flags = (int16_t) htons (BROADCAST_FLAG);
message.hwlen = 0;
break;
default:
#ifndef DHCP_H
#define DHCP_H
-#include <sys/types.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
+#include <stdint.h>
#include "dhcpcd.h"
#include "interface.h"
/* We need to define this to get kill on GNU systems */
#ifdef __linux__
+#define _BSD_SOURCE
#define _POSIX_SOURCE
#endif
_int = (int) _number; \
}
+#ifdef THERE_IS_NO_FORK
+char dhcpcd[PATH_MAX];
+char **dhcpcd_argv = NULL;
+int dhcpcd_argc = 0;
+#endif
+
static pid_t read_pid (const char *pidfile)
{
FILE *fp;
{"nonis", no_argument, NULL, 'Y'},
{"help", no_argument, &dohelp, 1},
{"version", no_argument, &doversion, 1},
+#ifdef THERE_IS_NO_FORK
+ {"daemonised", no_argument, NULL, 'f'},
+#endif
{NULL, 0, NULL, 0}
};
break;
}
break;
+#ifdef THERE_IS_NO_FORK
+ case 'f':
+ options.daemonised = true;
+ close_fds ();
+ break;
+#endif
case 'h':
if (! optarg)
memset (options.hostname, 0, sizeof (options.hostname));
break;
case 's':
options.doinform = true;
+ options.doarp = false;
if (! optarg || strlen (optarg) == 0) {
options.request_address.s_addr = 0;
break;
/* nullify the slash, so the -r option can read the
* address */
*slash++ = '\0';
- if (sscanf (slash, "%d", &cidr) != 1) {
+ if (sscanf (slash, "%d", &cidr) != 1 ||
+ inet_cidrtoaddr (cidr, &options.request_netmask) != 0) {
logger (LOG_ERR, "`%s' is not a valid CIDR", slash);
exit (EXIT_FAILURE);
}
- options.request_netmask = inet_cidrtoaddr (cidr);
}
/* fall through */
}
if (dohelp)
usage ();
+#ifdef THERE_IS_NO_FORK
+ dhcpcd_argv = argv;
+ dhcpcd_argc = argc;
+
+ /* We need the full path to the dhcpcd */
+ if (*argv[0] == '/')
+ strlcpy (dhcpcd, argv[0], sizeof (dhcpcd));
+ else {
+ char pwd[PATH_MAX];
+ if (! getcwd (pwd, PATH_MAX)) {
+ logger (LOG_ERR, "getcwd: %s", strerror (errno));
+ exit (EXIT_FAILURE);
+ }
+ snprintf (dhcpcd, sizeof (dhcpcd), "%s/%s", pwd, argv[0]);
+ }
+
+#endif
+
if (optind < argc) {
if (strlen (argv[optind]) > IF_NAMESIZE) {
logger (LOG_ERR, "`%s' is too long for an interface name (max=%d)",
chdir ("/");
umask (022);
-
+
if (mkdir (CONFIGDIR, S_IRUSR |S_IWUSR |S_IXUSR | S_IRGRP | S_IXGRP
| S_IROTH | S_IXOTH) && errno != EEXIST )
{
}
}
- if (sig != 0 ) {
+ if (sig != 0) {
int killed = -1;
pid = read_pid (options.pidfile);
if (pid != 0)
exit (EXIT_FAILURE);
}
- if (! options.test) {
+ if (! options.test && ! options.daemonised) {
if ((pid = read_pid (options.pidfile)) > 0 && kill (pid, 0) == 0) {
logger (LOG_ERR, ""PACKAGE" already running on pid %d (%s)",
pid, options.pidfile);
/* Seed random */
srandomdev ();
- if (dhcp_run (&options, &pidfd)) {
- if (pidfd > -1)
- close (pidfd);
- unlink (options.pidfile);
- exit (EXIT_FAILURE);
- }
+ i = EXIT_FAILURE;
+ if (dhcp_run (&options, &pidfd) == 0)
+ i = EXIT_SUCCESS;
+
+ logger (LOG_INFO, "exiting");
+
+ if (pidfd > -1)
+ close (pidfd);
- exit (EXIT_SUCCESS);
+ exit (i);
}
#define CLIENT_ID_MAX_LEN 48
#define USERCLASS_MAX_LEN 255
+#ifndef HAVE_FORK
+extern char dhcpcd[PATH_MAX];
+extern char **dhcpcd_argv;
+extern int dhcpcd_argc;
+#endif
+
typedef struct options_t {
char interface[IF_NAMESIZE];
char hostname[MAXHOSTNAMELEN];
bool persistent;
bool keep_address;
bool daemonise;
+ bool daemonised;
bool test;
char *script;
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <arpa/inet.h>
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
address_t *p = addresses;
address_t *n = NULL;
- if (! addresses)
- return;
-
while (p) {
n = p->next;
free (p);
route_t *p = routes;
route_t *n = NULL;
- if (! routes)
- return;
-
while (p) {
n = p->next;
free (p);
return (cidr);
}
-struct in_addr inet_cidrtoaddr (int cidr) {
- struct in_addr addr;
+int inet_cidrtoaddr (int cidr, struct in_addr *addr) {
int ocets;
- if (cidr == 0)
- ocets = 0;
- else if (cidr < 9)
- ocets = 1;
- else if (cidr < 17)
- ocets = 2;
- else if (cidr < 25)
- ocets = 3;
- else
- ocets = 4;
+ if (cidr < 0 || cidr > 32) {
+ errno = EINVAL;
+ return (-1);
+ }
+ ocets = (cidr + 7) / 8;
- memset (&addr, 0, sizeof (struct in_addr));
+ memset (addr, 0, sizeof (struct in_addr));
if (ocets > 0) {
- memset (&addr.s_addr, 255, ocets - 1);
- memset ((unsigned char *) &addr.s_addr + (ocets - 1),
+ memset (&addr->s_addr, 255, ocets - 1);
+ memset ((unsigned char *) &addr->s_addr + (ocets - 1),
(256 - (1 << (32 - cidr) % 8)), 1);
}
- return (addr);
+ return (0);
}
unsigned long get_netmask (unsigned long addr)
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) \
|| defined(__APPLE__)
+
+/* Darwin doesn't define this for some very odd reason */
+#ifndef SA_SIZE
+# define SA_SIZE(sa) \
+ ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \
+ sizeof(long) : \
+ 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
+#endif
+
static int do_address (const char *ifname, struct in_addr address,
struct in_addr netmask, struct in_addr broadcast, int del)
{
struct in_addr previous_netmask;
route_t *previous_routes;
- long start_uptime;
+ time_t start_uptime;
#ifdef ENABLE_DUID
unsigned char duid[DUID_LEN];
struct in_addr netmask, struct in_addr gateway, int metric);
int inet_ntocidr (struct in_addr address);
-struct in_addr inet_cidrtoaddr (int cidr);
+int inet_cidrtoaddr (int cidr, struct in_addr *addr);
#endif
#define LINKLOCAL_MASK 0xffff0000
#define LINKLOCAL_BRDC 0xa9feffff
-#define IN_LINKLOCAL(addr) ((ntohl (addr) & IN_CLASSB_NET) == LINKLOCAL_ADDR)
+#ifndef IN_LINKLOCAL
+# define IN_LINKLOCAL(addr) ((ntohl (addr) & IN_CLASSB_NET) == LINKLOCAL_ADDR)
+#endif
int ipv4ll_get_address (interface_t *iface, dhcp_t *dhcp);
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define _BSD_SOURCE
+
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/select.h>