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