1 #include "config.h"
2 
3 #include <razorback/api.h>
4 #include <razorback/log.h>
5 #include <razorback/daemon.h>
6 #include <razorback/config_file.h>
7 #include <razorback/uuids.h>
8 
9 #include <string.h>
10 #include <getopt.h>
11 
12 #include <signal.h>
13 
14 
15 
16 #ifdef _MSC_VER
17 #pragma comment(lib, "api.lib")
18 #define sleep(x) Sleep(x*1000)
19 #include "bobins.h"
20 #else
21 #include <ftw.h>
22 #include <dlfcn.h>
23 #include <sys/wait.h>
24 #endif
25 
26 
27 #define MASTER_CONF "master_nugget.conf"
28 static char *sg_sPidFile = NULL;
29 static char *sg_sSoPath = NULL;
30 static char *sg_sSoVersion;
31 static uuid_t sg_uuidNuggetId;
32 struct RazorbackContext *sg_pContext =NULL;
33 
34 static struct option sg_options[] =
35 {
36     {"debug",no_argument, NULL, 'd'},
37     {NULL, 0, NULL, 0}
38 };
39 
40 static RZBConfKey_t sg_Master_Config[] = {
41     {"NuggetId", RZB_CONF_KEY_TYPE_UUID, &sg_uuidNuggetId, NULL},
42     {"Nuggets.Path", RZB_CONF_KEY_TYPE_STRING, &sg_sSoPath, NULL},
43     {"PidFile", RZB_CONF_KEY_TYPE_STRING, &sg_sPidFile, NULL},
44     {NULL, RZB_CONF_KEY_TYPE_END, NULL, NULL}
45 };
46 
47 struct NuggetHandle
48 {
49     char *name;
50 #ifdef _MSC_VER
51 	HINSTANCE dlHandle;
52 #else
53     void *dlHandle;
54 #endif
55     bool (*initNug)(void);
56     void (*shutdownNug)(void);
57     struct NuggetHandle *pNext;
58 };
59 
60 struct NuggetHandle *nuggetList = NULL;
61 
62 
63 static bool loadNuggets();
64 static void unloadNuggets();
65 bool restart = false;
66 bool end = false;
67 
68 #ifdef _MSC_VER
69 #else
70 void termination_handler (int signum);
71 /* SIGCHLD handler. */
72 static void
sigchld_handler(int sig)73 sigchld_handler (int sig)
74 {
75     while (waitpid(-1, NULL, WNOHANG) > 0) {}
76 }
77 #endif
78 
main(int argc,char ** argv)79 int main (int argc, char ** argv)
80 {
81 
82     int optId; /* holds the option index for getopt*/
83     int option_index = 0;
84     int debug = 0;
85 	uuid_t masterNugget;
86 
87     while (1)
88     {
89         optId = getopt_long(argc, argv, "d", sg_options, &option_index);
90 
91         if (optId == -1)
92             break;
93 
94         switch (optId)
95         {
96             case 'd':
97                 debug = 1;
98                 break;
99             case '?':  /* getopt errors */
100                 // TODO: Print errors
101                 break;
102             default:
103                 // TODO: Print Usage
104                 break;
105         }
106     }
107     // TODO: Add command line option for config dir.
108     if (!readMyConfig (NULL, MASTER_CONF, sg_Master_Config))
109 	{
110 		rzb_log(LOG_ERR, "%s: Failed to read configuation", __func__);
111 		return -1;
112 	}
113 #ifdef _MSC_VER
114 #else
115     signal (SIGINT, termination_handler);
116     signal (SIGTERM, termination_handler);
117     signal (SIGHUP, termination_handler);
118     signal (SIGPIPE, termination_handler);
119     signal (SIGCHLD, sigchld_handler);
120 
121 #endif
122     if (!debug) {
123         if (!rzb_daemonize(NULL, sg_sPidFile)) {
124             rzb_log(LOG_ERR, "Failed to daemonize");
125             return 1;
126         }
127     } else {
128         rzb_debug_logging();
129     }
130     if ((sg_pContext= calloc(1, sizeof(struct RazorbackContext))) == NULL)
131     {
132         rzb_log(LOG_ERR, "Failed to allocate master nugget context");
133         return 1;
134     }
135 
136 
137     UUID_Get_UUID(NUGGET_TYPE_MASTER, UUID_TYPE_NUGGET_TYPE, masterNugget);
138     uuid_copy(sg_pContext->uuidNuggetId, sg_uuidNuggetId);
139     uuid_copy(sg_pContext->uuidNuggetType, masterNugget);
140     uuid_clear(sg_pContext->uuidApplicationType);
141     sg_pContext->iFlags=CONTEXT_FLAG_STAND_ALONE;
142     sg_pContext->iDataTypeCount=0;
143     sg_pContext->pCommandHooks=NULL;
144     sg_pContext->pInspectionHooks=NULL;
145     if (!Razorback_Init_Context(sg_pContext))
146     {
147         rzb_log(LOG_ERR, "Master Nugget: Failed to register context");
148         return 1;
149     }
150     loadNuggets();
151     while (!end)
152     {
153         if (restart)
154         {
155             unloadNuggets();
156             loadNuggets();
157             restart = false;
158         }
159         sleep(1);
160     }
161     unloadNuggets();
162     Razorback_Shutdown_Context(sg_pContext);
163 
164     return 0;
165 }
166 
167 
168 #ifdef _MSC_VER
169 static bool
processFile(WIN32_FIND_DATAA fileData)170 processFile (WIN32_FIND_DATAA fileData)
171 {
172 	struct NuggetHandle *nugget;
173 	rzb_log(LOG_DEBUG, "Load Nuggets: Found File: %s", fileData.cFileName);
174     if ((nugget = calloc(1,sizeof(struct NuggetHandle))) == NULL)
175     {
176         rzb_log(LOG_ERR, "%s: Failed to allocate nugget handle (%s)", __func__, fileData.cFileName);
177         return false;
178     }
179 	if ( asprintf(&nugget->name, "%s\\%s", sg_sSoPath, fileData.cFileName) == -1)
180     {
181         rzb_log(LOG_ERR, "%s: Failed to allocate nugget name (%s)", __func__, fileData.cFileName);
182         return false;
183     }
184 	if ((nugget->dlHandle = LoadLibraryA(nugget->name)) == NULL)
185 	{
186         free(nugget);
187         rzb_log(LOG_ERR, "Load Nuggets: Failed to open %s, %d", fileData.cFileName, GetLastError());
188 		return false;
189     }
190 	*(void **)&nugget->initNug = GetProcAddress(nugget->dlHandle, "initNug");
191     *(void **)&nugget->shutdownNug = GetProcAddress(nugget->dlHandle, "shutdownNug");
192 	if (nugget->initNug == NULL)
193     {
194         FreeLibrary(nugget->dlHandle);
195         rzb_log(LOG_ERR, "Failed to resolve initNug() for %s.", fileData.cFileName);
196         free(nugget);
197         return false;
198     }
199     if (nugget->shutdownNug == NULL)
200     {
201         FreeLibrary(nugget->dlHandle);
202         rzb_log(LOG_ERR, "Failed to resolve shutdownNug() for %s.", fileData.cFileName);
203         free(nugget);
204         return false;
205     }
206 
207     if (!nugget->initNug())
208     {
209         rzb_log(LOG_ERR, "Failed to initialize nugget: %s", fileData.cFileName);
210         FreeLibrary(nugget->dlHandle);
211         free(nugget);
212         return false;
213     }
214 	rzb_log(LOG_INFO, "Functions registered for %s", fileData.cFileName);
215     // Add nugget to list.
216     nugget->pNext = nuggetList;
217     nuggetList = nugget;
218 	return true;
219 }
220 #else
221 // ftw callback that looks for files with the provided extension
222 static int
processFile(const char * name,const struct stat * status,int type)223 processFile(const char *name, const struct stat *status, int type)
224 {
225 //    int name_len, offset;
226     struct NuggetHandle *nugget;
227     char *errstr;
228     if (type == FTW_F)
229     {
230         if (strstr(name,sg_sSoVersion) == &name[strlen(name) - strlen(sg_sSoVersion)])
231         {
232             rzb_log(LOG_DEBUG, "Load Nuggets: Found File: %s", name);
233             if ((nugget = calloc(1,sizeof(struct NuggetHandle))) == NULL)
234             {
235                 rzb_log(LOG_ERR, "%s: Failed to allocate nugget handle (%s)", __func__, name);
236                 return 0;
237             }
238             if ( asprintf(&nugget->name, "%s", name) == -1)
239             {
240                 rzb_log(LOG_ERR, "%s: Failed to allocate nugget name (%s)", __func__, name);
241                 return 0;
242             }
243 
244             if ((nugget->dlHandle = dlopen(name, RTLD_LOCAL | RTLD_NOW)) == NULL)
245             {
246                 errstr = dlerror();
247                 free(nugget);
248                 rzb_log(LOG_ERR, "Load Nuggets: Failed to open %s, %s", name, errstr);
249                 return 0;
250             }
251 
252             *(void **)&nugget->initNug = dlsym(nugget->dlHandle, "initNug");
253             *(void **)&nugget->shutdownNug = dlsym(nugget->dlHandle, "shutdownNug");
254             if (nugget->initNug == NULL)
255             {
256                 dlclose(nugget->dlHandle);
257                 rzb_log(LOG_ERR, "Failed to resolve initNug() for %s.", name);
258                 free(nugget);
259                 return 0;
260             }
261             if (nugget->shutdownNug == NULL)
262             {
263                 dlclose(nugget->dlHandle);
264                 rzb_log(LOG_ERR, "Failed to resolve shutdownNug() for %s.", name);
265                 free(nugget);
266                 return 0;
267             }
268 
269             if (!nugget->initNug())
270             {
271                 rzb_log(LOG_ERR, "Failed to initialize nugget: %s", name);
272                 dlclose(nugget->dlHandle);
273                 free(nugget);
274                 return 0;
275             }
276             rzb_log(LOG_INFO, "Functions registered for %s", name);
277             // Add nugget to list.
278             nugget->pNext = nuggetList;
279             nuggetList = nugget;
280 
281         }
282     }
283     return 0;
284 }
285 #endif
286 
loadNuggets()287 static bool loadNuggets()
288 {
289 #ifdef _MSC_VER
290 	WIN32_FIND_DATAA FindFileData;
291 	HANDLE hFind;
292 	char * path;
293 	if (asprintf(&path, "%s\\%s", sg_sSoPath, "\\*.dll") == -1)
294 		return false;
295 
296 	hFind = FindFirstFileA(path, &FindFileData);
297 	if (hFind == INVALID_HANDLE_VALUE)
298 	{
299 		rzb_log(LOG_ERR, "%s: FindFirstFile failed (%d)", __func__, GetLastError());
300 		return false;
301 	}
302 
303 	while (hFind != INVALID_HANDLE_VALUE)
304 	{
305 		if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
306 		{
307 			processFile(FindFileData);
308 		}
309 		if (!FindNextFileA(hFind, &FindFileData))
310 		{
311 			if (GetLastError() == ERROR_NO_MORE_FILES)
312 			{
313 				FindClose(hFind);
314 				hFind = INVALID_HANDLE_VALUE;
315 			}
316 			else
317 			{
318 				rzb_log(LOG_ERR, "%s: Failed to find file", __func__);
319 				return false;
320 			}
321 		}
322 	}
323 #else
324 	int l_iIt, l_iLen;
325     if ((l_iLen = asprintf(&sg_sSoVersion, "%s", NUGGET_SO_VERSION))== -1)
326         return false;
327 
328     // This is ugly there must be a better way
329     for (l_iIt =0; l_iIt < l_iLen; l_iIt++)
330         if (sg_sSoVersion[l_iIt] == ':')
331             sg_sSoVersion[l_iIt] = '.';
332 
333     rzb_log(LOG_DEBUG, "LoadNuggets: SO Version: %s", sg_sSoVersion);
334     ftw(sg_sSoPath, processFile, 1);
335 #endif
336     return true;
337 }
338 
339 
unloadNuggets()340 static void unloadNuggets()
341 {
342     struct NuggetHandle *current = nuggetList;
343     while(current != NULL)
344     {
345         rzb_log(LOG_INFO, "Shutting down nugget: %s", current->name);
346         current->shutdownNug();
347 #ifdef _MSC_VER
348 #else
349         dlclose(current->dlHandle);
350 #endif
351         nuggetList = current->pNext;
352         free(current->name);
353         free(current);
354         current = nuggetList;
355     }
356 }
357 
358 
359 #ifdef _MSC_VER
360 #else
361 void
termination_handler(int signum)362 termination_handler (int signum)
363 {
364     switch(signum)
365     {
366     case SIGPIPE:
367         // Ignore it
368         break;
369     case SIGINT:
370     case SIGTERM:
371         rzb_log(LOG_INFO, "Master Nugget shutting down");
372         end=true;
373         break;
374     case SIGHUP:
375         rzb_log(LOG_INFO, "Master Nugget Reloading Nuggets");
376         restart = true;
377         break;
378     default:
379         rzb_log(LOG_ERR, "%s: Master Nugget Unknown signal: %i", __func__, signum);
380         break;
381     }
382 }
383 #endif
384 
385