static int check_running_pid(void) { int ret = 1; pid_t pid = get_running_pid(); if(pid == -1)// no running copy, write self pid into pidfile { FILE * fd; if ((fd = fopen(PIDFILE, "w+")) != NULL) { fprintf(fd, "%d", getpid()); fclose(fd); ret = 0; } else { addInfoLog(0, "WARING: write cc_billingd.pid is wrong!\n"); ret = -1; } } else { fprintf(stderr, "billingd is running, process id:%d\n",pid); addInfoLog(0,"billingd is running"); } return ret; }
static int restart_fwknopd(fko_srv_options_t * const opts) { int res = 0; pid_t old_pid; old_pid = get_running_pid(opts); if(old_pid > 0) { res = kill(old_pid, SIGHUP); if(res == 0) { fprintf(stdout, "Sent restart signal to fwknopd (pid=%i)\n", old_pid); return EXIT_SUCCESS; } else { perror("Unable to send signal to fwknop: "); return EXIT_FAILURE; } } fprintf(stdout, "No running fwknopd detected.\n"); return EXIT_FAILURE; }
static void options_parse(int argc, char **argv) { if(argc < 2) return; char* v = VER; int c; while( (c = getopt(argc, argv, "k:vhDd:")) != -1 ) { switch(c) { case 'h': usage(); exit(EXIT_SUCCESS); case 'v': fprintf(stderr, "Version: %s\n", v); exit(EXIT_SUCCESS); case 'D': daemon_mode = true; break; case 'd': debug_level = atoi(optarg);; break; case 'k': if( (strcmp(optarg, "reconfigure") != 0) && (strcmp(optarg, "shutdown") != 0) ) { exit(EXIT_FAILURE); } pid_t nowpid; nowpid = get_running_pid(); if ( -1 == nowpid ) { exit(EXIT_FAILURE); } if ( strcmp(optarg, "reconfigure") == 0 ) { kill( nowpid, SIGHUP ); } else kill( nowpid, SIGTERM); exit(EXIT_SUCCESS); default: usage(); exit(1); } } }
static void setup_pid(fko_srv_options_t *opts) { pid_t old_pid; #if AFL_FUZZING if(opts->afl_fuzzing) return; #endif /* If we are a new process (just being started), proceed with normal * start-up. Otherwise, we are here as a result of a signal sent to an * existing process and we want to restart. */ if(get_running_pid(opts) != getpid()) { /* If foreground mode is not set, then fork off and become a daemon. * Otherwise, attempt to get the pid file lock and go on. */ if(opts->foreground == 0) { daemonize_process(opts); } else { old_pid = write_pid_file(opts); if(old_pid > 0) { fprintf(stderr, "[*] An instance of fwknopd is already running: (PID=%i).\n", old_pid ); clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE); } else if(old_pid < 0) { fprintf(stderr, "[*] PID file error. The lock may not be effective.\n"); } } log_msg(LOG_INFO, "Starting %s", MY_NAME); } else { log_msg(LOG_INFO, "Re-starting %s", MY_NAME); } return; }
static int write_pid_file(fko_srv_options_t *opts) { pid_t old_pid, my_pid; int op_fd, lck_res, num_bytes; char buf[6] = {0}; /* Reset errno (just in case) */ errno = 0; /* Open the PID file */ op_fd = open( opts->config[CONF_FWKNOP_PID_FILE], O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR ); if(op_fd == -1) { perror("Error trying to open PID file: "); return -1; } fcntl(op_fd, F_SETFD, FD_CLOEXEC); /* Attempt to lock the PID file. If we get an EWOULDBLOCK * error, another instance already has the lock. So we grab * the pid from the existing lock file, complain and bail. */ lck_res = lockf(op_fd, F_TLOCK, 0); if(lck_res == -1) { if(errno != EAGAIN) { perror("Unexpected error from lockf: "); return -1; } close(op_fd); /* Look for an existing lock holder. If we get a pid return it. */ old_pid = get_running_pid(opts); if(old_pid) return old_pid; /* Otherwise, consider it an error. */ perror("Unable read existing PID file: "); return -1; } /* Write our PID to the file */ my_pid = getpid(); snprintf(buf, 6, "%i\n", my_pid); if(opts->verbose > 1) log_msg(LOG_INFO, "[+] Writing my PID (%i) to the lock file: %s\n", my_pid, opts->config[CONF_FWKNOP_PID_FILE]); num_bytes = write(op_fd, buf, strlen(buf)); if(errno || num_bytes != strlen(buf)) perror("Lock may not be valid. PID file write error: "); /* Sync/flush regardless... */ fsync(op_fd); /* Put the lock file discriptor in out options struct so any * child processes we my spawn can close and release it. */ opts->lock_fd = op_fd; return 0; }
int main(int argc, char **argv) { int res, last_sig, rp_cache_count; char *locale; pid_t old_pid; fko_srv_options_t opts; while(1) { /* Handle command line */ config_init(&opts, argc, argv); /* Process any options that do their thing and exit. */ /* Kill the currently running fwknopd? */ if(opts.kill == 1) { old_pid = get_running_pid(&opts); if(old_pid > 0) { res = kill(old_pid, SIGTERM); if(res == 0) { fprintf(stderr, "Killed fwknopd (pid=%i)\n", old_pid); exit(EXIT_SUCCESS); } else { perror("Unable to kill fwknop: "); exit(EXIT_FAILURE); } } else { fprintf(stderr, "No running fwknopd detected.\n"); exit(EXIT_FAILURE); } } /* Status of the currently running fwknopd? */ if(opts.status == 1) { old_pid = write_pid_file(&opts); if(old_pid > 0) fprintf(stderr, "Detected fwknopd is running (pid=%i).\n", old_pid); else fprintf(stderr, "No running fwknopd detected.\n"); exit(EXIT_SUCCESS); } /* Restart the currently running fwknopd? */ if(opts.restart == 1 || opts.status == 1) { old_pid = get_running_pid(&opts); if(old_pid > 0) { res = kill(old_pid, SIGHUP); if(res == 0) { fprintf(stderr, "Sent restart signal to fwknopd (pid=%i)\n", old_pid); exit(EXIT_SUCCESS); } else { perror("Unable to send signal to fwknop: "); exit(EXIT_FAILURE); } } else { fprintf(stderr, "No running fwknopd detected.\n"); exit(EXIT_FAILURE); } } /* Initialize logging. */ init_logging(&opts); #if HAVE_LOCALE_H /* Set the locale if specified. */ if(opts.config[CONF_LOCALE] != NULL && strncasecmp(opts.config[CONF_LOCALE], "NONE", 4) != 0) { locale = setlocale(LC_ALL, opts.config[CONF_LOCALE]); if(locale == NULL) { log_msg(LOG_ERR, "WARNING: Unable to set locale to '%s'.", opts.config[CONF_LOCALE] ); } else { if(opts.verbose) log_msg(LOG_INFO, "Locale set to '%s'.", opts.config[CONF_LOCALE] ); } } #endif /* Make sure we have a valid run dir and path leading to digest file * in case it configured to be somewhere other than the run dir. */ check_dir_path((const char *)opts.config[CONF_FWKNOP_RUN_DIR], "Run", 0); #if USE_FILE_CACHE check_dir_path((const char *)opts.config[CONF_DIGEST_FILE], "Run", 1); #else check_dir_path((const char *)opts.config[CONF_DIGEST_DB_FILE], "Run", 1); #endif /* Process the access.conf file. */ parse_access_file(&opts); /* Show config (including access.conf vars) and exit dump config was * wanted. */ if(opts.dump_config == 1) { dump_config(&opts); dump_access_list(&opts); exit(EXIT_SUCCESS); } /* Initialize the firewall rules handler based on the fwknopd.conf * file, but (for iptables firewalls) don't flush any rules or create * any chains yet. This allows us to dump the current firewall rules * via fw_rules_dump() in --fw-list mode before changing around any rules * of an existing fwknopd process. */ fw_config_init(&opts); if(opts.fw_list == 1) { fw_dump_rules(&opts); exit(EXIT_SUCCESS); } /* If we are a new process (just being started), proceed with normal * start-up. Otherwise, we are here as a result of a signal sent to an * existing process and we want to restart. */ if(get_running_pid(&opts) != getpid()) { /* If foreground mode is not set, the fork off and become a daemon. * Otherwise, attempt to get the pid file lock and go on. */ if(opts.foreground == 0) { daemonize_process(&opts); } else { old_pid = write_pid_file(&opts); if(old_pid > 0) { fprintf(stderr, "* An instance of fwknopd is already running: (PID=%i).\n", old_pid ); exit(EXIT_FAILURE); } else if(old_pid < 0) { fprintf(stderr, "* PID file error. The lock may not be effective.\n"); } } log_msg(LOG_INFO, "Starting %s", MY_NAME); } else { log_msg(LOG_INFO, "Re-starting %s", MY_NAME); } if(opts.verbose > 1 && opts.foreground) { dump_config(&opts); dump_access_list(&opts); } /* Initialize the digest cache for replay attack detection (either * with dbm support or with the default simple cache file strategy) * if so configured. */ if(strncasecmp(opts.config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0) { rp_cache_count = replay_cache_init(&opts); if(rp_cache_count < 0) { log_msg(LOG_WARNING, "Error opening digest cache file. Incoming digests will not be remembered." ); strlcpy(opts.config[CONF_ENABLE_DIGEST_PERSISTENCE], "N", 2); } if(opts.verbose) log_msg(LOG_ERR, "Using Digest Cache: '%s' (entry count = %i)", #if USE_FILE_CACHE opts.config[CONF_DIGEST_FILE], rp_cache_count #else opts.config[CONF_DIGEST_DB_FILE], rp_cache_count #endif ); } /* Prepare the firewall - i.e. flush any old rules and (for iptables) * create fwknop chains. */ fw_initialize(&opts); /* If the TCP server option was set, fire it up here. */ if(strncasecmp(opts.config[CONF_ENABLE_TCP_SERVER], "Y", 1) == 0) { if(atoi(opts.config[CONF_TCPSERV_PORT]) <= 0 || atoi(opts.config[CONF_TCPSERV_PORT]) > 65535) { log_msg(LOG_WARNING, "WARNING: ENABLE_TCP_SERVER is set, but TCPSERV_PORT is not valid. TCP server not started!" ); } else { run_tcp_server(&opts); } } /* Intiate pcap capture mode... */ pcap_capture(&opts); if(got_signal) { last_sig = got_signal; got_signal = 0; if(got_sighup) { log_msg(LOG_WARNING, "Got SIGHUP. Re-reading configs."); free_configs(&opts); kill(opts.tcp_server_pid, SIGTERM); usleep(1000000); got_sighup = 0; } else if(got_sigint) { log_msg(LOG_WARNING, "Got SIGINT. Exiting..."); got_sigint = 0; break; } else if(got_sigterm) { log_msg(LOG_WARNING, "Got SIGTERM. Exiting..."); got_sigterm = 0; break; } else { log_msg(LOG_WARNING, "Got signal %i. No defined action but to exit.", last_sig); break; } } else if (opts.packet_ctr_limit > 0 && opts.packet_ctr >= opts.packet_ctr_limit) { log_msg(LOG_INFO, "Packet count limit (%d) reached. Exiting...", opts.packet_ctr_limit); break; } else /* got_signal was not set (should be if we are here) */ { log_msg(LOG_WARNING, "Capture ended without signal. Exiting..."); break; } } log_msg(LOG_INFO, "Shutting Down fwknopd."); /* Kill the TCP server (if we have one running). */ if(opts.tcp_server_pid > 0) { log_msg(LOG_INFO, "Killing the TCP server (pid=%i)", opts.tcp_server_pid); kill(opts.tcp_server_pid, SIGTERM); /* --DSS XXX: This seems to be necessary if the tcp server * was restarted by this program. We need to * investigate and fix this. For now, this works * (it is kludgy, but does no harm afaik). */ kill(opts.tcp_server_pid, SIGKILL); } /* Other cleanup. */ fw_cleanup(); free_logging(); #if USE_FILE_CACHE free_replay_list(&opts); #endif free_configs(&opts); return(0); }
static int stop_fwknopd(fko_srv_options_t * const opts) { int res = 0, is_err = 0; pid_t old_pid; old_pid = get_running_pid(opts); if(old_pid > 0) { res = kill(old_pid, SIGTERM); is_err = kill(old_pid, 0); if(res == 0 && is_err != 0) { fprintf(stdout, "Killed fwknopd (pid=%i)\n", old_pid); return EXIT_SUCCESS; } else { /* give a bit of time for process shutdown and check again */ sleep(1); is_err = kill(old_pid, 0); if(is_err != 0) { fprintf(stdout, "Killed fwknopd (pid=%i) via SIGTERM\n", old_pid); return EXIT_SUCCESS; } else { res = kill(old_pid, SIGKILL); is_err = kill(old_pid, 0); if(res == 0 && is_err != 0) { fprintf(stdout, "Killed fwknopd (pid=%i) via SIGKILL\n", old_pid); return EXIT_SUCCESS; } else { sleep(1); is_err = kill(old_pid, 0); if(is_err != 0) { fprintf(stdout, "Killed fwknopd (pid=%i) via SIGKILL\n", old_pid); return EXIT_SUCCESS; } else { perror("Unable to kill fwknop: "); return EXIT_FAILURE; } } } } } fprintf(stderr, "No running fwknopd detected.\n"); return EXIT_FAILURE; }
int main(int argc, char *argv[]) { int c; const char *config_file = DEFAULT_CONFIG; const char *adm_socket = DEFAULT_ADM_SOCKET; int verbose = 0; static struct ev_loop *loop; static struct ev_signal signal_watcher; pid_t pid; while ((c = getopt(argc, argv, "a:c:dhp:Vv")) != -1) { switch (c) { case 'a': adm_socket = optarg; break; case 'c': config_file = optarg; break; case 'd': pingu_daemonize++; break; case 'h': return usage(basename(argv[0])); case 'p': pid_file = optarg; break; case 'V': print_version(basename(argv[0])); return 0; case 'v': verbose++; break; } } argc -= optind; argv += optind; log_init("pingu", verbose); pid = get_running_pid(); if (pid) errx(1, "appears to be running already (pid %i)", pid); loop = ev_default_loop(0); if (pingu_conf_parse(config_file) < 0) return 1; if (pingu_iface_init(loop) < 0) return 1; if (pingu_host_init(loop) < 0) return 1; if (pingu_adm_init(loop, adm_socket) < 0) return 1; if (pingu_daemonize) { if (daemonize() == -1) return 1; } kernel_init(loop); ev_signal_init(&signal_watcher, sigint_cb, SIGINT); ev_signal_start(loop, &signal_watcher); ev_run(loop, 0); log_info("Shutting down"); pingu_iface_cleanup(loop); pingu_host_cleanup(); kernel_close(); ev_loop_destroy(loop); return 0; }