aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2009-09-21 10:45:09 -0700
committerGuy Harris <guy@alum.mit.edu>2009-09-21 10:45:09 -0700
commit71dac45765e9bbb9a2851ee3b1eaecfac6e7a8fd (patch)
tree7a5038d9ece2ca34716e8d1db0c141231f58a699
parent2fbb5a5e315355746f0c863bf4a9757057478561 (diff)
If an activate routine fails, it needs to clean up the pcap_t, close
anything it's opened, etc.. In addition, the op pointers need to be restored to the un-activated state; do that in pcap_activate() if the call to the activate op fails. Also, in the common cleanup code, set the fd's to -1.
-rw-r--r--pcap-nit.c1
-rw-r--r--pcap-pf.c1
-rw-r--r--pcap-snit.c1
-rw-r--r--pcap-snoop.c1
-rw-r--r--pcap-usb-linux.c1
-rw-r--r--pcap.c93
6 files changed, 64 insertions, 34 deletions
diff --git a/pcap-nit.c b/pcap-nit.c
index 4dba11c..b799549 100644
--- a/pcap-nit.c
+++ b/pcap-nit.c
@@ -323,6 +323,7 @@ pcap_activate_nit(pcap_t *p)
return (0);
bad:
+ pcap_cleanup_live_common(p);
return (PCAP_ERROR);
}
diff --git a/pcap-pf.c b/pcap-pf.c
index c258e1a..d8326df 100644
--- a/pcap-pf.c
+++ b/pcap-pf.c
@@ -494,6 +494,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
return (0);
bad:
+ pcap_cleanup_live_common(p);
return (PCAP_ERROR);
}
diff --git a/pcap-snit.c b/pcap-snit.c
index 2990f7a..fa0c4ef 100644
--- a/pcap-snit.c
+++ b/pcap-snit.c
@@ -402,6 +402,7 @@ pcap_activate_snit(pcap_t *p)
return (0);
bad:
+ pcap_cleanup_live_common(p);
return (PCAP_ERROR);
}
diff --git a/pcap-snoop.c b/pcap-snoop.c
index c8259a4..330e01d 100644
--- a/pcap-snoop.c
+++ b/pcap-snoop.c
@@ -389,6 +389,7 @@ pcap_activate_snoop(pcap_t *p)
return (0);
bad:
+ pcap_cleanup_live_common(p);
return (PCAP_ERROR);
}
diff --git a/pcap-usb-linux.c b/pcap-usb-linux.c
index ba18277..bcbe45a 100644
--- a/pcap-usb-linux.c
+++ b/pcap-usb-linux.c
@@ -384,6 +384,7 @@ usb_activate(pcap_t* handle)
if (!handle->buffer) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
+ close(handle->fd);
return PCAP_ERROR;
}
return 0;
diff --git a/pcap.c b/pcap.c
index c9b461c..ccf1d70 100644
--- a/pcap.c
+++ b/pcap.c
@@ -174,6 +174,42 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
return (p->read_op(p, 1, pcap_oneshot, (u_char *)&s));
}
+static void
+initialize_ops(pcap_t *p)
+{
+ /*
+ * Set operation pointers for operations that only work on
+ * an activated pcap_t to point to a routine that returns
+ * a "this isn't activated" error.
+ */
+ p->read_op = (read_op_t)pcap_not_initialized;
+ p->inject_op = (inject_op_t)pcap_not_initialized;
+ p->setfilter_op = (setfilter_op_t)pcap_not_initialized;
+ 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->setbuff_op = (setbuff_op_t)pcap_not_initialized;
+ p->setmode_op = (setmode_op_t)pcap_not_initialized;
+ p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized;
+#endif
+
+ /*
+ * Default cleanup operation - implementations can override
+ * this, but should call pcap_cleanup_live_common() after
+ * doing their own additional cleanup.
+ */
+ p->cleanup_op = pcap_cleanup_live_common;
+
+ /*
+ * In most cases, the standard one-short callback can
+ * be used for pcap_next()/pcap_next_ex().
+ */
+ p->oneshot_callback = pcap_oneshot;
+}
+
pcap_t *
pcap_create_common(const char *source, char *ebuf)
{
@@ -188,6 +224,8 @@ pcap_create_common(const char *source, char *ebuf)
memset(p, 0, sizeof(*p));
#ifndef WIN32
p->fd = -1; /* not opened yet */
+ p->selectable_fd = -1;
+ p->send_fd = -1;
#endif
p->opt.source = strdup(source);
@@ -200,36 +238,13 @@ pcap_create_common(const char *source, char *ebuf)
/*
* Default to "can't set rfmon mode"; if it's supported by
- * a platform, it can set the op to its routine to check
- * whether a particular device supports it.
+ * a platform, the create routine that called us can set
+ * the op to its routine to check whether a particular
+ * device supports it.
*/
p->can_set_rfmon_op = pcap_cant_set_rfmon;
- /*
- * Some operations can be performed only on activated pcap_t's;
- * have those operations handled by a "not supported" handler
- * until the pcap_t is activated.
- */
- p->read_op = (read_op_t)pcap_not_initialized;
- p->inject_op = (inject_op_t)pcap_not_initialized;
- p->setfilter_op = (setfilter_op_t)pcap_not_initialized;
- 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->setbuff_op = (setbuff_op_t)pcap_not_initialized;
- p->setmode_op = (setmode_op_t)pcap_not_initialized;
- p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized;
-#endif
- p->cleanup_op = pcap_cleanup_live_common;
-
- /*
- * In most cases, the standard one-short callback can
- * be used for pcap_next()/pcap_next_ex().
- */
- p->oneshot_callback = pcap_oneshot;
+ initialize_ops(p);
/* put in some defaults*/
pcap_set_timeout(p, 0);
@@ -303,15 +318,23 @@ pcap_activate(pcap_t *p)
status = p->activate_op(p);
if (status >= 0)
p->activated = 1;
- else if (p->errbuf[0] == '\0') {
+ else {
+ if (p->errbuf[0] == '\0') {
+ /*
+ * No error message supplied by the activate routine;
+ * for the benefit of programs that don't specially
+ * handle errors other than PCAP_ERROR, return the
+ * error message corresponding to the status.
+ */
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
+ pcap_statustostr(status));
+ }
+
/*
- * No error message supplied by the activate routine;
- * for the benefit of programs that don't specially
- * handle errors other than PCAP_ERROR, return the
- * error message corresponding to the status.
+ * Undo any operation pointer setting, etc. done by
+ * the activate operation.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
- pcap_statustostr(status));
+ initialize_ops(p);
}
return (status);
}
@@ -1179,6 +1202,8 @@ pcap_cleanup_live_common(pcap_t *p)
close(p->fd);
p->fd = -1;
}
+ p->selectable_fd = -1;
+ p->send_fd = -1;
#endif
}