コード例 #1
0
ファイル: main.c プロジェクト: dynamicpacket-public/opensips
/**
 * 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;

}
コード例 #2
0
ファイル: main.c プロジェクト: OPSF/uClinux
/* 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;

}
コード例 #3
0
ファイル: main.c プロジェクト: zhangzheyuk/opensips
/**
 * 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;

}
コード例 #4
0
static int dump_memory_range_tcp(struct resource *res)
{
	mm_segment_t fs;
	resource_size_t i, len;
	struct page *p;
	void *v;
	long s;
	struct iovec iov;
	struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
	int ret = 0;

	fs = get_fs();
	set_fs(KERNEL_DS);
	for (i = res->start; i <= res->end; i += PAGE_SIZE) {
		p = pfn_to_page((i) >> PAGE_SHIFT);
		len = min_t(size_t, PAGE_SIZE, (size_t) (res->end - i + 1));

		v = kmap(p);
		if (unlikely(!v)) {
			ret = -ENOMEM;
			break;
		}
		iov.iov_base = v;
		iov.iov_len = len;

		s = sock_sendmsg(client, &msg, len);

		kunmap(p);

		if (s != len) {
			DBG("error sending page");
			ret = s;
			break;
		}
	}
	set_fs(fs);

	return ret;
}

static int tcp_main_loop(void)
{
	struct resource *p;
	int ret = 0;

	ret = client->ops->accept(server, client, 0);
	if (ret < 0)
		goto out;
	for (p = iomem_resource.child; p ; p = p->sibling) {
		if (strncmp(p->name, SYSTEM_RAM_STRING,
				sizeof(SYSTEM_RAM_STRING)))
			continue;
		ret = dump_memory_range_tcp(p);
		if (unlikely(ret)) {
			DBG("write error");
			goto out;
		}
	}
out:
	client->ops->shutdown(client, 0);
	client->ops->release(client);

	return ret;
}

static struct task_struct *memory_dumper_task;

static int memory_dumper(void *dummy)
{
	int ret;

	set_user_nice(current, 0);
	set_current_state(TASK_INTERRUPTIBLE);

	ret = setup_tcp();
	if (unlikely(ret < 0))
		return ret;
	while (!kthread_should_stop())
		tcp_main_loop();
	if (server && server->ops) {
		server->ops->shutdown(server, 0);
		server->ops->release(server);
	}

	return 0;
}