blob: a88dba84ae0961a8434f25df5cb536e413c35767 [file]
/** @file
A brief file description
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
*
* Main.cc
* - Entry point to the traffic manager.
* - Splitted off from LocalManager.cc on 10/23/98.
*
*
*/
#include "Main.h"
#include "MgmtUtils.h"
#include "MgmtSchema.h"
#include "MgmtConverter.h"
#include "WebMgmtUtils.h"
#include "WebIntrMain.h"
#include "MgmtRaf.h"
#include "WebOverview.h"
#include "FileManager.h"
#include "WebReconfig.h"
#include "I_Version.h"
#include "ink_syslog.h"
#include "ink_lockfile.h"
#include "Diags.h"
#include "DiagsConfig.h"
#include "URL.h"
#include "MIME.h"
#include "HTTP.h"
#include "RecordsConfig.h"
#if defined(HAVE_LIBSSL) && defined(TRAFFIC_NET)
#include "traffic_net/tn_Thread.h"
#endif
#if defined(MGMT_API)
#include "TSControlMain.h"
#endif
#define USE_STATPRO
#if defined(USE_STATPRO)
#include "StatProcessor.h"
#else
#include "StatAggregation.h"
#endif
#include "P_RecLocal.h"
#include "P_RecCore.h"
#if defined(OEM)
#include "tools/ConfigAPI.h"
#include "tools/SysAPI.h"
#endif
#define FD_THROTTLE_HEADROOM (128 + 64) // TODO: consolidate with THROTTLE_FD_HEADROOM
#if (HOST_OS != linux)
extern "C"
{
int gethostname(char *name, int namelen);
}
#endif
#if (HOST_OS == freebsd)
extern "C" int getpwnam_r(const char *name, struct passwd *result, char *buffer, size_t buflen, struct passwd **resptr);
#endif
//SNMP *snmp; // global binding with SNMP.cc
LocalManager *lmgmt = NULL;
MgmtPing *icmp_ping;
FileManager *configFiles;
#if defined(USE_STATPRO)
StatProcessor *statProcessor; // Statistics Processors
#endif
AppVersionInfo appVersionInfo; // Build info for this application
inkcoreapi Diags *diags;
inkcoreapi DiagsConfig *diagsConfig;
char debug_tags[1024] = "";
char action_tags[1024] = "";
int diags_init = 0;
int snmpLogLevel = 0;
bool proxy_on = true;
bool forceProcessRecordsSnap = false;
bool schema_on = false;
char *schema_path = NULL;
bool xml_on = false;
char *xml_path = NULL;
char system_root_dir[PATH_NAME_MAX + 1] = DEFAULT_ROOT_DIRECTORY;
char system_local_state_dir[PATH_NAME_MAX + 1] = DEFAULT_LOCAL_STATE_DIRECTORY;
char system_config_directory[PATH_NAME_MAX + 1] = DEFAULT_SYSTEM_CONFIG_DIRECTORY;
char system_log_dir[PATH_NAME_MAX + 1] = DEFAULT_LOG_DIRECTORY;
char mgmt_path[PATH_NAME_MAX + 1] = DEFAULT_SYSTEM_CONFIG_DIRECTORY;
// By default, set the current directory as base
char *ts_base_dir = ".";
char *recs_conf = "records.config";
int fds_limit;
typedef void (*PFV) (int);
#if (HOST_OS != linux) && (HOST_OS != freebsd)
void SignalHandler(int sig, siginfo_t * t, void *f);
void SignalAlrmHandler(int sig, siginfo_t * t, void *f);
#else
void SignalHandler(int sig);
void SignalAlrmHandler(int sig);
#endif
volatile int sigHupNotifier = 0;
volatile int sigUsr2Notifier = 0;
void SigChldHandler(int sig);
void
check_lockfile()
{
char lockfile[PATH_MAX];
int err;
pid_t holding_pid;
//////////////////////////////////////
// test for presence of server lock //
//////////////////////////////////////
ink_snprintf(lockfile, PATH_MAX, "%s%s%s", system_local_state_dir, DIR_SEP, SERVER_LOCK);
Lockfile server_lockfile(lockfile);
err = server_lockfile.Open(&holding_pid);
if (err == 1) {
server_lockfile.Close(); // no server running
} else {
char *reason = strerror(-err);
if (err == 0) {
fprintf(stderr, "FATAL: Lockfile '%s' says server already running as PID %d\n", lockfile, holding_pid);
mgmt_elog(stderr, "FATAL: Lockfile '%s' says server already running as PID %d\n", lockfile, holding_pid);
} else {
fprintf(stderr, "FATAL: Can't open server lockfile '%s' (%s)\n", lockfile, (reason ? reason : "Unknown Reason"));
mgmt_elog(stderr, "FATAL: Can't open server lockfile '%s' (%s)\n",
lockfile, (reason ? reason : "Unknown Reason"));
}
exit(1);
}
///////////////////////////////////////////
// try to get the exclusive manager lock //
///////////////////////////////////////////
ink_snprintf(lockfile, sizeof(lockfile), "%s%s%s", system_local_state_dir, DIR_SEP, MANAGER_LOCK);
Lockfile manager_lockfile(lockfile);
err = manager_lockfile.Get(&holding_pid);
if (err != 1) {
char *reason = strerror(-err);
fprintf(stderr, "FATAL: Can't acquire manager lockfile '%s'", lockfile);
mgmt_elog(stderr, "FATAL: Can't acquire manager lockfile '%s'", lockfile);
if (err == 0) {
fprintf(stderr, " (Lock file held by process ID %d)\n", holding_pid);
mgmt_elog(stderr, " (Lock file held by process ID %d)\n", holding_pid);
} else if (reason) {
fprintf(stderr, " (%s)\n", reason);
mgmt_elog(stderr, " (%s)\n", reason);
} else {
fprintf(stderr, "\n");
}
exit(1);
fprintf(stderr, "unable to acquire manager lock [%d]\n", -err);
exit(1);
}
}
void
initSignalHandlers()
{
#ifndef _WIN32
struct sigaction sigHandler, sigChldHandler, sigAlrmHandler;
sigset_t sigsToBlock;
// Set up the signal handler
#if (HOST_OS != linux) && (HOST_OS != freebsd)
sigHandler.sa_handler = NULL;
sigHandler.sa_sigaction = SignalHandler;
#else
sigHandler.sa_handler = SignalHandler;
#endif
sigemptyset(&sigHandler.sa_mask);
// We want the handler to remain in place on
// SIGHUP to avoid any races with the signals
// coming too quickly. Also restart systems calls
// after the signal since not all calls are wrapped
// to check errno for EINTR
sigHandler.sa_flags = SA_RESTART;
sigaction(SIGHUP, &sigHandler, NULL);
sigaction(SIGUSR2, &sigHandler, NULL);
// Don't block the signal on entry to the signal
// handler so we can reissue it and get a core
// file in the appropriate circumstances
#if (HOST_OS != linux) && (HOST_OS != freebsd)
sigHandler.sa_flags = SA_RESETHAND | SA_SIGINFO;
#else
sigHandler.sa_flags = SA_RESETHAND;
#endif
sigaction(SIGINT, &sigHandler, NULL);
sigaction(SIGQUIT, &sigHandler, NULL);
sigaction(SIGILL, &sigHandler, NULL);
sigaction(SIGBUS, &sigHandler, NULL);
sigaction(SIGSEGV, &sigHandler, NULL);
sigaction(SIGTERM, &sigHandler, NULL);
#if (HOST_OS != linux) && (HOST_OS != freebsd)
sigAlrmHandler.sa_handler = NULL;
sigAlrmHandler.sa_sigaction = SignalAlrmHandler;
#else
sigAlrmHandler.sa_handler = SignalAlrmHandler;
#endif
sigemptyset(&sigAlrmHandler.sa_mask);
#if (HOST_OS != linux) && (HOST_OS != freebsd)
sigAlrmHandler.sa_flags = SA_SIGINFO;
#else
sigAlrmHandler.sa_flags = 0;
#endif
sigaction(SIGALRM, &sigAlrmHandler, NULL);
// Block the delivery of any signals we are not catching
//
// except for SIGALARM since we use it
// to break out of deadlock on semaphore
// we share with the proxy
//
sigfillset(&sigsToBlock);
sigdelset(&sigsToBlock, SIGHUP);
sigdelset(&sigsToBlock, SIGUSR2);
sigdelset(&sigsToBlock, SIGINT);
sigdelset(&sigsToBlock, SIGQUIT);
sigdelset(&sigsToBlock, SIGILL);
sigdelset(&sigsToBlock, SIGABRT);
sigdelset(&sigsToBlock, SIGBUS);
sigdelset(&sigsToBlock, SIGSEGV);
sigdelset(&sigsToBlock, SIGTERM);
sigdelset(&sigsToBlock, SIGALRM);
ink_thread_sigsetmask(SIG_SETMASK, &sigsToBlock, NULL);
// Set up the SIGCHLD handler so we do not get into
// a problem with Solaris 2.6 and strange waitpid()
// behavior
sigChldHandler.sa_handler = SigChldHandler;
sigChldHandler.sa_flags = SA_RESTART;
sigemptyset(&sigChldHandler.sa_mask);
sigaction(SIGCHLD, &sigChldHandler, NULL);
#endif /* !_WIN32 */
}
#if (HOST_OS == linux)
#include <sys/prctl.h>
#endif
static int
setup_coredump()
{
#if (HOST_OS == linux)
#ifndef PR_SET_DUMPABLE
#define PR_SET_DUMPABLE 4 /* Ugly, but we cannot compile with 2.2.x otherwise.
Should be removed when we compile only on 2.4.x */
#endif
prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
#endif // linux check
return 0;
}
static void
init_dirs(bool use_librecords = true)
{
struct stat s;
int err;
if ((err = stat(mgmt_path, &s)) < 0) {
if (use_librecords)
REC_ReadConfigString(mgmt_path, "proxy.config.config_dir", PATH_NAME_MAX);
if ((err = stat(mgmt_path, &s)) < 0) {
// Try 'system_root_dir/etc/trafficserver' directory
snprintf(mgmt_path, sizeof(mgmt_path),
"%s%s%s%s%s",system_root_dir, DIR_SEP,"etc",DIR_SEP,"trafficserver");
if ((err = stat(mgmt_path, &s)) < 0) {
mgmt_elog("unable to stat() mgmt path '%s': %d %d, %s\n",
mgmt_path, err, errno, strerror(errno));
mgmt_elog("please set config path via command line '-path <path>' or 'proxy.config.config_dir' \n");
_exit(1);
}
}
}
if ((err = stat(system_config_directory, &s)) < 0) {
ink_strncpy(system_config_directory,mgmt_path,sizeof(system_config_directory));
if ((err = stat(system_config_directory, &s)) < 0) {
if (use_librecords)
REC_ReadConfigString(system_config_directory, "proxy.config.config_dir", PATH_NAME_MAX);
if ((err = stat(system_config_directory, &s)) < 0) {
// Try 'system_root_dir/etc/trafficserver' directory
snprintf(system_config_directory, sizeof(system_config_directory),
"%s%s%s%s%s",system_root_dir, DIR_SEP,"etc",DIR_SEP,"trafficserver");
if ((err = stat(system_config_directory, &s)) < 0) {
mgmt_elog("unable to stat() config dir '%s': %d %d, %s\n",
system_config_directory, err, errno, strerror(errno));
mgmt_elog("please set config path via command line '-path <path>' or 'proxy.config.config_dir' \n");
_exit(1);
}
}
}
}
if ((err = stat(system_local_state_dir, &s)) < 0) {
if (use_librecords)
REC_ReadConfigString(system_local_state_dir, "proxy.config.local_state_dir", PATH_NAME_MAX);
if ((err = stat(system_local_state_dir, &s)) < 0) {
// Try 'system_root_dir/var/trafficserver' directory
snprintf(system_local_state_dir, sizeof(system_local_state_dir),
"%s%s%s%s%s",system_root_dir, DIR_SEP,"var",DIR_SEP,"trafficserver");
if ((err = stat(system_local_state_dir, &s)) < 0) {
mgmt_elog("unable to stat() local state dir '%s': %d %d, %s\n",
system_local_state_dir, err, errno, strerror(errno));
mgmt_elog("please set 'proxy.config.local_state_dir'\n");
_exit(1);
}
}
}
if ((err = stat(system_log_dir, &s)) < 0) {
if (use_librecords)
REC_ReadConfigString(system_log_dir, "proxy.config.log2.logfile_dir", PATH_NAME_MAX);
if ((err = stat(system_log_dir, &s)) < 0) {
// Try 'system_root_dir/var/log/trafficserver' directory
snprintf(system_log_dir, sizeof(system_log_dir), "%s%s%s%s%s%s%s",
system_root_dir, DIR_SEP,"var",DIR_SEP,"log",DIR_SEP,"trafficserver");
if ((err = stat(system_log_dir, &s)) < 0) {
mgmt_elog("unable to stat() log dir'%s': %d %d, %s\n",
system_log_dir, err, errno, strerror(errno));
mgmt_elog("please set 'proxy.config.log2.logfile_dir'\n");
_exit(1);
}
}
}
}
void
chdir_root()
{
char buffer[1024];
char *env_path;
FILE *ts_file;
int i = 0;
if ((env_path = getenv("TS_ROOT"))) {
ink_strncpy(system_root_dir, env_path, sizeof(system_root_dir));
} else {
if ((ts_file = fopen(DEFAULT_TS_DIRECTORY_FILE, "r")) != NULL) {
NOWARN_UNUSED_RETURN(fgets(buffer, 1024, ts_file));
fclose(ts_file);
while (!isspace(buffer[i])) {
system_root_dir[i] = buffer[i];
i++;
}
system_root_dir[i] = '\0';
} else {
ink_strncpy(system_root_dir, PREFIX, sizeof(system_root_dir));
}
}
if (system_root_dir[0] && (chdir(system_root_dir) < 0)) {
mgmt_elog("unable to change to root directory \"%s\" [%d '%s']\n", system_root_dir, errno, strerror(errno));
mgmt_elog(" please set correct path in env variable TS_ROOT \n");
exit(1);
} else {
mgmt_log("[TrafficManager] using root directory '%s'\n",system_root_dir);
}
}
#define set_rlimit(name,max_it,ulim_it) max_out_limit(#name, name, max_it, ulim_it)
static rlim_t
max_out_limit(char *name, int which, bool max_it = true, bool unlim_it = true)
{
struct rlimit rl;
#if (HOST_OS == linux)
# define MAGIC_CAST(x) (enum __rlimit_resource)(x)
#else
# define MAGIC_CAST(x) x
#endif
if (max_it) {
ink_release_assert(getrlimit(MAGIC_CAST(which), &rl) >= 0);
if (rl.rlim_cur != rl.rlim_max) {
rl.rlim_cur = rl.rlim_max;
ink_release_assert(setrlimit(MAGIC_CAST(which), &rl) >= 0);
}
}
if (unlim_it) {
ink_release_assert(getrlimit(MAGIC_CAST(which), &rl) >= 0);
if (rl.rlim_cur != RLIM_INFINITY) {
rl.rlim_cur = (rl.rlim_max = RLIM_INFINITY);
ink_release_assert(setrlimit(MAGIC_CAST(which), &rl) >= 0);
}
}
ink_release_assert(getrlimit(MAGIC_CAST(which), &rl) >= 0);
#ifdef MGMT_USE_SYSLOG
//syslog(LOG_NOTICE, "NOTE: %s(%d):cur(%d),max(%d)", name, which, (int)rl.rlim_cur, (int)rl.rlim_max);
#endif
return rl.rlim_cur;
}
static void
set_process_limits(int fds_throttle)
{
struct rlimit lim;
// Set needed rlimits (root)
set_rlimit(RLIMIT_NOFILE, true, false);
set_rlimit(RLIMIT_STACK, true, true);
set_rlimit(RLIMIT_DATA, true, true);
set_rlimit(RLIMIT_FSIZE, true, false);
set_rlimit(RLIMIT_RSS, true, true);
if (!getrlimit(RLIMIT_NOFILE, &lim)) {
if (fds_throttle > (int) (lim.rlim_cur + FD_THROTTLE_HEADROOM)) {
lim.rlim_cur = (lim.rlim_max = (rlim_t) fds_throttle);
if (!setrlimit(RLIMIT_NOFILE, &lim) && !getrlimit(RLIMIT_NOFILE, &lim)) {
fds_limit = (int) lim.rlim_cur;
#ifdef MGMT_USE_SYSLOG
syslog(LOG_NOTICE, "NOTE: RLIMIT_NOFILE(%d):cur(%d),max(%d)",RLIMIT_NOFILE, (int)lim.rlim_cur, (int)lim.rlim_max);
#endif
}
}
}
}
int
main(int argc, char **argv)
{
// change the directory to the "root" directory
chdir_root();
// Line buffer standard output & standard error
int status;
status = setvbuf(stdout, NULL, _IOLBF, 0);
if (status != 0)
perror("WARNING: can't line buffer stdout");
status = setvbuf(stderr, NULL, _IOLBF, 0);
if (status != 0)
perror("WARNING: can't line buffer stderr");
bool found = false;
int just_started = 0;
int cluster_port = -1, cluster_server_port = -1;
int dump_config = 0, dump_process = 0, dump_node = 0, proxy_port = -1;
int dump_cluster = 0, dump_local = 0, proxy_backdoor = -1;
char *envVar = NULL, *group_addr = NULL, *tsArgs = NULL;
bool log_to_syslog = true;
char userToRunAs[80];
char config_internal_dir[PATH_MAX];
int fds_throttle = -1;
time_t ticker;
ink_thread webThrId;
while ((setsid() == (pid_t) - 1) && (errno == EINTR)) {
}
// Set up the application version info
appVersionInfo.setup(PACKAGE_NAME,"traffic_manager", PACKAGE_VERSION,
__DATE__, __TIME__, BUILD_MACHINE, BUILD_PERSON, "");
initSignalHandlers();
// Process Environment Variables
if ((envVar = getenv("MGMT_WEB_PORT")) != NULL) {
web_port_arg = atoi(envVar);
}
if ((envVar = getenv("MGMT_ACONF_PORT")) != NULL) {
aconf_port_arg = atoi(envVar);
}
if ((envVar = getenv("MGMT_CLUSTER_PORT")) != NULL) {
cluster_port = atoi(envVar);
}
if ((envVar = getenv("MGMT_CLUSTER_RS_PORT")) != NULL) {
cluster_server_port = atoi(envVar);
}
if ((envVar = getenv("MGMT_GROUP_ADDR")) != NULL) {
group_addr = envVar;
}
for (int i = 1; i < argc; i++) { /* Process command line args */
if (argv[i][0] == '-') {
if ((strcmp(argv[i], "-version") == 0) || (strcmp(argv[i], "-V") == 0)) {
fprintf(stderr, "%s\n", appVersionInfo.FullVersionInfoStr);
exit(0);
} else if (strcmp(argv[i], "-proxyOff") == 0) {
proxy_on = false;
} else if (strcmp(argv[i], "-nosyslog") == 0) {
log_to_syslog = false;
} else if (strcmp(argv[i], "-snmplog") == 0) {
i++;
snmpLogLevel = atoi(argv[i]);
} else {
// The rest of the options require an argument in the form of -<Flag> <val>
if ((i + 1) < argc) {
if (strcmp(argv[i], "-webPort") == 0) {
++i;
web_port_arg = atoi(argv[i]);
} else if (strcmp(argv[i], "-aconfPort") == 0) {
++i;
aconf_port_arg = atoi(argv[i]);
} else if (strcmp(argv[i], "-clusterPort") == 0) {
++i;
cluster_port = atoi(argv[i]);
} else if (strcmp(argv[i], "-groupAddr") == 0) {
++i;
group_addr = argv[i];
} else if (strcmp(argv[i], "-clusterRSPort") == 0) {
++i;
cluster_server_port = atoi(argv[i]);
#ifndef NO_DIAGS
} else if (strcmp(argv[i], "-debug") == 0) {
++i;
strncpy(debug_tags, argv[i], 1023);
debug_tags[1023] = '\0';
} else if (strcmp(argv[i], "-action") == 0) {
++i;
strncpy(action_tags, argv[i], 1023);
action_tags[1023] = '\0';
#endif
} else if (strcmp(argv[i], "-path") == 0) {
++i;
//bugfixed by YTS Team, yamsat(id-59703)
if ((strlen(argv[i]) > PATH_NAME_MAX)) {
fprintf(stderr, "\n Path exceeded the maximum allowed characters.\n");
exit(1);
}
ink_strncpy(mgmt_path, argv[i], sizeof(mgmt_path));
/*
} else if(strcmp(argv[i], "-lmConf") == 0) {
++i;
lm_conf = argv[i];
*/
} else if (strcmp(argv[i], "-recordsConf") == 0) {
++i;
recs_conf = argv[i];
} else if (strcmp(argv[i], "-printRecords") == 0) {
++i;
while (i < argc && argv[i][0] != '-') {
if (strcasecmp(argv[i], "config") == 0) {
dump_config = 1;
} else if (strcasecmp(argv[i], "process") == 0) {
dump_process = 1;
} else if (strcasecmp(argv[i], "node") == 0) {
dump_node = 1;
} else if (strcasecmp(argv[i], "cluster") == 0) {
dump_cluster = 1;
} else if (strcasecmp(argv[i], "local") == 0) {
dump_local = 1;
} else if (strcasecmp(argv[i], "all") == 0) {
dump_config = dump_node = dump_process = dump_cluster = dump_local = 1;
}
++i;
}
--i;
} else if (strcmp(argv[i], "-tsArgs") == 0) {
int size_of_args = 0, j = (++i);
while (j < argc) {
size_of_args += 1;
size_of_args += strlen((argv[j++]));
}
ink_assert((tsArgs = (char *) xmalloc(size_of_args + 1)));
j = 0;
while (i < argc) {
ink_snprintf(&tsArgs[j], ((size_of_args + 1) - j), " %s", argv[i]);
j += strlen(argv[i]) + 1;
++i;
}
} else if (strcmp(argv[i], "-proxyPort") == 0) {
++i;
proxy_port = atoi(argv[i]);
} else if (strcmp(argv[i], "-proxyBackDoor") == 0) {
++i;
proxy_backdoor = atoi(argv[i]);
} else if (strcmp(argv[i], "-vingid") == 0) {
// smanager/cnp integration, this argument is
// really just a dummy argument used so that
// smanager can find all instances of a
// particular TM process.
++i;
} else if (strcmp(argv[i], "-schema") == 0) {
// hidden option
++i;
schema_path = argv[i];
schema_on = true;
} else if (strcmp(argv[i], "-xml") == 0) { // hidden option
++i;
xml_path = argv[i];
xml_on = true;
} else {
printUsage();
}
} else {
printUsage();
}
}
}
}
#ifdef MGMT_USE_SYSLOG
// Bootstrap with LOG_DAEMON until we've read our configuration
if (log_to_syslog) {
openlog("traffic_manager", LOG_PID | LOG_NDELAY | LOG_NOWAIT, LOG_DAEMON);
mgmt_use_syslog();
syslog(LOG_NOTICE, "NOTE: --- Manager Starting ---");
syslog(LOG_NOTICE, "NOTE: Manager Version: %s", appVersionInfo.FullVersionInfoStr);
}
#endif /* MGMT_USE_SYSLOG */
// Bootstrap the Diags facility so that we can use it while starting
// up the manager
diagsConfig = NEW(new DiagsConfig(debug_tags, action_tags, false));
diags = diagsConfig->diags;
diags->prefix_str = "Manager ";
/* Disable 12/14/98 (see explanation below)
icmp_ping = new MgmtPing(); */
icmp_ping = NULL;
init_dirs(false);// setup directories
// Get the config info we need while we are still root
extractConfigInfo(mgmt_path, recs_conf, userToRunAs, &fds_throttle);
set_process_limits(fds_throttle); // as root
runAsUser(userToRunAs);
setup_coredump();
check_lockfile();
ink_snprintf(config_internal_dir, sizeof(config_internal_dir),
"%s%sinternal", mgmt_path, DIR_SEP);
url_init(config_internal_dir);
mime_init(config_internal_dir);
http_init(config_internal_dir);
#if defined(MGMT_API)
// initialize alarm queue
int ret;
ret = init_mgmt_alarm_q(mgmt_alarm_event_q);
if (ret < 0)
mgmt_alarm_event_q = NULL;
#endif
RecLocalInit();
LibRecordsConfigInit();
lmgmt = new LocalManager(mgmt_path, new LMRecords(mgmt_path, recs_conf, 0), proxy_on);
RecLocalInitMessage();
lmgmt->initAlarm();
if (diags) {
delete diagsConfig;
// diagsConfig->reconfigure_diags(); INKqa11968
/*
delete diags;
diags = NEW (new Diags(debug_tags,action_tags));
*/
}
// INKqa11968: need to set up callbacks and diags data structures
// using configuration in records.config
diagsConfig = NEW(new DiagsConfig(debug_tags, action_tags, true));
diags = diagsConfig->diags;
RecSetDiags(diags);
diags->prefix_str = "Manager ";
if (is_debug_tag_set("diags"))
diags->dump();
diags->cleanup_func = mgmt_cleanup;
diags_init = 1;
// Setup the exported manager version records.
RecSetRecordString("proxy.node.version.manager.short", appVersionInfo.VersionStr);
RecSetRecordString("proxy.node.version.manager.long", appVersionInfo.FullVersionInfoStr);
RecSetRecordString("proxy.node.version.manager.build_number", appVersionInfo.BldNumStr);
RecSetRecordString("proxy.node.version.manager.build_time", appVersionInfo.BldTimeStr);
RecSetRecordString("proxy.node.version.manager.build_date", appVersionInfo.BldDateStr);
RecSetRecordString("proxy.node.version.manager.build_machine", appVersionInfo.BldMachineStr);
RecSetRecordString("proxy.node.version.manager.build_person", appVersionInfo.BldPersonStr);
// RecSetRecordString("proxy.node.version.manager.build_compile_flags",
// appVersionInfo.BldCompileFlagsStr);
#ifdef MGMT_USE_SYSLOG
if (log_to_syslog) {
char sys_var[] = "proxy.config.syslog_facility";
char *facility_str = NULL;
int facility_int;
facility_str = REC_readString(sys_var, &found);
ink_assert(found);
if (!found) {
mgmt_elog("Could not read %s. Defaulting to DAEMON\n", sys_var);
facility_int = LOG_DAEMON;
} else {
facility_int = facility_string_to_int(facility_str);
xfree(facility_str);
if (facility_int < 0) {
mgmt_elog("Bad syslog facility specified. Defaulting to DAEMON\n");
facility_int = LOG_DAEMON;
}
}
// NOTE: do NOT call closelog() here. Solaris gets confused
// and some how it hoses later calls to readdir_r.
openlog("traffic_manager", LOG_PID | LOG_NDELAY | LOG_NOWAIT, facility_int);
lmgmt->syslog_facility = facility_int;
} else {
lmgmt->syslog_facility = -1;
}
#endif /* MGMT_USE_SYSLOG */
#ifdef USE_SNMP
ink_thread snmpThrId;
SNMPStateInit();
snmp = new SNMP();
if (snmpLogLevel > 0) {
snmp->enableLogging(snmpLogLevel);
}
#endif
/****************************
* Register Alarm Callbacks *
****************************/
lmgmt->alarm_keeper->registerCallback(overviewAlarmCallback);
#ifdef USE_SNMP
lmgmt->alarm_keeper->registerCallback(snmpAlarmCallback);
#endif
// Find out our hostname so we can use it as part of the initialization
setHostnameVar();
// Create the data structure for overview page
// Do this before the rest of the set up since it needs
// to created to handle any alarms thrown by later
// initialization
overviewGenerator = new overviewPage();
// Initialize the Config Object bindings before
// starting any other threads
configFiles = new FileManager();
initializeRegistry();
configFiles->registerCallback(fileUpdated);
// RecLocal's 'sync_thr' depends on 'configFiles', so we can't
// stat the 'sync_thr' until 'configFiles' has been initialized.
RecLocalStart();
/* Disabled 12/14/98
* Goldmine is seeing ping failures for no apparent reason.
* My tests show that the ping packets go over the loop back interface
* and the driver forwards them to loop back even if the link status
* for the interface is down
if(!icmp_ping->init()) { // Initialize after the records data object has been created
delete icmp_ping;
icmp_ping = NULL;
lmgmt->alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_SYSTEM_ERROR,
"Unable to open raw icmp socket, Virtual IP failover at risk"
" if multiple interfaces are present on this node.");
}
*/
/* Update cmd line overrides/environmental overrides/etc */
if (tsArgs) { /* Passed command line args for proxy */
if (lmgmt->proxy_options) {
xfree(lmgmt->proxy_options);
}
lmgmt->proxy_options = tsArgs;
mgmt_log(stderr, "[main] Traffic Server Args: '%s'\n", lmgmt->proxy_options);
}
if (proxy_port != -1) {
lmgmt->proxy_server_port[0] = proxy_port;
mgmt_log(stderr, "[main] Traffic Server Port: '%d'\n", lmgmt->proxy_server_port[0]);
}
if (proxy_backdoor != -1) {
REC_setInteger("proxy.config.process_manager.mgmt_port", proxy_backdoor);
}
if (cluster_server_port == -1) {
cluster_server_port = REC_readInteger("proxy.config.cluster.rsport", &found);
ink_assert(found);
}
if (cluster_port == -1) {
cluster_port = REC_readInteger("proxy.config.cluster.mcport", &found);
ink_assert(found);
}
if (!group_addr) {
group_addr = REC_readString("proxy.config.cluster.mc_group_addr", &found);
ink_assert(found);
}
if (schema_on) {
XMLDom schema;
schema.LoadFile(schema_path);
bool validate = validateRecordsConfig(&schema);
NOWARN_UNUSED(validate);
// Why is this assert disabled? /leif
//ink_assert(validate);
}
in_addr_t min_ip = inet_network("224.0.0.255");
in_addr_t max_ip = inet_network("239.255.255.255");
in_addr_t group_addr_ip = inet_network(group_addr);
if (!(min_ip < group_addr_ip && group_addr_ip < max_ip)) {
mgmt_fatal("[TrafficManager] Multi-Cast group addr '%s' is not in the permitted range of %s\n",
group_addr, "224.0.1.0 - 239.255.255.255");
}
lmgmt->initCCom(cluster_port, group_addr, cluster_server_port); /* Setup cluster communication */
lmgmt->initMgmtProcessServer(); /* Setup p-to-p process server */
// Now that we know our cluster ip address, add the
// UI record for this machine
overviewGenerator->addSelfRecord();
webThrId = ink_thread_create(webIntr_main, NULL); /* Spin web agent thread */
#ifdef USE_SNMP
snmpThrId = ink_thread_create(snmpThread, (void *) snmp); /* Spin snmp agent thread */
#endif
lmgmt->listenForProxy();
#if defined(HAVE_LIBSSL) && defined(TRAFFIC_NET)
// Traffic Net Thread
ink_thread tnThrId;
tnThrId = ink_thread_create(tn_mgmt_main, NULL); /* Spin Traffic Net thread */
mgmt_log("[TrafficManager] Traffic Net thread created\n");
#endif
/* Check the permissions on vip_config */
if (lmgmt->virt_map->enabled) {
char absolute_vipconf_binary[1024];
struct stat buf;
ink_snprintf(absolute_vipconf_binary, sizeof(absolute_vipconf_binary), "%s/vip_config", lmgmt->bin_path);
if (stat(absolute_vipconf_binary, &buf) < 0) {
mgmt_elog(stderr, "[main] Unable to stat vip_config for proper permissions\n");
} else if (!((buf.st_mode & S_ISUID) &&
(buf.st_mode & S_IRWXU) &&
(buf.st_mode & S_IRGRP) &&
(buf.st_mode & S_IXGRP) && (buf.st_mode & S_IROTH) && (buf.st_mode & S_IXOTH))) {
lmgmt->alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_SYSTEM_ERROR,
"Virtual IP Addressing enabled, but improper permissions on '/inktomi/bin/vip_config'"
"[requires: setuid root and at least a+rx]\n");
}
}
ticker = time(NULL);
mgmt_log("[TrafficManager] Setup complete\n");
#ifdef USE_STATPRO
statProcessor = NEW(new StatProcessor());
#endif
if (xml_on) {
converterInit();
TrafficServer_xml(xml_path);
}
#if defined(OEM) && !defined(OEM_3COM)
//For OEM releases we check here whether a floppy with the correct config file exists
//if it does, we first configure the network, then we continue
char floppyLockFile[256];
ink_snprintf(floppyLockFile, sizeof(floppyLockFile), "./etc/trafficserver/internal/floppy.dat");
struct stat lockFileStat;
FILE *floppy_lock_fd;
bool floppyRestore = true;
// Check for the presence of floppy.dat lock file in the etc/trafficserver/internal directory
// If the lock is found, check if it is more than 120 seconds old.
// If the lock file is missing or if it is more than 120 seconds old, create a new lock file
// and restore network settings.
if (stat(floppyLockFile, &lockFileStat) < 0) {
perror("floppy.lock: ");
if ((floppy_lock_fd = fopen(floppyLockFile, "w+")) == NULL) {
mgmt_log(stderr, "[main] Could not create floppy.lock. Not restoring floppy configurations\n");
floppyRestore = false;
} else
fclose(floppy_lock_fd);
} else {
time_t now;
floppyRestore = false;
if ((time(&now) - lockFileStat.st_mtime) > 120) {
unlink(floppyLockFile);
floppyRestore = true;
if ((floppy_lock_fd = fopen(floppyLockFile, "w+")) == NULL) {
mgmt_log(stderr, "[main] Could not create floppy.lock. Not restoring floppy configurations\n");
floppyRestore = false;
} else {
fclose(floppy_lock_fd);
}
}
}
if (floppyRestore) {
int oem_status;
int old_euid = getuid();
if (seteuid(0))
perror("Main: Config_FloppyRestore setuid failed: ");
if (setreuid(0, 0))
perror("Main: Config_FloppyRestore setreuid failed: ");
oem_status = Config_FloppyNetRestore();
setreuid(old_euid, old_euid);
if (oem_status) {
Debug("lm", "[Main] Failed to initialize network using floppy configuration file\n");
}
//try a to queue a request for a restart
//lmgmt->mgmt_shutdown_outstanding = true; //This is marked out as we don't need to restart
}
#endif //OEM - Floppy Configuration
for (;;) {
lmgmt->processEventQueue();
lmgmt->pollMgmtProcessServer();
// Check for a SIGHUP
if (sigHupNotifier != 0) {
if (xml_on) // convert xml into TS config files
TrafficServer_xml(xml_path);
mgmt_log(stderr, "[main] Reading Configuration Files due to SIGHUP\n");
configFiles->rereadConfig();
lmgmt->signalEvent(MGMT_EVENT_PLUGIN_CONFIG_UPDATE, "*");
sigHupNotifier = 0;
mgmt_log(stderr, "[main] Reading Configuration Files Reread\n");
}
// Check for SIGUSR2
if (sigUsr2Notifier != 0) {
xdump();
sigUsr2Notifier = 0;
}
// if(lmgmt->processRunning() && just_started >= 10) { /* Sync the config/process records */
// lmgmt->record_data->syncRecords();
// } else {
// /* Continue to update the db for config, this also syncs the records.config */
// lmgmt->record_data->syncRecords(false);
// }
// snmp->poll();
lmgmt->ccom->generateClusterDelta();
if (lmgmt->run_proxy && lmgmt->processRunning()) {
lmgmt->ccom->sendSharedData();
lmgmt->virt_map->lt_runGambit();
} else {
if (!lmgmt->run_proxy) { /* Down if we are not going to start another immed. */
/* Proxy is not up, so no addrs should be */
lmgmt->virt_map->downOurAddrs();
}
/* Proxy is not up, but we should still exchange config and alarm info */
lmgmt->ccom->sendSharedData(false);
}
#ifndef USE_STATPRO
// Aggregate node statistics
overviewGenerator->doClusterAg();
#endif
lmgmt->ccom->checkPeers(&ticker);
overviewGenerator->checkForUpdates();
#ifndef USE_STATPRO
// Aggregate cluster statistics
aggregateNodeRecords();
#else
if (statProcessor) {
statProcessor->processStat();
}
#endif
if (lmgmt->mgmt_shutdown_outstanding == true) {
lmgmt->mgmtShutdown(0, true);
}
#ifdef USE_SNMP
// deal with the SNMP agent daemon, fork/exec/etc.
if (snmp) {
snmp->processMgmt(lmgmt);
}
#endif
if (lmgmt->run_proxy && !lmgmt->processRunning()) { /* Make sure we still have a proxy up */
if (lmgmt->startProxy())
just_started = 0;
else
just_started++;
} else { /* Give the proxy a chance to fire up */
just_started++;
}
/* This will catch the case were the proxy dies before it can connect to manager */
if (lmgmt->proxy_launch_outstanding && !lmgmt->processRunning() && just_started >= 120) {
just_started = 0;
lmgmt->proxy_launch_outstanding = false;
#ifndef _WIN32
if (lmgmt->proxy_launch_pid != -1) {
int res;
kill(lmgmt->proxy_launch_pid, 9);
waitpid(lmgmt->proxy_launch_pid, &res, 0);
if (WIFSIGNALED(res)) {
int sig = WTERMSIG(res);
#ifdef NEED_PSIGNAL
mgmt_log(stderr, "[main] Proxy terminated due to Sig %d\n", sig);
#else
mgmt_log(stderr, "[main] Proxy terminated due to Sig %d: %s\n", sig, strsignal(sig));
#endif /* NEED_PSIGNAL */
}
}
#else
if (lmgmt->proxy_launch_hproc != INVALID_HANDLE_VALUE) {
TerminateProcess(lmgmt->proxy_launch_hproc, 1);
}
#endif /* !_WIN32 */
mgmt_log(stderr, "[main] Proxy launch failed, retrying...\n");
}
}
#if defined(STATPRO)
if (statProcessor) {
delete(statProcessor);
}
#endif
#ifndef MGMT_SERVICE
return 0;
#endif
} /* End main */
#ifndef _WIN32
#if (HOST_OS != linux) && (HOST_OS != freebsd)
void
SignalAlrmHandler(int sig, siginfo_t * t, void *c)
#else
void
SignalAlrmHandler(int sig)
#endif
{
/*
fprintf(stderr,"[TrafficManager] ==> SIGALRM received\n");
mgmt_elog(stderr,"[TrafficManager] ==> SIGALRM received\n");
*/
#if (HOST_OS != linux) && (HOST_OS != freebsd)
if (t) {
if (t->si_code <= 0) {
fprintf(stderr, "[TrafficManager] ==> User Alarm from pid: %d uid: %d\n", t->si_pid, t->si_uid);
mgmt_elog(stderr, "[TrafficManager] ==> User Alarm from pid: %d uid: %d\n", t->si_pid, t->si_uid);
} else {
fprintf(stderr, "[TrafficManager] ==> Kernel Alarm Reason: %d\n", t->si_code);
mgmt_elog(stderr, "[TrafficManager] ==> Kernel Alarm Reason: %d\n", t->si_code);
}
}
#endif
return;
}
#if (HOST_OS != linux) && (HOST_OS != freebsd)
void
SignalHandler(int sig, siginfo_t * t, void *c)
#else
void
SignalHandler(int sig)
#endif
{
static int clean = 0;
int status;
#if (HOST_OS != linux) && (HOST_OS != freebsd)
if (t) {
if (t->si_code <= 0) {
fprintf(stderr, "[TrafficManager] ==> User Sig %d from pid: %d uid: %d\n", sig, t->si_pid, t->si_uid);
mgmt_elog(stderr, "[TrafficManager] ==> User Sig %d from pid: %d uid: %d\n", sig, t->si_pid, t->si_uid);
} else {
fprintf(stderr, "[TrafficManager] ==> Kernel Sig %d; Reason: %d\n", sig, t->si_code);
mgmt_elog(stderr, "[TrafficManager] ==> Kernel Sig %d; Reason: %d\n", sig, t->si_code);
}
}
#endif
if (sig == SIGHUP) {
sigHupNotifier = 1;
return;
}
if (sig == SIGUSR2) {
sigUsr2Notifier = 1;
return;
}
fprintf(stderr, "[TrafficManager] ==> Cleaning up and reissuing signal #%d\n", sig);
mgmt_elog(stderr, "[TrafficManager] ==> Cleaning up and reissuing signal #%d\n", sig);
if (lmgmt && !clean) {
clean = 1;
#ifdef __alpha
lmgmt->clean_up = true;
#endif
if (lmgmt->watched_process_pid != -1) {
if (sig == SIGTERM || sig == SIGINT) {
kill(lmgmt->watched_process_pid, sig);
waitpid(lmgmt->watched_process_pid, &status, 0);
#if (HOST_OS == linux) && defined (USE_SNMP)
// INKqa08918: band-aid: for some reasons if snmpd.cnf is modified
// the snmp processes are killed and restarted successfully. But
// when traffic server is shut down, the snmp processes are not killed.
// NOTE: race condition with the shutdown() call in LocalManager.cc
if (snmp) {
snmp->shutdown();
snmp = NULL;
}
#endif
}
}
lmgmt->mgmtCleanup();
}
// INKqa08323 (linux/mgmt: tm process doesn't exit on SIGxxx)
#if (HOST_OS == linux) && defined(_exit)
#undef _exit // _exit redefined below to be ink__exit()
#endif
switch (sig) {
case SIGQUIT:
case SIGILL:
case SIGTRAP:
#if (HOST_OS != linux)
case SIGEMT:
case SIGSYS:
#endif
case SIGFPE:
case SIGBUS:
case SIGSEGV:
case SIGXCPU:
case SIGXFSZ:
abort();
default:
fprintf(stderr, "[TrafficManager] ==> signal #%d\n", sig);
mgmt_elog(stderr, "[TrafficManager] ==> signal #%d\n", sig);
_exit(sig);
}
fprintf(stderr, "[TrafficManager] ==> signal2 #%d\n", sig);
mgmt_elog(stderr, "[TrafficManager] ==> signal2 #%d\n", sig);
_exit(sig);
#if (HOST_OS == linux)
#define _exit(val) ink__exit(val)
#endif
} /* End SignalHandler */
// void SigChldHandler(int sig)
//
// An empty handler needed so that we catch SIGCHLD
// With Solaris 2.6, ignoring sig child changes the behavior
// of waitpid() so that if there are no unwaited children,
// waitpid() blocks until all child are transformed into
// zombies which is bad for us
//
void
SigChldHandler(int sig)
{
}
// void SigHupHandler(int sig,...)
//
// Records that a sigHup was sent so that we can reread our
// config files on the next run through the main loop
void
SigHupHandler(int sig, ...)
{
ink_assert(sig == SIGHUP);
Debug("lm", "[SigHupHandler] hup caught\n");
sigHupNotifier = 1;
} /* End SigHupHandler */
#endif /* !_WIN32 */
void
printUsage()
{
fprintf(stderr, "----------------------------------------------------------------------------\n");
fprintf(stderr, " Traffic Manager Usage: (all args are optional)\n");
fprintf(stderr, "\n");
fprintf(stderr, " traffic_manager [options]\n");
fprintf(stderr, " -proxyPort <port> Port to have proxy listen on, overrides records.config.\n");
/* Function is currently #ifdef'ed out so no reason to advertise
fprintf(stderr,
" -proxyBackdoor <port> Port to put proxy mgmt port on.\n");
*/
/* Commented out because this option is used for debugging only.
fprintf(stderr,
" -noProxy Do not launch the proxy process.\n");
*/
fprintf(stderr, " -tsArgs [...] Args to proxy, everything till eol is passed.\n");
fprintf(stderr, " -webPort <port> Port for web interface.\n");
/*
fprintf(stderr,
" -graphPort <port> Port for dynamic graphs.\n");
*/
fprintf(stderr, " -clusterPort <port> Cluster Multicast port\n");
fprintf(stderr, " -groupAddr <addr> Cluster Multicast group, example: \"225.0.0.37\".\n");
fprintf(stderr, " -clusterRSPort <port> Cluster Multicast port.\n");
fprintf(stderr, " -path <path> Root path for config files.\n");
/*
fprintf(stderr,
" -lmConf <fname> Local Management config file.\n");
*/
fprintf(stderr, " -recordsConf <fname> General config file.\n");
fprintf(stderr, " -printRecords [...] Print flags, default all are off.\n");
fprintf(stderr, " -debug <tags> Enable the given debug tags\n");
fprintf(stderr, " -action <tags> Enable the given action tags.\n");
fprintf(stderr, " -version or -V Print version id and exit.\n");
fprintf(stderr, " -snmplog <int> Turn on SNMP SDK diagnostics. (2147450879 is good...)\n");
fprintf(stderr, " -vingid <id> Vingid Flag\n");
fprintf(stderr, "\n");
fprintf(stderr, " [...] can be one+ of: [config process node cluster local all]\n");
fprintf(stderr, "----------------------------------------------------------------------------\n");
exit(0);
} /* End printUsage */
void
fileUpdated(char *fname)
{
if (strcmp(fname, "cluster.config") == 0) {
lmgmt->signalFileChange("proxy.config.cluster.cluster_configuration");
} else if (strcmp(fname, "remap.config") == 0) {
lmgmt->signalFileChange("proxy.config.url_remap.filename");
} else if (strcmp(fname, "logs.config") == 0) {
lmgmt->signalFileChange("proxy.config.log2.config_file");
} else if (strcmp(fname, "socks.config") == 0) {
lmgmt->signalFileChange("proxy.config.socks.socks_config_file");
} else if (strcmp(fname, "records.config") == 0) {
lmgmt->signalFileChange("records.config");
} else if (strcmp(fname, "cache.config") == 0) {
lmgmt->signalFileChange("proxy.config.cache.control.filename");
} else if (strcmp(fname, "filter.config") == 0) {
lmgmt->convert_filters();
lmgmt->signalFileChange("proxy.config.content_filter.filename");
} else if (strcmp(fname, "parent.config") == 0) {
lmgmt->signalFileChange("proxy.config.http.parent_proxy.file");
} else if (strcmp(fname, "mgmt_allow.config") == 0) {
lmgmt->signalFileChange("proxy.config.admin.ip_allow.filename");
// signalFileChange does not cause callbacks in the manager
// so generate one here by hand
markMgmtIpAllowChange();
} else if (strcmp(fname, "ip_allow.config") == 0) {
lmgmt->signalFileChange("proxy.config.cache.ip_allow.filename");
} else if (strcmp(fname, "lm.config") == 0) {
/* Fix INKqa00919. The lm.config file is for stats only so
* we should never need to re-read it and destroy stats
* the manager has stored there
*
mgmt_log(stderr, "[fileUpdated] lm.config updated\n");
if(lmgmt->record_data->rereadRecordFile(lmgmt->config_path, lm_conf) < 0) {
mgmt_elog(stderr, "[FileUpdated] Config update failed for lm.config\n");
}
*/
} else if (strcmp(fname, "vaddrs.config") == 0) {
mgmt_log(stderr, "[fileUpdated] vaddrs.config updated\n");
lmgmt->virt_map->lt_readAListFile(fname);
} else if (strcmp(fname, "storage.config") == 0) {
mgmt_log(stderr, "[fileUpdated] storage.config changed, need restart auto-rebuild mode\n");
} else if (strcmp(fname, "proxy.pac") == 0) {
mgmt_log(stderr, "[fileUpdated] proxy.pac file has been modified\n");
} else if (strcmp(fname, "wpad.dat") == 0) {
mgmt_log(stderr, "[fileUpdated] wpad.dat file has been modified\n");
} else if (strcmp(fname, "snmpd.cnf") == 0) {
lmgmt->signalFileChange("snmpd.cnf");
} else if (strcmp(fname, "icp.config") == 0) {
lmgmt->signalFileChange("proxy.config.icp.icp_configuration");
} else if (strcmp(fname, "update.config") == 0) {
lmgmt->signalFileChange("proxy.config.update.update_configuration");
} else if (strcmp(fname, "admin_access.config") == 0) {
lmgmt->signalFileChange("admin_access.config");
} else if (strcmp(fname, "partition.config") == 0) {
mgmt_log(stderr, "[fileUpdated] partition.config changed, need restart\n");
} else if (strcmp(fname, "hosting.config") == 0) {
lmgmt->signalFileChange("proxy.config.cache.hosting_filename");
// INKqa07930: recently added SNMP config files need to be caught here to
} else if (strcmp(fname, "snmpinfo.dat") == 0) {
mgmt_log(stderr, "[fileUpdated] snmpinfo.dat file has been modified\n");
} else if (strcmp(fname, "mgr.cnf") == 0) {
mgmt_log(stderr, "[fileUpdated] mgr.cnf file has been modified\n");
} else if (strcmp(fname, "log_hosts.config") == 0) {
lmgmt->signalFileChange("proxy.config.log2.hosts_config_file");
} else if (strcmp(fname, "logs_xml.config") == 0) {
lmgmt->signalFileChange("proxy.config.log2.xml_config_file");
// INKqa10113
} else if (strcmp(fname, "ldapsrvr.config") == 0) {
mgmt_log(stderr, "[fileUpdated] ldapsrvr.config file has been modified\n");
} else if (strcmp(fname, "splitdns.config") == 0) {
mgmt_log(stderr, "[fileUpdated] splitdns.config file has been modified\n");
} else if (strcmp(fname, "ftp_remap.config") == 0) {
lmgmt->signalFileChange("proxy.config.ftp.reverse_ftp_remap_file_name");
} else if (strcmp(fname, "plugin.config") == 0) {
mgmt_log(stderr, "[fileUpdated] plugin.config file has been modified\n");
} else if (strcmp(fname, "ssl_multicert.config") == 0) {
mgmt_log(stderr, "[fileUpdated] ssl_multicert.config file has been modified\n");
} else if (strcmp(fname, "ipnat.conf") == 0) {
mgmt_log(stderr, "[fileUpdated] ipnat.conf file has been modified\n");
// INKqa11910
} else if (strcmp(fname, "proxy.config.body_factory.template_sets_dir") == 0) {
lmgmt->signalFileChange("proxy.config.body_factory.template_sets_dir");
} else if (strcmp(fname, "nntp_config.xml") == 0) {
lmgmt->signalFileChange("proxy.config.nntp.config_file");
} else if (strcmp(fname, "stats.config.xml") == 0) {
#if defined(STATPRO)
if (statProcessor) {
statProcessor->rereadConfig();
}
#endif
mgmt_log(stderr, "[fileUpdated] stats.config.xml file has been modified\n");
} else if (strcmp(fname, "congestion.config") == 0) {
lmgmt->signalFileChange("proxy.config.http.congestion_control.filename");
#if defined(OEM)
} else if (strcmp(fname, "net.config.xml") == 0) {
mgmt_log(stderr, "[fileUpdated] net.config.xml file has been modified\n");
} else if (strcmp(fname, "plugins/vscan.config") == 0) {
mgmt_log(stderr, "[fileUpdated] plugins/vscan.config file has been modified\n");
} else if (strcmp(fname, "plugins/trusted-host.config") == 0) {
mgmt_log(stderr, "[fileUpdated] plugins/trusted-host.config file has been modified\n");
} else if (strcmp(fname, "plugins/extensions.config") == 0) {
mgmt_log(stderr, "[fileUpdated] plugins/extensions.config file has been modified\n");
#endif
} else {
mgmt_elog(stderr, "[fileUpdated] Unknown config file updated '%s'\n", fname);
}
return;
} /* End fileUpdate */
// void runAsUser(...)
//
// If we are root, switched to user to run as
// specified in records.config
//
// If we are not root, do nothing
//
void
runAsUser(char *userName)
{
uid_t uid, euid;
struct passwd *result;
const int bufSize = 1024;
char buf[bufSize];
uid = getuid();
euid = geteuid();
if (uid == 0 || euid == 0) {
/* Figure out what user we should run as */
Debug("lm", "[runAsUser] Attempting to run as user '%s'\n", userName);
if (userName == NULL || userName[0] == '\0') {
mgmt_elog(stderr, "[runAsUser] Fatal Error: proxy.config.admin.user_id is not set\n", userName, strerror(errno));
_exit(1);
}
// this is behaving weird. refer to getpwnam(3C) sparc -jcoates
// this looks like the POSIX getpwnam_r
struct passwd passwdInfo;
struct passwd *ppasswd = NULL;
result = NULL;
int res = getpwnam_r(&userName[0], &passwdInfo, buf, bufSize, &ppasswd);
#if 0
// non-POSIX
struct passwd *ppasswd = NULL;
result = NULL;
int res = (int) getpwnam_r(&userName[0], ppasswd, buf, bufSize);
#endif
if (!res && ppasswd) {
result = ppasswd;
}
if (result == NULL) {
mgmt_elog(stderr, "[runAsUser] Fatal Error: Unable to get info about user %s : %s\n", userName, strerror(errno));
_exit(1);
}
if (setegid(result->pw_gid) != 0 || seteuid(result->pw_uid) != 0) {
mgmt_elog(stderr, "[runAsUser] Fatal Error: Unable to switch to user %s : %s\n", userName, strerror(errno));
_exit(1);
}
uid = getuid();
euid = geteuid();
Debug("lm", "[runAsUser] Running with uid: '%d' euid: '%d'\n", uid, euid);
if (uid != result->pw_uid && euid != result->pw_uid) {
mgmt_elog(stderr, "[runAsUser] Fatal Error: Failed to switch to user %s\n", userName);
_exit(1);
}
}
} /* End runAsUser() */
// void extractConfigInfo(...)
//
// We need to get certain records.config values while we are
// root. We can not use LMRecords to get them because the constructor
// for LMRecords creates the mgmt DBM and we do not want that to
// be owned as root. This function extracts that info from
// records.config
//
//
void
extractConfigInfo(char *mgmt_path, char *recs_conf, char *userName, int *fds_throttle)
{
char file[1024];
bool useridFound = false;
bool throttleFound = false;
/* Figure out what user we should run as */
if (mgmt_path && recs_conf) {
FILE *fin;
ink_snprintf(file, sizeof(file), "%s%s%s.shadow", mgmt_path, DIR_SEP, recs_conf);
if (!(fin = fopen(file, "r"))) {
ink_snprintf(file, sizeof(file), "%s%s%s", mgmt_path, DIR_SEP, recs_conf);
if (!(fin = fopen(file, "r"))) {
mgmt_elog(stderr, "[extractConfigInfo] Unable to open config file(%s)\n", file);
_exit(1);
}
}
// Get 'user id' and 'network connections throttle limit'
while (((!useridFound) || (!throttleFound)) && fgets(file, 1024, fin)) {
if (strstr(file, "CONFIG proxy.config.admin.user_id STRING")) {
//coverity[secure_coding]
if ((sscanf(file, "CONFIG proxy.config.admin.user_id STRING %1023s\n", userName) == 1) &&
strcmp(userName, "NULL") != 0) {
useridFound = true;
}
} else if (strstr(file, "CONFIG proxy.config.net.connections_throttle INT")) {
if ((sscanf(file, "CONFIG proxy.config.net.connections_throttle INT %d\n", fds_throttle) == 1)) {
throttleFound = true;
}
}
}
fclose(fin);
} else {
mgmt_elog(stderr, "[extractConfigInfo] Fatal Error: unable to access records file\n");
_exit(1);
}
if (useridFound == false) {
mgmt_elog(stderr, "[extractConfigInfo] Fatal Error: proxy.config.admin.user_id is not set\n");
_exit(1);
}
} /* End extractConfigInfo() */