コード例 #1
0
ファイル: create_object.c プロジェクト: dseomn/rpstir
/*
 * 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);
}
コード例 #2
0
ファイル: rtr-update.c プロジェクト: dseomn/rpstir
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, &current_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;
}
コード例 #3
0
ファイル: query.c プロジェクト: bgpsecurity/rpstir
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;
}
コード例 #4
0
ファイル: proofreader.c プロジェクト: gvsurenderreddy/rpstir
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;
}
コード例 #5
0
ファイル: rcli.c プロジェクト: dseomn/rpstir
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);
}