#ifdef _WIN32
/*
- * DllMain(), required when built as a Windows DLL.
- *
* To quote the WSAStartup() documentation:
*
* The WSAStartup function typically leads to protocol-specific helper
* be called from the DllMain function in a application DLL. This can
* potentially cause deadlocks.
*
- * So we don't initialize Winsock here. pcap_init() should be called
- * to initialize pcap on both UN*X and Windows; it will initialize
- * Winsock on Windows. (It will also be initialized as needed if
- * pcap_init() hasn't been called.)
+ * So we don't initialize Winsock in a DllMain() routine.
+ *
+ * pcap_init() should be called to initialize pcap on both UN*X and
+ * Windows; it will initialize Winsock on Windows. (It will also be
+ * initialized as needed if pcap_init() hasn't been called.)
*/
-BOOL WINAPI DllMain(
- HANDLE hinstDLL _U_,
- DWORD dwReason _U_,
- LPVOID lpvReserved _U_
-)
-{
- return (TRUE);
-}
/*
* Start Winsock.
if (pcap_utf_8_mode) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Multiple pcap_init calls with different character encodings");
- return (-1);
+ return (PCAP_ERROR);
}
}
break;
if (!pcap_utf_8_mode) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Multiple pcap_init calls with different character encodings");
- return (-1);
+ return (PCAP_ERROR);
}
}
pcap_utf_8_mode = 1;
default:
snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unknown options specified");
- return (-1);
+ return (PCAP_ERROR);
}
/*
*/
if (internal_wsockinit(errbuf) == -1) {
/* Failed. */
- return (-1);
+ return (PCAP_ERROR);
}
#endif
* Return codes for pcap_offline_read() are:
* - 0: EOF
* - -1: error
- * - >1: OK
+ * - >0: OK - result is number of packets read, so
+ * it will be 1 in this case, as we've passed
+ * a maximum packet count of 1
* The first one ('0') conflicts with the return code of
* 0 from pcap_read() meaning "no packets arrived before
* the timeout expired", so we map it to -2 so you can
* - 0: timeout
* - -1: error
* - -2: loop was broken out of with pcap_breakloop()
- * - >1: OK
+ * - >0: OK, result is number of packets captured, so
+ * it will be 1 in this case, as we've passed
+ * a maximum packet count of 1
* The first one ('0') conflicts with the return code of 0 from
* pcap_offline_read() meaning "end of file".
*/
* see if it looks like a loopback device.
*/
if (name[0] == 'l' && name[1] == 'o' &&
- (PCAP_ISDIGIT(name[2]) || name[2] == '\0')
+ (PCAP_ISDIGIT(name[2]) || name[2] == '\0'))
pcap_flags |= PCAP_IF_LOOPBACK;
#endif
#ifdef IFF_UP
}
static pcap_t *
-pcap_alloc_pcap_t(char *ebuf, size_t size)
+pcap_alloc_pcap_t(char *ebuf, size_t total_size, size_t private_offset)
{
char *chunk;
pcap_t *p;
/*
- * Allocate a chunk of memory big enough for a pcap_t
- * plus a structure following it of size "size". The
- * structure following it is a private data structure
- * for the routines that handle this pcap_t.
- *
- * The structure following it must be aligned on
- * the appropriate alignment boundary for this platform.
- * We align on an 8-byte boundary as that's probably what
- * at least some platforms do, even with 32-bit integers,
- * and because we can't be sure that some values won't
- * require 8-byte alignment even on platforms with 32-bit
- * integers.
+ * total_size is the size of a structure containing a pcap_t
+ * followed by a private structure.
*/
-#define PCAP_T_ALIGNED_SIZE ((sizeof(pcap_t) + 7U) & ~0x7U)
- chunk = calloc(PCAP_T_ALIGNED_SIZE + size, 1);
+ chunk = calloc(total_size, 1);
if (chunk == NULL) {
pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
errno, "malloc");
#endif /* MSDOS */
#endif /* _WIN32 */
- if (size == 0) {
- /* No private data was requested. */
- p->priv = NULL;
- } else {
- /*
- * Set the pointer to the private data; that's the structure
- * of size "size" following the pcap_t.
- */
- p->priv = (void *)(chunk + PCAP_T_ALIGNED_SIZE);
- }
+ /*
+ * private_offset is the offset, in bytes, of the private
+ * data from the beginning of the structure.
+ *
+ * Set the pointer to the private data; that's private_offset
+ * bytes past the pcap_t.
+ */
+ p->priv = (void *)(chunk + private_offset);
return (p);
}
pcap_t *
-pcap_create_common(char *ebuf, size_t size)
+pcap_create_common(char *ebuf, size_t total_size, size_t private_offset)
{
pcap_t *p;
- p = pcap_alloc_pcap_t(ebuf, size);
+ p = pcap_alloc_pcap_t(ebuf, total_size, private_offset);
if (p == NULL)
return (NULL);
goto fail;
return (p);
fail:
- if (status == PCAP_ERROR)
+ if (status == PCAP_ERROR) {
+ /*
+ * Another buffer is a bit cumbersome, but it avoids
+ * -Wformat-truncation.
+ */
+ char trimbuf[PCAP_ERRBUF_SIZE - 5]; /* 2 bytes shorter */
+
+ pcap_strlcpy(trimbuf, p->errbuf, sizeof(trimbuf));
snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %.*s", device,
- PCAP_ERRBUF_SIZE - 3, p->errbuf);
- else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
+ PCAP_ERRBUF_SIZE - 3, trimbuf);
+ } else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
status == PCAP_ERROR_PERM_DENIED ||
- status == PCAP_ERROR_PROMISC_PERM_DENIED)
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%.*s)", device,
- pcap_statustostr(status), PCAP_ERRBUF_SIZE - 6, p->errbuf);
- else
+ status == PCAP_ERROR_PROMISC_PERM_DENIED) {
+ /*
+ * Only show the additional message if it's not
+ * empty.
+ */
+ if (p->errbuf[0] != '\0') {
+ /*
+ * Idem.
+ */
+ char trimbuf[PCAP_ERRBUF_SIZE - 8]; /* 2 bytes shorter */
+
+ pcap_strlcpy(trimbuf, p->errbuf, sizeof(trimbuf));
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%.*s)",
+ device, pcap_statustostr(status),
+ PCAP_ERRBUF_SIZE - 6, trimbuf);
+ } else {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+ device, pcap_statustostr(status));
+ }
+ } else {
snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
pcap_statustostr(status));
+ }
pcap_close(p);
return (NULL);
}
pcap_t *
-pcap_open_offline_common(char *ebuf, size_t size)
+pcap_open_offline_common(char *ebuf, size_t total_size, size_t private_offset)
{
pcap_t *p;
- p = pcap_alloc_pcap_t(ebuf, size);
+ p = pcap_alloc_pcap_t(ebuf, total_size, private_offset);
if (p == NULL)
return (NULL);
if (description != NULL) {
return description;
} else {
- (void)snprintf(unkbuf, sizeof(unkbuf), "DLT %u", dlt);
+ (void)snprintf(unkbuf, sizeof(unkbuf), "DLT %d", dlt);
return unkbuf;
}
}
/*
* This is a bogus and now-deprecated API; we
* squelch the narrowing warning for the cast
- * from HANDLE to DWORD - Windows programmers
- * should use pcap_handle().
+ * from HANDLE to intptr_t. If Windows programmmers
+ * need to get at the HANDLE for a pcap_t, *if*
+ * there is one, they should request such a
+ * routine (and be prepared for it to return
+ * INVALID_HANDLE_VALUE).
*/
DIAG_OFF_NARROWING
- return ((int)(DWORD)p->handle);
+ return ((int)(intptr_t)p->handle);
DIAG_ON_NARROWING
} else
return (PCAP_ERROR);
return ("That operation is supported only in monitor mode");
case PCAP_ERROR_PERM_DENIED:
- return ("You don't have permission to capture on that device");
+ return ("You don't have permission to perform this capture on that device");
case PCAP_ERROR_IFACE_NOT_UP:
return ("That device is not up");
void
pcap_cleanup_live_common(pcap_t *p)
{
+ if (p->opt.device != NULL) {
+ free(p->opt.device);
+ p->opt.device = NULL;
+ }
if (p->buffer != NULL) {
free(p->buffer);
p->buffer = NULL;
void
pcap_close(pcap_t *p)
{
- if (p->opt.device != NULL)
- free(p->opt.device);
p->cleanup_op(p);
free(p);
}
/*
- * Helpers for safely loding code at run time.
+ * Helpers for safely loading code at run time.
* Currently Windows-only.
*/
#ifdef _WIN32
// C:\Windows\System32) to the relative path of the DLL, so that the DLL
// is always loaded from an absolute path (it's no longer possible to
// load modules from the application folder).
-// This solves the DLL Hijacking issue discovered in August 2010
-// http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
+// This solves the DLL Hijacking issue discovered in August 2010:
+//
+// https://blog.rapid7.com/2010/08/23/exploiting-dll-hijacking-flaws/
+// https://blog.rapid7.com/2010/08/23/application-dll-load-hijacking/
+// (the purported Rapid7 blog post link in the first of those two links
+// is broken; the second of those links works.)
+//
+// If any links there are broken from all the content shuffling Rapid&
+// did, see archived versions of the posts at their original homes, at
+//
+// https://web.archive.org/web/20110122175058/http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
+// https://web.archive.org/web/20100828112111/http://blog.rapid7.com/?p=5325
//
pcap_code_handle_t
pcap_load_code(const char *name)
return (-1);
}
+static void
+pcap_breakloop_dead(pcap_t *p _U_)
+{
+ /*
+ * A "dead" pcap_t is just a placeholder to use in order to
+ * compile a filter to BPF code or to open a savefile for
+ * writing. It doesn't support any operations, including
+ * capturing or reading packets, so there will never be a
+ * get-packets loop in progress to break out *of*.
+ *
+ * As such, this routine doesn't need to do anything.
+ */
+}
+
static int
pcap_inject_dead(pcap_t *p, const void *buf _U_, int size _U_)
{
p->live_dump_ended_op = pcap_live_dump_ended_dead;
p->get_airpcap_handle_op = pcap_get_airpcap_handle_dead;
#endif
+ p->breakloop_op = pcap_breakloop_dead;
p->cleanup_op = pcap_cleanup_dead;
/*