/* * 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) { 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) { 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) { 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); }