mirror of
https://github.com/nmap/nmap.git
synced 2025-12-27 18:09:01 +00:00
Update libpcap to 1.9.0 (no patches applied yet)
This commit is contained in:
@@ -28,27 +28,14 @@
|
||||
* dependent values so we can print the dump file on any architecture.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header$ (LBL)";
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <pcap-types.h>
|
||||
#ifdef _WIN32
|
||||
#include <pcap-stdinc.h>
|
||||
#else /* _WIN32 */
|
||||
#if HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#elif HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_BITYPES_H
|
||||
#include <sys/bitypes.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include <errno.h>
|
||||
@@ -185,9 +172,8 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
|
||||
sizeof(hdr) - sizeof(hdr.magic), fp);
|
||||
if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
|
||||
if (ferror(fp)) {
|
||||
pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"error reading dump file: %s",
|
||||
pcap_strerror(errno));
|
||||
pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
|
||||
errno, "error reading dump file");
|
||||
} else {
|
||||
pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"truncated dump file; tried to read %lu file header bytes, only got %lu",
|
||||
@@ -232,14 +218,6 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hdr.snaplen > MAXIMUM_SNAPLEN) {
|
||||
pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"invalid file capture length %u, bigger than "
|
||||
"maximum of %u", hdr.snaplen, MAXIMUM_SNAPLEN);
|
||||
*err = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, this is a good pcap file.
|
||||
* Allocate a pcap_t for it.
|
||||
@@ -255,6 +233,17 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
|
||||
p->version_minor = hdr.version_minor;
|
||||
p->tzoff = hdr.thiszone;
|
||||
p->snapshot = hdr.snaplen;
|
||||
if (p->snapshot <= 0) {
|
||||
/*
|
||||
* Bogus snapshot length; use the maximum for this
|
||||
* link-layer type as a fallback.
|
||||
*
|
||||
* XXX - the only reason why snapshot is signed is
|
||||
* that pcap_snapshot() returns an int, not an
|
||||
* unsigned int.
|
||||
*/
|
||||
p->snapshot = max_snaplen_for_dlt(hdr.linktype);
|
||||
}
|
||||
p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
|
||||
p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
|
||||
|
||||
@@ -390,14 +379,16 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
|
||||
|
||||
/*
|
||||
* Allocate a buffer for the packet data.
|
||||
* Choose the minimum of the file's snapshot length and 2K bytes;
|
||||
* that should be enough for most network packets - we'll grow it
|
||||
* if necessary. That way, we don't allocate a huge chunk of
|
||||
* memory just because there's a huge snapshot length, as the
|
||||
* snapshot length might be larger than the size of the largest
|
||||
* packet.
|
||||
*/
|
||||
p->bufsize = p->snapshot;
|
||||
if (p->bufsize <= 0) {
|
||||
/*
|
||||
* Bogus snapshot length; use the maximum as a fallback.
|
||||
*/
|
||||
p->bufsize = MAXIMUM_SNAPLEN;
|
||||
}
|
||||
if (p->bufsize > 2048)
|
||||
p->bufsize = 2048;
|
||||
p->buffer = malloc(p->bufsize);
|
||||
if (p->buffer == NULL) {
|
||||
pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
|
||||
@@ -411,6 +402,24 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Grow the packet buffer to the specified size.
|
||||
*/
|
||||
static int
|
||||
grow_buffer(pcap_t *p, u_int bufsize)
|
||||
{
|
||||
void *bigger_buffer;
|
||||
|
||||
bigger_buffer = realloc(p->buffer, bufsize);
|
||||
if (bigger_buffer == NULL) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "out of memory");
|
||||
return (0);
|
||||
}
|
||||
p->buffer = bigger_buffer;
|
||||
p->bufsize = bufsize;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read and return the next packet from the savefile. Return the header
|
||||
* in hdr and a pointer to the contents in data. Return 0 on success, 1
|
||||
@@ -435,9 +444,8 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
|
||||
if (amt_read != ps->hdrsize) {
|
||||
if (ferror(fp)) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"error reading dump file: %s",
|
||||
pcap_strerror(errno));
|
||||
pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
errno, "error reading dump file");
|
||||
return (-1);
|
||||
} else {
|
||||
if (amt_read != 0) {
|
||||
@@ -513,41 +521,87 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
break;
|
||||
}
|
||||
|
||||
if (hdr->caplen > p->bufsize) {
|
||||
/*
|
||||
* Is the packet bigger than we consider sane?
|
||||
*/
|
||||
if (hdr->caplen > max_snaplen_for_dlt(p->linktype)) {
|
||||
/*
|
||||
* Yes. This may be a damaged or fuzzed file.
|
||||
*
|
||||
* Is it bigger than the snapshot length?
|
||||
* (We don't treat that as an error if it's not
|
||||
* bigger than the maximum we consider sane; see
|
||||
* below.)
|
||||
*/
|
||||
if (hdr->caplen > (bpf_u_int32)p->snapshot) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"invalid packet capture length %u, bigger than "
|
||||
"snaplen of %d", hdr->caplen, p->snapshot);
|
||||
} else {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"invalid packet capture length %u, bigger than "
|
||||
"maximum of %u", hdr->caplen,
|
||||
max_snaplen_for_dlt(p->linktype));
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (hdr->caplen > (bpf_u_int32)p->snapshot) {
|
||||
/*
|
||||
* The packet is bigger than the snapshot length
|
||||
* for this file.
|
||||
*
|
||||
* This can happen due to Solaris 2.3 systems tripping
|
||||
* over the BUFMOD problem and not setting the snapshot
|
||||
* correctly in the savefile header.
|
||||
* This can also happen with a corrupted savefile or a
|
||||
* savefile built/modified by a fuzz tester.
|
||||
* If the caplen isn't grossly wrong, try to salvage.
|
||||
* length correctly in the savefile header.
|
||||
*
|
||||
* libpcap 0.4 and later on Solaris 2.3 should set the
|
||||
* snapshot length correctly in the pcap file header,
|
||||
* even though they don't set a snapshot length in bufmod
|
||||
* (the buggy bufmod chops off the *beginning* of the
|
||||
* packet if a snapshot length is specified); they should
|
||||
* also reduce the captured length, as supplied to the
|
||||
* per-packet callback, to the snapshot length if it's
|
||||
* greater than the snapshot length, so the code using
|
||||
* libpcap should see the packet cut off at the snapshot
|
||||
* length, even though the full packet is copied up to
|
||||
* userland.
|
||||
*
|
||||
* However, perhaps some versions of libpcap failed to
|
||||
* set the snapshot length currectly in the file header
|
||||
* or the per-packet header, or perhaps this is a
|
||||
* corrupted safefile or a savefile built/modified by a
|
||||
* fuzz tester, so we check anyway. We grow the buffer
|
||||
* to be big enough for the snapshot length, read up
|
||||
* to the snapshot length, discard the rest of the
|
||||
* packet, and report the snapshot length as the captured
|
||||
* length; we don't want to hand our caller a packet
|
||||
* bigger than the snapshot length, because they might
|
||||
* be assuming they'll never be handed such a packet,
|
||||
* and might copy the packet into a snapshot-length-
|
||||
* sized buffer, assuming it'll fit.
|
||||
*/
|
||||
size_t bytes_to_discard;
|
||||
size_t bytes_to_read, bytes_read;
|
||||
char discard_buf[4096];
|
||||
|
||||
if (hdr->caplen > MAXIMUM_SNAPLEN) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"invalid packet capture length %u, bigger than "
|
||||
"maximum of %u", hdr->caplen, MAXIMUM_SNAPLEN);
|
||||
return (-1);
|
||||
if (hdr->caplen > p->bufsize) {
|
||||
/*
|
||||
* Grow the buffer to the snapshot length.
|
||||
*/
|
||||
if (!grow_buffer(p, p->snapshot))
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX - we don't grow the buffer here because some
|
||||
* program might assume that it will never get packets
|
||||
* bigger than the snapshot length; for example, it might
|
||||
* copy data from our buffer to a buffer of its own,
|
||||
* allocated based on the return value of pcap_snapshot().
|
||||
*
|
||||
* Read the first p->bufsize bytes into the buffer.
|
||||
* Read the first p->snapshot bytes into the buffer.
|
||||
*/
|
||||
amt_read = fread(p->buffer, 1, p->bufsize, fp);
|
||||
if (amt_read != p->bufsize) {
|
||||
amt_read = fread(p->buffer, 1, p->snapshot, fp);
|
||||
if (amt_read != (bpf_u_int32)p->snapshot) {
|
||||
if (ferror(fp)) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"error reading dump file: %s",
|
||||
pcap_strerror(errno));
|
||||
pcap_fmt_errmsg_for_errno(p->errbuf,
|
||||
PCAP_ERRBUF_SIZE, errno,
|
||||
"error reading dump file");
|
||||
} else {
|
||||
/*
|
||||
* Yes, this uses hdr->caplen; technically,
|
||||
@@ -558,7 +612,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
*/
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"truncated dump file; tried to read %u captured bytes, only got %lu",
|
||||
hdr->caplen, (unsigned long)amt_read);
|
||||
p->snapshot, (unsigned long)amt_read);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
@@ -566,7 +620,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
/*
|
||||
* Now read and discard what's left.
|
||||
*/
|
||||
bytes_to_discard = hdr->caplen - p->bufsize;
|
||||
bytes_to_discard = hdr->caplen - p->snapshot;
|
||||
bytes_read = amt_read;
|
||||
while (bytes_to_discard != 0) {
|
||||
bytes_to_read = bytes_to_discard;
|
||||
@@ -576,9 +630,9 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
bytes_read += amt_read;
|
||||
if (amt_read != bytes_to_read) {
|
||||
if (ferror(fp)) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"error reading dump file: %s",
|
||||
pcap_strerror(errno));
|
||||
pcap_fmt_errmsg_for_errno(p->errbuf,
|
||||
PCAP_ERRBUF_SIZE, errno,
|
||||
"error reading dump file");
|
||||
} else {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"truncated dump file; tried to read %u captured bytes, only got %lu",
|
||||
@@ -593,15 +647,41 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
|
||||
* Adjust caplen accordingly, so we don't get confused later
|
||||
* as to how many bytes we have to play with.
|
||||
*/
|
||||
hdr->caplen = p->bufsize;
|
||||
hdr->caplen = p->snapshot;
|
||||
} else {
|
||||
if (hdr->caplen > p->bufsize) {
|
||||
/*
|
||||
* Grow the buffer to the next power of 2, or
|
||||
* the snaplen, whichever is lower.
|
||||
*/
|
||||
u_int new_bufsize;
|
||||
|
||||
new_bufsize = hdr->caplen;
|
||||
/*
|
||||
* http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
|
||||
*/
|
||||
new_bufsize--;
|
||||
new_bufsize |= new_bufsize >> 1;
|
||||
new_bufsize |= new_bufsize >> 2;
|
||||
new_bufsize |= new_bufsize >> 4;
|
||||
new_bufsize |= new_bufsize >> 8;
|
||||
new_bufsize |= new_bufsize >> 16;
|
||||
new_bufsize++;
|
||||
|
||||
if (new_bufsize > (u_int)p->snapshot)
|
||||
new_bufsize = p->snapshot;
|
||||
|
||||
if (!grow_buffer(p, new_bufsize))
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* read the packet itself */
|
||||
amt_read = fread(p->buffer, 1, hdr->caplen, fp);
|
||||
if (amt_read != hdr->caplen) {
|
||||
if (ferror(fp)) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"error reading dump file: %s",
|
||||
pcap_strerror(errno));
|
||||
pcap_fmt_errmsg_for_errno(p->errbuf,
|
||||
PCAP_ERRBUF_SIZE, errno,
|
||||
"error reading dump file");
|
||||
} else {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
"truncated dump file; tried to read %u captured bytes, only got %lu",
|
||||
@@ -672,11 +752,11 @@ pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
|
||||
if (f == stdout)
|
||||
SET_BINMODE(f);
|
||||
else
|
||||
setbuf(f, NULL);
|
||||
setvbuf(f, NULL, _IONBF, 0);
|
||||
#endif
|
||||
if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
|
||||
fname, pcap_strerror(errno));
|
||||
pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
errno, "Can't write to %s", fname);
|
||||
if (f != stdout)
|
||||
(void)fclose(f);
|
||||
return (NULL);
|
||||
@@ -721,14 +801,16 @@ pcap_dump_open(pcap_t *p, const char *fname)
|
||||
f = stdout;
|
||||
fname = "standard output";
|
||||
} else {
|
||||
#if !defined(_WIN32) && !defined(MSDOS)
|
||||
f = fopen(fname, "w");
|
||||
#else
|
||||
/*
|
||||
* "b" is supported as of C90, so *all* UN*Xes should
|
||||
* support it, even though it does nothing. It's
|
||||
* required on Windows, as the file is a binary file
|
||||
* and must be written in binary mode.
|
||||
*/
|
||||
f = fopen(fname, "wb");
|
||||
#endif
|
||||
if (f == NULL) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
|
||||
fname, pcap_strerror(errno));
|
||||
pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
errno, "%s", fname);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
@@ -779,14 +861,15 @@ pcap_dump_open_append(pcap_t *p, const char *fname)
|
||||
if (fname[0] == '-' && fname[1] == '\0')
|
||||
return (pcap_setup_dump(p, linktype, stdout, "standard output"));
|
||||
|
||||
#if !defined(_WIN32) && !defined(MSDOS)
|
||||
f = fopen(fname, "r+");
|
||||
#else
|
||||
/*
|
||||
* "b" is supported as of C90, so *all* UN*Xes should support it,
|
||||
* even though it does nothing. It's required on Windows, as the
|
||||
* file is a binary file and must be read in binary mode.
|
||||
*/
|
||||
f = fopen(fname, "rb+");
|
||||
#endif
|
||||
if (f == NULL) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
|
||||
fname, pcap_strerror(errno));
|
||||
pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
errno, "%s", fname);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -796,8 +879,8 @@ pcap_dump_open_append(pcap_t *p, const char *fname)
|
||||
amt_read = fread(&ph, 1, sizeof (ph), f);
|
||||
if (amt_read != sizeof (ph)) {
|
||||
if (ferror(f)) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
|
||||
fname, pcap_strerror(errno));
|
||||
pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
errno, "%s", fname);
|
||||
fclose(f);
|
||||
return (NULL);
|
||||
} else if (feof(f) && amt_read > 0) {
|
||||
@@ -813,7 +896,7 @@ pcap_dump_open_append(pcap_t *p, const char *fname)
|
||||
* We turn off buffering.
|
||||
* XXX - why? And why not on the standard output?
|
||||
*/
|
||||
setbuf(f, NULL);
|
||||
setvbuf(f, NULL, _IONBF, 0);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -904,8 +987,8 @@ pcap_dump_open_append(pcap_t *p, const char *fname)
|
||||
* A header isn't present; attempt to write it.
|
||||
*/
|
||||
if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
|
||||
fname, pcap_strerror(errno));
|
||||
pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
errno, "Can't write to %s", fname);
|
||||
(void)fclose(f);
|
||||
return (NULL);
|
||||
}
|
||||
@@ -915,8 +998,8 @@ pcap_dump_open_append(pcap_t *p, const char *fname)
|
||||
* Start writing at the end of the file.
|
||||
*/
|
||||
if (fseek(f, 0, SEEK_END) == -1) {
|
||||
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't seek to end of %s: %s",
|
||||
fname, pcap_strerror(errno));
|
||||
pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
errno, "Can't seek to end of %s", fname);
|
||||
(void)fclose(f);
|
||||
return (NULL);
|
||||
}
|
||||
@@ -935,6 +1018,45 @@ pcap_dump_ftell(pcap_dumper_t *p)
|
||||
return (ftell((FILE *)p));
|
||||
}
|
||||
|
||||
#if defined(HAVE_FSEEKO)
|
||||
/*
|
||||
* We have fseeko(), so we have ftello().
|
||||
* If we have large file support (files larger than 2^31-1 bytes),
|
||||
* ftello() will give us a current file position with more than 32
|
||||
* bits.
|
||||
*/
|
||||
int64_t
|
||||
pcap_dump_ftell64(pcap_dumper_t *p)
|
||||
{
|
||||
return (ftello((FILE *)p));
|
||||
}
|
||||
#elif defined(_MSC_VER)
|
||||
/*
|
||||
* We have Visual Studio; we support only 2005 and later, so we have
|
||||
* _ftelli64().
|
||||
*/
|
||||
int64_t
|
||||
pcap_dump_ftell64(pcap_dumper_t *p)
|
||||
{
|
||||
return (_ftelli64((FILE *)p));
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* We don't have ftello() or _ftelli64(), so fall back on ftell().
|
||||
* Either long is 64 bits, in which case ftell() should suffice,
|
||||
* or this is probably an older 32-bit UN*X without large file
|
||||
* support, which means you'll probably get errors trying to
|
||||
* write files > 2^31-1, so it won't matter anyway.
|
||||
*
|
||||
* XXX - what about MinGW?
|
||||
*/
|
||||
int64_t
|
||||
pcap_dump_ftell64(pcap_dumper_t *p)
|
||||
{
|
||||
return (ftell((FILE *)p));
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
pcap_dump_flush(pcap_dumper_t *p)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user