Build for Ubuntu precise, no build for maverick
[yazproxy-moved-to-github.git] / src / modules.cpp
1 /* This file is part of YAZ proxy
2    Copyright (C) 1998-2011 Index Data
3
4 YAZ proxy is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 #include <string.h>
20 #if HAVE_DLFCN_H
21 #include <dlfcn.h>
22 #endif
23
24 #include <yaz/nmem.h>
25 #include <yaz/log.h>
26 #include <yazproxy/module.h>
27
28 class Yaz_ProxyModule {
29     friend class Proxy_Msg;
30 private:
31     void *m_dl_handle;                /* dlopen/close handle */
32     Yaz_ProxyModule_entry *m_entry;
33     Yaz_ProxyModule *m_next;
34     void *m_user_handle;              /* user handle */
35 public:
36     Yaz_ProxyModule(void *dl_handle, Yaz_ProxyModule_entry *ent,
37                     Yaz_ProxyModule *next);
38     ~Yaz_ProxyModule();
39
40     Yaz_ProxyModule *get_next() { return m_next; };
41     int is_module(const char *name);
42     int authenticate(const char *target_name, void *element_ptr,
43                      const char *user, const char *group, const char *password,
44                      const char *peer_IP);
45 };
46
47 int Yaz_ProxyModule::is_module(const char *name)
48 {
49     if (!name || !strcmp(m_entry->module_name, name))
50         return 1;
51     return 0;
52 }
53
54 Yaz_ProxyModule::Yaz_ProxyModule(void *dl_handle, Yaz_ProxyModule_entry *ent,
55                                  Yaz_ProxyModule *next)
56 {
57     m_dl_handle = dl_handle;
58     m_entry = ent;
59     m_next = next;
60     m_user_handle = 0;
61     if (m_entry->int_version == 0)
62     {
63         struct Yaz_ProxyModule_int0 *int0 =
64             reinterpret_cast<Yaz_ProxyModule_int0 *>(m_entry->fl);
65         if (int0->init)
66             m_user_handle = (*int0->init)();
67     }
68 }
69
70 Yaz_ProxyModule::~Yaz_ProxyModule()
71 {
72     if (m_entry->int_version == 0)
73     {
74         struct Yaz_ProxyModule_int0 *int0 =
75             reinterpret_cast<Yaz_ProxyModule_int0 *>(m_entry->fl);
76         if (int0->destroy)
77             (*int0->destroy)(m_user_handle);
78     }
79 #if HAVE_DLFCN_H
80     dlclose(m_dl_handle);
81 #endif
82 }
83
84 int Yaz_ProxyModule::authenticate(const char *name,
85                                   void *element_ptr,
86                                   const char *user, const char *group,
87                                   const char *password,
88                                   const char *peer_IP)
89 {
90     if (m_entry->int_version == 0)
91     {
92         struct Yaz_ProxyModule_int0 *int0 =
93             reinterpret_cast<Yaz_ProxyModule_int0 *>(m_entry->fl);
94
95         if (!int0->authenticate)
96             return YAZPROXY_RET_NOT_ME;
97         return (*int0->authenticate)(m_user_handle, name, element_ptr,
98                                      user, group, password, peer_IP);
99     }
100     return YAZPROXY_RET_NOT_ME;
101 }
102
103 Yaz_ProxyModules::Yaz_ProxyModules()
104 {
105     m_list = 0;
106     m_no_open = 0;
107 }
108
109
110 Yaz_ProxyModules::~Yaz_ProxyModules()
111 {
112     unload_modules();
113 }
114
115 void Yaz_ProxyModules::unload_modules()
116 {
117     Yaz_ProxyModule *m = m_list;
118     while (m)
119     {
120         Yaz_ProxyModule *m_next = m->get_next();
121         delete m;
122         m_no_open--;
123         m = m_next;
124     }
125     m_list = 0;
126 }
127
128
129 int Yaz_ProxyModules::authenticate(const char *module_name,
130                                    const char *target_name, void *element_ptr,
131                                    const char *user,
132                                    const char *group,
133                                    const char *password,
134                                    const char *peer_IP)
135 {
136     int ret = YAZPROXY_RET_NOT_ME;
137     Yaz_ProxyModule *m = m_list;
138     for (; m; m = m->get_next())
139     {
140         if (m->is_module(module_name))
141         {
142             ret = m->authenticate(target_name, element_ptr,
143                                   user, group, password,
144                                   peer_IP);
145             if (ret != YAZPROXY_RET_NOT_ME)
146                 break;
147         }
148     }
149     return ret;
150 }
151
152 int Yaz_ProxyModules::add_module(const char *fname)
153 {
154 #if HAVE_DLFCN_H
155     void *dl_handle = dlopen(fname, RTLD_NOW|RTLD_GLOBAL);
156     if (dl_handle)
157     {
158         Yaz_ProxyModule_entry *fl_ptr = 0;
159         fl_ptr = reinterpret_cast<Yaz_ProxyModule_entry *>
160             (dlsym(dl_handle, "yazproxy_module"));
161         if (fl_ptr)
162         {
163             Yaz_ProxyModule *m = new Yaz_ProxyModule(dl_handle,
164                                                      fl_ptr,
165                                                      m_list);
166             m_list = m;
167
168             m_no_open++;
169             yaz_log(YLOG_LOG, "Loaded module %s OK", fname);
170             return 0;
171         }
172         else
173         {
174             yaz_log(YLOG_WARN, "Failed loading module %s - missing symbols",
175                     fname);
176             return -1;
177             dlclose(dl_handle);
178         }
179     }
180     else
181     {
182         yaz_log(YLOG_WARN, "Failed loading module %s", fname);
183         return -1;
184     }
185 #else
186     yaz_log(YLOG_WARN, "Failed loading module %s - no module support", fname);
187     return -1;
188 #endif
189 }
190
191 /*
192  * Local variables:
193  * c-basic-offset: 4
194  * c-file-style: "Stroustrup"
195  * indent-tabs-mode: nil
196  * End:
197  * vim: shiftwidth=4 tabstop=8 expandtab
198  */
199