* blocking mode.
*/
static int
-pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
+pcap_getnonblock_bpf(pcap_t *p)
{
#ifdef HAVE_ZEROCOPY_BPF
struct pcap_bpf *pb = p->priv;
if (pb->zerocopy)
return (pb->nonblock);
#endif
- return (pcap_getnonblock_fd(p, errbuf));
+ return (pcap_getnonblock_fd(p));
}
static int
-pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
+pcap_setnonblock_bpf(pcap_t *p, int nonblock)
{
#ifdef HAVE_ZEROCOPY_BPF
struct pcap_bpf *pb = p->priv;
return (0);
}
#endif
- return (pcap_setnonblock_fd(p, nonblock, errbuf));
+ return (pcap_setnonblock_fd(p, nonblock));
}
#ifdef HAVE_ZEROCOPY_BPF
static int dag_stats(pcap_t *p, struct pcap_stat *ps);
static int dag_set_datalink(pcap_t *p, int dlt);
static int dag_get_datalink(pcap_t *p);
-static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf);
+static int dag_setnonblock(pcap_t *p, int nonblock);
static void
delete_pcap_dag(pcap_t *p)
}
static int
-dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+dag_setnonblock(pcap_t *p, int nonblock)
{
struct pcap_dag *pd = p->priv;
dag_size_t mindata;
* and have a "dag_getnonblock()" function that looks at
* "pd->dag_flags".
*/
- if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0)
+ if (pcap_setnonblock_fd(p, nonblock) < 0)
return (-1);
if (dag_get_stream_poll64(p->fd, pd->dag_stream,
&mindata, &maxwait, &poll) < 0) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s", pcap_strerror(errno));
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s", pcap_strerror(errno));
return -1;
}
if (dag_set_stream_poll64(p->fd, pd->dag_stream,
mindata, &maxwait, &poll) < 0) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s", pcap_strerror(errno));
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s", pcap_strerror(errno));
return -1;
}
handle->getnonblock_op = pcap_getnonblock_fd;
handle->setnonblock_op = pcap_setnonblock_fd;
handle->stats_op = dbus_stats;
+ handle->cleanup_op = dbus_cleanup;
handle->selectable_fd = handle->fd = -1;
if (!init_watt32(pcap, pcap->opt.device, pcap->errbuf) ||
!first_init(pcap->opt.device, pcap->errbuf, pcap->opt.promisc))
{
+ /* XXX - free pcap->buffer? */
return (PCAP_ERROR);
}
atexit (close_driver);
pcap_snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
"Cannot use different devices simultaneously "
"(`%s' vs. `%s')", active_dev->name, pcap->opt.device);
+ /* XXX - free pcap->buffer? */
return (PCAP_ERROR);
}
handle_to_device [pcap->fd-1] = active_dev;
return;
}
close_driver();
+ /* XXX - call pcap_cleanup_live_common? */
}
/*
int promisc;
int rfmon; /* monitor mode */
int immediate; /* immediate mode - deliver packets as soon as they arrive */
+ int nonblock; /* non-blocking mode - don't wait for packets to be delivered, return "no packets available" */
int tstamp_type;
int tstamp_precision;
};
typedef int (*setfilter_op_t)(pcap_t *, struct bpf_program *);
typedef int (*setdirection_op_t)(pcap_t *, pcap_direction_t);
typedef int (*set_datalink_op_t)(pcap_t *, int);
-typedef int (*getnonblock_op_t)(pcap_t *, char *);
-typedef int (*setnonblock_op_t)(pcap_t *, int, char *);
+typedef int (*getnonblock_op_t)(pcap_t *);
+typedef int (*setnonblock_op_t)(pcap_t *, int);
typedef int (*stats_op_t)(pcap_t *, struct pcap_stat *);
#ifdef _WIN32
typedef struct pcap_stat *(*stats_ex_op_t)(pcap_t *, int *);
* Routines that most pcap implementations can use for non-blocking mode.
*/
#if !defined(_WIN32) && !defined(MSDOS)
-int pcap_getnonblock_fd(pcap_t *, char *);
-int pcap_setnonblock_fd(pcap_t *p, int, char *);
+int pcap_getnonblock_fd(pcap_t *);
+int pcap_setnonblock_fd(pcap_t *p, int);
#endif
/*
static int pcap_read_linux_mmap_v3(pcap_t *, int, pcap_handler , u_char *);
#endif
static int pcap_setfilter_linux_mmap(pcap_t *, struct bpf_program *);
-static int pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf);
-static int pcap_getnonblock_mmap(pcap_t *p, char *errbuf);
+static int pcap_setnonblock_mmap(pcap_t *p, int nonblock);
+static int pcap_getnonblock_mmap(pcap_t *p);
static void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
const u_char *bytes);
#endif
static int
-pcap_getnonblock_mmap(pcap_t *p, char *errbuf)
+pcap_getnonblock_mmap(pcap_t *p)
{
struct pcap_linux *handlep = p->priv;
}
static int
-pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf)
+pcap_setnonblock_mmap(pcap_t *p, int nonblock)
{
struct pcap_linux *handlep = p->priv;
* Set the file descriptor to non-blocking mode, as we use
* it for sending packets.
*/
- if (pcap_setnonblock_fd(p, nonblock, errbuf) == -1)
+ if (pcap_setnonblock_fd(p, nonblock) == -1)
return -1;
/*
static int septel_setfilter(pcap_t *p, struct bpf_program *fp);
static int septel_stats(pcap_t *p, struct pcap_stat *ps);
-static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf);
+static int septel_setnonblock(pcap_t *p, int nonblock);
/*
* Private data for capturing on Septel devices.
return NULL;
p->activate_op = septel_activate;
+ p->setnonblock_op = septel_setnonblock; /* not supported */
return p;
}
static int
-septel_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+septel_setnonblock(pcap_t *p, int nonblock)
{
- fprintf(errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
+ fprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
return (-1);
}
}
static int
-snf_getnonblock(pcap_t *p, char *errbuf)
+snf_getnonblock(pcap_t *p)
{
struct pcap_snf *ps = p->priv;
}
static int
-snf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+snf_setnonblock(pcap_t *p, int nonblock)
{
struct pcap_snf *ps = p->priv;
static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port);
static int TcSetDatalink(pcap_t *p, int dlt);
-static int TcGetNonBlock(pcap_t *p, char *errbuf);
-static int TcSetNonBlock(pcap_t *p, int nonblock, char *errbuf);
+static int TcGetNonBlock(pcap_t *p);
+static int TcSetNonBlock(pcap_t *p, int nonblock);
static void TcCleanup(pcap_t *p);
static int TcInject(pcap_t *p, const void *buf, size_t size);
static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
return NULL;
p->activate_op = TcActivate;
+ p->setnonblock_op = TcSetNonBlock; /* not supported */
return p;
}
return 0;
}
-static int TcGetNonBlock(pcap_t *p, char *errbuf)
+static int TcGetNonBlock(pcap_t *p)
{
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Getting the non blocking status is not available for TurboCap ports");
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "Getting the non blocking status is not available for TurboCap ports");
return -1;
}
-static int TcSetNonBlock(pcap_t *p, int nonblock, char *errbuf)
+static int TcSetNonBlock(pcap_t *p, int nonblock)
{
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Setting the non blocking status is not available for TurboCap ports");
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "Setting the non blocking status is not available for TurboCap ports");
return -1;
}
static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
-static int pcap_getnonblock_win32(pcap_t *, char *);
-static int pcap_setnonblock_win32(pcap_t *, int, char *);
+static int pcap_getnonblock_win32(pcap_t *);
+static int pcap_setnonblock_win32(pcap_t *, int);
/*dimension of the buffer in the pcap_t structure*/
#define WIN32_DEFAULT_USER_BUFFER_SIZE 256000
}
static int
-pcap_getnonblock_win32(pcap_t *p, char *errbuf)
+pcap_getnonblock_win32(pcap_t *p)
{
struct pcap_win *pw = p->priv;
}
static int
-pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
+pcap_setnonblock_win32(pcap_t *p, int nonblock)
{
struct pcap_win *pw = p->priv;
int newtimeout;
}
if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
pcap_win32_err_to_str(GetLastError(), win_errbuf);
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"PacketSetReadTimeout: %s", win_errbuf);
return (-1);
}
return (p);
}
+/*
+ * Set nonblocking mode on an unactivated pcap_t; this sets a flag
+ * checked by pcap_activate(), which sets the mode after calling
+ * the activate routine.
+ */
+static int
+pcap_setnonblock_unactivated(pcap_t *p, int nonblock)
+{
+ p->opt.nonblock = nonblock;
+ return (0);
+}
+
static void
initialize_ops(pcap_t *p)
{
p->setdirection_op = (setdirection_op_t)pcap_not_initialized;
p->set_datalink_op = (set_datalink_op_t)pcap_not_initialized;
p->getnonblock_op = (getnonblock_op_t)pcap_not_initialized;
- p->setnonblock_op = (setnonblock_op_t)pcap_not_initialized;
p->stats_op = (stats_op_t)pcap_not_initialized;
#ifdef _WIN32
p->stats_ex_op = (stats_ex_op_t)pcap_not_initialized_ptr;
*/
p->can_set_rfmon_op = pcap_cant_set_rfmon;
+ /*
+ * If pcap_setnonblock() is called on a not-yet-activated
+ * pcap_t, default to setting a flag and turning
+ * on non-blocking mode when activated.
+ */
+ p->setnonblock_op = pcap_setnonblock_unactivated;
+
initialize_ops(p);
/* put in some defaults*/
if (pcap_check_activated(p))
return (PCAP_ERROR_ACTIVATED);
status = p->activate_op(p);
- if (status >= 0)
+ if (status >= 0) {
+ /*
+ * If somebody requested non-blocking mode before
+ * calling pcap_activate(), turn it on now.
+ */
+ if (p->opt.nonblock) {
+ status = p->setnonblock_op(p, 1);
+ if (status < 0) {
+ /*
+ * Failed. Undo everything done by
+ * the activate operation.
+ */
+ p->cleanup_op(p);
+ initialize_ops(p);
+ return (status);
+ }
+ }
p->activated = 1;
- else {
+ } else {
if (p->errbuf[0] == '\0') {
/*
* No error message supplied by the activate routine;
{
int ret;
- ret = p->getnonblock_op(p, errbuf);
+ ret = p->getnonblock_op(p);
if (ret == -1) {
/*
- * In case somebody depended on the bug wherein
- * the error message was put into p->errbuf
- * by pcap_getnonblock_fd().
+ * The get nonblock operation sets p->errbuf; this
+ * function *shouldn't* have had a separate errbuf
+ * argument, as it didn't need one, but I goofed
+ * when adding it.
+ *
+ * We copy the error message to errbuf, so callers
+ * can find it in either place.
*/
- strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
+ strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
}
return (ret);
}
*/
#if !defined(_WIN32) && !defined(MSDOS)
int
-pcap_getnonblock_fd(pcap_t *p, char *errbuf)
+pcap_getnonblock_fd(pcap_t *p)
{
int fdflags;
fdflags = fcntl(p->fd, F_GETFL, 0);
if (fdflags == -1) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
pcap_strerror(errno));
return (-1);
}
{
int ret;
- ret = p->setnonblock_op(p, nonblock, errbuf);
+ ret = p->setnonblock_op(p, nonblock);
if (ret == -1) {
/*
- * In case somebody depended on the bug wherein
- * the error message was put into p->errbuf
- * by pcap_setnonblock_fd().
+ * The set nonblock operation sets p->errbuf; this
+ * function *shouldn't* have had a separate errbuf
+ * argument, as it didn't need one, but I goofed
+ * when adding it.
+ *
+ * We copy the error message to errbuf, so callers
+ * can find it in either place.
*/
- strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
+ strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
}
return (ret);
}
* needs to do some additional work.)
*/
int
-pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
+pcap_setnonblock_fd(pcap_t *p, int nonblock)
{
int fdflags;
fdflags = fcntl(p->fd, F_GETFL, 0);
if (fdflags == -1) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
pcap_strerror(errno));
return (-1);
}
else
fdflags &= ~O_NONBLOCK;
if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
pcap_strerror(errno));
return (-1);
}
#endif
static int
-sf_getnonblock(pcap_t *p, char *errbuf)
+sf_getnonblock(pcap_t *p)
{
/*
* This is a savefile, not a live capture file, so never say
}
static int
-sf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+sf_setnonblock(pcap_t *p, int nonblock)
{
/*
* This is a savefile, not a live capture file, so reject