summaryrefslogtreecommitdiffstats
path: root/contrib/tcpdump/tcpdump.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tcpdump/tcpdump.c')
-rw-r--r--contrib/tcpdump/tcpdump.c125
1 files changed, 124 insertions, 1 deletions
diff --git a/contrib/tcpdump/tcpdump.c b/contrib/tcpdump/tcpdump.c
index c8f86db..7cfcc68 100644
--- a/contrib/tcpdump/tcpdump.c
+++ b/contrib/tcpdump/tcpdump.c
@@ -68,6 +68,13 @@ extern int SIZE_BUF;
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#ifdef __FreeBSD__
+#include <sys/capability.h>
+#include <sys/ioccom.h>
+#include <net/bpf.h>
+#include <fcntl.h>
+#include <libgen.h>
+#endif /* __FreeBSD__ */
#ifndef WIN32
#include <sys/wait.h>
#include <sys/resource.h>
@@ -384,6 +391,9 @@ struct dump_info {
char *CurrentFileName;
pcap_t *pd;
pcap_dumper_t *p;
+#ifdef __FreeBSD__
+ int dirfd;
+#endif
};
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
@@ -702,6 +712,10 @@ main(int argc, char **argv)
#endif
int status;
FILE *VFile;
+#ifdef __FreeBSD__
+ int cansandbox;
+#endif
+
#ifdef WIN32
if(wsockinit() != 0) return 1;
#endif /* WIN32 */
@@ -1189,6 +1203,12 @@ main(int argc, char **argv)
pd = pcap_open_offline(RFileName, ebuf);
if (pd == NULL)
error("%s", ebuf);
+#ifdef __FreeBSD__
+ if (cap_rights_limit(fileno(pcap_file(pd)), CAP_READ) < 0 &&
+ errno != ENOSYS) {
+ error("unable to limit pcap descriptor");
+ }
+#endif
dlt = pcap_datalink(pd);
dlt_name = pcap_datalink_val_to_name(dlt);
if (dlt_name == NULL) {
@@ -1437,6 +1457,20 @@ main(int argc, char **argv)
if (pcap_setfilter(pd, &fcode) < 0)
error("%s", pcap_geterr(pd));
+#ifdef __FreeBSD__
+ if (RFileName == NULL && VFileName == NULL) {
+ static const unsigned long cmds[] = { BIOCGSTATS };
+
+ if (cap_rights_limit(pcap_fileno(pd),
+ CAP_IOCTL | CAP_READ) < 0 && errno != ENOSYS) {
+ error("unable to limit pcap descriptor");
+ }
+ if (cap_ioctls_limit(pcap_fileno(pd), cmds,
+ sizeof(cmds) / sizeof(cmds[0])) < 0 && errno != ENOSYS) {
+ error("unable to limit ioctls on pcap descriptor");
+ }
+ }
+#endif
if (WFileName) {
pcap_dumper_t *p;
/* Do not exceed the default PATH_MAX for files. */
@@ -1458,9 +1492,30 @@ main(int argc, char **argv)
#endif
if (p == NULL)
error("%s", pcap_geterr(pd));
+#ifdef __FreeBSD__
+ if (cap_rights_limit(fileno(pcap_dump_file(p)),
+ CAP_SEEK | CAP_WRITE) < 0 && errno != ENOSYS) {
+ error("unable to limit dump descriptor");
+ }
+#endif
if (Cflag != 0 || Gflag != 0) {
- callback = dump_packet_and_trunc;
+#ifdef __FreeBSD__
+ dumpinfo.WFileName = strdup(basename(WFileName));
+ dumpinfo.dirfd = open(dirname(WFileName),
+ O_DIRECTORY | O_RDONLY);
+ if (dumpinfo.dirfd < 0) {
+ error("unable to open directory %s",
+ dirname(WFileName));
+ }
+ if (cap_rights_limit(dumpinfo.dirfd, CAP_CREATE |
+ CAP_FCNTL | CAP_FTRUNCATE | CAP_LOOKUP | CAP_SEEK |
+ CAP_WRITE) < 0 && errno != ENOSYS) {
+ error("unable to limit directory rights");
+ }
+#else /* !__FreeBSD__ */
dumpinfo.WFileName = WFileName;
+#endif
+ callback = dump_packet_and_trunc;
dumpinfo.pd = pd;
dumpinfo.p = p;
pcap_userdata = (u_char *)&dumpinfo;
@@ -1530,6 +1585,15 @@ main(int argc, char **argv)
(void)fflush(stderr);
}
#endif /* WIN32 */
+
+#ifdef __FreeBSD__
+ cansandbox = (nflag && VFileName == NULL && zflag == NULL);
+ if (cansandbox && cap_enter() < 0 && errno != ENOSYS)
+ error("unable to enter the capability mode");
+ if (cap_sandboxed())
+ fprintf(stderr, "capability mode sandbox enabled\n");
+#endif
+
do {
status = pcap_loop(pd, cnt, callback, pcap_userdata);
if (WFileName == NULL) {
@@ -1569,6 +1633,12 @@ main(int argc, char **argv)
pd = pcap_open_offline(RFileName, ebuf);
if (pd == NULL)
error("%s", ebuf);
+#ifdef __FreeBSD__
+ if (cap_rights_limit(fileno(pcap_file(pd)),
+ CAP_READ) < 0 && errno != ENOSYS) {
+ error("unable to limit pcap descriptor");
+ }
+#endif
new_dlt = pcap_datalink(pd);
if (WFileName && new_dlt != dlt)
error("%s: new dlt does not match original", RFileName);
@@ -1765,6 +1835,11 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
/* If the time is greater than the specified window, rotate */
if (t - Gflag_time >= Gflag) {
+#ifdef __FreeBSD__
+ FILE *fp;
+ int fd;
+#endif
+
/* Update the Gflag_time */
Gflag_time = t;
/* Update Gflag_count */
@@ -1811,13 +1886,35 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
capng_apply(CAPNG_EFFECTIVE);
#endif /* HAVE_CAP_NG_H */
+#ifdef __FreeBSD__
+ fd = openat(dump_info->dirfd,
+ dump_info->CurrentFileName,
+ O_CREAT | O_WRONLY | O_TRUNC, 0644);
+ if (fd < 0) {
+ error("unable to open file %s",
+ dump_info->CurrentFileName);
+ }
+ fp = fdopen(fd, "w");
+ if (fp == NULL) {
+ error("unable to fdopen file %s",
+ dump_info->CurrentFileName);
+ }
+ dump_info->p = pcap_dump_fopen(dump_info->pd, fp);
+#else /* !__FreeBSD__ */
dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
+#endif
#ifdef HAVE_CAP_NG_H
capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
capng_apply(CAPNG_EFFECTIVE);
#endif /* HAVE_CAP_NG_H */
if (dump_info->p == NULL)
error("%s", pcap_geterr(pd));
+#ifdef __FreeBSD__
+ if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)),
+ CAP_SEEK | CAP_WRITE) < 0 && errno != ENOSYS) {
+ error("unable to limit dump descriptor");
+ }
+#endif
}
}
@@ -1827,6 +1924,11 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
* file could put it over Cflag.
*/
if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) {
+#ifdef __FreeBSD__
+ FILE *fp;
+ int fd;
+#endif
+
/*
* Close the current file and open a new one.
*/
@@ -1849,9 +1951,30 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
if (dump_info->CurrentFileName == NULL)
error("dump_packet_and_trunc: malloc");
MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars);
+#ifdef __FreeBSD__
+ fd = openat(dump_info->dirfd, dump_info->CurrentFileName,
+ O_CREAT | O_WRONLY | O_TRUNC, 0644);
+ if (fd < 0) {
+ error("unable to open file %s",
+ dump_info->CurrentFileName);
+ }
+ fp = fdopen(fd, "w");
+ if (fp == NULL) {
+ error("unable to fdopen file %s",
+ dump_info->CurrentFileName);
+ }
+ dump_info->p = pcap_dump_fopen(dump_info->pd, fp);
+#else /* !__FreeBSD__ */
dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
+#endif
if (dump_info->p == NULL)
error("%s", pcap_geterr(pd));
+#ifdef __FreeBSD__
+ if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)),
+ CAP_SEEK | CAP_WRITE) < 0 && errno != ENOSYS) {
+ error("unable to limit dump descriptor");
+ }
+#endif
}
pcap_dump((u_char *)dump_info->p, h, sp);
OpenPOWER on IntegriCloud