Skip to content
Snippets Groups Projects
Select Git revision
  • 3fc9ca286bd824c866d8af64616198b60bcc07e4
  • master default protected
  • daemon
  • threading
4 results

main.cpp

Blame
  • main.cpp 4.55 KiB
    /* 
     * File:   main.cpp
     * Author: Eckl, Máté<ecklm94@gmail.com>
     *
     * Created on 2016. április 19., 12:59
     */
    
    #include <string.h>
    #include <string>
    #include <unistd.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <pwd.h>
    #include <signal.h>
    
    #include "include/general_sockaddr_wp.h"
    #include "include/dns_server.h"
    #include "include/exceptions/db_exception.h"
    #include "include/logger.h"
    #include "include/IPC_US_communicator.h"
    #include "include/command.h"
    
    #define WORKING_DIR "/home/mate/Dokumentumok/Egyetem/Tárgyak/2016 tavasz/Linux programozás/HF/DNS_server"
    #define COMM_SOCK_PATH "/var/run/ecklm-dns/"
    
    logger log_on_demand;
    bool verbose = false;
    
    void kill_handler(int);
    void print_help();
    
    int main(int argc, char *argv[])
    {
    	int cli_option;
    	bool run_as_daemon = false;
    	std::vector<command> command_list;
    	while((cli_option = getopt (argc, argv, "dmskvh")) != -1)
    	{
    		switch(cli_option)
    		{
    			case 'd':
    				run_as_daemon = true;
    				break;
    			case 'm':
    				command_list.push_back(MONITOR);
    				break;
    			case 's':
    				command_list.push_back(STATISTICS);
    				break;
    			case 'k':
    				command_list.push_back(KILL);
    				break;
    			case 'v':
    				verbose = true;
    				break;
    			case 'h':
    				print_help();
    				exit(EXIT_SUCCESS);
    			case '?':
    				print_help();
    				exit(EXIT_FAILURE);
    				break;
    			default:
    				break;
    		}
    	}
    	if(!run_as_daemon)
    	{
    		log_on_demand = stdlog_on_demand;
    	}
    	else
    	{
    		openlog("ecklm-dns", LOG_PID, LOG_DAEMON);
    		log_on_demand = syslog_on_demand;
    #ifdef DEBUG // ezt az egész mókát parancssori paraméterektől kell majd függővé tenni
    		if(daemon(0,1) < 0)
    #else
    		if(daemon(0,0) < 0)
    #endif
    		{
    			PERROR_ON_DEMAND("daemon");
    			exit(EXIT_FAILURE);
    		}
    	}
    
    	if(getuid() != 0)
    	{
    		log_on_demand(LOG_ERR, "You should run with root privileges!");
    		exit(EXIT_FAILURE);
    	}
    
    	log_on_demand(LOG_INFO, "Server started on pid %d", getpid()); // Enélkül nem hajlandó sudo után logolni.
    	struct passwd *new_uid = getpwnam("dnsuser");
    
    	if(chroot(WORKING_DIR) < 0)
    	{
    		PERROR_ON_DEMAND("chroot");
    		exit(EXIT_SUCCESS);
    	}
    	log_on_demand(LOG_INFO, "Chrooted to \"%s\"", WORKING_DIR);
    	if(chdir("/") < 0)
    	{
    		PERROR_ON_DEMAND("chdir");
    		exit(EXIT_FAILURE);
    	}
    	setgid(new_uid->pw_gid);
    	setuid(new_uid->pw_uid);
    
    	IPC_US_communicator comm_link(COMM_SOCK_PATH, run_as_daemon);
    	if(!run_as_daemon)
    	{
    		if(command_list.empty())
    		{
    			log_on_demand(LOG_ERR, "In this mode you must specify at least one command!");
    			exit(EXIT_FAILURE);
    		}
    		for(command c : command_list)
    		{
    			comm_link.send_data(get_readable_command(c));
    			log_on_demand(LOG_INFO, "Answer received: %s", comm_link.recv_data().c_str());
    		}
    		exit(EXIT_SUCCESS);
    	}
    
    	struct sigaction killer;
    	sigemptyset(&killer.sa_mask);
    	killer.sa_flags = 0;
    	killer.sa_handler = kill_handler;
    	killer.sa_restorer = NULL;
    	if(sigaction(SIGTERM, &killer, NULL) < 0)
    	{
    		PERROR_ON_DEMAND("sigaction");
    		exit(EXIT_FAILURE);
    	}
    
    // --------------- INIT ---------------------
    	dns_server server;
    	try
    	{
    		server.connect_db("dns.db");
    	}
    	catch(db_exception ex)
    	{
    		log_on_demand(LOG_ERR, ex.what());
    		exit(EXIT_FAILURE);
    	}
    
    	// Init server
    	struct in6_addr in6_addr_any = IN6ADDR_ANY_INIT; //IN6ADDR_LOOPBACK_INIT;
    	struct sockaddr_in6 server_address;
    	memset(&server_address, 0, sizeof(server_address));
    	server_address.sin6_family = AF_INET6;
    	server_address.sin6_addr = in6_addr_any;
    	server_address.sin6_port = htons(10053);
    
    	server.init(general_sockaddr_wp((sockaddr *) &server_address, sizeof(server_address)));
    	if(verbose)
    	{
    		static char addr[INET6_ADDRSTRLEN];
    		inet_ntop(server_address.sin6_family, &server_address.sin6_addr, addr, INET6_ADDRSTRLEN);
    		log_on_demand(LOG_DEBUG, "Server started serving on: %s",addr);
    	}
    
    // ----------------- INIT END --------------------------
    
    // ------------------ SERVE ----------------------------
    	while(true)
    	{
    		server.serve_one_request();
    		if(comm_link.recv_data() == "kill")
    		{
    			comm_link.send_data("go to hell!");
    			log_on_demand(LOG_DEBUG, "Raising SIGTERM");
    			raise(SIGTERM);
    		}
    		else
    			comm_link.send_data("nothing has happened");
    	}
    // ---------------- SERVE END -------------------------
    
    // ------------------- SHUTDOWN -------------------------
    	server.shutdown();
    // ----------------- SHUTDOWN END -----------------------
    	exit(EXIT_SUCCESS);
    }
    
    void print_help() {
    	printf(R"(Usage: Runs in foreground mode by default.
    For more info look at the man page.
    
    Options:
    	-d Run as daemon
    	-m Monitor daemon
    	-s Statistics from daemon
    	-k Kill daemon
    	-v Verbose
    	-h help
    )");
    }
    
    void kill_handler(int x) {
    	log_on_demand(LOG_INFO, "SIGTERM received");
    	exit(EXIT_SUCCESS);
    }