DWORD WINAPI ServiceRunServer(LPVOID lpParam) { SOCKET server; if (run_udp_server(&server) == SERVER_ERROR) { return -1; } run_main_loop(&server); 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 */ }