An Overlay-based
Virtual Network Substrate
SpoVNet

source: trash/old-modules/transport/protlib/threadsafe_db.cpp @ 5641

Last change on this file since 5641 was 5641, checked in by Christoph Mayer, 14 years ago
File size: 10.3 KB
Line 
1/// ----------------------------------------*- mode: C++; -*--
2/// @file threadsafe_db.cpp
3/// Thread-safe access for some resolving functions (netdb)...
4/// ----------------------------------------------------------
5/// $Id: threadsafe_db.cpp 2872 2008-02-18 10:58:03Z bless $
6/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/threadsafe_db.cpp $
7// ===========================================================
8//                     
9// Copyright (C) 2005-2007, all rights reserved by
10// - Institute of Telematics, Universitaet Karlsruhe (TH)
11//
12// More information and contact:
13// https://projekte.tm.uka.de/trac/NSIS
14//                     
15// This program is free software; you can redistribute it and/or modify
16// it under the terms of the GNU General Public License as published by
17// the Free Software Foundation; version 2 of the License
18//
19// This program is distributed in the hope that it will be useful,
20// but WITHOUT ANY WARRANTY; without even the implied warranty of
21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22// GNU General Public License for more details.
23//
24// You should have received a copy of the GNU General Public License along
25// with this program; if not, write to the Free Software Foundation, Inc.,
26// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27//
28// ===========================================================
29/** @ingroup netdb
30 *
31 * As the reentrant functions for netdb access seem not portable, I decided to
32 * write some wrappers for those functions I need. This is not
33 * object-oriented because the NetDB would be another singleton object and
34 * I only want some wrapper functions.
35 */
36
37#include <netdb.h>
38#include <pwd.h>
39#include <netinet/in.h>
40#include <cerrno>
41
42#include "threadsafe_db.h"
43#include "cleanuphandler.h"
44#include "logfile.h"
45
46namespace protlib { 
47
48/** @addtogroup netdb Thread-safe DB
49 * @{
50 */
51
52  using namespace log;
53
54bool tsdb::is_init = false;
55bool tsdb::resolvenames = true;
56pthread_mutex_t tsdb::mutex = 
57#ifdef _DEBUG
58    PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
59#else
60    PTHREAD_MUTEX_INITIALIZER;
61#endif
62
63
64uint32 tsdb::id32 = 1;
65uint64 tsdb::id64 = 1;
66
67protocol_t tsdb::udp_id= 17;
68protocol_t tsdb::tcp_id= 6;
69protocol_t tsdb::sctp_id= 132;
70
71
72void 
73tsdb::init(bool noresolving) 
74{
75  if (is_init) 
76  {
77    Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to initialize tstdb although already initialized.");
78  } else 
79  {
80    pthread_mutex_init(&mutex,NULL);
81    is_init = true;
82
83    // initialize frequently used protocol constants
84    udp_id= tsdb::getprotobyname("udp");
85    tcp_id= tsdb::getprotobyname("tcp");
86    sctp_id= tsdb::getprotobyname("sctp");
87
88    resolvenames=!noresolving;
89    if (!resolvenames) 
90      Log(INFO_LOG,LOG_NORMAL,"Threadsafe_DB"," ** Disabled reverse name lookups - addresses will not be resolved to names **");
91  } // end if is_init
92} // end init
93 
94void tsdb::end() {
95        if (is_init) {
96                is_init = false;
97                pthread_mutex_destroy(&mutex);
98        } else {
99          Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to end tstdb although not initialized.");
100        } // end if is_init
101} // end end
102
103uint32 tsdb::get_new_id32() {
104        uint32 res = 0;
105        if (is_init) {
106                pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
107                res = id32++;
108                pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
109        } else {
110          Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
111        } // end if is_init
112        return res;
113} // end get_new_id32
114
115uint64 tsdb::get_new_id64() {
116        uint64 res = 0;
117        if (is_init) {
118                pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
119                res = id64++;
120                pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
121        } else {
122          Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
123        } // end if is_init
124        return res;
125} // end get_new_id64
126
127string tsdb::getprotobynumber(protocol_t proto, bool *res) {
128        string str;
129        if (is_init) 
130        {
131                pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
132                struct protoent* entry = ::getprotobynumber(proto);
133
134                if (res) *res = (entry!=NULL);
135                if (entry) 
136                  str = entry->p_name;
137                else 
138                  str = "UNKNOWN";
139
140                pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
141        } 
142        else 
143        {
144          Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
145          if (res) *res = false;
146          str = "";
147        } // end if is_init
148        return str;
149} // end getprotobynumber
150
151protocol_t tsdb::getprotobyname(const string &pname, bool *res) {
152        return getprotobyname(pname.c_str(),res);
153} // end getprotobyname
154
155protocol_t tsdb::getprotobyname(const char* pname, bool *res) {
156        register protocol_t pnum;
157        struct protoent* entry = NULL;
158        if (is_init) {
159                pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
160                if (pname) entry = ::getprotobyname(pname);
161                if (res) *res = (entry!=NULL);
162                if (entry) pnum = entry->p_proto;
163                else pnum = 0;
164                pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
165        } else {
166          Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
167          if (res) *res = false;
168          pnum = 0;
169        } // end if is_init
170        return pnum;
171} // end getprotobyname
172
173string tsdb::get_username(uid_t uid, bool *res) {
174        string str;
175        if (is_init) {
176                pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
177                struct passwd* entry = ::getpwuid(uid);
178                if (res) *res = (entry!=NULL);
179                if (entry) str = entry->pw_name;
180                else str = "UNKNOWN";
181                pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
182        } else {
183          Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
184          if (res) *res = false;
185          str = "";
186        } // end if is_init
187        return str;
188} // end get_username
189
190uid_t tsdb::get_userid(const char* uname, bool *res) {
191        register uid_t uid;
192        struct passwd* entry = NULL;
193        if (is_init) {
194                pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
195                if (uname) entry = ::getpwnam(uname);
196                if (res) *res = (entry!=NULL);
197                if (entry) uid = entry->pw_uid;
198                else uid = 0;
199                pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
200        } else {
201          Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
202          if (res) *res = false;
203          uid = 0;
204        } // end if is_init
205        return uid;
206} // end get_userid
207
208uid_t tsdb::get_userid(const string& uname, bool *res) {
209        return get_userid(uname.c_str(),res);
210} // end get_userid
211
212string tsdb::get_portname(port_t port, protocol_t prot, bool *res) {
213        string str;
214        if (is_init) {
215                bool tmpres = true;
216                string pname = getprotobynumber(prot,&tmpres);
217                if (tmpres) {
218                        pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
219                        struct servent* entry = ::getservbyport(htons(port),pname.c_str());
220                        if (res) *res = (entry!=NULL);
221                        if (entry) str = entry->s_name;
222                        else str = "UNKNOWN";
223                        pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
224                } else {
225                        if (res) *res = false;
226                        str = "UNKNOWN";
227                } // end if tmpres
228        } else {
229          Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
230          if (res) *res = false;
231          str = "";
232        } // end if is_init
233        return str;
234} // end get_portname
235
236port_t tsdb::get_portnumber(const char* pname, protocol_t prot, bool *res) {
237        register port_t pnum;
238        struct servent* entry = NULL;
239        if (is_init) {
240                bool tmpres = true;
241                string protoname = getprotobynumber(prot,&tmpres);
242                if (tmpres) {
243                        pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
244                        if (pname) entry = ::getservbyname(pname,protoname.c_str());
245                        if (res) *res = (entry!=NULL);
246                        if (entry) pnum = ntohs(entry->s_port);
247                        else pnum = 0;
248                        pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
249                } else {
250                        if (res) *res = false;
251                        pnum = 0;
252                } // end if tmpres
253        } else {
254          Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
255          if (res) *res = false;
256          pnum = 0;
257        } // end if is_init
258        return pnum;
259} // end get_portnumber
260
261port_t tsdb::get_portnumber(const string& pname, protocol_t prot, bool *res) {
262        return get_portnumber(pname.c_str(),prot,res);
263} // end get_portnumber
264
265
266string
267tsdb::get_hostname(const struct sockaddr* sa, bool *res) 
268{
269  string str;
270  static char tmpbuf[NI_MAXHOST];
271
272  if (is_init) 
273  {
274    pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
275    if (resolvenames)
276    {
277      int resultval= getnameinfo(sa,sizeof(struct sockaddr),
278                                 tmpbuf,sizeof(tmpbuf),
279                                 0,0, // services
280                                 0);  // flags
281     
282      if (res) *res = (resultval==0);
283      if (resultval==0)
284      { // success
285        str= tmpbuf; // this should copy the buffer contents
286      }
287      else
288      {
289        str = "UNKNOWN";
290        if (resultval==EAI_AGAIN || errno==EAI_AGAIN)
291        {
292          Log(INFO_LOG,LOG_NORMAL, "Threadsafe_DB", "Temporary failure in name lookup. Try again later.");
293        }
294        else
295          Log(INFO_LOG,LOG_NORMAL, "Threadsafe_DB", "Name lookup failed -" << strerror(errno));
296
297        if (res) *res= false;
298      }
299    }
300    else
301    {
302      str= "disabled";
303      if (res) *res= false;
304    }
305    pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
306  }
307  else 
308  {
309    Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
310    if (res) *res = false;
311    str = "";
312  } // end if is_init
313  return str;
314} // ent get_hostname(in_addr)
315
316
317
318/** lookup of hostname for an ipv4 address
319 *  @param in ipv4 address structure
320 *  @param res returns true if name lookup was successful, otherwise false
321 *
322 *  @return in case that resolving is enabled it returns the host name corresponding to the given address or "UNKNOWN",
323 *           otherwise it returns "disabled"
324 */
325string
326tsdb::get_hostname(const in_addr& in, bool *res) 
327{
328  struct sockaddr_in sa={
329    AF_INET,
330    0,
331    in
332  };
333  return get_hostname(reinterpret_cast<const sockaddr*>(&sa),res);
334}
335
336/** lookup of hostname for ipv6 address
337 *  @param in ipv6 address structure
338 *  @param res returns true if name lookup was successful, otherwise false
339 *
340 *  @return in case that resolving is enabled it returns the host name corresponding to the given address or "UNKNOWN",
341 *           otherwise it returns "disabled"
342 */
343string
344tsdb::get_hostname(const in6_addr& in, bool *res) 
345{
346  struct sockaddr_in6 sa={
347    AF_INET6,
348    0, // transport layer port #
349    0, // IPv6 flow information
350    in,
351    0  // scope id (new in RFC2553)
352  };
353  return get_hostname(reinterpret_cast<const sockaddr*>(&sa),res);
354} // ent get_hostname(in6_addr)
355
356//@}
357
358} // end namespace protlib
Note: See TracBrowser for help on using the repository browser.