func New(exec utilexec.Interface) Interface {
	return &runner{
		exec: exec,
	}
}
New returns a new Interface which will exec ipset.
package ipset
import (
	"bytes"
	"fmt"
	"net"
	"regexp"
	"strconv"
	"strings"
	"k8s.io/klog/v2"
	utilexec "k8s.io/utils/exec"
)
type Interface interface {
	FlushSet(set string) error
	DestroySet(set string) error
	DestroyAllSets() error
	CreateSet(set *IPSet, ignoreExistErr bool) error
	AddEntry(entry string, set *IPSet, ignoreExistErr bool) error
	DelEntry(entry string, set string) error
	TestEntry(entry string, set string) (bool, error)
	ListEntries(set string) ([]string, error)
	ListSets() ([]string, error)
	GetVersion() (string, error)
}
const IPSetCmd = "ipset"
var EntryMemberPattern = "(?m)^(.*\n)*Members:\n"
var VersionPattern = "v[0-9]+\\.[0-9]+"
type IPSet struct {
	Name string
	SetType Type
	HashFamily string
	HashSize int
	MaxElem int
	PortRange string
	Comment string
}
func (set *IPSet) Validate() bool {
	if set.SetType == HashIPPort || set.SetType == HashIPPortIP || set.SetType == HashIPPortNet {
		if valid := validateHashFamily(set.HashFamily); !valid {
			return false
		}
	}
	if valid := validateIPSetType(set.SetType); !valid {
		return false
	}
	if set.SetType == BitmapPort {
		if valid := validatePortRange(set.PortRange); !valid {
			return false
		}
	}
	if set.HashSize <= 0 {
		klog.Errorf("Invalid hashsize value %d, should be >0", set.HashSize)
		return false
	}
	if set.MaxElem <= 0 {
		klog.Errorf("Invalid maxelem value %d, should be >0", set.MaxElem)
		return false
	}
	return true
}
func (set *IPSet) setIPSetDefaults() {
	if set.HashSize == 0 {
		set.HashSize = 1024
	}
	if set.MaxElem == 0 {
		set.MaxElem = 65536
	}
	if set.HashFamily == "" {
		set.HashFamily = ProtocolFamilyIPV4
	}
	if len(set.SetType) == 0 {
		set.SetType = HashIPPort
	}
	if len(set.PortRange) == 0 {
		set.PortRange = DefaultPortRange
	}
}
type Entry struct {
	IP string
	Port int
	Protocol string
	Net string
	IP2 string
	SetType Type
}
func (e *Entry) Validate(set *IPSet) bool {
	if e.Port < 0 {
		klog.Errorf("Entry %v port number %d should be >=0 for ipset %v", e, e.Port, set)
		return false
	}
	switch e.SetType {
	case HashIPPort:
		if valid := e.checkIPandProtocol(set); !valid {
			return false
		}
	case HashIPPortIP:
		if valid := e.checkIPandProtocol(set); !valid {
			return false
		}
		if net.ParseIP(e.IP2) == nil {
			klog.Errorf("Error parsing entry %v second ip address %v for ipset %v", e, e.IP2, set)
			return false
		}
	case HashIPPortNet:
		if valid := e.checkIPandProtocol(set); !valid {
			return false
		}
		if _, ipNet, err := net.ParseCIDR(e.Net); ipNet == nil {
			klog.Errorf("Error parsing entry %v ip net %v for ipset %v, error: %v", e, e.Net, set, err)
			return false
		}
	case BitmapPort:
		if set == nil {
			klog.Errorf("Unable to reference ip set where the entry %v exists", e)
			return false
		}
		begin, end, err := parsePortRange(set.PortRange)
		if err != nil {
			klog.Errorf("Failed to parse set %v port range %s for ipset %v, error: %v", set, set.PortRange, set, err)
			return false
		}
		if e.Port < begin || e.Port > end {
			klog.Errorf("Entry %v port number %d is not in the port range %s of its ipset %v", e, e.Port, set.PortRange, set)
			return false
		}
	case HashIP:
		if ip := net.ParseIP(e.IP); ip == nil {
			err := fmt.Errorf("%s is not a valid textual representation of an IP address", e.IP)
			klog.Errorf("Failed to parse entry %v ip %v for ipset %v, error: %v", e, e.IP, set, err)
			return false
		}
	case HashNet:
		if _, _, err := net.ParseCIDR(e.Net); err != nil {
			klog.Errorf("Failed to parse entry %v net %v for ipset %v, error: %v", e, e.Net, set, err)
			return false
		}
	}
	return true
}
func (e *Entry) String() string {
	switch e.SetType {
	case HashIPPort:
		return fmt.Sprintf("%s,%s:%s", e.IP, e.Protocol, strconv.Itoa(e.Port))
	case HashIPPortIP:
		return fmt.Sprintf("%s,%s:%s,%s", e.IP, e.Protocol, strconv.Itoa(e.Port), e.IP2)
	case HashIPPortNet:
		return fmt.Sprintf("%s,%s:%s,%s", e.IP, e.Protocol, strconv.Itoa(e.Port), e.Net)
	case BitmapPort:
		return strconv.Itoa(e.Port)
	case HashIP:
		return e.IP
	case HashNet:
		return e.Net
	}
	return ""
}
func (e *Entry) checkIPandProtocol(set *IPSet) bool {
	if len(e.Protocol) == 0 {
		e.Protocol = ProtocolTCP
	} else if !validateProtocol(e.Protocol) {
		return false
	}
	if net.ParseIP(e.IP) == nil {
		klog.Errorf("Error parsing entry %v ip address %v for ipset %v", e, e.IP, set)
		return false
	}
	return true
}
type runner struct {
	exec utilexec.Interface
}