From 71dac45765e9bbb9a2851ee3b1eaecfac6e7a8fd Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Mon, 21 Sep 2009 10:45:09 -0700 Subject: 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. --- pcap.c | 93 ++++++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 34 deletions(-) (limited to 'pcap.c') 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 } -- cgit v1.2.3