123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- package flowclass
- import (
- "bytes"
- "fmt"
- "strconv"
- "idio.link/go/parser"
- )
- /*********************** IPPDelim *************************/
- type fcIPPDelim struct {
- val *bytes.Buffer
- }
- func (t fcIPPDelim) Shift(sm *parser.SM, e rune) error {
- switch e {
- case ' ':
- case ':':
- t.val.WriteRune(e)
- default:
- if string(t.val.Bytes()) != ":" {
- return fmt.Errorf("ipp delimiter: unexpected input: '%s'", t.val.Bytes())
- }
- return parser.NewUnrecognized("ipp delimiter", e)
- }
- return nil
- }
- func (_ fcIPPDelim) Coalesce(_ []*parser.CSTNode) any {
- return nil
- }
- func (t fcIPPDelim) Value() *bytes.Buffer {
- return t.val
- }
- /************************* IPPs ***************************/
- type fcIPPs struct {
- }
- func (t fcIPPs) Shift(sm *parser.SM, e rune) error {
- switch {
- case e == ' ':
- case e == '{':
- sm.Push(fcIPPSet{})
- case isDigit(e) || isAlpha(e):
- return sm.Push(fcIPPSet{}).Shift(sm, e)
- default:
- return parser.NewUnrecognized("ipps", e)
- }
- return nil
- }
- func (t fcIPPs) Coalesce(nodes []*parser.CSTNode) any {
- return nodes[0].Coalesce()
- }
- func (t fcIPPs) Value() *bytes.Buffer {
- return nil
- }
- /************************ IPPSet **************************/
- type fcIPPSet struct {
- }
- func (t fcIPPSet) Shift(sm *parser.SM, e rune) error {
- next := fcSet[fcIPPInst, IPP]{
- newToken: func() fcIPPInst {
- return fcIPPInst{}
- },
- }
- if len(sm.Top().Nodes) == 0 {
- return sm.Push(next).Shift(sm, e)
- }
- return parser.NewUnrecognized("ipp set", e)
- }
- func (t fcIPPSet) Coalesce(nodes []*parser.CSTNode) any {
- return nodes[0].Coalesce()
- }
- func (t fcIPPSet) Value() *bytes.Buffer {
- return nil
- }
- /*********************** IPPInst **************************/
- type fcIPPInst struct {
- }
- func (t fcIPPInst) Shift(sm *parser.SM, e rune) error {
- length := len(sm.Top().Nodes)
- if length == 0 {
- return sm.Push(fcIPP{}).Shift(sm, e)
- }
- switch {
- case e == '(':
- if length > 1 {
- return fmt.Errorf("ipp instance: unexpected state: %+v; event %v", sm, e)
- }
- // ippinst -> ipp -> octet | ippname
- ippVal :=
- sm.Top().Nodes[0].Nodes[0].ASTNode.Value().Bytes()
- if bytes.Equal(ippVal, []byte("icmp")) ||
- bytes.Equal(ippVal, []byte("1")) {
- sm.Push(fcICMPParms{})
- }
- if bytes.Equal(ippVal, []byte("tcp")) ||
- bytes.Equal(ippVal, []byte("6")) {
- sm.Push(fcTCPParms{})
- }
- if bytes.Equal(ippVal, []byte("udp")) ||
- bytes.Equal(ippVal, []byte("17")) {
- sm.Push(fcUDPParms{})
- }
- default:
- return parser.NewUnrecognized("ipp instance", e)
- }
- return nil
- }
- func (t fcIPPInst) Coalesce(nodes []*parser.CSTNode) any {
- if len(nodes) == 2 {
- return nodes[1].Coalesce()
- }
- return nodes[0].Coalesce()
- }
- func (t fcIPPInst) Value() *bytes.Buffer {
- return nil
- }
- /************************* IPP ****************************/
- type fcIPP struct {
- }
- func (t fcIPP) Shift(sm *parser.SM, e rune) error {
- switch {
- case isDigit(e):
- return sm.Push(fcIPPDecimal{}).Shift(sm, e)
- case isAlpha(e):
- buf := new(bytes.Buffer)
- buf.WriteRune(e)
- sm.Push(fcIPPName{val: buf})
- default:
- return parser.NewUnrecognized("ipp", e)
- }
- return nil
- }
- func (t fcIPP) Coalesce(nodes []*parser.CSTNode) any {
- return nodes[0].Coalesce()
- }
- func (t fcIPP) Value() *bytes.Buffer {
- return nil
- }
- /*********************** IPPName **************************/
- var ippNameToProto = map[string]byte{
- "any": 0,
- "icmp": 1,
- "tcp": 6,
- "udp": 17,
- }
- type fcIPPName struct {
- val *bytes.Buffer
- }
- func (t fcIPPName) Shift(sm *parser.SM, e rune) error {
- switch {
- case isAlpha(e):
- t.val.WriteRune(e)
- default:
- name := string(t.val.Bytes())
- if _, ok := ippNameToProto[name]; !ok {
- return fmt.Errorf("ipp name: unknown ipp name '%s'", name)
- }
- return parser.NewUnrecognized("ipp name", e)
- }
- return nil
- }
- func (t fcIPPName) Coalesce(_ []*parser.CSTNode) any {
- switch string(t.val.Bytes()) {
- case "any":
- return ipProtocol(0)
- case "icmp":
- return ippICMP{}
- case "tcp":
- return ippTCP{}
- case "udp":
- return ippUDP{}
- default:
- panic("BUG: unknown ipp name")
- }
- }
- func (t fcIPPName) Value() *bytes.Buffer {
- return t.val
- }
- /********************** IPPDecimal ************************/
- type fcIPPDecimal struct {
- }
- func (t fcIPPDecimal) Shift(sm *parser.SM, e rune) error {
- if len(sm.Top().Nodes) == 0 {
- return sm.Push(fcOctet{}).Shift(sm, e)
- }
- return parser.NewUnrecognized("ipp decimal", e)
- }
- func (t fcIPPDecimal) Coalesce(nodes []*parser.CSTNode) any {
- oct := nodes[0].Coalesce().(byte)
- switch oct {
- case 1:
- return ippICMP{}
- case 6:
- return ippTCP{}
- case 17:
- return ippUDP{}
- default:
- return ipProtocol(oct)
- }
- }
- func (t fcIPPDecimal) Value() *bytes.Buffer {
- return nil
- }
- /********************** Parameters ************************/
- type fcICMPParms struct {
- }
- func (t fcICMPParms) Value() *bytes.Buffer {
- return nil
- }
- func (t fcICMPParms) Shift(sm *parser.SM, e rune) error {
- next := fcVector[fcOctet, byte]{
- dim: 2,
- newToken: func() fcOctet {
- return fcOctet{val: new(bytes.Buffer)}
- },
- }
- if len(sm.Top().Nodes) == 0 {
- return sm.Push(next).Shift(sm, e)
- }
- return parser.NewUnrecognized("icmp params", e)
- }
- func (t fcICMPParms) Coalesce(nodes []*parser.CSTNode) any {
- return ippICMP{
- icmpType: nodes[0].Nodes[0].Coalesce().(byte),
- code: nodes[0].Nodes[1].Coalesce().(byte),
- }
- }
- type fcTCPParms struct {
- }
- func (t fcTCPParms) Shift(sm *parser.SM, e rune) error {
- next := fcVector[fcPort, uint16]{
- dim: 2,
- newToken: func() fcPort {
- return fcPort{val: new(bytes.Buffer)}
- },
- }
- if len(sm.Top().Nodes) == 0 {
- return sm.Push(next).Shift(sm, e)
- }
- return parser.NewUnrecognized("tcp params", e)
- }
- func (t fcTCPParms) Coalesce(nodes []*parser.CSTNode) any {
- return ippTCP{
- spt: nodes[0].Nodes[0].Coalesce().(uint16),
- dpt: nodes[0].Nodes[1].Coalesce().(uint16),
- }
- }
- func (t fcTCPParms) Value() *bytes.Buffer {
- return nil
- }
- type fcUDPParms struct {
- }
- func (t fcUDPParms) Shift(sm *parser.SM, e rune) error {
- next := fcVector[fcPort, uint16]{
- dim: 2,
- newToken: func() fcPort {
- return fcPort{val: new(bytes.Buffer)}
- },
- }
- if len(sm.Top().Nodes) == 0 {
- return sm.Push(next).Shift(sm, e)
- }
- return parser.NewUnrecognized("udp params", e)
- }
- func (t fcUDPParms) Coalesce(nodes []*parser.CSTNode) any {
- return ippUDP{
- spt: nodes[0].Nodes[0].Coalesce().(uint16),
- dpt: nodes[0].Nodes[1].Coalesce().(uint16),
- }
- }
- func (t fcUDPParms) Value() *bytes.Buffer {
- return nil
- }
- type fcPort struct {
- val *bytes.Buffer
- }
- func (t fcPort) Shift(sm *parser.SM, e rune) error {
- return accNatural(e, "65535", t.val, "port")
- }
- func (t fcPort) Coalesce(_ []*parser.CSTNode) any {
- p, _ := strconv.Atoi(string(t.val.Bytes()))
- return uint16(p)
- }
- func (t fcPort) Value() *bytes.Buffer {
- return t.val
- }
|