]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Many thanks to Michael Durrant for testing the below changes.
authorRoy Marples <roy@marples.name>
Tue, 4 Sep 2007 12:48:40 +0000 (12:48 +0000)
committerRoy Marples <roy@marples.name>
Tue, 4 Sep 2007 12:48:40 +0000 (12:48 +0000)
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.

17 files changed:
ChangeLog
INSTALL
Makefile
client.c
common.c
common.h
config.h
configure.c
dhcp.c
dhcp.h
dhcpcd.c
dhcpcd.h
duid.c
interface.c
interface.h
ipv4ll.h
socket.c

index 29d009cbded675891ed43c8006223bc10945f5d1..ef958b2bdb993809c64b2abe65e267573d7bf617 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+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.
diff --git a/INSTALL b/INSTALL
index c5687c1542c7c8d5737b3f9c0419bafee6f7154a..272fedc1a422b926bdc3cc41dac22955dd6edf2c 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -3,8 +3,6 @@ Edit config.h to match your building requirements.
 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
index 53b77e8f33ee8c09a97f318016c3d8a1b796f60d..56ede2b5bb7453994f7156c990145494cf58a8df 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,17 +1,71 @@
 # 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
@@ -28,36 +82,29 @@ CFLAGS += -pedantic -std=gnu99 \
 #  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)
@@ -66,9 +113,6 @@ install: $(TARGET)
        $(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)
@@ -77,3 +121,10 @@ dist:
        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
index 656fc6de7b9786f28c88a41a67b985ee6579de12..0c17d838711afbf4ca6aa9655fbea995dc00dcec 100644 (file)
--- a/client.c
+++ b/client.c
@@ -19,7 +19,9 @@
  * 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;
@@ -201,7 +237,7 @@ int dhcp_run (const options_t *options, int *pidfd)
        int state = STATE_INIT;
        struct timeval tv;
        int xid = 0;
-       long timeout = 0;
+       time_t timeout = 0;
        fd_set rset;
        int maxfd;
        int retval;
@@ -209,9 +245,10 @@ int dhcp_run (const options_t *options, int *pidfd)
        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;
@@ -234,7 +271,7 @@ int dhcp_run (const options_t *options, int *pidfd)
        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))
@@ -243,6 +280,35 @@ int dhcp_run (const options_t *options, int *pidfd)
                        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;
@@ -255,7 +321,7 @@ int dhcp_run (const options_t *options, int *pidfd)
           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 {
@@ -308,7 +374,7 @@ int dhcp_run (const options_t *options, int *pidfd)
                                        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;
@@ -452,11 +518,18 @@ int dhcp_run (const options_t *options, int *pidfd)
 
                                                        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;
@@ -741,17 +814,26 @@ int dhcp_run (const options_t *options, int *pidfd)
 
                                                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 ",
@@ -778,8 +860,7 @@ eexit:
        free (dhcp);
 
        if (iface) {
-               if (iface->previous_routes)
-                       free_route (iface->previous_routes);
+               free_route (iface->previous_routes);
                free (iface);
        }
 
@@ -791,10 +872,8 @@ eexit:
                *pidfd = -1;
        }
 
-       logger (LOG_INFO, "exiting");
-
-       /* Unlink our pidfile */
-       unlink (options->pidfile);
+       if (daemonised)
+               unlink (options->pidfile);
 
        return retval;
 }
index 1c3951b29c650d04805c78feb7d45614ef2d5950..517ab677597c486460395488f47810a7d8a9faea 100644 (file)
--- a/common.c
+++ b/common.c
 
 #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);
@@ -67,8 +69,7 @@ size_t strlcpy (char *dst, const char *src, size_t size)
        if (! n) {
                if (size)
                        *dst = '\0';
-               while (*src++)
-                       ;
+               while (*src++);
        }
 
        return (src - s - 1);
@@ -76,57 +77,31 @@ size_t strlcpy (char *dst, const char *src, size_t size)
 #  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) {
@@ -137,17 +112,24 @@ int get_time (struct timeval *tp)
        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)
 {
index 79940997db0ad2166c9283eed377d30297b00b77..1c8170874d719514d3ae62b25c54c6039b01ef81 100644 (file)
--- a/common.h
+++ b/common.h
@@ -37,8 +37,9 @@ size_t strlcpy (char *dst, const char *src, size_t size);
 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);
 
index 4d3ee0b67259b5c0f4a66bd3de324cc51196a1c6..050d4dc6f7b80169dba5fb2adafa82ddc4e2f023 100644 (file)
--- a/config.h
+++ b/config.h
  * 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. */
index f0194bfad4132cebf97b52c7938d2f1681cb3b5f..eb751bc0eac1e35b758b37f5e34b999558e567e5 100644 (file)
@@ -28,7 +28,7 @@
 
 #include <netinet/in.h>
 #ifdef __linux__
-#include <netinet/ether.h>
+# include <netinet/ether.h>
 #endif
 #include <string.h>
 #include <errno.h>
@@ -43,7 +43,7 @@
 #include "configure.h"
 #include "dhcp.h"
 #ifdef ENABLE_INFO
-#include "info.h"
+# include "info.h"
 #endif
 #include "interface.h"
 #include "dhcpcd.h"
@@ -62,11 +62,7 @@ static int exec_cmd (const char *cmd, const char *args, ...)
        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;
@@ -81,9 +77,13 @@ static int exec_cmd (const char *cmd, const char *args, ...)
                        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);
 }
 
diff --git a/dhcp.c b/dhcp.c
index 80ca8b51a64234b32379200d528e1ef8d20ab75c..c180ed6b988f2de65c6617cadcefa0d3ce427753 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -67,7 +67,7 @@ size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
        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;
@@ -106,7 +106,7 @@ size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
                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:
diff --git a/dhcp.h b/dhcp.h
index e47113beeb46e791b1227f5eac225f827a07db4a..a11286ce8af5b8a02fcb59cd04f72c2944daff5f 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
 #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"
index 63f922da04c0743905f651d25160c44abdd57949..b54cbd2fdf9dcb274a82fa7316e9d7bc8996ea0c 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -21,6 +21,7 @@
 
 /* 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;
@@ -128,6 +135,9 @@ int main(int argc, char **argv)
                {"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}
        };
 
@@ -185,6 +195,12 @@ int main(int argc, char **argv)
                                                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));
@@ -228,6 +244,7 @@ int main(int argc, char **argv)
                                break;
                        case 's':
                                options.doinform = true;
+                               options.doarp = false;
                                if (! optarg || strlen (optarg) == 0) {
                                        options.request_address.s_addr = 0;
                                        break;
@@ -238,11 +255,11 @@ int main(int argc, char **argv)
                                                /* 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 */
                                }
@@ -368,6 +385,24 @@ int main(int argc, char **argv)
        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)",
@@ -408,7 +443,7 @@ int main(int argc, char **argv)
 
        chdir ("/");
        umask (022);
-
+       
        if (mkdir (CONFIGDIR, S_IRUSR |S_IWUSR |S_IXUSR | S_IRGRP | S_IXGRP
                           | S_IROTH | S_IXOTH) && errno != EEXIST )
        {
@@ -440,7 +475,7 @@ int main(int argc, char **argv)
                }
        }
 
-       if (sig != 0 ) {
+       if (sig != 0) {
                int killed = -1;
                pid = read_pid (options.pidfile);
                if (pid != 0)
@@ -459,7 +494,7 @@ int main(int argc, char **argv)
                        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);
@@ -489,12 +524,14 @@ int main(int argc, char **argv)
        /* 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);
 }
index 235149cac9407e3a7f43cbce1ada7811fc150c8c..fe0dbcdf25cc8e839e2b5ccbde58a90b97855375 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
 #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];
@@ -69,6 +75,7 @@ typedef struct options_t {
        bool persistent;
        bool keep_address;
        bool daemonise;
+       bool daemonised;
        bool test;
 
        char *script;
diff --git a/duid.c b/duid.c
index 8ddbf2cafab51c371ba9b8d960f144d5ee4fcfcc..160b131c5ad1b5b052157e97d5e90b426e98b2e6 100644 (file)
--- a/duid.c
+++ b/duid.c
@@ -19,6 +19,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <arpa/inet.h>
 #include <errno.h>
 #include <stdbool.h>
 #include <stdlib.h>
index 3502fecc9d340169001bdc1a30bee3d4607304fe..9a87687bd14b363b25cec67c220db68eb56cb385 100644 (file)
@@ -58,9 +58,6 @@ void free_address (address_t *addresses)
        address_t *p = addresses;
        address_t *n = NULL;
 
-       if (! addresses)
-               return;
-
        while (p) {
                n = p->next;
                free (p);
@@ -73,9 +70,6 @@ void free_route (route_t *routes)
        route_t *p = routes;
        route_t *n = NULL;
 
-       if (! routes)
-               return;
-
        while (p) {
                n = p->next;
                free (p);
@@ -96,29 +90,23 @@ int inet_ntocidr (struct in_addr address)
        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)
@@ -498,6 +486,15 @@ static void log_route(
 
 #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)
 {
index eae71dd5cedaef40ca5b5750d08456e2f05e15e8..f3bf0505cb3503349c400b25a4a47360e4240156 100644 (file)
@@ -90,7 +90,7 @@ typedef struct interface_t
        struct in_addr previous_netmask;
        route_t *previous_routes;
 
-       long start_uptime;
+       time_t start_uptime;
 
 #ifdef ENABLE_DUID
        unsigned char duid[DUID_LEN];
@@ -124,6 +124,6 @@ int del_route (const char *ifname, struct in_addr destination,
                           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
index f05d188e3a34ff710ccbb6305581c850aaff1b2d..db5cb78b3a6099aa449f9dbc5439dfce234ad381 100644 (file)
--- a/ipv4ll.h
+++ b/ipv4ll.h
@@ -29,7 +29,9 @@
 #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);
 
index b1b87cb271e1afa05812e6e2bfe47230ed5b0ccf..832c0ab81a96e3bd5dfbb149b6fa9e50646c41e9 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -19,6 +19,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define _BSD_SOURCE
+
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/select.h>