static void fatal( int err, char *param) { warn(err, param); config_unload(); exit(err); }
static void cleanup_control(control_t *control) { assert(control != NULL); assert(control->reply); expbuf_clear(control->reply); expbuf_free(control->reply); free(control->reply); control->reply = NULL; if (control->entries) { config_unload(control); } assert(control->req == NULL); assert(control->rqsvc == NULL); assert(control->risp == NULL); assert(control->sigint_event == NULL); assert(control->sighup_event == NULL); }
// print usage to stdout for the user void printUsage( char **argv) { fprintf(stderr, "Usage:\n"); fprintf(stderr, " %s OBJECT_TYPE arg1=value arg2=value arg3=value\n", argv[0]); fprintf(stderr, "\n"); fprintf(stderr, "where OBJECT_TYPE is one of the following: \n"); fprintf(stderr, " (CERT, CRL, ROA or MANIFEST)\n"); fprintf(stderr, "and argument/value pairs are based upon the object type\n"); fprintf(stderr, "\n"); fprintf(stderr, "options:\n"); fprintf(stderr, "\t-f\tread config file for additional argument/value pairs (cmd line takes precedence)\n"); fprintf(stderr, "\t-t\tuse specified file template rather than the default\n"); fprintf(stderr, "\t-h\tprint this usage\n"); config_unload(); exit(0); }
/* * create_object parse the object fields from the command line and call the * appropriate object creator with a table of fields filled in. */ int main( int argc, char **argv) { int ret = 0; int parse_err = 0; int index = 1; int c; char *obj_type; char *configFile = NULL; extern char *optarg; struct object_field *table; OPEN_LOG("create_object", LOG_USER); if (!my_config_load()) { LOG(LOG_ERR, "can't load configuration"); return EXIT_FAILURE; } // parse options while ((c = getopt(argc, argv, "hf:t:")) != -1) { switch (c) { case 'h': printUsage(argv); break; case 'f': configFile = optarg; break; case 't': templateFile = optarg; break; case '?': printUsage(argv); break; default: fprintf(stderr, "Illegal Option\n"); printUsage(argv); break; } } index = optind; // remaining arguments if (configFile == NULL) fprintf(stdout, "No Config file\n"); if (index >= argc) fatal(INPUT_ARG_ERR, "No Object Type"); else obj_type = argv[index++]; if (strncasecmp(obj_type, "CERT", strlen("CERT")) == 0) { table = get_cert_field_table(); if (configFile != NULL) if (parse_config(configFile, table) != 0) { warn(INPUT_ARG_ERR, parse_errstr); parse_err = 1; } // parse and validate arguments, exit if either or both fail if (parse_args(argc, argv, index, table) != 0) { warn(INPUT_ARG_ERR, parse_errstr); parse_err = 1; } if (validate_table(table, validate_errstr, sizeof(validate_errstr)) != 0) fatal(MISSING_FIELDS, validate_errstr); // if no validation error but we did have a parse err - exit if (parse_err) { config_unload(); exit(INPUT_ARG_ERR); } ret = create_cert(table); // fprintf(stdout,"return from creating certificate %d\n", ret); } else if (strncasecmp(obj_type, "CRL", strlen("CRL")) == 0) { table = get_crl_field_table(); if (configFile != NULL) if (parse_config(configFile, table) != 0) { warn(INPUT_ARG_ERR, parse_errstr); parse_err = 1; } if (parse_args(argc, argv, index, table) != 0) { warn(INPUT_ARG_ERR, parse_errstr); parse_err = 1; } if (validate_table(table, validate_errstr, sizeof(validate_errstr)) != 0) fatal(MISSING_FIELDS, validate_errstr); // if no validation error but we did have a parse err - exit if (parse_err) { config_unload(); exit(INPUT_ARG_ERR); } ret = create_crl(table); } else if (strncasecmp(obj_type, "ROA", strlen("ROA")) == 0) { table = get_roa_field_table(); if (configFile != NULL) if (parse_config(configFile, table) != 0) { warn(INPUT_ARG_ERR, parse_errstr); parse_err = 1; } if (parse_args(argc, argv, index, table) != 0) fatal(INPUT_ARG_ERR, parse_errstr); if (validate_table(table, validate_errstr, sizeof(validate_errstr)) != 0) fatal(MISSING_FIELDS, validate_errstr); ret = create_roa(table); } else if (strncasecmp(obj_type, "MANIFEST", strlen("MANIFEST")) == 0) { table = get_man_field_table(); if (configFile != NULL) if (parse_config(configFile, table) != 0) { warn(INPUT_ARG_ERR, parse_errstr); parse_err = 1; } // parse arguments and validate table if (parse_args(argc, argv, index, table) != 0) warn(INPUT_ARG_ERR, parse_errstr); if (validate_table(table, validate_errstr, sizeof(validate_errstr)) != 0) fatal(MISSING_FIELDS, validate_errstr); ret = create_manifest(table); } else fatal(INPUT_ARG_ERR, argv[1]); config_unload(); exit(ret); }
int main( int argc, char **argv) { int ret = EXIT_SUCCESS; bool done_db_init = false; bool done_db_thread_init = false; dbconn * db = NULL; bool first_time; bool force_update = false; bool update_had_changes; serial_number_t previous_serial; serial_number_t current_serial; if (argc < 1 || argc > 2) { fprintf(stderr, "Usage: %s [<next serial number>]\n", argv[0]); fprintf(stderr, "\n"); fprintf(stderr, "The next serial number should only be specified in test mode.\n"); return EXIT_FAILURE; } OPEN_LOG("rtr-update", LOG_USER); if (!my_config_load()) { LOG(LOG_ERR, "can't load configuration"); return EXIT_FAILURE; } // initialize the database connection if (!db_init()) { LOG(LOG_ERR, "Could not initialize database program."); ret = EXIT_FAILURE; goto done; } done_db_init = true; if (!db_thread_init()) { LOG(LOG_ERR, "Could not initialize database thread."); ret = EXIT_FAILURE; goto done; } done_db_thread_init = true; db = db_connect_default(DB_CLIENT_RTR); if (db == NULL) { LOG(LOG_ERR, "Could not connect to the database, check your config " "file."); ret = EXIT_FAILURE; goto done; } if (!db_rtr_has_valid_session(db)) { return EXIT_FAILURE; } // Get the previous serial number. switch (db_rtr_get_latest_sernum(db, &previous_serial)) { case GET_SERNUM_SUCCESS: first_time = false; // previous_serial was set by db_rtr_get_latest_sernum break; case GET_SERNUM_NONE: first_time = true; // Set previous_serial to a pseudo-random number srandom((unsigned int)time(NULL)); previous_serial = (serial_number_t)random(); break; case GET_SERNUM_ERR: default: LOG(LOG_ERR, "Error finding latest serial number."); ret = EXIT_FAILURE; goto done; } if (!db_rtr_delete_incomplete_updates(db)) { LOG(LOG_ERR, "Error deleting incomplete updates."); ret = EXIT_FAILURE; goto done; } // Get/compute the current serial number. if (argc > 1) { force_update = true; if (sscanf(argv[1], "%" SCNSERIAL, ¤t_serial) != 1) { fprintf(stderr, "Error: next serial number must be a nonnegative integer\n"); return EXIT_FAILURE; } } else { // NOTE: this relies on unsigned integer wrap-around to zero current_serial = previous_serial + 1; } // Make sure we're not about to overwrite current_serial, create a // loop, or start a diverging history, even though these should be // *really* unlikely. if (!first_time && !db_rtr_good_serials(db, previous_serial, current_serial)) { if (argc > 1) { LOG(LOG_ERR, "Error: rtr_update is full or in an unusual state, " "or the specified next serial number already " "exists."); } else { LOG(LOG_ERR, "Error: rtr_update table is either full or in an " "unusual state."); } ret = EXIT_FAILURE; goto done; } if (!db_rtr_insert_full(db, current_serial)) { LOG(LOG_ERR, "Could not copy current RPKI state."); ret = EXIT_FAILURE; goto done; } if (!first_time && !db_rtr_insert_incremental(db, previous_serial, current_serial)) { LOG(LOG_ERR, "Could not compute incremental changes."); ret = EXIT_FAILURE; goto done; } if (first_time) { update_had_changes = true; } else { switch (db_rtr_has_incremental_changes(db, current_serial)) { case 1: update_had_changes = true; break; case 0: update_had_changes = false; break; case -1: default: LOG(LOG_ERR, "Error determining if there were any changes."); ret = EXIT_FAILURE; goto done; } } if (update_had_changes || force_update) { // Make the new serial number available for use. if ( !db_rtr_insert_update(db, current_serial, previous_serial, first_time)) { LOG(LOG_ERR, "Error making updates available."); ret = EXIT_FAILURE; goto done; } } else { LOG(LOG_INFO, "Data had no changes since the last update, so no update " "was made."); // The new data in rtr_full is useless, so delete it. if (!db_rtr_delete_full(db, current_serial)) { LOG(LOG_ERR, "Error deleting duplicate data in rtr_full."); ret = EXIT_FAILURE; goto done; } // there's nothing to delete from rtr_incremental } // clean up all the data no longer needed // save last two full updates so that no problems at transition // (with client still receiving data from previous one) // // NOTE: The order of these updates and deletes is important. // All data must be marked as unusable according to rtr_update // before it is deleted from rtr_full or rtr_incremental. if ( !db_rtr_ignore_old_full( db, current_serial, previous_serial) || !db_rtr_delete_old_full( db, current_serial, previous_serial) || !db_rtr_delete_old_update( db, current_serial, previous_serial) || !db_rtr_ignore_old_incremental(db) || !db_rtr_delete_old_incremental(db) || false) { LOG(LOG_ERR, "Error cleaning up old data."); ret = EXIT_FAILURE; goto done; } done: if (db != NULL) { db_disconnect(db); } if (done_db_thread_init) { db_thread_close(); } if (done_db_init) { db_close(); } config_unload(); CLOSE_LOG(); return ret; }
int main (int argc, char *argv[]) { struct pollfd *poll_fd; struct config etherpoke_conf; struct config_filter *filter_iter; struct session_data *pcap_session; struct option_data opt; char conf_errbuff[CONF_ERRBUF_SIZE]; char pcap_errbuff[PCAP_ERRBUF_SIZE]; struct pathname path_config; struct sigaction sa; #ifdef DBG_AVG_LOOP_SPEED clock_t clock_start; double clock_avg; #endif pid_t pid; int i, c, j, rval, syslog_flags, opt_index, filter_cnt, sock, poll_len; struct option opt_long[] = { { "", no_argument, NULL, '4' }, { "", no_argument, NULL, '6' }, { "hostname", required_argument, NULL, 't' }, { "daemon", no_argument, NULL, 'd' }, { "accept-max", required_argument, NULL, 'm' }, { "verbose", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { NULL, 0, NULL, 0 } }; sock = -1; poll_fd = NULL; pcap_session = NULL; exitno = EXIT_SUCCESS; syslog_flags = LOG_PID | LOG_PERROR; #ifdef DBG_AVG_LOOP_SPEED clock_avg = 0; #endif memset (&opt, 0, sizeof (struct option_data)); opt.accept_max = ACCEPT_MAX; opt.ip_version = AF_UNSPEC; memset (&path_config, 0, sizeof (struct pathname)); memset (ðerpoke_conf, 0, sizeof (struct config)); while ( (c = getopt_long (argc, argv, "46t:dm:Vhv", opt_long, &opt_index)) != -1 ){ switch ( c ){ case 'd': opt.daemon = 1; break; case 't': rval = hostformat_parse (optarg, opt.hostname, opt.port); if ( rval == -1 || strlen (opt.hostname) == 0 || strlen (opt.port) == 0 ){ fprintf (stderr, "%s: invalid hostname format (expects HOSTNAME:PORT)\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } opt.tcp_event = 1; break; case '4': opt.ip_version = AF_INET; break; case '6': opt.ip_version = AF_INET6; break; case 'm': rval = sscanf (optarg, "%u", &(opt.accept_max)); if ( rval < 1 || opt.accept_max == 0 ){ fprintf (stderr, "%s: invalid number for maximum connections\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } break; case 'V': opt.verbose = 1; break; case 'h': etherpoke_help (argv[0]); exitno = EXIT_SUCCESS; goto cleanup; case 'v': etherpoke_version (argv[0]); exitno = EXIT_SUCCESS; goto cleanup; default: etherpoke_help (argv[0]); exitno = EXIT_FAILURE; goto cleanup; } } // Check if there are some non-option arguments, these are treated as paths // to configuration files. if ( (argc - optind) == 0 ){ fprintf (stderr, "%s: configuration file not specified. Use '--help' to see usage information.\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } // Change working directory to match the dirname of the config file. rval = path_split (argv[optind], &path_config); if ( rval != 0 ){ fprintf (stderr, "%s: cannot split path to configuration file.\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } rval = chdir (path_config.dir); if ( rval == -1 ){ fprintf (stderr, "%s: cannot set working directory to '%s': %s\n", argv[0], path_config.dir, strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } // // Load configuration file // filter_cnt = config_load (ðerpoke_conf, path_config.base, conf_errbuff); if ( filter_cnt == -1 ){ fprintf (stderr, "%s: cannot load configuration file '%s': %s\n", argv[0], argv[optind], conf_errbuff); exitno = EXIT_FAILURE; goto cleanup; } else if ( filter_cnt == 0 ){ fprintf (stderr, "%s: nothing to do, no filters defined.\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } // Allocate enough memory for filters (+1 means that we are also allocating // space for listening socket). // NOTE: always allocate space for listening socket here, to move this // allocation inside the block below (where listening socket is actually // allocated) is not a good idea as more complex condition would have to be // used inside the main loop. poll_len = filter_cnt + 1; if ( opt.tcp_event ){ struct addrinfo *host_addr, addr_hint; int opt_val; // Increase poll size to accommodate socket descriptors for clients. poll_len += opt.accept_max; host_addr = NULL; memset (&addr_hint, 0, sizeof (struct addrinfo)); // Setup addrinfo hints addr_hint.ai_family = opt.ip_version; addr_hint.ai_socktype = SOCK_STREAM; addr_hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; rval = getaddrinfo (opt.hostname, opt.port, &addr_hint, &host_addr); if ( rval != 0 ){ fprintf (stderr, "%s: hostname resolve failed: %s\n", argv[0], gai_strerror (rval)); exitno = EXIT_FAILURE; goto cleanup; } sock = socket (host_addr->ai_family, host_addr->ai_socktype | SOCK_NONBLOCK, host_addr->ai_protocol); if ( sock == -1 ){ freeaddrinfo (host_addr); fprintf (stderr, "%s: cannot create socket: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } opt_val = 1; if ( setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof (opt_val)) == -1 ){ freeaddrinfo (host_addr); fprintf (stderr, "%s: cannot set socket options: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } rval = bind (sock, (struct sockaddr*) host_addr->ai_addr, host_addr->ai_addrlen); if ( rval == -1 ){ freeaddrinfo (host_addr); fprintf (stderr, "%s: cannot bind to address: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } rval = listen (sock, LISTEN_QUEUE_LEN); if ( rval == -1 ){ freeaddrinfo (host_addr); fprintf (stderr, "%s: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } freeaddrinfo (host_addr); } pcap_session = (struct session_data*) calloc (filter_cnt, sizeof (struct session_data)); if ( pcap_session == NULL ){ fprintf (stderr, "%s: cannot allocate memory: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } for ( i = 0, filter_iter = etherpoke_conf.head; filter_iter != NULL; i++, filter_iter = filter_iter->next ){ int link_type; session_data_init (&(pcap_session[i])); pcap_session[i].timeout = filter_iter->session_timeout; pcap_session[i].evt_mask = filter_iter->notify; pcap_session[i].filter_name = strdup (filter_iter->name); if ( pcap_session[i].filter_name == NULL ){ fprintf (stderr, "%s: cannot allocate memory: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } if ( filter_iter->notify & NOTIFY_EXEC ){ if ( filter_iter->session_begin != NULL ){ rval = wordexp (filter_iter->session_begin, &(pcap_session[i].evt_cmd_beg), WORDEXP_FLAGS); if ( rval != 0 ) goto filter_error; } if ( filter_iter->session_error != NULL ){ rval = wordexp (filter_iter->session_error, &(pcap_session[i].evt_cmd_err), WORDEXP_FLAGS); if ( rval != 0 ) goto filter_error; } if ( filter_iter->session_end != NULL ){ rval = wordexp (filter_iter->session_end, &(pcap_session[i].evt_cmd_end), WORDEXP_FLAGS); if ( rval != 0 ) goto filter_error; } filter_error: switch ( rval ){ case WRDE_SYNTAX: fprintf (stderr, "%s: invalid event hook in '%s': syntax error\n", argv[0], filter_iter->name); exitno = EXIT_FAILURE; goto cleanup; case WRDE_BADCHAR: fprintf (stderr, "%s: invalid event hook in '%s': bad character\n", argv[0], filter_iter->name); exitno = EXIT_FAILURE; goto cleanup; case WRDE_BADVAL: fprintf (stderr, "%s: invalid event hook in '%s': referencing undefined variable\n", argv[0], filter_iter->name); exitno = EXIT_FAILURE; goto cleanup; case WRDE_NOSPACE: fprintf (stderr, "%s: cannot expand event hook string in '%s': out of memory\n", argv[0], filter_iter->name); exitno = EXIT_FAILURE; goto cleanup; } } pcap_session[i].handle = pcap_create (filter_iter->interface, pcap_errbuff); if ( pcap_session[i].handle == NULL ){ fprintf (stderr, "%s: cannot start packet capture: %s\n", argv[0], pcap_errbuff); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_set_rfmon (pcap_session[i].handle, filter_iter->rfmon); if ( rval != 0 ){ fprintf (stderr, "%s: cannot enable monitor mode on interface '%s': %s\n", argv[0], filter_iter->interface, pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_set_promisc (pcap_session[i].handle, !(filter_iter->rfmon)); if ( rval != 0 ){ fprintf (stderr, "%s: cannot enable promiscuous mode on interface '%s'\n", argv[0], filter_iter->interface); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_set_timeout (pcap_session[i].handle, SELECT_TIMEOUT_MS); if ( rval != 0 ){ fprintf (stderr, "%s: cannot set read timeout on interface '%s': %s\n", argv[0], filter_iter->interface, pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_setnonblock (pcap_session[i].handle, 1, pcap_errbuff); if ( rval == -1 ){ fprintf (stderr, "%s: cannot set nonblock mode on packet capture resource: %s\n", argv[0], pcap_errbuff); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_activate (pcap_session[i].handle); if ( rval != 0 ){ fprintf (stderr, "%s: cannot activate packet capture on interface '%s': %s\n", argv[0], filter_iter->interface, pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } // Set link-layer type from configuration file. if ( filter_iter->link_type != NULL ){ link_type = pcap_datalink_name_to_val (filter_iter->link_type); if ( link_type == -1 ){ fprintf (stderr, "%s: cannot convert link-layer type '%s': unknown link-layer type name\n", argv[0], filter_iter->link_type); exitno = EXIT_FAILURE; goto cleanup; } } else { // If no link-layer type is specified in the configuration file, // use default value. At this point I am sticking with DLTs used by // wireshark on hardware I have available. Different values may // apply to different hardware/driver, therefore more research time // should be put into finding 'best' values. // More information: http://www.tcpdump.org/linktypes.html if ( filter_iter->rfmon ){ link_type = DLT_IEEE802_11_RADIO; } else { link_type = DLT_EN10MB; } } rval = pcap_set_datalink (pcap_session[i].handle, link_type); if ( rval == -1 ){ fprintf (stderr, "%s: cannot set data-link type: %s\n", argv[0], pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } if ( filter_iter->match != NULL ){ struct bpf_program bpf_prog; rval = pcap_compile (pcap_session[i].handle, &bpf_prog, filter_iter->match, 0, PCAP_NETMASK_UNKNOWN); if ( rval == -1 ){ fprintf (stderr, "%s: cannot compile the filter '%s' match rule: %s\n", argv[0], filter_iter->name, pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_setfilter (pcap_session[i].handle, &bpf_prog); if ( rval == -1 ){ fprintf (stderr, "%s: cannot apply the filter '%s' on interface '%s': %s\n", argv[0], filter_iter->name, filter_iter->interface, pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } pcap_freecode (&bpf_prog); } pcap_session[i].fd = pcap_get_selectable_fd (pcap_session[i].handle); if ( pcap_session[i].fd == -1 ){ fprintf (stderr, "%s: cannot obtain file descriptor for packet capture interface '%s'\n", argv[0], filter_iter->interface); exitno = EXIT_FAILURE; goto cleanup; } } // We no longer need data stored in config structure. All neccessary data // were moved into session_data structure. config_unload (ðerpoke_conf); poll_fd = (struct pollfd*) malloc (sizeof (struct pollfd) * poll_len); if ( poll_fd == NULL ){ fprintf (stderr, "%s: cannot allocate memory: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } // Populate poll structure... for ( i = 0; i < poll_len; i++ ){ // ... with pcap file descriptors... if ( i < filter_cnt ) poll_fd[i].fd = pcap_session[i].fd; // ... listening socket... else if ( i == filter_cnt ) poll_fd[i].fd = sock; // ... invalid file descriptors (will be ignored by poll(2)), in space reserved for client sockets... else poll_fd[i].fd = -1; poll_fd[i].events = POLLIN | POLLERR; poll_fd[i].revents = 0; } // // Setup signal handler // sa.sa_handler = etherpoke_sigdie; sigemptyset (&(sa.sa_mask)); sa.sa_flags = 0; rval = 0; rval &= sigaction (SIGINT, &sa, NULL); rval &= sigaction (SIGQUIT, &sa, NULL); rval &= sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigemptyset (&(sa.sa_mask)); sa.sa_flags = 0; rval &= sigaction (SIGCHLD, &sa, NULL); if ( rval != 0 ){ fprintf (stderr, "%s: cannot setup signal handler: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } // // Daemonize the process if the flag was set // if ( opt.daemon == 1 ){ pid = fork (); if ( pid > 0 ){ exitno = EXIT_SUCCESS; goto cleanup; } else if ( pid == -1 ){ fprintf (stderr, "%s: cannot daemonize the process (fork failed).\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } if ( setsid () == -1 ){ fprintf (stderr, "%s: cannot daemonize the process (setsid failed).\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } umask (0); freopen ("/dev/null", "r", stdin); freopen ("/dev/null", "w", stdout); freopen ("/dev/null", "w", stderr); syslog_flags = LOG_PID; } openlog ("etherpoke", syslog_flags, LOG_DAEMON); syslog (LOG_INFO, "Etherpoke started (loaded filters: %u)", filter_cnt); if ( opt.tcp_event ) syslog (LOG_INFO, "Event notifications available via %s:%s (ACCEPT_MAX: %u)", opt.hostname, opt.port, opt.accept_max); // // Main loop // main_loop = 1; while ( main_loop ){ const u_char *pkt_data; struct pcap_pkthdr *pkt_header; time_t current_time; errno = 0; rval = poll (poll_fd, poll_len, SELECT_TIMEOUT_MS); if ( rval == -1 ){ if ( errno == EINTR ) continue; syslog (LOG_ERR, "poll(2) failed: %s", strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } #ifdef DBG_AVG_LOOP_SPEED clock_start = clock (); #endif // Accept incoming connection if ( poll_fd[filter_cnt].revents & POLLIN ){ int sock_new; sock_new = accept (sock, NULL, NULL); if ( sock_new == -1 ){ syslog (LOG_ERR, "cannot accept new connection: %s", strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } // Find unused place in the poll array for ( j = (filter_cnt + 1); j < poll_len; j++ ){ if ( poll_fd[j].fd == -1 ){ poll_fd[j].fd = sock_new; sock_new = -1; break; } } if ( sock_new != -1 ){ if ( opt.verbose ) syslog (LOG_INFO, "Client refused: too many concurrent connections"); close (sock_new); } else { if ( opt.verbose ) syslog (LOG_INFO, "Client connected..."); } } // Take care of incoming client data. At this point only shutdown and // close is handled, no other input is expected from the clients. for ( i = (filter_cnt + 1); i < poll_len; i++ ){ if ( poll_fd[i].revents & POLLIN ){ char nok[128]; errno = 0; rval = recv (poll_fd[i].fd, nok, sizeof (nok), MSG_DONTWAIT); if ( rval <= 0 && (errno != EAGAIN && errno != EWOULDBLOCK) ){ if ( opt.verbose ) syslog (LOG_INFO, "Client disconnected..."); close (poll_fd[i].fd); poll_fd[i].fd = -1; } } } time (¤t_time); // Handle changes on pcap file descriptors for ( i = 0; i < filter_cnt; i++ ){ wordexp_t *cmd_exp; const char *evt_str; // Handle incoming packet if ( (poll_fd[i].revents & POLLIN) || (poll_fd[i].revents & POLLERR) ){ rval = pcap_next_ex (pcap_session[i].handle, &pkt_header, &pkt_data); if ( rval == 1 ){ if ( pcap_session[i].evt.ts == 0 ) pcap_session[i].evt.type = SE_BEG; pcap_session[i].evt.ts = pkt_header->ts.tv_sec; } else if ( rval < 0 ){ pcap_session[i].evt.type = SE_ERR; } } if ( (pcap_session[i].evt.ts > 0) && (difftime (current_time, pcap_session[i].evt.ts) >= pcap_session[i].timeout) ){ pcap_session[i].evt.type = SE_END; } switch ( pcap_session[i].evt.type ){ case SE_NUL: // There was no change on this file descriptor, skip to // another one. 'continue' may seem a bit confusing here, // but it applies to a loop above. Not sure how other // compilers will behave (other than gcc). continue; case SE_BEG: evt_str = "BEG"; cmd_exp = &(pcap_session[i].evt_cmd_beg); pcap_session[i].evt.type = SE_NUL; break; case SE_END: cmd_exp = &(pcap_session[i].evt_cmd_end); evt_str = "END"; pcap_session[i].evt.type = SE_NUL; pcap_session[i].evt.ts = 0; break; case SE_ERR: evt_str = "ERR"; cmd_exp = &(pcap_session[i].evt_cmd_err); pcap_session[i].evt.type = SE_NUL; pcap_session[i].evt.ts = 0; break; default: // Undefined state... What to do, other than die? syslog (LOG_ERR, "undefined event type"); exitno = EXIT_FAILURE; goto cleanup; } if ( opt.verbose ) syslog (LOG_INFO, "%s:%s", pcap_session[i].filter_name, evt_str); // Send socket notification if ( pcap_session[i].evt_mask & NOTIFY_SOCK ){ char msg[CONF_FILTER_NAME_MAXLEN + 5]; snprintf (msg, sizeof (msg), "%s:%s", pcap_session[i].filter_name, evt_str); for ( j = (filter_cnt + 1); j < poll_len; j++ ){ if ( poll_fd[j].fd == -1 ) continue; errno = 0; rval = send (poll_fd[j].fd, msg, strlen (msg) + 1, MSG_NOSIGNAL | MSG_DONTWAIT); if ( rval == -1 && (errno != EAGAIN && errno != EWOULDBLOCK) ){ syslog (LOG_WARNING, "failed to send notification: %s", strerror (errno)); close (poll_fd[j].fd); poll_fd[j].fd = -1; } } } // Execute an event hook if ( pcap_session[i].evt_mask & NOTIFY_EXEC ){ // Expansion was not made... if ( cmd_exp->we_wordc == 0 ) continue; pid = fork (); if ( pid == -1 ){ syslog (LOG_ERR, "cannot fork the process: %s", strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } // Parent process, carry on... if ( pid > 0 ) continue; errno = 0; execv (cmd_exp->we_wordv[0], cmd_exp->we_wordv); // This code gets executed only if execv(3) fails. Wrapping // this code in a condition is unneccessary. syslog (LOG_WARNING, "cannot execute event hook in '%s': %s", pcap_session[i].filter_name, strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } } #ifdef DBG_AVG_LOOP_SPEED clock_avg = (clock_avg + (clock () - clock_start)) / 2; syslog (LOG_DEBUG, "Average loop speed: %lf", (double) (clock_avg / CLOCKS_PER_SEC)); #endif } syslog (LOG_INFO, "Etherpoke shutdown (signal %u)", exitno); cleanup: closelog (); if ( pcap_session != NULL ){ for ( i = 0; i < filter_cnt; i++ ) session_data_free (&(pcap_session[i])); free (pcap_session); } if ( poll_fd != NULL ) free (poll_fd); if ( sock != -1 ) close (sock); config_unload (ðerpoke_conf); path_free (&path_config); return exitno; }
//----------------------------------------------------------------------------- // Main... process command line parameters, and then setup our listening // sockets and event loop. int main(int argc, char **argv) { rq_service_t *service; control_t *control = NULL; char *queue; ///============================================================================ /// Initialization. ///============================================================================ // create the 'control' object that will be passed to all the handlers so // that they have access to the information that they require. control = (control_t *) malloc(sizeof(control_t)); init_control(control); // create new service object. service = rq_svc_new(); control->rqsvc = service; // add the command-line options that are specific to this service. rq_svc_setname(service, PACKAGE " " VERSION); rq_svc_setoption(service, 'f', "filename", "blacklist .csv file."); rq_svc_setoption(service, 'q', "queue", "Queue to listen on for requests."); rq_svc_process_args(service, argc, argv); rq_svc_initdaemon(service); assert(control->evbase == NULL); control->evbase = event_base_new(); assert(control->evbase); rq_svc_setevbase(service, control->evbase); // initialise the risp system for processing what we receive on the queue. assert(control); assert(control->risp == NULL); control->risp = risp_init(NULL); assert(control->risp != NULL); risp_add_command(control->risp, BL_CMD_NOP, &cmdNop); risp_add_command(control->risp, BL_CMD_CLEAR, &cmdClear); risp_add_command(control->risp, BL_CMD_CHECK, &cmdCheck); risp_add_command(control->risp, BL_CMD_IP, &cmdIP); // initialise signal handlers. assert(control); assert(control->evbase); assert(control->sigint_event == NULL); control->sigint_event = evsignal_new(control->evbase, SIGINT, sigint_handler, control); assert(control->sigint_event); event_add(control->sigint_event, NULL); assert(control->sighup_event == NULL); control->sighup_event = evsignal_new(control->evbase, SIGHUP, sighup_handler, control); assert(control->sighup_event); event_add(control->sighup_event, NULL); // load the config file that we assume is supplied. assert(control->configfile == NULL); control->configfile = rq_svc_getoption(service, 'f'); if (control->configfile == NULL) { fprintf(stderr, "Configfile is required\n"); exit(EXIT_FAILURE); } else { if (config_load(control) < 0) { fprintf(stderr, "Errors loading config file: %s\n", control->configfile); exit(EXIT_FAILURE); } } // Tell the rq subsystem to connect to the rq servers. It gets its info // from the common paramaters that it expects. rq_svc_connect(service, NULL, NULL, NULL); // initialise the queue that we are consuming, provide callback handler. queue = rq_svc_getoption(service, 'q'); assert(queue); assert(service->rq); rq_consume(service->rq, queue, 200, RQ_PRIORITY_NORMAL, 0, message_handler, NULL, NULL, control); // we also want to make sure that when we lose the connection to the // controller, we indicate that we lost connection to the queue, unless we // have already established another controller connection. ///============================================================================ /// Main Event Loop. ///============================================================================ // enter the processing loop. This function will not return until there is // nothing more to do and the service has shutdown. Therefore everything // needs to be setup and running before this point. Once inside the // rq_process function, everything is initiated by the RQ event system. assert(control != NULL); assert(control->evbase); event_base_loop(control->evbase, 0); ///============================================================================ /// Shutdown ///============================================================================ assert(control); assert(control->evbase); event_base_free(control->evbase); control->evbase = NULL; // the rq service sub-system has no real way of knowing when the event-base // has been cleared, so we need to tell it. rq_svc_setevbase(service, NULL); control->rqsvc = NULL; // unload the config entries. assert(control); if (control->entries) { config_unload(control); } assert(control->entries == NULL); // make sure signal handlers have been cleared. assert(control); assert(control->sigint_event == NULL); assert(control->sighup_event == NULL); // cleanup risp library. assert(control); assert(control->risp); control->risp = risp_shutdown(control->risp); assert(control->risp == NULL); // we are done, cleanup what is left in the control structure. cleanup_control(control); free(control); rq_svc_cleanup(service); return 0; }
int main( int argc, char **argv) { char **skis; char inbuf[128]; int numskis = 0; if (argc < 2) fatal("Usage: name of constraints file"); FILE *str = fopen(argv[1], "r"); if (!str) fatal("Can't open %s", argv[1]); FILE *tmpstr; char *f = "xproof.tmp"; int i = 0; struct keyring keyring = { NULL, NULL, NULL }; OPEN_LOG("proofreader", LOG_USER); if (!my_config_load()) { LOG(LOG_ERR, "can't load configuration"); exit(EXIT_FAILURE); } if (!(tmpstr = fopen(f, "w+"))) fatal("Can't open %s", f); if (parse_SKI_blocks(&keyring, str, argv[1], inbuf, sizeof(inbuf), &i) < 0) fatal("Invalid line: %s", errbuf); fseek(str, (long)0, 0); *inbuf = 0; while (1) { if (!fgets(inbuf, sizeof(inbuf), str)) abort(); if (!strncmp(inbuf, "SKI ", 4)) break; fputs(inbuf, tmpstr); } char *c; do // starting with first SKI line { for (c = &inbuf[4]; *c && ((*c >= '0' && *c <= '9') || *c == ':' || (*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f')); c++); if (c != &inbuf[63]) fatal("Invalid line: %s", inbuf); while (*c == ' ' || *c == '\t') c++; if (*c != '\n') fatal("Invalid line: %s", inbuf); if (numskis) { int num; for (num = 0; num < numskis && strcmp(inbuf, skis[num]); num++); if (num < numskis) fatal("Duplicate SKI: %s ", &inbuf[4]); } if (!numskis) skis = (char **)calloc(2, sizeof(char *)); else skis = (char **)realloc(skis, (sizeof(char *) * (numskis + 2))); skis[numskis] = calloc(1, strlen(inbuf) + 2); strcpy(skis[numskis], inbuf); numskis++; fputs(inbuf, tmpstr); // get IPv4 start if (!fgets(inbuf, sizeof(inbuf), str)) fatal("Premature end of file"); if (strcmp(inbuf, "IPv4\n")) fatal("Missing IPv4 line"); fputs(inbuf, tmpstr); // print v4 hdr // get first v4 line, if any if (!fgets(inbuf, sizeof(inbuf), str)) fatal("Premature end of file"); // process v4 entries, if any process_type(str, tmpstr, 4, inbuf, "IPv6\n"); fputs(inbuf, tmpstr); // print v6 hdr // get first v6 line, if any if (!fgets(inbuf, sizeof(inbuf), str)) fatal("Premature end of file"); process_type(str, tmpstr, 6, inbuf, "AS#\n"); fputs(inbuf, tmpstr); // print as# hdr // get first AS#, if any if (!(c = fgets(inbuf, sizeof(inbuf), str))) break; process_type(str, tmpstr, 8, inbuf, "SKI "); } while (*inbuf); if (warnings == 0) { LOG(LOG_INFO, "Finished %s OK", argv[1]); } else { LOG(LOG_ERR, "Had %d warnings. New file NOT created", warnings); } config_unload(); CLOSE_LOG(); return 0; }
int main( int argc, char **argv) { char *displays[MAX_VALS]; char *clauses[MAX_CONDS]; char *orderp = NULL; int i; err_code status; int numDisplays = 0; int numClauses = 0; OPEN_LOG("query", LOG_USER); if (!my_config_load()) { LOG(LOG_ERR, "can't initialize configuration"); exit(EXIT_FAILURE); } output = stdout; useLabels = 1; multiline = 0; validate = 1; if (argc == 1) return printUsage(); if (strcasecmp(argv[1], "-l") == 0) { if (argc != 3) return printUsage(); setObjectType(argv[2]); return listOptions(); } for (i = 1; i < argc; i += 2) { if (strcasecmp(argv[i], "-i") == 0) { validate = 0; i--; } else if (strcasecmp(argv[i], "-n") == 0) { useLabels = 0; i--; } else if (strcasecmp(argv[i], "-m") == 0) { multiline = 1; i--; } else if (argc == (i + 1)) { return printUsage(); } else if (strcasecmp(argv[i], "-t") == 0) { setObjectType(argv[i + 1]); } else if (strcasecmp(argv[i], "-d") == 0) { displays[numDisplays++] = argv[i + 1]; } else if (strcasecmp(argv[i], "-f") == 0) { clauses[numClauses++] = argv[i + 1]; } else if (strcasecmp(argv[i], "-o") == 0) { output = fopen(argv[i + 1], "w"); } else if (strcasecmp(argv[i], "-x") == 0) { orderp = argv[i + 1]; } else { // unknown switch return printUsage(); } } checkErr((!isROA) && (!isCRL) && (!isCert) && (!isManifest) && (!isGBR), BAD_OBJECT_TYPE); checkErr(numDisplays == 0, "Need to display something\n"); if (numDisplays == 1 && strcasecmp(displays[0], "all") == 0) numDisplays = addAllFields(displays, 0); displays[numDisplays++] = NULL; clauses[numClauses++] = NULL; status = doQuery(displays, clauses, orderp); if (status == ERR_SCM_NODATA) { LOG(LOG_DEBUG, "%s", err2string(status)); status = 0; } else if (status < 0) { LOG(LOG_ERR, "%s", err2string(status)); } config_unload(); CLOSE_LOG(); return status; }
int main( int argc, char **argv) { scmcon *testconp = NULL; scmcon *realconp = NULL; scm *scmp = NULL; FILE *sfile = NULL; char *thedelfile = NULL; char *topdir = NULL; char *thefile = NULL; char *outfile = NULL; char *outfull = NULL; char *outdir = NULL; char *tmpdsn = NULL; char *ne; char *porto = NULL; char errmsg[1024]; char *skifile = NULL; int ians = 0; int do_create = 0; int do_delete = 0; int do_sockopts = 0; int do_fileopts = 0; int use_filelist = 0; int perpetual = 0; int really = 0; int trusted = 0; int force = 0; int allowex = 0; int sta = 0; int s; int c; (void)setbuf(stdout, NULL); if (argc <= 1) { usage(); return (1); } while ((c = getopt(argc, argv, "t:xyhad:f:F:lLwz:pm:c:s")) != EOF) { switch (c) { case 'a': allowex = 1; break; case 't': do_create++; topdir = optarg; break; case 'x': do_delete++; break; case 'y': force++; break; case 'D': trusted++; case 'd': thedelfile = optarg; break; case 'F': trusted++; case 'f': thefile = optarg; break; case 'L': trusted++; case 'l': use_filelist++; break; case 'w': do_sockopts++; break; case 'z': do_fileopts++; porto = optarg; break; case 'p': perpetual++; break; case 'c': skifile = optarg; break; case 'h': usage(); return (0); case 's': strict_profile_checks = 1; // global from myssl.c strict_profile_checks_cms = 1; // global from roa_validate.c break; default: (void)fprintf(stderr, "Invalid option '%c'\n", c); usage(); return (1); } } // if there is anything left in argv, or no operation specified, warn user if (optind < argc) { (void)printf("Extra arguments at the end of the command line.\n"); usage(); return (1); } if ((do_create + do_delete + do_sockopts + do_fileopts) == 0 && thefile == 0 && thedelfile == 0 && skifile == 0 && use_filelist == 0) { (void)printf("You need to specify at least one operation " "(e.g. -f file).\n"); usage(); return (1); } OPEN_LOG("rcli", LOG_USER); if (!my_config_load()) { LOG(LOG_ERR, "can't load configuration"); exit(EXIT_FAILURE); } if (force == 0) { if (do_delete > 0) { ians = yorn("Do you REALLY want to delete all database tables"); if (ians <= 0) { LOG(LOG_NOTICE, "Delete operation cancelled"); return (1); } really++; } if ((do_create > 0) && (really == 0)) { ians = yorn("Do you REALLY want to create all database tables"); if (ians <= 0) { LOG(LOG_NOTICE, "Create operation cancelled"); return (1); } really++; } } scmp = initscm(); if (scmp == NULL) { LOG(LOG_ERR, "Internal error: cannot initialize database schema"); return (-2); } /* * If a create or delete operation is being performed, then a test dsn * will be needed; create it now and defer the creation of the real dsn * until later. Otherwise, create the real dsn. * * A test dsn is needed for operations that operate on the overall * database state as opposed to the rpki tables, namely the create and * delete operations. */ if ((do_create + do_delete) > 0) { /* * Note that in the following line, we do not intend to edit * the database named "information_schema". We are simply * filling in the "database name" parameter with something * that is guaranteed to be valid for MySQL. */ tmpdsn = makedsnscm(scmp->dsnpref, "information_schema", CONFIG_DATABASE_USER_get(), CONFIG_DATABASE_PASSWORD_get()); if (tmpdsn == NULL) { membail(); return (-1); } testconp = connectscm(tmpdsn, errmsg, 1024); memset(tmpdsn, 0, strlen(tmpdsn)); free((void *)tmpdsn); if (testconp == NULL) { LOG(LOG_ERR, "Cannot connect to DSN: %s", errmsg); freescm(scmp); return (-1); } } else { realconp = connectscm(scmp->dsn, errmsg, 1024); if (realconp == NULL) { LOG(LOG_ERR, "Cannot connect to DSN %s: %s", scmp->dsn, errmsg); freescm(scmp); return (-1); } } /* * Process command line options in the following order: delete, create, * dofile, dodir, listener. */ if (do_delete > 0) sta = deleteop(testconp, scmp); if ((do_create > 0) && (sta == 0)) /* first phase of create */ sta = createop(testconp, scmp); /* * Don't need the test connection any more */ if (testconp != NULL) { disconnectscm(testconp); testconp = NULL; } /* * If there has been an error or if we're done because the database was * just deleted and not re-created, bail out. */ if (sta < 0 || (do_delete > 0 && do_create == 0)) { if (realconp != NULL) disconnectscm(realconp); freescm(scmp); if (tdir != NULL) free((void *)tdir); return (sta); } /* * If a connection to the real DSN has not been opened yet, open it now. */ if (realconp == NULL) { realconp = connectscm(scmp->dsn, errmsg, 1024); if (realconp == NULL) { LOG(LOG_ERR, "Cannot connect to DSN %s: %s", scmp->dsn, errmsg); freescm(scmp); if (tdir != NULL) free((void *)tdir); return (-1); } } /* * If a create operation was requested, complete it now. */ if ((do_create > 0) && (sta == 0)) sta = create2op(scmp, realconp, topdir); /* * If the top level repository directory is not set, then retrieve it from * the database. */ if ((tdir == NULL) && (sta == 0)) { tdir = retrieve_tdir(scmp, realconp, &sta); if (tdir == NULL) LOG(LOG_ERR, "Cannot retrieve top level repository info from DB"); } if (sta == 0) { LOG(LOG_INFO, "Top level repository directory is %s", tdir); tdirlen = strlen(tdir); } /* * Setup for actual SSL operations */ OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); LOG(LOG_NOTICE, "Rsync client session started"); if (thefile != NULL && sta == 0) { // Check that the file is in the repository, ask if not and force is // off sta = splitdf(NULL, NULL, thefile, &outdir, &outfile, &outfull); if (sta == 0) { if (strncmp(tdir, outdir, tdirlen) != 0 && force == 0) { ians = yorn("That file is not in the repository. Proceed anyway"); if (ians <= 0) sta = 1; } // if ( strstr(outdir, "TRUST") != NULL ) // trusted++; // if the user has declared it to be trusted // ask for verification unless force is set if (trusted > 0 && force == 0 && sta == 0) { ians = yorn("Really declare this file as trusted"); if (ians <= 0) sta = 1; } if (sta == 1) LOG(LOG_NOTICE, "File operation cancelled"); if (sta == 0) { LOG(LOG_INFO, "Attempting add: %s", outfile); setallowexpired(allowex); sta = add_object(scmp, realconp, outfile, outdir, outfull, trusted); if (sta < 0) { LOG(LOG_ERR, "Add failed: %s: error %s (%d)", thefile, err2string(sta), sta); if (sta == ERR_SCM_SQL) { ne = geterrorscm(realconp); if (ne != NULL && ne != 0) LOG(LOG_ERR, "\t%s", ne); } } else LOG(LOG_INFO, "Add succeeded: %s", outfile); } free((void *)outdir); free((void *)outfile); free((void *)outfull); } else LOG(LOG_ERR, "%s (%d)", err2string(sta), sta); } if (use_filelist > 0 && sta == 0) { char *line = NULL; size_t len = 0; ssize_t read; int status; setallowexpired(allowex); while ((read = getline(&line, &len, stdin)) != -1) { if (read == 0) continue; // Trim newline and skip line if empty if (line[read - 1] == '\n') line[read - 1] = '\0'; if (strlen(line) == 0) continue; // Split directory and file components of path status = splitdf(NULL, NULL, line, &outdir, &outfile, &outfull); if (status != 0) { LOG(LOG_ERR, "%s (%d)", err2string(status), status); continue; } LOG(LOG_INFO, "Attempting add: %s", outfile); // Warn if file not within repository directory if (strncmp(tdir, outdir, tdirlen) != 0) LOG(LOG_WARNING, "%s is not in the repository", line); // Add status = add_object(scmp, realconp, outfile, outdir, outfull, trusted); if (status == 0) { LOG(LOG_INFO, "Add succeeded: %s", outfile); } else { LOG(LOG_ERR, "Add failed: %s: error %s (%d)", line, err2string(status), status); if (status == ERR_SCM_SQL) { ne = geterrorscm(realconp); if (ne != NULL && ne != 0) LOG(LOG_ERR, "\t%s", ne); } } free((void *)outdir); free((void *)outfile); free((void *)outfull); } free(line); } if (thedelfile != NULL && sta == 0) { sta = splitdf(NULL, NULL, thedelfile, &outdir, &outfile, &outfull); if (sta == 0) { sta = delete_object(scmp, realconp, outfile, outdir, outfull, 0); if (sta < 0) { LOG(LOG_ERR, "Could not delete file %s: error %s (%d)", thedelfile, err2string(sta), sta); if (sta == ERR_SCM_SQL) { ne = geterrorscm(realconp); if (ne != NULL && ne != 0) LOG(LOG_ERR, "\t%s", ne); } } else LOG(LOG_INFO, "Delete operation succeeded (%s removed)", thedelfile); free((void *)outdir); free((void *)outfile); free((void *)outfull); } else LOG(LOG_ERR, "Error: %s (%d)", err2string(sta), sta); } if ((do_sockopts + do_fileopts) > 0 && sta == 0) { int protos = (-1); const int max_makesock_attempts = 10; int makesock_failures = 0; do { if (do_sockopts > 0) { uint16_t port = CONFIG_RPKI_PORT_get(); s = makesock(port, &protos); if (s < 0) { makesock_failures++; LOG(LOG_ERR, "Failed to listen on port %" PRIu16 " (failure #%d)", port, makesock_failures); sleep(1); if (makesock_failures >= max_makesock_attempts) { LOG(LOG_ERR, "%d failed attempts to create socket. Aborting.", max_makesock_attempts); sta = -1; break; } } else { makesock_failures = 0; FLUSH_LOG(); sta = sockline(scmp, realconp, s); LOG(LOG_INFO, "Socket connection closed"); FLUSH_LOG(); (void)close(s); } } if (do_fileopts > 0 && porto != NULL) { if (!isatty(0)) { LOG(LOG_DEBUG, "Opening stdin"); sfile = stdin; sta = fileline(scmp, realconp, sfile); } else { LOG(LOG_DEBUG, "Opening a socket cmdfile %s", porto); sfile = fopen(porto, "r"); if (sfile == NULL) LOG(LOG_ERR, "Could not open cmdfile"); else { sta = fileline(scmp, realconp, sfile); LOG(LOG_DEBUG, "Cmdfile closed"); (void)fclose(sfile); } } } if (sta == 0 && skifile) { LOG(LOG_DEBUG, "Starting skifile %s", skifile); sta = read_SKI_blocks(scmp, realconp, skifile); if (sta > 0) sta = 0; if (sta) LOG(LOG_ERR, "Error with skifile: %s (%d)", err2string(sta), sta); } } while (perpetual > 0); if (protos >= 0) (void)close(protos); } if (sta == 0 && skifile) { LOG(LOG_DEBUG, "Starting skifile %s", skifile); sta = read_SKI_blocks(scmp, realconp, skifile); if (sta > 0) sta = 0; if (sta) LOG(LOG_ERR, "Error with skifile: %s (%d)", err2string(sta), sta); } (void)ranlast(scmp, realconp, "RSYNC"); sqcleanup(); if (realconp != NULL) disconnectscm(realconp); freescm(scmp); if (tdir != NULL) free((void *)tdir); LOG(LOG_NOTICE, "Rsync client session ended"); config_unload(); CLOSE_LOG(); return (sta); }