| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | /*-
 | 
					
						
							|  |  |  |  * Copyright (c) 2015, Babak Farrokhi | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  * modification, are permitted provided that the following conditions are met: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * * Redistributions of source code must retain the above copyright notice, this | 
					
						
							|  |  |  |  *   list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * * Redistributions in binary form must reproduce the above copyright notice, | 
					
						
							|  |  |  |  *   this list of conditions and the following disclaimer in the documentation | 
					
						
							|  |  |  |  *   and/or other materials provided with the distribution. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
					
						
							|  |  |  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
					
						
							|  |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
					
						
							|  |  |  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | 
					
						
							|  |  |  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
					
						
							|  |  |  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
					
						
							|  |  |  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
					
						
							|  |  |  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
					
						
							|  |  |  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
					
						
							|  |  |  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <sys/cdefs.h>
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <sys/param.h>
 | 
					
						
							|  |  |  | #include <sys/time.h>
 | 
					
						
							|  |  |  | #include <sys/file.h>
 | 
					
						
							|  |  |  | #include <sys/socket.h>
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | #include <netdb.h>
 | 
					
						
							|  |  |  | #include <netinet/in.h>
 | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 
 | 
					
						
							|  |  |  | #include <err.h>
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <signal.h>
 | 
					
						
							|  |  |  | #include <stdbool.h>
 | 
					
						
							|  |  |  | #include <stdint.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <sysexits.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | #include <syslog.h>
 | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | #include <libutil.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | #define	PORT 5060
 | 
					
						
							|  |  |  | #define BACKLOG 1024
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | /* Globals */ | 
					
						
							|  |  |  | struct pidfh *pfh; | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | struct sockaddr_in sa; | 
					
						
							|  |  |  | struct protoent *proto_tcp, *proto_udp; | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Prepare for a clean shutdown | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | daemon_shutdown() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	pidfile_remove(pfh); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Act upon receiving signals | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | signal_handler(int sig) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	switch (sig) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case SIGHUP: | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 	case SIGINT: | 
					
						
							|  |  |  | 	case SIGTERM: | 
					
						
							|  |  |  | 		daemon_shutdown(); | 
					
						
							|  |  |  | 		exit(EXIT_SUCCESS); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | void | 
					
						
							|  |  |  | process_request(char *str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* check input str for SIP requests */ | 
					
						
							|  |  |  | 	syslog(LOG_ALERT, "incoming packet: %s\n", str); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Daemonize and persist pid | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | daemon_start() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sigaction sig_action; | 
					
						
							|  |  |  | 	sigset_t sig_set; | 
					
						
							|  |  |  | 	pid_t otherpid; | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 	int curPID; | 
					
						
							|  |  |  | 	register int s, c; | 
					
						
							|  |  |  | 	unsigned int b; | 
					
						
							|  |  |  | 	FILE *client; | 
					
						
							|  |  |  | 	char inputstr[8192]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Check if we can acquire the pid file */ | 
					
						
							|  |  |  | 	pfh = pidfile_open(NULL, 0600, &otherpid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (pfh == NULL) { | 
					
						
							|  |  |  | 		if (errno == EEXIST) { | 
					
						
							|  |  |  | 			errx(EXIT_FAILURE, "Daemon already running, pid: %jd.", (intmax_t)otherpid); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		warn("Cannot open or create pidfile."); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 	/* setup socket */ | 
					
						
							|  |  |  | 	if ((proto_tcp = getprotobyname("tcp")) == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 	bzero(&sa, sizeof(sa)); | 
					
						
							|  |  |  | 	sa.sin_port = htons(PORT); | 
					
						
							|  |  |  | 	sa.sin_family = AF_INET; | 
					
						
							|  |  |  | 	sa.sin_addr.s_addr = htonl(INADDR_ANY); | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 	if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { | 
					
						
							|  |  |  | 	    perror("socket"); | 
					
						
							|  |  |  | 	    return EXIT_FAILURE; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 	if (bind(s, (struct sockaddr *)&sa, sizeof sa) < 0) { | 
					
						
							|  |  |  |         	perror("bind"); | 
					
						
							|  |  |  |         	return EXIT_FAILURE; | 
					
						
							|  |  |  |     	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* start daemonizing */ | 
					
						
							|  |  |  | 	curPID = fork(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (curPID) { | 
					
						
							|  |  |  | 	case 0:			/* This process is the child */ | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case -1:			/* fork() failed, should exit */ | 
					
						
							|  |  |  | 		perror("fork"); | 
					
						
							|  |  |  | 		return (EXIT_FAILURE); | 
					
						
							|  |  |  | 	default:			/* fork() successful, should exit */ | 
					
						
							|  |  |  | 		return (EXIT_SUCCESS); | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 	/* we are the child, complete the daemonization */ | 
					
						
							|  |  |  | 	/* Close standard IO */ | 
					
						
							|  |  |  | 	fclose(stdin); | 
					
						
							|  |  |  | 	fclose(stdout); | 
					
						
							|  |  |  | 	fclose(stderr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Block unnecessary signals */ | 
					
						
							|  |  |  | 	sigemptyset(&sig_set); | 
					
						
							|  |  |  | 	sigaddset(&sig_set, SIGCHLD);	/* ignore child - i.e. we don't need
 | 
					
						
							|  |  |  | 					 * to wait for it */ | 
					
						
							|  |  |  | 	sigaddset(&sig_set, SIGTSTP);	/* ignore Tty stop signals */ | 
					
						
							|  |  |  | 	sigaddset(&sig_set, SIGTTOU);	/* ignore Tty background writes */ | 
					
						
							|  |  |  | 	sigaddset(&sig_set, SIGTTIN);	/* ignore Tty background reads */ | 
					
						
							|  |  |  | 	sigprocmask(SIG_BLOCK, &sig_set, NULL);	/* Block the above specified
 | 
					
						
							|  |  |  | 						 * signals */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Catch necessary signals */ | 
					
						
							|  |  |  | 	sig_action.sa_handler = signal_handler; | 
					
						
							|  |  |  | 	sigemptyset(&sig_action.sa_mask); | 
					
						
							|  |  |  | 	sig_action.sa_flags = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sigaction(SIGTERM, &sig_action, NULL); | 
					
						
							|  |  |  | 	sigaction(SIGHUP, &sig_action, NULL); | 
					
						
							|  |  |  | 	sigaction(SIGINT, &sig_action, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* create new session and process group */ | 
					
						
							|  |  |  | 	setsid(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* persist pid */ | 
					
						
							|  |  |  | 	pidfile_write(pfh); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 	/* TODO: Network Logic Here */ | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 
 | 
					
						
							|  |  |  | 	listen(s, BACKLOG); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 	while (1) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 		b = sizeof(sa); | 
					
						
							|  |  |  | 		if ((c = accept(s, (struct sockaddr *)&sa, &b)) < 0) { | 
					
						
							|  |  |  | 			perror("accept"); | 
					
						
							|  |  |  | 			return (EXIT_FAILURE); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if ((client = fdopen(c, "w")) == NULL) { | 
					
						
							|  |  |  | 			perror("fdopen"); | 
					
						
							|  |  |  | 			return (EXIT_FAILURE); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 		fgets(inputstr, sizeof(inputstr), client); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		process_request(inputstr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		fclose(client); | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 	return (EXIT_SUCCESS); | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | main(int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-16 16:41:39 +04:30
										 |  |  | 	return (daemon_start()); | 
					
						
							| 
									
										
										
										
											2015-09-16 11:29:27 +04:30
										 |  |  | } |