[tools/bgpgrep] Add support for -o option

This commit is contained in:
Lorenzo Cogotti 2021-08-03 23:55:48 +02:00
parent 11dc537d21
commit 49e4ee3bfa
4 changed files with 82 additions and 41 deletions

View File

@ -17,7 +17,9 @@ utility reads each possibly compressed Multithreaded Routing Toolkit
(MRT) (MRT)
dump file specified by dump file specified by
.IR FILES .IR FILES
and formats its contents to standard output. and formats its contents to standard output (or any custom output file
as specified by
.IR OPTIONS ).
.IR @UTILITY@ .IR @UTILITY@
may optionally evaluate a predicate defined by may optionally evaluate a predicate defined by
.IR EXPRESSION .IR EXPRESSION
@ -37,8 +39,8 @@ regardless of any filtering rule.
prints diagnostics to standard error, prints diagnostics to standard error,
it detects and tolerates data corruption as much as possible. it detects and tolerates data corruption as much as possible.
Corruption within a BGP message causes only the affected message to be Corruption within a BGP message causes only the affected message to be
dropped. Unrecoverable corruption within the entire MRT dump file causes dropped. Though unrecoverable errors affecting the entire MRT dump file may
the whole file to be dropped, require it to be dropped as a whole,
.IR @UTILITY@ .IR @UTILITY@
will then move to the next file in will then move to the next file in
.IR FILES , .IR FILES ,
@ -46,7 +48,7 @@ if any.
.P .P
Such events are always reported with reasonable diagnostic errors. Such events are always reported with reasonable diagnostic errors.
Parsed data up to the corruption point may still be printed to Parsed data up to the corruption point may still be printed to
standard output. regular output.
.SH OPTIONS .SH OPTIONS
.IR @UTILITY@ .IR @UTILITY@
@ -74,6 +76,15 @@ may ease visualization by surrounding some output with color escape sequences,
on terminals that support this feature. This option forces colored text on terminals that support this feature. This option forces colored text
output off. output off.
.IP "\fB\-o \fI<file>\fP" 10
Write output to
.BR file .
Instead of using standard output,
.IR @UTILITY@
shall format MRT contents to the specified file. If option occurs
multiple times, last specified file is used. This option forces colored
text output off.
.IP "\fB\-h or \-\-help\fP" 10 .IP "\fB\-h or \-\-help\fP" 10
Prints a short help message, summarizing Prints a short help message, summarizing
.IR @UTILITY@ .IR @UTILITY@
@ -582,8 +593,11 @@ supported compression formats. If the file extension is not recognized,
or there is no extension, then it is assumed to be uncompressed. or there is no extension, then it is assumed to be uncompressed.
.SH STDOUT .SH STDOUT
The standard output is used to print a human readable text representation of Unless redirected explicitly via
BGP message data, nothing else shall be written to the standard output. .IR OPTIONS ,
the standard output is used to print a human readable text
representation of BGP message data, nothing else shall be written
to the standard output.
.IR @UTILITY@ .IR @UTILITY@
may detect and treat as error whenever the standard output is a regular file, may detect and treat as error whenever the standard output is a regular file,
and is the same file as any of the and is the same file as any of the
@ -597,7 +611,9 @@ section.
.SH STDERR .SH STDERR
The standard error is used only for diagnostic messages and error reporting. The standard error is used only for diagnostic messages and error reporting.
Any BGP message output is exclusive to standard output. Any BGP message output is exclusive to standard output or any file explicitly
specified by
.IR OPTIONS .
.SH EXAMPLES .SH EXAMPLES
This section contains some useful examples, starting from trivial ones, This section contains some useful examples, starting from trivial ones,

View File

@ -38,6 +38,7 @@ BgpgrepState S;
typedef enum { typedef enum {
NO_COLOR_FLAG, NO_COLOR_FLAG,
DUMP_BYTECODE_FLAG, DUMP_BYTECODE_FLAG,
OUTPUT_FLAG,
NUM_FLAGS NUM_FLAGS
} BgpgrepOpt; } BgpgrepOpt;
@ -49,6 +50,9 @@ static Optflag options[] = {
[DUMP_BYTECODE_FLAG] = { [DUMP_BYTECODE_FLAG] = {
'-', "dump-bytecode", NULL, "Dump BGP VM bytecode to stderr (debug)", ARG_NONE '-', "dump-bytecode", NULL, "Dump BGP VM bytecode to stderr (debug)", ARG_NONE
}, },
[OUTPUT_FLAG] = {
'o', NULL, "file", "Write output to file", ARG_REQ
},
[NUM_FLAGS] = { '\0' } [NUM_FLAGS] = { '\0' }
}; };
@ -63,34 +67,14 @@ static void Bgpgrep_SetupCommandLine(char *argv0)
com_shortDescr = "Filter and print BGP data within MRT dumps"; com_shortDescr = "Filter and print BGP data within MRT dumps";
com_longDescr = com_longDescr =
"Reads MRT dumps in various formats, applying filtering rules\n" "Reads MRT dumps in various formats, applying filtering rules\n"
"to each BGP message therein, then outputs every passing message to stdout.\n" "to each BGP message therein, then outputs every passing message\n"
"to stdout (or any custom output file defined by OPTIONS).\n"
"If - is found inside FILES, then input is read from stdin.\n" "If - is found inside FILES, then input is read from stdin.\n"
"If no FILES arguments are provided, then input\n" "If no FILES arguments are provided, then input\n"
"is implicitly expected from stdin.\n" "is implicitly expected from stdin.\n"
"Any diagnostic message is logged to stderr."; "Any diagnostic message is logged to stderr.";
} }
static void Bgpgrep_ApplyProgramOptions(void)
{
S.noColor = options[NO_COLOR_FLAG].flagged;
S.dumpBytecode = options[DUMP_BYTECODE_FLAG].flagged;
}
static int CountFileArguments(int argc, char **argv)
{
int i;
for (i = 0; i < argc; i++) {
const char *arg = argv[i];
if (arg[0] == '-' && arg[1] != '\0')
break;
if (strcmp(arg, "(") == 0 || strcmp(arg, "!") == 0)
break;
}
return i;
}
void Bgpgrep_Fatal(const char *fmt, ...) void Bgpgrep_Fatal(const char *fmt, ...)
{ {
va_list va; va_list va;
@ -126,6 +110,46 @@ void Bgpgrep_Warning(const char *fmt, ...)
Sys_Print(STDERR, "\n"); Sys_Print(STDERR, "\n");
} }
static void Bgpgrep_ApplyProgramOptions(void)
{
S.noColor = options[NO_COLOR_FLAG].flagged;
S.dumpBytecode = options[DUMP_BYTECODE_FLAG].flagged;
if (options[OUTPUT_FLAG].flagged) {
const char *filename = options[OUTPUT_FLAG].optarg;
Fildes fd = Sys_Fopen(filename, FM_WRITE, /*hints=*/0);
if (fd == FILDES_BAD)
Bgpgrep_Fatal("Can't open output file \"%s\"", filename);
S.outf = STM_FILDES(fd);
S.outfOps = Stm_FildesOps;
S.noColor = TRUE;
} else {
S.outf = STM_CONHN(STDOUT);
S.outfOps = Stm_ConOps;
}
if (!S.noColor && Sys_IsVt100Console(STDOUT))
S.outFmt = Bgp_IsolarioFmtWc; // console supports colors
else
S.outFmt = Bgp_IsolarioFmt;
}
static int CountFileArguments(int argc, char **argv)
{
int i;
for (i = 0; i < argc; i++) {
const char *arg = argv[i];
if (arg[0] == '-' && arg[1] != '\0')
break;
if (strcmp(arg, "(") == 0 || strcmp(arg, "!") == 0)
break;
}
return i;
}
void Bgpgrep_DropMessage(const char *fmt, ...) void Bgpgrep_DropMessage(const char *fmt, ...)
{ {
va_list va; va_list va;
@ -278,11 +302,6 @@ NOINLINE static void Bgpgrep_HandleBgpError(BgpRet err, Srcloc *loc, void *obj)
static void Bgpgrep_Init(void) static void Bgpgrep_Init(void)
{ {
if (!S.noColor && Sys_IsVt100Console(STDOUT))
S.outFmt = Bgp_IsolarioFmtWc; // console supports colors
else
S.outFmt = Bgp_IsolarioFmt;
Mrtrecord *rec = &S.rec; Mrtrecord *rec = &S.rec;
Bgpmsg *msg = &S.msg; Bgpmsg *msg = &S.msg;
@ -389,6 +408,9 @@ static int Bgpgrep_CleanupAndExit(void)
t = tn; t = tn;
} }
if (S.outfOps->Close) S.outfOps->Close(S.outf);
return (S.nerrors > 0) ? EXIT_FAILURE : EXIT_SUCCESS; return (S.nerrors > 0) ? EXIT_FAILURE : EXIT_SUCCESS;
} }

View File

@ -68,7 +68,7 @@ static void FixBgpAttributeTableForRib(Bgpattrtab tab, Boolean isRibv2)
static void OutputBgp4mp(const Mrthdr *hdr, Bgpattrtab tab) static void OutputBgp4mp(const Mrthdr *hdr, Bgpattrtab tab)
{ {
S.lenientBgpErrors = TRUE; S.lenientBgpErrors = TRUE;
S.outFmt->DumpBgp4mp(hdr, STM_CONHN(STDOUT), Stm_ConOps, tab); S.outFmt->DumpBgp4mp(hdr, S.outf, S.outfOps, tab);
S.lenientBgpErrors = FALSE; S.lenientBgpErrors = FALSE;
} }
@ -104,7 +104,7 @@ void BgpgrepD_Bgp4mp(void)
static void OutputZebra(const Mrthdr *hdr, Bgpattrtab tab) static void OutputZebra(const Mrthdr *hdr, Bgpattrtab tab)
{ {
S.lenientBgpErrors = TRUE; S.lenientBgpErrors = TRUE;
S.outFmt->DumpZebra(hdr, STM_CONHN(STDOUT), Stm_ConOps, tab); S.outFmt->DumpZebra(hdr, S.outf, S.outfOps, tab);
S.lenientBgpErrors = FALSE; S.lenientBgpErrors = FALSE;
} }
@ -149,7 +149,7 @@ static void OutputRibv2(const Mrthdr *hdr,
Bgpattrtab tab) Bgpattrtab tab)
{ {
S.lenientBgpErrors = TRUE; S.lenientBgpErrors = TRUE;
S.outFmt->DumpRibv2(hdr, peerent, ent, STM_CONHN(STDOUT), Stm_ConOps, tab); S.outFmt->DumpRibv2(hdr, peerent, ent, S.outf, S.outfOps, tab);
S.lenientBgpErrors = FALSE; S.lenientBgpErrors = FALSE;
} }
@ -219,7 +219,7 @@ void BgpgrepD_TableDumpv2(void)
static void OutputRib(const Mrthdr *hdr, const Mrtribent *ent, Bgpattrtab tab) static void OutputRib(const Mrthdr *hdr, const Mrtribent *ent, Bgpattrtab tab)
{ {
S.lenientBgpErrors = TRUE; S.lenientBgpErrors = TRUE;
S.outFmt->DumpRib(hdr, ent, STM_CONHN(STDOUT), Stm_ConOps, tab); S.outFmt->DumpRib(hdr, ent, S.outf, S.outfOps, tab);
S.lenientBgpErrors = FALSE; S.lenientBgpErrors = FALSE;
} }

View File

@ -104,10 +104,13 @@ typedef jmp_buf frame_buf;
typedef struct BgpgrepState BgpgrepState; typedef struct BgpgrepState BgpgrepState;
struct BgpgrepState { struct BgpgrepState {
const char *filename; // current file being processed // Output
const BgpDumpfmt *outFmt; const BgpDumpfmt *outFmt;
void *outf;
const StmOps *outfOps;
// MRT input file stream // MRT input file stream
const char *filename; // current file being processed
void *inf; // NOTE: may be NULL even in a file is open void *inf; // NOTE: may be NULL even in a file is open
const StmOps *infOps; // if NULL no file is open const StmOps *infOps; // if NULL no file is open