int main(int argc, char *argv[]) { _tzset(); if((gPrefs = new Prefs(argv[0])) == NULL) exit(0); if( gPrefs->LoadFromCLI(argc, argv) < 0) return(-1); gCenter = new HubCenter(); gCenter->Build(); if(gPrefs->IsDaemonize()) { Daemonize(); #ifndef WIN32 if(gPrefs->PidPath() != NULL) { FILE *fd = fopen(gPrefs->PidPath(), "w"); if(fd != NULL) { fprintf(fd, "%u\n", getpid()); fclose(fd); chmod(gPrefs->PidPath(), 0777); Trace::traceEvent(TRACE_NORMAL, "PID stored in file %s", gPrefs->PidPath()); } else Trace::traceEvent(TRACE_ERROR, "Unable to store PID in file %s", gPrefs->PidPath()); } #endif } signal(SIGINT, sigproc); signal(SIGTERM, sigproc); signal(SIGINT, sigproc); gCenter->Run(); gCenter->Cleanup(); delete gCenter; delete gPrefs; gPrefs = 0; Trace::traceEvent(TRACE_NORMAL, "main finish"); }
void handleoptions(const std::vector<std::string> &options, bool &startup) { Option option; std::string val(""); for(std::vector<std::string>::const_iterator i=options.begin(); i!=options.end(); i++) { std::string::size_type pos=(*i).find("="); if((*i).size()>3 && (*i).substr(0,2)=="--" && pos!=std::string::npos) { if(option.Get((*i).substr(2,pos-2),val)==true) { option.Set((*i).substr(2,pos-2),(*i).substr(pos+1)); startup=false; } } else { if((*i)=="--help" || (*i)=="-?" || (*i)=="/?") { showhelp(); startup=false; } if((*i)=="--daemon") { Daemonize(); global::daemon=true; } } } }
void PayguideInit() { /* Init variables from payguide namespace */ payguide::namespace_init(); ReloadConfigIfImportant(); if (curl_global_init(CURL_GLOBAL_ALL)!=0) { printf("CURL init failed! Payguide shutdown.\n"); exit(1); } /* Deatch from console */ if (payguide::daemonize==1) { if (Daemonize()!=0) { LogWrite(LOGMSG_ERROR, "Daemonize failed!"); } } my_init(); DBVeryFirstInit(); OperatorsInit(); OpenSSLInit(); StatisticInit(); /* Catching TERM signal - shut down server */ struct sigaction sterm; memset (&sterm, 0, sizeof(sterm)); sterm.sa_handler=&SigHandler; sigaction(SIGTERM, &sterm, NULL); /* Catching INT signal - shut down server */ struct sigaction sint; memset (&sint, 0, sizeof(sint)); sint.sa_handler=&SigHandler; sigaction(SIGINT, &sint, NULL); atexit (CleanUp); /* Init backtrace */ #ifdef ENABLE_BACKTRACE open_backtrace_fd(payguide::backtrace_file.c_str()); install_handlers() ; #endif }
/// Activated the stored config. This will: /// - Drop permissions to the stored "username", if any. /// - Daemonize the process if "daemonize" exists and is true. /// - Set is_active to true. /// - Set up a signal handler to set is_active to false for the SIGINT, SIGHUP and SIGTERM signals. void Util::Config::activate(){ if (vals.isMember("username")){ setUser(getString("username")); } if (vals.isMember("daemonize") && getBool("daemonize")){ Daemonize(); } struct sigaction new_action; new_action.sa_handler = signal_handler; sigemptyset( &new_action.sa_mask); new_action.sa_flags = 0; sigaction(SIGINT, &new_action, NULL); sigaction(SIGHUP, &new_action, NULL); sigaction(SIGTERM, &new_action, NULL); sigaction(SIGPIPE, &new_action, NULL); sigaction(SIGCHLD, &new_action, NULL); is_active = true; }
bool VDaemon::Init(VProcess::InitOptions inOptions) { if (!fInitCalled) { if (inherited::Init( inOptions)) { fInitCalled = true; fImpl = new XDaemonImpl( this); if (fImpl != NULL) fInitOK = fImpl->Init(); } } #if WITH_DAEMONIZE if (fInitOK && IsDaemon()) fInitOK = (VE_OK == Daemonize()); #endif return fInitOK; }
void svServer::Start(void) { CreateSockets(); CreateVpnClientThreads(); SwitchUserGroup(); Daemonize(); SaveProcessId(); StartSignalHandler(); LoadKeyRing(); CreateStorageThreads(); svEvent *event; for ( ;; ) { while ((event = PopEvent())) { switch (event->GetId()) { case svEVT_QUIT: return; case svEVT_KEYRING_REQUEST: KeyRingRequest((svEventKeyRingRequest *)event); break; case svEVT_HOSTKEY_REQUEST: HostKeyRequest((svEventHostKeyRequest *)event); break; case svEVT_HOSTKEY_RESULT: HostKeyResult((svEventHostKeyResult *)event); break; case svEVT_POOLCLIENT_SAVE: PoolClientSave((svEventPoolClientSave *)event); break; case svEVT_POOLCLIENT_LOAD: PoolClientLoad((svEventPoolClientLoad *)event); break; default: ProcessEvent(event); } delete event; } SelectSockets(); } }
/* * Main */ int main(int argc, char* argv[]) { GetOpts(argc, argv); Fork(); SetProcessFlags(); rand_initialize(); DeviceInit(); FdInit(); AttachPrefix("/dev/random", UNIT_RANDOM); AttachPrefix("/dev/urandom", UNIT_URANDOM); HookIrqs(); Daemonize(); return Loop(); }
//============================================================================= bool Metaserver::Initialize(char *binaryName) { struct sockaddr_in servaddr; if(mDaemon) Daemonize(binaryName, LOG_DAEMON); mSigalrmHandler = new SIGALRMHandler; mSigintHandler = new SIGINTHandler; SignalManager::GetInstance().RegisterHandler(SIGINT, mSigintHandler); mListenSocket = socket(AF_INET, SOCK_DGRAM, 0); memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; memcpy(&servaddr.sin_addr, &mBindAddress, sizeof(struct in_addr)); servaddr.sin_port = htons(mListenPort); if(bind(mListenSocket, (SA *)&servaddr, sizeof(servaddr))) return false; else return true; }
int main(int argc, char **argv) { int opt; char *pcap_file = NULL; char pcap_dev[128]; #ifdef HAVE_PFRING char *pfring_dev = NULL; #endif char *sig_file = NULL; char *nfq_id = NULL; char *conf_filename = NULL; char *pid_filename = NULL; #ifdef UNITTESTS char *regex_arg = NULL; #endif int dump_config = 0; int list_unittests = 0; int list_cuda_cards = 0; int daemon = 0; char *user_name = NULL; char *group_name = NULL; uint8_t do_setuid = FALSE; uint8_t do_setgid = FALSE; uint32_t userid = 0; uint32_t groupid = 0; char *erf_file = NULL; char *dag_input = NULL; char *log_dir; struct stat buf; sc_set_caps = FALSE; SC_ATOMIC_INIT(engine_stage); /* initialize the logging subsys */ SCLogInitLogModule(NULL); /* By default use IDS mode, but if nfq or ipfw * are specified, IPS mode will overwrite this */ SET_ENGINE_MODE_IDS(engine_mode); #ifdef OS_WIN32 /* service initialization */ if (SCRunningAsService()) { char path[MAX_PATH]; char *p = NULL; strlcpy(path, argv[0], MAX_PATH); if ((p = strrchr(path, '\\'))) { *p = '\0'; } if (!SetCurrentDirectory(path)) { SCLogError(SC_ERR_FATAL, "Can't set current directory to: %s", path); return -1; } SCLogInfo("Current directory is set to: %s", path); daemon = 1; SCServiceInit(argc, argv); } /* Windows socket subsystem initialization */ WSADATA wsaData; if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)) { SCLogError(SC_ERR_FATAL, "Can't initialize Windows sockets: %d", WSAGetLastError()); exit(EXIT_FAILURE); } #endif /* OS_WIN32 */ #ifdef REVISION SCLogInfo("This is %s version %s (rev %s)", PROG_NAME, PROG_VER, xstr(REVISION)); #else SCLogInfo("This is %s version %s", PROG_NAME, PROG_VER); #endif /* Initialize the configuration module. */ ConfInit(); struct option long_opts[] = { {"dump-config", 0, &dump_config, 1}, {"pfring-int", required_argument, 0, 0}, {"pfring-cluster-id", required_argument, 0, 0}, {"pfring-cluster-type", required_argument, 0, 0}, {"pcap-buffer-size", required_argument, 0, 0}, {"unittest-filter", required_argument, 0, 'U'}, {"list-unittests", 0, &list_unittests, 1}, {"list-cuda-cards", 0, &list_cuda_cards, 1}, {"engine-analysis", 0, &engine_analysis, 1}, #ifdef OS_WIN32 {"service-install", 0, 0, 0}, {"service-remove", 0, 0, 0}, {"service-change-params", 0, 0, 0}, #endif /* OS_WIN32 */ {"pidfile", required_argument, 0, 0}, {"init-errors-fatal", 0, 0, 0}, {"fatal-unittests", 0, 0, 0}, {"user", required_argument, 0, 0}, {"group", required_argument, 0, 0}, {"erf-in", required_argument, 0, 0}, {"dag", required_argument, 0, 0}, {NULL, 0, NULL, 0} }; /* getopt_long stores the option index here. */ int option_index = 0; char short_opts[] = "c:Dhi:l:q:d:r:us:U:V"; while ((opt = getopt_long(argc, argv, short_opts, long_opts, &option_index)) != -1) { switch (opt) { case 0: if(strcmp((long_opts[option_index]).name , "pfring-int") == 0){ #ifdef HAVE_PFRING run_mode = MODE_PFRING; if (ConfSet("pfring.interface", optarg, 0) != 1) { fprintf(stderr, "ERROR: Failed to set pfring interface.\n"); exit(EXIT_FAILURE); } #else SCLogError(SC_ERR_NO_PF_RING,"PF_RING not enabled. Make sure to pass --enable-pfring to configure when building."); exit(EXIT_FAILURE); #endif /* HAVE_PFRING */ } else if(strcmp((long_opts[option_index]).name , "pfring-cluster-id") == 0){ #ifdef HAVE_PFRING if (ConfSet("pfring.cluster-id", optarg, 0) != 1) { fprintf(stderr, "ERROR: Failed to set pfring cluster-id.\n"); exit(EXIT_FAILURE); } #else SCLogError(SC_ERR_NO_PF_RING,"PF_RING not enabled. Make sure to pass --enable-pfring to configure when building."); exit(EXIT_FAILURE); #endif /* HAVE_PFRING */ } else if(strcmp((long_opts[option_index]).name , "pfring-cluster-type") == 0){ #ifdef HAVE_PFRING if (ConfSet("pfring.cluster-type", optarg, 0) != 1) { fprintf(stderr, "ERROR: Failed to set pfring cluster-type.\n"); exit(EXIT_FAILURE); } #else SCLogError(SC_ERR_NO_PF_RING,"PF_RING not enabled. Make sure to pass --enable-pfring to configure when building."); exit(EXIT_FAILURE); #endif /* HAVE_PFRING */ } else if(strcmp((long_opts[option_index]).name, "init-errors-fatal") == 0) { if (ConfSet("engine.init_failure_fatal", "1", 0) != 1) { fprintf(stderr, "ERROR: Failed to set engine init_failure_fatal.\n"); exit(EXIT_FAILURE); } } else if(strcmp((long_opts[option_index]).name, "list-unittests") == 0) { #ifdef UNITTESTS /* Set run_mode to unit tests. */ run_mode = MODE_UNITTEST; #else fprintf(stderr, "ERROR: Unit tests not enabled. Make sure to pass --enable-unittests to configure when building.\n"); exit(EXIT_FAILURE); #endif /* UNITTESTS */ } else if(strcmp((long_opts[option_index]).name, "list-cuda-cards") == 0) { #ifndef __SC_CUDA_SUPPORT__ fprintf(stderr, "ERROR: Cuda not enabled. Make sure to pass " "--enable-cuda to configure when building.\n"); exit(EXIT_FAILURE); #endif /* UNITTESTS */ } else if(strcmp((long_opts[option_index]).name, "engine-analysis") == 0) { // do nothing for now } #ifdef OS_WIN32 else if(strcmp((long_opts[option_index]).name, "service-install") == 0) { if (SCServiceInstall(argc, argv)) { exit(EXIT_FAILURE); } SCLogInfo("Suricata service has been successfuly installed."); exit(EXIT_SUCCESS); } else if(strcmp((long_opts[option_index]).name, "service-remove") == 0) { if (SCServiceRemove(argc, argv)) { exit(EXIT_FAILURE); } SCLogInfo("Suricata service has been successfuly removed."); exit(EXIT_SUCCESS); } else if(strcmp((long_opts[option_index]).name, "service-change-params") == 0) { if (SCServiceChangeParams(argc, argv)) { exit(EXIT_FAILURE); } SCLogInfo("Suricata service startup parameters has been successfuly changed."); exit(EXIT_SUCCESS); } #endif /* OS_WIN32 */ else if(strcmp((long_opts[option_index]).name, "pidfile") == 0) { pid_filename = optarg; } else if(strcmp((long_opts[option_index]).name, "fatal-unittests") == 0) { #ifdef UNITTESTS if (ConfSet("unittests.failure_fatal", "1", 0) != 1) { fprintf(stderr, "ERROR: Failed to set unittests failure_fatal.\n"); exit(EXIT_FAILURE); } #else fprintf(stderr, "ERROR: Unit tests not enabled. Make sure to pass --enable-unittests to configure when building.\n"); exit(EXIT_FAILURE); #endif /* UNITTESTS */ } else if(strcmp((long_opts[option_index]).name, "user") == 0) { #ifndef HAVE_LIBCAP_NG SCLogError(SC_ERR_LIBCAP_NG_REQUIRED, "libcap-ng is required to" " drop privileges, but it was not compiled into Suricata."); exit(EXIT_FAILURE); #else user_name = optarg; do_setuid = TRUE; #endif /* HAVE_LIBCAP_NG */ } else if(strcmp((long_opts[option_index]).name, "group") == 0) { #ifndef HAVE_LIBCAP_NG SCLogError(SC_ERR_LIBCAP_NG_REQUIRED, "libcap-ng is required to" " drop privileges, but it was not compiled into Suricata."); exit(EXIT_FAILURE); #else group_name = optarg; do_setgid = TRUE; #endif /* HAVE_LIBCAP_NG */ } else if (strcmp((long_opts[option_index]).name, "erf-in") == 0) { run_mode = MODE_ERF_FILE; erf_file = optarg; } else if (strcmp((long_opts[option_index]).name, "dag") == 0) { #ifdef HAVE_DAG run_mode = MODE_DAG; dag_input = optarg; #else SCLogError(SC_ERR_DAG_REQUIRED, "libdag and a DAG card are required" " to receieve packets using --dag."); exit(EXIT_FAILURE); #endif /* HAVE_DAG */ } else if(strcmp((long_opts[option_index]).name, "pcap-buffer-size") == 0) { #ifdef HAVE_PCAP_SET_BUFF if (ConfSet("pcap.buffer-size", optarg, 0) != 1) { fprintf(stderr, "ERROR: Failed to set pcap-buffer-size.\n"); exit(EXIT_FAILURE); } #else SCLogError(SC_ERR_NO_PCAP_SET_BUFFER_SIZE, "The version of libpcap you have" " doesn't support setting buffer size."); #endif /* HAVE_PCAP_SET_BUFF */ } break; case 'c': conf_filename = optarg; break; #ifndef OS_WIN32 case 'D': daemon = 1; break; #endif /* OS_WIN32 */ case 'h': usage(argv[0]); exit(EXIT_SUCCESS); break; case 'i': if (run_mode == MODE_UNKNOWN) { run_mode = MODE_PCAP_DEV; PcapLiveRegisterDevice(optarg); } else if (run_mode == MODE_PCAP_DEV) { #ifdef OS_WIN32 SCLogError(SC_ERR_PCAP_MULTI_DEV_NO_SUPPORT, "pcap multi dev " "support is not (yet) supported on Windows."); exit(EXIT_FAILURE); #else SCLogWarning(SC_WARN_PCAP_MULTI_DEV_EXPERIMENTAL, "using " "multiple pcap devices to get packets is experimental."); PcapLiveRegisterDevice(optarg); #endif } else { SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode " "has been specified"); usage(argv[0]); exit(EXIT_FAILURE); } memset(pcap_dev, 0, sizeof(pcap_dev)); strlcpy(pcap_dev, optarg, ((strlen(optarg) < sizeof(pcap_dev)) ? (strlen(optarg)+1) : (sizeof(pcap_dev)))); break; case 'l': if (ConfSet("default-log-dir", optarg, 0) != 1) { fprintf(stderr, "ERROR: Failed to set log directory.\n"); exit(EXIT_FAILURE); } if (stat(optarg, &buf) != 0) { SCLogError(SC_ERR_LOGDIR_CMDLINE, "The logging directory \"%s\" " "supplied at the commandline (-l %s) doesn't " "exist. Shutting down the engine.", optarg, optarg); exit(EXIT_FAILURE); } break; case 'q': #ifdef NFQ if (run_mode == MODE_UNKNOWN) { run_mode = MODE_NFQ; SET_ENGINE_MODE_IPS(engine_mode); if (NFQRegisterQueue(optarg) == -1) exit(EXIT_FAILURE); } else if (run_mode == MODE_NFQ) { if (NFQRegisterQueue(optarg) == -1) exit(EXIT_FAILURE); } else { SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode " "has been specified"); usage(argv[0]); exit(EXIT_FAILURE); } nfq_id = optarg; #else SCLogError(SC_ERR_NFQ_NOSUPPORT,"NFQUEUE not enabled. Make sure to pass --enable-nfqueue to configure when building."); exit(EXIT_FAILURE); #endif /* NFQ */ break; case 'd': #ifdef IPFW if (run_mode == MODE_UNKNOWN) { run_mode = MODE_IPFW; SET_ENGINE_MODE_IPS(engine_mode); } else { SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode " "has been specified"); usage(argv[0]); exit(EXIT_SUCCESS); } if (ConfSet("ipfw-divert-port", optarg, 0) != 1) { fprintf(stderr, "ERROR: Failed to set ipfw_divert_port\n"); exit(EXIT_FAILURE); } #else SCLogError(SC_ERR_IPFW_NOSUPPORT,"IPFW not enabled. Make sure to pass --enable-ipfw to configure when building."); exit(EXIT_FAILURE); #endif /* IPFW */ break; case 'r': if (run_mode == MODE_UNKNOWN) { run_mode = MODE_PCAP_FILE; } else { SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode " "has been specified"); usage(argv[0]); exit(EXIT_SUCCESS); } pcap_file = optarg; break; case 's': sig_file = optarg; break; case 'u': #ifdef UNITTESTS if (run_mode == MODE_UNKNOWN) { run_mode = MODE_UNITTEST; } else { SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode has" " been specified"); usage(argv[0]); exit(EXIT_SUCCESS); } #else fprintf(stderr, "ERROR: Unit tests not enabled. Make sure to pass --enable-unittests to configure when building.\n"); exit(EXIT_FAILURE); #endif /* UNITTESTS */ break; case 'U': #ifdef UNITTESTS regex_arg = optarg; if(strlen(regex_arg) == 0) regex_arg = NULL; #endif break; case 'V': #ifdef REVISION printf("\nThis is %s version %s (rev %s)\n\n", PROG_NAME, PROG_VER, xstr(REVISION)); #else printf("\nThis is %s version %s\n\n", PROG_NAME, PROG_VER); #endif exit(EXIT_SUCCESS); default: usage(argv[0]); exit(EXIT_FAILURE); } } SetBpfString(optind, argv); UtilCpuPrintSummary(); #ifdef __SC_CUDA_SUPPORT__ /* Init the CUDA environment */ SCCudaInitCudaEnvironment(); if (list_cuda_cards) { SCCudaListCards(); exit(EXIT_SUCCESS); } #endif if (!CheckValidDaemonModes(daemon, run_mode)) { exit(EXIT_FAILURE); } /* Initializations for global vars, queues, etc (memsets, mutex init..) */ GlobalInits(); TimeInit(); SupportFastPatternForSigMatchTypes(); /* Load yaml configuration file if provided. */ if (conf_filename != NULL) { if (ConfYamlLoadFile(conf_filename) != 0) { /* Error already displayed. */ exit(EXIT_FAILURE); } } else if (run_mode != MODE_UNITTEST){ SCLogError(SC_ERR_OPENING_FILE, "Configuration file has not been provided"); usage(argv[0]); exit(EXIT_FAILURE); } if (dump_config) { ConfDump(); exit(EXIT_SUCCESS); } /* Check for the existance of the default logging directory which we pick * from suricata.yaml. If not found, shut the engine down */ if (ConfGet("default-log-dir", &log_dir) != 1) log_dir = DEFAULT_LOG_DIR; if (stat(log_dir, &buf) != 0) { SCLogError(SC_ERR_LOGDIR_CONFIG, "The logging directory \"%s\" " "supplied by %s (default-log-dir) doesn't exist. " "Shutting down the engine", log_dir, conf_filename); exit(EXIT_FAILURE); } /* Pull the max pending packets from the config, if not found fall * back on a sane default. */ if (ConfGetInt("max-pending-packets", &max_pending_packets) != 1) max_pending_packets = DEFAULT_MAX_PENDING_PACKETS; SCLogDebug("Max pending packets set to %"PRIiMAX, max_pending_packets); /* Pull the default packet size from the config, if not found fall * back on a sane default. */ if (ConfGetInt("default-packet-size", &default_packet_size) != 1) { switch (run_mode) { case MODE_PCAP_DEV: case MODE_PFRING: /* find payload for interface and use it */ default_packet_size = GetIfaceMaxPayloadSize(pcap_dev); if (default_packet_size) break; default: default_packet_size = DEFAULT_PACKET_SIZE; } } SCLogDebug("Default packet size set to %"PRIiMAX, default_packet_size); #ifdef NFQ if (run_mode == MODE_NFQ) NFQInitConfig(FALSE); #endif /* Since our config is now loaded we can finish configurating the * logging module. */ SCLogLoadConfig(); #ifdef __SC_CUDA_SUPPORT__ /* load the cuda configuration */ SCCudaHlGetYamlConf(); #endif /* __SC_CUDA_SUPPORT__ */ /* Load the Host-OS lookup. */ SCHInfoLoadFromConfig(); if (run_mode == MODE_UNKNOWN) { if (!engine_analysis) { usage(argv[0]); exit(EXIT_FAILURE); } } if (engine_analysis) { SCLogInfo("== Carrying out Engine Analysis =="); char *temp = NULL; if (ConfGet("engine-analysis", &temp) == 0) { SCLogInfo("no engine-analysis parameter(s) defined in conf file. " "Please define/enable them in the conf to use this " "feature."); exit(EXIT_FAILURE); } } /* create table for O(1) lowercase conversion lookup. It was removed, but * we still need it for cuda. So resintalling it back into the codebase */ uint8_t c = 0; memset(g_u8_lowercasetable, 0x00, sizeof(g_u8_lowercasetable)); for ( ; c < 255; c++) { if (c >= 'A' && c <= 'Z') g_u8_lowercasetable[c] = (c + ('a' - 'A')); else g_u8_lowercasetable[c] = c; } /* hardcoded initialization code */ MpmTableSetup(); /* load the pattern matchers */ SigTableSetup(); /* load the rule keywords */ TmqhSetup(); CIDRInit(); SigParsePrepare(); //PatternMatchPrepare(mpm_ctx, MPM_B2G); SCPerfInitCounterApi(); #ifdef PROFILING SCProfilingInit(); #endif /* PROFILING */ SCReputationInitCtx(); SCProtoNameInit(); TagInitCtx(); TmModuleReceiveNFQRegister(); TmModuleVerdictNFQRegister(); TmModuleDecodeNFQRegister(); TmModuleReceiveIPFWRegister(); TmModuleVerdictIPFWRegister(); TmModuleDecodeIPFWRegister(); TmModuleReceivePcapRegister(); TmModuleDecodePcapRegister(); TmModuleReceivePfringRegister(); TmModuleDecodePfringRegister(); TmModuleReceivePcapFileRegister(); TmModuleDecodePcapFileRegister(); TmModuleDetectRegister(); TmModuleAlertFastLogRegister(); TmModuleAlertDebugLogRegister(); TmModuleAlertPreludeRegister(); TmModuleRespondRejectRegister(); TmModuleAlertFastLogIPv4Register(); TmModuleAlertFastLogIPv6Register(); TmModuleAlertSyslogIPv4Register(); TmModuleAlertSyslogIPv6Register(); TmModuleAlertUnifiedLogRegister(); TmModuleAlertUnifiedAlertRegister(); TmModuleUnified2AlertRegister(); TmModuleAlertSyslogRegister(); TmModuleLogDropLogRegister(); TmModuleStreamTcpRegister(); TmModuleLogHttpLogRegister(); TmModuleLogHttpLogIPv4Register(); TmModuleLogHttpLogIPv6Register(); #ifdef __SC_CUDA_SUPPORT__ TmModuleCudaMpmB2gRegister(); TmModuleCudaPacketBatcherRegister(); #endif TmModuleReceiveErfFileRegister(); TmModuleDecodeErfFileRegister(); TmModuleReceiveErfDagRegister(); TmModuleDecodeErfDagRegister(); TmModuleDebugList(); /** \todo we need an api for these */ AppLayerDetectProtoThreadInit(); RegisterAppLayerParsers(); RegisterHTPParsers(); RegisterTLSParsers(); RegisterSMBParsers(); RegisterDCERPCParsers(); RegisterDCERPCUDPParsers(); RegisterFTPParsers(); RegisterSSHParsers(); AppLayerParsersInitPostProcess(); #ifdef UNITTESTS if (run_mode == MODE_UNITTEST) { #ifdef DBG_MEM_ALLOC SCLogInfo("Memory used at startup: %"PRIdMAX, (intmax_t)global_mem); #endif /* test and initialize the unittesting subsystem */ if(regex_arg == NULL){ regex_arg = ".*"; UtRunSelftest(regex_arg); /* inits and cleans up again */ } AppLayerHtpEnableRequestBodyCallback(); AppLayerHtpRegisterExtraCallbacks(); UtInitialize(); UTHRegisterTests(); SCReputationRegisterTests(); TmModuleRegisterTests(); SigTableRegisterTests(); HashTableRegisterTests(); HashListTableRegisterTests(); BloomFilterRegisterTests(); BloomFilterCountingRegisterTests(); PoolRegisterTests(); ByteRegisterTests(); MpmRegisterTests(); FlowBitRegisterTests(); FlowAlertSidRegisterTests(); SCPerfRegisterTests(); DecodePPPRegisterTests(); DecodeVLANRegisterTests(); HTPParserRegisterTests(); TLSParserRegisterTests(); SSHParserRegisterTests(); SMBParserRegisterTests(); DCERPCParserRegisterTests(); DCERPCUDPParserRegisterTests(); FTPParserRegisterTests(); DecodeRawRegisterTests(); DecodePPPOERegisterTests(); DecodeICMPV4RegisterTests(); DecodeICMPV6RegisterTests(); DecodeIPV4RegisterTests(); DecodeTCPRegisterTests(); DecodeUDPV4RegisterTests(); DecodeGRERegisterTests(); DecodeAsn1RegisterTests(); AlpDetectRegisterTests(); ConfRegisterTests(); ConfYamlRegisterTests(); TmqhFlowRegisterTests(); FlowRegisterTests(); SCSigRegisterSignatureOrderingTests(); SCRadixRegisterTests(); DefragRegisterTests(); SigGroupHeadRegisterTests(); SCHInfoRegisterTests(); SCRuleVarsRegisterTests(); AppLayerParserRegisterTests(); ThreadMacrosRegisterTests(); UtilSpmSearchRegistertests(); UtilActionRegisterTests(); SCClassConfRegisterTests(); SCThresholdConfRegisterTests(); SCRConfRegisterTests(); #ifdef __SC_CUDA_SUPPORT__ SCCudaRegisterTests(); #endif PayloadRegisterTests(); DcePayloadRegisterTests(); UriRegisterTests(); #ifdef PROFILING SCProfilingRegisterTests(); #endif DeStateRegisterTests(); DetectRingBufferRegisterTests(); MemcmpRegisterTests(); DetectEngineHttpClientBodyRegisterTests(); DetectEngineHttpHeaderRegisterTests(); DetectEngineHttpRawHeaderRegisterTests(); DetectEngineHttpMethodRegisterTests(); DetectEngineHttpCookieRegisterTests(); DetectEngineRegisterTests(); SCLogRegisterTests(); if (list_unittests) { UtListTests(regex_arg); } else { uint32_t failed = UtRunTests(regex_arg); UtCleanup(); #ifdef __SC_CUDA_SUPPORT__ /* need this in case any of the cuda dispatcher threads are still * running, kill them, so that we can free the cuda contexts. We * need to free those cuda contexts so that next when we call * deregister functions, we will need to attach to those contexts * the contexts and its associated data */ TmThreadKillThreads(); SCCudaHlDeRegisterAllRegisteredModules(); #endif if (failed) { exit(EXIT_FAILURE); } } #ifdef DBG_MEM_ALLOC SCLogInfo("Total memory used (without SCFree()): %"PRIdMAX, (intmax_t)global_mem); #endif exit(EXIT_SUCCESS); } #endif /* UNITTESTS */ if (daemon == 1) { Daemonize(); if (pid_filename != NULL) { if (SCPidfileCreate(pid_filename) != 0) { pid_filename = NULL; exit(EXIT_FAILURE); } } } else { if (pid_filename != NULL) { SCLogError(SC_ERR_PIDFILE_DAEMON, "The pidfile file option applies " "only to the daemon modes"); pid_filename = NULL; exit(EXIT_FAILURE); } } /* registering signals we use */ SignalHandlerSetup(SIGINT, SignalHandlerSigint); SignalHandlerSetup(SIGTERM, SignalHandlerSigterm); #ifndef OS_WIN32 /* SIGHUP is not implemnetd on WIN32 */ //SignalHandlerSetup(SIGHUP, SignalHandlerSighup); /* Get the suricata user ID to given user ID */ if (do_setuid == TRUE) { if (SCGetUserID(user_name, group_name, &userid, &groupid) != 0) { SCLogError(SC_ERR_UID_FAILED, "failed in getting user ID"); exit(EXIT_FAILURE); } sc_set_caps = TRUE; /* Get the suricata group ID to given group ID */ } else if (do_setgid == TRUE) { if (SCGetGroupID(group_name, &groupid) != 0) { SCLogError(SC_ERR_GID_FAILED, "failed in getting group ID"); exit(EXIT_FAILURE); } sc_set_caps = TRUE; } #endif /* OS_WIN32 */ /* pre allocate packets */ SCLogDebug("preallocating packets... packet size %" PRIuMAX "", (uintmax_t)SIZE_OF_PACKET); int i = 0; for (i = 0; i < max_pending_packets; i++) { /* XXX pkt alloc function */ Packet *p = SCMalloc(SIZE_OF_PACKET); if (p == NULL) { SCLogError(SC_ERR_FATAL, "Fatal error encountered while allocating a packet. Exiting..."); exit(EXIT_FAILURE); } PACKET_INITIALIZE(p); PacketPoolStorePacket(p); } SCLogInfo("preallocated %"PRIiMAX" packets. Total memory %"PRIuMAX"", max_pending_packets, (uintmax_t)(max_pending_packets*SIZE_OF_PACKET)); FlowInitConfig(FLOW_VERBOSE); DetectEngineCtx *de_ctx = DetectEngineCtxInit(); SCClassConfLoadClassficationConfigFile(de_ctx); SCRConfLoadReferenceConfigFile(de_ctx); ActionInitConfig(); if (SigLoadSignatures(de_ctx, sig_file) < 0) { if (sig_file == NULL) { SCLogError(SC_ERR_OPENING_FILE, "Signature file has not been provided"); } else { SCLogError(SC_ERR_NO_RULES_LOADED, "Loading signatures failed."); } if (de_ctx->failure_fatal) exit(EXIT_FAILURE); } if (engine_analysis) { exit(EXIT_SUCCESS); } #ifdef PROFILING SCProfilingInitRuleCounters(de_ctx); #endif /* PROFILING */ #ifdef __SC_CUDA_SUPPORT__ SCCudaPBSetUpQueuesAndBuffers(); #endif /* __SC_CUDA_SUPPORT__ */ AppLayerHtpRegisterExtraCallbacks(); SCThresholdConfInitContext(de_ctx,NULL); SCAsn1LoadConfig(); struct timeval start_time; memset(&start_time, 0, sizeof(start_time)); gettimeofday(&start_time, NULL); SCDropMainThreadCaps(userid, groupid); RunModeInitializeOutputs(); /* run the selected runmode */ if (run_mode == MODE_PCAP_DEV) { //RunModeIdsPcap3(de_ctx, pcap_dev); //RunModeIdsPcap2(de_ctx, pcap_dev); //RunModeIdsPcap(de_ctx, pcap_dev); PcapTranslateIPToDevice(pcap_dev, sizeof(pcap_dev)); RunModeIdsPcapAuto(de_ctx, pcap_dev); } else if (run_mode == MODE_PCAP_FILE) { //RunModeFilePcap(de_ctx, pcap_file); //RunModeFilePcap2(de_ctx, pcap_file); RunModeFilePcapAuto(de_ctx, pcap_file); //RunModeFilePcapAutoFp(de_ctx, pcap_file); //RunModeFilePcapAuto2(de_ctx, pcap_file); } #ifdef HAVE_PFRING else if (run_mode == MODE_PFRING) { PfringLoadConfig(); //RunModeIdsPfring3(de_ctx, pfring_dev); //RunModeIdsPfring2(de_ctx, pfring_dev); //RunModeIdsPfring(de_ctx, pfring_dev); //RunModeIdsPfring4(de_ctx, pfring_dev); if (PfringConfGetThreads() == 1) { RunModeIdsPfringAuto(de_ctx, pfring_dev); } else { RunModeIdsPfringAutoFp(de_ctx, pfring_dev); } } #endif /* HAVE_PFRING */ else if (run_mode == MODE_NFQ) { //RunModeIpsNFQ(de_ctx, nfq_id); RunModeIpsNFQAuto(de_ctx, nfq_id); } else if (run_mode == MODE_IPFW) { //RunModeIpsIPFW(de_ctx); RunModeIpsIPFWAuto(de_ctx); } else if (run_mode == MODE_ERF_FILE) { RunModeErfFileAuto(de_ctx, erf_file); } else if (run_mode == MODE_DAG) { RunModeErfDagAuto(de_ctx, dag_input); } else { SCLogError(SC_ERR_UNKNOWN_RUN_MODE, "Unknown runtime mode. Aborting"); exit(EXIT_FAILURE); } #ifdef __SC_CUDA_SUPPORT__ if (PatternMatchDefaultMatcher() == MPM_B2G_CUDA) { /* start the dispatcher thread for this module */ if (B2gCudaStartDispatcherThreadRC("SC_RULES_CONTENT_B2G_CUDA") == -1) exit(EXIT_FAILURE); } #endif /* Spawn the flow manager thread */ FlowManagerThreadSpawn(); StreamTcpInitConfig(STREAM_VERBOSE); DefragInit(); /* Spawn the L7 App Detect thread */ //AppLayerDetectProtoThreadSpawn(); /* Spawn the perf counter threads. Let these be the last one spawned */ SCPerfSpawnThreads(); /* Check if the alloted queues have at least 1 reader and writer */ TmValidateQueueState(); /* Wait till all the threads have been initialized */ if (TmThreadWaitOnThreadInit() == TM_ECODE_FAILED) { SCLogError(SC_ERR_INITIALIZATION, "Engine initialization failed, " "aborting..."); exit(EXIT_FAILURE); } SC_ATOMIC_CAS(&engine_stage, SURICATA_INIT, SURICATA_RUNTIME); /* Un-pause all the paused threads */ TmThreadContinueThreads(); #ifdef DBG_MEM_ALLOC SCLogInfo("Memory used at startup: %"PRIdMAX, (intmax_t)global_mem); #ifdef DBG_MEM_ALLOC_SKIP_STARTUP print_mem_flag = 1; #endif #endif while(1) { if (suricata_ctl_flags != 0) { SCLogInfo("signal received"); if (suricata_ctl_flags & SURICATA_STOP) { SCLogInfo("EngineStop received"); /* Stop the engine so it quits after processing the pcap file * but first make sure all packets are processed by all other * threads. */ char done = 0; do { if (suricata_ctl_flags & SURICATA_KILL) break; /* if all packets are returned to the packetpool * we are done */ if (PacketPoolSize() == max_pending_packets) done = 1; if (done == 0) { usleep(100); } } while (done == 0); SCLogInfo("all packets processed by threads, stopping engine"); } struct timeval end_time; memset(&end_time, 0, sizeof(end_time)); gettimeofday(&end_time, NULL); SCLogInfo("time elapsed %" PRIuMAX "s", (uintmax_t)(end_time.tv_sec - start_time.tv_sec)); #ifdef __SC_CUDA_SUPPORT__ SCCudaPBKillBatchingPackets(); #endif TmThreadKillThreads(); SCPerfReleaseResources(); break; } TmThreadCheckThreadState(); usleep(10* 1000); } /* Update the engine stage/status flag */ SC_ATOMIC_CAS(&engine_stage, SURICATA_RUNTIME, SURICATA_DEINIT); FlowShutdown(); FlowPrintQueueInfo(); StreamTcpFreeConfig(STREAM_VERBOSE); HTPFreeConfig(); HTPAtExitPrintStats(); #ifdef DBG_MEM_ALLOC SCLogInfo("Total memory used (without SCFree()): %"PRIdMAX, (intmax_t)global_mem); #ifdef DBG_MEM_ALLOC_SKIP_STARTUP print_mem_flag = 0; #endif #endif SCPidfileRemove(pid_filename); /** \todo review whats needed here */ #ifdef __SC_CUDA_SUPPORT__ if (PatternMatchDefaultMatcher() == MPM_B2G_CUDA) { /* all threadvars related to cuda should be free by now, which means * the cuda contexts would be floating */ if (SCCudaHlPushCudaContextFromModule("SC_RULES_CONTENT_B2G_CUDA") == -1) { SCLogError(SC_ERR_CUDA_HANDLER_ERROR, "Call to " "SCCudaHlPushCudaContextForModule() failed during the " "shutdown phase just before the call to SigGroupCleanup()"); } } #endif SigGroupCleanup(de_ctx); #ifdef __SC_CUDA_SUPPORT__ if (PatternMatchDefaultMatcher() == MPM_B2G_CUDA) { /* pop the cuda context we just pushed before the call to SigGroupCleanup() */ if (SCCudaCtxPopCurrent(NULL) == -1) { SCLogError(SC_ERR_CUDA_HANDLER_ERROR, "Call to SCCudaCtxPopCurrent() " "during the shutdown phase just before the call to " "SigGroupCleanup()"); return 0; } } #endif AppLayerHtpPrintStats(); SigCleanSignatures(de_ctx); if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { MpmFactoryDeRegisterAllMpmCtxProfiles(); } DetectEngineCtxFree(de_ctx); AlpProtoDestroy(); TagDestroyCtx(); RunModeShutDown(); OutputDeregisterAll(); TimeDeinit(); SCProtoNameDeInit(); DefragDestroy(); TmqhPacketpoolDestroy(); #ifdef PROFILING if (profiling_rules_enabled) SCProfilingDump(stdout); SCProfilingDestroy(); #endif #ifdef __SC_CUDA_SUPPORT__ /* all cuda contexts attached to any threads should be free by now. * if any host_thread is still attached to any cuda_context, they need * to pop them by the time we reach here, if they aren't using those * cuda contexts in any way */ SCCudaHlDeRegisterAllRegisteredModules(); #endif #ifdef OS_WIN32 if (daemon) { return 0; } #endif /* OS_WIN32 */ SC_ATOMIC_DESTROY(engine_stage); exit(EXIT_SUCCESS); }
/*=========================================================================*/ int main(int argc, char* argv[]) /*=========================================================================*/ { fd_set readfds; fd_set writefds; int highfd; int fdcount = 0; /*------------------------------*/ /* Make sure we are root */ /*------------------------------*/ if(getuid() != 0) { SLPFatal("slpd must be started by root\n"); } /*------------------------*/ /* Parse the command line */ /*------------------------*/ if(SLPDParseCommandLine(argc,argv)) { SLPFatal("Invalid command line\n"); } /*------------------------------*/ /* Initialize the log file */ /*------------------------------*/ SLPLogFileOpen(G_SlpdCommandLine.logfile, 0); SLPLog("****************************************\n"); SLPLog("*** SLPD daemon started ***\n"); SLPLog("****************************************\n"); SLPLog("command line = %s\n",argv[0]); /*--------------------------------------------------*/ /* Initialize for the first time */ /*--------------------------------------------------*/ SLPDPropertyInit(G_SlpdCommandLine.cfgfile); SLPDDatabaseInit(G_SlpdCommandLine.regfile); SLPDIncomingInit(); SLPDOutgoingInit(); SLPDKnownDAInit(); /* TODO: Check error codes on all init functions */ /*---------------------------*/ /* make slpd run as a daemon */ /*---------------------------*/ if(Daemonize(G_SlpdCommandLine.pidfile)) { SLPFatal("Could not run as daemon\n"); } /*-----------------------*/ /* Setup signal handlers */ /*-----------------------*/ if(SetUpSignalHandlers()) { SLPFatal("Could not set up signal handlers.\n"); } /*------------------------------*/ /* Set up alarm to age database */ /*------------------------------*/ alarm(SLPD_AGE_INTERVAL); /*-----------*/ /* Main loop */ /*-----------*/ G_SIGALRM = 0; G_SIGTERM = 0; G_SIGHUP = 0; SLPLog("Initialization complete\n\n"); while(G_SIGTERM == 0) { /*--------------------------------------------------------*/ /* Load the fdsets up with all valid sockets in the list */ /*--------------------------------------------------------*/ highfd = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); LoadFdSets(&G_IncomingSocketList, &highfd, &readfds,&writefds); LoadFdSets(&G_OutgoingSocketList, &highfd, &readfds,&writefds); /*--------------------------------------------------*/ /* Before select(), check to see if we got a signal */ /*--------------------------------------------------*/ if(G_SIGALRM || G_SIGHUP) { goto HANDLE_SIGNAL; } /*-------------*/ /* Main select */ /*-------------*/ fdcount = select(highfd+1,&readfds,&writefds,0,0); if(fdcount > 0) /* fdcount will be < 0 when interrupted by a signal */ { SLPDIncomingHandler(&fdcount,&readfds,&writefds); SLPDOutgoingHandler(&fdcount,&readfds,&writefds); } /*----------------*/ /* Handle signals */ /*----------------*/ HANDLE_SIGNAL: if(G_SIGHUP) { /* Reinitialize */ SLPLog("****************************************\n"); SLPLog("*** SLPD daemon restarted ***\n"); SLPLog("****************************************\n"); SLPLog("Got SIGHUP reinitializing... \n"); SLPDPropertyInit(G_SlpdCommandLine.cfgfile); SLPDDatabaseInit(G_SlpdCommandLine.regfile); /* Don't reinitialize Incoming because we can't rebind to */ /* slp reserved port because we are not root now */ /* SLPDIncomingInit(); */ SLPDOutgoingInit(); SLPDKnownDAInit(); G_SIGHUP = 0; } if(G_SIGALRM) { /* TODO: add call to do passive DAAdvert */ SLPDIncomingAge(SLPD_AGE_INTERVAL); SLPDOutgoingAge(SLPD_AGE_INTERVAL); SLPDDatabaseAge(SLPD_AGE_INTERVAL); SLPDKnownDAActiveDiscovery(); G_SIGALRM = 0; alarm(SLPD_AGE_INTERVAL); } } /* End of main loop */ SLPLog("Got SIGTERM. Going down\n"); #if(defined DEBUG) SLPDIncomingDeinit(); SLPDOutgoingDeinit(); printf("Number of calls to SLPBufferAlloc() = %i\n",G_Debug_SLPBufferAllocCount); printf("Number of calls to SLPBufferFree() = %i\n",G_Debug_SLPBufferFreeCount); #endif return 0; }
/*=========================================================================*/ int main(int argc, char* argv[]) /*=========================================================================*/ { fd_set readfds; fd_set writefds; int highfd; int fdcount = 0; /*------------------------*/ /* Parse the command line */ /*------------------------*/ if(SLPDParseCommandLine(argc,argv)) { SLPFatal("Invalid command line\n"); } /*------------------------------*/ /* Make sure we are root */ /*------------------------------*/ if(getuid() != 0) { SLPFatal("slpd must be started by root\n"); } /*--------------------------------------*/ /* Make sure we are not already running */ /*--------------------------------------*/ if(CheckPid(G_SlpdCommandLine.pidfile)) { SLPFatal("slpd is already running. Check %s\n", G_SlpdCommandLine.pidfile); } /*------------------------------*/ /* Initialize the log file */ /*------------------------------*/ if(SLPLogFileOpen(G_SlpdCommandLine.logfile, 1)) { SLPFatal("Could not open logfile %s\n",G_SlpdCommandLine.logfile); } /*------------------------*/ /* Seed the XID generator */ /*------------------------*/ SLPXidSeed(); /*---------------------*/ /* Log startup message */ /*---------------------*/ SLPLog("****************************************\n"); SLPLogTime(); SLPLog("SLPD daemon started\n"); SLPLog("****************************************\n"); SLPLog("Command line = %s\n",argv[0]); SLPLog("Using configuration file = %s\n",G_SlpdCommandLine.cfgfile); SLPLog("Using registration file = %s\n",G_SlpdCommandLine.regfile); /*--------------------------------------------------*/ /* Initialize for the first time */ /*--------------------------------------------------*/ if(SLPDPropertyInit(G_SlpdCommandLine.cfgfile) || SLPDDatabaseInit(G_SlpdCommandLine.regfile) || SLPDIncomingInit() || SLPDOutgoingInit() || SLPDKnownDAInit()) { SLPFatal("slpd initialization failed\n"); } SLPLog("Agent Interfaces = %s\n",G_SlpdProperty.interfaces); SLPLog("Agent URL = %s\n",G_SlpdProperty.myUrl); /*---------------------------*/ /* make slpd run as a daemon */ /*---------------------------*/ if(Daemonize(G_SlpdCommandLine.pidfile)) { SLPFatal("Could not daemonize\n"); } /*-----------------------*/ /* Setup signal handlers */ /*-----------------------*/ if(SetUpSignalHandlers()) { SLPFatal("Error setting up signal handlers.\n"); } /*------------------------------*/ /* Set up alarm to age database */ /*------------------------------*/ alarm(SLPD_AGE_INTERVAL); /*-----------*/ /* Main loop */ /*-----------*/ SLPLog("Startup complete entering main run loop ...\n\n"); G_SIGALRM = 0; G_SIGTERM = 0; G_SIGHUP = 0; while(G_SIGTERM == 0) { /*--------------------------------------------------------*/ /* Load the fdsets up with all valid sockets in the list */ /*--------------------------------------------------------*/ highfd = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); LoadFdSets(&G_IncomingSocketList, &highfd, &readfds,&writefds); LoadFdSets(&G_OutgoingSocketList, &highfd, &readfds,&writefds); /*--------------------------------------------------*/ /* Before select(), check to see if we got a signal */ /*--------------------------------------------------*/ if(G_SIGALRM || G_SIGHUP) { goto HANDLE_SIGNAL; } /*-------------*/ /* Main select */ /*-------------*/ fdcount = select(highfd+1,&readfds,&writefds,0,0); if(fdcount > 0) /* fdcount will be < 0 when interrupted by a signal */ { SLPDIncomingHandler(&fdcount,&readfds,&writefds); SLPDOutgoingHandler(&fdcount,&readfds,&writefds); } /*----------------*/ /* Handle signals */ /*----------------*/ HANDLE_SIGNAL: if(G_SIGHUP) { HandleSigHup(); G_SIGHUP = 0; } if(G_SIGALRM) { HandleSigAlrm(); G_SIGALRM = 0; alarm(SLPD_AGE_INTERVAL); } } /* End of main loop */ /* Got SIGTERM */ HandleSigTerm(); return 0; }
void Server::Run() { if (Daemonize() != 0) exit(-1); if (!pool_.Run()) exit(-1); acceptor_.LoopAccept(server_ip_.c_str(), listent_port_); }
int main( int argc, char *argv[] ) { const char *fn = "main()"; char f_randfile[ PATH_MAX ]; int listensd; /* socket descriptor we'll bind to */ int clientsd; /* incoming socket descriptor */ int sockaddrlen; struct sockaddr_storage srvaddr; struct sockaddr_storage cliaddr; pthread_t ThreadId; /* thread id of each incoming conn */ pthread_t RecycleThread; /* used just for the recycle thread */ pthread_attr_t attr; /* generic thread attribute struct */ int rc, i, fd; unsigned int ui; struct linger lingerstruct; /* for the socket reuse stuff */ int flag; /* for the socket reuse stuff */ ICC_Struct *ICC_tptr; extern char *optarg; extern int optind; char ConfigFile[ MAXPATHLEN ]; /* path to our config file */ char PidFile[ MAXPATHLEN ]; /* path to our pidfile */ #ifdef HAVE_LIBWRAP struct request_info r; /* request struct for libwrap */ #endif struct addrinfo aihints, *ai; int gaierrnum; flag = 1; ConfigFile[0] = '\0'; strncpy( PidFile, DEFAULT_PID_FILE, sizeof PidFile -1 ); /* * Ignore signals we don't want to die from but we don't care enough * about to catch. */ signal( SIGPIPE, SIG_IGN ); signal( SIGHUP, SIG_IGN ); while (( i = getopt( argc, argv, "f:p:h" ) ) != EOF ) { switch( i ) { case 'f': /* user specified a config filename */ strncpy( ConfigFile, optarg, sizeof ConfigFile -1 ); ConfigFile[ sizeof ConfigFile - 1 ] = '\0'; syslog( LOG_INFO, "%s: Using configuration file '%s'", fn, ConfigFile ); break; case 'p': /* user specified a pidfile */ strncpy( PidFile, optarg, sizeof PidFile -1 ); PidFile[ sizeof PidFile - 1 ] = '\0'; syslog( LOG_INFO, "%s: Using pidfile '%s'", fn, PidFile ); break; case 'h': Usage(); exit( 0 ); case '?': Usage(); exit( 1 ); } } /* * Make sure we know which config file to use and then set our config * options. */ if ( ! ConfigFile[0] ) { strncpy( ConfigFile, DEFAULT_CONFIG_FILE, sizeof ConfigFile -1 ); ConfigFile[ sizeof ConfigFile - 1 ] = '\0'; syslog( LOG_INFO, "%s: Using default configuration file '%s'.", fn, ConfigFile ); } SetDefaultConfigValues(&PC_Struct); SetConfigOptions( ConfigFile ); SetLogOptions(); /* * Just for logging purposes, are we doing SELECT caching or not? */ if ( PC_Struct.enable_select_cache ) syslog( LOG_INFO, "%s: SELECT caching is enabled", fn ); else syslog( LOG_INFO, "%s: SELECT caching is disabled", fn ); /* * Just for logging purposes, are the admin commands enabled or not? */ if ( PC_Struct.enable_admin_commands ) syslog( LOG_INFO, "%s: Internal admin commands are enabled", fn ); else syslog( LOG_INFO, "%s: Internal admin commands are disabled", fn ); #ifdef HAVE_LIBWRAP /* * Set our tcpd service name */ if (service = strrchr(argv[0], '/')) service++; else service = argv[0]; #endif /* * Initialize some stuff. */ rc = pthread_mutex_init(&mp, NULL); if ( rc ) { syslog(LOG_ERR, "%s: pthread_mutex_init() returned error [%d] initializing main mutex. Exiting.", fn, rc ); exit( 1 ); } rc = pthread_mutex_init(&trace, NULL); if ( rc ) { syslog(LOG_ERR, "%s: pthread_mutex_init() returned error [%d] initializing trace mutex. Exiting.", fn, rc ); exit( 1 ); } TraceUser[0] = '\0'; syslog( LOG_INFO, "%s: Allocating %d IMAP connection structures.", fn, PC_Struct.cache_size ); ICC_free = (ICC_Struct *)malloc( ( sizeof ( ICC_Struct ) ) * PC_Struct.cache_size ); if ( ! ICC_free ) { syslog(LOG_ERR, "%s: malloc() failed to allocate [%d] IMAPConnectionContext structures: %s", fn, PC_Struct.cache_size, strerror( errno ) ); exit( 1 ); } memset( ICC_free, 0, sizeof ( ICC_Struct ) * PC_Struct.cache_size ); ICC_tptr = ICC_free; /* * Bug fixed by Gary Mills <*****@*****.**>. I was pre-incrementing * ICC_tptr and then assigning. I guess gcc evaluates the expression * incorrectly, since I never had a problem with this. Gary had the * problem with cc, so it's fixed here. */ for ( ui = 0; ui < PC_Struct.cache_size - 1; ui++ ) { ICC_tptr->next = ICC_tptr + 1; ICC_tptr++; } memset( ICC_HashTable, 0, sizeof ICC_HashTable ); #if HAVE_LIBSSL /* Initialize SSL_CTX */ syslog( LOG_INFO, "%s: Enabling openssl library.", fn ); SSL_library_init(); /* Set up OpenSSL thread protection */ ssl_thread_setup(fn); /* Need to seed PRNG, too! */ if ( RAND_egd( ( RAND_file_name( f_randfile, sizeof( f_randfile ) ) == f_randfile ) ? f_randfile : "/.rnd" ) ) { /* Not an EGD, so read and write it. */ if ( RAND_load_file( f_randfile, -1 ) ) RAND_write_file( f_randfile ); } SSL_load_error_strings(); tls_ctx = SSL_CTX_new( TLSv1_client_method() ); if ( tls_ctx == NULL ) { syslog(LOG_ERR, "%s: Failed to create new SSL_CTX. Exiting.", fn); exit( 1 ); } /* Work around all known bugs */ SSL_CTX_set_options( tls_ctx, SSL_OP_ALL ); if ( PC_Struct.tls_ca_file != NULL || PC_Struct.tls_ca_path != NULL ) { rc = SSL_CTX_load_verify_locations( tls_ctx, PC_Struct.tls_ca_file, PC_Struct.tls_ca_path ); } else { rc = SSL_CTX_set_default_verify_paths( tls_ctx ); } if ( rc == 0 ) { syslog(LOG_ERR, "%s: Failed to load CA data. Exiting.", fn); exit( 1 ); } if ( ! set_cert_stuff( tls_ctx, PC_Struct.tls_cert_file, PC_Struct.tls_key_file ) ) { syslog(LOG_ERR, "%s: Failed to load cert/key data. Exiting.", fn); exit( 1 ); } SSL_CTX_set_verify(tls_ctx, SSL_VERIFY_NONE, verify_callback); #endif /* HAVE_LIBSSL */ ServerInit(); /* Daemonize() would go here */ SetBannerAndCapability(); /* * We don't need to check PC_Struct.support_starttls since we * probably have refetched the capability list after a STARTTLS * if we did one; it won't ever be supported at this point. * * It also makes no difference to check PC_Struct.force_tls now * because we've either done a STARTTLS or we haven't - all that * matters is if we got LOGINDISABLED or not. * * Note that all these things *ARE* tested when checking the * server capabilities (in fact, the following check is probably * a duplicate). */ if ( PC_Struct.login_disabled ) { /* We're screwed! We can't login */ syslog(LOG_ERR, "%s: IMAP server has LOGINDISABLED. Exiting.", fn); exit( 1 ); } memset( &aihints, 0, sizeof aihints ); aihints.ai_family = AF_UNSPEC; aihints.ai_socktype = SOCK_STREAM; aihints.ai_flags = AI_PASSIVE; if ( ( gaierrnum = getaddrinfo( PC_Struct.listen_addr, PC_Struct.listen_port, &aihints, &ai ) ) ) { syslog( LOG_ERR, "%s: bad bind address: '%s' specified in config file. Exiting.", fn, PC_Struct.listen_addr ); exit( 1 ); } syslog( LOG_INFO, "%s: Binding to tcp %s:%s", fn, PC_Struct.listen_addr ? PC_Struct.listen_addr : "*", PC_Struct.listen_port ); for ( ; ai != NULL; ai = ai->ai_next ) { listensd = socket( ai->ai_family, ai->ai_socktype, ai->ai_protocol ); if ( listensd == -1 ) { syslog(LOG_WARNING, "%s: socket() failed: %s", fn, strerror(errno)); continue; } setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void *)&flag, sizeof(flag)); lingerstruct.l_onoff = 1; lingerstruct.l_linger = 5; setsockopt(listensd, SOL_SOCKET, SO_LINGER, (void *)&lingerstruct, sizeof(lingerstruct)); if ( PC_Struct.send_tcp_keepalives ) { lingerstruct.l_onoff = 1; syslog( LOG_INFO, "%s: Enabling SO_KEEPALIVE.", fn ); setsockopt( listensd, SOL_SOCKET, SO_KEEPALIVE, (void *)&lingerstruct.l_onoff, sizeof lingerstruct.l_onoff ); } memcpy( &srvaddr, ai->ai_addr, ai->ai_addrlen ); if ( bind( listensd, (struct sockaddr *)&srvaddr, ai->ai_addrlen ) < 0 ) { syslog(LOG_WARNING, "%s: bind() failed: %s", fn, strerror(errno) ); continue; } else break; } if ( ai == NULL ) { syslog( LOG_ERR, "%s: no useable addresses to bind to", fn ); exit( EXIT_FAILURE); } /* * Create and mmap() our stat file while we're still root. Since it's * configurable, we want to make sure we do this as root so there's the * greatest possibility that we'll have permission to write where we * need to. */ syslog( LOG_INFO, "%s: Using global statistics file '%s'", fn, PC_Struct.stat_filename ); fd = open( PC_Struct.stat_filename, O_RDWR | O_CREAT, S_IREAD | S_IWRITE ); if ( fd == -1 ) { syslog(LOG_ERR, "%s: open() failed for '%s': %s -- Exiting.", fn, PC_Struct.stat_filename, strerror( errno ) ); exit( 1 ); } if ( ( ftruncate( fd, sizeof( IMAPCounter_Struct ) ) ) == -1 ) { syslog(LOG_ERR, "%s: ftruncate() failed: %s -- Exiting.", fn, strerror( errno ) ); exit( 1 ); } IMAPCount = ( IMAPCounter_Struct *)mmap( 0, sizeof( IMAPCounter_Struct ), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); if ( IMAPCount == MAP_FAILED ) { syslog(LOG_ERR, "%s: mmap() failed: %s -- Exiting.", fn, strerror( errno ) ); exit( 1 ); } memset( IMAPCount, 0, sizeof( IMAPCounter_Struct ) ); IMAPCount->StartTime = time( 0 ); IMAPCount->CountTime = time( 0 ); /* * Daemonize as late as possible, so that connection failures can be caught * and startup aborted before dettaching from parent */ Daemonize( PidFile ); if ( BecomeNonRoot() ) exit( 1 ); /* some misc thread setup */ rc = pthread_attr_init( &attr ); if ( rc ) { syslog(LOG_ERR, "%s: pthread_attr_init() failed: [%d]\n", fn, rc); exit( 1 ); } rc = pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); if ( rc ) { syslog(LOG_ERR, "%s: pthread_attr_setdetachstate() failed: [%d]\n", fn, rc); exit( 1 ); } /* launch a recycle thread before we loop */ pthread_create( &RecycleThread, &attr, (void *)ICC_Recycle_Loop, NULL ); syslog(LOG_INFO, "%s: Launched ICC recycle thread with id %d", fn, (int)RecycleThread ); /* * Now start listening and accepting connections. */ if ( listen(listensd, MAX_CONN_BACKLOG) < 0) { syslog( LOG_ERR, "%s: listen() failed: %s -- Exiting", fn, strerror(errno)); exit( 1 ); } syslog( LOG_INFO, "%s: squirrelmail-imap_proxy version %s normal server startup.", fn, IMAP_PROXY_VERSION ); /* * Main server loop */ for ( ;; ) { /* * Bug fixed by Gary Mills <*****@*****.**>. I forgot * to initialize sockaddrlen. */ sockaddrlen = sizeof cliaddr; clientsd = accept( listensd, (struct sockaddr *)&cliaddr, &sockaddrlen ); if ( clientsd == -1 ) { syslog(LOG_WARNING, "%s: accept() failed: %s -- retrying", fn, strerror(errno)); sleep( 1 ); continue; } #ifdef HAVE_LIBWRAP request_init(&r, RQ_DAEMON, service, 0); request_set(&r, RQ_FILE, clientsd, 0); sock_host(&r); if (!hosts_access(&r)) { shutdown(clientsd, SHUT_RDWR); close(clientsd); syslog(deny_severity, "refused connection from %s", eval_client(&r)); continue; } #endif IMAPCount->TotalClientConnectionsAccepted++; IMAPCount->CurrentClientConnections++; if ( IMAPCount->CurrentClientConnections > IMAPCount->PeakClientConnections ) IMAPCount->PeakClientConnections = IMAPCount->CurrentClientConnections; rc = pthread_create( &ThreadId, &attr, (void *)HandleRequest, (void *)clientsd ); if (rc != 0) { syslog(LOG_ERR, "%s: pthread_create() returned error [%d] for HandleRequest.", fn, rc ); close(clientsd); } } }
/** * StartMainLoop * * Executes shroudBNC's main loop. */ void CCore::StartMainLoop(bool ShouldDaemonize) { unsigned int i; time(&g_CurrentTime); int Port = CacheGetInteger(m_ConfigCache, port); #ifdef HAVE_LIBSSL int SSLPort = CacheGetInteger(m_ConfigCache, sslport); if (Port == 0 && SSLPort == 0) { #else if (Port == 0) { #endif Port = 9000; } const char *BindIp = CacheGetString(m_ConfigCache, ip); if (m_Listener == NULL) { if (Port != 0) { m_Listener = new CClientListener(Port, BindIp, AF_INET); } else { m_Listener = NULL; } } if (m_ListenerV6 == NULL) { if (Port != 0) { m_ListenerV6 = new CClientListener(Port, BindIp, AF_INET6); if (m_ListenerV6->IsValid() == false) { delete m_ListenerV6; m_ListenerV6 = NULL; } } else { m_ListenerV6 = NULL; } } #ifdef HAVE_LIBSSL if (m_SSLListener == NULL) { if (SSLPort != 0) { m_SSLListener = new CClientListener(SSLPort, BindIp, AF_INET, true); } else { m_SSLListener = NULL; } } if (m_SSLListenerV6 == NULL) { if (SSLPort != 0) { m_SSLListenerV6 = new CClientListener(SSLPort, BindIp, AF_INET6, true); if (m_SSLListenerV6->IsValid() == false) { delete m_SSLListenerV6; m_SSLListenerV6 = NULL; } } else { m_SSLListenerV6 = NULL; } } SSL_library_init(); SSL_load_error_strings(); SSL_METHOD *SSLMethod = (SSL_METHOD *)SSLv23_method(); m_SSLContext = SSL_CTX_new(SSLMethod); SSL_CTX_set_passwd_cb(m_SSLContext); m_SSLClientContext = SSL_CTX_new(SSLMethod); SSL_CTX_set_passwd_cb(m_SSLClientContext); SSL_CTX_set_mode(m_SSLContext, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); SSL_CTX_set_mode(m_SSLClientContext, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); g_SSLCustomIndex = SSL_get_ex_new_index(0, (void *)"CConnection*", NULL, NULL, NULL); if (!SSL_CTX_use_PrivateKey_file(m_SSLContext, BuildPathConfig("sbnc.key"), SSL_FILETYPE_PEM)) { if (SSLPort != 0) { Log("Could not load private key (sbnc.key)."); ERR_print_errors_fp(stdout); return; } else { SSL_CTX_free(m_SSLContext); m_SSLContext = NULL; } } else { SSL_CTX_set_verify(m_SSLContext, SSL_VERIFY_PEER, SSLVerifyCertificate); } if (!SSL_CTX_use_certificate_chain_file(m_SSLContext, BuildPathConfig("sbnc.crt"))) { if (SSLPort != 0) { Log("Could not load public key (sbnc.crt)."); ERR_print_errors_fp(stdout); return; } else { SSL_CTX_free(m_SSLContext); m_SSLContext = NULL; } } else { SSL_CTX_set_verify(m_SSLClientContext, SSL_VERIFY_PEER, SSLVerifyCertificate); } #endif if (Port != 0 && m_Listener != NULL && m_Listener->IsValid()) { Log("Created main listener."); } else if (Port != 0) { Log("Could not create listener port"); return; } #ifdef HAVE_LIBSSL if (SSLPort != 0 && m_SSLListener != NULL && m_SSLListener->IsValid()) { Log("Created ssl listener."); } else if (SSLPort != 0) { Log("Could not create ssl listener port"); return; } #endif InitializeAdditionalListeners(); Log("Starting main loop."); if (ShouldDaemonize) { #ifndef _WIN32 fprintf(stderr, "Daemonizing... "); UnlockPidFile(); if (Daemonize()) { fprintf(stderr, "DONE\n"); } else { fprintf(stderr, "FAILED\n"); } WritePidFile(); #endif } /* Note: We need to load the modules after using fork() as otherwise tcl cannot be cleanly unloaded */ m_LoadingModules = true; #ifdef _MSC_VER LoadModule("bnctcl.dll"); LoadModule("bncidentd.dll"); #else LoadModule("libbnctcl.la"); #endif char *Out; i = 0; while (true) { int rc = asprintf(&Out, "system.modules.mod%d", i++); if (RcFailed(rc)) { Fatal(); } const char *File = m_Config->ReadString(Out); free(Out); if (File == NULL) { break; } LoadModule(File); } m_LoadingModules = false; i = 0; while (hash_t<CUser *> *User = m_Users.Iterate(i++)) { User->Value->LoadEvent(); } int m_ShutdownLoop = 5; time_t Last = 0; while (GetStatus() == Status_Running || --m_ShutdownLoop) { time_t Now, Best = 0, SleepInterval = 0; #if defined(_WIN32) && defined(_DEBUG) DWORD TickCount = GetTickCount(); #endif time(&Now); i = 0; while (hash_t<CUser *> *UserHash = m_Users.Iterate(i++)) { CIRCConnection *IRC; if ((IRC = UserHash->Value->GetIRCConnection()) != NULL) { if (GetStatus() != Status_Running) { Log("Closing connection for user %s", UserHash->Name); IRC->Kill("Shutting down."); UserHash->Value->SetIRCConnection(NULL); } if (IRC->ShouldDestroy()) { IRC->Destroy(); } } } CUser::RescheduleReconnectTimer(); time(&Now); if (g_CurrentTime - 5 > Now) { Log("Time warp detected: %d seconds", Now - g_CurrentTime); } g_CurrentTime = Now; Best = CTimer::GetNextCall(); if (Best <= g_CurrentTime) { #ifdef _DEBUG if (g_CurrentTime - 1 > Best) { #else if (g_CurrentTime - 5 > Best) { #endif Log("Time warp detected: %d seconds", g_CurrentTime - Best); } CTimer::CallTimers(); Best = CTimer::GetNextCall(); } SleepInterval = Best - g_CurrentTime; DnsSocketCookie *DnsCookie = CDnsQuery::RegisterSockets(); for (CListCursor<socket_t> SocketCursor(&m_OtherSockets); SocketCursor.IsValid(); SocketCursor.Proceed()) { if (SocketCursor->PollFd->fd == INVALID_SOCKET) { continue; } if (SocketCursor->Events->ShouldDestroy()) { SocketCursor->Events->Destroy(); } else { SocketCursor->PollFd->events = POLLIN | POLLERR; if (SocketCursor->Events->HasQueuedData()) { SocketCursor->PollFd->events |= POLLOUT; } } } bool ModulesBusy = false; for (int j = 0; j < m_Modules.GetLength(); j++) { if (m_Modules[j]->MainLoop()) { ModulesBusy = true; } } if (SleepInterval <= 0 || GetStatus() != Status_Running || ModulesBusy) { SleepInterval = 1; } if (GetStatus() != Status_Running && SleepInterval > 3) { SleepInterval = 3; } timeval interval = { (long)SleepInterval, 0 }; time(&Last); #ifdef _DEBUG //printf("poll: %d seconds\n", SleepInterval); #endif #if defined(_WIN32) && defined(_DEBUG) DWORD TimeDiff = GetTickCount(); #endif int ready = poll(m_PollFds.GetList(), m_PollFds.GetLength(), interval.tv_sec * 1000); #if defined(_WIN32) && defined(_DEBUG) TickCount += GetTickCount() - TimeDiff; #endif time(&g_CurrentTime); if (ready > 0) { for (CListCursor<socket_t> SocketCursor(&m_OtherSockets); SocketCursor.IsValid(); SocketCursor.Proceed()) { pollfd *PollFd = SocketCursor->PollFd; CSocketEvents *Events = SocketCursor->Events; if (PollFd->fd != INVALID_SOCKET) { if (PollFd->revents & (POLLERR|POLLHUP|POLLNVAL)) { int ErrorCode; socklen_t ErrorCodeLength = sizeof(ErrorCode); ErrorCode = 0; if (getsockopt(PollFd->fd, SOL_SOCKET, SO_ERROR, (char *)&ErrorCode, &ErrorCodeLength) != -1) { if (ErrorCode != 0) { Events->Error(ErrorCode); } } if (ErrorCode == 0) { Events->Error(-1); } Events->Destroy(); continue; } if (PollFd->revents & (POLLIN|POLLPRI)) { int Code; if ((Code = Events->Read()) != 0) { Events->Error(Code); Events->Destroy(); continue; } } if (PollFd->revents & POLLOUT) { Events->Write(); } } } } else if (ready == -1) { #ifndef _WIN32 if (errno != EBADF && errno != 0) { #else if (errno != WSAENOTSOCK) { #endif continue; } m_OtherSockets.Lock(); for (CListCursor<socket_t> SocketCursor(&m_OtherSockets); SocketCursor.IsValid(); SocketCursor.Proceed()) { if (SocketCursor->PollFd->fd == INVALID_SOCKET) { continue; } pollfd pfd; pfd.fd = SocketCursor->PollFd->fd; pfd.events = POLLIN | POLLOUT | POLLERR; int code = poll(&pfd, 1, 0); if (code == -1) { SocketCursor->Events->Error(-1); SocketCursor->Events->Destroy(); } } } CDnsQuery::ProcessTimeouts(); CDnsQuery::UnregisterSockets(DnsCookie); #if defined(_WIN32) && defined(_DEBUG) DWORD Ticks = GetTickCount() - TickCount; if (Ticks > 50) { printf("Spent %d msec in the main loop.\n", Ticks); } #endif } #ifdef HAVE_LIBSSL SSL_CTX_free(m_SSLContext); SSL_CTX_free(m_SSLClientContext); #endif } /** * GetUser * * Returns a user object for the specified username (or NULL * if there's no such user). * * @param Name the username */ CUser *CCore::GetUser(const char *Name) { if (Name == NULL) { return NULL; } else { return m_Users.Get(Name); } } /** * GlobalNotice * * Sends a message to all bouncer users who are currently * logged in. * * @param Text the text of the message */ void CCore::GlobalNotice(const char *Text) { int i = 0; char *GlobalText; int rc = asprintf(&GlobalText, "Global admin message: %s", Text); if (RcFailed(rc)) { return; } while (hash_t<CUser *> *User = m_Users.Iterate(i++)) { if (User->Value->GetClientConnectionMultiplexer() != NULL) { User->Value->GetClientConnectionMultiplexer()->Privmsg(GlobalText); } else { User->Value->Log("%s", GlobalText); } } free(GlobalText); } /** * GetUsers * * Returns a hashtable which contains all bouncer users. */ CHashtable<CUser *, false> *CCore::GetUsers(void) { return &m_Users; } /** * SetIdent * * Sets the ident which is returned for the next ident request. * * @param Ident the ident */ void CCore::SetIdent(const char *Ident) { if (m_Ident != NULL) { m_Ident->SetIdent(Ident); } } /** * GetIdent * * Returns the ident which is to be returned for the next ident * request. */ const char *CCore::GetIdent(void) const { if (m_Ident != NULL) { return m_Ident->GetIdent(); } else { return NULL; } } /** * GetModules * * Returns a list of currently loaded modules. */ const CVector<CModule *> *CCore::GetModules(void) const { return &m_Modules; } /** * LoadModule * * Attempts to load a bouncer module. * * @param Filename the module's filename */ RESULT<CModule *> CCore::LoadModule(const char *Filename) { RESULT<bool> Result; CModule *Module = new CModule(Filename); if (AllocFailed(Module)) { THROW(CModule *, Generic_OutOfMemory, "new operator failed."); } Result = Module->GetError(); if (!IsError(Result)) { Result = m_Modules.Insert(Module); if (IsError(Result)) { delete Module; Log("Insert() failed. Could not load module"); THROWRESULT(CModule *, Result); } Log("Loaded module: %s", Module->GetFilename()); Module->Init(this); if (!m_LoadingModules) { UpdateModuleConfig(); } RETURN(CModule *, Module); } else { static char *ErrorString = NULL; free(ErrorString); ErrorString = strdup(GETDESCRIPTION(Result)); if (AllocFailed(ErrorString)) { delete Module; THROW(CModule *, Generic_OutOfMemory, "strdup() failed."); } Log("Module %s could not be loaded: %s", Filename, ErrorString); delete Module; THROW(CModule *, Generic_Unknown, ErrorString); } THROW(CModule *, Generic_Unknown, NULL); } /** * UnloadModule * * Unloads a module. * * @param Module the module */ bool CCore::UnloadModule(CModule *Module) { if (m_Modules.Remove(Module)) { Log("Unloaded module: %s", Module->GetFilename()); delete Module; UpdateModuleConfig(); return true; } else { return false; } } /** * UpdateModuleConfig * * Updates the module list in the main config. */ void CCore::UpdateModuleConfig(void) { char *Out; int a = 0, rc; for (int i = 0; i < m_Modules.GetLength(); i++) { rc = asprintf(&Out, "system.modules.mod%d", a++); if (RcFailed(rc)) { Fatal(); } m_Config->WriteString(Out, m_Modules[i]->GetFilename()); free(Out); } rc = asprintf(&Out, "system.modules.mod%d", a); if (RcFailed(rc)) { Fatal(); } m_Config->WriteString(Out, NULL); free(Out); }
/*=========================================================================*/ int main(int argc, char* argv[]) /*=========================================================================*/ { fd_set readfds; fd_set writefds; int highfd = 0; int fdcount = 0; SLPDSocket* sock = 0; SLPDSocket* del = 0; SLPDSocketList socketlist = {0,0}; /*------------------------------*/ /* Make sure we are root */ /*------------------------------*/ if(getuid() != 0) { SLPFatal("slpd must be started by root\n"); } /*------------------------*/ /* Parse the command line */ /*------------------------*/ if(SLPDParseCommandLine(argc,argv)) { SLPFatal("Invalid command line\n"); } /*------------------------------*/ /* Initialize the log file */ /*------------------------------*/ SLPLogFileOpen(G_SlpdCommandLine.logfile, 0); SLPLog("****************************************\n"); SLPLog("*** SLPD daemon started ***\n"); SLPLog("****************************************\n"); SLPLog("command line = %s\n",argv[0]); /*--------------------------------------------------*/ /* Initialize for the first time */ /*--------------------------------------------------*/ SLPDPropertyInit(G_SlpdCommandLine.cfgfile); SLPDDatabaseInit(G_SlpdCommandLine.regfile); SLPDSocketInit(&socketlist); /*---------------------------*/ /* make slpd run as a daemon */ /*---------------------------*/ if(Daemonize(G_SlpdCommandLine.pidfile)) { SLPFatal("Could not run as daemon\n"); } /*-----------------------*/ /* Setup signal handlers */ /*-----------------------*/ if(SetUpSignalHandlers()) { SLPFatal("Could not set up signal handlers.\n"); } /*------------------------------*/ /* Set up alarm to age database */ /*------------------------------*/ alarm(SLPD_AGE_TIMEOUT); /*-----------*/ /* Main loop */ /*-----------*/ while(G_SIGTERM == 0) { if(G_SIGHUP) { /* Reinitialize */ SLPLog("****************************************\n"); SLPLog("*** SLPD daemon restarted ***\n"); SLPLog("****************************************\n"); SLPLog("Got SIGHUP reinitializing... \n"); SLPDPropertyInit(G_SlpdCommandLine.cfgfile); SLPDDatabaseInit(G_SlpdCommandLine.regfile); SLPDSocketInit(&socketlist); G_SIGHUP = 0; } /*--------------------------------------------------------*/ /* Load the fdsets up with all of the sockets in the list */ /*--------------------------------------------------------*/ highfd = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); sock = socketlist.head; while(sock) { if(sock->fd > highfd) { highfd = sock->fd; } switch(sock->state) { case DATAGRAM_UNICAST: case DATAGRAM_MULTICAST: FD_SET(sock->fd,&readfds); break; case SOCKET_LISTEN: if(socketlist.count < SLPD_MAX_SOCKETS) { FD_SET(sock->fd,&readfds); } break; case STREAM_READ: case STREAM_FIRST_READ: FD_SET(sock->fd,&readfds); break; case STREAM_WRITE: case STREAM_FIRST_WRITE: FD_SET(sock->fd,&writefds); break; case SOCKET_CLOSE: default: break; } sock = (SLPDSocket*)sock->listitem.next; } /*-----------------------------------------------*/ /* Check to see if we we should age the database */ /*-----------------------------------------------*/ /* there is a reason this is here instead of somewhere else, but I */ /* can't remember what it was. */ if(G_SIGALRM) { SLPDDatabaseAge(SLPD_AGE_TIMEOUT); G_SIGALRM = 0; alarm(SLPD_AGE_TIMEOUT); } /*-------------*/ /* Main select */ /*-------------*/ fdcount = select(highfd+1,&readfds,&writefds,0,0); if(fdcount > 0) { sock = socketlist.head; while(sock && fdcount) { if(FD_ISSET(sock->fd,&readfds)) { switch(sock->state) { case SOCKET_LISTEN: HandleSocketListen(&socketlist,sock); break; case DATAGRAM_UNICAST: case DATAGRAM_MULTICAST: HandleDatagramRead(&socketlist,sock); break; case STREAM_READ: case STREAM_FIRST_READ: HandleStreamRead(&socketlist,sock); break; default: break; } fdcount --; } if(FD_ISSET(sock->fd,&writefds)) { HandleStreamWrite(&socketlist,sock); fdcount --; } /* Should we close the socket */ /* TODO: Close aged sockets */ if(sock->state == SOCKET_CLOSE) { del = sock; sock = (SLPDSocket*)sock->listitem.next; HandleSocketClose(&socketlist,del); } else { sock = (SLPDSocket*)sock->listitem.next; } } } } SLPLog("Got SIGTERM. Going down\n"); return 0; }
void Run(bool bReload) { g_pLog = new Log(); debug("nzbget %s", Util::VersionRevision()); if (!bReload) { Thread::Init(); } #ifdef WIN32 g_pWinConsole = new WinConsole(); g_pWinConsole->InitAppMode(); #endif g_pServerPool = new ServerPool(); g_pScheduler = new Scheduler(); g_pQueueCoordinator = new QueueCoordinator(); g_pStatMeter = new StatMeter(); g_pScanner = new Scanner(); g_pPrePostProcessor = new PrePostProcessor(); g_pHistoryCoordinator = new HistoryCoordinator(); g_pDupeCoordinator = new DupeCoordinator(); g_pUrlCoordinator = new UrlCoordinator(); g_pFeedCoordinator = new FeedCoordinator(); g_pArticleCache = new ArticleCache(); g_pMaintenance = new Maintenance(); g_pQueueScriptCoordinator = new QueueScriptCoordinator(); debug("Reading options"); g_pOptions = new Options(); g_pOptions->Init(g_iArgumentCount, *g_szArguments); #ifndef WIN32 if (g_pOptions->GetUMask() < 01000) { /* set newly created file permissions */ umask(g_pOptions->GetUMask()); } #endif g_pLog->InitOptions(); g_pScanner->InitOptions(); g_pQueueScriptCoordinator->InitOptions(); if (g_pOptions->GetDaemonMode()) { #ifdef WIN32 info("nzbget %s service-mode", Util::VersionRevision()); #else if (!bReload) { Daemonize(); } info("nzbget %s daemon-mode", Util::VersionRevision()); #endif } else if (g_pOptions->GetServerMode()) { info("nzbget %s server-mode", Util::VersionRevision()); } else if (g_pOptions->GetRemoteClientMode()) { info("nzbget %s remote-mode", Util::VersionRevision()); } if (!bReload) { Connection::Init(); } if (!g_pOptions->GetRemoteClientMode()) { g_pServerPool->InitConnections(); g_pStatMeter->Init(); } InstallErrorHandler(); #ifdef DEBUG if (g_pOptions->GetTestBacktrace()) { TestSegFault(); } #endif if (g_pOptions->GetWebGet()) { ProcessWebGet(); return; } // client request if (g_pOptions->GetClientOperation() != Options::opClientNoOperation) { ProcessClientRequest(); Cleanup(); return; } // Setup the network-server if (g_pOptions->GetServerMode()) { g_pRemoteServer = new RemoteServer(false); g_pRemoteServer->Start(); if (g_pOptions->GetSecureControl()) { g_pRemoteSecureServer = new RemoteServer(true); g_pRemoteSecureServer->Start(); } } // Create the frontend if (!g_pOptions->GetDaemonMode()) { switch (g_pOptions->GetOutputMode()) { case Options::omNCurses: #ifndef DISABLE_CURSES g_pFrontend = new NCursesFrontend(); break; #endif case Options::omColored: g_pFrontend = new ColoredFrontend(); break; case Options::omLoggable: g_pFrontend = new LoggableFrontend(); break; } } // Starting a thread with the frontend if (g_pFrontend) { g_pFrontend->Start(); } // Starting QueueCoordinator and PrePostProcessor if (!g_pOptions->GetRemoteClientMode()) { // Standalone-mode if (!g_pOptions->GetServerMode()) { const char* szCategory = g_pOptions->GetAddCategory() ? g_pOptions->GetAddCategory() : ""; NZBFile* pNZBFile = NZBFile::Create(g_pOptions->GetArgFilename(), szCategory); if (!pNZBFile) { abort("FATAL ERROR: Parsing NZB-document %s failed\n\n", g_pOptions->GetArgFilename() ? g_pOptions->GetArgFilename() : "N/A"); return; } g_pScanner->InitPPParameters(szCategory, pNZBFile->GetNZBInfo()->GetParameters(), false); g_pQueueCoordinator->AddNZBFileToQueue(pNZBFile, NULL, false); delete pNZBFile; } if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode()) { g_pDiskState = new DiskState(); } #ifdef WIN32 g_pWinConsole->Start(); #endif g_pQueueCoordinator->Start(); g_pUrlCoordinator->Start(); g_pPrePostProcessor->Start(); g_pFeedCoordinator->Start(); if (g_pOptions->GetArticleCache() > 0) { g_pArticleCache->Start(); } // enter main program-loop while (g_pQueueCoordinator->IsRunning() || g_pUrlCoordinator->IsRunning() || g_pPrePostProcessor->IsRunning() || g_pFeedCoordinator->IsRunning() || #ifdef WIN32 g_pWinConsole->IsRunning() || #endif g_pArticleCache->IsRunning()) { if (!g_pOptions->GetServerMode() && !g_pQueueCoordinator->HasMoreJobs() && !g_pUrlCoordinator->HasMoreJobs() && !g_pPrePostProcessor->HasMoreJobs()) { // Standalone-mode: download completed if (!g_pQueueCoordinator->IsStopped()) { g_pQueueCoordinator->Stop(); } if (!g_pUrlCoordinator->IsStopped()) { g_pUrlCoordinator->Stop(); } if (!g_pPrePostProcessor->IsStopped()) { g_pPrePostProcessor->Stop(); } if (!g_pFeedCoordinator->IsStopped()) { g_pFeedCoordinator->Stop(); } if (!g_pArticleCache->IsStopped()) { g_pArticleCache->Stop(); } } usleep(100 * 1000); } // main program-loop is terminated debug("QueueCoordinator stopped"); debug("UrlCoordinator stopped"); debug("PrePostProcessor stopped"); debug("FeedCoordinator stopped"); debug("ArticleCache stopped"); } ScriptController::TerminateAll(); // Stop network-server if (g_pRemoteServer) { debug("stopping RemoteServer"); g_pRemoteServer->Stop(); int iMaxWaitMSec = 1000; while (g_pRemoteServer->IsRunning() && iMaxWaitMSec > 0) { usleep(100 * 1000); iMaxWaitMSec -= 100; } if (g_pRemoteServer->IsRunning()) { debug("Killing RemoteServer"); g_pRemoteServer->Kill(); } debug("RemoteServer stopped"); } if (g_pRemoteSecureServer) { debug("stopping RemoteSecureServer"); g_pRemoteSecureServer->Stop(); int iMaxWaitMSec = 1000; while (g_pRemoteSecureServer->IsRunning() && iMaxWaitMSec > 0) { usleep(100 * 1000); iMaxWaitMSec -= 100; } if (g_pRemoteSecureServer->IsRunning()) { debug("Killing RemoteSecureServer"); g_pRemoteSecureServer->Kill(); } debug("RemoteSecureServer stopped"); } // Stop Frontend if (g_pFrontend) { if (!g_pOptions->GetRemoteClientMode()) { debug("Stopping Frontend"); g_pFrontend->Stop(); } while (g_pFrontend->IsRunning()) { usleep(50 * 1000); } debug("Frontend stopped"); } Cleanup(); }
/** Process main entry point. * * @param[in] argc - The number of command line arguments passed in @p argv. * @param[in] argv - An array of pointers to command line arguments. * * @return Zero on success, or a non-zero shell error code. * * @remarks This routine contains the main server loop. */ int main(int argc, char * argv[]) { fd_set readfds; fd_set writefds; int highfd; int fdcount = 0; time_t curtime; struct timeval timeout; #ifdef DEBUG xmalloc_init("/var/log/slpd_xmalloc.log", 0); #endif /* Parse the command line */ if (SLPDParseCommandLine(argc,argv)) SLPDFatal("Invalid command line\n"); /* make sure we are root */ if (getuid() != 0) SLPDFatal("slpd must be started by root\n"); /* make sure we are not already running */ if (CheckPid(G_SlpdCommandLine.pidfile)) SLPDFatal("slpd is already running. Check %s\n", G_SlpdCommandLine.pidfile); /* Initialize the preferences so we know if the log file is to be overwritten or appended.*/ if (SLPDPropertyInit(G_SlpdCommandLine.cfgfile)) SLPDFatal("slpd initialization failed during property load\n"); /* make slpd run as a daemon */ if (Daemonize(G_SlpdCommandLine.pidfile)) SLPDFatal("Could not daemonize\n"); /* initialize the log file */ if (SLPDLogFileOpen(G_SlpdCommandLine.logfile, G_SlpdProperty.appendLog)) SLPDFatal("Could not open logfile %s\n",G_SlpdCommandLine.logfile); /* seed the XID generator */ SLPXidSeed(); /* log startup message */ SLPDLog("****************************************\n"); SLPDLogTime(); SLPDLog("SLPD daemon started\n"); SLPDLog("****************************************\n"); SLPDLog("Command line = %s\n", argv[0]); SLPDLog("Using configuration file = %s\n", G_SlpdCommandLine.cfgfile); SLPDLog("Using registration file = %s\n", G_SlpdCommandLine.regfile); #ifdef ENABLE_SLPv2_SECURITY SLPDLog("Using SPI file = %s\n", G_SlpdCommandLine.spifile); #endif /* initialize for the first time */ SLPDPropertyReinit(); /*So we get any property-related log messages*/ if ( #ifdef ENABLE_SLPv2_SECURITY SLPDSpiInit(G_SlpdCommandLine.spifile) || #endif SLPDDatabaseInit(G_SlpdCommandLine.regfile) || SLPDIncomingInit() || SLPDOutgoingInit() || SLPDKnownDAInit()) SLPDFatal("slpd initialization failed\n"); SLPDLog("Agent Interfaces = %s\n", G_SlpdProperty.interfaces); if (G_SlpdProperty.port != SLP_RESERVED_PORT) SLPDLog("Using port %d instead of default %d\n", G_SlpdProperty.port, SLP_RESERVED_PORT); /* drop privileges to reduce security risk */ if (DropPrivileges()) SLPDFatal("Could not drop privileges\n"); /* Setup signal handlers */ if (SetUpSignalHandlers()) SLPDFatal("Error setting up signal handlers.\n"); /* Set up alarm to age database -- a shorter start, so SAs register with us quickly on our startup */ alarm(2); /* Main loop */ SLPDLog("Startup complete entering main run loop ...\n\n"); G_SIGALRM = 0; G_SIGTERM = 0; G_SIGHUP = 0; #ifdef DEBUG G_SIGINT = 0; G_SIGUSR1 = 0; #endif while (G_SIGTERM == 0) { /* load the fdsets up with all valid sockets in the list */ highfd = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); LoadFdSets(&G_IncomingSocketList, &highfd, &readfds, &writefds); LoadFdSets(&G_OutgoingSocketList, &highfd, &readfds, &writefds); /* before select(), check to see if we got a signal */ if (G_SIGALRM || G_SIGHUP) goto HANDLE_SIGNAL; /* main select -- we time out every second so the outgoing retries can occur*/ time(&curtime); timeout.tv_sec = 1; timeout.tv_usec = 0; fdcount = select(highfd + 1, &readfds, &writefds, 0, &timeout); if (fdcount > 0) /* fdcount will be < 0 when interrupted by a signal */ { SLPDIncomingHandler(&fdcount, &readfds, &writefds); SLPDOutgoingHandler(&fdcount, &readfds, &writefds); SLPDOutgoingRetry(time(0) - curtime); } else if (fdcount == 0) SLPDOutgoingRetry(time(0) - curtime); HANDLE_SIGNAL: if (G_SIGHUP) { HandleSigHup(); G_SIGHUP = 0; } if (G_SIGALRM) { HandleSigAlrm(); G_SIGALRM = 0; alarm(SLPD_AGE_INTERVAL); } #ifdef DEBUG if (G_SIGINT) { HandleSigInt(); G_SIGINT = 0; } if (G_SIGUSR1) { HandleSigUsr1(); G_SIGUSR1 = 0; } #endif } /* End of main loop */ /* Got SIGTERM */ HandleSigTerm(); return 0; }
void NZBGet::Init() { m_log = std::make_unique<Log>(); debug("nzbget %s", Util::VersionRevision()); if (!m_reloading) { Thread::Init(); Connection::Init(); #ifndef DISABLE_TLS TlsSocket::Init(); #endif } CreateGlobals(); #ifdef WIN32 m_winConsole->InitAppMode(); #endif BootConfig(); #ifndef WIN32 if (m_options->GetUMask() < 01000) { /* set newly created file permissions */ umask(m_options->GetUMask()); } #endif m_scanner->InitOptions(); m_queueScriptCoordinator->InitOptions(); if (m_commandLineParser->GetDaemonMode()) { #ifdef WIN32 info("nzbget %s service-mode", Util::VersionRevision()); #else if (!m_reloading) { Daemonize(); } info("nzbget %s daemon-mode", Util::VersionRevision()); #endif } else if (m_options->GetServerMode()) { info("nzbget %s server-mode", Util::VersionRevision()); } else if (m_commandLineParser->GetRemoteClientMode()) { info("nzbget %s remote-mode", Util::VersionRevision()); } m_reloading = false; if (!m_commandLineParser->GetRemoteClientMode()) { m_serverPool->InitConnections(); m_statMeter->Init(); } InstallErrorHandler(); }