]> The Tcpdump Group git mirrors - libpcap/commitdiff
If an activate routine fails, it needs to clean up the pcap_t, close
authorGuy Harris <[email protected]>
Mon, 21 Sep 2009 17:45:09 +0000 (10:45 -0700)
committerGuy Harris <[email protected]>
Mon, 21 Sep 2009 17:45:09 +0000 (10:45 -0700)
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.

pcap-nit.c
pcap-pf.c
pcap-snit.c
pcap-snoop.c
pcap-usb-linux.c
pcap.c

index 4dba11c5aed88a6a1d254a5bae198513e5fcb261..b799549e4eda39eb8e4e349c561d43015873e04c 100644 (file)
@@ -323,6 +323,7 @@ pcap_activate_nit(pcap_t *p)
 
        return (0);
  bad:
+       pcap_cleanup_live_common(p);
        return (PCAP_ERROR);
 }
 
index c258e1a69457b46b26b43d1c938e7094c545ab12..d8326df9ae984821c480870fedcfaa96f1ceaff4 100644 (file)
--- 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);
 }
 
index 2990f7a28b9e75195c7991faa3b48b6bed15d669..fa0c4ef259331444390b25a89e7cc3fc28f37be4 100644 (file)
@@ -402,6 +402,7 @@ pcap_activate_snit(pcap_t *p)
 
        return (0);
  bad:
+       pcap_cleanup_live_common(p);
        return (PCAP_ERROR);
 }
 
index c8259a40a793dc6faaa7bac2c6e5eb2b03a3acc7..330e01d3a92e45f9f4168714b0662ce7519451b0 100644 (file)
@@ -389,6 +389,7 @@ pcap_activate_snoop(pcap_t *p)
 
        return (0);
  bad:
+       pcap_cleanup_live_common(p);
        return (PCAP_ERROR);
 }
 
index ba18277b5c73cd4a4a20660356b280950004341f..bcbe45a83dbc351d4e9f255ff92f8f744421eb8a 100644 (file)
@@ -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 c9b461c46affcacaf7533f688e25b6d5dfa797af..ccf1d706d5f63d0ffbefb1b387ed00a6c2ee06a8 100644 (file)
--- 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
 }