github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/pkg/ipsetmanager/ipsetprovider.go (about) 1 // +build linux darwin 2 3 package ipsetmanager 4 5 import ( 6 "fmt" 7 "os/exec" 8 "strings" 9 10 "github.com/aporeto-inc/go-ipset/ipset" 11 "go.aporeto.io/enforcerd/trireme-lib/controller/constants" 12 "go.uber.org/zap" 13 ) 14 15 var ( 16 // path to aporeto-ipset 17 ipsetBinPath string 18 ) 19 20 // IpsetProvider returns a fabric for Ipset. 21 type IpsetProvider interface { 22 NewIpset(name string, ipsetType string, p *ipset.Params) (Ipset, error) 23 GetIpset(name string) Ipset 24 DestroyAll(prefix string) error 25 ListIPSets() ([]string, error) 26 } 27 28 // Ipset is an abstraction of all the methods an implementation of userspace 29 // ipsets need to provide. 30 type Ipset interface { 31 Add(entry string, timeout int) error 32 AddOption(entry string, option string, timeout int) error 33 Del(entry string) error 34 Destroy() error 35 Flush() error 36 Test(entry string) (bool, error) 37 } 38 39 type goIpsetProvider struct{} 40 41 var instance IpsetProvider = &goIpsetProvider{} 42 43 func ipsetCreateBitmapPort(setname string) error { 44 //Bitmap type is not supported by the ipset library 45 out, err := exec.Command(ipsetBinPath, "create", setname, "bitmap:port", "range", "0-65535", "timeout", "0").CombinedOutput() 46 if err != nil { 47 if strings.Contains(string(out), "set with the same name already exists") { 48 zap.L().Warn("Set already exists - cleaning up", zap.String("set name", setname)) 49 // Clean up the existing set 50 if _, cerr := exec.Command(ipsetBinPath, "-F", setname).CombinedOutput(); cerr != nil { 51 return fmt.Errorf("Failed to clean up existing ipset: %s", err) 52 } 53 return nil 54 } 55 zap.L().Error("Unable to create set", zap.String("set name", setname), zap.String("ipset-output", string(out))) 56 } 57 return err 58 } 59 60 // NewIpset returns an IpsetProvider interface based on the go-ipset 61 // external package. 62 func (i *goIpsetProvider) NewIpset(name string, ipsetType string, p *ipset.Params) (Ipset, error) { 63 64 // Check if hashtype is a type of hash 65 if strings.HasPrefix(ipsetType, "hash:") { 66 return ipset.New(name, ipsetType, p) 67 } 68 69 if err := ipsetCreateBitmapPort(name); err != nil { 70 return nil, err 71 } 72 73 return &ipset.IPSet{Name: name}, nil 74 } 75 76 // GetIpset gets the ipset object from the name. 77 func (i *goIpsetProvider) GetIpset(name string) Ipset { 78 return &ipset.IPSet{ 79 Name: name, 80 } 81 } 82 83 // DestroyAll destroys all the ipsets with the given prefix 84 func (i *goIpsetProvider) DestroyAll(prefix string) error { 85 return ipset.DestroyAll(prefix) 86 } 87 88 func (i *goIpsetProvider) ListIPSets() ([]string, error) { 89 90 out, err := exec.Command(ipsetBinPath, "-L", "-name").CombinedOutput() 91 if err != nil { 92 return nil, fmt.Errorf("unable to list ipsets:%s", err) 93 } 94 95 return strings.Split(string(out), "\n"), nil 96 } 97 98 func newIpset(name string, ipsetType string, p *ipset.Params) (Ipset, error) { 99 return instance.NewIpset(name, ipsetType, p) 100 } 101 102 func getIpset(name string) Ipset { 103 return instance.GetIpset(name) 104 } 105 106 func destroyAll(prefix string) error { 107 return instance.DestroyAll(prefix) 108 } 109 110 func listIPSets() ([]string, error) { 111 return instance.ListIPSets() 112 } 113 114 //SetIpsetTestInstance sets a test instance of ipsetprovider 115 func SetIpsetTestInstance(ipsetprovider IpsetProvider) { 116 instance = ipsetprovider 117 } 118 119 //SetIPsetPath sets the path for aporeto-ipset 120 func SetIPsetPath() { 121 ipsetBinPath, _ = exec.LookPath(constants.IpsetBinaryName) // nolint: errcheck 122 // tell the go-ipset package which ipset binary to use 123 ipset.Init(ipsetBinPath) // nolint: errcheck 124 }