OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / user / openvpn / thread.c
1 /*
2  *  OpenVPN -- An application to securely tunnel IP networks
3  *             over a single UDP port, with support for SSL/TLS-based
4  *             session authentication and key exchange,
5  *             packet encryption, packet authentication, and
6  *             packet compression.
7  *
8  *  Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License version 2
12  *  as published by the Free Software Foundation.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program (see the file COPYING included with this
21  *  distribution); if not, write to the Free Software Foundation, Inc.,
22  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
24
25 #include "syshead.h"
26
27 #ifdef USE_PTHREAD
28
29 #include "thread.h"
30 #include "buffer.h"
31 #include "common.h"
32 #include "error.h"
33 #include "crypto.h"
34
35 #include "memdbg.h"
36
37 static struct sparse_mutex *ssl_mutex;  /* GLOBAL */
38
39 static void
40 ssl_pthreads_locking_callback (int mode, int type, char *file, int line)
41 {
42   dmsg (D_OPENSSL_LOCK, "SSL LOCK thread=%4lu mode=%s lock=%s %s:%d",
43            CRYPTO_thread_id (),
44            (mode & CRYPTO_LOCK) ? "l" : "u",
45            (type & CRYPTO_READ) ? "r" : "w", file, line);
46
47   if (mode & CRYPTO_LOCK)
48     pthread_mutex_lock (&ssl_mutex[type].mutex);
49   else
50     pthread_mutex_unlock (&ssl_mutex[type].mutex);
51 }
52
53 static unsigned long
54 ssl_pthreads_thread_id (void)
55 {
56   unsigned long ret;
57
58   ret = (unsigned long) pthread_self ();
59   return ret;
60 }
61
62 static void
63 ssl_thread_setup (void)
64 {
65   int i;
66
67 #error L_MSG needs to be initialized as a recursive mutex
68
69   ssl_mutex = OPENSSL_malloc (CRYPTO_num_locks () * sizeof (struct sparse_mutex));
70   for (i = 0; i < CRYPTO_num_locks (); i++)
71     pthread_mutex_init (&ssl_mutex[i].mutex, NULL);
72
73   CRYPTO_set_id_callback ((unsigned long (*)(void)) ssl_pthreads_thread_id);
74   CRYPTO_set_locking_callback ((void (*)(int, int, const char*, int)) ssl_pthreads_locking_callback);
75 }
76
77 static void
78 ssl_thread_cleanup (void)
79 {
80   int i;
81
82   dmsg (D_OPENSSL_LOCK, "SSL LOCK cleanup");
83   CRYPTO_set_locking_callback (NULL);
84   for (i = 0; i < CRYPTO_num_locks (); i++)
85     pthread_mutex_destroy (&ssl_mutex[i].mutex);
86   OPENSSL_free (ssl_mutex);
87 }
88
89 struct sparse_mutex mutex_array[N_MUTEXES]; /* GLOBAL */
90 bool pthread_initialized;                   /* GLOBAL */
91
92 openvpn_thread_t
93 openvpn_thread_create (void *(*start_routine) (void *), void* arg)
94 {
95   openvpn_thread_t ret;
96   ASSERT (pthread_initialized);
97   ASSERT (!pthread_create (&ret, NULL, start_routine, arg));
98   dmsg (D_THREAD_DEBUG, "CREATE THREAD ID=%lu", (unsigned long)ret);
99   return ret;
100 }
101
102 void
103 openvpn_thread_join (openvpn_thread_t id)
104 {
105   ASSERT (pthread_initialized);
106   pthread_join (id, NULL);
107 }
108
109 void
110 openvpn_thread_init ()
111 {
112   int i;
113
114   ASSERT (!pthread_initialized);
115
116   msg (M_INFO, "PTHREAD support initialized");
117
118   /* initialize OpenSSL library locking */
119 #if defined(USE_CRYPTO) && defined(USE_SSL)
120   ssl_thread_setup();
121 #endif
122   
123   /* initialize static mutexes */
124   for (i = 0; i < N_MUTEXES; i++)
125     ASSERT (!pthread_mutex_init (&mutex_array[i].mutex, NULL));
126
127   msg_thread_init ();
128
129   pthread_initialized = true;
130 }
131
132 void
133 openvpn_thread_cleanup ()
134 {
135   if (pthread_initialized)
136     {
137       int i;
138
139       pthread_initialized = false;
140
141       /* cleanup OpenSSL library locking */
142 #if defined(USE_CRYPTO) && defined(USE_SSL)
143       ssl_thread_cleanup();
144 #endif
145
146       /* destroy static mutexes */
147       for (i = 0; i < N_MUTEXES; i++)
148         ASSERT (!pthread_mutex_destroy (&mutex_array[i].mutex));
149
150       msg_thread_uninit ();
151     }
152 }
153
154 #else
155 static void dummy(void) {}
156 #endif