62 #include "gw-config.h" 74 #include <sys/types.h> 77 #include <sys/utsname.h> 84 #include <sys/ucontext.h> 94 #if defined(HAVE_LIBSSL) || defined(HAVE_WTLS_OPENSSL) 95 #include <openssl/opensslv.h> 98 #include <mysql_version.h> 110 # define UNDEF_LIBSSL 1 112 #include <libpq-fe.h> 113 #include <pg_config.h> 148 #ifdef HAVE_BACKTRACE 151 ucontext_t *uc = (ucontext_t*)secret;
155 struct sigaction act;
157 act.sa_handler = SIG_DFL;
158 sigemptyset(&act.sa_mask);
160 sigaction(sig, &act, NULL);
162 #ifdef HAVE_BACKTRACE 163 size = backtrace(trace,
sizeof(trace) /
sizeof(
void*));
166 trace[1] = (
void *) uc->uc_mcontext.gregs[REG_EIP];
177 info(0,
"Signal %d received, forward to child pid (%ld)", signum, (
long)
child_pid);
212 sigemptyset(&sa.sa_mask);
222 sa.sa_handler = SIG_IGN;
224 sigaction(SIGTTOU, &sa, NULL);
225 sigaction(SIGTTIN, &sa, NULL);
226 sigaction(SIGTSTP, &sa, NULL);
231 panic(0,
"Child process signal handlers not initialized before.");
242 if (!S_ISREG(buf.st_mode) && !S_ISLNK(buf.st_mode)) {
247 if (S_IXOTH & buf.st_mode)
250 if ((S_IXGRP & buf.st_mode) && buf.st_gid == getgid())
253 if ((S_IXUSR & buf.st_mode) && buf.st_uid == getuid())
266 if (getppid() != 1) {
267 signal(SIGTTOU, SIG_IGN);
268 signal(SIGTTIN, SIG_IGN);
269 signal(SIGTSTP, SIG_IGN);
276 close(STDOUT_FILENO);
277 close(STDERR_FILENO);
278 fd = open(
"/dev/null", O_RDWR);
280 panic(errno,
"Could not open `/dev/null'");
288 #define PANIC_SCRIPT_MAX_LEN 4096 290 static PRINTFLIKE(2,3) void execute_panic_script(const
char *panic_script, const
char *
format, ...)
304 close(STDOUT_FILENO);
305 close(STDERR_FILENO);
307 args[0] = (
char*) panic_script;
311 execv(args[0], args);
316 time_t last_start = 0, last_panic = 0;
317 long respawn_count = 0;
322 panic(0,
"Panic script `%s' is not executable for us.", panic_script);
328 if (respawn_count > 0 && difftime(time(NULL), last_start) < 10) {
329 error(0,
"Child process died too fast, disabling for 30 sec.");
337 error(errno,
"Could not start child process! Will retry in 5 sec.");
343 info(0,
"Child process with PID (%ld) started.", (
long)
child_pid);
348 info(0,
"Child process exited gracefully, exit...");
352 else if (WIFEXITED(
status)) {
353 error(0,
"Caught child PID (%ld) which died with return code %d",
357 else if (WIFSIGNALED(
status)) {
358 error(0,
"Caught child PID (%ld) which died due to signal %d",
363 else if (errno != EINTR) {
364 error(errno,
"Error while waiting of child process.");
370 info(0,
"Child process crashed while shutdown. Exiting due to signal...");
371 info(0,
"Going into gwlib_shutdown...");
377 if (respawn_count == 0 && difftime(time(NULL), last_start) < 2) {
378 info(0,
"Child process crashed while starting. Exiting...");
379 info(0,
"Going into gwlib_shutdown...");
385 if (panic_script && myname && difftime(time(NULL), last_panic) > 300) {
387 debug(
"kannel", 0,
"Executing panic script: %s %s %ld", panic_script, myname, respawn_count);
388 execute_panic_script(panic_script,
"%s %ld", myname, respawn_count);
405 fd = open(
pid_file, O_WRONLY|O_NOCTTY|O_TRUNC|O_CREAT|O_EXCL, 0644);
409 file = fdopen(fd,
"w");
447 pass = getpwnam(user);
449 error(0,
"Could not find a user `%s' in system.", user);
453 if (-1 == setgid(pass->pw_gid)) {
454 error(errno,
"Could not change group id from %ld to %ld.", (
long) getgid(), (
long) pass->pw_gid);
458 #ifdef HAVE_INITGROUPS 459 if (initgroups(user, pass->pw_gid) == -1) {
460 error(errno,
"Could not set supplementary group ID's.");
464 if (-1 == setuid(pass->pw_uid)) {
465 error(errno,
"Could not change user id from %ld to %ld.", (
long) getuid(), (
long) pass->pw_uid);
481 for(*len=1;; (*len)++, source++) {
482 retval = retval * 0x80 + (*source & 0x7F);
496 revbuffer[loc++] = (value & 0x7F) + 0x80;
502 for(i=0; i < loc; i++)
503 dest[i] = revbuffer[loc-i-1];
514 dest = (source & 1) <<7;
515 dest += (source & 2) <<5;
516 dest += (source & 4) <<3;
517 dest += (source & 8) <<1;
518 dest += (source & 16) >>1;
519 dest += (source & 32) >>3;
520 dest += (source & 64) >>5;
521 dest += (source & 128) >>7;
530 struct sigaction act;
532 sigemptyset(&act.sa_mask);
534 act.sa_flags = SA_SIGINFO;
535 sigaction(SIGSEGV, &act, NULL);
554 return octstr_format(GW_NAME
" %s version `%s'.\nBuild `%s', compiler `%s'.\n" 555 "System %s, release %s, version %s, machine %s.\n" 556 "Hostname %s, IP %s.\n" 557 "Libxml version %s.\n" 560 #ifdef HAVE_WTLS_OPENSSL
566 "Compiled with MySQL %s, using MySQL %s.\n" 569 "Compiled with PostgreSQL %s.\n" 574 #
if defined(HAVE_SQLITE) || defined(HAVE_SQLITE3)
578 #
if defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
579 "Using Oracle OCI %d.%d.\n" 581 "Using Oracle OCI.\n" 585 "Using hiredis API %d.%d.%d\n" 587 "Using %s malloc.\n",
590 (__DATE__
" " __TIME__) ,
593 "unknown" ,
"unknown",
595 u.sysname, u.release, u.version, u.machine,
598 LIBXML_DOTTED_VERSION,
600 OPENSSL_VERSION_TEXT,
603 MYSQL_SERVER_VERSION, mysql_get_client_info(),
611 #
if defined(HAVE_SQLITE) || defined(HAVE_SQLITE3)
615 #
if defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
616 OCI_MAJOR_VERSION, OCI_MINOR_VERSION,
620 HIREDIS_MAJOR, HIREDIS_MINOR, HIREDIS_PATCH,
627 int (*find_own) (
int index,
int argc,
char **argv))
632 char *log_file = NULL;
633 char *debug_places = NULL;
634 char *panic_script = NULL, *user = NULL;
635 int parachute = 0, daemonize = 0;
637 for (i=1; i < argc; i++) {
638 if (strcmp(argv[i],
"-v")==0 || strcmp(argv[i],
"--verbosity")==0) {
640 debug_lvl = atoi(argv[i+1]);
643 panic(0,
"Missing argument for option %s\n", argv[i]);
644 }
else if (strcmp(argv[i],
"-F")==0 || strcmp(argv[i],
"--logfile")==0) {
645 if (i+1 < argc && *(argv[i+1]) !=
'-') {
646 log_file = argv[i+1];
649 panic(0,
"Missing argument for option %s\n", argv[i]);
650 }
else if (strcmp(argv[i],
"-V")==0 || strcmp(argv[i],
"--fileverbosity")==0) {
652 file_lvl = atoi(argv[i+1]);
655 panic(0,
"Missing argument for option %s\n", argv[i]);
656 }
else if (strcmp(argv[i],
"-D")==0 || strcmp(argv[i],
"--debug")==0) {
658 debug_places = argv[i+1];
661 panic(0,
"Missing argument for option %s\n", argv[i]);
662 }
else if (strcmp(argv[i],
"-X")==0 || strcmp(argv[i],
"--panic-script")==0) {
664 panic_script = argv[i+1];
667 panic(0,
"Missing argument for option %s\n", argv[i]);
668 }
else if (strcmp(argv[i],
"-P")==0 || strcmp(argv[i],
"--parachute")==0) {
670 }
else if (strcmp(argv[i],
"-d")==0 || strcmp(argv[i],
"--daemonize")==0) {
672 }
else if (strcmp(argv[i],
"-p")==0 || strcmp(argv[i],
"--pid-file")==0) {
677 panic(0,
"Missing argument for option %s\n", argv[i]);
678 }
else if (strcmp(argv[i],
"-u")==0 || strcmp(argv[i],
"--user")==0) {
683 panic(0,
"Missing argument for option %s\n", argv[i]);
684 }
else if (strcmp(argv[i],
"-g")==0 || strcmp(argv[i],
"--generate")==0) {
687 }
else if (strcmp(argv[i],
"--version")==0) {
692 }
else if (strcmp(argv[i],
"--")==0) {
695 }
else if (*argv[i] !=
'-') {
698 if (find_own != NULL) {
699 ret = find_own(i, argc, argv);
702 fprintf(stderr,
"Unknown option %s, exiting.\n", argv[i]);
703 panic(0,
"Option parsing failed");
710 panic(0,
"Could not change to user `%s'.", user);
727 char *ident = strrchr(argv[0],
'/');
742 if (debug_places != NULL)
744 if (log_file != NULL)
747 info(0,
"Debug_lvl = %d, log_file = %s, log_lvl = %d",
748 debug_lvl, log_file ? log_file :
"<none>", file_lvl);
749 if (debug_places != NULL)
750 info(0,
"Debug places: `%s'", debug_places);
762 long pat_len, ip_len;
770 while (i < pat_len && j < ip_len) {
777 }
else if (pat_c !=
'*') {
783 while (j < ip_len && ip_c !=
'.') {
790 if (i >= pat_len && j >= ip_len)
865 for (b = n; *b !=
'\0'; b++, p++) {
866 if (*p ==
';' || *p ==
'\0') {
871 if (*p ==
';' || *p ==
'\0') {
874 while (*p !=
'\0' && *p !=
';')
876 while (*p ==
';') p++;
884 char *t, *p, *official, *
start;
885 int len, official_len;
887 if (dial_prefixes == NULL || dial_prefixes[0] ==
'\0')
890 t = official = dial_prefixes;
898 for(
start = t, len = 0; ; t++, p++, len++)
900 if (*t ==
',' || *t ==
';' || *t ==
'\0') {
901 if (
start != official) {
905 if ( official[0] ==
'-' ) official_len=0;
907 if (strlen(official) < (
size_t) n)
908 n = strlen(official);
918 if (*p ==
'\0' || *t != *p)
921 for(; *t !=
',' && *t !=
';' && *t !=
'\0'; t++, len++)
923 if (*t ==
'\0')
break;
924 if (
start == official) official_len = len;
925 if (*t ==
';') official = t+1;
936 return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
941 data[0] = (value >> 24) & 0xff;
942 data[1] = (value >> 16) & 0xff;
943 data[2] = (value >> 8) & 0xff;
944 data[3] = value & 0xff;
954 tio->c_cc[VTIME] = 0;
962 tio->c_cflag &= ~(CSIZE|PARENB);
972 tio->c_iflag &= ~(BRKINT|ICRNL|IGNCR|IGNBRK|INLCR|IXON|ISTRIP);
980 tio->c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
984 tio->c_oflag &= ~OPOST;
1017 unsigned long random, timer;
1020 timer = (
unsigned long)time(NULL);
1022 return ((
unsigned long long)timer << 32) +
random;
void error(int err, const char *fmt,...)
void info(int err, const char *fmt,...)
void log_set_debug_places(const char *places)
void gw_backtrace(void **stack_frames, size_t size, int lock)
#define PANIC_SCRIPT_MAX_LEN
gw_assert(wtls_machine->packet_to_send !=NULL)
static void parachute_sig_handler(int signum)
void encode_network_long(unsigned char *data, unsigned long value)
static void write_pid_file(void)
static int become_daemon(void)
static struct sigaction child_actions[32]
void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len)
static int pattern_list_matches_ip(Octstr *pattern_list, Octstr *ip)
#define octstr_get_cstr(ostr)
unsigned long MultibyteInt
int connect_denied(Octstr *allow_ip, Octstr *ip)
int is_allowed_ip(Octstr *allow_ip, Octstr *deny_ip, Octstr *ip)
unsigned long long gw_generate_id(void)
Octstr * octstr_imm(const char *cstr)
int does_prefix_match(Octstr *prefix, Octstr *number)
void * gwlist_extract_first(List *list)
void log_set_output_level(enum output_level level)
static int change_user(const char *user)
static pid_t pidfile_owner_pid
static void parachute_start(const char *myname, const char *panic_script)
int roundup_div(int a, int b)
Octstr * octstr_format(const char *fmt,...)
void octstr_destroy(Octstr *ostr)
char filename[FILENAME_MAX+1]
void octstr_destroy_item(void *os)
Octstr * get_official_name(void)
static int child_actions_init
void gwthread_sleep(double seconds)
void log_set_syslog(const char *ident, int syslog_level)
static void parachute_init_signals(int child)
static void remove_pid_file(void)
int log_open(char *filename, int level, enum excl_state excl)
void report_versions(const char *boxname)
Octet reverse_octet(Octet source)
long octstr_len(const Octstr *ostr)
long decode_network_long(unsigned char *data)
Octstr * get_official_ip(void)
void init_fatal_signals()
static int pattern_matches_ip(Octstr *pattern, Octstr *ip)
void debug(const char *place, int err, const char *fmt,...)
void gwlib_shutdown(void)
MultibyteInt get_variable_value(Octet *source, int *len)
int normalize_number(char *dial_prefixes, Octstr **number)
static int is_executable(const char *filename)
void kannel_cfmakeraw(struct termios *tio)
Octstr * version_report_string(const char *boxname)
int write_variable_value(MultibyteInt value, Octet *dest)
int octstr_get_char(const Octstr *ostr, long pos)
int get_and_set_debugs(int argc, char **argv, int(*find_own)(int index, int argc, char **argv))
#define octstr_create_from_data(data, len)
static volatile sig_atomic_t parachute_shutdown
List * octstr_split(const Octstr *os, const Octstr *sep)
static void fatal_handler(int sig, siginfo_t *info, void *secret)
int gwlib_initialized(void)
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)