From 9210448f16ac41f8d2c733aa226dd91767e16516 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Mon, 20 Oct 2025 22:44:40 +0500 Subject: [PATCH] Add Version method to NFT interface and implementation Include `RunWithOutput` support in the command package and introduce version parsing logic, enabling retrieval of the nftables version and options. --- internal/command/command.go | 13 ++++++++++ nft.go | 49 +++++++++++++++++++++++++++++++++++++ version.go | 21 ++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 version.go diff --git a/internal/command/command.go b/internal/command/command.go index 560e8df..a21834d 100644 --- a/internal/command/command.go +++ b/internal/command/command.go @@ -7,6 +7,7 @@ import ( type NFT interface { Run(arg ...string) error + RunWithOutput(arg ...string) (string, error) } type execNFT struct { @@ -35,3 +36,15 @@ func (r *execNFT) Run(arg ...string) error { return nil } + +func (r *execNFT) RunWithOutput(arg ...string) (string, error) { + cmd := exec.Command(r.nftPath, arg...) + out, err := cmd.CombinedOutput() + if err != nil { + if len(out) > 0 { + return string(out), err + } + return "", err + } + return string(out), nil +} diff --git a/nft.go b/nft.go index 7c4582d..195f4a3 100644 --- a/nft.go +++ b/nft.go @@ -2,7 +2,10 @@ package nft import ( "errors" + "regexp" + "strings" + "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/table" ) @@ -15,6 +18,12 @@ type NFT interface { // nft flush ruleset Clear() error + // Version returns the version of nftables. + // + // This command is equivalent to: + // nft -V + Version() (Version, error) + // Table returns an API for working with tables. Table() table.API } @@ -22,6 +31,7 @@ type NFT interface { type nft struct { command command.NFT table table.API + chain chain.API } // New Returns a client for working with nftables. @@ -48,6 +58,7 @@ func NewWithPath(path string) (NFT, error) { return &nft{ command: nftCommand, table: table.New(nftCommand), + chain: chain.New(nftCommand), }, nil } @@ -56,6 +67,44 @@ func (n *nft) Clear() error { return n.command.Run(args...) } +func (n *nft) Version() (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(string(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() table.API { return n.table } + +func (n *nft) Chain() chain.API { + return n.chain +} diff --git a/version.go b/version.go new file mode 100644 index 0000000..78c53fd --- /dev/null +++ b/version.go @@ -0,0 +1,21 @@ +package nft + +type Version interface { + // Version returns the version of the nftables client. + Version() string + // Opts returns the options of the nftables client. + Opts() map[string]string +} + +type version struct { + version string + opts map[string]string +} + +func (v version) Version() string { + return v.version +} + +func (v version) Opts() map[string]string { + return v.opts +}