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