Kannel: Open Source WAP and SMS gateway  svn-r5335
utils.c File Reference
#include "gw-config.h"
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <termios.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include <libgen.h>
#include "gwlib.h"

Go to the source code of this file.

Macros

#define PANIC_SCRIPT_MAX_LEN   4096
 

Functions

static void fatal_handler (int sig, siginfo_t *info, void *secret)
 
static void parachute_sig_handler (int signum)
 
static void parachute_init_signals (int child)
 
static int is_executable (const char *filename)
 
static int become_daemon (void)
 
static PRINTFLIKE (2, 3)
 
static void parachute_start (const char *myname, const char *panic_script)
 
static void write_pid_file (void)
 
static void remove_pid_file (void)
 
static int change_user (const char *user)
 
MultibyteInt get_variable_value (Octet *source, int *len)
 
int write_variable_value (MultibyteInt value, Octet *dest)
 
Octet reverse_octet (Octet source)
 
void init_fatal_signals ()
 
void report_versions (const char *boxname)
 
Octstrversion_report_string (const char *boxname)
 
int get_and_set_debugs (int argc, char **argv, int(*find_own)(int index, int argc, char **argv))
 
static int pattern_matches_ip (Octstr *pattern, Octstr *ip)
 
static int pattern_list_matches_ip (Octstr *pattern_list, Octstr *ip)
 
int is_allowed_ip (Octstr *allow_ip, Octstr *deny_ip, Octstr *ip)
 
int connect_denied (Octstr *allow_ip, Octstr *ip)
 
int does_prefix_match (Octstr *prefix, Octstr *number)
 
int normalize_number (char *dial_prefixes, Octstr **number)
 
long decode_network_long (unsigned char *data)
 
void encode_network_long (unsigned char *data, unsigned long value)
 
void kannel_cfmakeraw (struct termios *tio)
 
int gw_isdigit (int c)
 
int gw_isxdigit (int c)
 
int roundup_div (int a, int b)
 
unsigned long long gw_generate_id (void)
 

Variables

static pid_t child_pid = -1
 
static pid_t pidfile_owner_pid = -1
 
static struct sigaction child_actions [32]
 
static int child_actions_init = 0
 
static char * pid_file = NULL
 
static volatile sig_atomic_t parachute_shutdown = 0
 

Macro Definition Documentation

◆ PANIC_SCRIPT_MAX_LEN

#define PANIC_SCRIPT_MAX_LEN   4096

Definition at line 288 of file utils.c.

Referenced by PRINTFLIKE().

Function Documentation

◆ become_daemon()

static int become_daemon ( void  )
static

Definition at line 263 of file utils.c.

References panic.

Referenced by get_and_set_debugs().

264 {
265  int fd;
266  if (getppid() != 1) {
267  signal(SIGTTOU, SIG_IGN);
268  signal(SIGTTIN, SIG_IGN);
269  signal(SIGTSTP, SIG_IGN);
270  if (fork())
271  return 0;
272  setsid();
273  }
274 
275  close(STDIN_FILENO);
276  close(STDOUT_FILENO);
277  close(STDERR_FILENO);
278  fd = open("/dev/null", O_RDWR); /* stdin */
279  if (fd == -1)
280  panic(errno, "Could not open `/dev/null'");
281  dup(fd); /* stdout */
282  dup(fd); /* stderr */
283 
284  chdir("/");
285  return 1;
286 }
#define panic
Definition: log.h:87

◆ change_user()

static int change_user ( const char *  user)
static

Definition at line 440 of file utils.c.

References error().

Referenced by get_and_set_debugs().

441 {
442  struct passwd *pass;
443 
444  if (!user)
445  return -1;
446 
447  pass = getpwnam(user);
448  if (!pass) {
449  error(0, "Could not find a user `%s' in system.", user);
450  return -1;
451  }
452 
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);
455  return -1;
456  }
457 
458 #ifdef HAVE_INITGROUPS
459  if (initgroups(user, pass->pw_gid) == -1) {
460  error(errno, "Could not set supplementary group ID's.");
461  }
462 #endif
463 
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);
466  return -1;
467  }
468 
469  return 0;
470 }
void error(int err, const char *fmt,...)
Definition: log.c:648

◆ connect_denied()

int connect_denied ( Octstr allow_ip,
Octstr ip 
)

Definition at line 833 of file utils.c.

References allow_ip, octstr_imm(), and pattern_list_matches_ip().

Referenced by httpsmsc_receiver().

834 {
835  if (ip == NULL)
836  return 1;
837 
838  /* If IP not set, allow from Localhost */
839  if (allow_ip == NULL) {
840  if (pattern_list_matches_ip(octstr_imm("127.0.0.1"), ip))
841  return 0;
842  } else {
844  return 0;
845  }
846  return 1;
847 }
static int pattern_list_matches_ip(Octstr *pattern_list, Octstr *ip)
Definition: utils.c:796
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
static Octstr * allow_ip
Definition: bb_udp.c:111

◆ decode_network_long()

long decode_network_long ( unsigned char *  data)

Definition at line 935 of file utils.c.

Referenced by conn_read_withlen(), parse_integer(), read_msg(), and smpp_pdu_read_len().

935  {
936  return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
937 }

◆ does_prefix_match()

int does_prefix_match ( Octstr prefix,
Octstr number 
)

Definition at line 850 of file utils.c.

References gw_assert(), number, and octstr_get_cstr.

Referenced by check_allowed_translation(), smsbox_req_handle(), and smscconn_usable().

851 {
852  /* XXX modify to use just octstr operations
853  */
854  char *b, *p, *n;
855 
856  gw_assert(prefix != NULL);
857  gw_assert(number != NULL);
858 
859  p = octstr_get_cstr(prefix);
860  n = octstr_get_cstr(number);
861 
862 
863  while (*p != '\0') {
864  b = n;
865  for (b = n; *b != '\0'; b++, p++) {
866  if (*p == ';' || *p == '\0') {
867  return 1;
868  }
869  if (*p != *b) break;
870  }
871  if (*p == ';' || *p == '\0') {
872  return 1;
873  }
874  while (*p != '\0' && *p != ';')
875  p++;
876  while (*p == ';') p++;
877  }
878  return 0;
879 }
int number
Definition: smsc_cimd2.c:213
gw_assert(wtls_machine->packet_to_send !=NULL)
#define octstr_get_cstr(ostr)
Definition: octstr.h:233

◆ encode_network_long()

void encode_network_long ( unsigned char *  data,
unsigned long  value 
)

Definition at line 940 of file utils.c.

Referenced by append_integer(), conn_write_withlen(), and write_msg().

940  {
941  data[0] = (value >> 24) & 0xff;
942  data[1] = (value >> 16) & 0xff;
943  data[2] = (value >> 8) & 0xff;
944  data[3] = value & 0xff;
945 }

◆ fatal_handler()

static void fatal_handler ( int  sig,
siginfo_t *  info,
void *  secret 
)
static

Definition at line 146 of file utils.c.

References gw_backtrace(), and size.

Referenced by init_fatal_signals().

147 {
148 #ifdef HAVE_BACKTRACE
149  void *trace[50];
150 #ifdef REG_EIP
151  ucontext_t *uc = (ucontext_t*)secret;
152 #endif
153  size_t size;
154 #endif
155  struct sigaction act;
156 
157  act.sa_handler = SIG_DFL;
158  sigemptyset(&act.sa_mask);
159  act.sa_flags = 0;
160  sigaction(sig, &act, NULL);
161 
162 #ifdef HAVE_BACKTRACE
163  size = backtrace(trace, sizeof(trace) / sizeof(void*));
164 #ifdef REG_EIP
165  /* overwrite sigaction with caller's address */
166  trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP];
167 #endif
168  gw_backtrace(trace, size, 0);
169 #endif
170 
171  raise(sig);
172 }
int size
Definition: wsasm.c:84
void gw_backtrace(void **stack_frames, size_t size, int lock)
Definition: log.c:599

◆ get_and_set_debugs()

int get_and_set_debugs ( int  argc,
char **  argv,
int(*)(int index, int argc, char **argv)  find_own 
)

Definition at line 626 of file utils.c.

References become_daemon(), cfg_dump_all(), change_user(), GW_DEBUG, GW_NON_EXCL, info(), init_fatal_signals(), log_close_all(), log_open(), log_set_debug_places(), log_set_output_level(), log_set_syslog(), octstr_destroy(), octstr_get_cstr, panic, parachute_start(), pid_file, remove_pid_file(), version_report_string(), and write_pid_file().

Referenced by main().

628 {
629  int i, ret = -1;
630  int debug_lvl = -1;
631  int file_lvl = GW_DEBUG;
632  char *log_file = NULL;
633  char *debug_places = NULL;
634  char *panic_script = NULL, *user = NULL;
635  int parachute = 0, daemonize = 0;
636 
637  for (i=1; i < argc; i++) {
638  if (strcmp(argv[i],"-v")==0 || strcmp(argv[i],"--verbosity")==0) {
639  if (i+1 < argc) {
640  debug_lvl = atoi(argv[i+1]);
641  i++;
642  } else
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];
647  i++;
648  } else
649  panic(0, "Missing argument for option %s\n", argv[i]);
650  } else if (strcmp(argv[i],"-V")==0 || strcmp(argv[i],"--fileverbosity")==0) {
651  if (i+1 < argc) {
652  file_lvl = atoi(argv[i+1]);
653  i++;
654  } else
655  panic(0, "Missing argument for option %s\n", argv[i]);
656  } else if (strcmp(argv[i],"-D")==0 || strcmp(argv[i],"--debug")==0) {
657  if (i+1 < argc) {
658  debug_places = argv[i+1];
659  i++;
660  } else
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) {
663  if (i+1 < argc) {
664  panic_script = argv[i+1];
665  i++;
666  } else
667  panic(0, "Missing argument for option %s\n", argv[i]);
668  } else if (strcmp(argv[i], "-P")==0 || strcmp(argv[i], "--parachute")==0) {
669  parachute = 1;
670  } else if (strcmp(argv[i], "-d")==0 || strcmp(argv[i], "--daemonize")==0) {
671  daemonize = 1;
672  } else if (strcmp(argv[i], "-p")==0 || strcmp(argv[i], "--pid-file")==0) {
673  if (i+1 < argc) {
674  pid_file = argv[i+1];
675  i++;
676  } else
677  panic(0, "Missing argument for option %s\n", argv[i]);
678  } else if (strcmp(argv[i], "-u")==0 || strcmp(argv[i], "--user")==0) {
679  if (i+1 < argc) {
680  user = argv[i+1];
681  i++;
682  } else
683  panic(0, "Missing argument for option %s\n", argv[i]);
684  } else if (strcmp(argv[i], "-g")==0 || strcmp(argv[i], "--generate")==0) {
685  cfg_dump_all();
686  exit(0);
687  } else if (strcmp(argv[i], "--version")==0) {
688  Octstr *version = version_report_string(basename(argv[0]));
689  printf("%s", octstr_get_cstr(version));
690  octstr_destroy(version);
691  exit(0);
692  } else if (strcmp(argv[i],"--")==0) {
693  i++;
694  break;
695  } else if (*argv[i] != '-') {
696  break;
697  } else {
698  if (find_own != NULL) {
699  ret = find_own(i, argc, argv);
700  }
701  if (ret < 0) {
702  fprintf(stderr, "Unknown option %s, exiting.\n", argv[i]);
703  panic(0, "Option parsing failed");
704  } else
705  i += ret; /* advance additional args */
706  }
707  }
708 
709  if (user && -1 == change_user(user))
710  panic(0, "Could not change to user `%s'.", user);
711 
712  /* deamonize */
713  if (daemonize && !become_daemon())
714  exit(0);
715 
716  if (pid_file) {
717  write_pid_file();
718  atexit(remove_pid_file);
719  }
720 
721  if (parachute) {
722  /*
723  * if we are running as daemon so open syslog
724  * in order not to deal with i.e. log rotate.
725  */
726  if (daemonize) {
727  char *ident = strrchr(argv[0], '/');
728  if (!ident)
729  ident = argv[0];
730  else
731  ident++;
732  log_set_syslog(ident, (debug_lvl > -1 ? debug_lvl : 0));
733  }
734  parachute_start(argv[0], panic_script);
735  /* now we are in child process so close syslog */
736  if (daemonize)
737  log_close_all();
738  }
739 
740  if (debug_lvl > -1)
741  log_set_output_level(debug_lvl);
742  if (debug_places != NULL)
743  log_set_debug_places(debug_places);
744  if (log_file != NULL)
745  log_open(log_file, file_lvl, GW_NON_EXCL);
746 
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);
751 
752 
754 
755  return i;
756 }
void info(int err, const char *fmt,...)
Definition: log.c:672
void log_set_debug_places(const char *places)
Definition: log.c:746
static char * pid_file
Definition: utils.c:142
static void write_pid_file(void)
Definition: utils.c:397
static int become_daemon(void)
Definition: utils.c:263
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void log_close_all(void)
Definition: log.c:341
void log_set_output_level(enum output_level level)
Definition: log.c:253
static int change_user(const char *user)
Definition: utils.c:440
Definition: log.h:69
static void parachute_start(const char *myname, const char *panic_script)
Definition: utils.c:315
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
void log_set_syslog(const char *ident, int syslog_level)
Definition: log.c:284
void cfg_dump_all(void)
Definition: cfg.c:869
static void remove_pid_file(void)
Definition: utils.c:417
int log_open(char *filename, int level, enum excl_state excl)
Definition: log.c:375
Definition: octstr.c:118
void init_fatal_signals()
Definition: utils.c:527
#define panic
Definition: log.h:87
Octstr * version_report_string(const char *boxname)
Definition: utils.c:549

◆ get_variable_value()

MultibyteInt get_variable_value ( Octet source,
int *  len 
)

Definition at line 477 of file utils.c.

Referenced by sema_decode_msg().

478 {
479  MultibyteInt retval = 0;
480 
481  for(*len=1;; (*len)++, source++) {
482  retval = retval * 0x80 + (*source & 0x7F);
483  if (*source < 0x80) /* if the continue-bit (high bit) is not set */
484  break;
485  }
486  return retval;
487 }
unsigned long MultibyteInt
Definition: utils.h:76

◆ gw_generate_id()

unsigned long long gw_generate_id ( void  )

Definition at line 1013 of file utils.c.

References gw_rand().

1014 {
1015  /* create a 64 bit unique Id by putting a 32 bit epoch time value
1016  * and a 32 bit random value together */
1017  unsigned long random, timer;
1018 
1019  random = gw_rand();
1020  timer = (unsigned long)time(NULL);
1021 
1022  return ((unsigned long long)timer << 32) + random;
1023 }
int gw_rand(void)
Definition: protected.c:174

◆ gw_isdigit()

int gw_isdigit ( int  c)

◆ gw_isxdigit()

int gw_isxdigit ( int  c)

Definition at line 994 of file utils.c.

Referenced by octstr_hex_to_binary(), octstr_is_all_hex(), octstr_symbolize(), packet_check(), and packet_check_parameter().

995 {
996  return isxdigit(c);
997 }

◆ init_fatal_signals()

void init_fatal_signals ( void  )

Install fatal signal handler. Usefull to receive backtrace if program crash with SEGFAULT.

Definition at line 527 of file utils.c.

References fatal_handler().

Referenced by get_and_set_debugs(), and parachute_init_signals().

528 {
529  /* install fatal signal handler */
530  struct sigaction act;
531  /* set segfault handler */
532  sigemptyset(&act.sa_mask);
533  act.sa_sigaction = fatal_handler;
534  act.sa_flags = SA_SIGINFO;
535  sigaction(SIGSEGV, &act, NULL);
536 }
static void fatal_handler(int sig, siginfo_t *info, void *secret)
Definition: utils.c:146

◆ is_allowed_ip()

int is_allowed_ip ( Octstr allow_ip,
Octstr deny_ip,
Octstr ip 
)

Definition at line 815 of file utils.c.

References allow_ip, deny_ip, octstr_len(), and pattern_list_matches_ip().

Referenced by accept_boxc(), authorise_username(), cgw_listener(), check_login(), emi2_listener(), fake_listener(), get_data(), httpadmin_run(), main(), and udp_receiver().

816 {
817  if (ip == NULL)
818  return 0;
819 
820  if (octstr_len(deny_ip) == 0)
821  return 1;
822 
823  if (allow_ip != NULL && pattern_list_matches_ip(allow_ip, ip))
824  return 1;
825 
827  return 0;
828 
829  return 1;
830 }
static int pattern_list_matches_ip(Octstr *pattern_list, Octstr *ip)
Definition: utils.c:796
static Octstr * deny_ip
Definition: bb_udp.c:112
static Octstr * allow_ip
Definition: bb_udp.c:111
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342

◆ is_executable()

static int is_executable ( const char *  filename)
static

Definition at line 234 of file utils.c.

References error(), and filename.

Referenced by parachute_start().

235 {
236  struct stat buf;
237 
238  if (stat(filename, &buf)) {
239  error(errno, "Error while stat of file `%s'", filename);
240  return 0;
241  }
242  if (!S_ISREG(buf.st_mode) && !S_ISLNK(buf.st_mode)) {
243  error(0, "File `%s' is not a regular file.", filename);
244  return 0;
245  }
246  /* others has exec permission */
247  if (S_IXOTH & buf.st_mode)
248  return 1;
249  /* group has exec permission */
250  if ((S_IXGRP & buf.st_mode) && buf.st_gid == getgid())
251  return 1;
252  /* owner has exec permission */
253  if ((S_IXUSR & buf.st_mode) && buf.st_uid == getuid())
254  return 1;
255 
256  return 0;
257 }
void error(int err, const char *fmt,...)
Definition: log.c:648
char filename[FILENAME_MAX+1]
Definition: log.c:171

◆ kannel_cfmakeraw()

void kannel_cfmakeraw ( struct termios *  tio)

Definition at line 951 of file utils.c.

Referenced by at2_open_device(), at_dial(), and X28_open_data_link().

951  {
952  /* Block until a charactor is available, but it only needs to be one*/
953  tio->c_cc[VMIN] = 1;
954  tio->c_cc[VTIME] = 0;
955 
956  /* GNU cfmakeraw sets these flags so we had better too...*/
957 
958  /* Control modes */
959  /* Mask out character size (CSIZE), then set it to 8 bits (CS8).
960  * Enable parity bit generation in both directions (PARENB).
961  */
962  tio->c_cflag &= ~(CSIZE|PARENB);
963  tio->c_cflag |= CS8;
964 
965  /* Input Flags,*/
966  /* Turn off all input flags that interfere with the byte stream:
967  * BRKINT - generate SIGINT when receiving BREAK, ICRNL - translate
968  * NL to CR, IGNCR - ignore CR, IGNBRK - ignore BREAK,
969  * INLCR - translate NL to CR, IXON - use XON/XOFF flow control,
970  * ISTRIP - strip off eighth bit.
971  */
972  tio->c_iflag &= ~(BRKINT|ICRNL|IGNCR|IGNBRK|INLCR|IXON|ISTRIP);
973 
974  /* Other flags,*/
975  /* Turn off all local flags that interpret the byte stream:
976  * ECHO - echo input chars, ECHONL - always echo NL even if ECHO is off,
977  * ICANON - enable canonical mode (basically line-oriented mode),
978  * IEXTEN - enable implementation-defined input processing,
979  * ISIG - generate signals when certain characters are received. */
980  tio->c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
981 
982  /* Output flags,*/
983  /* Disable implementation defined processing on the output stream*/
984  tio->c_oflag &= ~OPOST;
985 }

◆ normalize_number()

int normalize_number ( char *  dial_prefixes,
Octstr **  number 
)

Definition at line 882 of file utils.c.

References gw_assert(), number, octstr_create_from_data, octstr_destroy(), octstr_get_cstr, octstr_insert_data(), octstr_len(), and start.

Referenced by bb_smscconn_receive(), radius_acct_get_msisdn(), smsc2_rout(), and smscconn_send().

883 {
884  char *t, *p, *official, *start;
885  int len, official_len;
886 
887  if (dial_prefixes == NULL || dial_prefixes[0] == '\0')
888  return 0;
889 
890  t = official = dial_prefixes;
891  official_len = 0;
892 
893  gw_assert(number != NULL);
894 
895  while(1) {
896 
897  p = octstr_get_cstr(*number);
898  for(start = t, len = 0; ; t++, p++, len++)
899  {
900  if (*t == ',' || *t == ';' || *t == '\0') {
901  if (start != official) {
902  Octstr *nstr;
903  long n;
904 
905  if ( official[0] == '-' ) official_len=0;
906  n = official_len;
907  if (strlen(official) < (size_t) n)
908  n = strlen(official);
909  nstr = octstr_create_from_data(official, n);
910  octstr_insert_data(nstr, official_len,
911  octstr_get_cstr(*number) + len,
912  octstr_len(*number) - len);
914  *number = nstr;
915  }
916  return 1;
917  }
918  if (*p == '\0' || *t != *p)
919  break; /* not matching */
920  }
921  for(; *t != ',' && *t != ';' && *t != '\0'; t++, len++)
922  ;
923  if (*t == '\0') break;
924  if (start == official) official_len = len;
925  if (*t == ';') official = t+1;
926  t++;
927  }
928  return 0;
929 }
int number
Definition: smsc_cimd2.c:213
gw_assert(wtls_machine->packet_to_send !=NULL)
void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len)
Definition: octstr.c:1461
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Definition: octstr.c:118
#define octstr_create_from_data(data, len)
Definition: octstr.h:134
static int start

◆ parachute_init_signals()

static void parachute_init_signals ( int  child)
static

Definition at line 195 of file utils.c.

References child_actions, child_actions_init, init_fatal_signals(), panic, and parachute_sig_handler().

Referenced by parachute_start().

196 {
197  struct sigaction sa;
198 
199  if (child_actions_init && child) {
200  sigaction(SIGTERM, &child_actions[SIGTERM], NULL);
201  sigaction(SIGQUIT, &child_actions[SIGQUIT], NULL);
202  sigaction(SIGINT, &child_actions[SIGINT], NULL);
203  sigaction(SIGABRT, &child_actions[SIGABRT], NULL);
204  sigaction(SIGHUP, &child_actions[SIGHUP], NULL);
205  sigaction(SIGALRM, &child_actions[SIGALRM], NULL);
206  sigaction(SIGUSR1, &child_actions[SIGUSR1], NULL);
207  sigaction(SIGUSR2, &child_actions[SIGUSR2], NULL);
208  sigaction(SIGPIPE, &child_actions[SIGPIPE], NULL);
209  }
210  else if (!child && !child_actions_init) {
211  sa.sa_flags = 0;
212  sigemptyset(&sa.sa_mask);
213  sa.sa_handler = parachute_sig_handler;
214  sigaction(SIGTERM, &sa, &child_actions[SIGTERM]);
215  sigaction(SIGQUIT, &sa, &child_actions[SIGQUIT]);
216  sigaction(SIGINT, &sa, &child_actions[SIGINT]);
217  sigaction(SIGABRT, &sa, &child_actions[SIGABRT]);
218  sigaction(SIGHUP, &sa, &child_actions[SIGHUP]);
219  sigaction(SIGALRM, &sa, &child_actions[SIGALRM]);
220  sigaction(SIGUSR1, &sa, &child_actions[SIGUSR1]);
221  sigaction(SIGUSR2, &sa, &child_actions[SIGUSR2]);
222  sa.sa_handler = SIG_IGN;
223  sigaction(SIGPIPE, &sa, &child_actions[SIGPIPE]);
224  sigaction(SIGTTOU, &sa, NULL);
225  sigaction(SIGTTIN, &sa, NULL);
226  sigaction(SIGTSTP, &sa, NULL);
227  child_actions_init = 1;
229  }
230  else
231  panic(0, "Child process signal handlers not initialized before.");
232 }
static void parachute_sig_handler(int signum)
Definition: utils.c:175
static struct sigaction child_actions[32]
Definition: utils.c:138
static int child_actions_init
Definition: utils.c:140
void init_fatal_signals()
Definition: utils.c:527
#define panic
Definition: log.h:87

◆ parachute_sig_handler()

static void parachute_sig_handler ( int  signum)
static

Definition at line 175 of file utils.c.

References child_pid, info(), and parachute_shutdown.

Referenced by parachute_init_signals().

176 {
177  info(0, "Signal %d received, forward to child pid (%ld)", signum, (long) child_pid);
178 
179  /* we do not handle any signal, just forward these to child process */
180  if (child_pid != -1 && getpid() != child_pid)
181  kill(child_pid, signum);
182 
183  /* if signal received and no child there, terminating */
184  switch(signum) {
185  case SIGTERM:
186  case SIGINT:
187  case SIGABRT:
188  if (child_pid == -1)
189  exit(0);
190  else
191  parachute_shutdown = 1;
192  }
193 }
void info(int err, const char *fmt,...)
Definition: log.c:672
static pid_t child_pid
Definition: utils.c:134
static volatile sig_atomic_t parachute_shutdown
Definition: utils.c:143

◆ parachute_start()

static void parachute_start ( const char *  myname,
const char *  panic_script 
)
static

Definition at line 315 of file utils.c.

References child_pid, debug(), error(), gwlib_shutdown(), gwthread_sleep(), info(), is_executable(), panic, parachute_init_signals(), and parachute_shutdown.

Referenced by get_and_set_debugs().

315  {
316  time_t last_start = 0, last_panic = 0;
317  long respawn_count = 0;
318  int status;
319 
320 
321  if (panic_script && !is_executable(panic_script))
322  panic(0, "Panic script `%s' is not executable for us.", panic_script);
323 
324  /* setup sighandler */
326 
327  for (;;) {
328  if (respawn_count > 0 && difftime(time(NULL), last_start) < 10) {
329  error(0, "Child process died too fast, disabling for 30 sec.");
330  gwthread_sleep(30.0);
331  }
332  if (!(child_pid = fork())) { /* child process */
333  parachute_init_signals(1); /* reset sighandlers */
334  return;
335  }
336  else if (child_pid < 0) {
337  error(errno, "Could not start child process! Will retry in 5 sec.");
338  gwthread_sleep(5.0);
339  continue;
340  }
341  else { /* father process */
342  time(&last_start);
343  info(0, "Child process with PID (%ld) started.", (long) child_pid);
344  do {
345  if (waitpid(child_pid, &status, 0) == child_pid) {
346  /* check here why child terminated */
347  if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
348  info(0, "Child process exited gracefully, exit...");
349  gwlib_shutdown();
350  exit(0);
351  }
352  else if (WIFEXITED(status)) {
353  error(0, "Caught child PID (%ld) which died with return code %d",
354  (long) child_pid, WEXITSTATUS(status));
355  child_pid = -1;
356  }
357  else if (WIFSIGNALED(status)) {
358  error(0, "Caught child PID (%ld) which died due to signal %d",
359  (long) child_pid, WTERMSIG(status));
360  child_pid = -1;
361  }
362  }
363  else if (errno != EINTR) {
364  error(errno, "Error while waiting of child process.");
365  }
366  } while(child_pid > 0);
367 
368  if (parachute_shutdown) {
369  /* may only happens if child process crashed while shutdown */
370  info(0, "Child process crashed while shutdown. Exiting due to signal...");
371  info(0, "Going into gwlib_shutdown...");
372  gwlib_shutdown();
373  exit(WIFEXITED(status) ? WEXITSTATUS(status) : 0);
374  }
375 
376  /* check whether it's panic while start */
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...");
380  gwlib_shutdown();
381  exit(WIFEXITED(status) ? WEXITSTATUS(status) : 1);
382  }
383 
384  respawn_count++;
385  if (panic_script && myname && difftime(time(NULL), last_panic) > 300) {
386  time(&last_panic);
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);
389  }
390  /* sleep a while to get e.g. sockets released */
391  gwthread_sleep(5.0);
392  }
393  }
394 }
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
static pid_t child_pid
Definition: utils.c:134
void gwthread_sleep(double seconds)
static void parachute_init_signals(int child)
Definition: utils.c:195
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
#define panic
Definition: log.h:87
void gwlib_shutdown(void)
Definition: gwlib.c:94
static int is_executable(const char *filename)
Definition: utils.c:234
static volatile sig_atomic_t parachute_shutdown
Definition: utils.c:143

◆ pattern_list_matches_ip()

static int pattern_list_matches_ip ( Octstr pattern_list,
Octstr ip 
)
static

Definition at line 796 of file utils.c.

References gwlist_destroy(), gwlist_extract_first(), octstr_destroy(), octstr_destroy_item(), octstr_imm(), octstr_split(), and pattern_matches_ip().

Referenced by connect_denied(), and is_allowed_ip().

797 {
798  List *patterns;
799  Octstr *pattern;
800  int matches;
801 
802  patterns = octstr_split(pattern_list, octstr_imm(";"));
803  matches = 0;
804 
805  while (!matches && (pattern = gwlist_extract_first(patterns)) != NULL) {
806  matches = pattern_matches_ip(pattern, ip);
807  octstr_destroy(pattern);
808  }
809 
811  return matches;
812 }
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
void * gwlist_extract_first(List *list)
Definition: list.c:305
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
void octstr_destroy_item(void *os)
Definition: octstr.c:336
Definition: octstr.c:118
static int pattern_matches_ip(Octstr *pattern, Octstr *ip)
Definition: utils.c:759
List * octstr_split(const Octstr *os, const Octstr *sep)
Definition: octstr.c:1640
Definition: list.c:102
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ pattern_matches_ip()

static int pattern_matches_ip ( Octstr pattern,
Octstr ip 
)
static

Definition at line 759 of file utils.c.

References octstr_get_char(), and octstr_len().

Referenced by pattern_list_matches_ip().

760 {
761  long i, j;
762  long pat_len, ip_len;
763  int pat_c, ip_c;
764 
765  pat_len = octstr_len(pattern);
766  ip_len = octstr_len(ip);
767 
768  i = 0;
769  j = 0;
770  while (i < pat_len && j < ip_len) {
771  pat_c = octstr_get_char(pattern, i);
772  ip_c = octstr_get_char(ip, j);
773  if (pat_c == ip_c) {
774  /* The characters match, go to the next ones. */
775  ++i;
776  ++j;
777  } else if (pat_c != '*') {
778  /* They differ, and the pattern isn't a wildcard one. */
779  return 0;
780  } else {
781  /* We found a wildcard in the pattern. Skip in ip. */
782  ++i;
783  while (j < ip_len && ip_c != '.') {
784  ++j;
785  ip_c = octstr_get_char(ip, j);
786  }
787  }
788  }
789 
790  if (i >= pat_len && j >= ip_len)
791  return 1;
792  return 0;
793 }
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:406

◆ PRINTFLIKE()

static PRINTFLIKE ( ,
 
)
static

Definition at line 290 of file utils.c.

References PANIC_SCRIPT_MAX_LEN.

291 {
292  char *args[3];
293  char buf[PANIC_SCRIPT_MAX_LEN + 1];
294  va_list ap;
295 
296  va_start(ap, format);
297  vsnprintf(buf, PANIC_SCRIPT_MAX_LEN, format, ap);
298  va_end(ap);
299 
300  if (fork())
301  return;
302 
303  close(STDIN_FILENO);
304  close(STDOUT_FILENO);
305  close(STDERR_FILENO);
306 
307  args[0] = (char*) panic_script;
308  args[1] = buf;
309  args[2] = NULL;
310 
311  execv(args[0], args);
312 }
#define PANIC_SCRIPT_MAX_LEN
Definition: utils.c:288

◆ remove_pid_file()

static void remove_pid_file ( void  )
static

Definition at line 417 of file utils.c.

References error(), gwlib_init(), gwlib_initialized(), gwlib_shutdown(), log_set_syslog(), pid_file, and pidfile_owner_pid.

Referenced by get_and_set_debugs().

418 {
419  if (!pid_file)
420  return;
421 
422  /* ensure that only pidfile owner can remove it */
423  if (pidfile_owner_pid != getpid())
424  return;
425 
426  if (-1 == unlink(pid_file)) {
427  int initdone = gwlib_initialized();
428  /* we are called at exit so gwlib may be shutdown already, init again */
429  if (!initdone) {
430  gwlib_init();
431  log_set_syslog("kannel", 0);
432  }
433  error(errno, "Could not unlink pid-file `%s'", pid_file);
434  if (!initdone)
435  gwlib_shutdown();
436  }
437 }
void error(int err, const char *fmt,...)
Definition: log.c:648
static char * pid_file
Definition: utils.c:142
static pid_t pidfile_owner_pid
Definition: utils.c:136
void log_set_syslog(const char *ident, int syslog_level)
Definition: log.c:284
void gwlib_shutdown(void)
Definition: gwlib.c:94
void gwlib_init(void)
Definition: gwlib.c:78
int gwlib_initialized(void)
Definition: gwlib.c:111

◆ report_versions()

void report_versions ( const char *  boxname)

Definition at line 539 of file utils.c.

References debug(), octstr_destroy(), octstr_get_cstr, and version_report_string().

Referenced by main().

540 {
541  Octstr *os;
542 
543  os = version_report_string(boxname);
544  debug("gwlib.gwlib", 0, "%s", octstr_get_cstr(os));
545  octstr_destroy(os);
546 }
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
Octstr * version_report_string(const char *boxname)
Definition: utils.c:549

◆ reverse_octet()

Octet reverse_octet ( Octet  source)

Definition at line 511 of file utils.c.

Referenced by OTAbitmap_create(), and wbmp_create().

512 {
513  Octet dest;
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;
522 
523  return dest;
524 }
unsigned char Octet
Definition: utils.h:75

◆ roundup_div()

int roundup_div ( int  a,
int  b 
)

Definition at line 1001 of file utils.c.

1002 {
1003  int t;
1004 
1005  t = a / b;
1006  if (t * b != a)
1007  t += 1;
1008 
1009  return t;
1010 }

◆ version_report_string()

Octstr* version_report_string ( const char *  boxname)

Definition at line 549 of file utils.c.

References get_official_ip(), get_official_name(), octstr_format(), and octstr_get_cstr.

Referenced by bb_print_status(), get_and_set_debugs(), and report_versions().

550 {
551  struct utsname u;
552 
553  uname(&u);
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"
558 #ifdef HAVE_LIBSSL
559  "Using "
560 #ifdef HAVE_WTLS_OPENSSL
561  "WTLS library "
562 #endif
563  "%s.\n"
564 #endif
565 #ifdef HAVE_MYSQL
566  "Compiled with MySQL %s, using MySQL %s.\n"
567 #endif
568 #ifdef HAVE_PGSQL
569  "Compiled with PostgreSQL %s.\n"
570 #endif
571 #ifdef HAVE_SDB
572  "Using LibSDB %s.\n"
573 #endif
574 #if defined(HAVE_SQLITE) || defined(HAVE_SQLITE3)
575  "Using SQLite %s.\n"
576 #endif
577 #ifdef HAVE_ORACLE
578 #if defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
579  "Using Oracle OCI %d.%d.\n"
580 #else
581  "Using Oracle OCI.\n"
582 #endif
583 #endif
584 #ifdef HAVE_REDIS
585  "Using hiredis API %d.%d.%d\n"
586 #endif
587  "Using %s malloc.\n",
588  boxname, GW_VERSION,
589 #ifdef __GNUC__
590  (__DATE__ " " __TIME__) ,
591  __VERSION__,
592 #else
593  "unknown" , "unknown",
594 #endif
595  u.sysname, u.release, u.version, u.machine,
598  LIBXML_DOTTED_VERSION,
599 #ifdef HAVE_LIBSSL
600  OPENSSL_VERSION_TEXT,
601 #endif
602 #ifdef HAVE_MYSQL
603  MYSQL_SERVER_VERSION, mysql_get_client_info(),
604 #endif
605 #ifdef HAVE_PGSQL
606  PG_VERSION,
607 #endif
608 #ifdef HAVE_SDB
609  LIBSDB_VERSION,
610 #endif
611 #if defined(HAVE_SQLITE) || defined(HAVE_SQLITE3)
612  SQLITE_VERSION,
613 #endif
614 #ifdef HAVE_ORACLE
615 #if defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
616  OCI_MAJOR_VERSION, OCI_MINOR_VERSION,
617 #endif
618 #endif
619 #ifdef HAVE_REDIS
620  HIREDIS_MAJOR, HIREDIS_MINOR, HIREDIS_PATCH,
621 #endif
622  octstr_get_cstr(gwmem_type()));
623 }
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
Octstr * get_official_name(void)
Definition: socket.c:627
Octstr * get_official_ip(void)
Definition: socket.c:634

◆ write_pid_file()

static void write_pid_file ( void  )
static

Definition at line 397 of file utils.c.

References file, panic, pid_file, and pidfile_owner_pid.

Referenced by get_and_set_debugs().

398 {
399  int fd;
400  FILE *file;
401 
402  if (!pid_file)
403  return;
404 
405  fd = open(pid_file, O_WRONLY|O_NOCTTY|O_TRUNC|O_CREAT|O_EXCL, 0644);
406  if (fd == -1)
407  panic(errno, "Could not open pid-file `%s'", pid_file);
408 
409  file = fdopen(fd, "w");
410  if (!file)
411  panic(errno, "Could not open file-stream `%s'", pid_file);
412 
413  fprintf(file, "%ld\n", (long) (pidfile_owner_pid = getpid()));
414  fclose(file);
415 }
static char * pid_file
Definition: utils.c:142
FILE * file
Definition: log.c:169
static pid_t pidfile_owner_pid
Definition: utils.c:136
#define panic
Definition: log.h:87

◆ write_variable_value()

int write_variable_value ( MultibyteInt  value,
Octet dest 
)

Definition at line 490 of file utils.c.

Referenced by sema_encode_msg(), sema_submit_result(), and wbmp_create_stream().

491 {
492  int i, loc = 0;
493  Octet revbuffer[20]; /* we write it backwards */
494 
495  for (;;) {
496  revbuffer[loc++] = (value & 0x7F) + 0x80;
497  if (value >= 0x80)
498  value = value >> 7;
499  else
500  break;
501  }
502  for(i=0; i < loc; i++) /* reverse the buffer */
503  dest[i] = revbuffer[loc-i-1];
504 
505  dest[loc-1] &= 0x7F; /* remove trailer-bit from last */
506 
507  return loc;
508 }
unsigned char Octet
Definition: utils.h:75

Variable Documentation

◆ child_actions

struct sigaction child_actions[32]
static

Definition at line 138 of file utils.c.

Referenced by parachute_init_signals().

◆ child_actions_init

int child_actions_init = 0
static

Definition at line 140 of file utils.c.

Referenced by parachute_init_signals().

◆ child_pid

pid_t child_pid = -1
static

Definition at line 134 of file utils.c.

Referenced by parachute_sig_handler(), and parachute_start().

◆ parachute_shutdown

volatile sig_atomic_t parachute_shutdown = 0
static

Definition at line 143 of file utils.c.

Referenced by parachute_sig_handler(), and parachute_start().

◆ pid_file

char* pid_file = NULL
static

Definition at line 142 of file utils.c.

Referenced by get_and_set_debugs(), remove_pid_file(), and write_pid_file().

◆ pidfile_owner_pid

pid_t pidfile_owner_pid = -1
static

Definition at line 136 of file utils.c.

Referenced by remove_pid_file(), and write_pid_file().

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.