github.com/sagernet/wireguard-go@v0.0.0-20231215174105-89dec3b2f3e8/ipc/uapi_windows.go (about)

     1  /* SPDX-License-Identifier: MIT
     2   *
     3   * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
     4   */
     5  
     6  package ipc
     7  
     8  import (
     9  	"net"
    10  
    11  	"github.com/sagernet/wireguard-go/ipc/namedpipe"
    12  	"golang.org/x/sys/windows"
    13  )
    14  
    15  // TODO: replace these with actual standard windows error numbers from the win package
    16  const (
    17  	IpcErrorIO        = -int64(5)
    18  	IpcErrorProtocol  = -int64(71)
    19  	IpcErrorInvalid   = -int64(22)
    20  	IpcErrorPortInUse = -int64(98)
    21  	IpcErrorUnknown   = -int64(55)
    22  )
    23  
    24  type UAPIListener struct {
    25  	listener net.Listener // unix socket listener
    26  	connNew  chan net.Conn
    27  	connErr  chan error
    28  	kqueueFd int
    29  	keventFd int
    30  }
    31  
    32  func (l *UAPIListener) Accept() (net.Conn, error) {
    33  	for {
    34  		select {
    35  		case conn := <-l.connNew:
    36  			return conn, nil
    37  
    38  		case err := <-l.connErr:
    39  			return nil, err
    40  		}
    41  	}
    42  }
    43  
    44  func (l *UAPIListener) Close() error {
    45  	return l.listener.Close()
    46  }
    47  
    48  func (l *UAPIListener) Addr() net.Addr {
    49  	return l.listener.Addr()
    50  }
    51  
    52  var UAPISecurityDescriptor *windows.SECURITY_DESCRIPTOR
    53  
    54  func init() {
    55  	var err error
    56  	UAPISecurityDescriptor, err = windows.SecurityDescriptorFromString("O:SYD:P(A;;GA;;;SY)(A;;GA;;;BA)S:(ML;;NWNRNX;;;HI)")
    57  	if err != nil {
    58  		panic(err)
    59  	}
    60  }
    61  
    62  func UAPIListen(name string) (net.Listener, error) {
    63  	listener, err := (&namedpipe.ListenConfig{
    64  		SecurityDescriptor: UAPISecurityDescriptor,
    65  	}).Listen(`\\.\pipe\ProtectedPrefix\Administrators\WireGuard\` + name)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	uapi := &UAPIListener{
    71  		listener: listener,
    72  		connNew:  make(chan net.Conn, 1),
    73  		connErr:  make(chan error, 1),
    74  	}
    75  
    76  	go func(l *UAPIListener) {
    77  		for {
    78  			conn, err := l.listener.Accept()
    79  			if err != nil {
    80  				l.connErr <- err
    81  				break
    82  			}
    83  			l.connNew <- conn
    84  		}
    85  	}(uapi)
    86  
    87  	return uapi, nil
    88  }