Exemple #1
0
/**
 * Main loop, forks the children, bind to addresses,
 * handle signals.
 * \return don't return on sucess, -1 on error
 */
static int main_loop(void)
{
	static int chd_rank;
	int  i;
	pid_t pid;
	struct socket_info* si;
	int* startup_done = NULL;
	atomic_t *load_p;

	chd_rank=0;

	if (dont_fork){
		if (udp_listen==0){
			LM_ERR("no fork mode requires at least one"
					" udp listen address, exiting...\n");
			goto error;
		}
		/* only one address, we ignore all the others */
		if (udp_init(udp_listen)==-1) goto error;
		bind_address=udp_listen;
		sendipv4=bind_address;
		sendipv6=bind_address; /*FIXME*/
		if (udp_listen->next){
			LM_WARN("using only the first listen address (no fork)\n");
		}

		/* try to drop privileges */
		if (do_suid(uid, gid)==-1)
			goto error;

		if (start_module_procs()!=0) {
			LM_ERR("failed to fork module processes\n");
			goto error;
		}

		/* we need another process to act as the timer*/
		if (start_timer_processes()!=0) {
			LM_CRIT("cannot start timer process(es)\n");
			goto error;
		}

		/* main process, receive loop */
		set_proc_attrs("stand-alone SIP receiver %.*s", 
			 bind_address->sock_str.len, bind_address->sock_str.s );

		/* 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 */
		if (init_child(1) < 0) {
			LM_ERR("init_child failed in don't fork\n");
			goto error;
		}

		if (startup_rlist.a)
			run_startup_route();

		is_main=1;
		load_p = shm_malloc(sizeof(atomic_t));
		if (!load_p) {
		/* highly improbable */
			LM_ERR("no more shm\n");
			goto error;
		}
		memset(load_p,0,sizeof(atomic_t));
		pt[process_no].load = load_p;

		register_udp_load_stat(&udp_listen->sock_str,load_p);
		return udp_rcv_loop();
	} else {  /* don't fork */

		for(si=udp_listen;si;si=si->next){
			/* create the listening socket (for each address)*/
			/* udp */
			if (udp_init(si)==-1) goto error;
			/* get first ipv4/ipv6 socket*/
			if ((si->address.af==AF_INET)&&
					((sendipv4==0)||(sendipv4->flags&SI_IS_LO)))
				sendipv4=si;
			#ifdef USE_IPV6
			if((sendipv6==0)&&(si->address.af==AF_INET6))
				sendipv6=si;
			#endif
		}
		#ifdef USE_TCP
		if (!tcp_disable){
			for(si=tcp_listen; si; si=si->next){
				/* same thing for tcp */
				if (tcp_init(si)==-1)  goto error;
				/* get first ipv4/ipv6 socket*/
				if ((si->address.af==AF_INET)&&
						((sendipv4_tcp==0)||(sendipv4_tcp->flags&SI_IS_LO)))
					sendipv4_tcp=si;
				#ifdef USE_IPV6
				if((sendipv6_tcp==0)&&(si->address.af==AF_INET6))
					sendipv6_tcp=si;
				#endif
			}
		}
		#ifdef USE_TLS
		if (!tls_disable){
			for(si=tls_listen; si; si=si->next){
				/* same as for tcp*/
				if (tls_init(si)==-1)  goto error;
				/* get first ipv4/ipv6 socket*/
				if ((si->address.af==AF_INET)&&
						((sendipv4_tls==0)||(sendipv4_tls->flags&SI_IS_LO)))
					sendipv4_tls=si;
				#ifdef USE_IPV6
				if((sendipv6_tls==0)&&(si->address.af==AF_INET6))
					sendipv6_tls=si;
				#endif
			}
		}
		#endif /* USE_TLS */
		#endif /* USE_TCP */
		#ifdef USE_SCTP
		if (!sctp_disable){
			for(si=sctp_listen; si; si=si->next){
				/* same thing for sctp */
				if (sctp_server_init(si)==-1)  goto error;
				/* get first ipv4/ipv6 socket*/
				if ((si->address.af==AF_INET)&&
						((sendipv4_sctp==0)||(sendipv4_sctp->flags&SI_IS_LO)))
					sendipv4_sctp=si;
			#ifdef USE_IPV6
				if((sendipv6_sctp==0)&&(si->address.af==AF_INET6))
					sendipv6_sctp=si;
			#endif
			}
		}
		#endif /* USE_SCTP */

		/* all processes should have access to all the sockets (for sending)
		 * so we open all first*/
		if (do_suid(uid, gid)==-1) goto error; /* try to drop privileges */

		if (start_module_procs()!=0) {
			LM_ERR("failed to fork module processes\n");
			goto error;
		}

		if(startup_rlist.a) {/* if a startup route was defined */
			startup_done = (int*)shm_malloc(sizeof(int));
			if(startup_done == NULL)
			{
				LM_ERR("No more shared memory\n");
				goto error;
			}
			*startup_done = 0;
		}

		/* udp processes */
		for(si=udp_listen; si; si=si->next){
			load_p = shm_malloc(sizeof(atomic_t));
			if (!load_p) {
			/* highly improbable */
				LM_ERR("no more shm\n");
				goto error;
			}
			memset(load_p,0,sizeof(atomic_t));
			register_udp_load_stat(&si->sock_str,load_p);

			for(i=0;i<children_no;i++){
				chd_rank++;
				if ( (pid=internal_fork( "UDP receiver"))<0 ) {
					LM_CRIT("cannot fork UDP process\n");
					goto error;
				} else {
					if (pid==0) {
						/* new UDP process */
						/* set a more detailed description */
						set_proc_attrs("SIP receiver %.*s ",
							si->sock_str.len, si->sock_str.s);
						bind_address=si; /* shortcut */
						if (init_child(chd_rank) < 0) {
							LM_ERR("init_child failed for UDP listener\n");
							exit(-1);
						}

						if(chd_rank == 1 && startup_rlist.a) {
							if(run_startup_route()< 0) {
								LM_ERR("Startup route processing failed\n");
								exit(-1);
							}
							*startup_done = 1;
						}

						/* all UDP listeners on same interface
						 * have same SHM load pointer */
						pt[process_no].load = load_p;
						udp_rcv_loop();
						exit(-1);
					}
					else {
						/* if the first process that runs startup_route*/
						if(chd_rank == 1 && startup_rlist.a) {
							while(!startup_done) {
								usleep(5);
							}
							shm_free(startup_done);
						}
					}
				}
			}
			/*parent*/
			/*close(udp_sock)*/; /*if it's closed=>sendto invalid fd errors?*/
		}
	}

	#ifdef USE_SCTP
	if(!sctp_disable){
		for(si=sctp_listen; si; si=si->next){
			for(i=0;i<children_no;i++){
				chd_rank++;
				if ( (pid=internal_fork( "SCTP receiver"))<0 ) {
					LM_CRIT("cannot fork SCTP process\n");
					goto error;
				} else if (pid==0){
					/* new SCTP process */
					/* set a more detailed description */
					set_proc_attrs("SIP receiver %.*s ",
						si->sock_str.len, si->sock_str.s);
					bind_address=si; /* shortcut */
					if (init_child(chd_rank) < 0) {
						LM_ERR("init_child failed\n");
						exit(-1);
					}
					sctp_server_rcv_loop();
					exit(-1);
				}
			}
		}
	}
	#endif /* USE_SCTP */

	/* this is the main process -> it shouldn't send anything */
	bind_address=0;

	/* fork for the timer process*/
	if (start_timer_processes()!=0) {
		LM_CRIT("cannot start timer process(es)\n");
		goto error;
	}

	#ifdef USE_TCP
	if (!tcp_disable){
		/* start tcp  & tls receivers */
		if (tcp_init_children(&chd_rank)<0) goto error;
		/* start tcp+tls master proc */
		if ( (pid=internal_fork( "TCP main"))<0 ) {
			LM_CRIT("cannot fork tcp main process\n");
			goto error;
		}else if (pid==0){
			/* child */
			/* close the TCP inter-process sockets */
			close(unix_tcp_sock);
			unix_tcp_sock = -1;
			close(pt[process_no].unix_sock);
			pt[process_no].unix_sock = -1;
			/* init modules */
			if (init_child(PROC_TCP_MAIN) < 0) {
				LM_ERR("error in init_child for tcp main\n");
				exit(-1);
			}
			tcp_main_loop();
			exit(-1);
		}
	}
	#endif

	/* main process left */
	is_main=1;
	set_proc_attrs("attendant");

	if (init_child(PROC_MAIN) < 0) {
		LM_ERR("error in init_child for PROC_MAIN\n");
		goto error;
	}

	for(;;){
			handle_sigs();
			pause();
	}

	/*return 0; */
error:
	is_main=1;  /* if we are here, we are the "main process",
				  any forked children should exit with exit(-1) and not
				  ever use return */
	return -1;

}
Exemple #2
0
/**
 * Main loop, forks the children, bind to addresses,
 * handle signals.
 * \return don't return on sucess, -1 on error
 */
static int main_loop(void)
{
    static int chd_rank;
    int* startup_done = NULL;

    chd_rank=0;

    if (init_debug() != 0) {
        LM_ERR("failed to init logging levels\n");
        goto error;
    }

    if (dont_fork) {

        if (create_status_pipe() < 0) {
            LM_ERR("failed to create status pipe\n");
            goto error;
        }

        if (udp_init_nofork() < 0) {
            LM_ERR("failed to init UDP for no fork mode\n");
            goto error;
        }

        /* try to drop privileges */
        if (do_suid(uid, gid)==-1)
            goto error;

        if (start_module_procs()!=0) {
            LM_ERR("failed to fork module processes\n");
            goto error;
        }

        /* we need another process to act as the timer*/
        if (start_timer_processes()!=0) {
            LM_CRIT("cannot start timer process(es)\n");
            goto error;
        }

        is_main=1;

        udp_start_nofork();
        /* udp_start_nofork() returns only if error */

        /* in case of failed startup, behave as "attendant" to trigger
         * proper cleanup sequance (and proper signal handler !!!).
         * So, reset the dont_fork (as it will force inline signal handling)*/
        dont_fork = 0;
        return -1;

    } else {  /* don't fork */

        if (trans_init_all_listeners()<0) {
            LM_ERR("failed to init all SIP listeners, aborting\n");
            goto error;
        }

        /* all processes should have access to all the sockets (for sending)
         * so we open all first*/
        if (do_suid(uid, gid)==-1) goto error; /* try to drop privileges */

        if (start_module_procs()!=0) {
            LM_ERR("failed to fork module processes\n");
            goto error;
        }

        if(startup_rlist.a) {/* if a startup route was defined */
            startup_done = (int*)shm_malloc(sizeof(int));
            if(startup_done == NULL) {
                LM_ERR("No more shared memory\n");
                goto error;
            }
            *startup_done = 0;
        }

        if (fix_socket_list(&bin) != 0) {
            LM_ERR("failed to initialize binary interface socket list!\n");
            goto error;
        }

        /* OpenSIPS <--> OpenSIPS communication interface */
        if (bin && start_bin_receivers() != 0) {
            LM_CRIT("cannot start binary interface receiver processes!\n");
            goto error;
        }

        /* fork for the timer process*/
        if (start_timer_processes()!=0) {
            LM_CRIT("cannot start timer process(es)\n");
            goto error;
        }

        /* fork all processes required by UDP network layer */
        if (udp_start_processes( &chd_rank, startup_done)<0) {
            LM_CRIT("cannot start TCP processes\n");
            goto error;
        }

        /* fork all processes required by TCP network layer */
        if (tcp_start_processes( &chd_rank, startup_done)<0) {
            LM_CRIT("cannot start TCP processes\n");
            goto error;
        }
    }

    /* this is the main process -> it shouldn't send anything */
    bind_address=0;

    if (startup_done) {
        if (*startup_done==0)
            LM_CRIT("BUG: startup route defined, but not run :( \n");
        shm_free(startup_done);
    }

    /* main process left */
    is_main=1;
    set_proc_attrs("attendant");

    if (init_child(PROC_MAIN) < 0) {
        LM_ERR("error in init_child for PROC_MAIN\n");
        report_failure_status();
        goto error;
    }

    report_conditional_status( (!no_daemon_mode), 0);

    for(;;) {
        handle_sigs();
        pause();
    }

    /*return 0; */
error:
    is_main=1;  /* if we are here, we are the "main process",
				  any forked children should exit with exit(-1) and not
				  ever use return */
    report_conditional_status( (!dont_fork), -1);
    return -1;

}
Exemple #3
0
/* main loop */
int main_loop()
{
	int  i;
	pid_t pid;
	struct socket_info* si;
#ifdef USE_TCP
	int sockfd[2];
#endif

	/* one "main" process and n children handling i/o */

	is_main=0;
	if (dont_fork){
#ifdef STATS
		setstats( 0 );
#endif
		if (udp_listen==0){
			LOG(L_ERR, "ERROR: no fork mode requires at least one"
					" udp listen address, exiting...\n");
			goto error;
		}
		/* only one address, we ignore all the others */
		if (udp_init(udp_listen)==-1) goto error;
		bind_address=udp_listen;
		sendipv4=bind_address;
		sendipv6=bind_address; /*FIXME*/
		if (udp_listen->next){
			LOG(L_WARN, "WARNING: using only the first listen address"
						" (no fork)\n");
		}
		/* initialize fifo server -- we need to open the fifo before
		 * do_suid() and start the fifo server after all the socket 
		 * are initialized, to inherit them*/
		if (init_fifo_server()<0) {
			LOG(L_ERR, "initializing fifo server failed\n");
			goto error;
		}
		 /* Initialize Unix domain socket server */
		if (init_unixsock_socket()<0) {
			LOG(L_ERR, "Error while creating unix domain sockets\n");
			goto error;
		}
		if (do_suid()==-1) goto error; /* try to drop privileges */
		/* process_no now initialized to zero -- increase from now on
		   as new processes are forked (while skipping 0 reserved for main 
		*/

		/* we need another process to act as the timer*/
#ifdef USE_TCP
		/* if we are using tcp we always need a timer process,
		 * we cannot count on select timeout to measure time
		 * (it works only on linux)
		 */
		if ((!tcp_disable)||(timer_list))
#else
		if (timer_list)
#endif
		{
				process_no++;
				if ((pid=fork())<0){
					LOG(L_CRIT,  "ERROR: main_loop: Cannot fork\n");
					goto error;
				}
				
				if (pid==0){
					/* child */
					/* timer!*/
					/* process_bit = 0; */
					if (init_child(PROC_TIMER) < 0) {
						LOG(L_ERR, "timer: init_child failed\n");
						goto error;
					}
					for(;;){
						sleep(TIMER_TICK);
						timer_ticker();
					}
				}else{
						pt[process_no].pid=pid; /*should be shared mem anyway*/
						strncpy(pt[process_no].desc, "timer", MAX_PT_DESC );
				}
		}

		/* if configured, start a server for accepting FIFO commands,
		 * we need to do it after all the sockets are initialized, to 
		 * inherit them*/
		if (start_fifo_server()<0) {
			LOG(L_ERR, "starting fifo server failed\n");
			goto error;
		}

		if (init_unixsock_children()<0) {
			LOG(L_ERR, "Error while initializing Unix domain socket server\n");
			goto error;
		}

		/* main process, receive loop */
		process_no=0; /*main process number*/
		pt[process_no].pid=getpid();
		snprintf(pt[process_no].desc, MAX_PT_DESC, 
			"stand-alone receiver @ %s:%s", 
			 bind_address->name.s, bind_address->port_no_str.s );
		
		
		     /* 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
		      */

		if (init_child(1) < 0) {
			LOG(L_ERR, "main_dontfork: init_child failed\n");
			goto error;
		}

		is_main=1; /* hack 42: call init_child with is_main=0 in case
					 some modules wants to fork a child */
		
		return udp_rcv_loop();
	}else{
		/* process_no now initialized to zero -- increase from now on
		   as new processes are forked (while skipping 0 reserved for main )
		*/

		for(si=udp_listen;si;si=si->next){
			/* create the listening socket (for each address)*/
			/* udp */
			if (udp_init(si)==-1) goto error;
			/* get first ipv4/ipv6 socket*/
			if ((si->address.af==AF_INET)&&
					((sendipv4==0)||(sendipv4->flags&SI_IS_LO)))
				sendipv4=si;
	#ifdef USE_IPV6
			if((sendipv6==0)&&(si->address.af==AF_INET6))
				sendipv6=si;
	#endif
		}
#ifdef USE_TCP
		if (!tcp_disable){
			for(si=tcp_listen; si; si=si->next){
				/* same thing for tcp */
				if (tcp_init(si)==-1)  goto error;
				/* get first ipv4/ipv6 socket*/
				if ((si->address.af==AF_INET)&&
						((sendipv4_tcp==0)||(sendipv4_tcp->flags&SI_IS_LO)))
					sendipv4_tcp=si;
		#ifdef USE_IPV6
				if((sendipv6_tcp==0)&&(si->address.af==AF_INET6))
					sendipv6_tcp=si;
		#endif
			}
		}
#ifdef USE_TLS
		if (!tls_disable){
			for(si=tls_listen; si; si=si->next){
				/* same as for tcp*/
				if (tls_init(si)==-1)  goto error;
				/* get first ipv4/ipv6 socket*/
				if ((si->address.af==AF_INET)&&
						((sendipv4_tls==0)||(sendipv4_tls->flags&SI_IS_LO)))
					sendipv4_tls=si;
		#ifdef USE_IPV6
				if((sendipv6_tls==0)&&(si->address.af==AF_INET6))
					sendipv6_tls=si;
		#endif
			}
		}
#endif /* USE_TLS */
#endif /* USE_TCP */

		/* initialize fifo server -- we need to open the fifo before
		 * do_suid() and start the fifo server after all the socket 
		 * are initialized, to inherit them*/
		if (init_fifo_server()<0) {
			LOG(L_ERR, "initializing fifo server failed\n");
			goto error;
		}
		 /* Initialize Unix domain socket server */
		     /* Create the unix domain sockets */
		if (init_unixsock_socket()<0) {
			LOG(L_ERR, "ERROR: Could not create unix domain sockets\n");
			goto error;
		}

			/* all processes should have access to all the sockets (for sending)
			 * so we open all first*/
		if (do_suid()==-1) goto error; /* try to drop privileges */

		/* if configured, start a server for accepting FIFO commands,
		 * we need to do it after all the sockets are initialized, to 
		 * inherit them*/
		if (start_fifo_server()<0) {
			LOG(L_ERR, "starting fifo server failed\n");
			goto error;
		}
		     /* Spawn children listening on unix domain socket if and only if
		      * the unix domain socket server has not been disabled (i == 0)
		      */
		if (init_unixsock_children()<0) {
			LOG(L_ERR, "ERROR: Could not initialize unix domain socket server\n");
			goto error;
		}

		/* udp processes */
		for(si=udp_listen; si; si=si->next){
			for(i=0;i<children_no;i++){
				process_no++;
#ifdef USE_TCP
				if(!tcp_disable){
		 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
						LOG(L_ERR, "ERROR: main_loop: socketpair failed: %s\n",
							strerror(errno));
						goto error;
					}
				}
#endif
				if ((pid=fork())<0){
					LOG(L_CRIT,  "main_loop: Cannot fork\n");
					goto error;
				}else if (pid==0){
					     /* child */
#ifdef USE_TCP
					if (!tcp_disable){
						close(sockfd[0]);
						unix_tcp_sock=sockfd[1];
					}
#endif
					bind_address=si; /* shortcut */
					if (init_child(i + 1) < 0) {
						LOG(L_ERR, "init_child failed\n");
						goto error;
					}
#ifdef STATS
					setstats( i+r*children_no );
#endif
					return udp_rcv_loop();
				}else{
						pt[process_no].pid=pid; /*should be in shared mem.*/
						snprintf(pt[process_no].desc, MAX_PT_DESC,
							"receiver child=%d sock= %s:%s", i, 	
							si->name.s, si->port_no_str.s );
#ifdef USE_TCP
						if (!tcp_disable){
							close(sockfd[1]);
							pt[process_no].unix_sock=sockfd[0];
							pt[process_no].idx=-1; /* this is not a "tcp"
													  process*/
						}
#endif
				}
			}
			/*parent*/
			/*close(udp_sock)*/; /*if it's closed=>sendto invalid fd errors?*/
		}
	}

	/*this is the main process*/
	bind_address=0;				/* main proc -> it shouldn't send anything, */
	

#ifdef USE_TCP
	/* if we are using tcp we always need the timer */
	if ((!tcp_disable)||(timer_list))
#else
	if (timer_list)
#endif
	{
#ifdef USE_TCP
		if (!tcp_disable){
 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
				LOG(L_ERR, "ERROR: main_loop: socketpair failed: %s\n",
					strerror(errno));
				goto error;
			}
		}
#endif
		/* fork again for the attendant process*/
		process_no++;
		if ((pid=fork())<0){
			LOG(L_CRIT, "main_loop: cannot fork timer process\n");
			goto error;
		}else if (pid==0){
			/* child */
			/* is_main=0; */
#ifdef USE_TCP
			if (!tcp_disable){
				close(sockfd[0]);
				unix_tcp_sock=sockfd[1];
			}
#endif
			if (init_child(PROC_TIMER) < 0) {
				LOG(L_ERR, "timer: init_child failed\n");
				goto error;
			}
			
			for(;;){
				/* debug:  instead of doing something useful */
				/* (placeholder for timers, etc.) */
				sleep(TIMER_TICK);
				/* if we received a signal => TIMER_TICK may have not elapsed*/
				timer_ticker();
			}
		}else{
			pt[process_no].pid=pid;
			strncpy(pt[process_no].desc, "timer", MAX_PT_DESC );
#ifdef USE_TCP
			if(!tcp_disable){
						close(sockfd[1]);
						pt[process_no].unix_sock=sockfd[0];
						pt[process_no].idx=-1; /* this is not a "tcp" process*/
			}
#endif
		}
	}
#ifdef USE_TCP
		if (!tcp_disable){
				/* start tcp  & tls receivers */
			if (tcp_init_children()<0) goto error;
				/* start tcp+tls master proc */
			process_no++;
			if ((pid=fork())<0){
				LOG(L_CRIT, "main_loop: cannot fork tcp main process\n");
				goto error;
			}else if (pid==0){
				/* child */
				/* is_main=0; */
				if (init_child(PROC_TCP_MAIN) < 0) {
					LOG(L_ERR, "tcp_main: error in init_child\n");
					goto error;
				}
				tcp_main_loop();
			}else{
				pt[process_no].pid=pid;
				strncpy(pt[process_no].desc, "tcp main process", MAX_PT_DESC );
				pt[process_no].unix_sock=-1;
				pt[process_no].idx=-1; /* this is not a "tcp" process*/
				unix_tcp_sock=-1;
			}
		}
#endif
	/* main */
	pt[0].pid=getpid();
	strncpy(pt[0].desc, "attendant", MAX_PT_DESC );
#ifdef USE_TCP
	if(!tcp_disable){
		pt[process_no].unix_sock=-1;
		pt[process_no].idx=-1; /* this is not a "tcp" process*/
		unix_tcp_sock=-1;
	}
#endif
	/*DEBUG- remove it*/
#ifdef DEBUG
	fprintf(stderr, "\n% 3d processes (%3d), % 3d children * "
			"listening addresses + tcp listeners + tls listeners"
			"+ main + fifo %s\n", process_no+1, process_count(), children_no,
			(timer_list)?"+ timer":"");
	for (r=0; r<=process_no; r++){
		fprintf(stderr, "% 3d   % 5d - %s\n", r, pt[r].pid, pt[r].desc);
	}
#endif
	process_no=0; 
	/* process_bit = 0; */
	is_main=1;
	
	if (init_child(PROC_MAIN) < 0) {
		LOG(L_ERR, "main: error in init_child\n");
		goto error;
	}
	for(;;){
			pause();
			handle_sigs();
	}
	
	
	/*return 0; */
 error:
	is_main=1;  /* if we are here, we are the "main process",
				  any forked children should exit with exit(-1) and not
				  ever use return */
	return -1;

}
Exemple #4
0
/**
 * Main loop, forks the children, bind to addresses,
 * handle signals.
 * \return don't return on sucess, -1 on error
 */
static int main_loop(void)
{
	static int chd_rank;
	int  i,rc;
	pid_t pid;
	struct socket_info* si;
	int* startup_done = NULL;
	stat_var *load_p = NULL;

	chd_rank=0;

	if (init_debug() != 0) {
		LM_ERR("failed to init logging levels\n");
		goto error;
	}

	if (dont_fork){

		if (create_status_pipe() < 0) {
			LM_ERR("failed to create status pipe");
			goto error;
		}

		if (udp_listen==0){
			LM_ERR("no fork mode requires at least one"
					" udp listen address, exiting...\n");
			goto error;
		}
		/* only one address, we ignore all the others */
		if (udp_init(udp_listen)==-1) goto error;
		bind_address=udp_listen;
		sendipv4=bind_address;
		sendipv6=bind_address; /*FIXME*/
		if (udp_listen->next){
			LM_WARN("using only the first listen address (no fork)\n");
		}

		/* try to drop privileges */
		if (do_suid(uid, gid)==-1)
			goto error;

		if (start_module_procs()!=0) {
			LM_ERR("failed to fork module processes\n");
			goto error;
		}

		/* we need another process to act as the timer*/
		if (start_timer_processes()!=0) {
			LM_CRIT("cannot start timer process(es)\n");
			goto error;
		}

		/* main process, receive loop */
		set_proc_attrs("stand-alone SIP receiver %.*s",
			 bind_address->sock_str.len, bind_address->sock_str.s );

		/* 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 */
		if (init_child(1) < 0) {
			LM_ERR("init_child failed in don't fork\n");
			goto error;
		}

		if (startup_rlist.a)
			run_startup_route();

		is_main=1;

		if (register_udp_load_stat(&udp_listen->sock_str,
		&pt[process_no].load, 1)!=0) {
			LM_ERR("failed to init udp load statistics\n");
			goto error;
		}

		clean_write_pipeend();
		LM_DBG("waiting for status code from children\n");
		rc = wait_for_all_children();
		if (rc < 0) {
			LM_ERR("failed to succesfully init children\n");
			return rc;
		}

		return udp_rcv_loop();
	} else {  /* don't fork */

		for(si=udp_listen;si;si=si->next){
			/* create the listening socket (for each address)*/
			/* udp */
			if (udp_init(si)==-1) goto error;
			/* get first ipv4/ipv6 socket*/
			if ((si->address.af==AF_INET)&&
					((sendipv4==0)||(sendipv4->flags&SI_IS_LO)))
				sendipv4=si;
			#ifdef USE_IPV6
			if((sendipv6==0)&&(si->address.af==AF_INET6))
				sendipv6=si;
			#endif
		}
		#ifdef USE_TCP
		if (!tcp_disable){
			for(si=tcp_listen; si; si=si->next){
				/* same thing for tcp */
				if (tcp_init(si)==-1)  goto error;
				/* get first ipv4/ipv6 socket*/
				if ((si->address.af==AF_INET)&
						((sendipv4_tcp==0)||(sendipv4_tcp->flags&SI_IS_LO)))
					sendipv4_tcp=si;
				#ifdef USE_IPV6
				if((sendipv6_tcp==0)&&(si->address.af==AF_INET6))
					sendipv6_tcp=si;
				#endif
			}
		}
		#ifdef USE_TLS
		if (!tls_disable){
			for(si=tls_listen; si; si=si->next){
				/* same as for tcp*/
				if (tls_init(si)==-1)  goto error;
				/* get first ipv4/ipv6 socket*/
				if ((si->address.af==AF_INET)&&
						((sendipv4_tls==0)||(sendipv4_tls->flags&SI_IS_LO)))
					sendipv4_tls=si;
				#ifdef USE_IPV6
				if((sendipv6_tls==0)&&(si->address.af==AF_INET6))
					sendipv6_tls=si;
				#endif
			}
		}
		#endif /* USE_TLS */
		#endif /* USE_TCP */
		#ifdef USE_SCTP
		if (!sctp_disable){
			for(si=sctp_listen; si; si=si->next){
				/* same thing for sctp */
				if (sctp_server_init(si)==-1)  goto error;
				/* get first ipv4/ipv6 socket*/
				if ((si->address.af==AF_INET)&&
						((sendipv4_sctp==0)||(sendipv4_sctp->flags&SI_IS_LO)))
					sendipv4_sctp=si;
			#ifdef USE_IPV6
				if((sendipv6_sctp==0)&&(si->address.af==AF_INET6))
					sendipv6_sctp=si;
			#endif
			}
		}
		#endif /* USE_SCTP */

		/* all processes should have access to all the sockets (for sending)
		 * so we open all first*/
		if (do_suid(uid, gid)==-1) goto error; /* try to drop privileges */

		if (start_module_procs()!=0) {
			LM_ERR("failed to fork module processes\n");
			goto error;
		}

		if(startup_rlist.a) {/* if a startup route was defined */
			startup_done = (int*)shm_malloc(sizeof(int));
			if(startup_done == NULL) {
				LM_ERR("No more shared memory\n");
				goto error;
			}
			*startup_done = 0;
		}

		if (fix_socket_list(&bin) != 0) {
			LM_ERR("failed to initialize binary interface socket list!\n");
			goto error;
		}

		/* OpenSIPS <--> OpenSIPS communication interface */
		if (bin && start_bin_receivers() != 0) {
			LM_CRIT("cannot start binary interface receiver processes!\n");
			goto error;
		}

		/* udp processes */
		for(si=udp_listen; si; si=si->next){

			if(register_udp_load_stat(&si->sock_str,&load_p,si->children)!=0){
				LM_ERR("failed to init load statistics\n");
				goto error;
			}

			for(i=0;i<si->children;i++){
				chd_rank++;
				if ( (pid=internal_fork( "UDP receiver"))<0 ) {
					LM_CRIT("cannot fork UDP process\n");
					goto error;
				} else {
					if (pid==0) {
						/* new UDP process */
						/* set a more detailed description */
						set_proc_attrs("SIP receiver %.*s ",
							si->sock_str.len, si->sock_str.s);
						bind_address=si; /* shortcut */
						if (init_child(chd_rank) < 0) {
							LM_ERR("init_child failed for UDP listener\n");
							if (send_status_code(-1) < 0)
								LM_ERR("failed to send status code\n");
							clean_write_pipeend();
							if (chd_rank == 1 && startup_done)
								*startup_done = -1;
							exit(-1);
						}

						/* first UDP proc runs statup_route (if defined) */
						if(chd_rank == 1 && startup_done!=NULL) {
							LM_DBG("runing startup for first UDP\n");
							if(run_startup_route()< 0) {
								if (send_status_code(-1) < 0)
									LM_ERR("failed to send status code\n");
								clean_write_pipeend();
								*startup_done = -1;
								LM_ERR("Startup route processing failed\n");
								exit(-1);
							}
							*startup_done = 1;
						}

						if (!no_daemon_mode && send_status_code(0) < 0)
							LM_ERR("failed to send status code\n");
						clean_write_pipeend();


						/* all UDP listeners on same interface
						 * have same SHM load pointer */
						pt[process_no].load = load_p;
						udp_rcv_loop();
						exit(-1);
					}
					else {
						/* wait for first proc to finish the startup route */
						if(chd_rank == 1 && startup_done!=NULL)
							while( !(*startup_done) ) {usleep(5);handle_sigs();}
					}
				}
			}
			/*parent*/
			/*close(udp_sock)*/; /*if it's closed=>sendto invalid fd errors?*/
		}
	}

	#ifdef USE_SCTP
	if(!sctp_disable){
		for(si=sctp_listen; si; si=si->next){
			for(i=0;i<si->children;i++){
				chd_rank++;
				if ( (pid=internal_fork( "SCTP receiver"))<0 ) {
					LM_CRIT("cannot fork SCTP process\n");
					goto error;
				} else if (pid==0){
					/* new SCTP process */
					/* set a more detailed description */
					set_proc_attrs("SIP receiver %.*s ",
						si->sock_str.len, si->sock_str.s);
					bind_address=si; /* shortcut */
					if (init_child(chd_rank) < 0) {
						LM_ERR("init_child failed\n");
						if (send_status_code(-1) < 0)
							LM_ERR("failed to send status code\n");
						clean_write_pipeend();
						if( (si==sctp_listen && i==0) && startup_done)
							*startup_done = -1;
						exit(-1);
					}

					/* was startup route executed so far ? if not, run it only by the
					 * first SCTP proc (first proc from first interface) */
					if( (si==sctp_listen && i==0) && startup_done!=NULL && *startup_done==0) {
						LM_DBG("runing startup for first SCTP\n");
						if(run_startup_route()< 0) {
							LM_ERR("Startup route processing failed\n");
							if (send_status_code(-1) < 0)
								LM_ERR("failed to send status code\n");
							clean_write_pipeend();
							*startup_done = -1;
							exit(-1);
						}
						*startup_done = 1;
					}

					if (!no_daemon_mode && send_status_code(0) < 0)
						LM_ERR("failed to send status code\n");
					clean_write_pipeend();

					sctp_server_rcv_loop();
					exit(-1);
				} else {
					/* wait for first proc to finish the startup route */
					if( (si==sctp_listen && i==0) && startup_done!=NULL)
						while( !(*startup_done) ) {usleep(5);handle_sigs();}
				}
			}
		}
	}
	#endif /* USE_SCTP */

	/* this is the main process -> it shouldn't send anything */
	bind_address=0;

	/* fork for the timer process*/
	if (start_timer_processes()!=0) {
		LM_CRIT("cannot start timer process(es)\n");
		goto error;
	}

	#ifdef USE_TCP
	if (!tcp_disable){
		/* start tcp  & tls receivers */
		if (tcp_init_children(&chd_rank, startup_done)<0) goto error;
		/* wait for the startup route to be executed */
		if( startup_done!=NULL)
			while( !(*startup_done) ) {usleep(5);handle_sigs();}
		/* start tcp+tls master proc */
		if ( (pid=internal_fork( "TCP main"))<0 ) {
			LM_CRIT("cannot fork tcp main process\n");
			goto error;
		}else if (pid==0){
			/* child */
			/* close the TCP inter-process sockets */
			close(unix_tcp_sock);
			unix_tcp_sock = -1;
			close(pt[process_no].unix_sock);
			pt[process_no].unix_sock = -1;
			/* init modules */
			if (init_child(PROC_TCP_MAIN) < 0) {
				LM_ERR("error in init_child for tcp main\n");
				if (send_status_code(-1) < 0)
					LM_ERR("failed to send status code\n");
				clean_write_pipeend();

				exit(-1);
			}

			if (!no_daemon_mode && send_status_code(0) < 0)
				LM_ERR("failed to send status code\n");
			clean_write_pipeend();

			tcp_main_loop();
			exit(-1);
		}
	}
	#endif

	if (startup_done) {
		if (*startup_done==0)
			LM_CRIT("BUG: startup route defined, but not run :( \n");
		shm_free(startup_done);
	}

	/* main process left */
	is_main=1;
	set_proc_attrs("attendant");

	if (init_child(PROC_MAIN) < 0) {
		if (send_status_code(-1) < 0)
			LM_ERR("failed to send status code\n");
		clean_write_pipeend();
		LM_ERR("error in init_child for PROC_MAIN\n");
		goto error;
	}

	if (!no_daemon_mode && send_status_code(0) < 0)
		LM_ERR("failed to send status code\n");
	clean_write_pipeend();

	for(;;){
			handle_sigs();
			pause();
	}

	/*return 0; */
error:
	is_main=1;  /* if we are here, we are the "main process",
				  any forked children should exit with exit(-1) and not
				  ever use return */
	if (!dont_fork && send_status_code(-1) < 0)
		LM_ERR("failed to send status code\n");
	clean_write_pipeend();

	return -1;

}
Exemple #5
0
/**
 * Main routine, start of the program execution.
 * \param argc the number of arguments
 * \param argv pointer to the arguments array
 * \return don't return on sucess, -1 on error
 * \see main_loop
 */
int main(int argc, char** argv)
{
	/* configure by default logging to syslog */
	int cfg_log_stderr = 1;
	FILE* cfg_stream;
	int c,r;
	char *tmp;
	int tmp_len;
	int port;
	int proto;
	char *options;
	int ret;
	unsigned int seed;
	int rfd;

	/*init*/
	ret=-1;
	my_argc=argc; my_argv=argv;

	/* process pkg mem size from command line */
	opterr=0;
	options="f:cCm:M:b:l:n:N:rRvdDFETSVhw:t:u:g:P:G:W:o:";

	while((c=getopt(argc,argv,options))!=-1){
		switch(c){
			case 'M':
					pkg_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024;
					if (tmp &&(*tmp)){
						LM_ERR("bad pkgmem size number: -m %s\n", optarg);
						goto error00;
					};

					break;
		}
	}
	/*init pkg mallocs (before parsing cfg but after parsing cmd line !)*/
	if (init_pkg_mallocs()==-1)
		goto error00;

	init_route_lists();

	/* process command line (get port no, cfg. file path etc) */
	/* first reset getopt */
	optind = 1;
	while((c=getopt(argc,argv,options))!=-1){
		switch(c){
			case 'f':
					cfg_file=optarg;
					break;
			case 'C':
					config_check |= 2;
			case 'c':
					if (config_check==3)
						break;
					config_check |= 1;
					cfg_log_stderr=1; /* force stderr logging */
					break;
			case 'm':
					shm_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024;
					if (tmp &&(*tmp)){
						LM_ERR("bad shmem size number: -m %s\n", optarg);
						goto error00;
					};
					break;
			case 'M':
					/* ignoring it, parsed previously */
					break;
			case 'b':
					maxbuffer=strtol(optarg, &tmp, 10);
					if (tmp &&(*tmp)){
						LM_ERR("bad max buffer size number: -b %s\n", optarg);
						goto error00;
					}
					break;
			case 'l':
					if (parse_phostport(optarg, strlen(optarg), &tmp, &tmp_len,
											&port, &proto)<0){
						LM_ERR("bad -l address specifier: %s\n", optarg);
						goto error00;
					}
					tmp[tmp_len]=0; /* null terminate the host */
					/* add a new addr. to our address list */
					if (add_cmd_listener(tmp, port, proto)!=0){
						LM_ERR("failed to add new listen address\n");
						goto error00;
					}
					break;
			case 'n':
					children_no=strtol(optarg, &tmp, 10);
					if ((tmp==0) ||(*tmp)){
						LM_ERR("bad process number: -n %s\n", optarg);
						goto error00;
					}
					break;
			case 'v':
					check_via=1;
					break;
			case 'r':
					received_dns|=DO_DNS;
					break;
			case 'R':
					received_dns|=DO_REV_DNS;
				    break;
			case 'd':
					*log_level = debug_mode ? L_DBG : (*log_level)+1;
					break;
			case 'D':
					debug_mode=1;
					*log_level = L_DBG;
					break;
			case 'F':
					no_daemon_mode=1;
					break;
			case 'E':
					cfg_log_stderr=1;
					break;
			case 'N':
					tcp_children_no=strtol(optarg, &tmp, 10);
					if ((tmp==0) ||(*tmp)){
						LM_ERR("bad process number: -N %s\n", optarg);
						goto error00;
					}
					break;
			case 'W':
					io_poll_method=get_poll_type(optarg);
					if (io_poll_method==POLL_NONE){
						LM_ERR("bad poll method name: -W %s\ntry "
							"one of %s.\n", optarg, poll_support);
						goto error00;
					}
					break;
			case 'V':
					printf("version: %s\n", version);
					printf("flags: %s\n", flags );
					print_ct_constants();
					printf("%s compiled on %s with %s\n", __FILE__,
							compiled, COMPILER );
					exit(0);
					break;
			case 'h':
					printf("version: %s\n", version);
					printf("%s",help_msg);
					exit(0);
					break;
			case 'w':
					working_dir=optarg;
					break;
			case 't':
					chroot_dir=optarg;
					break;
			case 'u':
					user=optarg;
					break;
			case 'g':
					group=optarg;
					break;
			case 'P':
					pid_file=optarg;
					break;
			case 'G':
					pgid_file=optarg;
					break;
			case 'o':
					if (add_arg_var(optarg) < 0)
						LM_ERR("cannot add option %s\n", optarg);
					break;
			case '?':
					if (isprint(optopt))
						LM_ERR("Unknown option `-%c`.\n", optopt);
					else
						LM_ERR("Unknown option character `\\x%x`.\n", optopt);
					goto error00;
			case ':':
					LM_ERR("Option `-%c` requires an argument.\n", optopt);
					goto error00;
			default:
					abort();
		}
	}

	log_stderr = cfg_log_stderr;

	/* fill missing arguments with the default values*/
	if (cfg_file==0) cfg_file=CFG_FILE;

	/* load config file or die */
	cfg_stream=fopen (cfg_file, "r");
	if (cfg_stream==0){
		LM_ERR("loading config file(%s): %s\n", cfg_file,
				strerror(errno));
		goto error00;
	}

	/* seed the prng, try to use /dev/urandom if possible */
	/* no debugging information is logged, because the standard
	   log level prior the config file parsing is L_NOTICE */
	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 */
			LM_WARN("could not read from /dev/urandom (%d)\n", errno);
		}
		LM_DBG("initialize the pseudo random generator from "
			"/dev/urandom\n");
		LM_DBG("read %u from /dev/urandom\n", seed);
			close(rfd);
	}else{
		LM_WARN("could not open /dev/urandom (%d)\n", errno);
		LM_WARN("using a unsafe seed for the pseudo random number generator");
	}
	seed+=getpid()+time(0);
	LM_DBG("seeding PRNG with %u\n", seed);
	srand(seed);
	LM_DBG("test random number %u\n", rand());

	/*register builtin  modules*/
	register_builtin_modules();

	/* init avps */
	if (init_global_avps() != 0) {
		LM_ERR("error while initializing avps\n");
		goto error;
	}

	/* used for parser debugging */
#ifdef DEBUG_PARSER
	yydebug = 1;
#endif

	/*
	 * initializes transport interfaces - we initialize them here because we
	 * can have listening interfaces declared in the command line
	 */
	if (trans_init() < 0) {
		LM_ERR("cannot initialize transport interface\n");
		goto error;
	}

		/* get uid/gid */
	if (user){
		if (user2uid(&uid, &gid, user)<0){
			LM_ERR("bad user name/uid number: -u %s\n", user);
			goto error00;
		}
	}
	if (group){
		if (group2gid(&gid, group)<0){
			LM_ERR("bad group name/gid number: -u %s\n", group);
			goto error00;
		}
	}

		/*init shm mallocs
	 *  this must be here
	 *     -to allow setting shm mem size from the command line
	 *     -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)
	 * --andrei */
	if (init_shm_mallocs()==-1)
		goto error;

	if (init_stats_collector() < 0) {
		LM_ERR("failed to initialize statistics\n");
		goto error;
	}

	/* parse the config file, prior to this only default values
	   e.g. for debugging settings will be used */
	yyin=cfg_stream;
	if ((yyparse()!=0)||(cfg_errors)){
		LM_ERR("bad config file (%d errors)\n", cfg_errors);
		goto error00;
	}

	if (config_check>1 && check_rls()!=0) {
		LM_ERR("bad function call in config file\n");
		return ret;
	}

	if (solve_module_dependencies(modules) != 0) {
		LM_ERR("failed to solve module dependencies\n");
		return -1;
	}

	/* init the resolver, before fixing the config */
	resolv_init();

	fix_poll_method( &io_poll_method );

	/* fix temporary listeners added in the cmd line */
	if (fix_cmd_listeners() < 0) {
		LM_ERR("cannot add temproray listeners\n");
		return ret;
	}

	/* load transport protocols */
	if (trans_load() < 0) {
		LM_ERR("cannot load transport protocols\n");
		goto error;
	}

	/* fix parameters */
	if (working_dir==0) working_dir="/";

	if (fix_all_socket_lists()!=0){
		LM_ERR("failed to initialize list addresses\n");
		goto error00;
	}
	/* print all the listen addresses */
	printf("Listening on \n");
	print_all_socket_lists();
	printf("Aliases: \n");
	/*print_aliases();*/
	print_aliases();
	printf("\n");

	if (config_check){
		LM_NOTICE("config file ok, exiting...\n");
		return 0;
	}

	time(&startup_time);

	/* Init statistics */
	init_shm_statistics();

	/*init UDP networking layer*/
	if (udp_init()<0){
		LM_CRIT("could not initialize tcp\n");
		goto error;
	}
	/*init TCP networking layer*/
	if (tcp_init()<0){
		LM_CRIT("could not initialize tcp\n");
		goto error;
	}

	if (create_status_pipe() < 0) {
		LM_ERR("failed to create status pipe\n");
		goto error;
	}

	if (debug_mode) {

		LM_NOTICE("DEBUG MODE activated\n");
		if (no_daemon_mode==0) {
			LM_NOTICE("disabling daemon mode (found enabled)\n");
			no_daemon_mode = 1;
		}
		if (log_stderr==0) {
			LM_NOTICE("enabling logging to standard error (found disabled)\n");
			log_stderr = 1;
		}
		if (*log_level<L_DBG) {
			LM_NOTICE("setting logging to debug level (found on %d)\n",
				*log_level);
			*log_level = L_DBG;
		}
		if (disable_core_dump) {
			LM_NOTICE("enabling core dumping (found off)\n");
			disable_core_dump = 0;
		}
		if (udp_count_processes()!=0) {
			if (children_no!=2) {
				LM_NOTICE("setting UDP children to 2 (found %d)\n",
					children_no);
				children_no = 2;
			}
		}
		if (tcp_count_processes()!=0) {
			if (tcp_children_no!=2) {
				LM_NOTICE("setting TCP children to 2 (found %d)\n",
					tcp_children_no);
				tcp_children_no = 2;
			}
		}

	} else { /* debug_mode */

		/* init_daemon */
		if ( daemonize((log_name==0)?argv[0]:log_name, &own_pgid) <0 )
			goto error;

	}

	/* install signal handlers */
	if (install_sigs() != 0){
		LM_ERR("could not install the signal handlers\n");
		goto error;
	}

	if (disable_core_dump) set_core_dump(0, 0);
	else set_core_dump(1, shm_mem_size+pkg_mem_size+4*1024*1024);
	if (open_files_limit>0) {
		if(set_open_fds_limit()<0){
			LM_ERR("ERROR: error could not increase file limits\n");
			goto error;
		}
	}

	/* print OpenSIPS version to log for history tracking */
	LM_NOTICE("version: %s\n", version);

	/* print some data about the configuration */
	LM_INFO("using %ld Mb shared memory\n", ((shm_mem_size/1024)/1024));
	LM_INFO("using %ld Mb private memory per process\n",
		((pkg_mem_size/1024)/1024));

	/* init async reactor */
	if (init_reactor_size()<0) {
		LM_CRIT("failed to init internal reactor, exiting...\n");
		goto error;
	}

	/* init timer */
	if (init_timer()<0){
		LM_CRIT("could not initialize timer, exiting...\n");
		goto error;
	}

	/* init serial forking engine */
	if (init_serialization()!=0) {
		LM_ERR("failed to initialize serialization\n");
		goto error;
	}
	/* Init MI */
	if (init_mi_core()<0) {
		LM_ERR("failed to initialize MI core\n");
		goto error;
	}

	/* Register core events */
	if (evi_register_core() != 0) {
		LM_ERR("failed register core events\n");
		goto error;
	}

	/* init black list engine */
	if (init_black_lists()!=0) {
		LM_CRIT("failed to init blacklists\n");
		goto error;
	}
	/* init resolver's blacklist */
	if (resolv_blacklist_init()!=0) {
		LM_CRIT("failed to create DNS blacklist\n");
		goto error;
	}

	/* init modules */
	if (init_modules() != 0) {
		LM_ERR("error while initializing modules\n");
		goto error;
	}

	/* register route timers */
	if(register_route_timers() < 0) {
		LM_ERR("Failed to register timer\n");
		goto error;
	}

	/* check pv context list */
	if(pv_contextlist_check() != 0) {
		LM_ERR("used pv context that was not defined\n");
		goto error;
	}

	/* init query list now in shm
	 * so all processes that will be forked from now on
	 * will have access to it
	 *
	 * if it fails, give it a try and carry on */
	if (init_ql_support() != 0) {
		LM_ERR("failed to initialise buffering query list\n");
		query_buffer_size = 0;
		*query_list = NULL;
	}

	/* init multi processes support */
	if (init_multi_proc_support()!=0) {
		LM_ERR("failed to init multi-proc support\n");
		goto error;
	}

	#ifdef PKG_MALLOC
	/* init stats support for pkg mem */
	if (init_pkg_stats(counted_processes)!=0) {
		LM_ERR("failed to init stats for pkg\n");
		goto error;
	}
	#endif

	/* init avps */
	if (init_extra_avps() != 0) {
		LM_ERR("error while initializing avps\n");
		goto error;
	}

	/* fix routing lists */
	if ( (r=fix_rls())!=0){
		LM_ERR("failed to fix configuration with err code %d\n", r);
		goto error;
	}

	if (init_log_level() != 0) {
		LM_ERR("failed to init logging levels\n");
		goto error;
	}

	if (trans_init_all_listeners()<0) {
		LM_ERR("failed to init all SIP listeners, aborting\n");
		goto error;
	}

	/* all processes should have access to all the sockets (for sending)
	 * so we open all first*/
	if (do_suid(uid, gid)==-1)
		goto error;

	ret = main_loop();

error:
	/*kill everything*/
	kill_all_children(SIGTERM);
	/*clean-up*/
	cleanup(0);
error00:
	LM_NOTICE("Exiting....\n");
	return ret;
}