コード例 #1
0
ファイル: pcaproc.c プロジェクト: Opmantek/nfdump
static inline void ProcessTCPFlow(FlowSource_t	*fs, struct FlowNode *NewNode ) {
struct FlowNode *Node;

	assert(NewNode->memflag == NODE_IN_USE);
	Node = Insert_Node(NewNode);
	// Return existing Node if flow exists already, otherwise insert es new
	if ( Node == NULL ) {
		// Insert as new
		dbg_printf("New TCP flow: Packets: %u, Bytes: %u\n", NewNode->packets, NewNode->bytes);

		// in case it's a FIN/RST only packet - immediately flush it
		if ( NewNode->fin == FIN_NODE  ) {
			// flush node
			if ( StorePcapFlow(fs, NewNode) ) {
				Remove_Node(NewNode);
			} 
		}

		if ( !CacheCheck() ) {
			uint32_t NumFlows;
			LogError("Node cache exhausted! - Immediate flush - increase flow cache!!");	
			NumFlows  = Flush_FlowTree(fs);
			LogError("Flushed flows: %u", NumFlows);	
		}

		if ( Link_RevNode(NewNode)) {
			// if we could link this new node, it is the server answer
			// -> calculate server latency
			SetServer_latency(NewNode);
		}
		return;
	}

	assert(Node->memflag == NODE_IN_USE);

	// check for first client ACK for client latency
	if ( Node->latency.flag == 1 ) {
		SetClient_latency(Node, &(NewNode->t_first));
	} else if ( Node->latency.flag == 2 ) {
		SetApplication_latency(Node, &(NewNode->t_first));
	}
	// update existing flow
	Node->flags |= NewNode->flags;
	Node->packets++;
	Node->bytes += NewNode->bytes; 
	Node->t_last = NewNode->t_last; 
	dbg_printf("Existing TCP flow: Packets: %u, Bytes: %u\n", Node->packets, Node->bytes);

	if ( NewNode->fin == FIN_NODE) {
		// flush node
		Node->fin = FIN_NODE;
		if ( StorePcapFlow(fs, Node) ) {
			Remove_Node(Node);
		} 
	} else {
		Free_Node(NewNode);
	}
 

} // End of ProcessTCPFlow
コード例 #2
0
ファイル: pcaproc.c プロジェクト: exaexa/nfdump
static inline void ProcessTCPFlow (FlowSource_t *fs, struct FlowNode *NewNode)
{
	struct FlowNode *Node;

	assert (NewNode->memflag == NODE_IN_USE);
	Node = Insert_Node (NewNode);
	// if insert fails, the existing node is returned -> flow exists already
	if (Node == NULL) {
		dbg_printf ("New TCP flow: Packets: %u, Bytes: %u\n", NewNode->packets, NewNode->bytes);

		// in case it's a FIN/RST only packet - immediately flush it
		if (NewNode->fin == FIN_NODE) {
			// flush node
			if (StorePcapFlow (fs, NewNode)) {
				Remove_Node (NewNode);
			}
		}

		if (!CacheCheck()) {
			uint32_t NumFlows;
			LogError ("Node cache exhausted! - Immediate flush - increase flow cache!!");
			NumFlows = Flush_FlowTree (fs);
			LogError ("Flushed flows: %u", NumFlows);
		}
		return;
	}

	assert (Node->memflag == NODE_IN_USE);

	// update existing flow
	Node->flags |= NewNode->flags;
	Node->packets++;
	Node->bytes += NewNode->bytes;
	Node->t_last = NewNode->t_last;
	dbg_printf ("Existing TCP flow: Packets: %u, Bytes: %u\n", Node->packets, Node->bytes);

	if (NewNode->fin == FIN_NODE) {
		// flush node
		Node->fin = FIN_NODE;
		if (StorePcapFlow (fs, Node)) {
			Remove_Node (Node);
		}
	} else {
		Free_Node (NewNode);
	}


} // End of ProcessTCPFlow
コード例 #3
0
ファイル: nfpcapd.c プロジェクト: jmagudo/nfdump
__attribute__((noreturn)) static void *p_flow_thread(void *thread_data) {
// argument dispatching
p_flow_thread_args_t *args = (p_flow_thread_args_t *)thread_data;
time_t t_win				 = args->t_win;
int subdir_index			 = args->subdir_index;
int compress			 	 = args->compress;
FlowSource_t *fs			 = args->fs;

// locals
time_t t_start, t_clock, t_udp_flush;
int err, done;

	done 	   = 0;
	args->done = 0;
	args->exit = 0;

	err = pthread_setspecific( buffer_key, (void *)args );
	if ( err ) {
		LogError("[%lu] pthread_setspecific() error in %s line %d: %s\n", 
			(long unsigned)args->tid, __FILE__, __LINE__, strerror(errno) );
		args->done = 1;
		args->exit = 255;
   		pthread_kill(args->parent, SIGUSR1);
		pthread_exit((void *)args);
	}

	if ( !Init_pcap2nf() ) {
		args->done = 1;
		args->exit = 255;
   		pthread_kill(args->parent, SIGUSR1);
		pthread_exit((void *)args);
	}

	// prepare file
	fs->nffile = OpenNewFile(fs->current, NULL, compress, 0, NULL);
	if ( !fs->nffile ) {
		args->done = 1;
		args->exit = 255;
   		pthread_kill(args->parent, SIGUSR1);
		pthread_exit((void *)args);
	}
	fs->xstat = NULL;

	// init vars
	fs->bad_packets		= 0;
	fs->first_seen      = 0xffffffffffffLL;
	fs->last_seen 		= 0;

	t_start = 0;
	t_clock = 0;
	t_udp_flush = 0;
	while ( 1 ) {
		struct FlowNode	*Node;

		Node = Pop_Node(args->NodeList, &args->done);
		if ( Node ) {
			t_clock = Node->t_last.tv_sec;
			dbg_printf("p_flow_thread() Next Node\n");
		} else {
			done = args->done;
			dbg_printf("p_flow_thread() NULL Node\n");
		}

		if ( t_start == 0 ) {
			t_udp_flush = t_start = t_clock - (t_clock % t_win);
		}

		if (((t_clock - t_start) >= t_win) || done) { /* rotate file */
			struct tm *when;
			nffile_t *nffile;
			char FullName[MAXPATHLEN];
			char netflowFname[128];
			char error[256];
			char *subdir;

			// flush all flows to disk
			DumpNodeStat();
			uint32_t NumFlows  = Flush_FlowTree(fs);

			when = localtime(&t_start);
			nffile = fs->nffile;

			// prepare sub dir hierarchy
			if ( subdir_index ) {
				subdir = GetSubDir(when);
				if ( !subdir ) {
					// failed to generate subdir path - put flows into base directory
					LogError("Failed to create subdir path!");
				
					// failed to generate subdir path - put flows into base directory
					subdir = NULL;
					snprintf(netflowFname, 127, "nfcapd.%i%02i%02i%02i%02i",
						when->tm_year + 1900, when->tm_mon + 1, when->tm_mday, when->tm_hour, when->tm_min);
				} else {
					snprintf(netflowFname, 127, "%s/nfcapd.%i%02i%02i%02i%02i", subdir,
						when->tm_year + 1900, when->tm_mon + 1, when->tm_mday, when->tm_hour, when->tm_min);
				}

			} else {
				subdir = NULL;
				snprintf(netflowFname, 127, "nfcapd.%i%02i%02i%02i%02i",
					when->tm_year + 1900, when->tm_mon + 1, when->tm_mday, when->tm_hour, when->tm_min);
			}
			netflowFname[127] = '\0';
	
			if ( subdir && !SetupSubDir(fs->datadir, subdir, error, 255) ) {
				// in this case the flows get lost! - the rename will fail
				// but this should not happen anyway, unless i/o problems, inode problems etc.
				LogError("Ident: %s, Failed to create sub hier directories: %s", fs->Ident, error );
			}

			if ( nffile->block_header->NumRecords ) {
				// flush current buffer to disc
				if ( WriteBlock(nffile) <= 0 )
					LogError("Ident: %s, failed to write output buffer to disk: '%s'" , fs->Ident, strerror(errno));
			} // else - no new records in current block

			// prepare full filename
			snprintf(FullName, MAXPATHLEN-1, "%s/%s", fs->datadir, netflowFname);
			FullName[MAXPATHLEN-1] = '\0';

			// update stat record
			// if no flows were collected, fs->last_seen is still 0
			// set first_seen to start of this time slot, with twin window size.
			if ( fs->last_seen == 0 ) {
				fs->first_seen = (uint64_t)1000 * (uint64_t)t_start;
				fs->last_seen  = (uint64_t)1000 * (uint64_t)(t_start + t_win);
			}
			nffile->stat_record->first_seen = fs->first_seen/1000;
			nffile->stat_record->msec_first	= fs->first_seen - nffile->stat_record->first_seen*1000;
			nffile->stat_record->last_seen 	= fs->last_seen/1000;
			nffile->stat_record->msec_last	= fs->last_seen - nffile->stat_record->last_seen*1000;
	
			// Flush Exporter Stat to file
			FlushExporterStats(fs);
			// Close file
			CloseUpdateFile(nffile, fs->Ident);
	
			// if rename fails, we are in big trouble, as we need to get rid of the old .current file
			// otherwise, we will loose flows and can not continue collecting new flows
			if ( !RenameAppend(fs->current, FullName) ) {
				LogError("Ident: %s, Can't rename dump file: %s", fs->Ident,  strerror(errno));
				LogError("Ident: %s, Serious Problem! Fix manually", fs->Ident);
	/* XXX
				if ( launcher_pid )
					commbuff->failed = 1;
	*/
				// we do not update the books here, as the file failed to rename properly
				// otherwise the books may be wrong
			} else {
				struct stat	fstat;
	/* XXX
				if ( launcher_pid )
					commbuff->failed = 0;
	*/
				// Update books
				stat(FullName, &fstat);
				UpdateBooks(fs->bookkeeper, t_start, 512*fstat.st_blocks);
			}

			LogInfo("Ident: '%s' Flows: %llu, Packets: %llu, Bytes: %llu, Max Flows: %u", 
				fs->Ident, (unsigned long long)nffile->stat_record->numflows, (unsigned long long)nffile->stat_record->numpackets, 
				(unsigned long long)nffile->stat_record->numbytes, NumFlows);

			// reset stats
			fs->bad_packets = 0;
			fs->first_seen  = 0xffffffffffffLL;
			fs->last_seen 	= 0;
	
			// Dump all extension maps and exporters to the buffer
			FlushStdRecords(fs);

			if ( done ) 
				break;
	
			t_start = t_clock - (t_clock % t_win);

			nffile = OpenNewFile(fs->current, nffile, compress, 0, NULL);
			if ( !nffile ) {
				LogError("Fatal: OpenNewFile() failed for ident: %s", fs->Ident);
				args->done = 1;
				args->exit = 255;
   				pthread_kill(args->parent, SIGUSR1);
				break;
			}
		}

		if (((t_clock - t_udp_flush) >= 10) || !done) { /* flush inactive UDP list */
			UDPexpire(fs, t_clock - 10 );
			t_udp_flush = t_clock;
		}

		if ( Node->fin != SIGNAL_NODE )
			// Process the Node
			ProcessFlowNode(fs, Node);

	}

	while ( fs ) {
		DisposeFile(fs->nffile);
		fs = fs->next;
	}
	LogInfo("Terminating flow processng: exit: %i", args->exit);
	dbg_printf("End flow thread[%lu]\n", (long unsigned)args->tid);

	pthread_exit((void *)args);
	/* NOTREACHED */

} // End of p_flow_thread