mirror of
https://github.com/maride/pancap.git
synced 2024-12-22 20:27:29 +00:00
Record and summarize network-related DHCP options
This commit is contained in:
parent
1ee36fc944
commit
ad532a5a22
@ -43,6 +43,7 @@ func HandleDHCPv4Packet(packet gopacket.Packet) error {
|
||||
|
||||
// Check for Hostname DHCP option (12)
|
||||
checkForHostname(dhcppacket)
|
||||
checkForNetworkInfos(dhcppacket)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -50,6 +51,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")
|
||||
|
153
ethernet/dhcpv4/network.go
Normal file
153
ethernet/dhcpv4/network.go
Normal file
@ -0,0 +1,153 @@
|
||||
package dhcpv4
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"github.com/google/gopacket/layers"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
var (
|
||||
networkSetup = make(map[layers.DHCPOpt][]byte)
|
||||
watchedOpts = []layers.DHCPOpt{
|
||||
layers.DHCPOptSubnetMask, // Option 1
|
||||
layers.DHCPOptRouter, // Option 3
|
||||
layers.DHCPOptDNS, // Option 6
|
||||
layers.DHCPOptBroadcastAddr, // Option 28
|
||||
layers.DHCPOptNTPServers, // Option 42
|
||||
layers.DHCPOptLeaseTime, // Option 51
|
||||
layers.DHCPOptT1, // Option 58
|
||||
}
|
||||
)
|
||||
|
||||
// Looks for information specifying the setup of the network. This includes
|
||||
// - Option 1: Subnet Mask
|
||||
// - Option 3: Router address
|
||||
// - Option 6: Domain Name Server address
|
||||
// - Option 28: Broadcast address
|
||||
// - Option 42: NTP Server address
|
||||
// - Option 51: IP Address Lease time
|
||||
// - Option 58: IP Renewal time
|
||||
func checkForNetworkInfos(dhcppacket layers.DHCPv4) {
|
||||
// Check if it is a DHCP request
|
||||
if dhcppacket.Operation == layers.DHCPOpRequest {
|
||||
// We can ignore requests, they won't help us here
|
||||
return
|
||||
}
|
||||
|
||||
// Search for different options (1, 3, 6, 28, 42, 51, 58) in DHCP Packet Options
|
||||
for _, o := range dhcppacket.Options {
|
||||
if isRelevantOption(o) {
|
||||
// Found DHCP option to be watched, let's watch it
|
||||
saveOption(o)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Checks if the given DHCPOption is part of the watchlist
|
||||
func isRelevantOption(opt layers.DHCPOption) bool {
|
||||
// Iterate over all DHCP options in our watchlist
|
||||
for _, o := range watchedOpts {
|
||||
if o == opt.Type {
|
||||
// Found.
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// This option is not on our watchlist.
|
||||
return false
|
||||
}
|
||||
|
||||
// Saves the given option in the networkSetup map, and informs the user if the value changes
|
||||
func saveOption(opt layers.DHCPOption) {
|
||||
// check if we already stored this value
|
||||
if networkSetup[opt.Type] != nil {
|
||||
// We already stored a value, let's check if it's the same as the new one
|
||||
if !bytes.Equal(networkSetup[opt.Type], opt.Data) {
|
||||
// Already stored a value and it's different from our new value - inform user and overwrite value later
|
||||
log.Printf("Received different values for DHCP Option %s (ID %d). (Old: %s, New. %s)", opt.Type.String(), opt.Type, networkSetup[opt.Type], opt.Data)
|
||||
} else {
|
||||
// Exactly this value was already stored, no need to overwrite it
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
networkSetup[opt.Type] = opt.Data
|
||||
}
|
||||
|
||||
// Formats the given byte array as string representing the IP address, or returns an error (as string)
|
||||
func formatIP(rawIP []byte) string {
|
||||
// Check if we even have an IP
|
||||
if rawIP == nil {
|
||||
// We don't have an IP, construct an error message (as string)
|
||||
error := color.New(color.FgRed)
|
||||
return error.Sprint("(not found)")
|
||||
}
|
||||
|
||||
// Return formatted IP
|
||||
return net.IP(rawIP).String()
|
||||
}
|
||||
|
||||
func formatDate(rawDate []byte) string {
|
||||
// Check if we even have a date
|
||||
if rawDate == nil {
|
||||
// We don't have a date, construct an error message (as string)
|
||||
error := color.New(color.FgRed)
|
||||
return error.Sprint("(not found)")
|
||||
}
|
||||
|
||||
// Actually format date
|
||||
intDate := binary.LittleEndian.Uint32(rawDate)
|
||||
seconds := intDate % 60
|
||||
minutes := intDate / 60 % 60
|
||||
hours := intDate / 60 / 60 % 60
|
||||
formattedDate := ""
|
||||
|
||||
// Check which words we need to pick
|
||||
// ... regarding hours
|
||||
if hours > 0 {
|
||||
formattedDate = fmt.Sprintf("%d hours", hours)
|
||||
}
|
||||
|
||||
// ... regarding minutes
|
||||
if minutes > 0 {
|
||||
// check if we got a previous string we need to take care of
|
||||
if len(formattedDate) > 0 {
|
||||
// yes, append our information to existing string
|
||||
formattedDate = fmt.Sprintf("%s, %d minutes", formattedDate, minutes)
|
||||
} else {
|
||||
// no, use our string
|
||||
formattedDate = fmt.Sprintf("%d minutes", minutes)
|
||||
}
|
||||
}
|
||||
|
||||
// ... regarding seconds
|
||||
if seconds > 0 {
|
||||
// check if we got a previous string we need to take care of
|
||||
if len(formattedDate) > 0 {
|
||||
// yes, append our information to existing string
|
||||
formattedDate = fmt.Sprintf("%s, %d seconds", formattedDate, seconds)
|
||||
} else {
|
||||
// no, use our string
|
||||
formattedDate = fmt.Sprintf("%d seconds", seconds)
|
||||
}
|
||||
}
|
||||
|
||||
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]))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user