#define PATH_MAX 1024
#endif
-#ifdef SIGINFO
+#if defined(SIGINFO)
#define SIGNAL_REQ_INFO SIGINFO
-#elif SIGUSR1
+#elif defined(SIGUSR1)
#define SIGNAL_REQ_INFO SIGUSR1
#endif
+#if defined(HAVE_PCAP_DUMP_FLUSH) && defined(SIGUSR2)
+#define SIGNAL_FLUSH_PCAP SIGUSR2
+#endif
+
static int Bflag; /* buffer size */
#ifdef HAVE_PCAP_DUMP_FTELL64
static int64_t Cflag; /* rotate dump files after this many bytes */
static int Wflag; /* recycle output files after this number of files */
static int WflagChars;
static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */
+#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
static int immediate_mode;
+#endif
static int infodelay;
static int infoprint;
static void droproot(const char *, const char *);
#ifdef SIGNAL_REQ_INFO
-void requestinfo(int);
+static void requestinfo(int);
+#endif
+
+#ifdef SIGNAL_FLUSH_PCAP
+static void flushpcap(int);
#endif
#ifdef _WIN32
{ PCAP_IF_RUNNING, "Running" },
#endif
{ PCAP_IF_LOOPBACK, "Loopback" },
+#ifdef PCAP_IF_WIRELESS
+ { PCAP_IF_WIRELESS, "Wireless" },
+#endif
{ 0, NULL }
};
#endif
static pcap_t *pd;
+static pcap_dumper_t *pdd = NULL;
static int supports_monitor_mode;
char *WFileName;
char *CurrentFileName;
pcap_t *pd;
- pcap_dumper_t *p;
+ pcap_dumper_t *pdd;
netdissect_options *ndo;
#ifdef HAVE_CAPSICUM
int dirfd;
printf("%d.%s", i+1, dev->name);
if (dev->description != NULL)
printf(" (%s)", dev->description);
- if (dev->flags != 0)
- printf(" [%s]", bittok2str(status_flags, "none", dev->flags));
+ if (dev->flags != 0) {
+ printf(" [");
+ printf("%s", bittok2str(status_flags, "none", dev->flags));
+#ifdef PCAP_IF_WIRELESS
+ if (dev->flags & PCAP_IF_WIRELESS) {
+ switch (dev->flags & PCAP_IF_CONNECTION_STATUS) {
+
+ case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
+ printf(", Association status unknown");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_CONNECTED:
+ printf(", Associated");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
+ printf(", Not associated");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
+ break;
+ }
+ } else {
+ switch (dev->flags & PCAP_IF_CONNECTION_STATUS) {
+
+ case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
+ printf(", Connection status unknown");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_CONNECTED:
+ printf(", Connected");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
+ printf(", Disconnected");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
+ break;
+ }
+ }
+#endif
+ printf("]");
+ }
printf("\n");
}
pcap_freealldevs(devlist);
static long
parse_interface_number(const char *device)
{
+ const char *p;
long devnum;
char *end;
+ /*
+ * Search for a colon, terminating any scheme at the beginning
+ * of the device.
+ */
+ p = strchr(device, ':');
+ if (p != NULL) {
+ /*
+ * We found it. Is it followed by "//"?
+ */
+ p++; /* skip the : */
+ if (strncmp(p, "//", 2) == 0) {
+ /*
+ * Yes. Search for the next /, at the end of the
+ * authority part of the URL.
+ */
+ p += 2; /* skip the // */
+ p = strchr(p, '/');
+ if (p != NULL) {
+ /*
+ * OK, past the / is the path.
+ */
+ device = p + 1;
+ }
+ }
+ }
devnum = strtol(device, &end, 10);
if (device != end && *end == '\0') {
/*
}
static char *
-find_interface_by_number(long devnum)
+find_interface_by_number(const char *url, long devnum)
{
pcap_if_t *dev, *devlist;
long i;
char ebuf[PCAP_ERRBUF_SIZE];
char *device;
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+ const char *endp;
+ char *host_url;
+#endif
+ int status;
- if (pcap_findalldevs(&devlist, ebuf) < 0)
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+ /*
+ * Search for a colon, terminating any scheme at the beginning
+ * of the URL.
+ */
+ endp = strchr(url, ':');
+ if (endp != NULL) {
+ /*
+ * We found it. Is it followed by "//"?
+ */
+ endp++; /* skip the : */
+ if (strncmp(endp, "//", 2) == 0) {
+ /*
+ * Yes. Search for the next /, at the end of the
+ * authority part of the URL.
+ */
+ endp += 2; /* skip the // */
+ endp = strchr(endp, '/');
+ } else
+ endp = NULL;
+ }
+ if (endp != NULL) {
+ /*
+ * OK, everything from device to endp is a URL to hand
+ * to pcap_findalldevs_ex().
+ */
+ endp++; /* Include the trailing / in the URL; pcap_findalldevs_ex() requires it */
+ host_url = malloc(endp - url + 1);
+ memcpy(host_url, url, endp - url);
+ host_url[endp - url] = '\0';
+ status = pcap_findalldevs_ex(host_url, NULL, &devlist, ebuf);
+ free(host_url);
+ } else
+#endif
+ status = pcap_findalldevs(&devlist, ebuf);
+ if (status < 0)
error("%s", ebuf);
/*
* Look for the devnum-th entry in the list of devices (1-based).
* Yes. Open it with pcap_open().
*/
*ebuf = '\0';
-fprintf(stderr, "Opening %s\n", device);
pc = pcap_open(device, ndo->ndo_snaplen,
pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL,
ebuf);
if (pc == NULL) {
/*
- * If this failed with "No such device", that means
+ * If this failed with "No such device" or "The system
+ * cannot find the device specified", that means
* the interface doesn't exist; return NULL, so that
* the caller can see whether the device name is
* actually an interface index.
*/
- if (strstr(ebuf, "No such device") != NULL)
+ if (strstr(ebuf, "No such device") != NULL ||
+ strstr(ebuf, "The system cannot find the device specified") != NULL)
return (NULL);
error("%s", ebuf);
}
* find_interface_by_number() exits if it
* couldn't be found.
*/
- device = find_interface_by_number(devnum);
+ device = find_interface_by_number(device, devnum);
pd = open_interface(device, ndo, ebuf);
if (pd == NULL)
error("%s", ebuf);
if (pcap_setfilter(pd, &fcode) < 0)
error("%s", pcap_geterr(pd));
#ifdef HAVE_CAPSICUM
- if (RFileName == NULL && VFileName == NULL) {
+ if (RFileName == NULL && VFileName == NULL && pcap_fileno(pd) != -1) {
static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF };
/*
}
#endif
if (WFileName) {
- pcap_dumper_t *p;
/* Do not exceed the default PATH_MAX for files. */
dumpinfo.CurrentFileName = (char *)malloc(PATH_MAX + 1);
else
MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0);
- p = pcap_dump_open(pd, dumpinfo.CurrentFileName);
+ pdd = pcap_dump_open(pd, dumpinfo.CurrentFileName);
#ifdef HAVE_LIBCAP_NG
/* Give up CAP_DAC_OVERRIDE capability.
* Only allow it to be restored if the -C or -G flag have been
);
capng_apply(CAPNG_SELECT_BOTH);
#endif /* HAVE_LIBCAP_NG */
- if (p == NULL)
+ if (pdd == NULL)
error("%s", pcap_geterr(pd));
#ifdef HAVE_CAPSICUM
set_dumper_capsicum_rights(p);
#endif
callback = dump_packet_and_trunc;
dumpinfo.pd = pd;
- dumpinfo.p = p;
+ dumpinfo.pdd = pdd;
pcap_userdata = (u_char *)&dumpinfo;
} else {
callback = dump_packet;
dumpinfo.WFileName = WFileName;
dumpinfo.pd = pd;
- dumpinfo.p = p;
+ dumpinfo.pdd = pdd;
pcap_userdata = (u_char *)&dumpinfo;
}
if (print) {
#ifdef HAVE_PCAP_DUMP_FLUSH
if (Uflag)
- pcap_dump_flush(p);
+ pcap_dump_flush(pdd);
#endif
} else {
dlt = pcap_datalink(pd);
if (RFileName == NULL)
(void)setsignal(SIGNAL_REQ_INFO, requestinfo);
#endif
+#ifdef SIGNAL_FLUSH_PCAP
+ (void)setsignal(SIGNAL_FLUSH_PCAP, flushpcap);
+#endif
if (ndo->ndo_vflag > 0 && WFileName && !print) {
/*
/*
* Close the current file and open a new one.
*/
- pcap_dump_close(dump_info->p);
+ pcap_dump_close(dump_info->pdd);
/*
* Compress the file we just closed, if the user asked for it
error("unable to fdopen file %s",
dump_info->CurrentFileName);
}
- dump_info->p = pcap_dump_fopen(dump_info->pd, fp);
+ dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp);
#else /* !HAVE_CAPSICUM */
- dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
+ dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
#endif
#ifdef HAVE_LIBCAP_NG
capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
capng_apply(CAPNG_SELECT_BOTH);
#endif /* HAVE_LIBCAP_NG */
- if (dump_info->p == NULL)
+ if (dump_info->pdd == NULL)
error("%s", pcap_geterr(pd));
#ifdef HAVE_CAPSICUM
- set_dumper_capsicum_rights(dump_info->p);
+ set_dumper_capsicum_rights(dump_info->pdd);
#endif
}
}
*/
if (Cflag != 0) {
#ifdef HAVE_PCAP_DUMP_FTELL64
- int64_t size = pcap_dump_ftell64(dump_info->p);
+ int64_t size = pcap_dump_ftell64(dump_info->pdd);
#else
/*
* XXX - this only handles a Cflag value > 2^31-1 on
* Windows) or LLP64 (64-bit Windows) would require
* a version of libpcap with pcap_dump_ftell64().
*/
- long size = pcap_dump_ftell(dump_info->p);
+ long size = pcap_dump_ftell(dump_info->pdd);
#endif
if (size == -1)
/*
* Close the current file and open a new one.
*/
- pcap_dump_close(dump_info->p);
+ pcap_dump_close(dump_info->pdd);
/*
* Compress the file we just closed, if the user
error("unable to fdopen file %s",
dump_info->CurrentFileName);
}
- dump_info->p = pcap_dump_fopen(dump_info->pd, fp);
+ dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp);
#else /* !HAVE_CAPSICUM */
- dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
+ dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
#endif
#ifdef HAVE_LIBCAP_NG
capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
capng_apply(CAPNG_SELECT_BOTH);
#endif /* HAVE_LIBCAP_NG */
- if (dump_info->p == NULL)
+ if (dump_info->pdd == NULL)
error("%s", pcap_geterr(pd));
#ifdef HAVE_CAPSICUM
- set_dumper_capsicum_rights(dump_info->p);
+ set_dumper_capsicum_rights(dump_info->pdd);
#endif
}
}
- pcap_dump((u_char *)dump_info->p, h, sp);
+ pcap_dump((u_char *)dump_info->pdd, h, sp);
#ifdef HAVE_PCAP_DUMP_FLUSH
if (Uflag)
- pcap_dump_flush(dump_info->p);
+ pcap_dump_flush(dump_info->pdd);
#endif
if (dump_info->ndo != NULL)
dump_info = (struct dump_info *)user;
- pcap_dump((u_char *)dump_info->p, h, sp);
+ pcap_dump((u_char *)dump_info->pdd, h, sp);
#ifdef HAVE_PCAP_DUMP_FLUSH
if (Uflag)
- pcap_dump_flush(dump_info->p);
+ pcap_dump_flush(dump_info->pdd);
#endif
if (dump_info->ndo != NULL)
}
#ifdef SIGNAL_REQ_INFO
-void requestinfo(int signo _U_)
+static void
+requestinfo(int signo _U_)
{
if (infodelay)
++infoprint;
}
#endif
+#ifdef SIGNAL_FLUSH_PCAP
+static void
+flushpcap(int signo _U_)
+{
+ if (pdd != NULL)
+ pcap_dump_flush(pdd);
+}
+#endif
+
static void
print_packets_captured (void)
{
(void)fprintf(stderr,
"\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n");
}
-/*
- * Local Variables:
- * c-style: whitesmith
- * c-basic-offset: 8
- * End:
- */