1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include <limits.h>
26 #include <protocol/protocol.h>
|
27 krisbash 1.4 #include <pal/sleep.h>
|
28 mike 1.2 #include <wsman/wsman.h>
|
29 mike 1.1 #include <provreg/provreg.h>
30 #include <provmgr/provmgr.h>
31 #include <disp/disp.h>
|
32 krisbash 1.4 #include <pal/strings.h>
33 #include <pal/dir.h>
|
34 mike 1.1 #include <base/log.h>
35 #include <base/env.h>
36 #include <base/process.h>
37 #include <base/pidfile.h>
38 #include <base/paths.h>
39 #include <base/conf.h>
40 #include <base/user.h>
|
41 krisbash 1.4 #include <base/omigetopt.h>
42 #include <base/multiplex.h>
43 #include <base/Strand.h>
44 #include <pal/format.h>
|
45 mike 1.1
46 #if defined(CONFIG_POSIX)
47 # include <signal.h>
48 # include <sys/wait.h>
|
49 krisbash 1.4 # include <pthread.h>
|
50 mike 1.1 #endif
51
52 typedef struct _ServerData ServerData;
53
54 typedef enum _ServerTransportType
55 {
56 SRV_PROTOCOL,
57 SRV_WSMAN
58 }
59 ServerTransportType;
60
61 typedef struct _ServerCallbackData
62 {
63 ServerData* data;
64 ServerTransportType type;
65 }
66 ServerCallbackData;
67
68 struct _ServerData
69 {
|
70 krisbash 1.4 Disp disp;
71 MuxIn mux;
72 ProtocolBase* protocol;
73 WSMAN* wsman;
74 Selector selector;
75 MI_Boolean selectorInitialized;
76 MI_Boolean terminated;
|
77 mike 1.1
78 /* pointers to self with different types - one per supported transport */
79 ServerCallbackData protocolData;
80 ServerCallbackData wsmanData;
81 } ;
82
83 typedef struct _Options
84 {
85 MI_Boolean help;
|
86 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
|
87 mike 1.1 MI_Boolean trace;
|
88 krisbash 1.4 #endif
|
89 mike 1.2 MI_Boolean httptrace;
|
90 mike 1.1 MI_Boolean terminateByNoop;
91 #if defined(CONFIG_POSIX)
92 MI_Boolean daemonize;
93 MI_Boolean stop;
94 MI_Boolean reloadConfig;
95 #endif
96 /* mostly for unittesting in non-root env */
97 MI_Boolean ignoreAuthentication;
98 MI_Boolean locations;
99 MI_Boolean logstderr;
100 unsigned short httpport;
101 unsigned short httpsport;
|
102 krisbash 1.4 char* sslCipherSuite;
103 Server_SSL_Options sslOptions;
|
104 mike 1.1 MI_Uint64 idletimeout;
105 MI_Uint64 livetime;
106 Log_Level logLevel;
107 }
108 Options;
109
110 static Options s_opts;
111
112 static ServerData s_data;
113
114 static const char* arg0 = 0;
115
|
116 krisbash 1.4 static const ZChar HELP[] = ZT("\
|
117 mike 1.1 Usage: %s [OPTIONS]\n\
118 \n\
119 This program starts the server.\n\
120 \n\
121 OPTIONS:\n\
122 -h, --help Print this help message.\n\
123 -d Daemonize the server process (POSIX only).\n\
124 -s Stop the server process (POSIX only).\n\
125 -r Re-read configuration by the running server (POSIX only).\n\
126 --httpport PORT HTTP protocol listener port.\n\
127 --httpsport PORT HTTPS protocol listener port.\n\
128 --idletimeout TIMEOUT Idle providers unload timeout (in seconds).\n\
129 -v, --version Print version information.\n\
130 -l, --logstderr Send log output to standard error.\n\
131 --loglevel LEVEL Set logging level to one of the following\n\
132 symbols/numbers: fatal/0, error/1, warning/2,\n\
|
133 krisbash 1.4 info/3, debug/4, verbose/5 (default 2).\n\
|
134 mike 1.2 --httptrace Enable logging of HTTP traffic.\n\
|
135 krisbash 1.4 --timestamp Print timestamp server was built with.\n\
136 \n");
137
138 STRAND_DEBUGNAME( NoopRequest );
|
139 mike 1.1
|
140 krisbash 1.4 static void FUNCTION_NEVER_RETURNS err(const ZChar* fmt, ...)
|
141 mike 1.1 {
142 va_list ap;
143 memset(&ap, 0, sizeof(ap));
144
|
145 krisbash 1.4 Ftprintf(stderr, ZT("%s: "), scs(arg0));
|
146 mike 1.1
147 va_start(ap, fmt);
|
148 krisbash 1.4 Vftprintf(stderr, fmt, ap);
|
149 mike 1.1 va_end(ap);
150
151 /* Write to log as well */
152 va_start(ap, fmt);
|
153 krisbash 1.4 __LOGE((fmt, ap));
|
154 mike 1.1 va_end(ap);
155
|
156 krisbash 1.4 Ftprintf(stderr, ZT("\n"));
|
157 mike 1.1 exit(1);
158 }
159
|
160 krisbash 1.4 static void FUNCTION_NEVER_RETURNS info_exit(const ZChar* fmt, ...)
|
161 mike 1.1 {
|
162 krisbash 1.4 va_list ap;
163 memset(&ap, 0, sizeof(ap));
164
165 Ftprintf(stderr, ZT("%s: "), scs(arg0));
166
167 va_start(ap, fmt);
168 Vftprintf(stderr, fmt, ap);
169 va_end(ap);
170
171 /* Write to log as well */
172 va_start(ap, fmt);
173 __LOGI((fmt, ap));
174 va_end(ap);
175
176 Ftprintf(stderr, ZT("\n"));
177 exit(0);
178 }
|
179 mike 1.1
|
180 krisbash 1.4 void PrintProviderMsg( _In_ Message* msg)
181 {
182 #if !defined(CONFIG_FAVORSIZE)
183 if (s_opts.trace)
|
184 mike 1.1 {
|
185 krisbash 1.4 switch ( msg->tag )
|
186 mike 1.1 {
|
187 krisbash 1.4 case PostResultMsgTag:
|
188 mike 1.1 {
|
189 krisbash 1.4 const PostResultMsg* rsp = (const PostResultMsg*)msg;
|
190 mike 1.1 PostResultMsg_Print(rsp, stdout);
191 }
|
192 krisbash 1.4 break;
|
193 mike 1.1
|
194 krisbash 1.4 case PostInstanceMsgTag:
|
195 mike 1.1 {
|
196 krisbash 1.4 const PostInstanceMsg* rsp = (const PostInstanceMsg*)msg;
|
197 mike 1.1 PostInstanceMsg_Print(rsp, stdout);
198 }
|
199 krisbash 1.4 break;
|
200 mike 1.1
|
201 krisbash 1.4 case PostSchemaMsgTag:
|
202 mike 1.1 {
|
203 krisbash 1.4 const PostSchemaMsg* rsp = (const PostSchemaMsg*)msg;
204 PostSchemaMsg_Print(rsp, stdout);
|
205 mike 1.1 }
|
206 krisbash 1.4 break;
|
207 mike 1.1
|
208 krisbash 1.4 case NoOpRspTag:
209 break; // send noop confirmation to the client
|
210 mike 1.1
|
211 krisbash 1.4 default:
212 {
213 trace_UnknownMessageType(msg->tag);
214 exit(1);
215 }
|
216 mike 1.1 }
217 }
|
218 krisbash 1.4 #endif // !defined(CONFIG_FAVORSIZE)
219 }
|
220 mike 1.1
|
221 krisbash 1.4 /*
222 Simple interaction object to respond to the noop request.
223 It just sends a noop response and closes the interaction
224 (therefore shutting down)
225 */
226 void _NoopInteractionAck( _In_ Strand* self)
227 {
228 // do nothing
229 }
|
230 mike 1.1
|
231 krisbash 1.4 StrandFT _NoopInteractionUserFT = {
232 NULL,
233 NULL,
234 _NoopInteractionAck,
235 NULL,
236 NULL,
237 NULL,
238 NULL,
239 NULL,
240 NULL,
241 NULL,
242 NULL,
243 NULL };
|
244 mike 1.1
|
245 krisbash 1.4 static void _ProcessNoopRequest(
246 _Inout_ InteractionOpenParams* params )
|
247 mike 1.1 {
|
248 krisbash 1.4 Strand* strand;
249 NoOpReq* req = (NoOpReq*)params->msg;
250 NoOpRsp* rsp;
|
251 mike 1.1
|
252 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
253 if (s_opts.trace)
254 {
255 NoOpReq_Print(req, stdout);
256 }
257 #endif
258
259 strand = Strand_New( STRAND_DEBUG( NoopRequest ) &_NoopInteractionUserFT, 0, STRAND_FLAG_ENTERSTRAND, params );
|
260 mike 1.1
|
261 krisbash 1.4 if( NULL == strand )
|
262 mike 1.1 {
|
263 krisbash 1.4 err(ZT("out of memory"));
264 trace_OutOfMemory();
265 Strand_FailOpen(params);
266 return;
267 }
|
268 mike 1.1
|
269 krisbash 1.4 /* Send NoOp response back */
270 rsp = NoOpRsp_New(req->base.base.operationId);
|
271 mike 1.1
|
272 krisbash 1.4 if (!rsp)
273 {
274 err(ZT("out of memory"));
275 trace_OutOfMemory();
276 Strand_FailOpen(params);
277 return;
278 }
|
279 mike 1.1
|
280 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
281 if (s_opts.trace)
282 {
283 NoOpRsp_Print(rsp, stdout);
284 }
285 #endif
|
286 mike 1.1
|
287 krisbash 1.4 Strand_Ack( strand ); // Ack open msg
288 Strand_Post( strand, &rsp->base );
289 Strand_Close( strand );
290 Strand_Leave( strand);
291
292 NoOpRsp_Release(rsp);
293
294 trace_ServerReceivedNoOpReqTag( (int)s_opts.terminateByNoop );
295
296 if (s_opts.terminateByNoop)
297 {
298 s_data.terminated = MI_TRUE;
299 Selector_StopRunning(&s_data.selector);
300 }
301 }
|
302 mike 1.1
|
303 krisbash 1.4 /* Called by protocol stack to dispatch an incoming request message */
304 static void _RequestCallback(
305 _Inout_ InteractionOpenParams* interactionParams )
306 {
307 ServerCallbackData* self = (ServerCallbackData*)interactionParams->callbackData;
308 Message* msg = interactionParams->msg;
309 MI_Result result;
310
311 DEBUG_ASSERT( NULL != interactionParams );
312 DEBUG_ASSERT( NULL != msg );
313
314 if (NoOpReqTag == msg->tag)
315 {
316 _ProcessNoopRequest( interactionParams );
317 return;
|
318 mike 1.1 }
319
|
320 krisbash 1.4 #if 1 // !defined(CONFIG_FAVORSIZE)
|
321 mike 1.1 if (s_opts.trace)
322 {
323 MessagePrint(msg, stdout);
324 }
|
325 krisbash 1.4 #endif
|
326 mike 1.1
|
327 krisbash 1.4 result = Disp_HandleInteractionRequest(
328 &self->data->disp,
329 interactionParams );
330 if( result != MI_RESULT_OK )
|
331 mike 1.1 {
|
332 krisbash 1.4 Strand_FailOpenWithResult(interactionParams, result, PostResultMsg_NewAndSerialize);
|
333 mike 1.1 }
334 }
|
335 krisbash 1.4
|
336 mike 1.1 static void GetCommandLineDestDirOption(
337 int* argc_,
338 const char* argv[])
339 {
340 int argc = *argc_;
341 int i;
342 const char* destdir = NULL;
343
344 for (i = 1; i < argc; )
345 {
346 if (strcmp(argv[i], "--destdir") == 0)
347 {
348 if (i + 1 == argc)
|
349 krisbash 1.4 err(ZT("missing argument for --destdir option"));
|
350 mike 1.1
351 destdir = argv[i+1];
352 memmove((char*)&argv[i], (char*)&argv[i+2],
353 sizeof(char*) * (argc-i-1));
354 argc -= 2;
355 }
356 else if (strncmp(argv[i], "--destdir=", 10) == 0)
357 {
358 destdir = argv[i] + 10;
359 memmove((char*)&argv[i], (char*)&argv[i+1],
360 sizeof(char*) * (argc-i));
361
362 argc -= 1;
363 }
364 else
365 i++;
366 }
367
368 if (destdir)
369 {
370 if (SetPath(ID_DESTDIR, destdir) != 0)
|
371 krisbash 1.4 err(ZT("failed to set destdir"));
|
372 mike 1.1 }
373
374 *argc_ = argc;
375 }
376
377 static void GetCommandLineOptions(
378 int* argc_,
379 const char* argv[])
380 {
381 int argc = *argc_;
382 GetOptState state = GETOPTSTATE_INITIALIZER;
383 static const char* opts[] =
384 {
385 "-h",
386 "--help",
387 "-p",
388 "-t",
|
389 mike 1.2 "--httptrace",
|
390 krisbash 1.4 "--timestamp",
|
391 mike 1.1 "--stopnoop",
392 "-v",
393 "--version",
394 "-d",
395 "-s",
396 "-r",
397 "--httpport:",
398 "--httpsport:",
399 "--idletimeout:",
400 "--livetime:",
401 "--ignoreAuthentication",
402 "-i",
403 "--prefix:",
404 "--libdir:",
405 "--bindir:",
406 "--localstatedir:",
407 "--sysconfdir:",
408 "--providerdir:",
|
409 krisbash 1.4 "--registerdir:",
|
410 mike 1.1 "--certsdir:",
411 "--rundir:",
412 "--logdir:",
413 "--pidfile:",
414 "--logfile:",
|
415 krisbash 1.4 "--configfile:",
|
416 mike 1.1 "--socketfile:",
417 "--pemfile:",
418 "--keyfile:",
419 "--agentprogram:",
420 "--serverprogram:",
421 "--logstderr",
422 "--loglevel:",
423 "-l",
|
424 krisbash 1.4 "--testopts",
|
425 mike 1.1 NULL,
426 };
427
428 for (;;)
429 {
430 int r = GetOpt(&argc, argv, opts, &state);
431
432 if (r == 1)
433 break;
434
435 if (r == -1)
436 {
|
437 krisbash 1.4 Ftprintf(stderr, ZT("error: %s\n"), scs(state.err));
|
438 mike 1.1 exit(1);
439 }
440
441 if (strcmp(state.opt, "-h") == 0 ||
442 strcmp(state.opt, "--help") == 0)
443 {
444 s_opts.help = MI_TRUE;
445 }
446 else if (strcmp(state.opt, "-p") == 0)
447 {
448 s_opts.locations = MI_TRUE;
449 }
|
450 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
|
451 mike 1.1 else if (strcmp(state.opt, "-t") == 0)
452 {
453 s_opts.trace = MI_TRUE;
454 }
|
455 krisbash 1.4 #endif
|
456 mike 1.2 else if (strcmp(state.opt, "--httptrace") == 0)
457 {
458 s_opts.httptrace = MI_TRUE;
459 }
|
460 krisbash 1.4 else if (strcmp(state.opt, "--timestamp") == 0)
461 {
462 #if defined(CONFIG_OS_WINDOWS)
463 Tprintf(PAL_T("%s: %T\n"), scs(arg0), tcs(CONFIG_TIMESTAMP));
464 #else
465 Tprintf(ZT("%s: %s\n"), scs(arg0), scs(CONFIG_TIMESTAMP));
466 #endif
467 exit(0);
468 }
|
469 mike 1.1 else if (strcmp(state.opt, "--stopnoop") == 0)
470 {
471 s_opts.terminateByNoop = MI_TRUE;
472 }
473 else if (strcmp(state.opt, "-v") == 0 ||
474 strcmp(state.opt, "--version") == 0)
475 {
|
476 krisbash 1.4 #if defined(CONFIG_OS_WINDOWS)
477 Tprintf(PAL_T("%s: %T\n"), scs(arg0),
478 tcs(CONFIG_PRODUCT PAL_T("-") CONFIG_VERSION PAL_T(" - ") CONFIG_DATE));
479 #else
480 Tprintf(ZT("%s: %s\n"), scs(arg0),
481 scs(CONFIG_PRODUCT "-" CONFIG_VERSION " - " CONFIG_DATE));
482 #endif
|
483 mike 1.1 exit(0);
484 }
485 #if defined(CONFIG_POSIX)
486 else if (strcmp(state.opt, "-d") == 0)
487 {
488 s_opts.daemonize = MI_TRUE;
489 }
490 else if (strcmp(state.opt, "-s") == 0)
491 {
492 s_opts.stop = MI_TRUE;
493 }
494 else if (strcmp(state.opt, "-r") == 0)
495 {
496 s_opts.reloadConfig = MI_TRUE;
497 }
498 #endif
499 else if (strcmp(state.opt, "--httpport") == 0)
500 {
501 unsigned long x;
|
502 krisbash 1.4 char* end = 0;
|
503 mike 1.1
504 x = Strtoul(state.arg, &end, 10);
505
506 if (*end != '\0' || x > USHRT_MAX)
|
507 krisbash 1.4 {
508 err(ZT("bad option argument for --httpport: %s"),
509 scs(state.arg));
510 }
|
511 mike 1.1
512 s_opts.httpport = (unsigned short)x;
513 }
514 else if (strcmp(state.opt, "--httpsport") == 0)
515 {
516 unsigned long x;
517 char* end;
518
519 x = Strtoul(state.arg, &end, 10);
520
521 if (*end != '\0' || x > USHRT_MAX)
|
522 krisbash 1.4 {
523 err(ZT("bad option argument for --httpsport: %s"),
524 scs(state.arg));
525 }
|
526 mike 1.1
527 s_opts.httpsport = (unsigned short)x;
528 }
529 else if (strcmp(state.opt, "--idletimeout") == 0)
530 {
531 char* end;
532 MI_Uint64 x = Strtoull(state.arg, &end, 10);
533
534 if (*end != '\0')
|
535 krisbash 1.4 {
536 err(ZT("bad option argument for --idletimeout: %s"),
537 scs(state.arg));
538 }
|
539 mike 1.1
540 s_opts.idletimeout = x;
541 }
542 else if (strcmp(state.opt, "--livetime") == 0)
543 {
544 char* end;
545 MI_Uint64 x = Strtoull(state.arg, &end, 10);
546
547 if (*end != '\0')
|
548 krisbash 1.4 {
549 err(ZT("bad option argument for --livetime: %s"),
550 scs(state.arg));
551 }
|
552 mike 1.1
553 s_opts.livetime = x;
554 }
555 else if (strcmp(state.opt, "--ignoreAuthentication") == 0 ||
556 strcmp(state.opt, "-i") == 0)
557 {
558 s_opts.ignoreAuthentication = MI_TRUE;
559 }
560 else if (strcmp(state.opt, "--logstderr") == 0 ||
561 strcmp(state.opt, "-l") == 0)
562 {
563 s_opts.logstderr = MI_TRUE;
564 }
565 else if (strcmp(state.opt, "--loglevel") == 0)
566 {
567 if (Log_SetLevelFromString(state.arg) != 0)
568 {
|
569 krisbash 1.4 err(ZT("bad option argument for %s: %s"),
570 scs(state.opt), scs(state.arg));
571 }
572 }
573 else if (strcmp(state.opt, "--testopts") == 0)
574 {
575 s_opts.httptrace = MI_TRUE;
576
577 if (Log_SetLevelFromString("DEBUG") != 0)
578 {
579 err(ZT("bad argument for Log_SetLevelFromString()"));
|
580 mike 1.1 }
581 }
582 else if (strncmp(state.opt, "--", 2) == 0 && IsNickname(state.opt+2))
583 {
584 if (SetPathFromNickname(state.opt+2, state.arg) != 0)
|
585 krisbash 1.4 err(ZT("SetPathFromNickname() failed"));
|
586 mike 1.1 }
587 }
588
589 *argc_ = argc;
590 }
591
592 static void OpenLogFile()
593 {
594 if (s_opts.logstderr)
595 {
596 if (Log_OpenStdErr() != MI_RESULT_OK)
|
597 krisbash 1.4 err(ZT("failed to open log file to stderr"));
|
598 mike 1.1 }
599 else
600 {
|
601 krisbash 1.4 TChar path[PAL_MAX_PATH_SIZE];
602 TcsStrlcpy(path, OMI_GetPath(ID_LOGFILE), MI_COUNT(path));
|
603 mike 1.1
604 /* Open the log file */
605 if (Log_Open(path) != MI_RESULT_OK)
|
606 krisbash 1.4 err(PAL_T("failed to open log file: %T"), tcs(path));
|
607 mike 1.1 }
608 }
609
610 #if defined(CONFIG_POSIX)
|
611 krisbash 1.4
|
612 mike 1.1 static void _HandleSIGTERM(int sig)
613 {
614 if (sig == SIGTERM && s_data.selectorInitialized)
615 {
|
616 krisbash 1.4 const char* socketFile = OMI_GetPath(ID_SOCKETFILE);
|
617 mike 1.1 s_data.terminated = MI_TRUE;
618 Selector_StopRunning(&s_data.selector);
|
619 krisbash 1.4 if (socketFile != NULL && *socketFile != '\0')
620 unlink(socketFile);
|
621 mike 1.1 }
622 }
623
624 static void _HandleSIGHUP(int sig)
625 {
626 if (sig == SIGHUP && s_data.selectorInitialized)
627 {
628 Selector_StopRunning(&s_data.selector);
629 }
630 }
631
|
632 krisbash 1.4 /* An array of PIDS that abnormally exited */
633 #define NPIDS 16
634 static pid_t _pids[NPIDS];
635 static volatile size_t _npids;
636
|
637 mike 1.1 static void _HandleSIGCHLD(int sig)
638 {
639 if (sig == SIGCHLD)
640 {
|
641 krisbash 1.4 for (;;)
642 {
643 int status = 0;
644 pid_t pid = waitpid(-1, &status, WNOHANG);
645
646 /* If abnormal exit, append to PIDs array */
647 if (pid > 0 && !WIFEXITED(status))
648 {
649 /* Save PID so error can be logged outside this function */
650 if (_npids < NPIDS)
651 _pids[_npids++] = pid;
652 }
653
654 if (pid > 0 || (pid == -1 && errno == EINTR))
655 continue;
656
657 break;
658 }
|
659 mike 1.1 }
660 }
|
661 krisbash 1.4
662 #endif /* defined(CONFIG_POSIX) */
|
663 mike 1.1
664 static void _PrintPaths()
665 {
666 PrintPaths();
667 }
668
669 static void GetConfigFileOptions()
670 {
|
671 krisbash 1.4 char path[PAL_MAX_PATH_SIZE];
|
672 mike 1.1 Conf* conf;
673
674 /* Form the configuration file path */
|
675 krisbash 1.4 Strlcpy(path, OMI_GetPath(ID_CONFIGFILE), sizeof(path));
|
676 mike 1.1
677 /* Open the configuration file */
678 conf = Conf_Open(path);
679 if (!conf)
|
680 krisbash 1.4 err(ZT("failed to open configuration file: %s"), scs(path));
|
681 mike 1.1
682 /* For each key=value pair in configuration file */
683 for (;;)
684 {
685 const char* key;
686 const char* value;
687 int r = Conf_Read(conf, &key, &value);
688
689 if (r == -1)
|
690 krisbash 1.4 err(ZT("%s: %s\n"), path, scs(Conf_Error(conf)));
|
691 mike 1.1
692 if (r == 1)
693 break;
694
695 if (strcmp(key, "httpport") == 0)
696 {
697 char* end;
698 unsigned long x = Strtoul(value, &end, 10);
699
700 if (*end != '\0' || x > USHRT_MAX)
701 {
|
702 krisbash 1.4 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path),
703 Conf_Line(conf), scs(key), scs(value));
|
704 mike 1.1 }
705
706 s_opts.httpport = (unsigned short)x;
707 }
708 else if (strcmp(key, "httpsport") == 0)
709 {
710 char* end;
711 unsigned long x = Strtoul(value, &end, 10);
712
713 if (*end != '\0' || x > USHRT_MAX)
714 {
|
715 krisbash 1.4 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path),
716 Conf_Line(conf), scs(key), scs(value));
|
717 mike 1.1 }
718
719 s_opts.httpsport = (unsigned short)x;
720 }
721 else if (strcmp(key, "idletimeout") == 0)
722 {
723 char* end;
724 MI_Uint64 x = Strtoull(value, &end, 10);
725
726 if (*end != '\0')
727 {
|
728 krisbash 1.4 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path),
729 Conf_Line(conf), scs(key), scs(value));
|
730 mike 1.1 }
731
732 s_opts.idletimeout = x;
733 }
734 else if (strcmp(key, "livetime") == 0)
735 {
736 char* end;
737 MI_Uint64 x = Strtoull(value, &end, 10);
738
739 if (*end != '\0')
740 {
|
741 krisbash 1.4 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path),
742 Conf_Line(conf), scs(key), scs(value));
|
743 mike 1.1 }
744
745 s_opts.livetime = x;
746 }
747 else if (strcmp(key, "trace") == 0)
748 {
749 if (Strcasecmp(value, "true") == 0)
750 {
|
751 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
|
752 mike 1.1 s_opts.trace = MI_TRUE;
|
753 krisbash 1.4 #endif
|
754 mike 1.1 }
755 else if (Strcasecmp(value, "false") == 0)
756 {
|
757 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
|
758 mike 1.1 s_opts.trace = MI_FALSE;
|
759 krisbash 1.4 #endif
|
760 mike 1.1 }
761 else
762 {
|
763 krisbash 1.4 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path),
764 Conf_Line(conf), scs(key), scs(value));
|
765 mike 1.1 }
766 }
|
767 mike 1.2 else if (strcmp(key, "httptrace") == 0)
768 {
769 if (Strcasecmp(value, "true") == 0)
770 {
771 s_opts.httptrace = MI_TRUE;
772 }
773 else if (Strcasecmp(value, "false") == 0)
774 {
775 s_opts.httptrace = MI_FALSE;
776 }
777 else
778 {
|
779 krisbash 1.4 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path),
780 Conf_Line(conf), scs(key), scs(value));
781 }
782 }
783 else if (strcmp(key, "loglevel") == 0)
784 {
785 if (Log_SetLevelFromString(value) != 0)
786 {
787 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path),
788 Conf_Line(conf), scs(key), scs(value));
789 }
790 }
791 else if (strcmp(key, "sslciphersuite") == 0)
792 {
793 size_t valueLength = strlen(value);
794 s_opts.sslCipherSuite = PAL_Malloc(valueLength + 1);
795 if (s_opts.sslCipherSuite == NULL)
796 err(ZT("Out of memory"));
797 Strlcpy(s_opts.sslCipherSuite, value, valueLength+1);
798 s_opts.sslCipherSuite[valueLength] = '\0';
799 }
800 krisbash 1.4 else if (Strcasecmp(key, "NoSSLv2") == 0)
801 {
802 if (Strcasecmp(value, "true") == 0)
803 {
804 s_opts.sslOptions |= DISABLE_SSL_V2;
805 }
806 else if (Strcasecmp(value, "false") != 0)
807 {
808 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path),
809 Conf_Line(conf), scs(key), scs(value));
810 }
811 }
812 else if (Strcasecmp(key, "NoSSLv3") == 0)
813 {
814 if (Strcasecmp(value, "true") == 0)
815 {
816 s_opts.sslOptions |= DISABLE_SSL_V3;
817 }
818 else if (Strcasecmp(value, "false") != 0)
819 {
820 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path),
821 krisbash 1.4 Conf_Line(conf), scs(key), scs(value));
|
822 mike 1.2 }
823 }
|
824 mike 1.1 else if (IsNickname(key))
825 {
826 if (SetPathFromNickname(key, value) != 0)
|
827 krisbash 1.4 err(ZT("SetPathFromNickname() failed"));
|
828 mike 1.1 }
829 else
830 {
|
831 krisbash 1.4 err(ZT("%s(%u): unknown key: %s"), scs(path), Conf_Line(conf),
832 scs(key));
|
833 mike 1.1 }
834 }
835
836 /* Close configuration file */
837 Conf_Close(conf);
838
839 return;
840 }
841
842 int servermain(int argc, const char* argv[])
843 {
844 MI_Result r;
845 #if defined(CONFIG_POSIX)
846 int pidfile = -1;
847 #endif
848
849 arg0 = argv[0];
850
851 memset(&s_data, 0, sizeof(s_data));
852
853 /* Set default options */
854 mike 1.1 s_opts.httpport = CONFIG_HTTPPORT;
855 s_opts.httpsport = CONFIG_HTTPSPORT;
856 s_opts.idletimeout = 0;
857 s_opts.livetime = 0;
858
859 /* Get --destdir command-line option */
860 GetCommandLineDestDirOption(&argc, argv);
861
862 /* Extract configuration file options */
863 GetConfigFileOptions();
864
865 /* Extract command-line options a second time (to override) */
866 GetCommandLineOptions(&argc, argv);
867
868 /* Open the log file */
869 OpenLogFile();
870
871 /* Print help */
872 if (s_opts.help)
873 {
|
874 krisbash 1.4 Ftprintf(stderr, HELP, scs(arg0));
|
875 mike 1.1 exit(1);
876 }
877
878 /* Print locations of files and directories */
879 if (s_opts.locations)
880 {
881 _PrintPaths();
|
882 krisbash 1.4 Tprintf(ZT("\n"));
|
883 mike 1.1 exit(0);
884 }
885
886 #if defined(CONFIG_POSIX)
887 if (s_opts.stop || s_opts.reloadConfig)
888 {
889 if (PIDFile_IsRunning() != 0)
|
890 krisbash 1.4 info_exit(ZT("server is not running\n"));
|
891 mike 1.1
892 if (PIDFile_Signal(s_opts.stop ? SIGTERM : SIGHUP) != 0)
|
893 krisbash 1.4 err(ZT("failed to stop server\n"));
|
894 mike 1.1
895 if (s_opts.stop)
|
896 krisbash 1.4 Tprintf(ZT("%s: stopped server\n"), scs(arg0));
|
897 mike 1.1 else
|
898 krisbash 1.4 Tprintf(ZT("%s: refreshed server\n"), scs(arg0));
|
899 mike 1.1
900 exit(0);
901 }
902 #endif
903
904 #if defined(CONFIG_POSIX)
905
906 if (PIDFile_IsRunning() == 0)
|
907 krisbash 1.4 err(ZT("server is already running\n"));
|
908 mike 1.1
909 /* Verify that server is started as root */
910 if (0 != IsRoot() && !s_opts.ignoreAuthentication)
911 {
|
912 krisbash 1.4 err(ZT("expected to run as root"));
|
913 mike 1.1 }
914
915 /* ATTN: unit-test support; should be removed/ifdefed later */
916 if (s_opts.ignoreAuthentication)
917 {
918 IgnoreAuthCalls(1);
919 }
920
921 /* Watch for SIGTERM signals */
922 if (0 != SetSignalHandler(SIGTERM, _HandleSIGTERM) ||
923 0 != SetSignalHandler(SIGHUP, _HandleSIGHUP))
|
924 krisbash 1.4 err(ZT("cannot set sighanlder, erron %d"), errno);
|
925 mike 1.1
926
927 /* Watch for SIGCHLD signals */
928 SetSignalHandler(SIGCHLD, _HandleSIGCHLD);
929
930 #endif
931
932 /* Change directory to 'rundir' */
|
933 krisbash 1.4 if (Chdir(OMI_GetPath(ID_RUNDIR)) != 0)
934 {
935 err(ZT("failed to change directory to: %s"),
936 scs(OMI_GetPath(ID_RUNDIR)));
937 }
|
938 mike 1.1
939 #if defined(CONFIG_POSIX)
940 /* Daemonize */
941 if (s_opts.daemonize && Process_Daemonize() != 0)
|
942 krisbash 1.4 err(ZT("failed to daemonize server process"));
|
943 mike 1.1 #endif
944
945 #if defined(CONFIG_POSIX)
946
947 /* Create PID file */
948 if ((pidfile = PIDFile_OpenWrite()) == -1)
949 {
|
950 krisbash 1.4 trace_CreatePIDFileFailed( scs(OMI_GetPath(ID_PIDFILE)) );
|
951 mike 1.1 exit(1);
952 }
|
953 krisbash 1.4
|
954 mike 1.1 #endif
955
956 /* Initialize calback parameters */
957 s_data.protocolData.data = &s_data;
958 s_data.protocolData.type = SRV_PROTOCOL;
959 s_data.wsmanData.data = &s_data;
960 s_data.wsmanData.type = SRV_WSMAN;
961
962 while (!s_data.terminated)
963 {
964 /* selector */
965 {
966 /* Initialize the network */
967 Sock_Start();
968
969 if(Selector_Init(&s_data.selector) != MI_RESULT_OK)
|
970 krisbash 1.4 err(ZT("Selector_Init() failed"));
|
971 mike 1.1
972 s_data.selectorInitialized = MI_TRUE;
|
973 krisbash 1.4
974 Timer_SetSelector(&s_data.selector);
|
975 mike 1.1 }
976
977 /* Create the dispatcher object. */
978 {
979 r = Disp_Init(&s_data.disp, &s_data.selector);
980
981 if (r != MI_RESULT_OK)
982 {
|
983 krisbash 1.4 trace_DispatchInitFailed(r);
984 err(ZT("failed to initialize the dispatcher: %u"), r);
|
985 mike 1.1 }
986 }
987
988 if (s_opts.idletimeout)
989 {
990 /* convert it to usec */
991 s_data.disp.agentmgr.provmgr.idleTimeoutUsec = s_opts.idletimeout * 1000000;
992 }
993
|
994 krisbash 1.4 /* Set WSMAN options and create WSMAN server */
|
995 mike 1.1 {
|
996 krisbash 1.4 WSMAN_Options options = DEFAULT_WSMAN_OPTIONS;
997 #if !defined(CONFIG_FAVORSIZE)
998 options.enableTracing = s_opts.trace;
999 #endif
1000 options.enableHTTPTracing = s_opts.httptrace;
1001
|
1002 mike 1.1 r = WSMAN_New_Listener(
1003 &s_data.wsman,
1004 &s_data.selector,
1005 s_opts.httpport,
1006 s_opts.httpsport,
|
1007 krisbash 1.4 s_opts.sslCipherSuite,
1008 s_opts.sslOptions,
1009 _RequestCallback,
1010 &s_data.wsmanData,
1011 &options);
|
1012 mike 1.1
1013 if (r != MI_RESULT_OK)
|
1014 krisbash 1.4 err(ZT("WSMAN_New_Listener() failed"));
|
1015 mike 1.1 }
1016
|
1017 krisbash 1.4 /* mux */
|
1018 mike 1.1 {
|
1019 krisbash 1.4 if(MuxIn_Init(&s_data.mux, _RequestCallback, &s_data.protocolData, NULL, PostResultMsg_NewAndSerialize) != MI_RESULT_OK)
1020 err(ZT("MuxIn_Init() failed"));
|
1021 mike 1.1 }
|
1022 krisbash 1.4
|
1023 mike 1.1 /* Create new protocol object */
1024 {
|
1025 krisbash 1.4 r = ProtocolBase_New_Listener(
1026 &s_data.protocol,
1027 &s_data.selector,
1028 OMI_GetPath(ID_SOCKETFILE),
1029 MuxIn_Open,
1030 &s_data.mux);
|
1031 mike 1.1
1032 if (r != MI_RESULT_OK)
|
1033 krisbash 1.4 err(ZT("Protocol_New_Listener() failed"));
|
1034 mike 1.1 }
1035
1036 /* Log start up message */
|
1037 krisbash 1.4 trace_ListeningOnPorts(s_opts.httpport, s_opts.httpsport);
|
1038 mike 1.1
1039 /* Run the protocol object (waiting for new messages) */
|
1040 krisbash 1.4 {
1041 const PAL_Uint64 ONE_SECOND_USEC = 1000 * 1000;
1042 PAL_Uint64 start;
1043 PAL_Uint64 finish;
|
1044 mike 1.1
|
1045 krisbash 1.4 PAL_Time(&start);
1046
1047 if (s_opts.livetime)
1048 finish = start + (s_opts.livetime * ONE_SECOND_USEC);
1049 else
1050 finish = 0;
1051
1052 for (;;)
1053 {
1054 PAL_Uint64 now;
1055
1056 r = Protocol_Run(s_data.protocol, ONE_SECOND_USEC);
1057
1058 if (r != MI_RESULT_TIME_OUT)
1059 break;
1060
1061 PAL_Time(&now);
1062
1063 /* Log abnormally terminated terminated process */
1064 {
1065 size_t i;
1066 krisbash 1.4
1067 for (i = 0; i < _npids; i++)
1068 trace_ChildProcessTerminatedAbnormally(_pids[i]);
1069
1070 _npids = 0;
1071 }
1072
1073 if (finish && now > finish)
1074 break;
1075 }
1076 }
1077
1078 trace_Server_ProtocolRun(r);
|
1079 mike 1.1
1080 s_data.selectorInitialized = MI_FALSE;
1081
1082 if (MI_RESULT_TIME_OUT == r)
1083 {
|
1084 krisbash 1.4 trace_Server_LiveTimeExpired();
|
1085 mike 1.1 s_data.terminated = MI_TRUE;
1086 }
1087
1088 #if defined(CONFIG_POSIX)
1089 if (r == MI_RESULT_OK)
1090 {
1091 if (s_data.terminated)
|
1092 krisbash 1.4 trace_ServerTerminated();
|
1093 mike 1.1 else
|
1094 krisbash 1.4 trace_ServerReReadingConfig();
|
1095 mike 1.1 }
1096 #endif
1097
1098 // Destroy the dispatcher.
1099 Selector_RemoveAllHandlers(&s_data.selector);
1100 Disp_Destroy(&s_data.disp);
1101 WSMAN_Delete(s_data.wsman);
|
1102 krisbash 1.4 ProtocolBase_Delete(s_data.protocol);
|
1103 mike 1.1 Selector_Destroy(&s_data.selector);
1104
1105 /* Shutdown the network */
1106 Sock_Stop();
1107 }
1108
1109 #if defined(CONFIG_POSIX)
1110 /* Close PID file */
1111 close(pidfile);
1112
1113 /* Remove PID file */
1114 if (PIDFile_Delete() != 0)
|
1115 krisbash 1.4 {
1116 trace_FailedRemovePIDFile(scs(OMI_GetPath(ID_PIDFILE)));
1117 }
|
1118 mike 1.1 #endif
1119
1120 /* Log that we are exiting */
|
1121 krisbash 1.4 trace_ServerExiting();
|
1122 mike 1.1
1123 Log_Close();
|
1124 krisbash 1.4
1125 #if defined(USE_ALLOCATOR)
1126
1127 # if defined(USE_PAL_ATEXIT)
1128 PAL_AtexitCall();
1129 # endif
1130
1131 PAL_DumpAllocStats();
1132
1133 if (PAL_GetBlocksAllocated())
1134 {
1135 printf("WARNING: %s: server has unfreed blocks on exit\n", arg0);
1136 PAL_DumpAllocList();
1137 }
1138 #endif
1139
|
1140 mike 1.1 return 0;
1141 }
|