]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Merge pull request #588 from glebius/casper
authorGuy Harris <[email protected]>
Thu, 2 Feb 2017 20:18:56 +0000 (12:18 -0800)
committerGitHub <[email protected]>
Thu, 2 Feb 2017 20:18:56 +0000 (12:18 -0800)
Add support for libcasper library available on FreeBSD 11.0 and newer.

addrtoname.c
config.h.in
configure
configure.in
tcpdump.c

index 6975b7134e23c39e91eef115885b63dc6e8e1ac3..85cbf7b73179799d3c6391306d750ca946930cff 100644 (file)
 #include "config.h"
 #endif
 
+#ifdef HAVE_CASPER
+#include <libcasper.h>
+#include <casper/cap_dns.h>
+#endif /* HAVE_CASPER */
+
 #include <netdissect-stdinc.h>
 
 #ifdef USE_ETHER_NTOHOST
@@ -197,6 +202,9 @@ intoa(uint32_t addr)
 
 static uint32_t f_netmask;
 static uint32_t f_localnet;
+#ifdef HAVE_CASPER
+extern cap_channel_t *capdns;
+#endif
 
 /*
  * Return a name for the IP address pointed to by ap.  This address
@@ -242,7 +250,13 @@ getname(netdissect_options *ndo, const u_char *ap)
         */
        if (!ndo->ndo_nflag &&
            (addr & f_netmask) == f_localnet) {
-               hp = gethostbyaddr((char *)&addr, 4, AF_INET);
+#ifdef HAVE_CASPER
+               if (capdns != NULL) {
+                       hp = cap_gethostbyaddr(capdns, (char *)&addr, 4,
+                           AF_INET);
+               } else
+#endif
+                       hp = gethostbyaddr((char *)&addr, 4, AF_INET);
                if (hp) {
                        char *dotp;
 
@@ -297,7 +311,14 @@ getname6(netdissect_options *ndo, const u_char *ap)
         * Do not print names if -n was given.
         */
        if (!ndo->ndo_nflag) {
-               hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET6);
+#ifdef HAVE_CASPER
+               if (capdns != NULL) {
+                       hp = cap_gethostbyaddr(capdns, (char *)&addr,
+                           sizeof(addr), AF_INET6);
+               } else
+#endif
+                       hp = gethostbyaddr((char *)&addr, sizeof(addr),
+                           AF_INET6);
                if (hp) {
                        char *dotp;
 
index 27ba4b10d7a0fe6ae10279e7630040320b27d270..bf5f120d1b7722de2bd43afe3d5b67c6a2d9bc8e 100644 (file)
@@ -12,8 +12,8 @@
 /* capsicum support available */
 #undef HAVE_CAPSICUM
 
-/* Define to 1 if you have the `cap_enter' function. */
-#undef HAVE_CAP_ENTER
+/* Casper library available */
+#undef HAVE_CASPER
 
 /* Define to 1 if you have the `cap_ioctls_limit' function. */
 #undef HAVE_CAP_IOCTLS_LIMIT
index d2c3eeb479429c89d621e3facd2d4204e8246efc..3eba815eb434eb22563147135b21192ea433b084 100755 (executable)
--- a/configure
+++ b/configure
@@ -4588,6 +4588,86 @@ else
 fi
 done
 
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cap_init in -lcasper" >&5
+$as_echo_n "checking for cap_init in -lcasper... " >&6; }
+if ${ac_cv_lib_casper_cap_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcasper  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char cap_init ();
+int
+main ()
+{
+return cap_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_casper_cap_init=yes
+else
+  ac_cv_lib_casper_cap_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_casper_cap_init" >&5
+$as_echo "$ac_cv_lib_casper_cap_init" >&6; }
+if test "x$ac_cv_lib_casper_cap_init" = xyes; then :
+  LIBS="$LIBS -lcasper"
+fi
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cap_gethostbyaddr in -lcap_dns" >&5
+$as_echo_n "checking for cap_gethostbyaddr in -lcap_dns... " >&6; }
+if ${ac_cv_lib_cap_dns_cap_gethostbyaddr+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcap_dns  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char cap_gethostbyaddr ();
+int
+main ()
+{
+return cap_gethostbyaddr ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_cap_dns_cap_gethostbyaddr=yes
+else
+  ac_cv_lib_cap_dns_cap_gethostbyaddr=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_dns_cap_gethostbyaddr" >&5
+$as_echo "$ac_cv_lib_cap_dns_cap_gethostbyaddr" >&6; }
+if test "x$ac_cv_lib_cap_dns_cap_gethostbyaddr" = xyes; then :
+  LIBS="$LIBS -lcap_dns"
+fi
+
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to sandbox using capsicum" >&5
 $as_echo_n "checking whether to sandbox using capsicum... " >&6; }
@@ -4601,6 +4681,18 @@ else
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to sandbox using Casper library" >&5
+$as_echo_n "checking whether to sandbox using Casper library... " >&6; }
+if test "x$ac_cv_lib_casper_cap_init" = "xyes" -a "x$ac_cv_lib_cap_dns_cap_gethostbyaddr" = "xyes"; then
+
+$as_echo "#define HAVE_CASPER 1" >>confdefs.h
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
 
 #
 # We must check this before checking whether to check the OS's IPv6,
index a78a12666347f6871966c8a1b209e82fa3f66a57..9b06fd9255308cb0a65f134cf679545fd9553463 100644 (file)
@@ -225,6 +225,8 @@ if test ! -z "$with_sandbox-capsicum" && test "$with_sandbox-capsicum" != "no" ;
        AC_CHECK_FUNCS(cap_enter cap_rights_limit cap_ioctls_limit openat,
            ac_lbl_capsicum_function_seen=yes,
            ac_lbl_capsicum_function_not_seen=yes)
+       AC_CHECK_LIB(casper, cap_init, LIBS="$LIBS -lcasper")
+       AC_CHECK_LIB(cap_dns, cap_gethostbyaddr, LIBS="$LIBS -lcap_dns")
 fi
 AC_MSG_CHECKING([whether to sandbox using capsicum])
 if test "x$ac_lbl_capsicum_function_seen" = "xyes" -a "x$ac_lbl_capsicum_function_not_seen" != "xyes"; then
@@ -233,6 +235,13 @@ if test "x$ac_lbl_capsicum_function_seen" = "xyes" -a "x$ac_lbl_capsicum_functio
 else
        AC_MSG_RESULT(no)
 fi
+AC_MSG_CHECKING([whether to sandbox using Casper library])
+if test "x$ac_cv_lib_casper_cap_init" = "xyes" -a "x$ac_cv_lib_cap_dns_cap_gethostbyaddr" = "xyes"; then
+       AC_DEFINE(HAVE_CASPER, 1, [Casper support available])
+       AC_MSG_RESULT(yes)
+else
+       AC_MSG_RESULT(no)
+fi
 
 #
 # We must check this before checking whether to check the OS's IPv6,
index e26fbafdd7013dde2b494cbd815d644eb6ccd570..2bfc6b0f2cf5ef864c501a747ed83d8d40665f06 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -80,6 +80,11 @@ The Regents of the University of California.  All rights reserved.\n";
 #include <sys/ioccom.h>
 #include <net/bpf.h>
 #include <libgen.h>
+#ifdef HAVE_CASPER
+#include <libcasper.h>
+#include <casper/cap_dns.h>
+#include <sys/nv.h>
+#endif /* HAVE_CASPER */
 #endif /* HAVE_CAPSICUM */
 #include <pcap.h>
 #include <signal.h>
@@ -170,6 +175,10 @@ static int infoprint;
 
 char *program_name;
 
+#ifdef HAVE_CASPER
+cap_channel_t *capdns;
+#endif
+
 /* Forwards */
 static void error(const char *, ...)
      __attribute__((noreturn))
@@ -720,6 +729,35 @@ get_next_file(FILE *VFile, char *ptr)
        return ret;
 }
 
+#ifdef HAVE_CASPER
+static cap_channel_t *
+capdns_setup(void)
+{
+       cap_channel_t *capcas, *capdnsloc;
+       const char *types[1];
+       int families[2];
+
+       capcas = cap_init();
+       if (capcas == NULL)
+               error("unable to create casper process");
+       capdnsloc = cap_service_open(capcas, "system.dns");
+       /* Casper capability no longer needed. */
+       cap_close(capcas);
+       if (capdnsloc == NULL)
+               error("unable to open system.dns service");
+       /* Limit system.dns to reverse DNS lookups. */
+       types[0] = "ADDR";
+       if (cap_dns_type_limit(capdnsloc, types, 1) < 0)
+               error("unable to limit access to system.dns service");
+       families[0] = AF_INET;
+       families[1] = AF_INET6;
+       if (cap_dns_family_limit(capdnsloc, families, 2) < 0)
+               error("unable to limit access to system.dns service");
+
+       return (capdnsloc);
+}
+#endif /* HAVE_CASPER */
+
 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
 static int
 tstamp_precision_from_string(const char *precision)
@@ -1779,6 +1817,12 @@ main(int argc, char **argv)
                pcap_freecode(&fcode);
                exit_tcpdump(0);
        }
+
+#ifdef HAVE_CASPER
+       if (!ndo->ndo_nflag)
+               capdns = capdns_setup();
+#endif /* HAVE_CASPER */
+
        init_print(ndo, localnet, netmask, timezone_offset);
 
 #ifndef _WIN32
@@ -2000,7 +2044,12 @@ main(int argc, char **argv)
        }
 
 #ifdef HAVE_CAPSICUM
-       cansandbox = (ndo->ndo_nflag && VFileName == NULL && zflag == NULL);
+       cansandbox = (VFileName == NULL && zflag == NULL);
+#ifdef HAVE_CASPER
+       cansandbox = (cansandbox && (ndo->ndo_nflag || capdns != NULL));
+#else
+       cansandbox = (cansandbox && ndo->ndo_nflag);
+#endif /* HAVE_CASPER */
        if (cansandbox && cap_enter() < 0 && errno != ENOSYS)
                error("unable to enter the capability mode");
 #endif /* HAVE_CAPSICUM */