Unify logging process

This commit is contained in:
maride 2019-12-03 23:51:03 +01:00
parent a368f18915
commit e9ec8ad46c
11 changed files with 124 additions and 72 deletions

View File

@ -16,15 +16,20 @@ func AppendIfUnique(appendee string, array []string) []string {
return append(array, appendee) return append(array, appendee)
} }
// Prints each element, along with a small ASCII tree // Generates a small ASCII tree for the given string array
func PrintTree(strarr []string) { func GenerateTree(strarr []string) string {
tmpstr := ""
// iterate over each element // iterate over each element
for iter, elem := range strarr { for iter, elem := range strarr {
// check if we got the last element // check if we got the last element
if iter < len(strarr) - 1 { if iter < len(strarr) - 1 {
fmt.Printf("|- %s\n", elem) tmpstr = fmt.Sprintf("%s|- %s\n", tmpstr, elem)
} else { } else {
fmt.Printf("'- %s\n\n", elem) tmpstr = fmt.Sprintf( "%s'- %s\n", tmpstr, elem)
} }
} }
// Return constructed (grown?) tree
return tmpstr
} }

View File

@ -3,7 +3,7 @@ package arp
import ( import (
"fmt" "fmt"
"git.darknebu.la/maride/pancap/common" "git.darknebu.la/maride/pancap/common"
"github.com/fatih/color" "git.darknebu.la/maride/pancap/output"
"github.com/google/gopacket" "github.com/google/gopacket"
"github.com/google/gopacket/layers" "github.com/google/gopacket/layers"
"log" "log"
@ -52,15 +52,12 @@ func ProcessARPPacket(packet gopacket.Packet) error {
// Print a summary after all packets are processed // Print a summary after all packets are processed
func PrintARPSummary() { func PrintARPSummary() {
headline := color.New(color.FgRed, color.Bold) output.PrintBlock("ARP traffic summary", generateTrafficStats())
headline.Println("ARP traffic summary") output.PrintBlock("ARP LAN overview", generateLANOverview())
printTrafficStats()
headline.Println("ARP LAN overview")
printLANOverview()
} }
// Constructs an answer regarding the ARP traffic // Generates an answer regarding the ARP traffic
func printTrafficStats() { func generateTrafficStats() string {
var tmparr []string var tmparr []string
// Iterate over all participants // Iterate over all participants
@ -82,11 +79,11 @@ func printTrafficStats() {
} }
// And print it as a tree // And print it as a tree
common.PrintTree(tmparr) return common.GenerateTree(tmparr)
} }
// Prints an overview over all connected devices in the LAN // Generates an overview over all connected devices in the LAN
func printLANOverview() { func generateLANOverview() string {
var tmparr []string var tmparr []string
// iterate over all devices // iterate over all devices
@ -95,7 +92,7 @@ func printLANOverview() {
} }
// And print it as a tree // 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 // Returns the arpStats object for the given MAC address, or creates a new one

View File

@ -1,7 +1,7 @@
package dhcpv4 package dhcpv4
import ( import (
"github.com/fatih/color" "git.darknebu.la/maride/pancap/output"
"github.com/google/gopacket" "github.com/google/gopacket"
"github.com/google/gopacket/layers" "github.com/google/gopacket/layers"
) )
@ -50,13 +50,8 @@ func HandleDHCPv4Packet(packet gopacket.Packet) error {
// Print summary after all packets are processed // Print summary after all packets are processed
func PrintDHCPv4Summary() { func PrintDHCPv4Summary() {
headline := color.New(color.FgRed, color.Bold) output.PrintBlock("DHCP Network Overview", generateNetworkSummary())
headline.Println("DHCP Network Overview") output.PrintBlock("DHCP Requests", generateRequestSummary())
printNetworkSummary() output.PrintBlock("DHCP Responses/Offers", generateResponseSummary())
headline.Println("DHCP Requests") output.PrintBlock("DHCP Hostnames", generateHostnamesSummary())
printRequestSummary()
headline.Println("DHCP Responses/Offers")
printResponseSummary()
headline.Println("DHCP Hostnames")
printHostnames()
} }

View File

@ -39,8 +39,8 @@ func checkForHostname(dhcppacket layers.DHCPv4) {
// None found, means client or server doesn't support Hostname option field. Ignore. // None found, means client or server doesn't support Hostname option field. Ignore.
} }
// Prints the list of all hostnames encountered. // Generates the list of all hostnames encountered.
func printHostnames() { func generateHostnamesSummary() string {
var tmparr []string var tmparr []string
// Construct meaningful text // Construct meaningful text
@ -72,7 +72,7 @@ func printHostnames() {
} }
// and print it as a tree. // 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 // Adds the given hostname to the hostname array, or patches an existing entry if found

View File

@ -140,14 +140,16 @@ func formatDate(rawDate []byte) string {
return formattedDate return formattedDate
} }
// Prints the summary of relevant DHCP options // Generates the summary of relevant DHCP options
func printNetworkSummary() { func generateNetworkSummary() string {
fmt.Printf("Subnet Mask: %s\n", formatIP(networkSetup[layers.DHCPOptSubnetMask])) // It's also possible to use strings.Builder here, but it produces code which is longer than this solution :shrug:
fmt.Printf("Broadcast: %s\n", formatIP(networkSetup[layers.DHCPOptBroadcastAddr])) summary := fmt.Sprintf("Subnet Mask: %s\n", formatIP(networkSetup[layers.DHCPOptSubnetMask]))
fmt.Printf("Router: %s\n", formatIP(networkSetup[layers.DHCPOptRouter])) summary = fmt.Sprintf("%sBroadcast: %s\n", summary, formatIP(networkSetup[layers.DHCPOptBroadcastAddr]))
fmt.Printf("DNS Server: %s\n", formatIP(networkSetup[layers.DHCPOptDNS])) summary = fmt.Sprintf("%sRouter: %s\n", summary, formatIP(networkSetup[layers.DHCPOptRouter]))
fmt.Printf("NTP Server: %s\n", formatIP(networkSetup[layers.DHCPOptNTPServers])) summary = fmt.Sprintf("%sDNS Server: %s\n", summary, formatIP(networkSetup[layers.DHCPOptDNS]))
fmt.Printf("Lease Time: %s\n", formatDate(networkSetup[layers.DHCPOptLeaseTime])) summary = fmt.Sprintf("%sNTP Server: %s\n", summary, formatIP(networkSetup[layers.DHCPOptNTPServers]))
fmt.Printf("Renewal Time: %s\n", formatDate(networkSetup[layers.DHCPOptT1])) 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
} }

View File

@ -15,8 +15,7 @@ func processRequestPacket(dhcppacket layers.DHCPv4) {
requestMAC = common.AppendIfUnique(dhcppacket.ClientHWAddr.String(), requestMAC) requestMAC = common.AppendIfUnique(dhcppacket.ClientHWAddr.String(), requestMAC)
} }
// Prints the summary of all DHCP request packets // Generates the summary of all DHCP request packets
func printRequestSummary() { func generateRequestSummary() string {
fmt.Printf("%d unique DHCP requests\n", len(requestMAC)) return fmt.Sprintf("%d unique DHCP requests\n%s", len(requestMAC), common.GenerateTree(requestMAC))
common.PrintTree(requestMAC)
} }

View File

@ -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()) addResponseEntry(dhcppacket.ClientIP.String(), dhcppacket.YourClientIP.String(), dhcppacket.ClientHWAddr.String(), ethernetpacket.SrcMAC.String())
} }
// Prints the summary of all DHCP offer packets // Generates the summary of all DHCP offer packets
func printResponseSummary() { func generateResponseSummary() string {
var tmpaddr []string var tmpaddr []string
// Iterate over all responses // Iterate over all responses
@ -31,7 +31,7 @@ func printResponseSummary() {
} }
// Draw as tree // 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 // 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

View File

@ -62,29 +62,31 @@ func processDNSAnswer(answers []layers.DNSResourceRecord) {
} }
} }
// Prints a summary of all DNS answers // Generates a summary of all DNS answers
func printDNSAnswerSummary() { func generateDNSAnswerSummary() string {
summary := ""
// Overall question stats // Overall question stats
fmt.Printf("%d DNS answers in total\n", numAnswers) summary = fmt.Sprintf("%s%d DNS answers in total\n", summary, numAnswers)
fmt.Printf("%s records\n", generateDNSTypeSummary(answerType)) summary = fmt.Sprintf("%s%s records\n", summary, 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 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 // Output base domains answered with
if len(answerBaseDomains) > 0 { if len(answerBaseDomains) > 0 {
fmt.Println("Answered with these base domains:") summary = fmt.Sprintf("Answered with these base domains:\n%s", common.GenerateTree(answerBaseDomains))
common.PrintTree(answerBaseDomains)
} }
// Output private domains // Output private domains
if len(answerPrivateDomains) > 0 { if len(answerPrivateDomains) > 0 {
fmt.Println("Answered with these private (non-ICANN managed) domains:") summary = fmt.Sprintf("%sAnswered with these private (non-ICANN managed) domains:\n%s", summary, common.GenerateTree(answerPrivateDomains))
common.PrintTree(answerPrivateDomains)
} }
// Check for public and private IPs // 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 { if len(answerPrivateIPv4) > 0 {
fmt.Println("Private IP addresses in answer:") summary = fmt.Sprintf("%sPrivate IP addresses in answer:\n%s", summary, common.GenerateTree(answerPrivateIPv4))
common.PrintTree(answerPrivateIPv4)
} }
// Return summary
return summary
} }

View File

@ -1,7 +1,7 @@
package dns package dns
import ( import (
"github.com/fatih/color" "git.darknebu.la/maride/pancap/output"
"github.com/google/gopacket" "github.com/google/gopacket"
"github.com/google/gopacket/layers" "github.com/google/gopacket/layers"
) )
@ -27,9 +27,6 @@ func ProcessDNSPacket(packet gopacket.Packet) error {
// Print a summary after all DNS packets were processed // Print a summary after all DNS packets were processed
func PrintDNSSummary() { func PrintDNSSummary() {
headline := color.New(color.FgRed, color.Bold) output.PrintBlock("DNS Request Summary", generateDNSQuestionSummary())
headline.Println("DNS Request Summary") output.PrintBlock("DNS Response Summary", generateDNSAnswerSummary())
printDNSQuestionSummary()
headline.Println("DNS Response Summary")
printDNSAnswerSummary()
} }

View File

@ -51,22 +51,25 @@ func processDNSQuestion(questions []layers.DNSQuestion) {
} }
} }
// Prints a summary of all DNS questions // Generates a summary of all DNS questions
func printDNSQuestionSummary() { func generateDNSQuestionSummary() string {
summary := ""
// Overall question stats // Overall question stats
fmt.Printf("%d DNS questions in total\n", numQuestions) summary = fmt.Sprintf("%s%d DNS questions in total\n", summary, numQuestions)
fmt.Printf("%s records\n", generateDNSTypeSummary(questionType)) summary = fmt.Sprintf("%s%s records\n", summary, 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 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 // Output base domains asked for
if len(questionBaseDomains) > 0 { if len(questionBaseDomains) > 0 {
fmt.Println("Asked for these base domains:") summary = fmt.Sprintf("%sAsked for these base domains:\n%s", summary, common.GenerateTree(questionBaseDomains))
common.PrintTree(questionBaseDomains)
} }
// Output private domains // Output private domains
if len(questionPrivateDomains) > 0 { if len(questionPrivateDomains) > 0 {
fmt.Println("Asked for these private (non-ICANN managed) domains:") summary = fmt.Sprintf("%sAsked for these private (non-ICANN managed) domains:\n%s", summary, common.GenerateTree(questionPrivateDomains))
common.PrintTree(questionPrivateDomains)
} }
// And return summary
return summary
} }

52
output/output.go Normal file
View 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
}