diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/filter.c | 24 | ||||
-rw-r--r-- | lib/if.c | 6 | ||||
-rw-r--r-- | lib/log.c | 8 | ||||
-rw-r--r-- | lib/log.h | 1 | ||||
-rw-r--r-- | lib/memtypes.c | 1 | ||||
-rw-r--r-- | lib/pthread_safe.c | 124 | ||||
-rw-r--r-- | lib/pthread_safe.h | 32 | ||||
-rw-r--r-- | lib/qlib_init.c | 3 | ||||
-rw-r--r-- | lib/sockunion.c | 4 |
10 files changed, 180 insertions, 27 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 7d97bfcb..9f21a377 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,7 +14,7 @@ libzebra_la_SOURCES = \ zclient.c sockopt.c smux.c md5.c if_rmap.c keychain.c privs.c \ sigevent.c pqueue.c jhash.c memtypes.c workqueue.c symtab.c heap.c \ qtime.c qpthreads.c mqueue.c qpselect.c qtimers.c qpnexus.c \ - command_queue.c qlib_init.c + command_queue.c qlib_init.c pthread_safe.c BUILT_SOURCES = memtypes.h route_types.h @@ -32,7 +32,7 @@ pkginclude_HEADERS = \ workqueue.h route_types.h symtab.h heap.h \ qtime.h qpthreads.h mqueue.h qpselect.h qtimers.h qpnexus.h \ command_queue.h qlib_init.h qafi_safi.h \ - confirm.h miyagi.h + confirm.h miyagi.h pthread_safe.h EXTRA_DIST = regex.c regex-gnu.h memtypes.awk route_types.awk route_types.txt diff --git a/lib/filter.c b/lib/filter.c index 57109854..a607cb4e 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -1620,9 +1620,9 @@ filter_show (struct vty *vty, const char *name, afi_t afi) vty_out (vty, " any%s", VTY_NEWLINE); else { - vty_out (vty, " %s", inet_ntoa (filter->addr)); + vty_out (vty, " %s", safe_inet_ntoa (filter->addr)); if (filter->addr_mask.s_addr != 0) - vty_out (vty, ", wildcard bits %s", inet_ntoa (filter->addr_mask)); + vty_out (vty, ", wildcard bits %s", safe_inet_ntoa (filter->addr_mask)); vty_out (vty, "%s", VTY_NEWLINE); } } @@ -1663,9 +1663,9 @@ filter_show (struct vty *vty, const char *name, afi_t afi) vty_out (vty, " any%s", VTY_NEWLINE); else { - vty_out (vty, " %s", inet_ntoa (filter->addr)); + vty_out (vty, " %s", safe_inet_ntoa (filter->addr)); if (filter->addr_mask.s_addr != 0) - vty_out (vty, ", wildcard bits %s", inet_ntoa (filter->addr_mask)); + vty_out (vty, ", wildcard bits %s", safe_inet_ntoa (filter->addr_mask)); vty_out (vty, "%s", VTY_NEWLINE); } } @@ -1735,21 +1735,21 @@ config_write_access_cisco (struct vty *vty, struct filter *mfilter) if (filter->addr_mask.s_addr == 0xffffffff) vty_out (vty, " any"); else if (filter->addr_mask.s_addr == 0) - vty_out (vty, " host %s", inet_ntoa (filter->addr)); + vty_out (vty, " host %s", safe_inet_ntoa (filter->addr)); else { - vty_out (vty, " %s", inet_ntoa (filter->addr)); - vty_out (vty, " %s", inet_ntoa (filter->addr_mask)); + vty_out (vty, " %s", safe_inet_ntoa (filter->addr)); + vty_out (vty, " %s", safe_inet_ntoa (filter->addr_mask)); } if (filter->mask_mask.s_addr == 0xffffffff) vty_out (vty, " any"); else if (filter->mask_mask.s_addr == 0) - vty_out (vty, " host %s", inet_ntoa (filter->mask)); + vty_out (vty, " host %s", safe_inet_ntoa (filter->mask)); else { - vty_out (vty, " %s", inet_ntoa (filter->mask)); - vty_out (vty, " %s", inet_ntoa (filter->mask_mask)); + vty_out (vty, " %s", safe_inet_ntoa (filter->mask)); + vty_out (vty, " %s", safe_inet_ntoa (filter->mask_mask)); } vty_out (vty, "%s", VTY_NEWLINE); } @@ -1759,9 +1759,9 @@ config_write_access_cisco (struct vty *vty, struct filter *mfilter) vty_out (vty, " any%s", VTY_NEWLINE); else { - vty_out (vty, " %s", inet_ntoa (filter->addr)); + vty_out (vty, " %s", safe_inet_ntoa (filter->addr)); if (filter->addr_mask.s_addr != 0) - vty_out (vty, " %s", inet_ntoa (filter->addr_mask)); + vty_out (vty, " %s", safe_inet_ntoa (filter->addr_mask)); vty_out (vty, "%s", VTY_NEWLINE); } } @@ -611,7 +611,7 @@ DEFUN (show_address, p = ifc->address; if (p->family == AF_INET) - vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen, + vty_out (vty, "%s/%d%s", safe_inet_ntoa (p->u.prefix4), p->prefixlen, VTY_NEWLINE); } } @@ -807,7 +807,7 @@ ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp) { route_unlock_node (rn); zlog_info ("ifaddr_ipv4_add(): address %s is already added", - inet_ntoa (*ifaddr)); + safe_inet_ntoa (*ifaddr)); return; } rn->info = ifp; @@ -827,7 +827,7 @@ ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp) if (! rn) { zlog_info ("ifaddr_ipv4_delete(): can't find address %s", - inet_ntoa (*ifaddr)); + safe_inet_ntoa (*ifaddr)); return; } rn->info = NULL; @@ -1235,14 +1235,6 @@ mes_lookup (const struct message *meslist, int max, int index, const char *none) return none; } -/* Wrapper around strerror to handle case where it returns NULL. */ -const char * -safe_strerror(int errnum) -{ - const char *s = strerror(errnum); - return (s != NULL) ? s : "Unknown error"; -} - struct zebra_desc_table { unsigned int type; @@ -26,6 +26,7 @@ #define _ZEBRA_LOG_H #include <syslog.h> +#include "pthread_safe.h" /* Here is some guidance on logging levels to use: * diff --git a/lib/memtypes.c b/lib/memtypes.c index f8f541de..2f2ac239 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -42,6 +42,7 @@ struct memory_list memory_list_lib[] = { MTYPE_QTIMER, "qtimer timer" }, { MTYPE_QPN_NEXUS, "qtn nexus" }, { MTYPE_MARSHAL, "marshalled commands" }, + { MTYPE_TSD, "Thread specific data" }, { MTYPE_VTY, "VTY" }, { MTYPE_VTY_OUT_BUF, "VTY output buffer" }, { MTYPE_VTY_HIST, "VTY history" }, diff --git a/lib/pthread_safe.c b/lib/pthread_safe.c new file mode 100644 index 00000000..a8da3a71 --- /dev/null +++ b/lib/pthread_safe.c @@ -0,0 +1,124 @@ +/* Quagga Pthreads support -- thread safe versions of standard functions + * Copyright (C) 2009 Chris Hall (GMCH), Highwayman + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* We use thread specific storeage to provide buufers for the _r versions + * of standard functions, so that the callers don't need to provide + * their own. The contents of a buffer will remain intact until another + * safe_ function is called on the same thread + */ + +#include "pthread_safe.h" +#include "qpthreads.h" +#include "memory.h" + +#include <pthread.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + + +/* prototypes */ +static void destructor(void* data); +static char * thread_buff(void); + +static pthread_key_t tsd_key; +static const int buff_size = 1024; + +/* Module initialization, before any threads have been created */ +void +safe_init_r(void) +{ + if (qpthreads_enabled) + { + int status; + status = pthread_key_create(&tsd_key, destructor); + if (status != 0) + zabort("Can't create thread specific data key"); + } +} + +/* Clean up */ +void +safe_finish(void) +{ + if (qpthreads_enabled) + pthread_key_delete(tsd_key); +} + +static void +destructor(void* data) +{ + XFREE(MTYPE_TSD, data); +} + +/* Thread safe version of strerror. Never returns NULL. + * Contents of result remains intact until another call of + * a safe_ function. + */ +const char * +safe_strerror(int errnum) +{ + static const char * unknown = "Unknown error"; + if (qpthreads_enabled) + { + char * buff = thread_buff(); + int ret = strerror_r(errnum, buff, buff_size); + + return (ret >= 0) + ? buff + : unknown; + } + else + { + const char *s = strerror(errnum); + return (s != NULL) + ? s + : unknown; + } +} + +const char * +safe_inet_ntoa (struct in_addr in) +{ + if (qpthreads_enabled) + return inet_ntop(AF_INET, &in, thread_buff(), buff_size); + else + return inet_ntoa(in); +} + +/* Return the thread's buffer */ +static char * +thread_buff(void) +{ + int ret; + char * buff = pthread_getspecific(tsd_key); + if (buff == NULL) + { + buff = XMALLOC(MTYPE_TSD, buff_size); + ret = pthread_setspecific(tsd_key, buff); + if (ret != 0) + zabort("Can't set thread specific data"); + } + + return buff; +} diff --git a/lib/pthread_safe.h b/lib/pthread_safe.h new file mode 100644 index 00000000..81adc668 --- /dev/null +++ b/lib/pthread_safe.h @@ -0,0 +1,32 @@ +/* Quagga Pthreads support -- thread safe versions of standard functions + * Copyright (C) 2009 Chris Hall (GMCH), Highwayman + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef PTHREAD_SAFE_H_ +#define PTHREAD_SAFE_H_ + +#include <netinet/in.h> + +extern void safe_init_r(void); +extern void safe_finish(void); +extern const char * safe_strerror(int errnum); +extern const char * safe_inet_ntoa (struct in_addr in); + +#endif /* PTHREAD_SAFE_H_ */ diff --git a/lib/qlib_init.c b/lib/qlib_init.c index 67391395..400b34fc 100644 --- a/lib/qlib_init.c +++ b/lib/qlib_init.c @@ -26,6 +26,7 @@ #include "thread.h" #include "privs.h" #include "mqueue.h" +#include "pthread_safe.h" /*============================================================================== * Quagga Library Initialise/Closedown @@ -77,12 +78,14 @@ qlib_init_second_stage(int pthreads) thread_init_r(); zprivs_init_r(); mqueue_initialise(); + safe_init_r(); } void qexit(int exit_code) { + safe_finish(); zprivs_finish(); thread_finish(); memory_finish(); diff --git a/lib/sockunion.c b/lib/sockunion.c index bfcadc96..479adc3e 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -322,7 +322,7 @@ sockunion_log (union sockunion *su) switch (su->sa.sa_family) { case AF_INET: - snprintf (buf, SU_ADDRSTRLEN, "%s", inet_ntoa (su->sin.sin_addr)); + snprintf (buf, SU_ADDRSTRLEN, "%s", safe_inet_ntoa (su->sin.sin_addr)); break; #ifdef HAVE_IPV6 case AF_INET6: @@ -642,7 +642,7 @@ sockunion_print (union sockunion *su) switch (su->sa.sa_family) { case AF_INET: - printf ("%s\n", inet_ntoa (su->sin.sin_addr)); + printf ("%s\n", safe_inet_ntoa (su->sin.sin_addr)); break; #ifdef HAVE_IPV6 case AF_INET6: |