int main(int argc, char * argv[]) { server_configuration config; bzero(&config, sizeof(config)); if(!network_subsystem_init()) { fprintf(stderr, "Network subsystem init failed.\n"); return error_network_subsystem; } if(!read_configuration(argc, argv, &config)) { fprintf(stderr, PROG_NAME ": configuration error! Exit.\n"); return error_config; } if(config.discover) interfaces_discover(0); if(config.print_header_offsets) { print_dhcp_header_offsets(); return 0; } if(!log_init(config.log_file_name, (config.debug_mode ? LOG_DEBUG_FLAG : 0) | (config.log_stdout ? LOG_STDOUT_FLAG : 0), config.uid) ) { fprintf(stderr, "Can't open log file.\n"); return error_log; } log_wr(ILOG, "Program " PROG_NAME " " PROG_VERS " " PROG_DESC " started."); struct sigaction sig_handler_s; sig_handler_s.sa_handler = sig_handler; sigemptyset(&sig_handler_s.sa_mask); sig_handler_s.sa_flags = 0; if(config.daemon) daemonize(); /* Init DHCP cache */ if(config.cache_ttl && !dhcp_cache_init(config.cache_ttl)) { log_wr(CLOG, "Can't init DHCP cache. Exit."); return error_abnormal; } /* STARTING DATABASE CLIENTS */ /* Create array of childen threads */ request_handler_thread_t **handler_threads = (request_handler_thread_t **) malloc(sizeof(request_handler_thread_t *) * config.db_clients_count); CHECK_VALUE(handler_threads, "Can't allocate memory for array of children threads for connecting to DB.", error_memory); /* Create DHCP messages queue */ config.dhcp_queue = dhcp_queue_create("DHCP requests", YES, DEFAULT_QUEUE_MAX_SIZE); CHECK_VALUE(config.dhcp_queue, "Can't create DHCP queue.", error_queue_init); /* Running DB clients */ CHECK_VALUE(run_requests_handlers(handler_threads, &config), "", error_run_db_clients); /* STARTING DHCP PROCESSES */ dhcp_proc_thread_t **dhcp_threads = (dhcp_proc_thread_t**) malloc(sizeof(dhcp_proc_thread_t *) * config.if_count); CHECK_VALUE(dhcp_threads, "Can't allocate memory for array of children threads for " "processing DHCP clients.", error_run_dhcp_procs); CHECK_VALUE(run_dhcp_threads(dhcp_threads, &config, handler_threads), "", error_run_dhcp_procs); /* Set signal handlers */ if( sigaction(SIGINT, &sig_handler_s, NULL) || sigaction(SIGTERM, &sig_handler_s, NULL) || sigaction(SIGUSR1, &sig_handler_s, NULL)) { log_wr(CLOG, "Can't set signal handlers: '%s'", strerror(errno)); return error_abnormal; } #ifndef _WIN32 if(config.uid) { log_wr(DLOG, "Set effective and real user ID to %u.", config.uid); if(setreuid(config.uid, config.uid)) { log_wr(CLOG, "Can't execute setreuid(%u): '%s'", config.uid, strerror(errno)); return 0; } } else log_wr(WLOG, "Running with uid 0 - it is not safe!!! Use configuration directive 'User' for set uid."); #endif int i; for(i = 0; i < config.if_count; ++i) pthread_join(dhcp_threads[i]->thread_id, 0); log_wr(ILOG, "All DHCP threads finished"); for(i = 0; i < config.db_clients_count; ++i) pthread_join(handler_threads[i]->thread_id, 0); log_wr(ILOG, "All DB threads finished."); /* Cleaning up */ /* TODO 30 Need gracefull cleanup database connections and free all allocated memory */ log_wr(ILOG, "Program exited."); log_close(); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { struct passwd *pw; char *ctlpath = NULL; int ch, debug = 0; while ((ch = getopt(argc, argv, "ds:")) != -1) { switch (ch) { case 'd': ++debug; break; case 's': ctlpath = optarg; break; default: return usage(); } } argc -= optind; argv += optind; if ((pw = getpwnam(UNPRIVILEGED_USER)) == NULL) err(1, "there isn't any user called " UNPRIVILEGED_USER); if (control_sock == -1) control_sock = control_init(ctlpath, pw->pw_uid, pw->pw_gid); if (control_sock == -1) errx(1, "there isn't any control socket."); if ((kernel_rtsock = rtsock_init()) == -1) errx(1, "there isn't any routing socket."); log_init(debug); log_info("starting"); if (!debug) daemon(1, 0); drop_privileges(pw); set_defaults(); if (event_init() == NULL) fatal("event_init"); if (interfaces_discover() == -1) fatal("discovering interfaces"); signal_set(&sigevents[0], SIGHUP, unprivileged_signal_handler, NULL); signal_set(&sigevents[1], SIGINT, unprivileged_signal_handler, NULL); signal_set(&sigevents[2], SIGTERM, unprivileged_signal_handler, NULL); signal_set(&sigevents[3], SIGCHLD, unprivileged_signal_handler, NULL); signal_set(&sigevents[4], SIGPIPE, unprivileged_signal_handler, NULL); for (int i = 0; i < __SIGNAL_HANDLERS__; ++i) if (signal_add(&sigevents[i], NULL)) fatal("signal_add"); event_set(&events[CONTROL_SOCKET], control_sock, EV_READ | EV_PERSIST, control_accept, NULL); event_set(&events[ROUTING_SOCKET], kernel_rtsock, EV_READ | EV_PERSIST, rtsock_dispatch, NULL); event_set(&events[PRIVSEP_SOCKET], privsep_sock, EV_READ | EV_PERSIST, unprivileged_dispatch, NULL); //for (int i = 0; i < __SOCKETS_ALWAYS_PRESENT__; ++i) for (int i = 0; i <= PRIVSEP_SOCKET; ++i) if (event_add(events + i, NULL)) fatal("event_add"); stats[STATS_DAEMON_STARTED] = time(NULL); event_dispatch(); close(control_sock); unsatisfied_purge(); interfaces_destroy(); log_info("exitting %s", privileged_exit_code ? "badly" : "gracefully"); return (privileged_exit_code); }