main.c
512dcd98
 /*
53c7e0f1
  * Copyright (C) 2001-2003 FhG Fokus
7dd0b342
  *
6a0f4382
  * This file is part of Kamailio, a free SIP server.
7dd0b342
  *
6a0f4382
  * Kamailio is free software; you can redistribute it and/or modify
7dd0b342
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
6a0f4382
  * Kamailio is distributed in the hope that it will be useful,
7dd0b342
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
b017f49c
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
9e1ff448
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
2d4b798e
  *
512dcd98
  */
 
6a0f4382
 /** Kamailio core :: main file (init, daemonize, startup) 
1ef55a09
  * @file main.c
  * @ingroup core
  * Module: core
1d0661db
  */
 
6a0f4382
 /*! @defgroup core Kamailio core
1d0661db
  *
1ef55a09
  * sip router core part.
1d0661db
  */
 
512dcd98
 #include <stdio.h>
3e429f5c
 #include <stdlib.h>
512dcd98
 #include <errno.h>
3e429f5c
 #include <ctype.h>
512dcd98
 #include <string.h>
e60a9728
 #include <netdb.h>
1b1b19d8
 #include <unistd.h>
a7380699
 #include <sys/types.h>
1b1b19d8
 #include <sys/socket.h>
a7380699
 #if defined(HAVE_NETINET_IN_SYSTM)
 #include <netinet/in_systm.h>
 #endif
1b1b19d8
 #include <netinet/in.h>
fe09f315
 #include <netinet/ip.h>
1b1b19d8
 #include <arpa/inet.h>
 #include <sys/utsname.h>
85f1f3ee
 #include <sys/stat.h>
f571aa35
 #include <sys/mman.h>
85f1f3ee
 #include <fcntl.h>
f571aa35
 #include <sys/time.h>
e9d701db
 #include <sys/wait.h>
054cb6cf
 #include <pwd.h>
 #include <grp.h>
4e2fdd79
 #include <signal.h>
512dcd98
 
57e2cd15
 #include <sys/ioctl.h>
 #include <net/if.h>
087d0976
 #ifdef HAVE_SYS_SOCKIO_H
57e2cd15
 #include <sys/sockio.h>
 #endif
 
e60a9728
 #include "config.h"
512dcd98
 #include "dprint.h"
c03cc017
 #include "daemonize.h"
512dcd98
 #include "route.h"
e60a9728
 #include "udp_server.h"
1b1b19d8
 #include "globals.h"
dda9dab1
 #include "mem/mem.h"
628e3a5a
 #ifdef SHM_MEM
dda9dab1
 #include "mem/shm_mem.h"
2c4ae148
 #include "shm_init.h"
 #endif /* SHM_MEM */
bf08223a
 #include "sr_module.h"
cd57180a
 #include "timer.h"
3881f12c
 #include "parser/msg_parser.h"
4e2fdd79
 #include "ip_addr.h"
 #include "resolve.h"
2bb60634
 #include "parser/parse_hname2.h"
335d097b
 #include "parser/digest/digest_parser.h"
e278821b
 #include "name_alias.h"
9df1213c
 #include "hash_func.h"
f51155cf
 #include "pt.h"
3c8bd369
 #include "script_cb.h"
ac34f9f4
 #include "nonsip_hooks.h"
f22b996b
 #include "ut.h"
2d826efb
 #include "events.h"
af93cbdf
 #include "signals.h"
22e7e32e
 #ifdef USE_RAW_SOCKS
 #include "raw_sock.h"
 #endif /* USE_RAW_SOCKS */
f2f969dd
 #ifdef USE_TCP
0ba367ec
 #include "poll_types.h"
f2f969dd
 #include "tcp_init.h"
dc93916e
 #include "tcp_options.h"
6c53d41a
 #ifdef CORE_TLS
e8f8146e
 #include "tls/tls_init.h"
6c53d41a
 #define tls_has_init_si() 1
 #define tls_loaded() 1
 #else
 #include "tls_hooks_init.h"
 #endif /* CORE_TLS */
 #endif /* USE_TCP */
c3611173
 #ifdef USE_SCTP
7f8e7a85
 #include "sctp_core.h"
c3611173
 #endif
74ce7043
 #include "usr_avp.h"
5099fd64
 #include "rpc_lookup.h"
539283cd
 #include "core_cmd.h"
65938e0e
 #include "flags.h"
8b8fc486
 #include "lock_ops_init.h"
d307929c
 #include "atomic_ops_init.h"
dcb59e67
 #ifdef USE_DNS_CACHE
 #include "dns_cache.h"
 #endif
 #ifdef USE_DST_BLACKLIST
 #include "dst_blacklist.h"
 #endif
2c07f591
 #include "rand/fastrand.h" /* seed */
0a974a1d
 
5b253cc6
 #include "stats.h"
4208dc00
 #include "counters.h"
7ac069af
 #include "cfg/cfg.h"
9188021a
 #include "cfg/cfg_struct.h"
7ac069af
 #include "cfg_core.h"
f769a620
 #include "endianness.h" /* init */
 #include "basex.h" /* init */
1f14e6ed
 #include "pvapi.h" /* init PV api */
0c73dfed
 #include "pv_core.h" /* register core pvars */
95dec431
 #include "ppcfg.h"
9eb54078
 #include "sock_ut.h"
d5a22ca8
 #include "async_task.h"
e4f18cb3
 #include "dset.h"
a482c5de
 #include "timer_proc.h"
726efa25
 
03150098
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
 #endif
1ef55a09
 #include "ver.h"
03150098
 
96d09107
 /* define SIG_DEBUG by default */
 #ifdef NO_SIG_DEBUG
 #undef SIG_DEBUG
 #else
 #define SIG_DEBUG
 #endif
 
dd0e65a8
 
726efa25
 
1b1b19d8
 static char help_msg[]= "\
f4194f69
 Usage: " NAME " [options]\n\
1b1b19d8
 Options:\n\
f4194f69
     -f file      Configuration file (default: " CFG_FILE ")\n\
c82fe029
     -L path      Modules search path (default: " MODS_DIR ")\n\
dda578ba
     -c           Check configuration file for errors\n\
5dcfb23d
     -l address   Listen on the specified address/interface (multiple -l\n\
16d4e079
                   mean listening on more addresses).  The address format is\n\
72bba9e3
                   [proto:]addr_lst[:port], where proto=udp|tcp|tls|sctp, \n\
                   addr_lst= addr|(addr, addr_lst) and \n\
                   addr= host|ip_address|interface_name. \n\
                   E.g: -l locahost, -l udp:127.0.0.1:5080, -l eth0:5062,\n\
                   -l \"sctp:(eth0)\", -l \"(eth0, eth1, 127.0.0.1):5065\".\n\
                   The default behaviour is to listen on all the interfaces.\n\
1b1b19d8
     -n processes Number of child processes to fork per interface\n\
16d4e079
                   (default: 8)\n\
1b1b19d8
     -r           Use dns to check if is necessary to add a \"received=\"\n\
16d4e079
                   field to a via\n\
c6016a4c
     -R           Same as `-r` but use reverse dns;\n\
16d4e079
                   (to use both use `-rR`)\n\
70d6cae2
     -K           Turn on \"via:\" host checking when forwarding replies\n\
1b1b19d8
     -d           Debugging mode (multiple -d increase the level)\n\
2b337687
     -D           Control how daemonize is done:\n\
                   -D..do not fork (almost) anyway;\n\
                   -DD..do not daemonize creator;\n\
                   -DDD..daemonize (default)\n\
6bda9c0b
     -E           Log to stderr\n\
     -e           Log messages printed in terminal colors (requires -E)\n"
5dcfb23d
 #ifdef USE_TCP
 "    -T           Disable tcp\n\
f4194f69
     -N           Number of tcp child processes (default: equal to `-n')\n\
84597b7b
     -W type      poll method (depending on support in OS, it can be: poll,\n\
                   epoll_lt, epoll_et, sigio_rt, select, kqueue, /dev/poll)\n"
5dcfb23d
 #endif
c3611173
 #ifdef USE_SCTP
c8e95587
 "    -S           disable sctp\n\
5219ecb7
     -Q            Number of sctp child processes (default: equal to `-n')\n"
c3611173
 #endif /* USE_SCTP */
5dcfb23d
 "    -V           Version number\n\
1b1b19d8
     -h           This help message\n\
c3ce2841
     -b nr        Maximum receive buffer size which will not be exceeded by\n\
16d4e079
                   auto-probing procedure even if  OS allows\n\
4e2fdd79
     -m nr        Size of shared memory allocated in Megabytes\n\
7b3a6eca
     -M nr        Size of private memory allocated, in Megabytes\n\
f4194f69
     -w dir       Change the working directory to \"dir\" (default: \"/\")\n\
0762e9d5
     -t dir       Chroot to \"dir\"\n\
5dcfb23d
     -u uid       Change uid \n\
     -g gid       Change gid \n\
     -P file      Create a pid file\n\
5219ecb7
     -G file      Create a pgid file\n\
b01dc20a
     -O nr        Script optimization level (debugging option)\n\
     -a mode      Auto aliases mode: enable with yes or on,\n\
95dec431
                   disable with no or off\n\
f3992928
     -A define    Add config pre-processor define (e.g., -A WITH_AUTH)\n\
     -x name      Specify internal manager for shared memory (shm)\n\
                   - can be: fm, qm or tlsf\n\
     -X name      Specify internal manager for private memory (pkg)\n\
                   - if omitted, the one for shm is used\n"
f571aa35
 #ifdef STATS
97f17e60
 "    -s file     File to which statistics is dumped (disabled otherwise)\n"
f571aa35
 #endif
 ;
512dcd98
 
9167c186
 
af6fb476
 /* print compile-time constants */
abb01fb4
 void print_ct_constants(void)
af6fb476
 {
30f1f956
 #ifdef ADAPTIVE_WAIT
 	printf("ADAPTIVE_WAIT_LOOPS=%d, ", ADAPTIVE_WAIT_LOOPS);
 #endif
40a8d9dd
 /*
30f1f956
 #ifdef SHM_MEM
 	printf("SHM_MEM_SIZE=%d, ", SHM_MEM_SIZE);
 #endif
40a8d9dd
 */
30f1f956
 	printf("MAX_RECV_BUFFER_SIZE %d, MAX_LISTEN %d,"
7b3a6eca
 			" MAX_URI_SIZE %d, BUF_SIZE %d, DEFAULT PKG_SIZE %uMB\n",
b017f49c
 		MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE,
bdc85a8c
 		BUF_SIZE, PKG_MEM_SIZE);
0ba367ec
 #ifdef USE_TCP
 	printf("poll method support: %s.\n", poll_support);
 #endif
af6fb476
 }
512dcd98
 
f5803916
 /* print compile-time constants */
abb01fb4
 void print_internals(void)
f5803916
 {
 	printf("Print out of %s internals\n", NAME);
 	printf("  Version: %s\n", full_version);
 	printf("  Default config: %s\n", CFG_FILE);
 	printf("  Default paths to modules: %s\n", MODS_DIR);
 	printf("  Compile flags: %s\n", ver_flags );
 	printf("  MAX_RECV_BUFFER_SIZE=%d\n", MAX_RECV_BUFFER_SIZE);
 	printf("  MAX_LISTEN=%d\n", MAX_LISTEN);
 	printf("  MAX_URI_SIZE=%d\n", MAX_URI_SIZE);
 	printf("  BUF_SIZE=%d\n", BUF_SIZE);
 	printf("  DEFAULT PKG_SIZE=%uMB\n", PKG_MEM_SIZE);
 #ifdef SHM_MEM
 	printf("  DEFAULT SHM_SIZE=%uMB\n", SHM_MEM_SIZE);
 #endif
 #ifdef ADAPTIVE_WAIT
 	printf("  ADAPTIVE_WAIT_LOOPS=%d\n", ADAPTIVE_WAIT_LOOPS);
 #endif
 #ifdef USE_TCP
 	printf("  TCP poll methods: %s\n", poll_support);
 #endif
 	printf("  Source code revision ID: %s\n", ver_id);
 	printf("  Compiled with: %s\n", ver_compiler);
 	printf("  Compiled on: %s\n", ver_compiled_time);
 	printf("Thank you for flying %s!\n", NAME);
 }
 
53c7e0f1
 /* debugging function */
e60a9728
 /*
abb01fb4
 void receive_stdin_loop(void)
888ca09d
 {
 	#define BSIZE 1024
 	char buf[BSIZE+1];
 	int len;
5655ca6f
 
888ca09d
 	while(1){
 		len=fread(buf,1,BSIZE,stdin);
 		buf[len+1]=0;
 		receive_msg(buf, len);
 		printf("-------------------------\n");
 	}
 }
e60a9728
 */
888ca09d
 
1b1b19d8
 /* global vars */
 
b484b774
 int own_pgid = 0; /* whether or not we have our own pgid (and it's ok
 					 to use kill(0, sig) */
f4194f69
 
c82fe029
 char* mods_dir = MODS_DIR;  /* search path for dyn. loadable modules */
e1e40d3a
 int   mods_dir_cmd = 0; /* mods dir path set in command lin e*/
f4194f69
 
1b1b19d8
 char* cfg_file = 0;
4e2fdd79
 unsigned int maxbuffer = MAX_RECV_BUFFER_SIZE; /* maximum buffer size we do
53c7e0f1
 												  not want to exceed during the
b017f49c
 												  auto-probing procedure; may
4e2fdd79
 												  be re-configured */
5cd87175
 unsigned int sql_buffer_size = 65535; /* Size for the SQL buffer. Defaults to 64k. 
                                          This may be re-configured */
edf5e385
 int socket_workers = 0;		/* number of workers processing requests for a socket
 							   - it's reset everytime with a new listen socket */
 int children_no = 0;		/* number of children processing requests */
5b532c7f
 #ifdef USE_TCP
edf5e385
 int tcp_cfg_children_no = 0; /* set via config or command line option */
 int tcp_children_no = 0; /* based on socket_workers and tcp_cfg_children_no */
5dcfb23d
 int tcp_disable = 0; /* 1 if tcp is disabled */
5b532c7f
 #endif
f22b996b
 #ifdef USE_TLS
6c53d41a
 #ifdef	CORE_TLS
 int tls_disable = 0;  /* tls enabled by default */
 #else
 int tls_disable = 1;  /* tls disabled by default */
 #endif /* CORE_TLS */
 #endif /* USE_TLS */
c3611173
 #ifdef USE_SCTP
 int sctp_children_no = 0;
c8e95587
 int sctp_disable = 2; /* 1 if sctp is disabled, 2 if auto mode, 0 enabled */
c3611173
 #endif /* USE_SCTP */
37209e14
 
53c7e0f1
 struct process_table *pt=0;		/*array with children pids, 0= main proc,
4e2fdd79
 									alloc'ed in shared mem if possible*/
021e7e0e
 int *process_count = 0;			/* Total number of SER processes currently
37209e14
 								   running */
 gen_lock_t* process_lock;		/* lock on the process table */
 int process_no = 0;				/* index of process in the pt */
 
78a65d14
 time_t up_since;
6e94f57f
 int sig_flag = 0;              /* last signal received */
1b1b19d8
 int dont_fork = 0;
bc404f2b
 int dont_daemonize = 0;
1b1b19d8
 int log_stderr = 0;
6bda9c0b
 int log_color = 0;
95bf8645
 /* set custom app name for syslog printing */
 char *log_name = 0;
35e94c97
 char *log_prefix_fmt = 0;
02f62296
 pid_t creator_pid = (pid_t) -1;
dda578ba
 int config_check = 0;
caf80ae6
 /* check if reply first via host==us */
b017f49c
 int check_via =  0;
face488e
 /* translate user=phone URIs to TEL URIs */
 int phone2tel = 1;
af93cbdf
 /* debugging level for timer debugging */
 int timerlog = L_WARN;
258b58e2
 /* should replies include extensive warnings? by default no,
caf80ae6
    good for trouble-shooting
 */
258b58e2
 int sip_warning = 0;
caf80ae6
 /* should localy-generated messages include server's signature?
    be default yes, good for trouble-shooting
 */
 int server_signature=1;
c745469f
 str server_hdr = {SERVER_HDR, SERVER_HDR_LEN};
 str user_agent_hdr = {USER_AGENT, USER_AGENT_LEN};
8fb8b261
 str version_table = {VERSION_TABLE, VERSION_TABLE_LEN};
2d4b798e
 /* should ser try to locate outbound interface on multihomed
  * host? by default not -- too expensive
  */
 int mhomed=0;
b017f49c
 /* use dns and/or rdns or to see if we need to add
caf80ae6
    a ;received=x.x.x.x to via: */
b017f49c
 int received_dns = 0;
bb4cd6b0
 /* add or not the rev dns names to aliases list */
 int sr_auto_aliases=1;
c9ca45b3
 char* working_dir = 0;
 char* chroot_dir = 0;
ca1358f2
 char* runtime_dir = "" RUN_DIR;
054cb6cf
 char* user=0;
 char* group=0;
c9ca45b3
 int uid = 0;
 int gid = 0;
71fd3ebd
 char* sock_user=0;
 char* sock_group=0;
 int sock_uid= -1;
 int sock_gid= -1;
 int sock_mode= S_IRUSR| S_IWUSR| S_IRGRP| S_IWGRP; /* rw-rw---- */
 
89fde575
 int server_id = 0; /* Configurable unique ID of the server */
 
e008edb9
 /* maximum number of branches for transaction */
 unsigned int sr_dst_max_branches = MAX_BRANCHES_DEFAULT;
 
d4ed4771
 /* set timeval for each received sip message */
 int sr_msg_time = 1;
 
214b161e
 /* onsend_route is executed for replies*/
 int onsend_route_reply = 0;
 
385c63eb
 /* more config stuff */
 int disable_core_dump=0; /* by default enabled */
 int open_files_limit=-1; /* don't touch it by default */
8390f722
 
 /* memory options */
 int shm_force_alloc=0; /* force immediate (on startup) page allocation
 						  (by writting 0 in the pages), useful if
 						  mlock_pages is also 1 */
 int mlock_pages=0; /* default off, try to disable swapping */
 
 /* real time options */
 int real_time=0; /* default off, flags: 1 on only timer, 2  slow timer,
16d4e079
 										4 all procs (7=all) */
021e7e0e
 int rt_prio=0;
8390f722
 int rt_policy=0; /* SCHED_OTHER */
 int rt_timer1_prio=0;  /* "fast" timer */
 int rt_timer2_prio=0;  /* "slow" timer */
 int rt_timer1_policy=0; /* "fast" timer, SCHED_OTHER */
 int rt_timer2_policy=0; /* "slow" timer, SCHED_OTHER */
 
 
caf80ae6
 /* a hint to reply modules whether they should send reply
    to IP advertised in Via or IP from which a request came
 */
 int reply_to_via=0;
1b1b19d8
 
2ba73117
 #ifdef USE_MCAST
 int mcast_loopback = 0;
956d111a
 int mcast_ttl = -1; /* if -1, don't touch it, use the default (usually 1) */
2ba73117
 #endif /* USE_MCAST */
 
fe09f315
 int tos = IPTOS_LOWDELAY;
f3a26797
 int pmtu_discovery = 0;
fe09f315
 
3e154160
 int auto_bind_ipv6 = 0;
 
36ef0329
 #if 0
1d597ac3
 char* names[MAX_LISTEN];              /* our names */
 int names_len[MAX_LISTEN];            /* lengths of the names*/
4e2fdd79
 struct ip_addr addresses[MAX_LISTEN]; /* our ips */
1d597ac3
 int addresses_no=0;                   /* number of names/ips */
36ef0329
 #endif
9f4c52ce
 struct socket_info* udp_listen=0;
5b532c7f
 #ifdef USE_TCP
f2e1aa50
 int tcp_main_pid=0; /* set after the tcp main process is started */
9f4c52ce
 struct socket_info* tcp_listen=0;
5b532c7f
 #endif
f22b996b
 #ifdef USE_TLS
9f4c52ce
 struct socket_info* tls_listen=0;
f22b996b
 #endif
c3611173
 #ifdef USE_SCTP
 struct socket_info* sctp_listen=0;
 #endif
1baa06b5
 struct socket_info* bind_address=0; /* pointer to the crt. proc.
e3fc93f4
 									 listening address*/
36ef0329
 struct socket_info* sendipv4; /* ipv4 socket to use when msg. comes from ipv6*/
 struct socket_info* sendipv6; /* same as above for ipv6 */
22e7e32e
 #ifdef USE_RAW_SOCKS
 int raw_udp4_send_sock = -1; /* raw socket used for sending udp4 packets */
 #endif /* USE_RAW_SOCKS */
f2f969dd
 #ifdef USE_TCP
b017f49c
 struct socket_info* sendipv4_tcp;
 struct socket_info* sendipv6_tcp;
f2f969dd
 #endif
f22b996b
 #ifdef USE_TLS
 struct socket_info* sendipv4_tls;
 struct socket_info* sendipv6_tls;
 #endif
c3611173
 #ifdef USE_SCTP
 struct socket_info* sendipv4_sctp;
 struct socket_info* sendipv6_sctp;
 #endif
36ef0329
 
 unsigned short port_no=0; /* default port*/
f22b996b
 #ifdef USE_TLS
 unsigned short tls_port_no=0; /* default port */
 #endif
1b1b19d8
 
e278821b
 struct host_alias* aliases=0; /* name aliases list */
 
3167c744
 /* Parameter to child_init */
 int child_rank = 0;
 
96d09107
 /* how much to wait for children to terminate, before taking extreme measures*/
 int ser_kill_timeout=DEFAULT_SER_KILL_TIMEOUT;
 
a76545c8
 /* process_bm_t process_bit = 0; */
cc2199a9
 #ifdef ROUTE_SRV
 #endif
888ca09d
 
63fa628f
 /* cfg parsing */
 int cfg_errors=0;
dcb59e67
 int cfg_warnings=0;
 
888ca09d
 
40a8d9dd
 /* shared memory (in MB) */
647cc983
 unsigned long shm_mem_size=0;
7b3a6eca
 /* private (pkg) memory (in MB) */
 unsigned long pkg_mem_size=0;
40a8d9dd
 
049f64c2
 /* export command-line to anywhere else */
 int my_argc;
 char **my_argv;
 
29e63735
 /* set to 1 when the cfg framework and core cfg is initialized/registered */
 static int cfg_ok=0;
 
cc2199a9
 #define MAX_FD 32 /* maximum number of inherited open file descriptors,
 		    (normally it shouldn't  be bigger  than 3) */
 
3e429f5c
 
 extern FILE* yyin;
abb01fb4
 extern int yyparse(void);
3e429f5c
 
 
428e3b83
 int is_main=1; /* flag = is this the  "main" process? */
b0123c36
 int fixup_complete=0; /* flag = is the fixup complete ? */
3e429f5c
 
a7cbdb26
 char* pid_file = 0; /* filename as asked by use */
9a428799
 char* pgid_file = 0;
8aeb47e2
 
 
4c2ef7f3
 /* memory manager */
0859d223
 #define SR_MEMMNG_DEFAULT	"qm"
4c2ef7f3
 
 char *sr_memmng_pkg = NULL;
 char *sr_memmng_shm = NULL;
 
53c7e0f1
 /* call it before exiting; if show_status==1, mem status is displayed */
ad2f899c
 void cleanup(int show_status)
8aeb47e2
 {
e4f42ce1
 	int memlog;
ad2f899c
 
8aeb47e2
 	/*clean-up*/
fbe11914
 #ifndef SHM_SAFE_MALLOC
4c2ef7f3
 	if (_shm_lock)
dd0e65a8
 		shm_unlock(); /* hack: force-unlock the shared memory lock in case
b017f49c
 					 some process crashed and let it locked; this will
7fb8a246
 					 allow an almost gracious shutdown */
fbe11914
 #endif
56131033
 	destroy_rpcs();
8aeb47e2
 	destroy_modules();
dcb59e67
 #ifdef USE_DNS_CACHE
 	destroy_dns_cache();
 #endif
 #ifdef USE_DST_BLACKLIST
 	destroy_dst_blacklist();
 #endif
5174bbf3
 	/* restore the original core configuration before the
 	 * config block is freed, otherwise even logging is unusable,
 	 * it can case segfault */
29e63735
 	if (cfg_ok){
 		cfg_update();
 		/* copy current config into default_core_cfg */
 		if (core_cfg)
 			default_core_cfg=*((struct cfg_group_core*)core_cfg);
 	}
5174bbf3
 	core_cfg = &default_core_cfg;
9188021a
 	cfg_destroy();
8aeb47e2
 #ifdef USE_TCP
 	destroy_tcp();
f22b996b
 #ifdef USE_TLS
 	destroy_tls();
7ad18de8
 #endif /* USE_TLS */
 #endif /* USE_TCP */
c3611173
 #ifdef USE_SCTP
7f8e7a85
 	sctp_core_destroy();
c3611173
 #endif
8aeb47e2
 	destroy_timer();
7e7d9399
 	pv_destroy_api();
3c8bd369
 	destroy_script_cb();
ac34f9f4
 	destroy_nonsip_hooks();
93349b4e
 	destroy_routes();
d307929c
 	destroy_atomic_ops();
4208dc00
 	destroy_counters();
e4f42ce1
 	memlog=cfg_get(core, core_cfg, memlog);
8aeb47e2
 #ifdef PKG_MALLOC
d740c34e
 	if (show_status && memlog <= cfg_get(core, core_cfg, debug)){
 		if (cfg_get(core, core_cfg, mem_summary) & 1) {
 			LOG(memlog, "Memory status (pkg):\n");
 			pkg_status();
 		}
a31cd01b
 		if (cfg_get(core, core_cfg, mem_summary) & 4) {
d740c34e
 			LOG(memlog, "Memory still-in-use summary (pkg):\n");
 			pkg_sums();
 		}
8aeb47e2
 	}
 #endif
 #ifdef SHM_MEM
b137a4b8
 	if (pt) shm_free(pt);
8aeb47e2
 	pt=0;
d740c34e
 	if (show_status && memlog <= cfg_get(core, core_cfg, debug)){
a31cd01b
 		if (cfg_get(core, core_cfg, mem_summary) & 2) {
8aeb47e2
 			LOG(memlog, "Memory status (shm):\n");
 			shm_status();
d740c34e
 		}
a31cd01b
 		if (cfg_get(core, core_cfg, mem_summary) & 8) {
ed20ee1d
 			LOG(memlog, "Memory still-in-use summary (shm):\n");
 			shm_sums();
d740c34e
 		}
8aeb47e2
 	}
 	/* zero all shmem alloc vars that we still use */
4c2ef7f3
 	shm_destroy_manager();
8aeb47e2
 #endif
8b8fc486
 	destroy_lock_ops();
8aeb47e2
 	if (pid_file) unlink(pid_file);
9a428799
 	if (pgid_file) unlink(pgid_file);
4c2ef7f3
 	pkg_destroy_manager();
8aeb47e2
 }
 
 
b484b774
 /* tries to send a signal to all our processes
  * if daemonized  is ok to send the signal to all the process group,
  * however if not daemonized we might end up sending the signal also
b017f49c
  * to the shell which launched us => most signals will kill it if
  * it's not in interactive mode and we don't want this. The non-daemonized
  * case can occur when an error is encountered before daemonize is called
b484b774
  * (e.g. when parsing the config file) or when ser is started in "dont-fork"
  *  mode. Sending the signal to all the processes in pt[] will not work
b017f49c
  *  for processes forked from modules (which have no correspondent entry in
b484b774
  *  pt), but this can happen only in dont_fork mode (which is only for
  *  debugging). So in the worst case + "dont-fork" we might leave some
  *  zombies. -- andrei */
 static void kill_all_children(int signum)
 {
 	int r;
02dae965
 
b484b774
 	if (own_pgid) kill(0, signum);
37209e14
 	else if (pt){
d4fb00dc
 		 /* lock processes table only if this is a child process
 		  * (only main can add processes, so from main is safe not to lock
 		  *  and moreover it avoids the lock-holding suicidal children problem)
 		  */
021e7e0e
 		if (!is_main) lock_get(process_lock);
37209e14
 		for (r=1; r<*process_count; r++){
d4fb00dc
 			if (r==process_no) continue; /* try not to be suicidal */
37209e14
 			if (pt[r].pid) {
 				kill(pt[r].pid, signum);
 			}
a2a91d7d
 			else LM_CRIT("killing: %s > %d no pid!!!\n",
37209e14
 							pt[r].desc, pt[r].pid);
 		}
d4fb00dc
 		if (!is_main) lock_release(process_lock);
37209e14
 	}
b484b774
 }
 
 
 
f2e1aa50
 /* if this handler is called, a critical timeout has occurred while
7fb8a246
  * waiting for the children to finish => we should kill everything and exit */
 static void sig_alarm_kill(int signo)
 {
 	kill_all_children(SIGKILL); /* this will kill the whole group
 								  including "this" process;
 								  for debugging replace with SIGABRT
 								  (but warning: it might generate lots
 								   of cores) */
 }
 
 
f2e1aa50
 /* like sig_alarm_kill, but the timeout has occurred when cleaning up
7fb8a246
  * => try to leave a core for future diagnostics */
 static void sig_alarm_abort(int signo)
 {
 	/* LOG is not signal safe, but who cares, we are abort-ing anyway :-) */
a2a91d7d
 	LM_CRIT("shutdown timeout triggered, dying...");
7fb8a246
 	abort();
 }
 
 
 
d4fb00dc
 static void shutdown_children(int sig, int show_status)
 {
 	kill_all_children(sig);
 	if (set_sig_h(SIGALRM, sig_alarm_kill) == SIG_ERR ) {
a2a91d7d
 		LM_ERR("could not install SIGALARM handler\n");
d4fb00dc
 		/* continue, the process will die anyway if no
 		 * alarm is installed which is exactly what we want */
 	}
 	alarm(ser_kill_timeout);
021e7e0e
 	while((wait(0) > 0) || (errno==EINTR)); /* wait for all the
d4fb00dc
 											   children to terminate*/
 	set_sig_h(SIGALRM, sig_alarm_abort);
 	cleanup(show_status); /* cleanup & show status*/
 	alarm(0);
 	set_sig_h(SIGALRM, SIG_IGN);
 }
 
 
 
abb01fb4
 void handle_sigs(void)
6e94f57f
 {
 	pid_t	chld;
 	int	chld_status;
e4f42ce1
 	int memlog;
6e94f57f
 
 	switch(sig_flag){
 		case 0: break; /* do nothing*/
 		case SIGPIPE:
c082a437
 				/* SIGPIPE might be rarely received on use of
 				   exec module; simply ignore it
 				 */
a2a91d7d
 				LM_WARN("SIGPIPE received and ignored\n");
c082a437
 				break;
 		case SIGINT:
6e94f57f
 		case SIGTERM:
 			/* we end the program in all these cases */
 			if (sig_flag==SIGINT)
002879f8
 				LM_DBG("INT received, program terminates\n");
6e94f57f
 			else
002879f8
 				LM_DBG("SIGTERM received, program terminates\n");
a2a91d7d
 			LM_NOTICE("Thank you for flying " NAME "!!!\n");
d4fb00dc
 			/* shutdown/kill all the children */
 			shutdown_children(SIGTERM, 1);
6e94f57f
 			exit(0);
 			break;
b017f49c
 
6e94f57f
 		case SIGUSR1:
 #ifdef STATS
 			dump_all_statistic();
 #endif
e4f42ce1
 		memlog=cfg_get(core, core_cfg, memlog);
6e94f57f
 #ifdef PKG_MALLOC
d740c34e
 		if (memlog <= cfg_get(core, core_cfg, debug)){
 			if (cfg_get(core, core_cfg, mem_summary) & 1) {
 				LOG(memlog, "Memory status (pkg):\n");
 				pkg_status();
 			}
 			if (cfg_get(core, core_cfg, mem_summary) & 2) {
 				LOG(memlog, "Memory still-in-use summary (pkg):\n");
 				pkg_sums();
 			}
 		}
6e94f57f
 #endif
 #ifdef SHM_MEM
d740c34e
 		if (memlog <= cfg_get(core, core_cfg, debug)){
 			if (cfg_get(core, core_cfg, mem_summary) & 1) {
 				LOG(memlog, "Memory status (shm):\n");
 				shm_status();
 			}
 			if (cfg_get(core, core_cfg, mem_summary) & 2) {
 				LOG(memlog, "Memory still-in-use summary (shm):\n");
 				shm_sums();
 			}
 		}
6e94f57f
 #endif
 			break;
b017f49c
 
6e94f57f
 		case SIGCHLD:
 			while ((chld=waitpid( -1, &chld_status, WNOHANG ))>0) {
b017f49c
 				if (WIFEXITED(chld_status))
a2a91d7d
 					LM_ALERT("child process %ld exited normally,"
ca351abe
 							" status=%d\n", (long)chld,
6e94f57f
 							WEXITSTATUS(chld_status));
 				else if (WIFSIGNALED(chld_status)) {
a2a91d7d
 					LM_ALERT("child process %ld exited by a signal"
ca351abe
 							" %d\n", (long)chld, WTERMSIG(chld_status));
6e94f57f
 #ifdef WCOREDUMP
a2a91d7d
 					LM_ALERT("core was %sgenerated\n",
a0196887
 							 WCOREDUMP(chld_status) ?  "" : "not " );
6e94f57f
 #endif
b017f49c
 				}else if (WIFSTOPPED(chld_status))
a2a91d7d
 					LM_ALERT("child process %ld stopped by a"
ca351abe
 								" signal %d\n", (long)chld,
6e94f57f
 								 WSTOPSIG(chld_status));
 			}
49041f7b
 #ifndef STOP_JIRIS_CHANGES
 			if (dont_fork) {
a2a91d7d
 				LM_INFO("dont_fork turned on, living on\n");
49041f7b
 				break;
b017f49c
 			}
a2a91d7d
 			LM_INFO("terminating due to SIGCHLD\n");
49041f7b
 #endif
5a142f7c
 			LM_DBG("terminating due to SIGCHLD\n");
6e94f57f
 			/* exit */
d4fb00dc
 			shutdown_children(SIGTERM, 1);
dd7854ea
 			if (WIFSIGNALED(chld_status)) {
 				exit(1);
 			} else {
 				exit(0);
 			}
6e94f57f
 			break;
b017f49c
 
6e94f57f
 		case SIGHUP: /* ignoring it*/
002879f8
 					LM_DBG("SIGHUP received, ignoring it\n");
6e94f57f
 					break;
 		default:
a2a91d7d
 			LM_CRIT("unhandled signal %d\n", sig_flag);
6e94f57f
 	}
 	sig_flag=0;
 }
 
 
 
428e3b83
 /* added by jku; allows for regular exit on a specific signal;
    good for profiling which only works if exited regularly and
    not by default signal handlers
b017f49c
     - modified by andrei: moved most of the stuff to handle_sigs,
428e3b83
        made it safer for the "fork" case
 */
17cde665
 void sig_usr(int signo)
428e3b83
 {
 
e4f42ce1
 #ifdef PKG_MALLOC
 	int memlog;
 #endif
428e3b83
 
 	if (is_main){
 		if (sig_flag==0) sig_flag=signo;
 		else /*  previous sig. not processed yet, ignoring? */
 			return; ;
b017f49c
 		if (dont_fork)
428e3b83
 				/* only one proc, doing everything from the sig handler,
 				unsafe, but this is only for debugging mode*/
 			handle_sigs();
 	}else{
 		/* process the important signals */
 		switch(signo){
 			case SIGPIPE:
96d09107
 #ifdef SIG_DEBUG /* signal unsafe stuff follows */
a2a91d7d
 					LM_INFO("signal %d received\n", signo);
96d09107
 #endif
428e3b83
 				break;
 			case SIGINT:
 			case SIGTERM:
96d09107
 #ifdef SIG_DEBUG /* signal unsafe stuff follows */
a2a91d7d
 					LM_INFO("signal %d received\n", signo);
428e3b83
 					/* print memory stats for non-main too */
 					#ifdef PKG_MALLOC
5c323052
 					/* make sure we have current cfg values, but update only
 					  the safe part (values not requiring callbacks), to
 					  account for processes that might not have registered
 					  config support */
 					cfg_update_no_cbs();
e4f42ce1
 					memlog=cfg_get(core, core_cfg, memlog);
d740c34e
 					if (memlog <= cfg_get(core, core_cfg, debug)){
 						if (cfg_get(core, core_cfg, mem_summary) & 1) {
 							LOG(memlog, "Memory status (pkg):\n");
 							pkg_status();
 						}
 						if (cfg_get(core, core_cfg, mem_summary) & 2) {
 							LOG(memlog, "Memory still-in-use summary (pkg):"
 									"\n");
 							pkg_sums();
 						}
 					}
428e3b83
 					#endif
96d09107
 #endif
5b84defd
 					_exit(0);
428e3b83
 					break;
 			case SIGUSR1:
 				/* statistics, do nothing, printed only from the main proc */
 					break;
 				/* ignored*/
 			case SIGUSR2:
 			case SIGHUP:
 					break;
 			case SIGCHLD:
 #ifndef 			STOP_JIRIS_CHANGES
96d09107
 #ifdef SIG_DEBUG /* signal unsafe stuff follows */
002879f8
 					LM_DBG("SIGCHLD received: "
428e3b83
 						"we do not worry about grand-children\n");
96d09107
 #endif
428e3b83
 #else
5b84defd
 					_exit(0); /* terminate if one child died */
428e3b83
 #endif
96d09107
 					break;
428e3b83
 		}
 	}
 }
 
 
 
 /* install the signal handlers, returns 0 on success, -1 on error */
abb01fb4
 int install_sigs(void)
428e3b83
 {
 	/* added by jku: add exit handler */
02dae965
 	if (set_sig_h(SIGINT, sig_usr) == SIG_ERR ) {
bf79b581
 		ERR("no SIGINT signal handler can be installed\n");
428e3b83
 		goto error;
 	}
 	/* if we debug and write to a pipe, we want to exit nicely too */
02dae965
 	if (set_sig_h(SIGPIPE, sig_usr) == SIG_ERR ) {
bf79b581
 		ERR("no SIGINT signal handler can be installed\n");
428e3b83
 		goto error;
 	}
02dae965
 	if (set_sig_h(SIGUSR1, sig_usr)  == SIG_ERR ) {
bf79b581
 		ERR("no SIGUSR1 signal handler can be installed\n");
428e3b83
 		goto error;
 	}
02dae965
 	if (set_sig_h(SIGCHLD , sig_usr)  == SIG_ERR ) {
bf79b581
 		ERR("no SIGCHLD signal handler can be installed\n");
428e3b83
 		goto error;
 	}
02dae965
 	if (set_sig_h(SIGTERM , sig_usr)  == SIG_ERR ) {
bf79b581
 		ERR("no SIGTERM signal handler can be installed\n");
428e3b83
 		goto error;
 	}
02dae965
 	if (set_sig_h(SIGHUP , sig_usr)  == SIG_ERR ) {
bf79b581
 		ERR("no SIGHUP signal handler can be installed\n");
428e3b83
 		goto error;
 	}
02dae965
 	if (set_sig_h(SIGUSR2 , sig_usr)  == SIG_ERR ) {
bf79b581
 		ERR("no SIGUSR2 signal handler can be installed\n");
428e3b83
 		goto error;
 	}
 	return 0;
 error:
 	return -1;
 }
 
943a9d00
 /* returns -1 on error, 0 on success
  * sets proto */
6335d07c
 int parse_proto(unsigned char* s, long len, int* proto)
943a9d00
 {
c3611173
 #define PROTO2UINT3(a, b, c) ((	(((unsigned int)(a))<<16)+ \
943a9d00
 								(((unsigned int)(b))<<8)+  \
 								((unsigned int)(c)) ) | 0x20202020)
c3611173
 #define PROTO2UINT4(a, b ,c ,d) ((	(((unsigned int)(a))<<24)+ \
 									(((unsigned int)(b))<<16)+ \
 									(((unsigned int)(c))<< 8)+ \
 									(((unsigned int)(d))) \
 								  )| 0x20202020 )
943a9d00
 	unsigned int i;
c3611173
 	if (likely(len==3)){
 		i=PROTO2UINT3(s[0], s[1], s[2]);
 		switch(i){
 			case PROTO2UINT3('u', 'd', 'p'):
 				*proto=PROTO_UDP;
 				break;
943a9d00
 #ifdef USE_TCP
c3611173
 			case PROTO2UINT3('t', 'c', 'p'):
 				*proto=PROTO_TCP;
 				break;
943a9d00
 #ifdef USE_TLS
c3611173
 			case PROTO2UINT3('t', 'l', 's'):
 				*proto=PROTO_TLS;
 				break;
943a9d00
 #endif
 #endif
c3611173
 			default:
 				return -1;
 		}
 	}
 #ifdef USE_SCTP
 	else if (likely(len==4)){
 		i=PROTO2UINT4(s[0], s[1], s[2], s[3]);
 		if (i==PROTO2UINT4('s', 'c', 't', 'p'))
 			*proto=PROTO_SCTP;
 		else
943a9d00
 			return -1;
 	}
c3611173
 #endif /* USE_SCTP */
 	else
3d4a77d8
 	/* Deliberately leaving out PROTO_WS and PROTO_WSS as these are just
 	   upgraded TCP/TLS connections. */
c3611173
 		return -1;
943a9d00
 	return 0;
 }
 
 
 
72bba9e3
 static struct name_lst* mk_name_lst_elem(char* name, int name_len, int flags)
 {
 	struct name_lst* l;
 	
 	l=pkg_malloc(sizeof(struct name_lst)+name_len+1/* 0 */);
 	if (l){
 		l->name=((char*)l)+sizeof(struct name_lst);
 		memcpy(l->name, name, name_len);
 		l->name[name_len]=0;
 		l->flags=flags;
 		l->next=0;
 	}
 	return l;
 }
 
 
 
 /* free a name_lst list with elements allocated with mk_name_lst_elem
  * (single block both for the structure and for the name) */
 static void free_name_lst(struct name_lst* lst)
 {
 	struct name_lst* l;
 	
 	while(lst){
 		l=lst;
 		lst=lst->next;
 		pkg_free(l);
 	}
 }
 
 
 
 /* parse h and returns a name lst (flags are set to SI_IS_MHOMED if
  * h contains more then one name or contains a name surrounded by '(' ')' )
  * valid formats:    "hostname"
  *                   "(hostname, hostname1, hostname2)"
  *                   "(hostname hostname1 hostname2)"
  *                   "(hostname)"
  */
 static struct name_lst* parse_name_lst(char* h, int h_len)
 {
 	char* last;
 	char* p;
 	struct name_lst* n_lst;
 	struct name_lst* l;
 	struct name_lst** tail;
 	int flags;
 	
 	n_lst=0;
 	tail=&n_lst;
 	last=h+h_len-1;
 	flags=0;
 	/* eat whitespace */
 	for(; h<=last && ((*h==' ') || (*h=='\t')); h++);
 	for(; last>h && ((*last==' ') || (*last=='\t')); last--);
 	/* catch empty strings and invalid lens */
 	if (h>last) goto error;
 	
 	if (*h=='('){
 		/* list mode */
 		if (*last!=')' || ((h+1)>(last-1)))
 			goto error;
 		h++;
 		last--;
 		flags=SI_IS_MHOMED;
 		for(p=h; p<=last; p++)
 			switch (*p){
 				case ',':
 				case ';':
 				case ' ':
 				case '\t':
 					if ((int)(p-h)>0){
 						l=mk_name_lst_elem(h, (int)(p-h), flags);
 						if (l==0) 
 							goto error;
 						*tail=l;
 						tail=&l->next;
 					}
 					h=p+1;
 					break;
 			}
 	}else{
 		/* single addr. mode */
 		flags=0;
 		p=last+1;
 	}
 	if ((int)(p-h)>0){
 		l=mk_name_lst_elem(h, (int)(p-h), flags);
 		if (l==0) 
 			goto error;
 		*tail=l;
 		tail=&l->next;
 	}
 	return n_lst;
 error:
 	if (n_lst) free_name_lst(n_lst);
 	return 0;
 }
 
 
 
943a9d00
 /*
72bba9e3
  * parses [proto:]host[:port]  or
  *  [proto:](host_1, host_2, ... host_n)[:port]
943a9d00
  * where proto= udp|tcp|tls
72bba9e3
  * returns  fills proto, port, host and returns list of addresses on success
  * (pkg malloc'ed) and 0 on failure
943a9d00
  */
df088fb8
 /** get protocol host and port from a string representation.
  * parses [proto:]host[:port]  or
  *  [proto:](host_1, host_2, ... host_n)[:port]
  * where proto= udp|tcp|tls|sctp
  * @param s  - string (like above)
  * @param host - will be filled with the host part
  *               Note: for multi-homing it wil contain all the addresses
  *               (e.g.: "sctp:(1.2.3.4, 5.6.7.8)" => host="(1.2.3.4, 5.6.7.8)")
  * @param hlen - will be filled with the length of the host part.
  * @param port - will be filled with the port if present or 0 if it's not.
  * @param proto - will be filled with the protocol if present or PROTO_NONE
  *                if it's not.
  * @return  fills proto, port, host and returns 0 on success and -1 on failure.
  */
 int parse_phostport(char* s, char** host, int* hlen,
537ce843
 								 int* port, int* proto)
943a9d00
 {
 	char* first; /* first ':' occurrence */
 	char* second; /* second ':' occurrence */
 	char* p;
 	int bracket;
 	char* tmp;
b017f49c
 
943a9d00
 	first=second=0;
 	bracket=0;
b017f49c
 
943a9d00
 	/* find the first 2 ':', ignoring possible ipv6 addresses
 	 * (substrings between [])
 	 */
 	for(p=s; *p; p++){
 		switch(*p){
 			case '[':
 				bracket++;
 				if (bracket>1) goto error_brackets;
 				break;
 			case ']':
 				bracket--;
 				if (bracket<0) goto error_brackets;
 				break;
 			case ':':
 				if (bracket==0){
 					if (first==0) first=p;
 					else if( second==0) second=p;
 					else goto error_colons;
 				}
 				break;
 		}
 	}
df088fb8
 	if (p==s) return -1;
943a9d00
 	if (*(p-1)==':') goto error_colons;
b017f49c
 
943a9d00
 	if (first==0){ /* no ':' => only host */
 		*host=s;
 		*hlen=(int)(p-s);
 		*port=0;
 		*proto=0;
72bba9e3
 		goto end;
943a9d00
 	}
 	if (second){ /* 2 ':' found => check if valid */
d7a3fdea
 		if (parse_proto((unsigned char*)s, first-s, proto)<0) goto error_proto;
943a9d00
 		*port=strtol(second+1, &tmp, 10);
 		if ((tmp==0)||(*tmp)||(tmp==second+1)) goto error_port;
 		*host=first+1;
 		*hlen=(int)(second-*host);
72bba9e3
 		goto end;
943a9d00
 	}
 	/* only 1 ':' found => it's either proto:host or host:port */
 	*port=strtol(first+1, &tmp, 10);
 	if ((tmp==0)||(*tmp)||(tmp==first+1)){
 		/* invalid port => it's proto:host */
d7a3fdea
 		if (parse_proto((unsigned char*)s, first-s, proto)<0) goto error_proto;
943a9d00
 		*port=0;
 		*host=first+1;
 		*hlen=(int)(p-*host);
 	}else{
 		/* valid port => its host:port */
 		*proto=0;
 		*host=s;
 		*hlen=(int)(first-*host);
 	}
72bba9e3
 end:
df088fb8
 	return 0;
943a9d00
 error_brackets:
a2a91d7d
 	LM_ERR("too many brackets in %s\n", s);
df088fb8
 	return -1;
943a9d00
 error_colons:
a2a91d7d
 	LM_ERR("too many colons in %s\n", s);
df088fb8
 	return -1;
943a9d00
 error_proto:
a2a91d7d
 	LM_ERR("bad protocol in %s\n", s);
df088fb8
 	return -1;
943a9d00
 error_port:
a2a91d7d
 	LM_ERR("bad port number in %s\n", s);
df088fb8
 	return -1;
 }
 
 
 
 /** get protocol host, port and MH addresses list from a string representation.
  * parses [proto:]host[:port]  or
  *  [proto:](host_1, host_2, ... host_n)[:port]
  * where proto= udp|tcp|tls|sctp
  * @param s  - string (like above)
  * @param host - will be filled with the host part
  *               Note: for multi-homing it wil contain all the addresses
  *               (e.g.: "sctp:(1.2.3.4, 5.6.7.8)" => host="(1.2.3.4, 5.6.7.8)")
  * @param hlen - will be filled with the length of the host part.
  * @param port - will be filled with the port if present or 0 if it's not.
  * @param proto - will be filled with the protocol if present or PROTO_NONE
  *                if it's not.
  * @return  fills proto, port, host and returns list of addresses on success
  * (pkg malloc'ed) and 0 on failure
  */
 static struct name_lst* parse_phostport_mh(char* s, char** host, int* hlen,
 								 int* port, int* proto)
 {
 	if (parse_phostport(s, host, hlen, port, proto)==0)
 		return parse_name_lst(*host, *hlen);
72bba9e3
 	return 0;
943a9d00
 }
 
 
df088fb8
 
b2471cfc
 /** Update \c cfg_file variable to contain full pathname. The function updates
  * the value of \c cfg_file global variable to contain full absolute pathname
  * to the main configuration file of SER. The function uses CFG_FILE macro to
  * determine the default path to the configuration file if the user did not
  * specify one using the command line option. If \c cfg_file contains an
  * absolute pathname then it is used unmodified, if it contains a relative
  * pathanme than the value returned by \c getcwd function will be added at the
  * beginning. This function must be run before SER changes its current working
  * directory to / (in daemon mode).
  * @return Zero on success, negative number
  * on error.
  */
 int fix_cfg_file(void)
 {
 	char* res = NULL;
 	size_t max_len, cwd_len, cfg_len;
 	
 	if (cfg_file == NULL) cfg_file = CFG_FILE;
 	if (cfg_file[0] == '/') return 0;
6f96f4fb
 	if (cfg_file[0] == '-' && strlen(cfg_file)==1) return 0;
b2471cfc
 	
 	/* cfg_file contains a relative pathname, get the current
 	 * working directory and add it at the beginning
 	 */
 	cfg_len = strlen(cfg_file);
 	
 	max_len = pathmax();
 	if ((res = malloc(max_len)) == NULL) goto error;
 	
 	if (getcwd(res, max_len) == NULL) goto error;
 	cwd_len = strlen(res);
 	
 	/* Make sure that the buffer is big enough */
 	if (cwd_len + 1 + cfg_len >= max_len) goto error;
 	
 	res[cwd_len] = '/';
 	memcpy(res + cwd_len + 1, cfg_file, cfg_len);
 	
 	res[cwd_len + 1 + cfg_len] = '\0'; /* Add terminating zero */
 	cfg_file = res;
 	return 0;
 	
  error:
 	fprintf(stderr, "ERROR: Unable to fix cfg_file to contain full pathname\n");
 	if (res) free(res);
 	return -1;
 }
 
943a9d00
 
cc2199a9
 /* main loop */
abb01fb4
 int main_loop(void)
cc2199a9
 {
9f4c52ce
 	int  i;
cc2199a9
 	pid_t pid;
9f4c52ce
 	struct socket_info* si;
f238de3d
 	char si_desc[MAX_PT_DESC];
af93cbdf
 #ifdef EXTRA_DEBUG
5f8ad85f
 	int r;
 #endif
edf5e385
 	int nrprocs;
b3d38eac
 	int woneinit;
cc2199a9
 
 	/* one "main" process and n children handling i/o */
 	if (dont_fork){
f571aa35
 #ifdef STATS
 		setstats( 0 );
 #endif
49de5d20
 		if (udp_listen==0){
a2a91d7d
 			LM_ERR("no fork mode requires at least one"
49de5d20
 					" udp listen address, exiting...\n");
 			goto error;
 		}
36ef0329
 		/* only one address, we ignore all the others */
9f4c52ce
 		if (udp_init(udp_listen)==-1) goto error;
 		bind_address=udp_listen;
22e7e32e
 		if (bind_address->address.af==AF_INET) {
61b60763
 			sendipv4=bind_address;
22e7e32e
 #ifdef USE_RAW_SOCKS
 		/* always try to have a raw socket opened if we are using ipv4 */
 		raw_udp4_send_sock = raw_socket(IPPROTO_RAW, 0, 0, 1);
 		if (raw_udp4_send_sock < 0) {
 			if ( default_core_cfg.udp4_raw > 0) {
 				/* force use raw socket failed */
 				ERR("could not initialize raw udp send socket (ipv4):"
 						" %s (%d)\n", strerror(errno), errno);
 				if (errno == EPERM)
 					ERR("could not initialize raw socket on startup"
 						" due to inadequate permissions, please"
 						" restart as root or with CAP_NET_RAW\n");
 				goto error;
 			}
 			default_core_cfg.udp4_raw = 0; /* disabled */
 		} else {
 			register_fds(1);
 			if (default_core_cfg.udp4_raw < 0) {
 				/* auto-detect => use it */
 				default_core_cfg.udp4_raw = 1; /* enabled */
002879f8
 				LM_DBG("raw socket possible => turning it on\n");
22e7e32e
 			}
9eb54078
 			if (default_core_cfg.udp4_raw_ttl < 0) {
 				/* auto-detect */
 				default_core_cfg.udp4_raw_ttl = sock_get_ttl(sendipv4->socket);
 				if (default_core_cfg.udp4_raw_ttl < 0)
 					/* error, use some default value */
 					default_core_cfg.udp4_raw_ttl = 63;
 			}
22e7e32e
 		}
 #else
94d2d2e6
 		default_core_cfg.udp4_raw = 0;
22e7e32e
 #endif /* USE_RAW_SOCKS */
 		} else
61b60763
 			sendipv6=bind_address;
9f4c52ce
 		if (udp_listen->next){
a2a91d7d
 			LM_WARN("using only the first listen address (no fork)\n");
36ef0329
 		}
5322385b
 
fbf0d2e0
 		/* delay cfg_shmize to the last moment (it must be called _before_
 		   forking). Changes to default cfgs after this point will be
 		   ignored.
 		*/
 		if (cfg_shmize() < 0) {
a2a91d7d
 			LM_CRIT("could not initialize shared configuration\n");
fbf0d2e0
 			goto error;
 		}
 	
5322385b
 		/* Register the children that will keep updating their
 		 * local configuration */
 		cfg_register_child(
 				1   /* main = udp listener */
 				+ 1 /* timer */
a482c5de
 				+ 1 /* wtimer */
5322385b
 #ifdef USE_SLOW_TIMER
 				+ 1 /* slow timer */
 #endif
 			);
53c7e0f1
 		if (do_suid()==-1) goto error; /* try to drop privileges */
db249450
 		/* process_no now initialized to zero -- increase from now on
b017f49c
 		   as new processes are forked (while skipping 0 reserved for main
db249450
 		*/
 
5d3449a0
 		/* Temporary set the local configuration of the main process
 		 * to make the group instances available in PROC_INIT.
 		 */
 		cfg_main_set_local();
 
35e94c97
 		/* init log prefix format */
 		log_prefix_init();
 
021e7e0e
 		/* init childs with rank==PROC_INIT before forking any process,
f828cb17
 		 * this is a place for delayed (after mod_init) initializations
 		 * (e.g. shared vars that depend on the total number of processes
 		 * that is known only after all mod_inits have been executed )
 		 * WARNING: the same init_child will be called latter, a second time
021e7e0e
 		 * for the "main" process with rank PROC_MAIN (make sure things are
f828cb17
 		 * not initialized twice)*/
 		if (init_child(PROC_INIT) < 0) {
a2a91d7d
 			LM_ERR("init_child(PROC_INT) -- exiting\n");
5d3449a0
 			cfg_main_reset_local();
f828cb17
 			goto error;
 		}
5d3449a0
 		cfg_main_reset_local();
4208dc00
 		if (counters_prefork_init(get_max_procs()) == -1) goto error;
f828cb17
 
af93cbdf
 #ifdef USE_SLOW_TIMER
 		/* we need another process to act as the "slow" timer*/
37209e14
 				pid = fork_process(PROC_TIMER, "slow timer", 0);
 				if (pid<0){
a2a91d7d
 					LM_CRIT("Cannot fork\n");
af93cbdf
 					goto error;
 				}
 				if (pid==0){
 					/* child */
 					/* timer!*/
 					/* process_bit = 0; */
8390f722
 					if (real_time&2)
 						set_rt_prio(rt_timer2_prio, rt_timer2_policy);
021e7e0e
 
af93cbdf
 					if (arm_slow_timer()<0) goto error;
 					slow_timer_main();
 				}else{
 					slow_timer_pid=pid;
 				}
5dc00db6
 #endif
af93cbdf
 				/* we need another process to act as the "main" timer*/
37209e14
 				pid = fork_process(PROC_TIMER, "timer", 0);
 				if (pid<0){
a2a91d7d
 					LM_CRIT("Cannot fork\n");
cd57180a
 					goto error;
 				}
 				if (pid==0){
 					/* child */
 					/* timer!*/
a76545c8
 					/* process_bit = 0; */
8390f722
 					if (real_time&1)
 						set_rt_prio(rt_timer1_prio, rt_timer1_policy);
af93cbdf
 					if (arm_timer()<0) goto error;
 					timer_main();
cbd9fc8b
 				}else{
cd57180a
 				}
1380e79e
 
a482c5de
 		if(sr_wtimer_start()<0) {
 			LM_CRIT("Cannot start wtimer\n");
 			goto error;
 		}
72b7f9a2
 		/* main process, receive loop */
 		process_no=0; /*main process number*/
f51155cf
 		pt[process_no].pid=getpid();
b017f49c
 		snprintf(pt[process_no].desc, MAX_PT_DESC,
 			"stand-alone receiver @ %s:%s",
f51155cf
 			 bind_address->name.s, bind_address->port_no_str.s );
021e7e0e
 
c3611173
 		/* call it also w/ PROC_MAIN to make sure modules that init things 
 		 * only in PROC_MAIN get a chance to run */
 		if (init_child(PROC_MAIN) < 0) {
a2a91d7d
 			LM_ERR("init_child(PROC_MAIN) -- exiting\n");
c3611173
 			goto error;
 		}
b017f49c
 
8390f722
 		/* We will call child_init even if we
 		 * do not fork - and it will be called with rank 1 because
 		 * in fact we behave like a child, not like main process
 		 */
eedd46b1
 
ece30366
 		if (init_child(PROC_SIPINIT) < 0) {
a2a91d7d
 			LM_ERR("init_child failed\n");
192ac55b
 			goto error;
 		}
391fa285
 		return udp_rcv_loop();
8390f722
 	}else{ /* fork: */
9e7eed4d
 
5322385b
 		/* Register the children that will keep updating their
 		 * local configuration. (udp/tcp/sctp listeneres
 		 * will be added later.) */
 		cfg_register_child(
 				1   /* timer */
a482c5de
 				+ 1   /* wtimer */
5322385b
 #ifdef USE_SLOW_TIMER
 				+ 1 /* slow timer */
 #endif
 			);
 
9f4c52ce
 		for(si=udp_listen;si;si=si->next){
1fb7b1aa
 			/* create the listening socket (for each address)*/
f2f969dd
 			/* udp */
9f4c52ce
 			if (udp_init(si)==-1) goto error;
36ef0329
 			/* get first ipv4/ipv6 socket*/
9f4c52ce
 			if ((si->address.af==AF_INET)&&
8b17718a
 					((sendipv4==0)||(sendipv4->flags&(SI_IS_LO|SI_IS_MCAST))))
9f4c52ce
 				sendipv4=si;
61b60763
 			if ( ((sendipv6==0)||(sendipv6->flags&(SI_IS_LO|SI_IS_MCAST))) &&
 					(si->address.af==AF_INET6))
9f4c52ce
 				sendipv6=si;
5322385b
 			/* children_no per each socket */
edf5e385
 			cfg_register_child((si->workers>0)?si->workers:children_no);
9f4c52ce
 		}
22e7e32e
 #ifdef USE_RAW_SOCKS
 		/* always try to have a raw socket opened if we are using ipv4 */
 		if (sendipv4) {
 			raw_udp4_send_sock = raw_socket(IPPROTO_RAW, 0, 0, 1);
 			if (raw_udp4_send_sock < 0) {
 				if ( default_core_cfg.udp4_raw > 0) {
 						/* force use raw socket failed */
 						ERR("could not initialize raw udp send socket (ipv4):"
 								" %s (%d)\n", strerror(errno), errno);
 						if (errno == EPERM)
 							ERR("could not initialize raw socket on startup"
 								" due to inadequate permissions, please"
 								" restart as root or with CAP_NET_RAW\n");
 						goto error;
 					}
 					default_core_cfg.udp4_raw = 0; /* disabled */
 			} else {
 				register_fds(1);
 				if (default_core_cfg.udp4_raw < 0) {
 					/* auto-detect => use it */
 					default_core_cfg.udp4_raw = 1; /* enabled */
002879f8
 					LM_DBG("raw socket possible => turning it on\n");
22e7e32e
 				}
9eb54078
 				if (default_core_cfg.udp4_raw_ttl < 0) {
 					/* auto-detect */
 					default_core_cfg.udp4_raw_ttl =
 						sock_get_ttl(sendipv4->socket);
 					if (default_core_cfg.udp4_raw_ttl < 0)
 						/* error, use some default value */
 						default_core_cfg.udp4_raw_ttl = 63;
 				}
22e7e32e
 			}
 		}
 #else
 		default_core_cfg.udp4_raw = 0;
 #endif /* USE_RAW_SOCKS */
c3611173
 #ifdef USE_SCTP
 		if (!sctp_disable){
 			for(si=sctp_listen; si; si=si->next){
7f8e7a85
 				if (sctp_core_init_sock(si)==-1)  goto error;
c3611173
 				/* get first ipv4/ipv6 socket*/
61b60763
 				if ((si->address.af==AF_INET) &&
 						((sendipv4_sctp==0) ||
 							(sendipv4_sctp->flags&(SI_IS_LO|SI_IS_MCAST))))
c3611173
 					sendipv4_sctp=si;
61b60763
 				if( ((sendipv6_sctp==0) || 
 							(sendipv6_sctp->flags&(SI_IS_LO|SI_IS_MCAST))) &&
 						(si->address.af==AF_INET6))
c3611173
 					sendipv6_sctp=si;
5322385b
 				/* sctp_children_no per each socket */
edf5e385
 				cfg_register_child((si->workers>0)?si->workers:sctp_children_no);
c3611173
 			}
 		}
 #endif /* USE_SCTP */
f2f969dd
 #ifdef USE_TCP
9f4c52ce
 		if (!tcp_disable){
 			for(si=tcp_listen; si; si=si->next){
5dcfb23d
 				/* same thing for tcp */
9f4c52ce
 				if (tcp_init(si)==-1)  goto error;
5dcfb23d
 				/* get first ipv4/ipv6 socket*/
9f4c52ce
 				if ((si->address.af==AF_INET)&&
61b60763
 						((sendipv4_tcp==0) ||
 							(sendipv4_tcp->flags&(SI_IS_LO|SI_IS_MCAST))))
9f4c52ce
 					sendipv4_tcp=si;
61b60763
 				if( ((sendipv6_tcp==0) ||
 							(sendipv6_tcp->flags&(SI_IS_LO|SI_IS_MCAST))) &&
 						(si->address.af==AF_INET6))
9f4c52ce
 					sendipv6_tcp=si;
5dcfb23d
 			}
5322385b
 			/* the number of sockets does not matter */
 			cfg_register_child(tcp_children_no + 1 /* tcp main */);
9f4c52ce
 		}
f22b996b
 #ifdef USE_TLS
6c53d41a
 		if (!tls_disable && tls_has_init_si()){
9f4c52ce
 			for(si=tls_listen; si; si=si->next){
f22b996b
 				/* same as for tcp*/
9f4c52ce
 				if (tls_init(si)==-1)  goto error;
f22b996b
 				/* get first ipv4/ipv6 socket*/
9f4c52ce
 				if ((si->address.af==AF_INET)&&
61b60763
 						((sendipv4_tls==0) ||
 							(sendipv4_tls->flags&(SI_IS_LO|SI_IS_MCAST))))
9f4c52ce
 					sendipv4_tls=si;
61b60763
 				if( ((sendipv6_tls==0) ||
 							(sendipv6_tls->flags&(SI_IS_LO|SI_IS_MCAST))) &&
 						(si->address.af==AF_INET6))
9f4c52ce
 					sendipv6_tls=si;
f22b996b
 			}
9f4c52ce
 		}
f22b996b
 #endif /* USE_TLS */
 #endif /* USE_TCP */
b3fef92b
 
c3611173
 			/* all processes should have access to all the sockets (for 
 			 * sending) so we open all first*/
53c7e0f1
 		if (do_suid()==-1) goto error; /* try to drop privileges */
9e7eed4d
 
fbf0d2e0
 		/* delay cfg_shmize to the last moment (it must be called _before_
 		   forking). Changes to default cfgs after this point will be
 		   ignored (cfg_shmize() will copy the default cfgs into shmem).
 		*/
 		if (cfg_shmize() < 0) {
a2a91d7d
 			LM_CRIT("could not initialize shared configuration\n");
fbf0d2e0
 			goto error;
 		}
5d3449a0
 
 		/* Temporary set the local configuration of the main process
 		 * to make the group instances available in PROC_INIT.
 		 */
 		cfg_main_set_local();
 
35e94c97
 		/* init log prefix format */
 		log_prefix_init();
 
021e7e0e
 		/* init childs with rank==PROC_INIT before forking any process,
8390f722
 		 * this is a place for delayed (after mod_init) initializations
 		 * (e.g. shared vars that depend on the total number of processes
 		 * that is known only after all mod_inits have been executed )
 		 * WARNING: the same init_child will be called latter, a second time
021e7e0e
 		 * for the "main" process with rank PROC_MAIN (make sure things are
8390f722
 		 * not initialized twice)*/
 		if (init_child(PROC_INIT) < 0) {
a2a91d7d
 			LM_ERR("error in init_child(PROC_INT) -- exiting\n");
5d3449a0
 			cfg_main_reset_local();
8390f722
 			goto error;
 		}
5d3449a0
 		cfg_main_reset_local();
4208dc00
 		if (counters_prefork_init(get_max_procs()) == -1) goto error;
8390f722
 
 
b3d38eac
 		woneinit = 0;
9f4c52ce
 		/* udp processes */
 		for(si=udp_listen; si; si=si->next){
edf5e385
 			nrprocs = (si->workers>0)?si->workers:children_no;
 			for(i=0;i<nrprocs;i++){
5629f449
 				if(si->address.af==AF_INET6) {
574daa6d
 					if(si->useinfo.name.s)
 						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
 							"sock=[%s]:%s (%s:%s)",
 							i, si->name.s, si->port_no_str.s,
 							si->useinfo.name.s, si->useinfo.port_no_str.s);
 					else
 						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
 							"sock=[%s]:%s",
 							i, si->name.s, si->port_no_str.s);
5629f449
 				} else {
574daa6d
 					if(si->useinfo.name.s)
 						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
 							"sock=%s:%s (%s:%s)",
 							i, si->name.s, si->port_no_str.s,
 							si->useinfo.name.s, si->useinfo.port_no_str.s);
 					else
 						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
 							"sock=%s:%s",
 							i, si->name.s, si->port_no_str.s);
5629f449
 				}
3167c744
 				child_rank++;
f238de3d
 				pid = fork_process(child_rank, si_desc, 1);
37209e14
 				if (pid<0){
a2a91d7d
 					LM_CRIT("Cannot fork\n");
cc2199a9
 					goto error;
36ef0329
 				}else if (pid==0){
37209e14
 					/* child */
9f4c52ce
 					bind_address=si; /* shortcut */
f571aa35
 #ifdef STATS
0df81fe8
 					setstats( i+r*children_no );
f571aa35
 #endif
b3d38eac
 					if(woneinit==0) {
 						if(run_child_one_init_route()<0)
 							goto error;
 					}
cc2199a9
 					return udp_rcv_loop();
 				}
b3d38eac
 				woneinit = 1;
cc2199a9
 			}
bf0fab3f
 			/*parent*/
 			/*close(udp_sock)*/; /*if it's closed=>sendto invalid fd errors?*/
cc2199a9
 		}
c3611173
 #ifdef USE_SCTP
 		/* sctp processes */
 		if (!sctp_disable){
 			for(si=sctp_listen; si; si=si->next){
edf5e385
 				nrprocs = (si->workers>0)?si->workers:sctp_children_no;
 				for(i=0;i<nrprocs;i++){
5629f449
 					if(si->address.af==AF_INET6) {
 						snprintf(si_desc, MAX_PT_DESC, "sctp receiver child=%d "
 								"sock=[%s]:%s",
 								i, si->name.s, si->port_no_str.s);
 					} else {
 						snprintf(si_desc, MAX_PT_DESC, "sctp receiver child=%d "
c3611173
 								"sock=%s:%s",
 								i, si->name.s, si->port_no_str.s);
5629f449
 					}
c3611173
 					child_rank++;
 					pid = fork_process(child_rank, si_desc, 1);
 					if (pid<0){
a2a91d7d
 						LM_CRIT("Cannot fork\n");
c3611173
 						goto error;
 					}else if (pid==0){
 						/* child */
 						bind_address=si; /* shortcut */
 #ifdef STATS
 						setstats( i+r*children_no );
 #endif
7f8e7a85
 						return sctp_core_rcv_loop();
c3611173
 					}
 				}
 			/*parent*/
 			/*close(sctp_sock)*/; /*if closed=>sendto invalid fd errors?*/
 			}
 		}
 #endif /* USE_SCTP */
db249450
 
c3611173
 		/*this is the main process*/
 		bind_address=0;	/* main proc -> it shouldn't send anything, */
b017f49c
 
af93cbdf
 #ifdef USE_SLOW_TIMER
 		/* fork again for the "slow" timer process*/
37209e14
 		pid = fork_process(PROC_TIMER, "slow timer", 1);
 		if (pid<0){
a2a91d7d
 			LM_CRIT("cannot fork \"slow\" timer process\n");
af93cbdf
 			goto error;
 		}else if (pid==0){
 			/* child */
8390f722
 			if (real_time&2)
 				set_rt_prio(rt_timer2_prio, rt_timer2_policy);
af93cbdf
 			if (arm_slow_timer()<0) goto error;
 			slow_timer_main();
 		}else{
 			slow_timer_pid=pid;
 		}
 #endif /* USE_SLOW_TIMER */
b017f49c
 
af93cbdf
 		/* fork again for the "main" timer process*/
37209e14
 		pid = fork_process(PROC_TIMER, "timer", 1);
 		if (pid<0){
a2a91d7d
 			LM_CRIT("cannot fork timer process\n");
6e94f57f
 			goto error;
 		}else if (pid==0){
 			/* child */
8390f722
 			if (real_time&1)
 				set_rt_prio(rt_timer1_prio, rt_timer1_policy);
af93cbdf
 			if (arm_timer()<0) goto error;
 			timer_main();
cd57180a
 		}
a482c5de
 		if(sr_wtimer_start()<0) {
 			LM_CRIT("Cannot start wtimer\n");
 			goto error;
 		}
f2e1aa50
 
c3611173
 	/* init childs with rank==MAIN before starting tcp main (in case they want
 	 * to fork  a tcp capable process, the corresponding tcp. comm. fds in
 	 * pt[] must be set before calling tcp_main_loop()) */
 		if (init_child(PROC_MAIN) < 0) {
a2a91d7d
 			LM_ERR("error in init_child\n");
c3611173
 			goto error;
 		}
f2e1aa50
 
0c5da34b
 #ifdef USE_TCP
5dcfb23d
 		if (!tcp_disable){
f22b996b
 				/* start tcp  & tls receivers */
5dcfb23d
 			if (tcp_init_children()<0) goto error;
f22b996b
 				/* start tcp+tls master proc */
37209e14
 			pid = fork_process(PROC_TCP_MAIN, "tcp main process", 0);
 			if (pid<0){
a2a91d7d
 				LM_CRIT("cannot fork tcp main process: %s\n", strerror(errno));
cb87691a
 				goto error;
5dcfb23d
 			}else if (pid==0){
 				/* child */
 				tcp_main_loop();
 			}else{
f2e1aa50
 				tcp_main_pid=pid;
5dcfb23d
 				unix_tcp_sock=-1;
cb87691a
 			}
0c5da34b
 		}
 #endif
c3611173
 		/* main */
b727c99b
 		strncpy(pt[0].desc, "main process - attendant", MAX_PT_DESC );
0c5da34b
 #ifdef USE_TCP
c3611173
 		close_extra_socks(PROC_ATTENDANT, get_proc_no());
 		if(!tcp_disable){
 			/* main's tcp sockets are disabled by default from init_pt() */
 			unix_tcp_sock=-1;
 		}
0c5da34b
 #endif
7362f824
 		/* init cfg, but without per child callbacks support */
 		cfg_child_no_cb_init();
9d8e1c67
 		cfg_ok=1;
55a45269
 
 #ifdef EXTRA_DEBUG
c3611173
 		for (r=0; r<*process_count; r++){
 			fprintf(stderr, "% 3d   % 5d - %s\n", r, pt[r].pid, pt[r].desc);
 		}
55a45269
 #endif
002879f8
 		LM_DBG("Expect maximum %d  open fds\n", get_max_open_fds());
83e91df1
 		/* in daemonize mode send the exit code back to the parent process */
 		if (!dont_daemonize) {
 			if (daemon_status_send(0) < 0) {
 				ERR("error sending daemon status: %s [%d]\n",
 						strerror(errno), errno);
9167c186
 				goto error;
 			}
 		}
c3611173
 		for(;;){
6e94f57f
 			handle_sigs();
d4fb00dc
 			pause();
7362f824
 			cfg_update();
c3611173
 		}
 	
6e94f57f
 	}
b017f49c
 
51eadd0c
 	/*return 0; */
c3611173
 error:
f2e1aa50
 				 /* if we are here, we are the "main process",
dd0e65a8
 				  any forked children should exit with exit(-1) and not
 				  ever use return */
cc2199a9
 	return -1;
 
 }
726efa25
 
55a45269
 /*
  * Calculate number of processes, this does not
  * include processes created by modules
  */
 static int calc_proc_no(void)
 {
 	int udp_listeners;
 	struct socket_info* si;
edf5e385
 #ifdef USE_TCP
 	int tcp_listeners;
 	int tcp_e_listeners;
 #endif
c3611173
 #ifdef USE_SCTP
 	int sctp_listeners;
 #endif
b017f49c
 
edf5e385
 	for (si=udp_listen, udp_listeners=0; si; si=si->next)
 		udp_listeners += (si->workers>0)?si->workers:children_no;
 #ifdef USE_TCP
 	for (si=tcp_listen, tcp_listeners=0, tcp_e_listeners=0; si; si=si->next) {
 		if(si->workers>0)
 			tcp_listeners += si->workers;
 		else
 			 tcp_e_listeners = tcp_cfg_children_no;
 	}
 	tcp_listeners += tcp_e_listeners;
eea7f9d0
 #ifdef USE_TLS
 	tcp_e_listeners = 0;
9b9d1587
 	for (si=tls_listen, tcp_e_listeners=0; si; si=si->next) {
eea7f9d0
 		if(si->workers>0)
 			tcp_listeners += si->workers;
 		else {
 			if(tcp_listeners==0)
 				tcp_e_listeners = tcp_cfg_children_no;
 		}
 	}
 	tcp_listeners += tcp_e_listeners;
 #endif
edf5e385
 	tcp_children_no = tcp_listeners;
 #endif
c3611173
 #ifdef USE_SCTP
edf5e385
 	for (si=sctp_listen, sctp_listeners=0; si; si=si->next)
 		sctp_listeners += (si->workers>0)?si->workers:sctp_children_no;
c3611173
 #endif
55a45269
 	return
 		     /* receivers and attendant */
edf5e385
 		(dont_fork ? 1 : udp_listeners + 1)
55a45269
 		     /* timer process */
 		+ 1 /* always, we need it in most cases, and we can't tell here
 		       & now if we don't need it */
 #ifdef USE_SLOW_TIMER
 		+ 1 /* slow timer process */
 #endif
a482c5de
 		+ 1 /* wtimer process */
55a45269
 #ifdef USE_TCP
edf5e385
 		+((!tcp_disable)?( 1/* tcp main */ + tcp_listeners ):0)
55a45269
 #endif
c3611173
 #ifdef USE_SCTP
edf5e385
 		+((!sctp_disable)?sctp_listeners:0)
c3611173
 #endif
55a45269
 		;
 }
57e2cd15
 
512dcd98
 int main(int argc, char** argv)
 {
 
 	FILE* cfg_stream;
9f4c52ce
 	int c,r;
1b1b19d8
 	char *tmp;
943a9d00
 	int tmp_len;
 	int port;
 	int proto;
f571aa35
 	char *options;
3db079b5
 	int ret;
7d31b911
 	unsigned int seed;
 	int rfd;
dcb59e67
 	int debug_save, debug_flag;
 	int dont_fork_cnt;
72bba9e3
 	struct name_lst* n_lst;
95dec431
 	char *p;
b151e9d6
 	struct stat st = {0};
9167c186
 
3db079b5
 	/*init*/
78a65d14
 	time(&up_since);
02f62296
 	creator_pid = getpid();
3db079b5
 	ret=-1;
049f64c2
 	my_argc=argc; my_argv=argv;
dcb59e67
 	debug_flag=0;
 	dont_fork_cnt=0;
b017f49c
 
83e91df1
 	daemon_status_init();
6bda9c0b
 
 	dprint_init_colors();
 
7b3a6eca
 	/* command line options */
4c2ef7f3
 	options=  ":f:cm:M:dVIhEeb:l:L:n:vKrRDTN:W:w:t:u:g:P:G:SQ:O:a:A:x:X:"
7b3a6eca
 #ifdef STATS
 		"s:"
 #endif
 	;
 	/* Handle special command line arguments, that must be treated before
 	 * intializing the various subsystem or before parsing other arguments:
 	 *  - get the startup debug and log_stderr values
 	 *  - look if pkg mem size is overriden on the command line (-M) and get
 	 *    the new value here (before intializing pkg_mem).
 	 *  - look if there is a -h, e.g. -f -h construction won't be caught
 	 *    later
 	 */
 	opterr = 0;
 	while((c=getopt(argc,argv,options))!=-1) {
 		switch(c) {
 			case 'd':
 					debug_flag = 1;
 					default_core_cfg.debug++;
 					break;
 			case 'E':
 					log_stderr=1;
 					break;
6bda9c0b
 			case 'e':
 					log_color=1;
 					break;
7b3a6eca
 			case 'M':
 					pkg_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024;
 					if (tmp &&(*tmp)){
 						fprintf(stderr, "bad private mem size number: -M %s\n",
 											optarg);
 						goto error;
 					};
 					break;
4c2ef7f3
 			case 'x':
 					sr_memmng_shm = optarg;
 					break;
 			case 'X':
 					sr_memmng_pkg = optarg;
 					break;
7b3a6eca
 			default:
 					if (c == 'h' || (optarg && strcmp(optarg, "-h") == 0)) {
 						printf("version: %s\n", full_version);
 						printf("%s",help_msg);
 						exit(0);
 					}
 					break;
 		}
 	}
4c2ef7f3
 
 	if(sr_memmng_pkg==NULL) {
 		if(sr_memmng_shm!=NULL) {
 			sr_memmng_pkg = sr_memmng_shm;
 		} else {
 			sr_memmng_pkg = SR_MEMMNG_DEFAULT;
 		}
 	}
 	if(sr_memmng_shm==NULL) {
 		sr_memmng_shm = SR_MEMMNG_DEFAULT;
 	}
 	shm_set_mname(sr_memmng_shm);
 	if (pkg_mem_size == 0) {
 		pkg_mem_size = PKG_MEM_POOL_SIZE;
 	}
 
7b3a6eca
 	/*init pkg mallocs (before parsing cfg or the rest of the cmd line !)*/
 	if (pkg_mem_size)
a2a91d7d
 		LM_INFO("private (per process) memory: %ld bytes\n", pkg_mem_size );
4c2ef7f3
 	if (pkg_init_manager(sr_memmng_pkg)<0)
d31fcdf0
 		goto error;
 
be125734
 #ifdef DBG_MSG_QA
 	fprintf(stderr, "WARNING: ser startup: "
 		"DBG_MSG_QA enabled, ser may exit abruptly\n");
 #endif
6e94f57f
 
4208dc00
 	/* init counters / stats */
 	if (init_counters() == -1)
 		goto error;
dc93916e
 #ifdef USE_TCP
 	init_tcp_options(); /* set the defaults before the config */
 #endif
a482c5de
 
f4194f69
 	/* process command line (cfg. file path etc) */
b017f49c
 	optind = 1;  /* reset getopt */
 	/* switches required before script processing */
 	while((c=getopt(argc,argv,options))!=-1) {
 		switch(c) {
4c2ef7f3
 			case 'M':
 			case 'x':
 			case 'X':
 					/* ignore, they were parsed immediately after startup */
 					break;
1b1b19d8
 			case 'f':
 					cfg_file=optarg;
 					break;
dda578ba
 			case 'c':
 					config_check=1;
 					log_stderr=1; /* force stderr logging */
 					break;
f4194f69
 			case 'L':
 					mods_dir = optarg;
e1e40d3a
 					mods_dir_cmd = 1;
f4194f69
 					break;
40a8d9dd
 			case 'm':
 					shm_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024;
 					if (tmp &&(*tmp)){
36ef0329
 						fprintf(stderr, "bad shmem size number: -m %s\n",
 										optarg);
40a8d9dd
 						goto error;
 					};
a2a91d7d
 					LM_INFO("shared memory: %ld bytes\n", shm_mem_size );
40a8d9dd
 					break;
b017f49c
 			case 'd':
7b3a6eca
 					/* ignore it, was parsed immediately after startup */
b017f49c
 					break;
70d6cae2
 			case 'v':
b017f49c
 			case 'V':
1ef55a09
 					printf("version: %s\n", full_version);
 					printf("flags: %s\n", ver_flags );
b017f49c
 					print_ct_constants();
1ef55a09
 					printf("id: %s\n", ver_id);
e03d1279
 					if(strlen(ver_compiled_time)>0)
 						printf("compiled on %s with %s\n",
1ef55a09
 							ver_compiled_time, ver_compiler );
e03d1279
 					else
 						printf("compiled with %s\n",
 							ver_compiler );
40a8d9dd
 
b017f49c
 					exit(0);
 					break;
f5803916
 			case 'I':
 					print_internals();
 					exit(0);
 					break;
b017f49c
 			case 'E':
7b3a6eca
 					/* ignore it, was parsed immediately after startup */
b017f49c
 					break;
6bda9c0b
 			case 'e':
 					/* ignore it, was parsed immediately after startup */
 					break;
5219ecb7
 			case 'O':
 					scr_opt_lev=strtol(optarg, &tmp, 10);
 					if (tmp &&(*tmp)){
 						fprintf(stderr, "bad optimization level: -O %s\n",
 										optarg);
 						goto error;
 					};
 					break;
2c4ae148
 			case 'u':
 					/* user needed for possible shm. pre-init */
 					user=optarg;
 					break;
95dec431
 			case 'A':
 					p = strchr(optarg, '=');
 					if(p) {
 						*p = '\0';
 					}
13de789c
 					pp_define_set_type(0);
95dec431
 					if(pp_define(strlen(optarg), optarg)<0) {
 						fprintf(stderr, "error at define param: -A %s\n",
 								optarg);
 						goto error;
 					}
 					if(p) {
 						*p = '=';
 						p++;
 						if(pp_define_set(strlen(p), p)<0) {
 							fprintf(stderr, "error at define value: -A %s\n",
 								optarg);
 							goto error;
 						}
 					}
 					break;
b017f49c
 			case 'b':
 			case 'l':
 			case 'n':
70d6cae2
 			case 'K':
b017f49c
 			case 'r':
 			case 'R':
 			case 'D':
 			case 'T':
 			case 'N':
 			case 'W':
 			case 'w':
 			case 't':
 			case 'g':
 			case 'P':
f4194f69
 			case 'G':
720f74cd
 			case 'S':
5219ecb7
 			case 'Q':
b01dc20a
 			case 'a':
b017f49c
 			case 's':
 					break;
 			case '?':
f4194f69
 					if (isprint(optopt)) {
16d4e079
 						fprintf(stderr, "Unknown option `-%c'."
 										" Use -h for help.\n", optopt);
f4194f69
 					} else {
16d4e079
 						fprintf(stderr, "Unknown option character `\\x%x'."
 										" Use -h for help.\n",
f4194f69
 							optopt);
 					}
b017f49c
 					goto error;
 			case ':':
16d4e079
 					fprintf(stderr, "Option `-%c' requires an argument."
 									" Use -h for help.\n",
f4194f69
 						optopt);
b017f49c
 					goto error;
 			default:
 					abort();
 		}
 	}
4c2ef7f3
 	if (shm_mem_size == 0) {
 		shm_mem_size = SHM_MEM_POOL_SIZE;
 	}
021e7e0e
 
22db42e4
 	if (endianness_sanity_check() != 0){
 		fprintf(stderr, "BUG: endianness sanity tests failed\n");
 		goto error;
 	}
93349b4e
 	if (init_routes()<0) goto error;
ac34f9f4
 	if (init_nonsip_hooks()<0) goto error;
0a99f1b3
 	if (init_script_cb()<0) goto error;
7e7d9399
 	if (pv_init_api()<0) goto error;
8c3a7158
 	if (pv_register_core_vars()!=0) goto error;
5099fd64
 	if (init_rpcs()<0) goto error;
 	if (register_core_rpcs()!=0) goto error;
b2471cfc
 
 	/* Fix the value of cfg_file variable.*/
 	if (fix_cfg_file() < 0) goto error;
b017f49c
 
 	/* load config file or die */
6f96f4fb
 	if (cfg_file[0] == '-' && strlen(cfg_file)==1) {
 		cfg_stream=stdin;
 	} else {
 		cfg_stream=fopen (cfg_file, "r");
 	}
b017f49c
 	if (cfg_stream==0){
 		fprintf(stderr, "ERROR: loading config file(%s): %s\n", cfg_file,
 				strerror(errno));
 		goto error;
 	}
 
 	/* seed the prng */
 	/* try to use /dev/urandom if possible */
 	seed=0;
 	if ((rfd=open("/dev/urandom", O_RDONLY))!=-1){
 try_again:
 		if (read(rfd, (void*)&seed, sizeof(seed))==-1){
 			if (errno==EINTR) goto try_again; /* interrupted by signal */
a2a91d7d
 			LM_WARN("could not read from /dev/urandom (%d)\n", errno);
b017f49c
 		}
002879f8
 		LM_DBG("read %u from /dev/urandom\n", seed);
b017f49c
 			close(rfd);
 	}else{
a2a91d7d
 		LM_WARN("could not open /dev/urandom (%d)\n", errno);
b017f49c
 	}
 	seed+=getpid()+time(0);
002879f8
 	LM_DBG("seeding PRNG with %u\n", seed);
b017f49c
 	srand(seed);
2c07f591
 	fastrand_seed(rand());
27937719
 	srandom(rand()+time(0));
002879f8
 	LM_DBG("test random numbers %u %lu %u\n", rand(), random(), fastrand());
b017f49c
 
 	/*register builtin  modules*/
 	register_builtin_modules();
 
65938e0e
 	/* init named flags */
 	init_named_flags();
 
b017f49c
 	yyin=cfg_stream;
7ac069af
 	debug_save = default_core_cfg.debug;
b017f49c
 	if ((yyparse()!=0)||(cfg_errors)){
 		fprintf(stderr, "ERROR: bad config file (%d errors)\n", cfg_errors);
713a0a1f
 		if (debug_flag) default_core_cfg.debug = debug_save;
 		pp_ifdef_level_check();
9167c186
 
b017f49c
 		goto error;
 	}
dcb59e67
 	if (cfg_warnings){
 		fprintf(stderr, "%d config warnings\n", cfg_warnings);
 	}
7ac069af
 	if (debug_flag) default_core_cfg.debug = debug_save;
713a0a1f
 	pp_ifdef_level_check();
93349b4e
 	print_rls();
b017f49c
 
e008edb9
 	if(init_dst_set()<0) {
 		LM_ERR("failed to initialize destination set structure\n");
 		goto error;
 	}
b017f49c
 	/* options with higher priority than cfg file */
 	optind = 1;  /* reset getopt */
 	while((c=getopt(argc,argv,options))!=-1) {
 		switch(c) {
 			case 'f':
 			case 'c':
 			case 'm':
7b3a6eca
 			case 'M':
b017f49c
 			case 'd':
70d6cae2
 			case 'v':
b017f49c
 			case 'V':
f5803916
 			case 'I':
b017f49c
 			case 'h':
5219ecb7
 			case 'O':
95dec431
 			case 'A':
b017f49c
 					break;
 			case 'E':
7b3a6eca
 					log_stderr=1;	/* use in both getopt switches,
 									   takes priority over config */
b017f49c
 					break;
6bda9c0b
 			case 'e':
 					log_color=1;	/* use in both getopt switches,
 									   takes priority over config */
 					break;
c3ce2841
 			case 'b':
 					maxbuffer=strtol(optarg, &tmp, 10);
 					if (tmp &&(*tmp)){
f4194f69
 						fprintf(stderr, "bad max buffer size number: -b %s\n",
36ef0329
 											optarg);
 						goto error;
 					}
 					break;
1b1b19d8
 			case 'l':
df088fb8
 					if ((n_lst=parse_phostport_mh(optarg, &tmp, &tmp_len,
72bba9e3
 											&port, &proto))==0){
943a9d00
 						fprintf(stderr, "bad -l address specifier: %s\n",
 										optarg);
 						goto error;
 					}
e7671eb9
 					/* add a new addr. to our address list */
72bba9e3
 					if (add_listen_iface(n_lst->name, n_lst->next,  port,
 											proto, n_lst->flags)!=0){
9f4c52ce
 						fprintf(stderr, "failed to add new listen address\n");
72bba9e3
 						free_name_lst(n_lst);
1b1b19d8
 						goto error;
 					}
72bba9e3
 					free_name_lst(n_lst);
1b1b19d8
 					break;
 			case 'n':
3e429f5c
 					children_no=strtol(optarg, &tmp, 10);
 					if ((tmp==0) ||(*tmp)){
36ef0329
 						fprintf(stderr, "bad process number: -n %s\n",
 									optarg);
1b1b19d8
 						goto error;
 					}
 					break;
70d6cae2
 			case 'K':
1b1b19d8
 					check_via=1;
 					break;
 			case 'r':
 					received_dns|=DO_DNS;
 					break;
 			case 'R':
 					received_dns|=DO_REV_DNS;
 					break;
 			case 'D':
bc404f2b
 					dont_fork_cnt++;
1b1b19d8
 					break;
5dcfb23d
 			case 'T':
b017f49c
 				#ifdef USE_TCP
5dcfb23d
 					tcp_disable=1;
b017f49c
 				#else
5dcfb23d
 					fprintf(stderr,"WARNING: tcp support not compiled in\n");
b017f49c
 				#endif
5dcfb23d
 					break;
 			case 'N':
b017f49c
 				#ifdef USE_TCP
edf5e385
 					tcp_cfg_children_no=strtol(optarg, &tmp, 10);
5dcfb23d
 					if ((tmp==0) ||(*tmp)){
 						fprintf(stderr, "bad process number: -N %s\n",
 									optarg);
 						goto error;
 					}
b017f49c
 				#else
5dcfb23d
 					fprintf(stderr,"WARNING: tcp support not compiled in\n");
b017f49c
 				#endif
5dcfb23d
 					break;
0ba367ec
 			case 'W':
b017f49c
 				#ifdef USE_TCP
0ba367ec
 					tcp_poll_method=get_poll_type(optarg);
 					if (tcp_poll_method==POLL_NONE){
 						fprintf(stderr, "bad poll method name: -W %s\ntry "
 										"one of %s.\n", optarg, poll_support);
 						goto error;
 					}
b017f49c
 				#else
0ba367ec
 					fprintf(stderr,"WARNING: tcp support not compiled in\n");
b017f49c
 				#endif
1b1b19d8
 					break;
c3611173
 			case 'S':
 				#ifdef USE_SCTP
 					sctp_disable=1;
 				#else
 					fprintf(stderr,"WARNING: sctp support not compiled in\n");
 				#endif
 					break;
5219ecb7
 			case 'Q':
c3611173
 				#ifdef USE_SCTP
 					sctp_children_no=strtol(optarg, &tmp, 10);
 					if ((tmp==0) ||(*tmp)){
 						fprintf(stderr, "bad process number: -O %s\n",
 									optarg);
 						goto error;
 					}
 				#else
 					fprintf(stderr,"WARNING: sctp support not compiled in\n");
 				#endif
 					break;
c9ca45b3
 			case 'w':
 					working_dir=optarg;
 					break;
 			case 't':
 					chroot_dir=optarg;
 					break;
 			case 'u':
054cb6cf
 					user=optarg;
c9ca45b3
 					break;
 			case 'g':
054cb6cf
 					group=optarg;
c9ca45b3
 					break;
b2934963
 			case 'P':
 					pid_file=optarg;
 					break;
f4194f69
 			case 'G':
 					pgid_file=optarg;
 					break;
b01dc20a
 			case 'a':
 					if(strcmp(optarg, "on")==0 || strcmp(optarg, "yes")==0)
 						sr_auto_aliases = 1;
 					else if(strcmp(optarg, "off")==0 || strcmp(optarg, "no")==0)
 						sr_auto_aliases = 0;
 					else {
 						fprintf(stderr,
 							"bad auto aliases parameter: %s (valid on, off, yes, no)\n",
 							optarg);
 						goto error;
 					}
 					break;
b017f49c
 			case 's':
 				#ifdef STATS
 					stat_file=optarg;
 				#endif
 					break;
1b1b19d8
 			default:
b017f49c
 					break;
7d31b911
 		}
 	}
404073d3
 
8d666c30
 	/* reinit if pv buffer size has been set in config */
 	if (pv_reinit_buffer()<0)
 		goto error;
 
2d826efb
 	/* init lookup for core event routes */
 	sr_core_ert_init();
 
bc404f2b
 	if (dont_fork_cnt)
 		dont_fork = dont_fork_cnt;	/* override by command line */
 
 	if (dont_fork > 0) {
 		dont_daemonize = dont_fork == 2;
 		dont_fork = dont_fork == 1;
 	}
8b8fc486
 	/* init locks first */
 	if (init_lock_ops()!=0)
 		goto error;
c3611173
 #ifdef USE_TCP
 #ifdef USE_TLS
 	if (tcp_disable)
 		tls_disable=1; /* if no tcp => no tls */
 #endif /* USE_TLS */
 #endif /* USE_TCP */
23ca6c06
 #ifdef USE_SCTP
 	if (sctp_disable!=1){
 		/* fix it */
7f8e7a85
 		if (sctp_core_check_support()==-1){
23ca6c06
 			/* check if sctp support is auto, if not warn about disabling it */
 			if (sctp_disable!=2){
 				fprintf(stderr, "ERROR: " "sctp enabled, but not supported by"
 								" the OS\n");
 				goto error;
 			}
 			sctp_disable=1;
 		}else{
 			/* sctp_disable!=1 and sctp supported => enable sctp */
 			sctp_disable=0;
 		}
 	}
 #endif /* USE_SCTP */
c3611173
 	/* initialize the configured proto list */
 	init_proto_order();
878fc194
 	/* init the resolver, before fixing the config */
 	resolv_init();
7268726e
 	/* fix parameters */
cc2199a9
 	if (port_no<=0) port_no=SIP_PORT;
f22b996b
 #ifdef USE_TLS
 	if (tls_port_no<=0) tls_port_no=SIPS_PORT;
 #endif
b017f49c
 
 
cc2199a9
 	if (children_no<=0) children_no=CHILD_NO;
5b532c7f
 #ifdef USE_TCP
5dcfb23d
 	if (!tcp_disable){
edf5e385
 		if (tcp_cfg_children_no<=0) tcp_cfg_children_no=children_no;
 		tcp_children_no = tcp_cfg_children_no;
4bd1673d
 	}
caf80ae6
 #endif
c3611173
 #ifdef USE_SCTP
 	if (!sctp_disable){
 		if (sctp_children_no<=0) sctp_children_no=children_no;
 	}
 #endif
b017f49c
 
c9ca45b3
 	if (working_dir==0) working_dir="/";
b017f49c
 
054cb6cf
 	/* get uid/gid */
 	if (user){
71fd3ebd
 		if (user2uid(&uid, &gid, user)<0){
 			fprintf(stderr, "bad user name/uid number: -u %s\n", user);
 			goto error;
054cb6cf
 		}
d7a10e6a
 		sock_uid = uid;
 		sock_gid = gid;
054cb6cf
 	}
 	if (group){
71fd3ebd
 		if (group2gid(&gid, group)<0){
054cb6cf
 				fprintf(stderr, "bad group name/gid number: -u %s\n", group);
71fd3ebd
 			goto error;
 		}
d7a10e6a
 		sock_gid = gid;
71fd3ebd
 	}
b151e9d6
 	/* create runtime dir if doesn't exist */
 	if (stat(runtime_dir, &st) == -1) {
 		if(mkdir(runtime_dir, 0700) == -1) {
5e9f144c
 			LM_ERR("failed to create runtime dir %s\n", runtime_dir);
 			fprintf(stderr,  "failed to create runtime dir %s\n", runtime_dir);
b151e9d6
 			goto error;
 		}
 		if(sock_uid!=-1 || sock_gid!=-1) {
 			if(chown(runtime_dir, sock_uid, sock_gid) == -1) {
5e9f144c
 				LM_ERR("failed to change owner of runtime dir %s\n", runtime_dir);
 				fprintf(stderr,  "failed to change owner of runtime dir %s\n", runtime_dir);
b151e9d6
 				goto error;
 			}
 		}
 	}
2cfcc6bb
 	if (fix_all_socket_lists()!=0){
53c7e0f1
 		fprintf(stderr,  "failed to initialize list addresses\n");
9f4c52ce
 		goto error;
e60a9728
 	}
2cfcc6bb
 	if (default_core_cfg.dns_try_ipv6 && !(socket_types & SOCKET_T_IPV6)){
dcb59e67
 		/* if we are not listening on any ipv6 address => no point
 		 * to try to resovle ipv6 addresses */
2cfcc6bb
 		default_core_cfg.dns_try_ipv6=0;
dcb59e67
 	}
57e2cd15
 	/* print all the listen addresses */
 	printf("Listening on \n");
9f4c52ce
 	print_all_socket_lists();
 	printf("Aliases: \n");
 	/*print_aliases();*/
 	print_aliases();
e278821b
 	printf("\n");
b017f49c
 
0df81fe8
 	if (dont_fork){
b017f49c
 		fprintf(stderr, "WARNING: no fork mode %s\n",
49de5d20
 				(udp_listen)?(
b017f49c
 				(udp_listen->next)?"and more than one listen address found "
64146b14
 				"(will use only the first one)":""
49de5d20
 				):"and no udp listen address found" );
0df81fe8
 	}
dda578ba
 	if (config_check){
 		fprintf(stderr, "config file ok, exiting...\n");
51e93de7
 		return 0;
dda578ba
 	}
dd0e65a8
 
 
 	/*init shm mallocs
b017f49c
 	 *  this must be here
dd0e65a8
 	 *     -to allow setting shm mem size from the command line
 	 *       => if shm_mem should be settable from the cfg file move
 	 *       everything after
 	 *     -it must be also before init_timer and init_tcp
 	 *     -it must be after we know uid (so that in the SYSV sems case,
 	 *        the sems will have the correct euid)
2c4ae148
 	 *  Note: shm can now be initialized when parsing the config script, that's
 	 *  why checking for a prior initialization is needed.
dd0e65a8
 	 * --andrei */
2c4ae148
 #ifdef SHM_MEM
 	if (!shm_initialized() && init_shm()<0)
dd0e65a8
 		goto error;
2c4ae148
 #endif /* SHM_MEM */
4c2ef7f3
 	pkg_print_manager();
 	shm_print_manager();
d307929c
 	if (init_atomic_ops()==-1)
 		goto error;
22db42e4
 	if (init_basex() != 0){
a2a91d7d
 		LM_CRIT("could not initialize base* framework\n");
22db42e4
 		goto error;
 	}
50ca02e5
 	if (sr_cfg_init() < 0) {
a2a91d7d
 		LM_CRIT("could not initialize configuration framework\n");
22db42e4
 		goto error;
 	}
 	/* declare the core cfg before the module configs */
 	if (cfg_declare("core", core_cfg_def, &default_core_cfg, cfg_sizeof(core),
 			&core_cfg)
 	) {
a2a91d7d
 		LM_CRIT("could not declare the core configuration\n");
22db42e4
 		goto error;
 	}
 #ifdef USE_TCP
 	if (tcp_register_cfg()){
a2a91d7d
 		LM_CRIT("could not register the tcp configuration\n");
22db42e4
 		goto error;
 	}
 #endif /* USE_TCP */
dd0e65a8
 	/*init timer, before parsing the cfg!*/
 	if (init_timer()<0){
a2a91d7d
 		LM_CRIT("could not initialize timer, exiting...\n");
dd0e65a8
 		goto error;
 	}
a482c5de
 	/* init wtimer */
 	if(sr_wtimer_init()<0) {
 		LM_CRIT("could not initialize wtimer, exiting...\n");
 		goto error;
 	}
 
dcb59e67
 #ifdef USE_DNS_CACHE
7905e2d6
 	if (init_dns_cache()<0){
a2a91d7d
 		LM_CRIT("could not initialize the dns cache, exiting...\n");
dcb59e67
 		goto error;
 	}
021e7e0e
 #ifdef USE_DNS_CACHE_STATS
 	/* preinitializing before the nubmer of processes is determined */
 	if (init_dns_cache_stats(1)<0){
a2a91d7d
 		LM_CRIT("could not initialize the dns cache measurement\n");
021e7e0e
 		goto error;
 	}
 #endif /* USE_DNS_CACHE_STATS */
dcb59e67
 #endif
 #ifdef USE_DST_BLACKLIST
 	if (init_dst_blacklist()<0){
a2a91d7d
 		LM_CRIT("could not initialize the dst blacklist, exiting...\n");
dcb59e67
 		goto error;
 	}
021e7e0e
 #ifdef USE_DST_BLACKLIST_STATS
4208dc00
 	/* preinitializing before the number of processes is determined */
021e7e0e
 	if (init_dst_blacklist_stats(1)<0){
a2a91d7d
 		LM_CRIT("could not initialize the dst blacklist measurement\n");
021e7e0e
 		goto error;
 	}
 #endif /* USE_DST_BLACKLIST_STATS */
dcb59e67
 #endif
74ce7043
 	if (init_avps()<0) goto error;
539283cd
 	if (rpc_init_time() < 0) goto error;
74ce7043
 
5dcfb23d
 #ifdef USE_TCP
 	if (!tcp_disable){
 		/*init tcp*/
 		if (init_tcp()<0){
a2a91d7d
 			LM_CRIT("could not initialize tcp, exiting...\n");
5dcfb23d
 			goto error;
 		}
 	}
f22b996b
 #endif /* USE_TCP */
31fd952b
 #ifdef USE_SCTP
 	if (!sctp_disable){
7f8e7a85
 		if (sctp_core_init()<0){
a2a91d7d
 			LM_CRIT("Could not initialize sctp, exiting...\n");
31fd952b
 			goto error;
 		}
 	}
 #endif /* USE_SCTP */
ed2b50d3
 	/* init_daemon? */
83e91df1
 	if( !dont_fork && daemonize((log_name==0)?argv[0]:log_name, 1) < 0)
 		goto error;
428e3b83
 	if (install_sigs() != 0){
 		fprintf(stderr, "ERROR: could not install the signal handlers\n");
 		goto error;
 	}
385c63eb
 
 	if (disable_core_dump) set_core_dump(0, 0);
7b3a6eca
 	else set_core_dump(1, shm_mem_size+pkg_mem_size+4*1024*1024);
385c63eb
 	if (open_files_limit>0){
b017f49c
 		if(increase_open_fds(open_files_limit)<0){
385c63eb
 			fprintf(stderr, "ERROR: error could not increase file limits\n");
 			goto error;
 		}
 	}
8390f722
 	if (mlock_pages)
 		mem_lock_pages();
021e7e0e
 
8390f722
 	if (real_time&4)
 			set_rt_prio(rt_prio, rt_policy);
021e7e0e
 
4700831f
 #ifdef USE_TCP
 #ifdef USE_TLS
 	if (!tls_disable){
 		if (!tls_loaded()){
 			LM_WARN("tls support enabled, but no tls engine "
 						" available (forgot to load the tls module?)\n");
 			LM_WARN("disabling tls...\n");
 			tls_disable=1;
 		} else {
 			if (pre_init_tls()<0){
 				LM_CRIT("could not pre-initialize tls, exiting...\n");
 				goto error;
 			}
 		}
 	}
 #endif /* USE_TLS */
 #endif /* USE_TCP */
9188021a
 	
385c63eb
 	if (init_modules() != 0) {
 		fprintf(stderr, "ERROR: error while initializing modules\n");
 		goto error;
 	}
9188021a
 	
021e7e0e
 	/* initialize process_table, add core process no. (calc_proc_no()) to the
37209e14
 	 * processes registered from the modules*/
 	if (init_pt(calc_proc_no())==-1)
55a45269
 		goto error;
8628de22
 #ifdef USE_TCP
 #ifdef USE_TLS
 	if (!tls_disable){
6c53d41a
 		if (!tls_loaded()){
a2a91d7d
 			LM_WARN("tls support enabled, but no tls engine "
6c53d41a
 						" available (forgot to load the tls module?)\n");
a2a91d7d
 			LM_WARN("disabling tls...\n");
6c53d41a
 			tls_disable=1;
 		}
8628de22
 		/* init tls*/
 		if (init_tls()<0){
a2a91d7d
 			LM_CRIT("could not initialize tls, exiting...\n");
8628de22
 			goto error;
 		}
 	}
 #endif /* USE_TLS */
 #endif /* USE_TCP */
021e7e0e
 
37209e14
 	/* The total number of processes is now known, note that no
 	 * function being called before this point may rely on the
 	 * number of processes !
 	 */
002879f8
 	LM_DBG("Expect (at least) %d kamailio processes in your process list\n",
37209e14
 			get_max_procs());
55a45269
 
021e7e0e
 #if defined USE_DNS_CACHE && defined USE_DNS_CACHE_STATS
 	if (init_dns_cache_stats(get_max_procs())<0){
a2a91d7d
 		LM_CRIT("could not initialize the dns cache measurement\n");
021e7e0e
 		goto error;
 	}
 #endif
 #if defined USE_DST_BLACKLIST && defined USE_DST_BLACKLIST_STATS
 	if (init_dst_blacklist_stats(get_max_procs())<0){
a2a91d7d
 		LM_CRIT("could not initialize the dst blacklist measurement\n");
021e7e0e
 		goto error;
 	}
 #endif
 
6bb03a39
 	/* fix routing lists */
 	if ( (r=fix_rls())!=0){
6cd48835
 		fprintf(stderr, "ERROR: error %d while trying to fix configuration\n",
6bb03a39
 						r);
 		goto error;
 	};
b0123c36
 	fixup_complete=1;
22d4aa5d
 
2f781952
 #ifdef STATS
 	if (init_stats(  dont_fork ? 1 : children_no  )==-1) goto error;
 #endif
b017f49c
 
3db079b5
 	ret=main_loop();
83e91df1
 	if (ret < 0)
 		goto error;
3db079b5
 	/*kill everything*/
d4fb00dc
 	if (is_main) shutdown_children(SIGTERM, 0);
83e91df1
 	if (!dont_daemonize) {
 		if (daemon_status_send(0) < 0)
 			ERR("error sending exit status: %s [%d]\n",
 					strerror(errno), errno);
 	}
d4fb00dc
 	/* else terminate process */
3db079b5
 	return ret;
512dcd98
 
 error:
3db079b5
 	/*kill everything*/
d4fb00dc
 	if (is_main) shutdown_children(SIGTERM, 0);
83e91df1
 	if (!dont_daemonize) {
 		if (daemon_status_send((char)-1) < 0)
 			ERR("error sending exit status: %s [%d]\n",
 					strerror(errno), errno);
 	}
512dcd98
 	return -1;
 }