mirror of
				https://codeberg.org/1414codeforge/ubgpsuite.git
				synced 2025-06-05 21:29:11 +02:00 
			
		
		
		
	[tools/peerindex] Add PEER INDEX TABLE inspection tool: peerindex
This commit is contained in:
		
							
								
								
									
										247
									
								
								tools/peerindex/peerindex.1.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								tools/peerindex/peerindex.1.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,247 @@ | |||||||
|  | '\" et | ||||||
|  | .TH PEERINDEX 1 @VERSION@ PEERINDEX "User Commands" | ||||||
|  | .\" | ||||||
|  | .SH NAME | ||||||
|  | @UTILITY@ | ||||||
|  | \(em filter and print BGP data within MRT dumps | ||||||
|  | .SH SYNOPSIS | ||||||
|  | .LP | ||||||
|  | .nf | ||||||
|  | @UTILITY@ \fB[\fIOPTIONS\fB]\fR... \fB[\fIFILES\fB]\fR... | ||||||
|  | .fi | ||||||
|  |  | ||||||
|  | .SH DESCRIPTION | ||||||
|  | The | ||||||
|  | .IR @UTILITY@ | ||||||
|  | utility reads each possibly compressed Multithreaded Routing Toolkit | ||||||
|  | (MRT) | ||||||
|  | Routing Information Base | ||||||
|  | (RIB) | ||||||
|  | file specified by | ||||||
|  | .IR FILES , | ||||||
|  | and extracts information related to PEER INDEX TABLE | ||||||
|  | records. | ||||||
|  | .IR @UTILITY@ | ||||||
|  | processes and formats such records according to the options specified by | ||||||
|  | .IR OPTIONS . | ||||||
|  | .IR @UTILITY@ | ||||||
|  | prints diagnostics to standard error, | ||||||
|  | it detects and tolerates data corruption as much as possible. | ||||||
|  | If data corruption cannot be tolerated, the entire MRT dump file is dropped, | ||||||
|  | .IR @UTILITY@ | ||||||
|  | will then move to the next file in | ||||||
|  | .IR FILES , | ||||||
|  | if any. | ||||||
|  | .P | ||||||
|  | Such events are always reported with reasonable diagnostic errors. | ||||||
|  | .P | ||||||
|  | See the | ||||||
|  | .IR EXAMPLES | ||||||
|  | section below for usage examples. | ||||||
|  |  | ||||||
|  | .SH OPTIONS | ||||||
|  | The following options are supported: | ||||||
|  |  | ||||||
|  | .IP "\fB\-r or \-\-only\-refs\fP" 10 | ||||||
|  | By default | ||||||
|  | .IR @UTILITY@ | ||||||
|  | writes all PEER INDEX TABLE entries, this option causes | ||||||
|  | .IR @UTILITY@ | ||||||
|  | to only print peers that are referenced by RIB entries. | ||||||
|  |  | ||||||
|  | .IP "\fB\-h or \-\-help\fP" 10 | ||||||
|  | Prints a short help message, summarizing | ||||||
|  | .IR @UTILITY@ | ||||||
|  | functionality. | ||||||
|  |  | ||||||
|  | .IP "\fB\-?\fP" 10 | ||||||
|  | Equivalent to | ||||||
|  | .BR \-h . | ||||||
|  |  | ||||||
|  | .SH "LINE ORIENTED OUTPUT" | ||||||
|  | .IR @UTILITY@ | ||||||
|  | splits each PEER INDEX TABLE record into multiple lines, every line represents a peer. | ||||||
|  | Note that | ||||||
|  | .IR OPTIONS | ||||||
|  | may cause some peers inside PEER INDEX TABLES to be discarded (See the | ||||||
|  | .IR OPTIONS | ||||||
|  | section for details). | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Each peer is formatted as the following `|' separated fields: | ||||||
|  | .RS 4 | ||||||
|  | .sp | ||||||
|  | .RS 4 | ||||||
|  | .nf | ||||||
|  |  | ||||||
|  | PEER ENTRY|ASN32BIT | ||||||
|  | .fi | ||||||
|  | .P | ||||||
|  | .RE | ||||||
|  | .P | ||||||
|  | Fields have the following meaning: | ||||||
|  |  | ||||||
|  | .IP "\fBPEER ENTRY\fP" 4 | ||||||
|  | The peer entry inside PEER INDEX TABLE, displayed as `peer\-address peer\-asn'. | ||||||
|  |  | ||||||
|  | .IP "\fBASN32BIT\fP" 4 | ||||||
|  | May be either 1, if the peer AS number was encoded within 32 bits, or 0 otherwise. | ||||||
|  | .P | ||||||
|  | Note that this flag being 0 does not necessarily imply that the peer does not have | ||||||
|  | ASN32BIT capability, it is merely an indicator of how the peer entry was encoded within | ||||||
|  | the PEER INDEX TABLE record (namely, it only used 2 octets to encode its ASN). | ||||||
|  | .P | ||||||
|  | .RE | ||||||
|  |  | ||||||
|  | Multiple PEER INDEX TABLES are concatenated within the output, meaning that | ||||||
|  | the same peer appearing in multiple PEER INDEX TABLE records may appear twice in | ||||||
|  | .IR @UTILITY@ | ||||||
|  | output. | ||||||
|  |  | ||||||
|  | .SH "EXIT STATUS" | ||||||
|  | The following exit values are returned: | ||||||
|  | .IP "\00" 6 | ||||||
|  | All input data was scanned successfully, | ||||||
|  | and data was written to output correctly. | ||||||
|  | .IP >0 6 | ||||||
|  | Errors were detected in input data, write error occurred, | ||||||
|  | or an unrecoverable error occurred (such as out of memory errors). | ||||||
|  |  | ||||||
|  | .SH STDIN | ||||||
|  | The standard input is used only if no | ||||||
|  | .IR FILES | ||||||
|  | arguments are provided, or when any of the specified | ||||||
|  | .IR FILES | ||||||
|  | arguments is `\-' , in which case MRT data is read from standard input at that | ||||||
|  | point, up to an <end\-of\-file>. | ||||||
|  | .P | ||||||
|  | Whenever | ||||||
|  | .IR @UTILITY@ | ||||||
|  | reads from standard input, MRT data is assumed to be uncompressed. | ||||||
|  |  | ||||||
|  | .SH "INPUT FILES" | ||||||
|  | .IR @UTILITY@ | ||||||
|  | supports most MRT dump formats as written by the majority of Route Collecting | ||||||
|  | projects (see the | ||||||
|  | .IR STANDARDS | ||||||
|  | section below for additional references). | ||||||
|  | MRT dumps may be provided either in their plain uncompressed form, or | ||||||
|  | as files compressed by | ||||||
|  | .IR gzip (1), | ||||||
|  | .IR bzip2 (1), | ||||||
|  | or | ||||||
|  | .IR xz (1). | ||||||
|  | .IR @UTILITY@ | ||||||
|  | performs appropriate decompression on the fly. | ||||||
|  | File extension is used, in a case insensitive way, to discriminate among | ||||||
|  | supported compression formats. If the file extension is not recognized, | ||||||
|  | or there is no extension, then it is assumed to be uncompressed. | ||||||
|  |  | ||||||
|  | .SH STDOUT | ||||||
|  | The standard output is used to print a human readable text representation of | ||||||
|  | PEER INDEX TABLE contents, nothing else shall be written to the standard output. | ||||||
|  | .IR @UTILITY@ | ||||||
|  | may detect and treat as error whenever the standard output is a regular file, | ||||||
|  | and is the same file as any of the | ||||||
|  | .IR FILES | ||||||
|  | arguments. | ||||||
|  | The default output format used by | ||||||
|  | .IR @UTILITY@ | ||||||
|  | is documented in the | ||||||
|  | .IR "LINE ORIENTED OUTPUT" | ||||||
|  | section. | ||||||
|  |  | ||||||
|  | .SH STDERR | ||||||
|  | The standard error is used only for diagnostic messages and error reporting. | ||||||
|  |  | ||||||
|  | .SH EXAMPLES | ||||||
|  | This section contains some useful examples, demonstrating basic | ||||||
|  | .IR @UTILITY@ | ||||||
|  | usage. | ||||||
|  |  | ||||||
|  | .IP \[bu] | ||||||
|  | The following is the simplest way to invoke | ||||||
|  | .IR @UTILITY@ : | ||||||
|  | .nf | ||||||
|  | \& | ||||||
|  | .in +2m | ||||||
|  | @UTILITY@ | ||||||
|  | .in | ||||||
|  | \& | ||||||
|  | .fi | ||||||
|  | It formats and prints all peers inside the uncompressed MRT | ||||||
|  | RIB input data it receives from standard input. | ||||||
|  |  | ||||||
|  | .IP \[bu] | ||||||
|  | The following command: | ||||||
|  | .nf | ||||||
|  | \& | ||||||
|  | .in +2m | ||||||
|  | @UTILITY@ -r | ||||||
|  | .in | ||||||
|  | \& | ||||||
|  | .fi | ||||||
|  | formats and print only peer entries referenced by at least one RIB entry | ||||||
|  | inside the uncompressed MRT RIB input data coming from standard input. | ||||||
|  |  | ||||||
|  | .IP \[bu] | ||||||
|  | The following is equivalent to the previous example: | ||||||
|  | .nf | ||||||
|  | \& | ||||||
|  | .in +2m | ||||||
|  | @UTILITY@ -r ./rib.1.bz2 | ||||||
|  | .in | ||||||
|  | \& | ||||||
|  | .fi | ||||||
|  | but takes MRT input data from a | ||||||
|  | .IR bzip (1) | ||||||
|  | compressed file. | ||||||
|  |  | ||||||
|  | .IP \[bu] | ||||||
|  | The following is equivalent to the previous example: | ||||||
|  | .nf | ||||||
|  | \& | ||||||
|  | .in +2m | ||||||
|  | @UTILITY@ -r ./rib.*.gz | ||||||
|  | .in | ||||||
|  | \& | ||||||
|  | .fi | ||||||
|  | but takes MRT input data from multiple | ||||||
|  | .IR gzip (1) | ||||||
|  | compressed files resulting from the glob expansion. | ||||||
|  | Most likely the command output is going to | ||||||
|  | contain data coming from multiple PEER INDEX TABLES, | ||||||
|  | peers may appear more than once. | ||||||
|  |  | ||||||
|  | .IP \[bu] | ||||||
|  | The following command: | ||||||
|  | .nf | ||||||
|  | \& | ||||||
|  | .in +2m | ||||||
|  | @UTILITY@ ./rib.*.gz | ||||||
|  | .in | ||||||
|  | \& | ||||||
|  | .fi | ||||||
|  | is similar to the previous example, but does not remove | ||||||
|  | unreferenced peer entries from output. | ||||||
|  |  | ||||||
|  | .SH SEE ALSO | ||||||
|  | .IR bgpgrep (1), | ||||||
|  | .IR awk (1), | ||||||
|  | .IR grep (1) | ||||||
|  |  | ||||||
|  | .SH STANDARDS | ||||||
|  | The | ||||||
|  | .IR @UTILITY@ | ||||||
|  | utility conforms to: | ||||||
|  | .IP \[bu] 2m | ||||||
|  | .IR "RFC 6396" " \-" "Multi\-Threaded Routing Toolkit (MRT) Routing Information Export Format" | ||||||
|  | .IP \[bu] 2m | ||||||
|  | .IR "RFC 8050" " \- " "Multi\-Threaded Routing Toolkit (MRT) Routing Information Export Format with BGP Additional Path Extensions" | ||||||
|  |  | ||||||
|  | .SH AUTHOR | ||||||
|  | .IR @UTILITY@ | ||||||
|  | was written by | ||||||
|  | .UR lcg@\:inventati.\:org | ||||||
|  | Lorenzo Cogotti | ||||||
|  | .UE . | ||||||
							
								
								
									
										380
									
								
								tools/peerindex/peerindex.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										380
									
								
								tools/peerindex/peerindex.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,380 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-3.0-or-later | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * \file peerindex.c | ||||||
|  |  * | ||||||
|  |  * `peerindex` main entry point and general command line parsing. | ||||||
|  |  * | ||||||
|  |  * \copyright The DoubleFourteen Code Forge (C) All Rights Reserved | ||||||
|  |  * \author    Lorenzo Cogotti | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "peerindex_local.h" | ||||||
|  |  | ||||||
|  | #include "bgp/bytebuf.h" | ||||||
|  | #include "cpr/flate.h" | ||||||
|  | #include "cpr/bzip2.h" | ||||||
|  | #include "cpr/xz.h" | ||||||
|  | #include "sys/endian.h" | ||||||
|  | #include "sys/fs.h" | ||||||
|  | #include "sys/con.h" | ||||||
|  | #include "sys/sys.h" | ||||||
|  | #include "argv.h" | ||||||
|  | #include "bufio.h" | ||||||
|  | #include "strlib.h" | ||||||
|  |  | ||||||
|  | #include <assert.h> | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #define BYTEBUFSIZ (256 * 1024) | ||||||
|  |  | ||||||
|  | typedef enum { | ||||||
|  | 	ONLY_REFS_FLAG, | ||||||
|  |  | ||||||
|  | 	NUM_FLAGS | ||||||
|  | } PeerindexOpt; | ||||||
|  |  | ||||||
|  | static Optflag options[] = { | ||||||
|  | 	[ONLY_REFS_FLAG] = { | ||||||
|  | 		'r', "only-refs", NULL, "Only dump peers referenced by RIBs", ARG_NONE | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	[NUM_FLAGS] = { '\0' } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static PeerindexState S; | ||||||
|  | static BGP_FIXBYTEBUF(BYTEBUFSIZ) bgp_msgBuf = { BYTEBUFSIZ }; | ||||||
|  |  | ||||||
|  | static void Peerindex_SetupCommandLine(char *argv0) | ||||||
|  | { | ||||||
|  | 	Sys_StripPath(argv0, NULL); | ||||||
|  | 	Sys_StripFileExtension(argv0, NULL); | ||||||
|  |  | ||||||
|  | 	com_progName   = argv0; | ||||||
|  | 	com_synopsis   = "[OPTIONS...] [FILES...]"; | ||||||
|  | 	com_shortDescr = "MRT TABLE_DUMPV2 Peer Index Table inspection tool"; | ||||||
|  | 	com_longDescr  = | ||||||
|  | 		"Reads MRT dumps in various formats, and inspects the\n" | ||||||
|  | 		"MRT TABLE_DUMPV2 peer index table, and prints it to stdout.\n" | ||||||
|  | 		"If - is found inside FILES, then input is read from stdin.\n" | ||||||
|  | 		"If no FILES arguments are provided, then input\n" | ||||||
|  | 		"is implicitly expected from stdin.\n" | ||||||
|  | 		"Any diagnostic message is logged to stderr."; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void Peerindex_Warning(const char *fmt, ...) | ||||||
|  | { | ||||||
|  | 	va_list va; | ||||||
|  |  | ||||||
|  | 	Sys_Print(STDERR, com_progName); | ||||||
|  | 	Sys_Print(STDERR, ": "); | ||||||
|  | 	if (S.filename) { | ||||||
|  | 		Sys_Print(STDERR, S.filename); | ||||||
|  | 		Sys_Print(STDERR, ": "); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Sys_Print(STDERR, "WARNING: "); | ||||||
|  |  | ||||||
|  | 	va_start(va, fmt); | ||||||
|  | 	Sys_VPrintf(STDERR, fmt, va); | ||||||
|  | 	va_end(va); | ||||||
|  |  | ||||||
|  | 	Sys_Print(STDERR, "\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Peerindex_DropRecord(const char *fmt, ...) | ||||||
|  | { | ||||||
|  | 	va_list va; | ||||||
|  |  | ||||||
|  | 	Sys_Print(STDERR, com_progName); | ||||||
|  | 	Sys_Print(STDERR, ": "); | ||||||
|  |  | ||||||
|  | 	assert(S.filename); | ||||||
|  | 	Sys_Print(STDERR, S.filename); | ||||||
|  | 	Sys_Print(STDERR, ": "); | ||||||
|  |  | ||||||
|  | 	va_start(va, fmt); | ||||||
|  | 	Sys_VPrintf(STDERR, fmt, va); | ||||||
|  | 	va_end(va); | ||||||
|  |  | ||||||
|  | 	Sys_Print(STDERR, "\n"); | ||||||
|  | 	S.nerrors++; | ||||||
|  |  | ||||||
|  | 	// If we're dropping a record we have to kill S.rec | ||||||
|  | 	Bgp_ClearMrt(&S.rec); | ||||||
|  |  | ||||||
|  | 	// ...but don't drop PEER_INDEX_TABLE | ||||||
|  |  | ||||||
|  | 	longjmp(S.dropRecordFrame, 1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Peerindex_DropFile(const char *fmt, ...) | ||||||
|  | { | ||||||
|  | 	va_list va; | ||||||
|  |  | ||||||
|  | 	Sys_Print(STDERR, com_progName); | ||||||
|  | 	Sys_Print(STDERR, ": "); | ||||||
|  |  | ||||||
|  | 	assert(S.filename); | ||||||
|  | 	Sys_Print(STDERR, S.filename); | ||||||
|  | 	Sys_Print(STDERR, ": "); | ||||||
|  |  | ||||||
|  | 	va_start(va, fmt); | ||||||
|  | 	Sys_VPrintf(STDERR, fmt, va); | ||||||
|  | 	va_end(va); | ||||||
|  |  | ||||||
|  | 	Sys_Print(STDERR, "\n"); | ||||||
|  | 	S.nerrors++; | ||||||
|  |  | ||||||
|  | 	// Must clear PEER_INDEX_TABLE also, along with S.rec... | ||||||
|  | 	Bgp_ClearMrt(&S.rec); | ||||||
|  | 	Bgp_ClearMrt(&S.peerIndex); | ||||||
|  | 	S.hasPeerIndex = FALSE; | ||||||
|  |  | ||||||
|  | 	longjmp(S.dropFileFrame, 1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | NOINLINE static void Peerindex_HandleError(BgpRet err, Srcloc *loc, void *obj) | ||||||
|  | { | ||||||
|  | 	USED(obj); | ||||||
|  |  | ||||||
|  | 	// On out of memory we die with an appropriate backtrace | ||||||
|  | 	if (err == BGPENOMEM) { | ||||||
|  | 		loc->call_depth++;  // include this function itself | ||||||
|  |  | ||||||
|  | 		_Sys_OutOfMemory(loc->filename, loc->func, loc->line, loc->call_depth); | ||||||
|  | 	} | ||||||
|  | 	// On I/O error we drop the entire file | ||||||
|  | 	if (err == BGPEIO) | ||||||
|  | 		Peerindex_DropFile("I/O error while reading MRT dump");  // TODO: better diagnostics | ||||||
|  |  | ||||||
|  | 	// Hopefully we are not dealing with a programming error... | ||||||
|  | 	assert(err != BGPEBADMRTTYPE); | ||||||
|  | 	assert(BGP_ISMRTERR(err)); | ||||||
|  |  | ||||||
|  | 	if (err == BGPEBADPEERIDXCNT || err == BGPEBADRIBV2CNT) { | ||||||
|  | 		// Only warrant a warning | ||||||
|  | 		Peerindex_Warning("CORRUPT MRT RECORD: %s", Bgp_ErrorString(err)); | ||||||
|  | 		S.nerrors++; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Anything else requires a full record drop | ||||||
|  | 	Peerindex_DropRecord("SKIPPING MRT RECORD: %s", Bgp_ErrorString(err)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void Peerindex_ApplyProgramOptions(void) | ||||||
|  | { | ||||||
|  | 	if (options[ONLY_REFS_FLAG].flagged) | ||||||
|  | 		S.peerIndexClearVal = 0; | ||||||
|  | 	else | ||||||
|  | 		S.peerIndexClearVal = 0xff;  // so we always print the full table | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void Peerindex_Init(void) | ||||||
|  | { | ||||||
|  | 	S.rec.allocp = S.rec.allocp = &bgp_msgBuf; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const StmOps *Peerindex_OpenMrtDump(const char *filename, void **phn) | ||||||
|  | { | ||||||
|  | 	Fildes fh = Sys_Fopen(filename, FM_READ, FH_SEQ); | ||||||
|  | 	if (fh == FILDES_BAD) | ||||||
|  | 		Peerindex_DropFile("Can't open file"); | ||||||
|  |  | ||||||
|  | 	const char *ext = Sys_GetFileExtension(filename); | ||||||
|  |  | ||||||
|  | 	void *hn; | ||||||
|  | 	const StmOps *ops; | ||||||
|  |  | ||||||
|  | 	if (Df_stricmp(ext, ".bz2") == 0) { | ||||||
|  | 		hn  = Bzip2_OpenDecompress(STM_FILDES(fh), Stm_FildesOps, /*opts=*/NULL); | ||||||
|  | 		ops = Bzip2_StmOps; | ||||||
|  |  | ||||||
|  | 		Bzip2Ret err = Bzip2_GetErrStat(); | ||||||
|  | 		if (err) | ||||||
|  | 			Peerindex_DropFile("Can't read Bz2 archive: %s", Bzip2_ErrorString(err)); | ||||||
|  |  | ||||||
|  | 	} else if (Df_stricmp(ext, ".gz") == 0 || Df_stricmp(ext, ".z") == 0) { | ||||||
|  | 		hn  = Zlib_InflateOpen(STM_FILDES(fh), Stm_FildesOps, /*opts=*/NULL); | ||||||
|  | 		ops = Zlib_StmOps; | ||||||
|  |  | ||||||
|  | 		ZlibRet err = Zlib_GetErrStat(); | ||||||
|  | 		if (err) | ||||||
|  | 			Peerindex_DropFile("Can't read Zlib archive: %s", Zlib_ErrorString(err)); | ||||||
|  |  | ||||||
|  | 	} else if (Df_stricmp(ext, ".xz") == 0) { | ||||||
|  | 		hn  = Xz_OpenDecompress(STM_FILDES(fh), Stm_FildesOps, /*opts=*/NULL); | ||||||
|  | 		ops = Xz_StmOps; | ||||||
|  |  | ||||||
|  | 		XzRet err = Xz_GetErrStat(); | ||||||
|  | 		if (err) | ||||||
|  | 			Peerindex_DropFile("Can't read LZMA archive: %s", Xz_ErrorString(err)); | ||||||
|  |  | ||||||
|  | 	} else { | ||||||
|  | 		// Assume uncompressed file | ||||||
|  | 		hn  = STM_FILDES(fh); | ||||||
|  | 		ops = Stm_FildesOps; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	*phn = hn; | ||||||
|  | 	return ops; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void Peerindex_MarkPeerRefs(void) | ||||||
|  | { | ||||||
|  | 	Mrtribiterv2 it; | ||||||
|  | 	Mrtribentv2 *rib; | ||||||
|  |  | ||||||
|  | 	Bgp_StartMrtRibEntriesv2(&it, &S.rec); | ||||||
|  | 	while ((rib = Bgp_NextRibEntryv2(&it)) != NULL) { | ||||||
|  | 		Uint16 idx = beswap16(rib->peerIndex); | ||||||
|  | 		if (idx >= S.npeers) { | ||||||
|  | 			Peerindex_Warning("CORRUPT MRT RECORD: Peer index '%u' is out of range", (unsigned) idx); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		MARKPEERINDEX(S.peerIndexRefs, idx); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void Peerindex_DumpPeerIndexTable(void) | ||||||
|  | { | ||||||
|  | 	char buf[IPV6_STRLEN + 1]; | ||||||
|  | 	Stmbuf sb; | ||||||
|  |  | ||||||
|  | 	Ipadr adr; | ||||||
|  |  | ||||||
|  | 	Mrtpeeriterv2 it; | ||||||
|  | 	Mrtpeerentv2 *peer; | ||||||
|  |  | ||||||
|  | 	if (!S.hasPeerIndex) | ||||||
|  | 		return;  // NOP | ||||||
|  |  | ||||||
|  | 	Uint16 idx = 0; | ||||||
|  |  | ||||||
|  | 	Bufio_Init(&sb, STM_CONHN(STDOUT), Stm_ConOps); | ||||||
|  |  | ||||||
|  | 	Bgp_StartMrtPeersv2(&it, &S.peerIndex); | ||||||
|  | 	while ((peer = Bgp_NextMrtPeerv2(&it)) != NULL) { | ||||||
|  | 		if (ISPEERINDEXREF(S.peerIndexRefs, idx)) { | ||||||
|  | 			Asn asn    = MRT_GETPEERADDR(&adr, peer); | ||||||
|  | 			char *eptr = Ip_AdrToString(&adr, buf); | ||||||
|  |  | ||||||
|  | 			Bufio_Putsn(&sb, buf, eptr - buf); | ||||||
|  | 			Bufio_Putc(&sb, ' '); | ||||||
|  | 			Bufio_Putu(&sb, beswap32(ASN(asn))); | ||||||
|  | 			Bufio_Putc(&sb, '|'); | ||||||
|  | 			Bufio_Putc(&sb, ISASN32BIT(asn) ? '1' : '0'); | ||||||
|  | 			Bufio_Putc(&sb, '\n'); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		idx++; | ||||||
|  | 	} | ||||||
|  | 	Bufio_Flush(&sb); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void Peerindex_ProcessMrtDump(const char *filename) | ||||||
|  | { | ||||||
|  | 	void *hn; | ||||||
|  | 	const StmOps *ops; | ||||||
|  |  | ||||||
|  | 	S.filename = filename;  // NOTE: Only function that manipulates this | ||||||
|  |  | ||||||
|  | 	if (strcmp(filename, "-") == 0) { | ||||||
|  | 		hn  = STM_FILDES(CON_FILDES(STDIN)); | ||||||
|  | 		ops = Stm_NcFildesOps; | ||||||
|  | 	} else | ||||||
|  | 		ops = Peerindex_OpenMrtDump(filename, &hn); | ||||||
|  |  | ||||||
|  | 	setjmp(S.dropRecordFrame);  // NOTE: The ONLY place where this is set | ||||||
|  | 	while (Bgp_ReadMrt(&S.rec, hn, ops) == OK) { | ||||||
|  | 		const Mrthdr *hdr = MRT_HDR(&S.rec); | ||||||
|  | 		if (hdr->type != MRT_TABLE_DUMPV2) | ||||||
|  | 			continue;  // don't care for anything else | ||||||
|  |  | ||||||
|  | 		if (hdr->subtype == TABLE_DUMPV2_PEER_INDEX_TABLE) { | ||||||
|  | 			// Dump peers seen so far, if any | ||||||
|  | 			Peerindex_DumpPeerIndexTable(); | ||||||
|  | 			// Clear previous PEER_INDEX_TABLE, if any | ||||||
|  | 			Bgp_ClearMrt(&S.peerIndex); | ||||||
|  | 			// Clear reference table... | ||||||
|  | 			memset(S.peerIndexRefs, S.peerIndexClearVal, sizeof(S.peerIndexRefs)); | ||||||
|  |  | ||||||
|  | 			//...and update current PEER_INDEX_TABLE | ||||||
|  | 			size_t npeers; | ||||||
|  |  | ||||||
|  | 			MRT_MOVEREC(&S.peerIndex, &S.rec); | ||||||
|  | 			Bgp_GetMrtPeerIndexPeers(&S.peerIndex, &npeers, /*nbytes=*/NULL); | ||||||
|  | 			S.npeers       = npeers; | ||||||
|  | 			S.hasPeerIndex = TRUE; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		if (!TABLE_DUMPV2_ISRIB(hdr->subtype)) | ||||||
|  | 			continue;  // don't care for anything but RIBs | ||||||
|  |  | ||||||
|  | 		if (!S.hasPeerIndex) { | ||||||
|  | 			Peerindex_Warning("SKIPPING"); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		Peerindex_MarkPeerRefs(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Peerindex_DumpPeerIndexTable();  // execute the very last dump | ||||||
|  |  | ||||||
|  | 	if (ops->Close) | ||||||
|  | 		ops->Close(hn); | ||||||
|  |  | ||||||
|  | 	S.filename = NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main(int argc, char **argv) | ||||||
|  | { | ||||||
|  | #ifndef NDEBUG | ||||||
|  | 	Sys_SetErrFunc(SYS_ERR_ABORT, NULL); | ||||||
|  | #else | ||||||
|  | 	Sys_SetErrFunc(SYS_ERR_QUIT, NULL); | ||||||
|  | #endif | ||||||
|  | 	Bgp_SetErrFunc(Peerindex_HandleError, NULL); | ||||||
|  |  | ||||||
|  | 	Peerindex_SetupCommandLine(argv[0]); | ||||||
|  |  | ||||||
|  | 	int optind = Com_ArgParse(argc, argv, options, /*flags=*/0); | ||||||
|  | 	if (optind == OPT_HELP) | ||||||
|  | 		return EXIT_SUCCESS;  // only called to get help... | ||||||
|  | 	if (optind < 0) | ||||||
|  | 		return EXIT_FAILURE;  // can't parse command line | ||||||
|  |  | ||||||
|  | 	Peerindex_ApplyProgramOptions(); | ||||||
|  |  | ||||||
|  | 	Peerindex_Init();  // initialize according to command line | ||||||
|  |  | ||||||
|  | 	// Done with options | ||||||
|  | 	argc -= optind; | ||||||
|  | 	argv += optind; | ||||||
|  |  | ||||||
|  | 	// Move to filtering rules and compile them | ||||||
|  | 	if (argc == 0) { | ||||||
|  | 		// If no FILES are provided, read from stdin | ||||||
|  | 		static const char *const stdinFile[] = { "-" }; | ||||||
|  |  | ||||||
|  | 		argv = (char **) stdinFile; | ||||||
|  | 		argc = ARRAY_SIZE(stdinFile); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	volatile int i = 0; | ||||||
|  |  | ||||||
|  | 	setjmp(S.dropFileFrame);  // NOTE: The ONLY place where this is set | ||||||
|  | 	while (i < argc) { | ||||||
|  | 		Peerindex_ProcessMrtDump(argv[i++]); | ||||||
|  |  | ||||||
|  | 		// Don't need PEER_INDEX_TABLE anymore | ||||||
|  | 		Bgp_ClearMrt(&S.peerIndex); | ||||||
|  | 		S.hasPeerIndex = FALSE; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return (S.nerrors > 0) ? EXIT_FAILURE : EXIT_SUCCESS; | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								tools/peerindex/peerindex_local.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								tools/peerindex/peerindex_local.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-3.0-or-later | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * \file peeridx_local.h | ||||||
|  |  * | ||||||
|  |  * `peerindex` private header. | ||||||
|  |  * | ||||||
|  |  * \copyright The DoubleFourteen Code Forge (C) All Rights Reserved | ||||||
|  |  * \author    Lorenzo Cogotti | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef DF_PEERINDEX_LOCAL_H_ | ||||||
|  | #define DF_PEERINDEX_LOCAL_H_ | ||||||
|  |  | ||||||
|  | #include "bgp/mrt.h" | ||||||
|  |  | ||||||
|  | #include <setjmp.h> | ||||||
|  |  | ||||||
|  | #define PEERREFSTABSIZ (0x10000uLL / 64) | ||||||
|  |  | ||||||
|  | typedef Uint64 PeerRefsTab[PEERREFSTABSIZ]; | ||||||
|  |  | ||||||
|  | FORCE_INLINE void MARKPEERINDEX(PeerRefsTab tab, Uint16 idx) | ||||||
|  | { | ||||||
|  | 	tab[idx >> 6] |= (1uLL << (idx & 0x3f)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | FORCE_INLINE Boolean ISPEERINDEXREF(const PeerRefsTab tab, Uint16 idx) | ||||||
|  | { | ||||||
|  | 	return (tab[idx >> 6] & (1uLL << (idx & 0x3f))) != 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  | 	const char *filename;  // current file being processed | ||||||
|  |  | ||||||
|  | 	// Miscellaneous global flags and data | ||||||
|  | 	Boolean8    hasPeerIndex; | ||||||
|  | 	Uint8       peerIndexClearVal; | ||||||
|  | 	Uint16      npeers; | ||||||
|  | 	PeerRefsTab peerIndexRefs; | ||||||
|  | 	Mrtrecord   peerIndex; | ||||||
|  | 	Mrtrecord   rec; | ||||||
|  |  | ||||||
|  | 	// Error tracking and management | ||||||
|  | 	jmp_buf dropRecordFrame;  // used by `Peerindex_DropRecord()` | ||||||
|  | 	jmp_buf dropFileFrame;    // used by `Peerindex_DropFile()` | ||||||
|  | 	int     nerrors;          // for `exit()` status | ||||||
|  | } PeerindexState; | ||||||
|  |  | ||||||
|  | #endif | ||||||
		Reference in New Issue
	
	Block a user