summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/filter.c24
-rw-r--r--lib/if.c6
-rw-r--r--lib/log.c8
-rw-r--r--lib/log.h1
-rw-r--r--lib/memtypes.c1
-rw-r--r--lib/pthread_safe.c124
-rw-r--r--lib/pthread_safe.h32
-rw-r--r--lib/qlib_init.c3
-rw-r--r--lib/sockunion.c4
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);
}
}
diff --git a/lib/if.c b/lib/if.c
index d14cfb93..c9a9b335 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -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;
diff --git a/lib/log.c b/lib/log.c
index f6231974..bc4ed1ff 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -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;
diff --git a/lib/log.h b/lib/log.h
index 6ab1b37c..ae573804 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -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: