github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/utils/frontman/wrapper_windows.go (about)

     1  // +build windows
     2  
     3  package frontman
     4  
     5  import (
     6  	"fmt"
     7  	"strings"
     8  	"syscall"
     9  	"unsafe"
    10  
    11  	"go.uber.org/zap"
    12  	"golang.org/x/sys/windows"
    13  )
    14  
    15  // WrapDriver represents convenience wrapper methods for calling our Windows Frontman DLL
    16  type WrapDriver interface {
    17  	GetDestInfo(socket uintptr, destInfo *DestInfo) error
    18  	ApplyDestHandle(socket, destHandle uintptr) error
    19  	FreeDestHandle(destHandle uintptr) error
    20  	NewIpset(name, ipsetType string) (uintptr, error)
    21  	GetIpset(name string) (uintptr, error)
    22  	DestroyAllIpsets(prefix string) error
    23  	ListIpsets() ([]string, error)
    24  	ListIpsetsDetail(format int) (string, error)
    25  	IpsetAdd(ipsetHandle uintptr, entry string, timeout int) error
    26  	IpsetAddOption(ipsetHandle uintptr, entry, option string, timeout int) error
    27  	IpsetDelete(ipsetHandle uintptr, entry string) error
    28  	IpsetDestroy(ipsetHandle uintptr, name string) error
    29  	IpsetFlush(ipsetHandle uintptr) error
    30  	IpsetTest(ipsetHandle uintptr, entry string) (bool, error)
    31  	PacketFilterStart(firewallName string, receiveCallback, loggingCallback func(uintptr, uintptr) uintptr) error
    32  	PacketFilterClose() error
    33  	PacketFilterForward(info *PacketInfo, packetBytes []byte) error
    34  	AppendFilter(outbound bool, filterName string, isGotoFilter bool) error
    35  	InsertFilter(outbound bool, priority int, filterName string, isGotoFilter bool) error
    36  	DestroyFilter(filterName string) error
    37  	EmptyFilter(filterName string) error
    38  	GetFilterList(outbound bool) ([]string, error)
    39  	AppendFilterCriteria(filterName, criteriaName string, ruleSpec *RuleSpec, ipsetRuleSpecs []IpsetRuleSpec) error
    40  	DeleteFilterCriteria(filterName, criteriaName string) error
    41  	GetCriteriaList(format int) (string, error)
    42  }
    43  
    44  type wrapper struct {
    45  	driverHandle uintptr
    46  	ruleCleaner  ruleCleanup
    47  }
    48  
    49  // Wrapper is the driver/dll wrapper implementation
    50  var Wrapper = WrapDriver(&wrapper{
    51  	driverHandle: uintptr(syscall.InvalidHandle),
    52  	ruleCleaner:  newRuleCleanup(),
    53  })
    54  
    55  func (w *wrapper) initDriverHandle() {
    56  	if w.driverHandle == 0 || syscall.Handle(w.driverHandle) == syscall.InvalidHandle {
    57  		ret, err := Driver.FrontmanOpenShared()
    58  		if err != nil {
    59  			zap.L().Fatal("Unable to initialize Frontman driver. Check Windows Event Viewer System logs for errors, and ensure that no other instances are currently running.", zap.Error(err))
    60  		}
    61  		w.driverHandle = ret
    62  	}
    63  }
    64  
    65  func (w *wrapper) GetDestInfo(socket uintptr, destInfo *DestInfo) error {
    66  	w.initDriverHandle()
    67  	if ret, err := Driver.GetDestInfo(w.driverHandle, socket, uintptr(unsafe.Pointer(destInfo))); ret == 0 {
    68  		return fmt.Errorf("GetDestInfo failed: %v", err)
    69  	}
    70  	return nil
    71  }
    72  
    73  func (w *wrapper) ApplyDestHandle(socket, destHandle uintptr) error {
    74  	w.initDriverHandle()
    75  	if ret, err := Driver.ApplyDestHandle(socket, destHandle); ret == 0 {
    76  		return fmt.Errorf("ApplyDestHandle failed: %v", err)
    77  	}
    78  	return nil
    79  }
    80  
    81  func (w *wrapper) FreeDestHandle(destHandle uintptr) error {
    82  	w.initDriverHandle()
    83  	if ret, err := Driver.FreeDestHandle(destHandle); ret == 0 {
    84  		return fmt.Errorf("FreeDestHandle failed: %v", err)
    85  	}
    86  	return nil
    87  }
    88  
    89  func (w *wrapper) NewIpset(name, ipsetType string) (uintptr, error) {
    90  	w.initDriverHandle()
    91  	var ipsetHandle uintptr
    92  	if ret, err := Driver.NewIpset(w.driverHandle, marshalString(name), marshalString(ipsetType), uintptr(unsafe.Pointer(&ipsetHandle))); ret == 0 {
    93  		return 0, fmt.Errorf("NewIpset failed: %v", err)
    94  	}
    95  	return ipsetHandle, nil
    96  }
    97  
    98  func (w *wrapper) GetIpset(name string) (uintptr, error) {
    99  	w.initDriverHandle()
   100  	var ipsetHandle uintptr
   101  	if ret, err := Driver.GetIpset(w.driverHandle, marshalString(name), uintptr(unsafe.Pointer(&ipsetHandle))); ret == 0 {
   102  		return 0, fmt.Errorf("GetIpset failed: %v", err)
   103  	}
   104  	return ipsetHandle, nil
   105  }
   106  
   107  func (w *wrapper) DestroyAllIpsets(prefix string) error {
   108  	w.initDriverHandle()
   109  	// order important: we must call cleaner routine before telling driver to delete the ipsets
   110  	errCleaner := w.ruleCleaner.deleteRuleForIpsetByPrefix(w, prefix)
   111  	if ret, err := Driver.DestroyAllIpsets(w.driverHandle, marshalString(prefix)); ret == 0 {
   112  		return fmt.Errorf("DestroyAllIpsets failed: %v", err)
   113  	}
   114  	return errCleaner
   115  }
   116  
   117  func (w *wrapper) ListIpsets() ([]string, error) {
   118  	w.initDriverHandle()
   119  	// first query for needed buffer size
   120  	var bytesNeeded, ignore uint32
   121  	ret, err := Driver.ListIpsets(w.driverHandle, 0, 0, uintptr(unsafe.Pointer(&bytesNeeded)))
   122  	if ret != 0 && bytesNeeded == 0 {
   123  		return []string{}, nil
   124  	}
   125  	if err != windows.ERROR_INSUFFICIENT_BUFFER {
   126  		return nil, fmt.Errorf("ListIpsets failed: %v", err)
   127  	}
   128  	if bytesNeeded%2 != 0 {
   129  		return nil, fmt.Errorf("ListIpsets failed: odd result (%d)", bytesNeeded)
   130  	}
   131  	// then allocate buffer for wide string and call again
   132  	buf := make([]uint16, bytesNeeded/2)
   133  	ret, err = Driver.ListIpsets(w.driverHandle, uintptr(unsafe.Pointer(&buf[0])), uintptr(bytesNeeded), uintptr(unsafe.Pointer(&ignore)))
   134  	if ret == 0 {
   135  		return nil, fmt.Errorf("ListIpsets failed: %v", err)
   136  	}
   137  	str := syscall.UTF16ToString(buf)
   138  	return strings.Split(str, ","), nil
   139  }
   140  
   141  func (w *wrapper) ListIpsetsDetail(format int) (string, error) {
   142  	w.initDriverHandle()
   143  	// first query for needed buffer size
   144  	var bytesNeeded, ignore uint32
   145  	emptyStr := ""
   146  	ret, err := Driver.ListIpsetsDetail(w.driverHandle, uintptr(format), 0, 0, uintptr(unsafe.Pointer(&bytesNeeded)))
   147  	if ret != 0 && bytesNeeded == 0 {
   148  		return emptyStr, nil
   149  	}
   150  	if err != windows.ERROR_INSUFFICIENT_BUFFER {
   151  		return emptyStr, fmt.Errorf("ListIpsetsDetail failed: %v", err)
   152  	}
   153  	if bytesNeeded%2 != 0 {
   154  		return emptyStr, fmt.Errorf("ListIpsetsDetail failed: odd result (%d)", bytesNeeded)
   155  	}
   156  	// then allocate buffer for wide string and call again
   157  	buf := make([]uint16, bytesNeeded/2)
   158  	ret, err = Driver.ListIpsetsDetail(w.driverHandle, uintptr(format), uintptr(unsafe.Pointer(&buf[0])), uintptr(bytesNeeded), uintptr(unsafe.Pointer(&ignore)))
   159  	if ret == 0 {
   160  		return emptyStr, fmt.Errorf("ListIpsetsDetail failed: %v", err)
   161  	}
   162  	str := syscall.UTF16ToString(buf)
   163  	return str, nil
   164  }
   165  
   166  func (w *wrapper) IpsetAdd(ipsetHandle uintptr, entry string, timeout int) error {
   167  	w.initDriverHandle()
   168  	if ret, err := Driver.IpsetAdd(w.driverHandle, ipsetHandle, marshalString(entry), uintptr(timeout)); ret == 0 {
   169  		// no error if already exists
   170  		if err == windows.ERROR_ALREADY_EXISTS {
   171  			return nil
   172  		}
   173  		return fmt.Errorf("IpsetAdd failed: %v", err)
   174  	}
   175  	return nil
   176  }
   177  
   178  func (w *wrapper) IpsetAddOption(ipsetHandle uintptr, entry, option string, timeout int) error {
   179  	w.initDriverHandle()
   180  	if ret, err := Driver.IpsetAddOption(w.driverHandle, ipsetHandle, marshalString(entry), marshalString(option), uintptr(timeout)); ret == 0 {
   181  		// no error if already exists
   182  		if err == windows.ERROR_ALREADY_EXISTS {
   183  			return nil
   184  		}
   185  		return fmt.Errorf("IpsetAddOption failed: %v", err)
   186  	}
   187  	return nil
   188  }
   189  
   190  func (w *wrapper) IpsetDelete(ipsetHandle uintptr, entry string) error {
   191  	w.initDriverHandle()
   192  	if ret, err := Driver.IpsetDelete(w.driverHandle, ipsetHandle, marshalString(entry)); ret == 0 {
   193  		return fmt.Errorf("IpsetDelete failed: %v", err)
   194  	}
   195  	return nil
   196  }
   197  
   198  func (w *wrapper) IpsetDestroy(ipsetHandle uintptr, name string) error {
   199  	w.initDriverHandle()
   200  	errCleaner := w.ruleCleaner.deleteRulesForIpset(w, name)
   201  	if ret, err := Driver.IpsetDestroy(w.driverHandle, ipsetHandle); ret == 0 {
   202  		return fmt.Errorf("IpsetDestroy failed: %v", err)
   203  	}
   204  	return errCleaner
   205  }
   206  
   207  func (w *wrapper) IpsetFlush(ipsetHandle uintptr) error {
   208  	w.initDriverHandle()
   209  	if ret, err := Driver.IpsetFlush(w.driverHandle, ipsetHandle); ret == 0 {
   210  		return fmt.Errorf("IpsetFlush failed: %v", err)
   211  	}
   212  	return nil
   213  }
   214  
   215  func (w *wrapper) IpsetTest(ipsetHandle uintptr, entry string) (bool, error) {
   216  	w.initDriverHandle()
   217  	if ret, err := Driver.IpsetTest(w.driverHandle, ipsetHandle, marshalString(entry)); ret == 0 {
   218  		if err == nil {
   219  			return false, nil
   220  		}
   221  		return false, fmt.Errorf("IpsetTest failed: %v", err)
   222  	}
   223  	return true, nil
   224  }
   225  
   226  func (w *wrapper) PacketFilterStart(firewallName string, receiveCallback, loggingCallback func(uintptr, uintptr) uintptr) error {
   227  	w.initDriverHandle()
   228  	if ret, err := Driver.PacketFilterStart(w.driverHandle, marshalString(firewallName), syscall.NewCallbackCDecl(receiveCallback), syscall.NewCallbackCDecl(loggingCallback)); ret == 0 {
   229  		return fmt.Errorf("PacketFilterStart failed: %v", err)
   230  	}
   231  	return nil
   232  }
   233  
   234  func (w *wrapper) PacketFilterClose() error {
   235  	w.initDriverHandle()
   236  	if ret, err := Driver.PacketFilterClose(); ret == 0 {
   237  		return fmt.Errorf("PacketFilterClose failed: %v", err)
   238  	}
   239  	return nil
   240  }
   241  
   242  func (w *wrapper) PacketFilterForward(info *PacketInfo, packetBytes []byte) error {
   243  	w.initDriverHandle()
   244  	if ret, err := Driver.PacketFilterForward(uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(&packetBytes[0]))); ret == 0 {
   245  		return fmt.Errorf("PacketFilterForward failed: %v", err)
   246  	}
   247  	return nil
   248  }
   249  
   250  func (w *wrapper) AppendFilter(outbound bool, filterName string, isGotoFilter bool) error {
   251  	w.initDriverHandle()
   252  	if ret, err := Driver.AppendFilter(w.driverHandle, marshalBool(outbound), marshalString(filterName), marshalBool(isGotoFilter)); ret == 0 {
   253  		// no error if already exists
   254  		if err == windows.ERROR_ALREADY_EXISTS {
   255  			return nil
   256  		}
   257  		return fmt.Errorf("AppendFilter failed: %v", err)
   258  	}
   259  	return nil
   260  }
   261  
   262  func (w *wrapper) InsertFilter(outbound bool, priority int, filterName string, isGotoFilter bool) error {
   263  	w.initDriverHandle()
   264  	if ret, err := Driver.InsertFilter(w.driverHandle, marshalBool(outbound), uintptr(priority), marshalString(filterName), marshalBool(isGotoFilter)); ret == 0 {
   265  		return fmt.Errorf("InsertFilter failed: %v", err)
   266  	}
   267  	return nil
   268  }
   269  
   270  func (w *wrapper) DestroyFilter(filterName string) error {
   271  	w.initDriverHandle()
   272  	if ret, err := Driver.DestroyFilter(w.driverHandle, marshalString(filterName)); ret == 0 {
   273  		return fmt.Errorf("DestroyFilter failed: %v", err)
   274  	}
   275  	return nil
   276  }
   277  
   278  func (w *wrapper) EmptyFilter(filterName string) error {
   279  	w.initDriverHandle()
   280  	if ret, err := Driver.EmptyFilter(w.driverHandle, marshalString(filterName)); ret == 0 {
   281  		return fmt.Errorf("EmptyFilter failed: %v", err)
   282  	}
   283  	return nil
   284  }
   285  
   286  func (w *wrapper) GetFilterList(outbound bool) ([]string, error) {
   287  	w.initDriverHandle()
   288  	// first query for needed buffer size
   289  	var bytesNeeded, ignore uint32
   290  	ret, err := Driver.GetFilterList(w.driverHandle, marshalBool(outbound), 0, 0, uintptr(unsafe.Pointer(&bytesNeeded)))
   291  	if ret != 0 && bytesNeeded == 0 {
   292  		return []string{}, nil
   293  	}
   294  	if err != windows.ERROR_INSUFFICIENT_BUFFER {
   295  		return nil, fmt.Errorf("GetFilterList failed: %v", err)
   296  	}
   297  	if bytesNeeded%2 != 0 {
   298  		return nil, fmt.Errorf("GetFilterList failed: odd result (%d)", bytesNeeded)
   299  	}
   300  	// then allocate buffer for wide string and call again
   301  	buf := make([]uint16, bytesNeeded/2)
   302  
   303  	// Not sure how this happens, but sometimes on shutdown we get a panic because the len(buf) is zero
   304  	if len(buf) <= 0 {
   305  		return nil, fmt.Errorf("GetFilterList returned unexpected bytes needed value: %d", bytesNeeded)
   306  	}
   307  
   308  	ret, err = Driver.GetFilterList(w.driverHandle, marshalBool(outbound), uintptr(unsafe.Pointer(&buf[0])), uintptr(bytesNeeded), uintptr(unsafe.Pointer(&ignore)))
   309  	if ret == 0 {
   310  		return nil, fmt.Errorf("GetFilterList failed: %v", err)
   311  	}
   312  	str := syscall.UTF16ToString(buf)
   313  	return strings.Split(str, ","), nil
   314  }
   315  
   316  func (w *wrapper) AppendFilterCriteria(filterName, criteriaName string, ruleSpec *RuleSpec, ipsetRuleSpecs []IpsetRuleSpec) error {
   317  	w.initDriverHandle()
   318  	if len(ipsetRuleSpecs) > 0 {
   319  		if ret, err := Driver.AppendFilterCriteria(w.driverHandle,
   320  			marshalString(filterName),
   321  			marshalString(criteriaName),
   322  			uintptr(unsafe.Pointer(ruleSpec)),
   323  			uintptr(unsafe.Pointer(&ipsetRuleSpecs[0])),
   324  			uintptr(len(ipsetRuleSpecs))); ret == 0 {
   325  			return fmt.Errorf("AppendFilterCriteria failed: %v", err)
   326  		}
   327  		for _, ipsrs := range ipsetRuleSpecs {
   328  			if ipsrs.IpsetName != 0 {
   329  				ipsetName := WideCharPointerToString((*uint16)(unsafe.Pointer(ipsrs.IpsetName))) // nolint:govet
   330  				w.ruleCleaner.mapIpsetToRule(ipsetName, filterName, criteriaName)
   331  			}
   332  		}
   333  	} else {
   334  		if ret, err := Driver.AppendFilterCriteria(w.driverHandle,
   335  			marshalString(filterName),
   336  			marshalString(criteriaName),
   337  			uintptr(unsafe.Pointer(ruleSpec)), 0, 0); ret == 0 {
   338  			return fmt.Errorf("AppendFilterCriteria failed: %v", err)
   339  		}
   340  	}
   341  	return nil
   342  }
   343  
   344  func (w *wrapper) DeleteFilterCriteria(filterName, criteriaName string) error {
   345  	w.initDriverHandle()
   346  	w.ruleCleaner.deleteRuleFromIpsetMap(filterName, criteriaName)
   347  	if ret, err := Driver.DeleteFilterCriteria(w.driverHandle, marshalString(filterName), marshalString(criteriaName)); ret == 0 {
   348  		return fmt.Errorf("DeleteFilterCriteria failed - could not delete %s: %v", criteriaName, err)
   349  	}
   350  	return nil
   351  }
   352  
   353  func (w *wrapper) GetCriteriaList(format int) (string, error) {
   354  	w.initDriverHandle()
   355  	// first query for needed buffer size
   356  	var bytesNeeded, ignore uint32
   357  	emptyStr := ""
   358  	ret, err := Driver.GetCriteriaList(w.driverHandle, uintptr(format), 0, 0, uintptr(unsafe.Pointer(&bytesNeeded)))
   359  	if ret != 0 && bytesNeeded == 0 {
   360  		return emptyStr, nil
   361  	}
   362  	if err != windows.ERROR_INSUFFICIENT_BUFFER {
   363  		return emptyStr, fmt.Errorf("GetCriteriaList failed: %v", err)
   364  	}
   365  	if bytesNeeded%2 != 0 {
   366  		return emptyStr, fmt.Errorf("GetCriteriaList failed: odd result (%d)", bytesNeeded)
   367  	}
   368  	// then allocate buffer for wide string and call again
   369  	buf := make([]uint16, bytesNeeded/2)
   370  	ret, err = Driver.GetCriteriaList(w.driverHandle, uintptr(format), uintptr(unsafe.Pointer(&buf[0])), uintptr(bytesNeeded), uintptr(unsafe.Pointer(&ignore)))
   371  	if ret == 0 {
   372  		return emptyStr, fmt.Errorf("GetCriteriaList failed: %v", err)
   373  	}
   374  	str := syscall.UTF16ToString(buf)
   375  	return str, nil
   376  }
   377  
   378  func marshalString(str string) uintptr {
   379  	return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(str))) // nolint
   380  }
   381  
   382  func marshalBool(b bool) uintptr {
   383  	if b {
   384  		return 1
   385  	}
   386  	return 0
   387  }