2019-11-28 16:16:22 +00:00
|
|
|
package dhcpv4
|
|
|
|
|
|
|
|
import (
|
2023-09-02 15:17:51 +00:00
|
|
|
"github.com/maride/pancap/output"
|
2019-11-28 16:16:22 +00:00
|
|
|
"github.com/google/gopacket"
|
|
|
|
"github.com/google/gopacket/layers"
|
|
|
|
)
|
|
|
|
|
2019-12-09 11:14:01 +00:00
|
|
|
type Protocol struct {
|
|
|
|
hostnames []hostname
|
|
|
|
networkSetup map[layers.DHCPOpt][]byte
|
|
|
|
requestMAC []string
|
|
|
|
responses []dhcpResponse
|
|
|
|
}
|
|
|
|
|
|
|
|
// Checks if the given packet is a DHCP packet we can process
|
|
|
|
func (p *Protocol) CanAnalyze(packet gopacket.Packet) bool {
|
|
|
|
return packet.Layer(layers.LayerTypeDHCPv4) != nil && packet.Layer(layers.LayerTypeEthernet) != nil && packet.Layers()[2].LayerPayload() != nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Analyzes the given DHCP packet
|
|
|
|
func (p *Protocol) Analyze(packet gopacket.Packet) error {
|
2019-11-28 16:16:22 +00:00
|
|
|
var dhcppacket layers.DHCPv4
|
|
|
|
var ethernetpacket layers.Ethernet
|
|
|
|
|
2019-12-09 11:14:01 +00:00
|
|
|
// Check if it's the first run - init networkSetup map then
|
|
|
|
if p.networkSetup == nil {
|
|
|
|
p.networkSetup = make(map[layers.DHCPOpt][]byte)
|
|
|
|
}
|
|
|
|
|
2019-11-28 17:48:54 +00:00
|
|
|
// For some reason I can't find an explanation for,
|
|
|
|
// packet.Layer(layers.LayerTypeDHCPv4).LayerContents(), which effectively is
|
|
|
|
// packet.Layers()[3].layerContents(), is empty, but
|
|
|
|
// packet.Layers()[2].layerPayload() contains the correct DHCP packet.
|
|
|
|
// ... although both calls should return the same bytes.
|
|
|
|
// TODO: Open an Issue on github.com/google/gopacket
|
|
|
|
|
2019-11-28 16:16:22 +00:00
|
|
|
// Decode raw packet into DHCPv4
|
2019-11-28 17:48:54 +00:00
|
|
|
decodeDHCPErr := dhcppacket.DecodeFromBytes(packet.Layers()[2].LayerPayload(), gopacket.NilDecodeFeedback)
|
2019-11-28 16:16:22 +00:00
|
|
|
if decodeDHCPErr != nil {
|
|
|
|
// Encountered an error during decoding, most likely a broken packet
|
|
|
|
return decodeDHCPErr
|
|
|
|
}
|
|
|
|
|
|
|
|
// And decode raw packet into Ethernet
|
|
|
|
decodeEthernetErr := ethernetpacket.DecodeFromBytes(packet.Layer(layers.LayerTypeEthernet).LayerContents(), gopacket.NilDecodeFeedback)
|
|
|
|
if decodeEthernetErr != nil {
|
|
|
|
// Encountered an error during decoding, most likely a broken packet
|
|
|
|
return decodeEthernetErr
|
|
|
|
}
|
|
|
|
|
|
|
|
// Examine packet further
|
|
|
|
if dhcppacket.Operation == layers.DHCPOpRequest {
|
|
|
|
// Request packet
|
2019-12-09 11:14:01 +00:00
|
|
|
p.processRequestPacket(dhcppacket)
|
2019-11-28 16:16:22 +00:00
|
|
|
} else {
|
|
|
|
// Response/Offer packet
|
2019-12-09 11:14:01 +00:00
|
|
|
p.processResponsePacket(dhcppacket, ethernetpacket)
|
2019-11-28 16:16:22 +00:00
|
|
|
}
|
|
|
|
|
2019-11-28 22:43:17 +00:00
|
|
|
// Check for Hostname DHCP option (12)
|
2019-12-09 11:14:01 +00:00
|
|
|
p.checkForHostname(dhcppacket)
|
|
|
|
p.checkForNetworkInfos(dhcppacket)
|
2019-11-28 22:43:17 +00:00
|
|
|
|
2019-11-28 16:16:22 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print summary after all packets are processed
|
2019-12-09 11:14:01 +00:00
|
|
|
func (p *Protocol) PrintSummary() {
|
|
|
|
output.PrintBlock("DHCP Network Overview", p.generateNetworkSummary())
|
|
|
|
output.PrintBlock("DHCP Requests", p.generateRequestSummary())
|
|
|
|
output.PrintBlock("DHCP Responses/Offers", p.generateResponseSummary())
|
|
|
|
output.PrintBlock("DHCP Hostnames", p.generateHostnamesSummary())
|
2019-11-28 16:16:22 +00:00
|
|
|
}
|