Add support for libcasper library available on FreeBSD 11.0 and newer.
#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
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
*/
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;
* 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;
/* Find the hash node that corresponds the NSAP 'nsap' */
static inline struct enamemem *
-lookup_nsap(netdissect_options *ndo, register const u_char *nsap)
+lookup_nsap(netdissect_options *ndo, register const u_char *nsap,
+ register u_int nsap_length)
{
register u_int i, j, k;
- unsigned int nlen = *nsap;
struct enamemem *tp;
- const u_char *ensap = nsap + nlen - 6;
+ const u_char *ensap;
- if (nlen > 6) {
+ if (nsap_length > 6) {
+ ensap = nsap + nsap_length - 6;
k = (ensap[0] << 8) | ensap[1];
j = (ensap[2] << 8) | ensap[3];
i = (ensap[4] << 8) | ensap[5];
if (tp->e_addr0 == i &&
tp->e_addr1 == j &&
tp->e_addr2 == k &&
- tp->e_nsap[0] == nlen &&
+ tp->e_nsap[0] == nsap_length &&
memcmp((const char *)&(nsap[1]),
- (char *)&(tp->e_nsap[1]), nlen) == 0)
+ (char *)&(tp->e_nsap[1]), nsap_length) == 0)
return tp;
else
tp = tp->e_nxt;
tp->e_addr0 = i;
tp->e_addr1 = j;
tp->e_addr2 = k;
- tp->e_nsap = (u_char *)malloc(nlen + 1);
+ tp->e_nsap = (u_char *)malloc(nsap_length + 1);
if (tp->e_nsap == NULL)
(*ndo->ndo_error)(ndo, "lookup_nsap: malloc");
- memcpy((char *)tp->e_nsap, (const char *)nsap, nlen + 1);
+ tp->e_nsap[0] = (u_char)nsap_length; /* guaranteed < ISONSAP_MAX_LENGTH */
+ memcpy((char *)&tp->e_nsap[1], (const char *)nsap, nsap_length);
tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
if (tp->e_nxt == NULL)
(*ndo->ndo_error)(ndo, "lookup_nsap: calloc");
if (nsap_length < 1 || nsap_length > ISONSAP_MAX_LENGTH)
return ("isonsap_string: illegal length");
- tp = lookup_nsap(ndo, nsap);
+ tp = lookup_nsap(ndo, nsap, nsap_length);
if (tp->e_name)
return tp->e_name;
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; }
{ $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,
-
LBL_LIBS="$LIBS"
pfopen=/usr/examples/packetfilter/pfopen.c
if test -f $pfopen ; then
else
+ as_fn_error $? "This is a bug, please follow the guidelines in CONTRIBUTING and include the
config.log file in your report. If you have downloaded libpcap from
tcpdump.org, and built it yourself, please also include the config.log
file from the libpcap source directory, the Makefile from the libpcap
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
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,
AC_SEARCH_LIBS(getrpcbynumber, nsl,
AC_DEFINE(HAVE_GETRPCBYNUMBER, 1, [define if you have getrpcbynumber()]))
-dnl AC_CHECK_LIB(z, uncompress)
-dnl AC_CHECK_HEADERS(zlib.h)
-
AC_LBL_LIBPCAP(V_PCAPDEP, V_INCLS)
#
#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>
char *program_name;
+ #ifdef HAVE_CASPER
+ cap_channel_t *capdns;
+ #endif
+
/* Forwards */
static void error(const char *, ...)
__attribute__((noreturn))
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)
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
if (RFileName == NULL && VFileName == NULL) {
static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF };
- cap_rights_init(&rights, CAP_IOCTL, CAP_READ);
+ /*
+ * The various libpcap devices use a combination of
+ * read (bpf), ioctl (bpf, netmap), poll (netmap)
+ * so we add the relevant access rights.
+ */
+ cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_EVENT);
if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 &&
errno != ENOSYS) {
error("unable to limit pcap descriptor");
}
#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 */