mirror of
				https://github.com/maride/pancap.git
				synced 2025-10-10 19:36:51 +00:00 
			
		
		
		
	Unify logging process
This commit is contained in:
		
							parent
							
								
									a368f18915
								
							
						
					
					
						commit
						e9ec8ad46c
					
				| @ -16,15 +16,20 @@ func AppendIfUnique(appendee string, array []string) []string { | ||||
| 	return append(array, appendee) | ||||
| } | ||||
| 
 | ||||
| // Prints each element, along with a small ASCII tree | ||||
| func PrintTree(strarr []string) { | ||||
| // Generates a small ASCII tree for the given string array | ||||
| func GenerateTree(strarr []string) string { | ||||
| 	tmpstr := "" | ||||
| 
 | ||||
| 	// iterate over each element | ||||
| 	for iter, elem := range strarr { | ||||
| 		// check if we got the last element | ||||
| 		if iter < len(strarr) - 1 { | ||||
| 			fmt.Printf("|- %s\n", elem) | ||||
| 			tmpstr = fmt.Sprintf("%s|- %s\n", tmpstr, elem) | ||||
| 		} else { | ||||
| 			fmt.Printf("'- %s\n\n", elem) | ||||
| 			tmpstr = fmt.Sprintf( "%s'- %s\n", tmpstr, elem) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Return constructed (grown?) tree | ||||
| 	return tmpstr | ||||
| } | ||||
|  | ||||
| @ -3,7 +3,7 @@ package arp | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"git.darknebu.la/maride/pancap/common" | ||||
| 	"github.com/fatih/color" | ||||
| 	"git.darknebu.la/maride/pancap/output" | ||||
| 	"github.com/google/gopacket" | ||||
| 	"github.com/google/gopacket/layers" | ||||
| 	"log" | ||||
| @ -52,15 +52,12 @@ func ProcessARPPacket(packet gopacket.Packet) error { | ||||
| 
 | ||||
| // Print a summary after all packets are processed | ||||
| func PrintARPSummary() { | ||||
| 	headline := color.New(color.FgRed, color.Bold) | ||||
| 	headline.Println("ARP traffic summary") | ||||
| 	printTrafficStats() | ||||
| 	headline.Println("ARP LAN overview") | ||||
| 	printLANOverview() | ||||
| 	output.PrintBlock("ARP traffic summary", generateTrafficStats()) | ||||
| 	output.PrintBlock("ARP LAN overview", generateLANOverview()) | ||||
| } | ||||
| 
 | ||||
| // Constructs an answer regarding the ARP traffic | ||||
| func printTrafficStats() { | ||||
| // Generates an answer regarding the ARP traffic | ||||
| func generateTrafficStats() string { | ||||
| 	var tmparr []string | ||||
| 
 | ||||
| 	// Iterate over all participants | ||||
| @ -82,11 +79,11 @@ func printTrafficStats() { | ||||
| 	} | ||||
| 
 | ||||
| 	// And print it as a tree | ||||
| 	common.PrintTree(tmparr) | ||||
| 	return common.GenerateTree(tmparr) | ||||
| } | ||||
| 
 | ||||
| // Prints an overview over all connected devices in the LAN | ||||
| func printLANOverview() { | ||||
| // Generates an overview over all connected devices in the LAN | ||||
| func generateLANOverview() string { | ||||
| 	var tmparr []string | ||||
| 
 | ||||
| 	// iterate over all devices | ||||
| @ -95,7 +92,7 @@ func printLANOverview() { | ||||
| 	} | ||||
| 
 | ||||
| 	// And print it as a tree | ||||
| 	common.PrintTree(tmparr) | ||||
| 	return common.GenerateTree(tmparr) | ||||
| } | ||||
| 
 | ||||
| // Returns the arpStats object for the given MAC address, or creates a new one | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| package dhcpv4 | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/fatih/color" | ||||
| 	"git.darknebu.la/maride/pancap/output" | ||||
| 	"github.com/google/gopacket" | ||||
| 	"github.com/google/gopacket/layers" | ||||
| ) | ||||
| @ -50,13 +50,8 @@ func HandleDHCPv4Packet(packet gopacket.Packet) error { | ||||
| 
 | ||||
| // Print summary after all packets are processed | ||||
| func PrintDHCPv4Summary() { | ||||
| 	headline := color.New(color.FgRed, color.Bold) | ||||
| 	headline.Println("DHCP Network Overview") | ||||
| 	printNetworkSummary() | ||||
| 	headline.Println("DHCP Requests") | ||||
| 	printRequestSummary() | ||||
| 	headline.Println("DHCP Responses/Offers") | ||||
| 	printResponseSummary() | ||||
| 	headline.Println("DHCP Hostnames") | ||||
| 	printHostnames() | ||||
| 	output.PrintBlock("DHCP Network Overview", generateNetworkSummary()) | ||||
| 	output.PrintBlock("DHCP Requests", generateRequestSummary()) | ||||
| 	output.PrintBlock("DHCP Responses/Offers", generateResponseSummary()) | ||||
| 	output.PrintBlock("DHCP Hostnames", generateHostnamesSummary()) | ||||
| } | ||||
|  | ||||
| @ -39,8 +39,8 @@ func checkForHostname(dhcppacket layers.DHCPv4) { | ||||
| 	// None found, means client or server doesn't support Hostname option field. Ignore. | ||||
| } | ||||
| 
 | ||||
| // Prints the list of all hostnames encountered. | ||||
| func printHostnames() { | ||||
| // Generates the list of all hostnames encountered. | ||||
| func generateHostnamesSummary() string { | ||||
| 	var tmparr []string | ||||
| 
 | ||||
| 	// Construct meaningful text | ||||
| @ -72,7 +72,7 @@ func printHostnames() { | ||||
| 	} | ||||
| 
 | ||||
| 	// and print it as a tree. | ||||
| 	common.PrintTree(tmparr) | ||||
| 	return common.GenerateTree(tmparr) | ||||
| } | ||||
| 
 | ||||
| // Adds the given hostname to the hostname array, or patches an existing entry if found | ||||
|  | ||||
| @ -140,14 +140,16 @@ func formatDate(rawDate []byte) string { | ||||
| 	return formattedDate | ||||
| } | ||||
| 
 | ||||
| // Prints the summary of relevant DHCP options | ||||
| func printNetworkSummary() { | ||||
| 	fmt.Printf("Subnet Mask: %s\n", formatIP(networkSetup[layers.DHCPOptSubnetMask])) | ||||
| 	fmt.Printf("Broadcast: %s\n", formatIP(networkSetup[layers.DHCPOptBroadcastAddr])) | ||||
| 	fmt.Printf("Router: %s\n", formatIP(networkSetup[layers.DHCPOptRouter])) | ||||
| 	fmt.Printf("DNS Server: %s\n", formatIP(networkSetup[layers.DHCPOptDNS])) | ||||
| 	fmt.Printf("NTP Server: %s\n", formatIP(networkSetup[layers.DHCPOptNTPServers])) | ||||
| 	fmt.Printf("Lease Time: %s\n", formatDate(networkSetup[layers.DHCPOptLeaseTime])) | ||||
| 	fmt.Printf("Renewal Time: %s\n", formatDate(networkSetup[layers.DHCPOptT1])) | ||||
| // Generates the summary of relevant DHCP options | ||||
| func generateNetworkSummary() string { | ||||
| 	// It's also possible to use strings.Builder here, but it produces code which is longer than this solution :shrug: | ||||
| 	summary := fmt.Sprintf("Subnet Mask: %s\n", formatIP(networkSetup[layers.DHCPOptSubnetMask])) | ||||
| 	summary = fmt.Sprintf("%sBroadcast: %s\n", summary, formatIP(networkSetup[layers.DHCPOptBroadcastAddr])) | ||||
| 	summary = fmt.Sprintf("%sRouter: %s\n", summary, formatIP(networkSetup[layers.DHCPOptRouter])) | ||||
| 	summary = fmt.Sprintf("%sDNS Server: %s\n", summary, formatIP(networkSetup[layers.DHCPOptDNS])) | ||||
| 	summary = fmt.Sprintf("%sNTP Server: %s\n", summary, formatIP(networkSetup[layers.DHCPOptNTPServers])) | ||||
| 	summary = fmt.Sprintf("%sLease Time: %s\n", summary, formatDate(networkSetup[layers.DHCPOptLeaseTime])) | ||||
| 	summary = fmt.Sprintf("%sRenewal Time: %s\n", summary, formatDate(networkSetup[layers.DHCPOptT1])) | ||||
| 	return summary | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -15,8 +15,7 @@ func processRequestPacket(dhcppacket layers.DHCPv4) { | ||||
| 	requestMAC = common.AppendIfUnique(dhcppacket.ClientHWAddr.String(), requestMAC) | ||||
| } | ||||
| 
 | ||||
| // Prints the summary of all DHCP request packets | ||||
| func printRequestSummary() { | ||||
| 	fmt.Printf("%d unique DHCP requests\n", len(requestMAC)) | ||||
| 	common.PrintTree(requestMAC) | ||||
| // Generates the summary of all DHCP request packets | ||||
| func generateRequestSummary() string { | ||||
| 	return fmt.Sprintf("%d unique DHCP requests\n%s", len(requestMAC), common.GenerateTree(requestMAC)) | ||||
| } | ||||
|  | ||||
| @ -15,8 +15,8 @@ func processResponsePacket(dhcppacket layers.DHCPv4, ethernetpacket layers.Ether | ||||
| 	addResponseEntry(dhcppacket.ClientIP.String(), dhcppacket.YourClientIP.String(), dhcppacket.ClientHWAddr.String(), ethernetpacket.SrcMAC.String()) | ||||
| } | ||||
| 
 | ||||
| // Prints the summary of all DHCP offer packets | ||||
| func printResponseSummary() { | ||||
| // Generates the summary of all DHCP offer packets | ||||
| func generateResponseSummary() string { | ||||
| 	var tmpaddr []string | ||||
| 
 | ||||
| 	// Iterate over all responses | ||||
| @ -31,7 +31,7 @@ func printResponseSummary() { | ||||
| 	} | ||||
| 
 | ||||
| 	// Draw as tree | ||||
| 	common.PrintTree(tmpaddr) | ||||
| 	return common.GenerateTree(tmpaddr) | ||||
| } | ||||
| 
 | ||||
| // Adds a new response entry. If an IP address was already issued or a MAC asks multiple times for DNS, the case is examined further | ||||
|  | ||||
| @ -62,29 +62,31 @@ func processDNSAnswer(answers []layers.DNSResourceRecord) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Prints a summary of all DNS answers | ||||
| func printDNSAnswerSummary() { | ||||
| // Generates a summary of all DNS answers | ||||
| func generateDNSAnswerSummary() string { | ||||
| 	summary := "" | ||||
| 
 | ||||
| 	// Overall question stats | ||||
| 	fmt.Printf("%d DNS answers in total\n", numAnswers) | ||||
| 	fmt.Printf("%s records\n", generateDNSTypeSummary(answerType)) | ||||
| 	fmt.Printf("%d unique domains of %d base domains, of which are %d private (non-ICANN) TLDs.\n", len(answerDomains), len(answerBaseDomains), len(answerPrivateDomains)) | ||||
| 	summary = fmt.Sprintf("%s%d DNS answers in total\n", summary, numAnswers) | ||||
| 	summary = fmt.Sprintf("%s%s records\n", summary, generateDNSTypeSummary(answerType)) | ||||
| 	summary = fmt.Sprintf("%s%d unique domains of %d base domains, of which are %d private (non-ICANN) TLDs.\n", summary, len(answerDomains), len(answerBaseDomains), len(answerPrivateDomains)) | ||||
| 
 | ||||
| 	// Output base domains answered with | ||||
| 	if len(answerBaseDomains) > 0 { | ||||
| 		fmt.Println("Answered with these base domains:") | ||||
| 		common.PrintTree(answerBaseDomains) | ||||
| 		summary = fmt.Sprintf("Answered with these base domains:\n%s", common.GenerateTree(answerBaseDomains)) | ||||
| 	} | ||||
| 
 | ||||
| 	// Output private domains | ||||
| 	if len(answerPrivateDomains) > 0 { | ||||
| 		fmt.Println("Answered with these private (non-ICANN managed) domains:") | ||||
| 		common.PrintTree(answerPrivateDomains) | ||||
| 		summary = fmt.Sprintf("%sAnswered with these private (non-ICANN managed) domains:\n%s", summary, common.GenerateTree(answerPrivateDomains)) | ||||
| 	} | ||||
| 
 | ||||
| 	// Check for public and private IPs | ||||
| 	fmt.Printf("Answered with %d public IP addresses and %d private IP addresses\n", len(answerPublicIPv4), len(answerPrivateIPv4)) | ||||
| 	summary = fmt.Sprintf("%sAnswered with %d public IP addresses and %d private IP addresses\n", summary, len(answerPublicIPv4), len(answerPrivateIPv4)) | ||||
| 	if len(answerPrivateIPv4) > 0 { | ||||
| 		fmt.Println("Private IP addresses in answer:") | ||||
| 		common.PrintTree(answerPrivateIPv4) | ||||
| 		summary = fmt.Sprintf("%sPrivate IP addresses in answer:\n%s", summary, common.GenerateTree(answerPrivateIPv4)) | ||||
| 	} | ||||
| 
 | ||||
| 	// Return summary | ||||
| 	return summary | ||||
| } | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/fatih/color" | ||||
| 	"git.darknebu.la/maride/pancap/output" | ||||
| 	"github.com/google/gopacket" | ||||
| 	"github.com/google/gopacket/layers" | ||||
| ) | ||||
| @ -27,9 +27,6 @@ func ProcessDNSPacket(packet gopacket.Packet) error { | ||||
| 
 | ||||
| // Print a summary after all DNS packets were processed | ||||
| func PrintDNSSummary() { | ||||
| 	headline := color.New(color.FgRed, color.Bold) | ||||
| 	headline.Println("DNS Request Summary") | ||||
| 	printDNSQuestionSummary() | ||||
| 	headline.Println("DNS Response Summary") | ||||
| 	printDNSAnswerSummary() | ||||
| 	output.PrintBlock("DNS Request Summary", generateDNSQuestionSummary()) | ||||
| 	output.PrintBlock("DNS Response Summary", generateDNSAnswerSummary()) | ||||
| } | ||||
|  | ||||
| @ -51,22 +51,25 @@ func processDNSQuestion(questions []layers.DNSQuestion) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Prints a summary of all DNS questions | ||||
| func printDNSQuestionSummary() { | ||||
| // Generates a summary of all DNS questions | ||||
| func generateDNSQuestionSummary() string { | ||||
| 	summary := "" | ||||
| 
 | ||||
| 	// Overall question stats | ||||
| 	fmt.Printf("%d DNS questions in total\n", numQuestions) | ||||
| 	fmt.Printf("%s records\n", generateDNSTypeSummary(questionType)) | ||||
| 	fmt.Printf("%d unique domains of %d base domains, of which are %d private (non-ICANN) TLDs.\n", len(questionDomains), len(questionBaseDomains), len(questionPrivateDomains)) | ||||
| 	summary = fmt.Sprintf("%s%d DNS questions in total\n", summary, numQuestions) | ||||
| 	summary = fmt.Sprintf("%s%s records\n", summary, generateDNSTypeSummary(questionType)) | ||||
| 	summary = fmt.Sprintf("%s%d unique domains of %d base domains, of which are %d private (non-ICANN) TLDs.\n", summary, len(questionDomains), len(questionBaseDomains), len(questionPrivateDomains)) | ||||
| 
 | ||||
| 	// Output base domains asked for | ||||
| 	if len(questionBaseDomains) > 0 { | ||||
| 		fmt.Println("Asked for these base domains:") | ||||
| 		common.PrintTree(questionBaseDomains) | ||||
| 		summary = fmt.Sprintf("%sAsked for these base domains:\n%s", summary, common.GenerateTree(questionBaseDomains)) | ||||
| 	} | ||||
| 
 | ||||
| 	// Output private domains | ||||
| 	if len(questionPrivateDomains) > 0 { | ||||
| 		fmt.Println("Asked for these private (non-ICANN managed) domains:") | ||||
| 		common.PrintTree(questionPrivateDomains) | ||||
| 		summary = fmt.Sprintf("%sAsked for these private (non-ICANN managed) domains:\n%s", summary, common.GenerateTree(questionPrivateDomains)) | ||||
| 	} | ||||
| 
 | ||||
| 	// And return summary | ||||
| 	return summary | ||||
| } | ||||
							
								
								
									
										52
									
								
								output/output.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								output/output.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| package output | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"github.com/fatih/color" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	MaxContentLines = 50 | ||||
| ) | ||||
| 
 | ||||
| // Prints a block of information with the given headline | ||||
| // If content is empty, printing the headline is omitted. | ||||
| // If the content is longer than MaxContentLines, content is cut. | ||||
| func PrintBlock(headline string, content string) { | ||||
| 	// Print a newline to add some space between blocks | ||||
| 	fmt.Println("") | ||||
| 
 | ||||
| 	// Check if we need to print a headline | ||||
| 	if len(content) > 0 { | ||||
| 		// We have content, we can print the headline | ||||
| 		headlineColor := color.New(color.FgRed, color.Bold) | ||||
| 		headlineColor.Println(headline) | ||||
| 	} | ||||
| 
 | ||||
| 	// Cut to MaxContentLines if required | ||||
| 	cutCont := cutContent(content) | ||||
| 	fmt.Print(cutCont) | ||||
| } | ||||
| 
 | ||||
| // Cut content after MaxContentLines lines | ||||
| func cutContent(content string) string { | ||||
| 	numNewlines := 0 | ||||
| 
 | ||||
| 	// iterate over every character | ||||
| 	for i, c := range content { | ||||
| 		// check if character is newline | ||||
| 		if c == '\n' { | ||||
| 			// it is, count occurrence | ||||
| 			numNewlines++ | ||||
| 
 | ||||
| 			// Check if we already hit our limit yet | ||||
| 			if numNewlines == MaxContentLines { | ||||
| 				// Found nth newline, return content up to this position. | ||||
| 				return content[:i+1] // +1 to include the last newline as well | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// We are done before reaching the cut limit; return the whole content | ||||
| 	return content | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user