int main() { struct rlimit rl; rl.rlim_max = rl.rlim_cur = 1024*64; if (setrlimit(RLIMIT_NOFILE, &rl) < -1) { return -1; } fiber_mutex_init(&mtx); memset((char*)sharedArr, 0, 64); const char *server_ip = "127.0.0.1"; struct Scheduler *sch = create_scheduler(8); if (sch == NULL) return 0; struct TcpServer *server = create_tcp_server(server_ip, 12400, data_processor); if (server == NULL) return 0; start_scheduler(sch); run_tcp_server(sch, server); return 0; }
/* The nfq capture routine. */ int nfq_capture(fko_srv_options_t *opts) { int res, child_pid, fd_flags; int nfq_errcnt = 0; int pending_break = 0; int status; char nfq_buf[1500]; int chk_rm_all = 0; /* Netfilter-related handles */ int nfq_fd; struct nfq_handle *nfq_h; struct nfq_q_handle *nfq_qh; struct nfnl_handle *nfq_nh; nfq_h = nfq_open(); if (!nfq_h) { log_msg(LOG_ERR, "[*] nfq_open error\n"); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } /* Unbind existing nf_queue handler for AF_INET (if any) */ res = nfq_unbind_pf(nfq_h, AF_INET); if (res < 0) { log_msg(LOG_WARNING, "[*] Error during nfq_unbind_pf() error: %d\n", res); } /* Bind the given queue connection handle to process packets. */ res = nfq_bind_pf(nfq_h, AF_INET); if ( res < 0) { log_msg(LOG_ERR, "Error during nfq_bind_pf(), error: %d\n", res); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } /* Create queue */ nfq_qh = nfq_create_queue(nfq_h, atoi(opts->config[CONF_NFQ_QUEUE_NUMBER]), &process_nfq_packet, opts); if (!nfq_qh) { log_msg(LOG_ERR, "Error during nfq_create_queue()\n"); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } /* Set the amount of data to be copied to userspace for each packet * queued to the given queue. */ if (nfq_set_mode(nfq_qh, NFQNL_COPY_PACKET, 0xffff) < 0) { log_msg(LOG_ERR, "Can't set packet_copy mode\n"); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } /* Get the netlink handle associated with the given queue connection * handle. Then use it to get the file descriptor we will use for * receiving the queued packets */ nfq_nh = nfq_nfnlh(nfq_h); nfq_fd = nfnl_fd(nfq_nh); /* Set our nfq handle nonblocking mode. * */ if((fd_flags = fcntl(nfq_fd, F_GETFL, 0)) < 0) { log_msg(LOG_ERR, "nfq_capture: fcntl F_GETFL error: %s", strerror(errno)); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } fd_flags |= O_NONBLOCK; if(fcntl(nfq_fd, F_SETFL, fd_flags) < 0) { log_msg(LOG_ERR, "nfq_capture: fcntl F_SETFL error setting O_NONBLOCK: %s", strerror(errno)); exit(EXIT_FAILURE); } /* Initialize our signal handlers. You can check the return value for * the number of signals that were *not* set. Those that were not set * will be listed in the log/stderr output. */ if(set_sig_handlers() > 0) log_msg(LOG_ERR, "Errors encountered when setting signal handlers."); log_msg(LOG_INFO, "Starting fwknopd main event loop."); /* Jump into our home-grown packet cature loop. */ while(1) { /* If we got a SIGCHLD and it was the tcp server, then handle it here. ** XXX: --DSS Do we need this here? I'm guessing we would not be using ** the TCP server in NF_QUEUE capture mode. */ if(got_sigchld) { if(opts->tcp_server_pid > 0) { child_pid = waitpid(0, &status, WNOHANG); if(child_pid == opts->tcp_server_pid) { if(WIFSIGNALED(status)) log_msg(LOG_WARNING, "TCP server got signal: %i", WTERMSIG(status)); log_msg(LOG_WARNING, "TCP server exited with status of %i. Attempting restart.", WEXITSTATUS(status) ); opts->tcp_server_pid = 0; /* Attempt to restart tcp server ? */ usleep(1000000); run_tcp_server(opts); } } got_sigchld = 0; } /* Any signal except USR1, USR2, and SIGCHLD mean break the loop. */ if(got_signal != 0) { if(got_sigint || got_sigterm || got_sighup) { pending_break = 1; } else if(got_sigusr1 || got_sigusr2) { /* Not doing anything with these yet. */ got_sigusr1 = got_sigusr2 = 0; got_signal = 0; } else got_signal = 0; } res = recv(nfq_fd, nfq_buf, sizeof(nfq_buf), 0); /* Count processed packets */ if(res > 0) { nfq_handle_packet(nfq_h, nfq_buf, res); /* Count the set of processed packets (nfq_dispatch() return * value) - we use this as a comparison for --packet-limit regardless * of SPA packet validity at this point. */ opts->packet_ctr += res; if (opts->packet_ctr_limit && opts->packet_ctr >= opts->packet_ctr_limit) { log_msg(LOG_WARNING, "* Incoming packet count limit of %i reached", opts->packet_ctr_limit ); pending_break = 1; } } /* If there was an error, complain and go on (to an extent before * giving up). */ else if(res < 0 && errno != EAGAIN) { log_msg(LOG_ERR, "[*] Error reading from nfq descriptor: %s", strerror); if(nfq_errcnt++ > MAX_NFQ_ERRORS_BEFORE_BAIL) { log_msg(LOG_ERR, "[*] %i consecutive nfq errors. Giving up", nfq_errcnt ); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } } else if(pending_break == 1 || res == -2) { log_msg(LOG_INFO, "Gracefully leaving the fwknopd event loop."); break; } else nfq_errcnt = 0; /* Check for any expired firewall rules and deal with them. */ check_firewall_rules(opts, chk_rm_all); usleep(atoi(opts->config[CONF_NFQ_LOOP_SLEEP])); } nfq_destroy_queue(nfq_qh); nfq_close(nfq_h); 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); }
/* The pcap capture routine. */ int pcap_capture(fko_srv_options_t *opts) { pcap_t *pcap; char errstr[PCAP_ERRBUF_SIZE] = {0}; struct bpf_program fp; int res; int pcap_errcnt = 0; int pending_break = 0; int promisc = 0; int set_direction = 1; int pcap_file_mode = 0; int status; int useconds; int pcap_dispatch_count; int max_sniff_bytes; int is_err; pid_t child_pid; #if FIREWALL_IPFW time_t now; #endif useconds = strtol_wrapper(opts->config[CONF_PCAP_LOOP_SLEEP], 0, RCHK_MAX_PCAP_LOOP_SLEEP, NO_EXIT_UPON_ERR, &is_err); if(is_err != FKO_SUCCESS) { log_msg(LOG_ERR, "[*] invalid PCAP_LOOP_SLEEP_value"); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } max_sniff_bytes = strtol_wrapper(opts->config[CONF_MAX_SNIFF_BYTES], 0, RCHK_MAX_SNIFF_BYTES, NO_EXIT_UPON_ERR, &is_err); if(is_err != FKO_SUCCESS) { log_msg(LOG_ERR, "[*] invalid MAX_SNIFF_BYTES"); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } /* Set promiscuous mode if ENABLE_PCAP_PROMISC is set to 'Y'. */ if(strncasecmp(opts->config[CONF_ENABLE_PCAP_PROMISC], "Y", 1) == 0) promisc = 1; if(opts->config[CONF_PCAP_FILE] != NULL && opts->config[CONF_PCAP_FILE][0] != '\0') pcap_file_mode = 1; if(pcap_file_mode == 1) { log_msg(LOG_INFO, "Reading pcap file: %s", opts->config[CONF_PCAP_FILE]); pcap = pcap_open_offline(opts->config[CONF_PCAP_FILE], errstr); if(pcap == NULL) { log_msg(LOG_ERR, "[*] pcap_open_offline() error: %s", errstr); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } } else { log_msg(LOG_INFO, "Sniffing interface: %s", opts->config[CONF_PCAP_INTF]); pcap = pcap_open_live(opts->config[CONF_PCAP_INTF], max_sniff_bytes, promisc, 100, errstr ); if(pcap == NULL) { log_msg(LOG_ERR, "[*] pcap_open_live() error: %s", errstr); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } } /* Set pcap filters, if any. */ if (opts->config[CONF_PCAP_FILTER][0] != '\0') { if(pcap_compile(pcap, &fp, opts->config[CONF_PCAP_FILTER], 1, 0) == -1) { log_msg(LOG_ERR, "[*] Error compiling pcap filter: %s", pcap_geterr(pcap) ); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } if(pcap_setfilter(pcap, &fp) == -1) { log_msg(LOG_ERR, "[*] Error setting pcap filter: %s", pcap_geterr(pcap) ); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } log_msg(LOG_INFO, "PCAP filter is: '%s'", opts->config[CONF_PCAP_FILTER]); pcap_freecode(&fp); } /* Determine and set the data link encapsulation offset. */ switch(pcap_datalink(pcap)) { case DLT_EN10MB: opts->data_link_offset = 14; break; #if defined(__linux__) case DLT_LINUX_SLL: opts->data_link_offset = 16; break; #elif defined(__OpenBSD__) case DLT_LOOP: set_direction = 0; opts->data_link_offset = 4; break; #endif case DLT_NULL: set_direction = 0; opts->data_link_offset = 4; break; default: opts->data_link_offset = 0; break; } /* We are only interested on seeing packets coming into the interface. */ if ((opts->pcap_any_direction == 0) && (set_direction == 1) && (pcap_file_mode == 0) && (pcap_setdirection(pcap, PCAP_D_IN) < 0)) if(opts->verbose) log_msg(LOG_WARNING, "[*] Warning: pcap error on setdirection: %s.", pcap_geterr(pcap)); /* Set our pcap handle nonblocking mode. * * NOTE: This is simply set to 0 for now until we find a need * to actually use this mode (which when set on a FreeBSD * system, it silently breaks the packet capture). */ if((pcap_file_mode == 0) && (pcap_setnonblock(pcap, DEF_PCAP_NONBLOCK, errstr)) == -1) { log_msg(LOG_ERR, "[*] Error setting pcap nonblocking to %i: %s", 0, errstr ); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } pcap_dispatch_count = strtol_wrapper(opts->config[CONF_PCAP_DISPATCH_COUNT], 0, RCHK_MAX_PCAP_DISPATCH_COUNT, NO_EXIT_UPON_ERR, &is_err); if(is_err != FKO_SUCCESS) { log_msg(LOG_ERR, "[*] invalid PCAP_DISPATCH_COUNT"); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } /* Initialize our signal handlers. You can check the return value for * the number of signals that were *not* set. Those that were not set * will be listed in the log/stderr output. */ if(set_sig_handlers() > 0) log_msg(LOG_ERR, "Errors encountered when setting signal handlers."); log_msg(LOG_INFO, "Starting fwknopd main event loop."); /* Jump into our home-grown packet cature loop. */ while(1) { /* If we got a SIGCHLD and it was the tcp server, then handle it here. */ if(got_sigchld) { if(opts->tcp_server_pid > 0) { child_pid = waitpid(0, &status, WNOHANG); if(child_pid == opts->tcp_server_pid) { if(WIFSIGNALED(status)) log_msg(LOG_WARNING, "TCP server got signal: %i", WTERMSIG(status)); log_msg(LOG_WARNING, "TCP server exited with status of %i. Attempting restart.", WEXITSTATUS(status) ); opts->tcp_server_pid = 0; /* Attempt to restart tcp server ? */ usleep(1000000); run_tcp_server(opts); } } got_sigchld = 0; } /* Any signal except USR1, USR2, and SIGCHLD mean break the loop. */ if(got_signal != 0) { if(got_sigint || got_sigterm || got_sighup) { pcap_breakloop(pcap); pending_break = 1; } else if(got_sigusr1 || got_sigusr2) { /* Not doing anything with these yet. */ got_sigusr1 = got_sigusr2 = 0; got_signal = 0; } else got_signal = 0; } res = pcap_dispatch(pcap, pcap_dispatch_count, (pcap_handler)&process_packet, (unsigned char *)opts); /* Count processed packets */ if(res > 0) { if(opts->foreground == 1 && opts->verbose > 2) log_msg(LOG_DEBUG, "pcap_dispatch() processed: %d packets", res); /* Count the set of processed packets (pcap_dispatch() return * value) - we use this as a comparison for --packet-limit regardless * of SPA packet validity at this point. */ opts->packet_ctr += res; if (opts->packet_ctr_limit && opts->packet_ctr >= opts->packet_ctr_limit) { log_msg(LOG_WARNING, "* Incoming packet count limit of %i reached", opts->packet_ctr_limit ); pcap_breakloop(pcap); pending_break = 1; } } /* If there was an error, complain and go on (to an extent before * giving up). */ else if(res == -1) { log_msg(LOG_ERR, "[*] Error from pcap_dispatch: %s", pcap_geterr(pcap) ); if(pcap_errcnt++ > MAX_PCAP_ERRORS_BEFORE_BAIL) { log_msg(LOG_ERR, "[*] %i consecutive pcap errors. Giving up", pcap_errcnt ); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } } else if(pending_break == 1 || res == -2) { /* pcap_breakloop was called, so we bail. */ log_msg(LOG_INFO, "Gracefully leaving the fwknopd event loop."); break; } else pcap_errcnt = 0; /* Check for any expired firewall rules and deal with them. */ check_firewall_rules(opts); #if FIREWALL_IPFW /* Purge expired rules that no longer have any corresponding * dynamic rules. */ if(opts->fw_config->total_rules > 0) { time(&now); if(opts->fw_config->last_purge < (now - opts->fw_config->purge_interval)) { ipfw_purge_expired_rules(opts); opts->fw_config->last_purge = now; } } #endif usleep(useconds); } pcap_close(pcap); return(0); }
int main(int argc, char **argv) { fko_srv_options_t opts; int depth = 0; while(1) { /* Handle command line */ //处理启动参数。 config_init(&opts, argc, argv); #if HAVE_LIBFIU /* Set any fault injection points early */ enable_fault_injections(&opts); #endif /* Process any options that do their thing and exit. */ /* Kill the currently running fwknopd process? */ if(opts.kill == 1) clean_exit(&opts, NO_FW_CLEANUP, stop_fwknopd(&opts)); /* Status of the currently running fwknopd process? */ if(opts.status == 1) clean_exit(&opts, NO_FW_CLEANUP, status_fwknopd(&opts)); /* Restart the currently running fwknopd process? */ if(opts.restart == 1) clean_exit(&opts, NO_FW_CLEANUP, restart_fwknopd(&opts)); /* Initialize logging. */ init_logging(&opts); /* Update the verbosity level for the log module */ log_set_verbosity(LOG_DEFAULT_VERBOSITY + opts.verbose); #if HAVE_LOCALE_H /* Set the locale if specified. */ set_locale(&opts); #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. */ if(!opts.afl_fuzzing && ! check_dir_path((const char *)opts.config[CONF_FWKNOP_RUN_DIR], "Run", 0)) clean_exit(&opts, NO_FW_CLEANUP, EXIT_FAILURE); /* 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. */ if(fw_config_init(&opts) != 1) clean_exit(&opts, NO_FW_CLEANUP, EXIT_FAILURE); if(opts.fw_list == 1 || opts.fw_list_all == 1) { fw_dump_rules(&opts); clean_exit(&opts, NO_FW_CLEANUP, EXIT_SUCCESS); } if(opts.fw_flush == 1) { fprintf(stdout, "Deleting any existing firewall rules...\n"); clean_exit(&opts, FW_CLEANUP, EXIT_SUCCESS); } if (opts.config[CONF_ACCESS_FOLDER] != NULL) //If we have an access folder, process it { if (parse_access_folder(&opts, opts.config[CONF_ACCESS_FOLDER], &depth) != EXIT_SUCCESS) { clean_exit(&opts, NO_FW_CLEANUP, EXIT_FAILURE); } } /* Process the access.conf file, but only if no access.conf folder was specified. */ //读入access.conf中的数据。 else if (parse_access_file(&opts, opts.config[CONF_ACCESS_FILE], &depth) != EXIT_SUCCESS) { clean_exit(&opts, NO_FW_CLEANUP, EXIT_FAILURE); } /* We must have at least one valid access stanza at this point */ //检查有没有合法的stanza。 if(! valid_access_stanzas(opts.acc_stanzas)) { log_msg(LOG_ERR, "Fatal, could not find any valid access.conf stanzas"); clean_exit(&opts, NO_FW_CLEANUP, EXIT_FAILURE); } /* Show config (including access.conf vars) and exit dump config was * wanted. */ if(opts.dump_config == 1) { dump_config(&opts); dump_access_list(&opts); clean_exit(&opts, NO_FW_CLEANUP, EXIT_SUCCESS); } /* Now is the right time to bail if we're just parsing the configs */ if(opts.exit_after_parse_config) { log_msg(LOG_INFO, "Configs parsed, exiting."); clean_exit(&opts, NO_FW_CLEANUP, EXIT_SUCCESS); } /* Acquire pid, become a daemon or run in the foreground, write pid * to pid file. */ if(! opts.exit_parse_digest_cache) setup_pid(&opts); 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. */ init_digest_cache(&opts); if(opts.exit_parse_digest_cache) { log_msg(LOG_INFO, "Digest cache parsed, exiting."); clean_exit(&opts, NO_FW_CLEANUP, EXIT_SUCCESS); } #if AFL_FUZZING /* SPA data from STDIN. */ if(opts.afl_fuzzing) { if(opts.config[CONF_AFL_PKT_FILE] != 0x0) { afl_enc_pkt_from_file(&opts); } else { afl_pkt_from_stdin(&opts); } } #endif /* Prepare the firewall - i.e. flush any old rules and (for iptables) * create fwknop chains. */ if(!opts.test && opts.enable_fw && (fw_initialize(&opts) != 1)) clean_exit(&opts, FW_CLEANUP, EXIT_FAILURE); /* If we are to acquire SPA data via a UDP socket, start it up here. */ //启动UDP监听。 if(opts.enable_udp_server || strncasecmp(opts.config[CONF_ENABLE_UDP_SERVER], "Y", 1) == 0) { if(run_udp_server(&opts) < 0) { log_msg(LOG_ERR, "Fatal run_udp_server() error"); clean_exit(&opts, FW_CLEANUP, EXIT_FAILURE); } else { break; } } /* If the TCP server option was set, fire it up here. Note that in * this mode, fwknopd still acquires SPA packets via libpcap. If you * want to use UDP only without the libpcap dependency, then fwknop * needs to be compiled with --enable-udp-server. Note that the UDP * server can be run even when fwknopd links against libpcap as well, * but there is no reason to link against it if SPA packets are * always going to be acquired via a UDP socket. */ if(strncasecmp(opts.config[CONF_ENABLE_TCP_SERVER], "Y", 1) == 0) { if(run_tcp_server(&opts) < 0) { log_msg(LOG_ERR, "Fatal run_tcp_server() error"); clean_exit(&opts, FW_CLEANUP, EXIT_FAILURE); } } #if USE_LIBPCAP /* Intiate pcap capture mode... */ if(!opts.enable_udp_server && strncasecmp(opts.config[CONF_ENABLE_UDP_SERVER], "N", 1) == 0) { pcap_capture(&opts); } #endif /* Deal with any signals that we've received and break out * of the loop for any terminating signals */ if(handle_signals(&opts) == 1) 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); } clean_exit(&opts, FW_CLEANUP, EXIT_SUCCESS); return(EXIT_SUCCESS); /* This never gets called */ }