save_restore.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package iptables
  14. import (
  15. "fmt"
  16. "strings"
  17. )
  18. // MakeChainLine return an iptables-save/restore formatted chain line given a Chain
  19. func MakeChainLine(chain Chain) string {
  20. return fmt.Sprintf(":%s - [0:0]", chain)
  21. }
  22. // GetChainLines parses a table's iptables-save data to find chains in the table.
  23. // It returns a map of iptables.Chain to string where the string is the chain line from the save (with counters etc).
  24. func GetChainLines(table Table, save []byte) map[Chain]string {
  25. chainsMap := make(map[Chain]string)
  26. tablePrefix := "*" + string(table)
  27. readIndex := 0
  28. // find beginning of table
  29. for readIndex < len(save) {
  30. line, n := ReadLine(readIndex, save)
  31. readIndex = n
  32. if strings.HasPrefix(line, tablePrefix) {
  33. break
  34. }
  35. }
  36. // parse table lines
  37. for readIndex < len(save) {
  38. line, n := ReadLine(readIndex, save)
  39. readIndex = n
  40. if len(line) == 0 {
  41. continue
  42. }
  43. if strings.HasPrefix(line, "COMMIT") || strings.HasPrefix(line, "*") {
  44. break
  45. } else if strings.HasPrefix(line, "#") {
  46. continue
  47. } else if strings.HasPrefix(line, ":") && len(line) > 1 {
  48. chain := Chain(strings.SplitN(line[1:], " ", 2)[0])
  49. chainsMap[chain] = line
  50. }
  51. }
  52. return chainsMap
  53. }
  54. func ReadLine(readIndex int, byteArray []byte) (string, int) {
  55. currentReadIndex := readIndex
  56. // consume left spaces
  57. for currentReadIndex < len(byteArray) {
  58. if byteArray[currentReadIndex] == ' ' {
  59. currentReadIndex++
  60. } else {
  61. break
  62. }
  63. }
  64. // leftTrimIndex stores the left index of the line after the line is left-trimmed
  65. leftTrimIndex := currentReadIndex
  66. // rightTrimIndex stores the right index of the line after the line is right-trimmed
  67. // it is set to -1 since the correct value has not yet been determined.
  68. rightTrimIndex := -1
  69. for ; currentReadIndex < len(byteArray); currentReadIndex++ {
  70. if byteArray[currentReadIndex] == ' ' {
  71. // set rightTrimIndex
  72. if rightTrimIndex == -1 {
  73. rightTrimIndex = currentReadIndex
  74. }
  75. } else if (byteArray[currentReadIndex] == '\n') || (currentReadIndex == (len(byteArray) - 1)) {
  76. // end of line or byte buffer is reached
  77. if currentReadIndex <= leftTrimIndex {
  78. return "", currentReadIndex + 1
  79. }
  80. // set the rightTrimIndex
  81. if rightTrimIndex == -1 {
  82. rightTrimIndex = currentReadIndex
  83. if currentReadIndex == (len(byteArray)-1) && (byteArray[currentReadIndex] != '\n') {
  84. // ensure that the last character is part of the returned string,
  85. // unless the last character is '\n'
  86. rightTrimIndex = currentReadIndex + 1
  87. }
  88. }
  89. return string(byteArray[leftTrimIndex:rightTrimIndex]), currentReadIndex + 1
  90. } else {
  91. // unset rightTrimIndex
  92. rightTrimIndex = -1
  93. }
  94. }
  95. return "", currentReadIndex
  96. }