예제 #1
0
/*
 *  status = ipv6routingioPrepare(stream);
 *
 *    Sets the record version to the default if it is unspecified,
 *    checks that the record format supports the requested record
 *    version, sets the record length, and sets the pack and unpack
 *    functions for this record format and version.
 */
int
ipv6routingioPrepare(
    skstream_t         *stream)
{
#define FILE_FORMAT "FT_RWIPV6ROUTING"
    sk_file_header_t *hdr = stream->silk_hdr;
    int rv = SKSTREAM_OK; /* return value */

    /* Set version if none was selected by caller */
    if ((stream->io_mode == SK_IO_WRITE)
        && (skHeaderGetRecordVersion(hdr) == SK_RECORD_VERSION_ANY))
    {
        skHeaderSetRecordVersion(hdr, DEFAULT_RECORD_VERSION);
    }

    /* version check; set values based on version */
    switch (skHeaderGetRecordVersion(hdr)) {
      case 3:
        stream->rwUnpackFn = &ipv6routingioRecordUnpack_V3;
        stream->rwPackFn   = &ipv6routingioRecordPack_V3;
        break;
      case 2:
        stream->rwUnpackFn = &ipv6routingioRecordUnpack_V2;
        stream->rwPackFn   = &ipv6routingioRecordPack_V1;
        break;
      case 1:
        stream->rwUnpackFn = &ipv6routingioRecordUnpack_V1;
        stream->rwPackFn   = &ipv6routingioRecordPack_V1;
        break;
      case 0:
      default:
        rv = SKSTREAM_ERR_UNSUPPORT_VERSION;
        goto END;
    }

    stream->recLen = ipv6routingioGetRecLen(skHeaderGetRecordVersion(hdr));

    /* verify lengths */
    if (stream->recLen == 0) {
        skAppPrintErr("Record length not set for %s version %u",
                      FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr));
        skAbort();
    }
    if (stream->recLen != skHeaderGetRecordLength(hdr)) {
        if (0 == skHeaderGetRecordLength(hdr)) {
            skHeaderSetRecordLength(hdr, stream->recLen);
        } else {
            skAppPrintErr(("Record length mismatch for %s version %u\n"
                           "\tcode = %" PRIu16 " bytes;  header = %lu bytes"),
                          FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr),
                          stream->recLen,
                          (unsigned long)skHeaderGetRecordLength(hdr));
            skAbort();
        }
    }

  END:
    return rv;
}
예제 #2
0
/*
 *  loadschemeUsage(fh);
 *
 *    Print the description of the argument to the --load-scheme
 *    switch to the 'fh' file handle.
 */
static void
loadschemeUsage(
    FILE               *fh)
{
    const sk_stringmap_entry_t *e;
    char buf[128];

    /* Find name of the default load-scheme */
    for (e = load_schemes; e->name; ++e) {
        if (DEFAULT_LOAD_SCHEME == e->id) {
            break;
        }
    }
    if (NULL == e->name) {
        skAbort();
    }

    fprintf(fh, "Split a record's volume (bytes & packets) among the\n"
            "\tbins it spans using this scheme. Def. %s. Choices:\n",
            e->name);
    for (e = load_schemes; e->name; ++e) {
        if (e->userdata) {
            snprintf(buf, sizeof(buf), "%s,%u", e->name, e->id);
            fprintf(fh, "\t  %-19s - %s\n",
                    buf, (const char*)e->userdata);
        }
    }
}
예제 #3
0
/*
 *    Parse the argument to the --log-flags switch.
 */
static int
parseLogFlags(
    const char         *log_flags_str)
{
    char *log_flags_copy = NULL;
    char *flag_next;
    char *flag;
    int rv = -1;

    skpcProbeClearLogFlags(probe);

    if (NULL == log_flags_str) {
        return 0;
    }

    /* create a copy of the input string and maintain a reference to
     * it so we can free it */
    log_flags_copy = strdup(log_flags_str);
    flag_next = log_flags_copy;
    if (NULL == log_flags_copy) {
        skAppPrintOutOfMemory(NULL);
        goto END;
    }

    /* parse the flags as a comma separated list of tokens */
    while ((flag = strsep(&flag_next, ",")) != NULL) {
        /* check for empty token (e.g., double comma) */
        if ('\0' == *flag) {
            continue;
        }
        switch (skpcProbeAddLogFlag(probe, flag)) {
          case 0:
            break;
          case -1:
            skAppPrintErr("Invalid %s: Unrecognized value '%s'",
                          appOptions[OPT_LOG_FLAGS].name, flag);
            goto END;
          case -2:
            skAppPrintErr("Invalid %s: Cannot mix 'none' with other value",
                          appOptions[OPT_LOG_FLAGS].name);
            goto END;
          default:
            skAppPrintErr("Bad return value from skpcProbeAddLogFlag()");
            skAbort();
        }
    }

    rv = 0;

  END:
    free(log_flags_copy);
    return rv;
}
예제 #4
0
/*
 *  status = appOptionsHandler(cData, opt_index, opt_arg);
 *
 *    This function is passed to skOptionsRegister(); it will be called
 *    by skOptionsParse() for each user-specified switch that the
 *    application has registered; it should handle the switch as
 *    required---typically by setting global variables---and return 1
 *    if the switch processing failed or 0 if it succeeded.  Returning
 *    a non-zero from from the handler causes skOptionsParse() to return
 *    a negative value.
 *
 *    The clientData in 'cData' is typically ignored; 'opt_index' is
 *    the index number that was specified as the last value for each
 *    struct option in appOptions[]; 'opt_arg' is the user's argument
 *    to the switch for options that have a REQUIRED_ARG or an
 *    OPTIONAL_ARG.
 */
static int
appOptionsHandler(
    clientData   UNUSED(cData),
    int                 opt_index,
    char        UNUSED(*opt_arg))
{

    switch ((appOptionsEnum)opt_index) {
      case OPT_HELP: /* remove this when options are added */
        assert(0);
        skAbort();
        break;
    }

    return 0; /* OK */
}
예제 #5
0
/*
 *  readerGetNextValidFile(&fc_src);
 *
 *    Pull the next file name off of the valid-queue and create a
 *    flowsource object to read the flowcap records in it.  Fills
 *    'fproc' with the new flowcap-source object and probe.
 *
 *    Return 0 on success.  Return -1 if getting the file name fails.
 *    If unable to open the file or file not of correct form, return
 *    -2 unless the --error-dir is set, in which case move the file
 *    there and try the next file.
 */
static int
readerGetNextValidFile(
    flow_proc_t        *fproc)
{
    skstream_t *fcfile = NULL;
    skpc_probe_t *probe = NULL;
    skPollDirErr_t pderr;
    char *filename;
    char path[PATH_MAX];
    int rv;

    do {
        /* Get next file from the directory poller */
        pderr = skPollDirGetNextFile(polldir, path, &filename);
        if (pderr != PDERR_NONE) {
            if (pderr == PDERR_STOPPED) {
                return -1;
            }
            CRITMSG("Fatal polldir error ocurred: %s",
                    ((pderr == PDERR_SYSTEM)
                     ? strerror(errno)
                     : skPollDirStrError(pderr)));
            skAbort();
        }

        INFOMSG((INPUT_MODE_TYPE_NAME " processing %s"), filename);

        /* open the file to create a source of records */
        rv = flowcapSourceCreateFromFile(path, &fcfile, &probe);
        if (rv) {
            rv = errorDirectoryInsertFile(path);
            if (rv != 0) {
                /* either no --error-dir (rv == 1) or problem moving
                 * the file (rv == -1).  either way, return an error
                 * code to the caller. */
                return -2;
            }
        }
    } while (fcfile == NULL);

    fproc->flow_src = fcfile;
    fproc->probe = probe;

    return 0;
}
예제 #6
0
/*
 *    Verify contents of silk.conf file matches the values we set here
 *    and set any globals we require.
 *
 *    Invoked from rwflowpack by packlogic->setup_fn
 */
static int
packLogicSetup(
    void)
{
    const size_t count = (sizeof(filetypeFormats)/sizeof(filetypeFormats[0]));
    uint32_t i;

#define FT_ASSERT(flowtype_id, flowtype_name)                           \
    sksiteFlowtypeAssert(plugin_path, (flowtype_id), "all", (flowtype_name))

    /* Make sure flowtype definitions match config file */
    FT_ASSERT(RW_IN,       "in");
    FT_ASSERT(RW_OUT,      "out");
    FT_ASSERT(RW_IN_WEB,   "inweb");
    FT_ASSERT(RW_OUT_WEB,  "outweb");
    FT_ASSERT(RW_IN_NULL,  "innull");
    FT_ASSERT(RW_OUT_NULL, "outnull");

    /* Confirm that number of flowtypes is not greater than the size
     * of the filetypeFormats[] array; abort if it is.  Complain if
     * the array is too large, but continue processing.  */
    if (count <= sksiteFlowtypeGetMaxID()) {
        skAppPrintErr(("File formats not specified for some flowtypes.\n"
                       "\tModify filetypeFormats[] in %s,\n"
                       "\trecompile and try running again."),
                      plugin_path);
        skAbort();
    } else if (count != (1u + sksiteFlowtypeGetMaxID())) {
        skAppPrintErr(("Warning: Number of flowtypes does not equal number\n"
                       "\tof file formats in filetypeFormats[] in %s"),
                      plugin_path);
    }

    /* Define all of our networks */
    for (i = 0; i < NUM_NETWORKS; ++i) {
        if (skpcNetworkAdd(i, net_names[i])) {
            skAppPrintErr("Unable to add network %" PRIu32 "->%s",
                          i, net_names[i]);
            return -1;
        }
    }

    return 0;
}
예제 #7
0
/*
 *  runPostCommand(command, filename, ident);
 *
 *    Spawn a new subprocess to run 'command'.  Formatting directives
 *    in 'command' may be expanded to hold to the 'filename' that has
 *    just been received and the 'ident' of the rwsender that sent the
 *    file.
 */
static void
runPostCommand(
    const char         *command,
    const char         *file,
    const char         *ident)
{
    sigset_t sigs;
    pid_t pid;
    size_t len;
    size_t file_len;
    size_t ident_len;
    const char *cp;
    const char *sp;
    char *expanded_cmd;
    char *exp_cp;

    /* Parent (original process) forks to create Child 1 */
    pid = fork();
    if (-1 == pid) {
        ERRMSG("Could not fork to run command: %s", strerror(errno));
        return;
    }

    /* Parent reaps Child 1 and returns */
    if (0 != pid) {
        /* Wait for Child 1 to exit. */
        while (waitpid(pid, NULL, 0) == -1) {
            if (EINTR != errno) {
                NOTICEMSG("Error waiting for child %ld: %s",
                          (long)pid, strerror(errno));
                break;
            }
        }
        return;
    }

    /* Disable log rotation in Child 1 */
    sklogDisableRotation();

    /* Child 1 forks to create Child 2 */
    pid = fork();
    if (pid == -1) {
        ERRMSG("Child could not fork for to run command: %s", strerror(errno));
        _exit(EXIT_FAILURE);
    }

    /* Child 1 immediately exits, so Parent can stop waiting */
    if (pid != 0) {
        _exit(EXIT_SUCCESS);
    }

    /* Only Child 2 makes it here */

    /* Unmask signals */
    sigemptyset(&sigs);
    sigprocmask(SIG_SETMASK, &sigs, NULL);

    /* Determine length of buffer needed for the expanded command
     * string and allocate it.  */
    len = strlen(command);
    file_len = strlen(file);
    ident_len = strlen(ident);
    cp = command;
    while (NULL != (cp = strchr(cp, (int)'%'))) {
        ++cp;
        switch (*cp) {
          case '%':
            --len;
            break;
          case 's':
            len += file_len - 2;
            break;
          case 'I':
            len += ident_len - 2;
            break;
          default:
            skAbortBadCase((int)(*cp));
        }
        ++cp;
    }
    expanded_cmd = (char*)malloc(len + 1);
    if (expanded_cmd == NULL) {
        WARNINGMSG("Unable to allocate memory to create command string");
        _exit(EXIT_FAILURE);
    }

    /* Copy command into buffer, handling %-expansions */
    cp = command;
    exp_cp = expanded_cmd;
    while (NULL != (sp = strchr(cp, (int)'%'))) {
        /* copy text we just jumped over */
        strncpy(exp_cp, cp, sp - cp);
        exp_cp += (sp - cp);
        /* handle conversion */
        switch (*(sp + 1)) {
          case '%':
            *exp_cp = '%';
            ++exp_cp;
            break;
          case 's':
            strcpy(exp_cp, file);
            exp_cp += file_len;
            break;
          case 'I':
            strcpy(exp_cp, ident);
            exp_cp += ident_len;
            break;
          default:
            skAbortBadCase((int)(*(sp+1)));
        }
        cp = sp + 2;
        assert(len >= (size_t)(exp_cp - expanded_cmd));
    }
    strcpy(exp_cp, cp);
    expanded_cmd[len] = '\0';

    /* Execute the command */
    DEBUGMSG("Invoking /bin/sh -c %s", expanded_cmd);
    if (execl("/bin/sh", "sh", "-c", expanded_cmd, (char*)NULL)
        == -1)
    {
        ERRMSG(("Error invoking /bin/sh: %s"),
               strerror(errno));
        _exit(EXIT_FAILURE);
    }

    /* Should never get here. */
    skAbort();
}
예제 #8
0
/*
 *  status = augsnmpoutioPrepare(&stream);
 *
 *    Sets the record version to the default if it is unspecified,
 *    checks that the record format supports the requested record
 *    version, sets the record length, and sets the pack and unpack
 *    functions for this record format and version.
 */
int
augsnmpoutioPrepare(
    skstream_t         *stream)
{
#define FILE_FORMAT "FT_RWAUGSNMPOUT"
    sk_file_header_t *hdr = stream->silk_hdr;
    int rv = SKSTREAM_OK; /* return value */

    assert(skHeaderGetFileFormat(hdr) == FT_RWAUGSNMPOUT);

    /* Set version if none was selected by caller */
    if ((stream->io_mode == SK_IO_WRITE)
        && (skHeaderGetRecordVersion(hdr) == SK_RECORD_VERSION_ANY))
    {
        skHeaderSetRecordVersion(hdr, DEFAULT_RECORD_VERSION);
    }

    /* version check; set values based on version */
    switch (skHeaderGetRecordVersion(hdr)) {
      case 5:
        stream->rwUnpackFn = &augsnmpoutioRecordUnpack_V5;
        stream->rwPackFn   = &augsnmpoutioRecordPack_V5;
        break;
      case 4:
        stream->rwUnpackFn = &augsnmpoutioRecordUnpack_V4;
        stream->rwPackFn   = &augsnmpoutioRecordPack_V4;
        break;
      case 3:
      case 2:
      case 1:
        /* V1 and V2 differ only in the padding of the header */
        /* V2 and V3 differ only in that V3 supports compression on
         * read and write; V2 supports compression only on read */
        stream->rwUnpackFn = &augsnmpoutioRecordUnpack_V1;
        stream->rwPackFn   = &augsnmpoutioRecordPack_V1;
        break;
      case 0:
      default:
        rv = SKSTREAM_ERR_UNSUPPORT_VERSION;
        goto END;
    }

    stream->recLen = augsnmpoutioGetRecLen(skHeaderGetRecordVersion(hdr));

    /* verify lengths */
    if (stream->recLen == 0) {
        skAppPrintErr("Record length not set for %s version %u",
                      FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr));
        skAbort();
    }
    if (stream->recLen != skHeaderGetRecordLength(hdr)) {
        if (0 == skHeaderGetRecordLength(hdr)) {
            skHeaderSetRecordLength(hdr, stream->recLen);
        } else {
            skAppPrintErr(("Record length mismatch for %s version %u\n"
                           "\tcode = %" PRIu16 " bytes;  header = %lu bytes"),
                          FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr),
                          stream->recLen,
                          (unsigned long)skHeaderGetRecordLength(hdr));
            skAbort();
        }
    }

  END:
    return rv;
}
예제 #9
0
/*
 *  status = genericioPrepare(&rwIOSPtr);
 *
 *    Sets the record version to the default if it is unspecified,
 *    checks that the record format supports the requested record
 *    version, sets the record length, and sets the pack and unpack
 *    functions for this record format and version.
 */
int
genericioPrepare(
    skstream_t         *rwIOS)
{
#define FILE_FORMAT "FT_RWGENERIC"
    sk_file_header_t *hdr = rwIOS->silk_hdr;
    int rv = SKSTREAM_OK; /* return value */

    assert(skHeaderGetFileFormat(hdr) == FT_RWGENERIC);

    /* Set version if none was selected by caller */
    if ((rwIOS->io_mode == SK_IO_WRITE)
        && (skHeaderGetRecordVersion(hdr) == SK_RECORD_VERSION_ANY))
    {
        skHeaderSetRecordVersion(hdr, DEFAULT_RECORD_VERSION);
    }

    /* version check; set values based on version */
    switch (skHeaderGetRecordVersion(hdr)) {
      case 5:
        rwIOS->rwUnpackFn = &genericioRecordUnpack_V5;
        rwIOS->rwPackFn   = &genericioRecordPack_V5;
        break;
      case 4:
      case 3:
        /* V3 and V4 differ only in that V4 supports compression on
         * read and write; V3 supports compression only on read */
        rwIOS->rwUnpackFn = &genericioRecordUnpack_V3;
        rwIOS->rwPackFn   = &genericioRecordPack_V3;
        break;
      case 2:
        rwIOS->rwUnpackFn = &genericioRecordUnpack_V2;
        rwIOS->rwPackFn   = &genericioRecordPack_V2;
        break;
      case 1:
      case 0:
        /* Version 0 and Version 1 records are nearly the same; the
         * on-disk Version 0 records included the 3 bytes of in-core
         * padding; the on-disk Version 1 records do not include these
         * 3 bytes. */
        rwIOS->rwUnpackFn = &genericioRecordUnpack_V1;
        rwIOS->rwPackFn   = &genericioRecordPack_V1;
        break;
      default:
        rv = SKSTREAM_ERR_UNSUPPORT_VERSION;
        goto END;
    }

    rwIOS->recLen = genericioGetRecLen(skHeaderGetRecordVersion(hdr));

    /* verify lengths */
    if (rwIOS->recLen == 0) {
        skAppPrintErr("Record length not set for %s version %u",
                      FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr));
        skAbort();
    }
    if (rwIOS->recLen != skHeaderGetRecordLength(hdr)) {
        if (0 == skHeaderGetRecordLength(hdr)) {
            skHeaderSetRecordLength(hdr, rwIOS->recLen);
        } else {
            skAppPrintErr(("Record length mismatch for %s version %u\n"
                           "\tcode = %" PRIu16 " bytes;  header = %lu bytes"),
                          FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr),
                          rwIOS->recLen,
                          (unsigned long)skHeaderGetRecordLength(hdr));
            skAbort();
        }
    }

  END:
    return rv;
}
예제 #10
0
/*
 *    Return the number of valid entries in the sk_file_format_names[]
 *    array defined in silk_files.h.
 */
static size_t
fileFormatGetCount(
    void)
{
    static size_t file_format_count = 0;
    size_t count;
    size_t len;
    size_t i;

    if (file_format_count) {
        /* already initialized */
        return file_format_count;
    }

    /* get the length of the sk_file_format_names[] array */
    count = sizeof(sk_file_format_names)/sizeof(sk_file_format_names[0]);

    /* loop over sk_file_format_names[] until we find a NULL name or a
     * name that is an empty string */
    for (i = 0; i < count; ++i) {
        if (NULL == sk_file_format_names[i]) {
            break;
        }

        len = strlen(sk_file_format_names[i]);
        if (0 == len) {
            break;
        }

        /* check the length of the file format name */
        if (len > SK_MAX_STRLEN_FILE_FORMAT) {
            skAppPrintErr(("FATAL! sk_file_format_names[] in silk_files.h"
                           " contains a name '%s' whose length (%" SK_PRIuZ
                           ") is longer than the maximum allowed (%u)"),
                          sk_file_format_names[i], len,
                          SK_MAX_STRLEN_FILE_FORMAT);
            skAbort();
        }
    }

    if (i >= UINT8_MAX) {
        skAppPrintErr("FATAL! sk_file_format_names[] in silk_files.h"
                      " contains more than %u entries",
                      UINT8_MAX - 1u);
        skAbort();
    }
    if (0 == i) {
        skAppPrintErr("FATAL! sk_file_format_names[] in silk_files.h"
                      " does not contain any names");
        skAbort();
    }

    /* only the final entry in array should be NULL or the empty
     * string */
    if (count - i > 1) {
        skAppPrintErr(("FATAL! sk_file_format_names[] in silk_files.h"
                       " contains a NULL or empty-string entry at"
                       " position %" SK_PRIuZ),
                      i);
        skAbort();
    }

    file_format_count = i;
    return file_format_count;
}