github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/pkg/ipsetmanager/ipsetmanager.go (about)

     1  package ipsetmanager
     2  
     3  import (
     4  	"encoding/base64"
     5  	"fmt"
     6  	"io"
     7  	"net"
     8  	"strings"
     9  	"sync"
    10  
    11  	ipsetpackage "github.com/aporeto-inc/go-ipset/ipset"
    12  	"github.com/spaolacci/murmur3"
    13  
    14  	"go.aporeto.io/enforcerd/trireme-lib/controller/constants"
    15  	"go.aporeto.io/enforcerd/trireme-lib/policy"
    16  	"go.uber.org/zap"
    17  )
    18  
    19  const (
    20  	//IPv6DefaultIP is the default ip of v6
    21  	IPv6DefaultIP = "::/0"
    22  	//IPv4DefaultIP is the  default ip for v4
    23  	IPv4DefaultIP = "0.0.0.0/0"
    24  	//IPsetV4 version for ipv4
    25  	IPsetV4 = iota
    26  	//IPsetV6 version for ipv6
    27  	IPsetV6
    28  
    29  	processPortSetPrefix = "ProcPort-"
    30  	proxyPortSetPrefix   = "Proxy-"
    31  	targetTCPSuffix      = "TargetTCP"
    32  	targetUDPSuffix      = "TargetUDP"
    33  	excludedSuffix       = "Excluded"
    34  )
    35  
    36  //TargetAndExcludedNetworks interface is used to interact with target and excluded networks
    37  type TargetAndExcludedNetworks interface {
    38  	//CreateIPsetsForTargetAndExcludedNetworks creates the ipsets for target and excluded networks
    39  	CreateIPsetsForTargetAndExcludedNetworks() error
    40  	//UpdateIPsetsForTargetAndExcludedNetworks updates the ipsets accordingly.
    41  	UpdateIPsetsForTargetAndExcludedNetworks([]string, []string, []string) error
    42  	//GetIPsetNamesForTargetAndExcludedNetworks returns the ipsets names for tcp, udp and excluded networks
    43  	GetIPsetNamesForTargetAndExcludedNetworks() (string, string, string)
    44  }
    45  
    46  //ServerL3 interface is used to interact with the ipsets required to program
    47  //ports that the server(PU) listens on in L3 datapath.
    48  type ServerL3 interface {
    49  	//CreateServerPortSet creates the ipset.
    50  	CreateServerPortSet(contextID string) error
    51  	//GetServerPortSetName returns the name of the portset created
    52  	GetServerPortSetName(contextID string) string
    53  	//DestroyServerPortSet destroys the server port set.
    54  	DestroyServerPortSet(contextID string) error
    55  	//AddPortToServerPortSet adds port to the portset.
    56  	AddPortToServerPortSet(contextID string, port string) error
    57  	//DeletePortFromServerPortSet deletes the port from port set.
    58  	DeletePortFromServerPortSet(contextID string, port string) error
    59  }
    60  
    61  // ACLL3 interface is used to interact with the ipsets required for
    62  // application and network acl's in L3.
    63  type ACLL3 interface {
    64  	//RegisterExternalNets registers the ipsets corresponding the external networks.
    65  	RegisterExternalNets(contextID string, extnets policy.IPRuleList) error
    66  	//AddACLIPsets adds the IPs in the ipsets corresponding to the external network service ID.
    67  	UpdateACLIPsets([]string, string)
    68  	//DestroyUnusedIPsets will remove the unused ipsets.
    69  	DestroyUnusedIPsets()
    70  	//RemoveExternalNets removes the external networks corresponding to the PU contextID.
    71  	RemoveExternalNets(contextID string)
    72  	//GetACLIPsets returns the ipset string that correspond to the external networks in the argument
    73  	GetACLIPsetsNames(extnets policy.IPRuleList) []string
    74  	// DeleteEntryFromIPset delete an entry from an ipset
    75  	DeleteEntryFromIPset(ips []string, serviceID string)
    76  }
    77  
    78  //ProxyL4 interface is used to interact with the ipsets required for
    79  //L4/L7 Services. These include dependent services and exposed Services
    80  type ProxyL4 interface {
    81  	//CreateProxySets creates the ipsets to implement L4/L7 services
    82  	CreateProxySets(contextID string) error
    83  	//GetProxyIPsetNames returns the ipset strings that correspond to the pu
    84  	GetProxySetNames(contextID string) (string, string)
    85  	//DestroyProxySet destroys the ipsets being used for L4/L7 services
    86  	DestroyProxySets(contextID string)
    87  	//FlushProxySets flushes the proxy IPsets
    88  	FlushProxySets(contextID string)
    89  	//AddIPPortToDependentService adds ip port to the dependent service
    90  	AddIPPortToDependentService(contextID string, ip *net.IPNet, port string) error
    91  	//AddPortToExposedService adds the port that this service is exposing
    92  	AddPortToExposedService(contextID string, port string) error
    93  }
    94  
    95  //DestroyAll destroys all the ipsets created.
    96  type DestroyAll interface {
    97  	//DestroyAllIPsets destroys the created ipsets.
    98  	DestroyAllIPsets() error
    99  }
   100  
   101  //IPsetPrefix returns the prefix used to construct the ipset.
   102  type IPsetPrefix interface {
   103  	//GetIPsetPrefix returns the prefix.
   104  	GetIPsetPrefix() string
   105  }
   106  
   107  //IPSetManager interface is used by supervisor. This interface provides the supervisor to
   108  //create ipsets corresponding to service ID.
   109  type IPSetManager interface {
   110  	TargetAndExcludedNetworks
   111  	ServerL3
   112  	ACLL3
   113  	ProxyL4
   114  	DestroyAll
   115  	IPsetPrefix
   116  
   117  	Reset()
   118  }
   119  
   120  type ipsetInfo struct {
   121  	contextIDs map[string]bool
   122  	name       string
   123  	addresses  map[string]bool
   124  }
   125  
   126  type aclHandler struct {
   127  	serviceIDtoACLIPset   map[string]*ipsetInfo
   128  	contextIDtoServiceIDs map[string]map[string]bool
   129  	toDestroy             []string
   130  }
   131  
   132  type targetNetwork struct {
   133  	tcp []string
   134  	udp []string
   135  }
   136  
   137  type excludedNetwork struct {
   138  	excluded []string
   139  }
   140  
   141  type handler struct {
   142  	sync.RWMutex
   143  
   144  	ipsetPrefix string
   145  	ipFilter    func(net.IP) bool
   146  	ipsetParams *ipsetpackage.Params
   147  
   148  	acl aclHandler
   149  	tn  targetNetwork
   150  	en  excludedNetwork
   151  
   152  	dynamicUpdates map[string][]string
   153  }
   154  
   155  const (
   156  	ipv4String = "v4-"
   157  	ipv6String = "v6-"
   158  )
   159  
   160  var ipv4Handler = &handler{
   161  	ipsetPrefix: constants.ChainPrefix + ipv4String,
   162  	ipFilter: func(ip net.IP) bool {
   163  		return (ip.To4() != nil)
   164  	},
   165  	ipsetParams: &ipsetpackage.Params{},
   166  
   167  	acl: aclHandler{
   168  		serviceIDtoACLIPset:   map[string]*ipsetInfo{},
   169  		contextIDtoServiceIDs: map[string]map[string]bool{},
   170  	},
   171  	tn:             targetNetwork{tcp: []string{}, udp: []string{}},
   172  	en:             excludedNetwork{excluded: []string{}},
   173  	dynamicUpdates: map[string][]string{},
   174  }
   175  
   176  var ipv6Handler = &handler{
   177  	ipsetPrefix: constants.ChainPrefix + ipv6String,
   178  	ipFilter: func(ip net.IP) bool {
   179  		return (ip.To4() == nil)
   180  	},
   181  	ipsetParams: &ipsetpackage.Params{HashFamily: "inet6"},
   182  
   183  	acl: aclHandler{
   184  		serviceIDtoACLIPset:   map[string]*ipsetInfo{},
   185  		contextIDtoServiceIDs: map[string]map[string]bool{},
   186  	},
   187  	tn:             targetNetwork{tcp: []string{}, udp: []string{}},
   188  	en:             excludedNetwork{excluded: []string{}},
   189  	dynamicUpdates: map[string][]string{},
   190  }
   191  
   192  //V4 returns the ipv4 instance of ipsetmanager
   193  func V4() IPSetManager {
   194  	return ipv4Handler
   195  }
   196  
   197  //V6 returns the ipv6 instance of ipsetmanager
   198  func V6() IPSetManager {
   199  	return ipv6Handler
   200  }
   201  
   202  func (ipHandler *handler) DestroyAllIPsets() error {
   203  
   204  	if err := destroyAll(ipHandler.ipsetPrefix); err != nil {
   205  		return err
   206  	}
   207  
   208  	return nil
   209  }
   210  
   211  func (ipHandler *handler) Reset() {
   212  	ipHandler.Lock()
   213  
   214  	ipHandler.acl = aclHandler{
   215  		serviceIDtoACLIPset:   map[string]*ipsetInfo{},
   216  		contextIDtoServiceIDs: map[string]map[string]bool{},
   217  	}
   218  
   219  	ipHandler.tn = targetNetwork{tcp: []string{}, udp: []string{}}
   220  	ipHandler.en = excludedNetwork{excluded: []string{}}
   221  
   222  	ipHandler.Unlock()
   223  }
   224  
   225  func (ipHandler *handler) CreateIPsetsForTargetAndExcludedNetworks() error {
   226  
   227  	targetTCPName := ipHandler.ipsetPrefix + targetTCPSuffix
   228  	targetUDPName := ipHandler.ipsetPrefix + targetUDPSuffix
   229  	excludedName := ipHandler.ipsetPrefix + excludedSuffix
   230  
   231  	existingSets, err := listIPSets()
   232  	if err != nil {
   233  		return fmt.Errorf("unable to read current sets: %s", err)
   234  	}
   235  
   236  	setIndex := map[string]struct{}{}
   237  	for _, s := range existingSets {
   238  		setIndex[s] = struct{}{}
   239  	}
   240  
   241  	createIPSet := func(name string) error {
   242  		var ipset Ipset
   243  		var err error
   244  
   245  		if _, ok := setIndex[name]; !ok {
   246  			ipset, err = newIpset(name, "hash:net", ipHandler.ipsetParams)
   247  			if err != nil {
   248  				return err
   249  			}
   250  		} else {
   251  			ipset = getIpset(name)
   252  		}
   253  
   254  		if err = ipset.Flush(); err != nil {
   255  			return err
   256  		}
   257  
   258  		return nil
   259  	}
   260  
   261  	if err := createIPSet(targetTCPName); err != nil {
   262  		return err
   263  	}
   264  
   265  	if err := createIPSet(targetUDPName); err != nil {
   266  		return err
   267  	}
   268  
   269  	if err := createIPSet(excludedName); err != nil {
   270  		return err
   271  	}
   272  
   273  	return nil
   274  }
   275  
   276  func updateIPSets(ipset Ipset, old []string, new []string) error {
   277  	// We need to delete first, because of nomatch.
   278  	// For example, if old has 1.2.3.4 and new has !1.2.3.4, then we delete the 1.2.3.4 first
   279  	// before we can add the 1.2.3.4 with the nomatch option.
   280  
   281  	deleteMap := map[string]bool{}
   282  	addMap := map[string]bool{}
   283  	for _, net := range old {
   284  		deleteMap[net] = true
   285  	}
   286  	for _, net := range new {
   287  		if _, ok := deleteMap[net]; ok {
   288  			deleteMap[net] = false
   289  			continue
   290  		}
   291  		addMap[net] = true
   292  	}
   293  
   294  	for net, delete := range deleteMap {
   295  		if delete {
   296  			if err := delFromIPset(ipset, net); err != nil {
   297  				zap.L().Debug("unable to remove network from set", zap.Error(err))
   298  			}
   299  		}
   300  	}
   301  
   302  	for net, add := range addMap {
   303  		if add {
   304  			if err := addToIPset(ipset, net); err != nil {
   305  				return fmt.Errorf("unable to update target set: %s", err)
   306  			}
   307  		}
   308  	}
   309  
   310  	return nil
   311  }
   312  
   313  func (ipHandler *handler) UpdateIPsetsForTargetAndExcludedNetworks(tcp []string, udp []string, excluded []string) error {
   314  
   315  	filterIPs := func(ips []string) []string {
   316  		var filteredIPs []string
   317  
   318  		for _, ip := range ips {
   319  			parsable := ip
   320  			if strings.HasPrefix(ip, "!") {
   321  				parsable = ip[1:]
   322  			}
   323  			netIP := net.ParseIP(parsable)
   324  			if netIP == nil {
   325  				netIP, _, _ = net.ParseCIDR(parsable)
   326  			}
   327  
   328  			if ipHandler.ipFilter(netIP) {
   329  				filteredIPs = append(filteredIPs, ip)
   330  			}
   331  		}
   332  
   333  		return filteredIPs
   334  	}
   335  
   336  	tcpSet := getIpset(ipHandler.ipsetPrefix + targetTCPSuffix)
   337  	udpSet := getIpset(ipHandler.ipsetPrefix + targetUDPSuffix)
   338  	excludedSet := getIpset(ipHandler.ipsetPrefix + excludedSuffix)
   339  
   340  	tcpFilterIPs := filterIPs(tcp)
   341  	if err := updateIPSets(tcpSet, ipHandler.tn.tcp, tcpFilterIPs); err != nil {
   342  		return err
   343  	}
   344  
   345  	udpFilterIPs := filterIPs(udp)
   346  	if err := updateIPSets(udpSet, ipHandler.tn.udp, udpFilterIPs); err != nil {
   347  		return err
   348  	}
   349  
   350  	excludedFilterIPs := filterIPs(excluded)
   351  	if err := updateIPSets(excludedSet, ipHandler.en.excluded, excludedFilterIPs); err != nil {
   352  		return err
   353  	}
   354  
   355  	ipHandler.tn.tcp = tcpFilterIPs
   356  	ipHandler.tn.udp = udpFilterIPs
   357  	ipHandler.en.excluded = excludedFilterIPs
   358  
   359  	return nil
   360  }
   361  
   362  func (ipHandler *handler) GetIPsetNamesForTargetAndExcludedNetworks() (string, string, string) {
   363  	return ipHandler.ipsetPrefix + targetTCPSuffix, ipHandler.ipsetPrefix + targetUDPSuffix, ipHandler.ipsetPrefix + excludedSuffix
   364  }
   365  
   366  func (ipHandler *handler) getServerPortSetName(contextID string) string {
   367  
   368  	prefix := ipHandler.ipsetPrefix + processPortSetPrefix
   369  
   370  	return createName(contextID, prefix)
   371  }
   372  
   373  func (ipHandler *handler) getProxyIPSetNames(contextID string) (string, string) {
   374  	prefix := ipHandler.ipsetPrefix + proxyPortSetPrefix
   375  	name := createName(contextID, prefix)
   376  
   377  	return name + "-dst", name + "-srv"
   378  }
   379  
   380  func (ipHandler *handler) GetProxySetNames(contextID string) (string, string) {
   381  	return ipHandler.getProxyIPSetNames(contextID)
   382  }
   383  
   384  func (ipHandler *handler) DestroyProxySets(contextID string) {
   385  	destSetName, srvSetName := ipHandler.getProxyIPSetNames(contextID)
   386  
   387  	ips := getIpset(destSetName)
   388  	if err := ips.Destroy(); err != nil {
   389  		zap.L().Warn("Failed to destroy proxyPortSet", zap.String("SetName", destSetName), zap.Error(err))
   390  	}
   391  
   392  	ips = getIpset(srvSetName)
   393  	if err := ips.Destroy(); err != nil {
   394  		zap.L().Warn("Failed to clear proxy port set", zap.String("set name", srvSetName), zap.Error(err))
   395  	}
   396  }
   397  
   398  //CreateProxySets creates the ipsets for L4/L7 services
   399  func (ipHandler *handler) CreateProxySets(contextID string) error {
   400  
   401  	destSetName, srvSetName := ipHandler.getProxyIPSetNames(contextID)
   402  
   403  	if _, err := newIpset(destSetName, "hash:net,port", ipHandler.ipsetParams); err != nil {
   404  		return fmt.Errorf("unable to create ipset for %s: %s", destSetName, err)
   405  	}
   406  
   407  	// create ipset for port match
   408  	if _, err := newIpset(srvSetName, proxySetPortIpsetType, nil); err != nil {
   409  		return fmt.Errorf("unable to create ipset for %s: %s", srvSetName, err)
   410  	}
   411  
   412  	return nil
   413  }
   414  
   415  func (ipHandler *handler) FlushProxySets(contextID string) {
   416  	destSetName, srvSetName := ipHandler.getProxyIPSetNames(contextID)
   417  
   418  	ips := getIpset(destSetName)
   419  	if err := ips.Flush(); err != nil {
   420  		zap.L().Warn("Failed to flush dest proxy port set", zap.String("SetName", destSetName), zap.Error(err))
   421  	}
   422  
   423  	ips = getIpset(srvSetName)
   424  	if err := ips.Flush(); err != nil {
   425  		zap.L().Warn("Failed to flush server proxy port set", zap.String("set name", srvSetName), zap.Error(err))
   426  	}
   427  }
   428  
   429  func (ipHandler *handler) AddIPPortToDependentService(contextID string, addr *net.IPNet, port string) error {
   430  
   431  	destSetName, _ := ipHandler.getProxyIPSetNames(contextID)
   432  	ips := getIpset(destSetName)
   433  
   434  	if ipHandler.ipFilter(addr.IP) {
   435  		pair := addr.String() + "," + port
   436  		if err := ips.Add(pair, 0); err != nil {
   437  			return fmt.Errorf("unable to add dependent ip %s to ipset: %s", pair, err)
   438  		}
   439  	}
   440  
   441  	return nil
   442  }
   443  
   444  func (ipHandler *handler) AddPortToExposedService(contextID string, port string) error {
   445  	_, srvSetName := ipHandler.getProxyIPSetNames(contextID)
   446  	ips := getIpset(srvSetName)
   447  
   448  	if err := ips.Add(port, 0); err != nil {
   449  		return fmt.Errorf("unable to add port %s to exposed service %s", port, err)
   450  	}
   451  
   452  	return nil
   453  }
   454  
   455  func (ipHandler *handler) GetServerPortSetName(contextID string) string {
   456  	return ipHandler.getServerPortSetName(contextID)
   457  }
   458  
   459  func (ipHandler *handler) CreateServerPortSet(contextID string) error {
   460  
   461  	if _, err := newIpset(ipHandler.getServerPortSetName(contextID), portSetIpsetType, nil); err != nil {
   462  		return err
   463  	}
   464  
   465  	return nil
   466  }
   467  
   468  func (ipHandler *handler) DestroyServerPortSet(contextID string) error {
   469  
   470  	portSetName := ipHandler.getServerPortSetName(contextID)
   471  	ips := getIpset(portSetName)
   472  
   473  	if err := ips.Destroy(); err != nil {
   474  		return fmt.Errorf("Failed to delete pu port set "+portSetName, zap.Error(err))
   475  	}
   476  
   477  	return nil
   478  }
   479  
   480  func (ipHandler *handler) AddPortToServerPortSet(contextID string, port string) error {
   481  
   482  	ips := getIpset(ipHandler.getServerPortSetName(contextID))
   483  
   484  	if err := ips.Add(port, 0); err != nil {
   485  		return fmt.Errorf("unable to add port to portset: %s", err)
   486  	}
   487  
   488  	return nil
   489  }
   490  
   491  func (ipHandler *handler) DeletePortFromServerPortSet(contextID string, port string) error {
   492  
   493  	ips := getIpset(ipHandler.getServerPortSetName(contextID))
   494  
   495  	if err := ips.Del(port); err != nil {
   496  		return fmt.Errorf("unable to delete port from portset: %s", err)
   497  	}
   498  
   499  	return nil
   500  }
   501  
   502  // RegisterExternalNets registers the contextID and the corresponding serviceIDs
   503  func (ipHandler *handler) RegisterExternalNets(contextID string, extnets policy.IPRuleList) error {
   504  	ipHandler.Lock()
   505  	defer ipHandler.Unlock()
   506  
   507  	processExtnets := func() error {
   508  		for _, extnet := range extnets {
   509  			var ipset *ipsetInfo
   510  
   511  			serviceID := extnet.Policy.ServiceID
   512  			if ipset = ipHandler.acl.serviceIDtoACLIPset[serviceID]; ipset == nil {
   513  				var err error
   514  				if ipset, err = ipHandler.createACLIPset(serviceID); err != nil {
   515  					return err
   516  				}
   517  			}
   518  
   519  			// make sure to include updates that were added dynamically by the DNS proxy
   520  			addrs := extnet.Addresses
   521  			if dynamicAddrs, ok := ipHandler.dynamicUpdates[serviceID]; ok {
   522  				addrs = append(addrs, dynamicAddrs...)
   523  			}
   524  
   525  			ipHandler.synchronizeIPsinIpset(ipset, addrs)
   526  			// have a backreference from serviceID to contextID
   527  			ipset.contextIDs[contextID] = true
   528  		}
   529  
   530  		return nil
   531  	}
   532  
   533  	processOlderExtnets := func() {
   534  		newExtnets := map[string]bool{}
   535  
   536  		for _, extnet := range extnets {
   537  
   538  			serviceID := extnet.Policy.ServiceID
   539  			newExtnets[serviceID] = true
   540  			m, ok := ipHandler.acl.contextIDtoServiceIDs[contextID]
   541  
   542  			if ok && m[serviceID] {
   543  				delete(m, serviceID)
   544  			}
   545  		}
   546  
   547  		for serviceID := range ipHandler.acl.contextIDtoServiceIDs[contextID] {
   548  			ipHandler.reduceReferenceFromServiceID(contextID, serviceID)
   549  		}
   550  
   551  		ipHandler.acl.contextIDtoServiceIDs[contextID] = newExtnets
   552  	}
   553  
   554  	if err := processExtnets(); err != nil {
   555  		return err
   556  	}
   557  
   558  	processOlderExtnets()
   559  
   560  	return nil
   561  }
   562  
   563  // deleteDynamicAddresses must only be alled by DeleteEntryFromIPset to update the internal map of dyanamic addresses
   564  func (ipHandler *handler) deleteDynamicAddresses(ips []string, serviceID string) {
   565  	if dynAddrs, ok := ipHandler.dynamicUpdates[serviceID]; ok {
   566  		ipMap := make(map[string]struct{}, len(ips))
   567  		for _, ip := range ips {
   568  			ipMap[ip] = struct{}{}
   569  		}
   570  
   571  		newAddrs := make([]string, 0, len(dynAddrs))
   572  		for _, dynAddr := range dynAddrs {
   573  			if _, ok := ipMap[dynAddr]; ok {
   574  				continue
   575  			}
   576  			newAddrs = append(newAddrs, dynAddr)
   577  		}
   578  
   579  		ipHandler.dynamicUpdates[serviceID] = newAddrs
   580  	}
   581  }
   582  
   583  // DeleteEntryFromIPset delete an entry from an ipset
   584  func (ipHandler *handler) DeleteEntryFromIPset(ips []string, serviceID string) {
   585  	ipHandler.Lock()
   586  	defer ipHandler.Unlock()
   587  
   588  	ipHandler.deleteDynamicAddresses(ips, serviceID)
   589  
   590  	for _, address := range ips {
   591  		parsableAddress := address
   592  		if strings.HasPrefix(address, "!") {
   593  			parsableAddress = address[1:]
   594  		}
   595  
   596  		netIP := net.ParseIP(parsableAddress)
   597  		if netIP == nil {
   598  			netIP, _, _ = net.ParseCIDR(parsableAddress)
   599  		}
   600  		if ipset := ipHandler.acl.serviceIDtoACLIPset[serviceID]; ipset != nil {
   601  			ipsetHandler := getIpset(ipset.name)
   602  			delFromIPset(ipsetHandler, netIP.String()) // nolint
   603  			delete(ipset.addresses, address)
   604  
   605  		}
   606  
   607  	}
   608  }
   609  
   610  // updateDynamicAddresses must only be called by UpdateACLIPsets to update the internal map of dynamic addresses
   611  func (ipHandler *handler) updateDynamicAddresses(addresses []string, serviceID string) {
   612  	// no need to lock, already done by the caller
   613  	if dynAddrs, ok := ipHandler.dynamicUpdates[serviceID]; ok {
   614  		ipMap := make(map[string]struct{}, len(dynAddrs))
   615  		for _, ip := range dynAddrs {
   616  			ipMap[ip] = struct{}{}
   617  		}
   618  
   619  		newAddrs := make([]string, 0, len(addresses))
   620  		for _, ip := range addresses {
   621  			if _, ok := ipMap[ip]; ok {
   622  				continue
   623  			}
   624  			newAddrs = append(newAddrs, ip)
   625  		}
   626  
   627  		ipHandler.dynamicUpdates[serviceID] = append(dynAddrs, newAddrs...)
   628  	} else {
   629  		ipHandler.dynamicUpdates[serviceID] = addresses
   630  	}
   631  }
   632  
   633  //UpdateACLIPsets updates the ip addresses in the ipsets corresponding to the serviceID
   634  func (ipHandler *handler) UpdateACLIPsets(addresses []string, serviceID string) {
   635  	ipHandler.Lock()
   636  	defer ipHandler.Unlock()
   637  
   638  	ipHandler.updateDynamicAddresses(addresses, serviceID)
   639  
   640  	for _, address := range addresses {
   641  		parsableAddress := address
   642  		if strings.HasPrefix(address, "!") {
   643  			parsableAddress = address[1:]
   644  		}
   645  
   646  		netIP := net.ParseIP(parsableAddress)
   647  		if netIP == nil {
   648  			netIP, _, _ = net.ParseCIDR(parsableAddress)
   649  		}
   650  
   651  		if !ipHandler.ipFilter(netIP) {
   652  			continue
   653  		}
   654  
   655  		if ipset := ipHandler.acl.serviceIDtoACLIPset[serviceID]; ipset != nil {
   656  			ipsetHandler := getIpset(ipset.name)
   657  			if err := addToIPset(ipsetHandler, address); err != nil {
   658  				zap.L().Error("Error adding IPs to ipset", zap.String("ipset", ipset.name), zap.String("address", address))
   659  			}
   660  
   661  			ipset.addresses[address] = true
   662  		}
   663  	}
   664  }
   665  
   666  func hashServiceID(serviceID string) string {
   667  	hash := murmur3.New64()
   668  	if _, err := io.WriteString(hash, serviceID); err != nil {
   669  		return ""
   670  	}
   671  
   672  	return base64.URLEncoding.EncodeToString(hash.Sum(nil))
   673  }
   674  
   675  func (ipHandler *handler) synchronizeIPsinIpset(ipsetInfo *ipsetInfo, addresses []string) {
   676  	newips := map[string]bool{}
   677  	ipsetHandler := getIpset(ipsetInfo.name)
   678  
   679  	var addrToAdd, addrToDelete []string
   680  
   681  	for _, address := range addresses {
   682  		parsableAddress := address
   683  		if strings.HasPrefix(address, "!") {
   684  			parsableAddress = address[1:]
   685  		}
   686  
   687  		netIP := net.ParseIP(parsableAddress)
   688  		if netIP == nil {
   689  			netIP, _, _ = net.ParseCIDR(parsableAddress)
   690  		}
   691  
   692  		if !ipHandler.ipFilter(netIP) {
   693  			continue
   694  		}
   695  
   696  		newips[address] = true
   697  
   698  		if _, ok := ipsetInfo.addresses[address]; !ok {
   699  			addrToAdd = append(addrToAdd, address)
   700  		}
   701  		delete(ipsetInfo.addresses, address)
   702  	}
   703  
   704  	for address, val := range ipsetInfo.addresses {
   705  		if val {
   706  			addrToDelete = append(addrToDelete, address)
   707  		}
   708  	}
   709  
   710  	if err := updateIPSets(ipsetHandler, addrToDelete, addrToAdd); err != nil {
   711  		zap.L().Error("Error updating ipset during sync", zap.Error(err))
   712  	}
   713  
   714  	ipsetInfo.addresses = newips
   715  }
   716  
   717  func (ipHandler *handler) createACLIPset(serviceID string) (*ipsetInfo, error) {
   718  	ipsetName := ipHandler.ipsetPrefix + "ext-" + hashServiceID(serviceID)
   719  	if _, err := newIpset(ipsetName, "hash:net", ipHandler.ipsetParams); err != nil {
   720  		return nil, err
   721  	}
   722  
   723  	ipset := &ipsetInfo{contextIDs: map[string]bool{}, name: ipsetName, addresses: map[string]bool{}}
   724  	ipHandler.acl.serviceIDtoACLIPset[serviceID] = ipset
   725  
   726  	return ipset, nil
   727  }
   728  
   729  func (ipHandler *handler) deleteServiceID(serviceID string) {
   730  	ipsetInfo := ipHandler.acl.serviceIDtoACLIPset[serviceID]
   731  	ipHandler.acl.toDestroy = append(ipHandler.acl.toDestroy, ipsetInfo.name)
   732  	delete(ipHandler.acl.serviceIDtoACLIPset, serviceID)
   733  }
   734  
   735  //reduceReferenceFromServiceID reduces the reference for the serviceID.
   736  func (ipHandler *handler) reduceReferenceFromServiceID(contextID string, serviceID string) {
   737  	var ipset *ipsetInfo
   738  
   739  	if ipset = ipHandler.acl.serviceIDtoACLIPset[serviceID]; ipset == nil {
   740  		zap.L().Error("Could not find ipset corresponding to serviceID", zap.String("serviceID", serviceID))
   741  		return
   742  	}
   743  
   744  	delete(ipset.contextIDs, contextID)
   745  
   746  	// there are no references from any pu. safe to destroy now
   747  	if len(ipset.contextIDs) == 0 {
   748  		ipHandler.deleteServiceID(serviceID)
   749  	}
   750  }
   751  
   752  // DestroyUnusedIPsets destroys the unused ipsets.
   753  func (ipHandler *handler) DestroyUnusedIPsets() {
   754  	ipHandler.Lock()
   755  	defer ipHandler.Unlock()
   756  
   757  	for _, ipsetName := range ipHandler.acl.toDestroy {
   758  		ipsetHandler := getIpset(ipsetName)
   759  		if err := ipsetHandler.Destroy(); err != nil {
   760  			zap.L().Warn("Failed to destroy ipset", zap.String("ipset", ipsetName), zap.Error(err))
   761  		}
   762  	}
   763  
   764  	ipHandler.acl.toDestroy = nil
   765  }
   766  
   767  // RemoveExternalNets is called when the contextID is being unsupervised such that all the external nets can be deleted.
   768  func (ipHandler *handler) RemoveExternalNets(contextID string) {
   769  	ipHandler.Lock()
   770  
   771  	m, ok := ipHandler.acl.contextIDtoServiceIDs[contextID]
   772  	if ok {
   773  		for serviceID := range m {
   774  			ipHandler.reduceReferenceFromServiceID(contextID, serviceID)
   775  		}
   776  	}
   777  
   778  	delete(ipHandler.acl.contextIDtoServiceIDs, contextID)
   779  
   780  	ipHandler.Unlock()
   781  	ipHandler.DestroyUnusedIPsets()
   782  }
   783  
   784  func (ipHandler *handler) GetIPsetPrefix() string {
   785  	return ipHandler.ipsetPrefix
   786  }
   787  
   788  // GetACLIPsets returns the ipset names corresponding to the serviceIDs.
   789  func (ipHandler *handler) GetACLIPsetsNames(extnets policy.IPRuleList) []string {
   790  
   791  	ipHandler.Lock()
   792  	defer ipHandler.Unlock()
   793  
   794  	var ipsets []string
   795  
   796  	for _, extnet := range extnets {
   797  		serviceID := extnet.Policy.ServiceID
   798  
   799  		ipsetInfo, ok := ipHandler.acl.serviceIDtoACLIPset[serviceID]
   800  		if ok {
   801  			ipsets = append(ipsets, ipsetInfo.name)
   802  		}
   803  	}
   804  
   805  	return ipsets
   806  }
   807  
   808  //createName takes the contextID and prefix and returns a name after processing
   809  func createName(contextID string, prefix string) string {
   810  	hash := murmur3.New64()
   811  
   812  	if _, err := io.WriteString(hash, contextID); err != nil {
   813  		return ""
   814  	}
   815  
   816  	output := base64.URLEncoding.EncodeToString(hash.Sum(nil))
   817  
   818  	if len(contextID) > 4 {
   819  		contextID = contextID[:4] + output[:4]
   820  	} else {
   821  		contextID = contextID + output[:4]
   822  	}
   823  
   824  	if len(prefix) > 16 {
   825  		prefix = prefix[:16]
   826  	}
   827  
   828  	return (prefix + contextID)
   829  }
   830  
   831  //V4test returns the test handler for ipv4
   832  func V4test() IPSetManager {
   833  	return &handler{
   834  		ipsetPrefix: "TRI-" + ipv4String,
   835  		ipFilter: func(ip net.IP) bool {
   836  			return (ip.To4() != nil)
   837  		},
   838  		ipsetParams: &ipsetpackage.Params{},
   839  
   840  		acl: aclHandler{
   841  			serviceIDtoACLIPset:   map[string]*ipsetInfo{},
   842  			contextIDtoServiceIDs: map[string]map[string]bool{},
   843  		},
   844  		tn: targetNetwork{tcp: []string{}, udp: []string{}},
   845  		en: excludedNetwork{excluded: []string{}},
   846  	}
   847  }
   848  
   849  //V6test returns the test handler for ipv6
   850  func V6test() IPSetManager {
   851  	return &handler{
   852  		ipsetPrefix: "TRI-" + ipv6String,
   853  		ipFilter: func(ip net.IP) bool {
   854  			return (ip.To4() == nil)
   855  		},
   856  		ipsetParams: &ipsetpackage.Params{HashFamily: "inet6"},
   857  
   858  		acl: aclHandler{
   859  			serviceIDtoACLIPset:   map[string]*ipsetInfo{},
   860  			contextIDtoServiceIDs: map[string]map[string]bool{},
   861  		},
   862  		tn: targetNetwork{tcp: []string{}, udp: []string{}},
   863  		en: excludedNetwork{excluded: []string{}},
   864  	}
   865  }