prefixes.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. package flowclass
  2. import (
  3. "bytes"
  4. "fmt"
  5. "strconv"
  6. "idio.link/go/netaddr/v2"
  7. "idio.link/go/parser"
  8. )
  9. /************************** Pfxs **************************/
  10. type fcPfxs struct{}
  11. func (t fcPfxs) Shift(sm *parser.SM, e rune) error {
  12. switch {
  13. case e == ' ':
  14. case e == '{':
  15. sm.Push(fcPfxSet{})
  16. case isDigit(e):
  17. return sm.Push(fcPfxSet{}).Shift(sm, e)
  18. default:
  19. return parser.NewUnrecognized("prefixes", e)
  20. }
  21. return nil
  22. }
  23. func (t fcPfxs) Coalesce(nodes []*parser.CSTNode) any {
  24. return nodes[0].Coalesce()
  25. }
  26. func (t fcPfxs) Value() *bytes.Buffer {
  27. return nil
  28. }
  29. /************************* PfxSet *************************/
  30. type fcPfxSet struct{}
  31. func (t fcPfxSet) Shift(sm *parser.SM, e rune) error {
  32. next := fcSet[fcPfx, *netaddr.NetAddr]{
  33. newToken: func() fcPfx {
  34. return fcPfx{}
  35. },
  36. }
  37. if len(sm.Top().Nodes) == 0 {
  38. return sm.Push(next).Shift(sm, e)
  39. }
  40. return parser.NewUnrecognized("prefix set", e)
  41. }
  42. func (t fcPfxSet) Coalesce(nodes []*parser.CSTNode) any {
  43. return nodes[0].Coalesce()
  44. }
  45. func (t fcPfxSet) Value() *bytes.Buffer {
  46. return nil
  47. }
  48. /*************************** Pfx **************************/
  49. type fcPfx struct{}
  50. func (t fcPfx) Shift(sm *parser.SM, e rune) error {
  51. // TODO: handle IPv6
  52. buf := new(bytes.Buffer)
  53. switch {
  54. case isDigit(e):
  55. buf.WriteRune(e)
  56. sm.Push(fcOctet{val: buf})
  57. case e == '.':
  58. sm.Push(fcOctet{val: buf})
  59. case e == '/':
  60. sm.Push(fcLength{val: buf})
  61. default:
  62. return parser.NewUnrecognized("prefix", e)
  63. }
  64. return nil
  65. }
  66. func (t fcPfx) Coalesce(nodes []*parser.CSTNode) any {
  67. var len byte
  68. addr := make([]byte, 0, 16)
  69. for _, e := range nodes {
  70. switch e.ASTNode.(type) {
  71. case fcOctet:
  72. addr = append(addr, e.Coalesce().(byte))
  73. case fcLength:
  74. len = e.Coalesce().(byte)
  75. }
  76. }
  77. return netaddr.NewNetAddr(addr, int(len))
  78. }
  79. func (t fcPfx) Value() *bytes.Buffer {
  80. return nil
  81. }
  82. /************************* Length *************************/
  83. type fcLength struct {
  84. val *bytes.Buffer
  85. }
  86. func (t fcLength) Shift(sm *parser.SM, e rune) error {
  87. return accNatural(e, "128", t.val, "length")
  88. }
  89. func (t fcLength) Coalesce(_ []*parser.CSTNode) any {
  90. l, _ := strconv.Atoi(string(t.val.Bytes()))
  91. return byte(l)
  92. }
  93. func (t fcLength) Value() *bytes.Buffer {
  94. return t.val
  95. }
  96. /************************* Octet **************************/
  97. type fcOctet struct {
  98. val *bytes.Buffer
  99. }
  100. func (t fcOctet) Shift(sm *parser.SM, e rune) error {
  101. return accNatural(e, "255", t.val, "octet")
  102. }
  103. func (t fcOctet) Coalesce(_ []*parser.CSTNode) any {
  104. o, _ := strconv.Atoi(string(t.val.Bytes()))
  105. return byte(o)
  106. }
  107. func (t fcOctet) Value() *bytes.Buffer {
  108. return t.val
  109. }
  110. func accNatural(
  111. b rune,
  112. max string,
  113. buf *bytes.Buffer,
  114. msg string,
  115. ) error {
  116. switch {
  117. case isDigit(b):
  118. dropLeadingZeros(buf)
  119. buf.WriteRune(b)
  120. val := buf.Bytes()
  121. if natGreaterThan(val, []byte(max)) {
  122. return fmt.Errorf("%s: %s cannot be greater than %s", msg, val, max)
  123. }
  124. case buf.Len() == 0:
  125. return fmt.Errorf("%s: unexpected input: '%s'", msg, string(b))
  126. default:
  127. return parser.NewUnrecognized(msg, b)
  128. }
  129. return nil
  130. }
  131. func dropLeadingZeros(buf *bytes.Buffer) {
  132. if buf == nil {
  133. return
  134. }
  135. if buf.Len() >= 1 && buf.Bytes()[0] == '0' {
  136. buf.Truncate(1)
  137. }
  138. return
  139. }
  140. func natGreaterThan(val []byte, max []byte) bool {
  141. switch {
  142. case len(val) < len(max):
  143. return false
  144. case len(val) > len(max):
  145. return true
  146. }
  147. for i := 0; i < len(val); i++ {
  148. if max[i] > val[i] {
  149. return false
  150. }
  151. }
  152. return true
  153. }