package nft import ( "errors" "regexp" "strings" "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract" nftContract "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract/nft" "git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/chain" "git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/command" "git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/rule" "git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/table" ) type nft struct { command contract.Command table nftContract.Table chain nftContract.Chain rule nftContract.Rule } // New Returns a client for working with nftables. // Searches for nft in paths: nft, /usr/sbin/nft, /sbin/nft func New() (contract.NFT, error) { paths := []string{"nft", "/usr/sbin/nft", "/sbin/nft"} for _, path := range paths { nftClient, err := NewWithPath(path) if err == nil { return nftClient, nil } } return nil, errors.New("nft not found") } // NewWithPath Returns the client for working with nftables with its path specified. func NewWithPath(path string) (contract.NFT, error) { nftCommand, err := command.New(path) if err != nil { return nil, err } return &nft{ command: nftCommand, table: table.New(nftCommand), chain: chain.New(nftCommand), rule: rule.New(nftCommand), }, nil } func (n *nft) Clear() error { args := []string{"flush", "ruleset"} return n.command.Run(args...) } func (n *nft) Version() (nftContract.Version, error) { args := []string{"-V"} out, err := n.command.RunWithOutput(args...) if err != nil { return nil, err } vers := "" opts := make(map[string]string) lines := regexp.MustCompile("\r?\n").Split(strings.TrimSpace(out), -1) for index, line := range lines { line = strings.TrimSpace(line) if index == 0 { vers = line continue } values := strings.Split(line, ":") if len(values) != 2 { continue } name := strings.TrimSpace(values[0]) value := strings.TrimSpace(values[1]) opts[name] = value } return &version{ version: vers, opts: opts, }, nil } func (n *nft) Table() nftContract.Table { return n.table } func (n *nft) Chain() nftContract.Chain { return n.chain } func (n *nft) Rule() nftContract.Rule { return n.rule } func (n *nft) Command() contract.Command { return n.command } func (n *nft) ExecuteBatchAfterCheck(batch contract.Batch) error { if err := batch.Check(n.command); err != nil { return err } return n.command.Run(batch.Args()...) } func (n *nft) ExecuteBatch(batch contract.Batch) error { return n.command.Run(batch.Args()...) }