324fcf
diff --git a/client/Makefile.am b/client/Makefile.am
324fcf
index b1ecf82..387c097 100644
324fcf
--- a/client/Makefile.am
324fcf
+++ b/client/Makefile.am
324fcf
@@ -15,6 +15,7 @@ dhclient_SOURCES = clparse.c dhclient.c dhc6.c \
324fcf
 		   scripts/bsdos scripts/freebsd scripts/linux scripts/macos \
324fcf
 		   scripts/netbsd scripts/nextstep scripts/openbsd \
324fcf
 		   scripts/solaris scripts/openwrt
324fcf
-dhclient_LDADD = ../common/libdhcp.a ../omapip/libomapi.la $(BIND_LIBS)
324fcf
+dhclient_LDADD = ../common/libdhcp.a ../omapip/libomapi.la \
324fcf
+		 $(CAPNG_LDADD) $(BIND_LIBS)
324fcf
 man_MANS = dhclient.8 dhclient-script.8 dhclient.conf.5 dhclient.leases.5
324fcf
 EXTRA_DIST = $(man_MANS)
324fcf
diff --git a/client/dhclient-script.8 b/client/dhclient-script.8
324fcf
index 3a3aaf7..fec726c 100644
324fcf
--- a/client/dhclient-script.8
324fcf
+++ b/client/dhclient-script.8
324fcf
@@ -245,6 +245,16 @@ repeatedly initialized to the values provided by one server, and then
324fcf
 the other.   Assuming the information provided by both servers is
324fcf
 valid, this shouldn't cause any real problems, but it could be
324fcf
 confusing.
324fcf
+.PP
324fcf
+Normally, if dhclient was compiled with libcap-ng support,
324fcf
+dhclient drops most capabilities immediately upon startup.
324fcf
+While more secure, this greatly restricts the additional actions that
324fcf
+hooks in dhclient-script can take. For example, any daemons that
324fcf
+dhclient-script starts or restarts will inherit the restricted
324fcf
+capabilities as well, which may interfere with their correct operation.
324fcf
+Thus, the
324fcf
+.BI \-nc
324fcf
+option can be used to prevent dhclient from dropping capabilities.
324fcf
 .SH SEE ALSO
324fcf
 dhclient(8), dhcpd(8), dhcrelay(8), dhclient.conf(5) and
324fcf
 dhclient.leases(5).
324fcf
diff --git a/client/dhclient.8 b/client/dhclient.8
324fcf
index aa2238d..005cda5 100644
324fcf
--- a/client/dhclient.8
324fcf
+++ b/client/dhclient.8
324fcf
@@ -134,6 +134,9 @@ dhclient - Dynamic Host Configuration Protocol Client
324fcf
 .B -w
324fcf
 ]
324fcf
 [
324fcf
+.B -nc
324fcf
+]
324fcf
+[
324fcf
 .B -B
324fcf
 ]
324fcf
 [
324fcf
@@ -320,6 +323,32 @@ not to exit when it doesn't find any such interfaces.  The
324fcf
 program can then be used to notify the client when a network interface
324fcf
 has been added or removed, so that the client can attempt to configure an IP
324fcf
 address on that interface.
324fcf
+.TP
324fcf
+.BI \-nc
324fcf
+Do not drop capabilities.
324fcf
+
324fcf
+Normally, if
324fcf
+.B dhclient
324fcf
+was compiled with libcap-ng support,
324fcf
+.B dhclient
324fcf
+drops most capabilities immediately upon startup.  While more secure,
324fcf
+this greatly restricts the additional actions that hooks in
324fcf
+.B dhclient-script (8)
324fcf
+can take.  (For example, any daemons that 
324fcf
+.B dhclient-script (8)
324fcf
+starts or restarts will inherit the restricted capabilities as well,
324fcf
+which may interfere with their correct operation.)  Thus, the
324fcf
+.BI \-nc
324fcf
+option can be used to prevent
324fcf
+.B dhclient
324fcf
+from dropping capabilities.
324fcf
+
324fcf
+The
324fcf
+.BI \-nc
324fcf
+option is ignored if
324fcf
+.B dhclient
324fcf
+was not compiled with libcap-ng support.
324fcf
+
324fcf
 .TP
324fcf
 .BI \-n
324fcf
 Do not configure any interfaces.  This is most likely to be useful in
324fcf
diff --git a/client/dhclient.c b/client/dhclient.c
324fcf
index 09ae09b..2d564ff 100644
324fcf
--- a/client/dhclient.c
324fcf
+++ b/client/dhclient.c
324fcf
@@ -40,6 +40,10 @@
324fcf
 #include <isc/file.h>
324fcf
 #include <dns/result.h>
324fcf
 
324fcf
+#ifdef HAVE_LIBCAP_NG
324fcf
+#include <cap-ng.h>
324fcf
+#endif
324fcf
+
324fcf
 /*
324fcf
  * Defined in stdio.h when _GNU_SOURCE is set, but we don't want to define
324fcf
  * that when building ISC code.
324fcf
@@ -239,6 +243,9 @@ main(int argc, char **argv) {
324fcf
 	int timeout_arg = 0;
324fcf
 	char *arg_conf = NULL;
324fcf
 	int arg_conf_len = 0;
324fcf
+#ifdef HAVE_LIBCAP_NG
324fcf
+	int keep_capabilities = 0;
324fcf
+#endif
324fcf
 
324fcf
 	/* Initialize client globals. */
324fcf
 	memset(&default_duid, 0, sizeof(default_duid));
324fcf
@@ -548,6 +555,10 @@ main(int argc, char **argv) {
324fcf
 			}
324fcf
 
324fcf
 			dhclient_request_options = argv[i];
324fcf
+		} else if (!strcmp(argv[i], "-nc")) {
324fcf
+#ifdef HAVE_LIBCAP_NG
324fcf
+			keep_capabilities = 1;
324fcf
+#endif
324fcf
 		} else if (argv[i][0] == '-') {
324fcf
 			usage("Unknown command: %s", argv[i]);
324fcf
 		} else if (interfaces_requested < 0) {
324fcf
@@ -608,6 +619,19 @@ main(int argc, char **argv) {
324fcf
 		path_dhclient_script = s;
324fcf
 	}
324fcf
 
324fcf
+#ifdef HAVE_LIBCAP_NG
324fcf
+	/* Drop capabilities */
324fcf
+	if (!keep_capabilities) {
324fcf
+		capng_clear(CAPNG_SELECT_CAPS);
324fcf
+		capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
324fcf
+				CAP_DAC_OVERRIDE); // Drop this someday
324fcf
+		capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
324fcf
+				CAP_NET_ADMIN, CAP_NET_RAW,
324fcf
+				CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, -1);
324fcf
+		capng_apply(CAPNG_SELECT_CAPS);
324fcf
+	}
324fcf
+#endif
324fcf
+
324fcf
 	/* Set up the initial dhcp option universe. */
324fcf
 	initialize_common_option_spaces();
324fcf
 
324fcf
diff --git a/configure.ac b/configure.ac
324fcf
index adc98a8..8bbe5ca 100644
324fcf
--- a/configure.ac
324fcf
+++ b/configure.ac
324fcf
@@ -592,6 +592,41 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[void foo() __attribute__((noreturn));
324fcf
 # Look for optional headers.
324fcf
 AC_CHECK_HEADERS(sys/socket.h net/if_dl.h net/if6.h regex.h)
324fcf
 
324fcf
+# look for capabilities library
324fcf
+AC_ARG_WITH(libcap-ng,
324fcf
+    [  --with-libcap-ng=[auto/yes/no]  Add Libcap-ng support [default=auto]],,
324fcf
+    with_libcap_ng=auto)
324fcf
+
324fcf
+# Check for Libcap-ng API
324fcf
+#
324fcf
+# libcap-ng detection
324fcf
+if test x$with_libcap_ng = xno ; then
324fcf
+    have_libcap_ng=no;
324fcf
+else
324fcf
+    # Start by checking for header file
324fcf
+    AC_CHECK_HEADER(cap-ng.h, capng_headers=yes, capng_headers=no)
324fcf
+
324fcf
+    # See if we have libcap-ng library
324fcf
+    AC_CHECK_LIB(cap-ng, capng_clear,
324fcf
+                 CAPNG_LDADD=-lcap-ng,)
324fcf
+
324fcf
+    # Check results are usable
324fcf
+    if test x$with_libcap_ng = xyes -a x$CAPNG_LDADD = x ; then
324fcf
+       AC_MSG_ERROR(libcap-ng support was requested and the library was not found)
324fcf
+    fi
324fcf
+    if test x$CAPNG_LDADD != x -a $capng_headers = no ; then
324fcf
+       AC_MSG_ERROR(libcap-ng libraries found but headers are missing)
324fcf
+    fi
324fcf
+fi
324fcf
+AC_SUBST(CAPNG_LDADD)
324fcf
+AC_MSG_CHECKING(whether to use libcap-ng)
324fcf
+if test x$CAPNG_LDADD != x ; then
324fcf
+    AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support])
324fcf
+    AC_MSG_RESULT(yes)
324fcf
+else
324fcf
+    AC_MSG_RESULT(no)
324fcf
+fi
324fcf
+
324fcf
 # Solaris needs some libraries for functions
324fcf
 AC_SEARCH_LIBS(socket, [socket])
324fcf
 AC_SEARCH_LIBS(inet_ntoa, [nsl])
324fcf
diff --git a/relay/Makefile.am b/relay/Makefile.am
324fcf
index 316a524..999e543 100644
324fcf
--- a/relay/Makefile.am
324fcf
+++ b/relay/Makefile.am
324fcf
@@ -5,7 +5,7 @@ AM_CPPFLAGS = -DLOCALSTATEDIR='"@localstatedir@"'
324fcf
 sbin_PROGRAMS = dhcrelay
324fcf
 dhcrelay_SOURCES = dhcrelay.c
324fcf
 dhcrelay_LDADD = ../common/libdhcp.a ../omapip/libomapi.la \
324fcf
-		 $(BIND_LIBS)
324fcf
+		 $(CAPNG_LDADD) $(BIND_LIBS)
324fcf
 man_MANS = dhcrelay.8
324fcf
 EXTRA_DIST = $(man_MANS)
324fcf
 
324fcf
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
324fcf
index eac119c..d2ab448 100644
324fcf
--- a/relay/dhcrelay.c
324fcf
+++ b/relay/dhcrelay.c
324fcf
@@ -32,6 +32,11 @@
324fcf
 #include <sys/time.h>
324fcf
 #include <isc/file.h>
324fcf
 
324fcf
+#ifdef HAVE_LIBCAP_NG
324fcf
+#  include <cap-ng.h>
324fcf
+   int keep_capabilities = 0;
324fcf
+#endif
324fcf
+
324fcf
 TIME default_lease_time = 43200; /* 12 hours... */
324fcf
 TIME max_lease_time = 86400; /* 24 hours... */
324fcf
 struct tree_cache *global_options[256];
324fcf
@@ -472,6 +477,10 @@ main(int argc, char **argv) {
324fcf
 			if (++i == argc)
324fcf
 				usage(use_noarg, argv[i-1]);
324fcf
 			dhcrelay_sub_id = argv[i];
324fcf
+#endif
324fcf
+		} else if (!strcmp(argv[i], "-nc")) {
324fcf
+#ifdef HAVE_LIBCAP_NG
324fcf
+			keep_capabilities = 1;
324fcf
 #endif
324fcf
 		} else if (!strcmp(argv[i], "-pf")) {
324fcf
 			if (++i == argc)
324fcf
@@ -547,6 +556,17 @@ main(int argc, char **argv) {
324fcf
 #endif
324fcf
 	}
324fcf
 
324fcf
+#ifdef HAVE_LIBCAP_NG
324fcf
+	/* Drop capabilities */
324fcf
+	if (!keep_capabilities) {
324fcf
+		capng_clear(CAPNG_SELECT_BOTH);
324fcf
+		capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
324fcf
+				CAP_NET_RAW, CAP_NET_BIND_SERVICE, -1);
324fcf
+		capng_apply(CAPNG_SELECT_BOTH);
324fcf
+		log_info ("Dropped all unnecessary capabilities.");
324fcf
+	}
324fcf
+#endif
324fcf
+
324fcf
 	if (!quiet) {
324fcf
 		log_info("%s %s", message, PACKAGE_VERSION);
324fcf
 		log_info(copyright);
324fcf
@@ -699,6 +719,15 @@ main(int argc, char **argv) {
324fcf
 	signal(SIGTERM, dhcp_signal_handler);  /* kill */
324fcf
 #endif
324fcf
 
324fcf
+#ifdef HAVE_LIBCAP_NG
324fcf
+	/* Drop all capabilities */
324fcf
+	if (!keep_capabilities) {
324fcf
+		capng_clear(CAPNG_SELECT_BOTH);
324fcf
+		capng_apply(CAPNG_SELECT_BOTH);
324fcf
+		log_info ("Dropped all capabilities.");
324fcf
+	}
324fcf
+#endif
324fcf
+
324fcf
 	/* Start dispatching packets and timeouts... */
324fcf
 	dispatch();
324fcf