
And update most of the comments to refer to "nftables" rather than "iptables" (even though it doesn't actually do any nftables updating at this point). For now the proxy also internally creates a utiliptablestesting.FakeIPTables to keep the existing sync code compiling.
118 lines
2.9 KiB
Go
118 lines
2.9 KiB
Go
/*
|
|
Copyright 2023 Red Hat, Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package knftables
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// PtrTo can be used to fill in optional field values in objects
|
|
func PtrTo[T any](val T) *T {
|
|
return &val
|
|
}
|
|
|
|
var numericPriorities = map[string]int{
|
|
"raw": -300,
|
|
"mangle": -150,
|
|
"dstnat": -100,
|
|
"filter": 0,
|
|
"security": 50,
|
|
"srcnat": 100,
|
|
}
|
|
|
|
var bridgeNumericPriorities = map[string]int{
|
|
"dstnat": -300,
|
|
"filter": -200,
|
|
"out": 100,
|
|
"srcnat": 300,
|
|
}
|
|
|
|
// ParsePriority tries to convert the string form of a chain priority into a number
|
|
func ParsePriority(family Family, priority string) (int, error) {
|
|
val, err := strconv.Atoi(priority)
|
|
if err == nil {
|
|
return val, nil
|
|
}
|
|
|
|
modVal := 0
|
|
if i := strings.IndexAny(priority, "+-"); i != -1 {
|
|
mod := priority[i:]
|
|
modVal, err = strconv.Atoi(mod)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("could not parse modifier %q: %w", mod, err)
|
|
}
|
|
priority = priority[:i]
|
|
}
|
|
|
|
var found bool
|
|
if family == BridgeFamily {
|
|
val, found = bridgeNumericPriorities[priority]
|
|
} else {
|
|
val, found = numericPriorities[priority]
|
|
}
|
|
if !found {
|
|
return 0, fmt.Errorf("unknown priority %q", priority)
|
|
}
|
|
|
|
return val + modVal, nil
|
|
}
|
|
|
|
// Concat is a helper (primarily) for constructing Rule objects. It takes a series of
|
|
// arguments and concatenates them together into a single string with spaces between the
|
|
// arguments. Strings are output as-is, string arrays are output element by element,
|
|
// numbers are output as with `fmt.Sprintf("%d")`, and all other types are output as with
|
|
// `fmt.Sprintf("%s")`. To help with set/map lookup syntax, an argument of "@" will not
|
|
// be followed by a space, so you can do, eg, `Concat("ip saddr", "@", setName)`.
|
|
func Concat(args ...interface{}) string {
|
|
b := &strings.Builder{}
|
|
var needSpace, wroteAt bool
|
|
for _, arg := range args {
|
|
switch x := arg.(type) {
|
|
case string:
|
|
if needSpace {
|
|
b.WriteByte(' ')
|
|
}
|
|
b.WriteString(x)
|
|
wroteAt = (x == "@")
|
|
case []string:
|
|
for _, s := range x {
|
|
if needSpace {
|
|
b.WriteByte(' ')
|
|
}
|
|
b.WriteString(s)
|
|
wroteAt = (s == "@")
|
|
needSpace = b.Len() > 0 && !wroteAt
|
|
}
|
|
case int, uint, int16, uint16, int32, uint32, int64, uint64:
|
|
if needSpace {
|
|
b.WriteByte(' ')
|
|
}
|
|
fmt.Fprintf(b, "%d", x)
|
|
default:
|
|
if needSpace {
|
|
b.WriteByte(' ')
|
|
}
|
|
fmt.Fprintf(b, "%s", x)
|
|
}
|
|
|
|
needSpace = b.Len() > 0 && !wroteAt
|
|
}
|
|
return b.String()
|
|
}
|