Files
yoloyolo/classify/classifier.go
T

73 lines
1.9 KiB
Go
Raw Normal View History

package classify
import (
"github.com/gopacket/gopacket"
"github.com/gopacket/gopacket/layers"
)
// Classifier classifies packets against a rule table.
type Classifier struct {
rules []Rule
}
// NewClassifier creates a classifier with the given rules.
func NewClassifier(rules []Rule) *Classifier {
return &Classifier{rules: rules}
}
// Classify inspects a gopacket.Packet and returns a ClassifiedPacket.
// It checks ICMP first, then extracts TCP/UDP port info and matches against rules.
// Per D-03: returns ClassUnknown if no rule matches.
func (c *Classifier) Classify(pkt gopacket.Packet) ClassifiedPacket {
result := ClassifiedPacket{
Class: ClassUnknown,
Length: len(pkt.Data()),
}
// Check ICMP
if pkt.Layer(layers.LayerTypeICMPv4) != nil || pkt.Layer(layers.LayerTypeICMPv6) != nil {
result.Protocol = "icmp"
// Match against rules
for _, rule := range c.rules {
if rule.Protocol == "icmp" {
result.Class = rule.Class
return result
}
}
return result
}
// Check TCP
if tcpLayer := pkt.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcp := tcpLayer.(*layers.TCP)
result.Protocol = "tcp"
result.SrcPort = uint16(tcp.SrcPort)
result.DstPort = uint16(tcp.DstPort)
for _, rule := range c.rules {
if rule.Protocol == "tcp" && (rule.DstPort == 0 || rule.DstPort == result.DstPort) {
result.Class = rule.Class
return result
}
}
return result
}
// Check UDP
if udpLayer := pkt.Layer(layers.LayerTypeUDP); udpLayer != nil {
udp := udpLayer.(*layers.UDP)
result.Protocol = "udp"
result.SrcPort = uint16(udp.SrcPort)
result.DstPort = uint16(udp.DstPort)
for _, rule := range c.rules {
if rule.Protocol == "udp" && (rule.DstPort == 0 || rule.DstPort == result.DstPort) {
result.Class = rule.Class
return result
}
}
return result
}
// No recognized transport layer -> ClassUnknown per D-03
return result
}