package flowclass import ( "fmt" "idio.link/go/netaddr/v2" "idio.link/go/parser" ) type FlowClass struct { // dstClasses indices correspond to ipps indices tree *parser.CSTNode srcs []*netaddr.NetAddr dsts [][]*netaddr.NetAddr ipps [][]IPP } func (fc *FlowClass) Compile(s string) error { err := fc.tree.Parse(s) if err != nil { return err } coalesced := fc.tree.Coalesce() fc.srcs = coalesced.srcs.(map[string]*netaddr.NetAddr) fc.dsts = coalesced.dsts.([]*DstSock) fc.tree = nil return nil } func (fc *FlowClass) Sources() []*netaddr.NetAddr { srcs := make([]*netaddr.NetAddr, len(fc.srcs)) for i, e := range fc.srcs { tmp := *e srcs[i] = &tmp } return srcs } func (fc *FlowClass) Destinations() []*netaddr.NetAddr { dsts := make([]*netaddr.NetAddr, len(fc.dsts)) for i, e := range fc.dstSocks { tmp := *e dsts[i] = &tmp } return dsts } type IPP interface { Name() string Decimal() ipProtocol String() string } /* If this is used to indicate ICMP with type of "any", how * do we represent this in port literals? */ type ipProtocol byte func (p ipProtocol) Name() string { return "" } func (p ipProtocol) String() string { return fmt.Sprintf("%d", p) } func (p ipProtocol) Decimal() ipProtocol { return p } type ippICMP struct { icmpType byte code byte } func (p ippICMP) Type() byte { return p.icmpType } func (p ippICMP) Code() byte { return p.code } func (p ippICMP) Name() string { return "icmp" } func (p ippICMP) Decimal() ipProtocol { return 1 } func (p ippICMP) String() string { return fmt.Sprintf("%s(%d,%d)", p.Name(), p.Type(), p.Code()) } type ippTCP struct { spt uint16 dpt uint16 } func (p ippTCP) Sport() uint16 { return p.spt } func (p ippTCP) Dport() uint16 { return p.dpt } func (p ippTCP) Name() string { return "tcp" } func (p ippTCP) Decimal() ipProtocol { return 6 } func (p ippTCP) String() string { return fmt.Sprintf("%s(%d,%d)", p.Name(), p.Sport(), p.Dport()) } type ippUDP struct { spt uint16 dpt uint16 } func (p ippUDP) Sport() uint16 { return p.spt } func (p ippUDP) Dport() uint16 { return p.dpt } func (p ippUDP) Name() string { return "udp" } func (p ippUDP) Decimal() ipProtocol { return 17 } func (p ippUDP) String() string { return fmt.Sprintf("%s(%d,%d)", p.Name(), p.Sport(), p.Dport()) }