diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2ef7198..0000000 --- a/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: go -go: - - "1.18" -go_import_path: github.com/net-byte/water -install: go get -u golang.org/x/lint/golint -script: make ci - -matrix: - include: - - os: linux - dist: xenial - - os: osx diff --git a/go.mod b/go.mod index aad645d..e944bd7 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,6 @@ require ( ) require ( - golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect + golang.org/x/net v0.0.0-20220725212005-46097bf591d3 // indirect golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect ) diff --git a/go.sum b/go.sum index 29c216f..8a98499 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220725212005-46097bf591d3 h1:2yWTtPWWRcISTw3/o+s/Y4UOMnQL71DWyToOANFusCg= +golang.org/x/net v0.0.0-20220725212005-46097bf591d3/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY= diff --git a/syscalls_windows.go b/syscalls_windows.go index 4ae5280..4ccc985 100644 --- a/syscalls_windows.go +++ b/syscalls_windows.go @@ -35,6 +35,16 @@ func openDev(config Config) (ifce *Interface, err error) { if err != nil { return nil, err } + nativeTunDevice := dev.(*tun.NativeTun) + link := winipcfg.LUID(nativeTunDevice.LUID()) + ip, err := netip.ParsePrefix(config.PlatformSpecificParams.Network) + if err != nil { + panic(err) + } + err = link.SetIPAddresses([]netip.Prefix{ip}) + if err != nil { + panic(err) + } wintun := &wintun{dev: dev} ifce = &Interface{isTAP: (config.DeviceType == TAP), ReadWriteCloser: wintun} return ifce, nil diff --git a/winipcfg/luid.go b/winipcfg/luid.go new file mode 100644 index 0000000..0c898b8 --- /dev/null +++ b/winipcfg/luid.go @@ -0,0 +1,387 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. + */ + +package winipcfg + +import ( + "errors" + "net/netip" + "strings" + + "golang.org/x/sys/windows" +) + +// LUID represents a network interface. +type LUID uint64 + +// IPInterface method retrieves IP information for the specified interface on the local computer. +func (luid LUID) IPInterface(family AddressFamily) (*MibIPInterfaceRow, error) { + row := &MibIPInterfaceRow{} + row.Init() + row.InterfaceLUID = luid + row.Family = family + err := row.get() + if err != nil { + return nil, err + } + return row, nil +} + +// Interface method retrieves information for the specified adapter on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getifentry2 +func (luid LUID) Interface() (*MibIfRow2, error) { + row := &MibIfRow2{} + row.InterfaceLUID = luid + err := row.get() + if err != nil { + return nil, err + } + return row, nil +} + +// GUID method converts a locally unique identifier (LUID) for a network interface to a globally unique identifier (GUID) for the interface. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-convertinterfaceluidtoguid +func (luid LUID) GUID() (*windows.GUID, error) { + guid := &windows.GUID{} + err := convertInterfaceLUIDToGUID(&luid, guid) + if err != nil { + return nil, err + } + return guid, nil +} + +// LUIDFromGUID function converts a globally unique identifier (GUID) for a network interface to the locally unique identifier (LUID) for the interface. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-convertinterfaceguidtoluid +func LUIDFromGUID(guid *windows.GUID) (LUID, error) { + var luid LUID + err := convertInterfaceGUIDToLUID(guid, &luid) + if err != nil { + return 0, err + } + return luid, nil +} + +// LUIDFromIndex function converts a local index for a network interface to the locally unique identifier (LUID) for the interface. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-convertinterfaceindextoluid +func LUIDFromIndex(index uint32) (LUID, error) { + var luid LUID + err := convertInterfaceIndexToLUID(index, &luid) + if err != nil { + return 0, err + } + return luid, nil +} + +// IPAddress method returns MibUnicastIPAddressRow struct that matches to provided 'ip' argument. Corresponds to GetUnicastIpAddressEntry +// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getunicastipaddressentry) +func (luid LUID) IPAddress(addr netip.Addr) (*MibUnicastIPAddressRow, error) { + row := &MibUnicastIPAddressRow{InterfaceLUID: luid} + + err := row.Address.SetAddr(addr) + if err != nil { + return nil, err + } + + err = row.get() + if err != nil { + return nil, err + } + + return row, nil +} + +// AddIPAddress method adds new unicast IP address to the interface. Corresponds to CreateUnicastIpAddressEntry function +// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry). +func (luid LUID) AddIPAddress(address netip.Prefix) error { + row := &MibUnicastIPAddressRow{} + row.Init() + row.InterfaceLUID = luid + row.DadState = DadStatePreferred + row.ValidLifetime = 0xffffffff + row.PreferredLifetime = 0xffffffff + err := row.Address.SetAddr(address.Addr()) + if err != nil { + return err + } + row.OnLinkPrefixLength = uint8(address.Bits()) + return row.Create() +} + +// AddIPAddresses method adds multiple new unicast IP addresses to the interface. Corresponds to CreateUnicastIpAddressEntry function +// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry). +func (luid LUID) AddIPAddresses(addresses []netip.Prefix) error { + for i := range addresses { + err := luid.AddIPAddress(addresses[i]) + if err != nil { + return err + } + } + return nil +} + +// SetIPAddresses method sets new unicast IP addresses to the interface. +func (luid LUID) SetIPAddresses(addresses []netip.Prefix) error { + err := luid.FlushIPAddresses(windows.AF_UNSPEC) + if err != nil { + return err + } + return luid.AddIPAddresses(addresses) +} + +// SetIPAddressesForFamily method sets new unicast IP addresses for a specific family to the interface. +func (luid LUID) SetIPAddressesForFamily(family AddressFamily, addresses []netip.Prefix) error { + err := luid.FlushIPAddresses(family) + if err != nil { + return err + } + for i := range addresses { + if !addresses[i].Addr().Is4() && family == windows.AF_INET { + continue + } else if !addresses[i].Addr().Is6() && family == windows.AF_INET6 { + continue + } + err := luid.AddIPAddress(addresses[i]) + if err != nil { + return err + } + } + return nil +} + +// DeleteIPAddress method deletes interface's unicast IP address. Corresponds to DeleteUnicastIpAddressEntry function +// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteunicastipaddressentry). +func (luid LUID) DeleteIPAddress(address netip.Prefix) error { + row := &MibUnicastIPAddressRow{} + row.Init() + row.InterfaceLUID = luid + err := row.Address.SetAddr(address.Addr()) + if err != nil { + return err + } + // Note: OnLinkPrefixLength member is ignored by DeleteUnicastIpAddressEntry(). + row.OnLinkPrefixLength = uint8(address.Bits()) + return row.Delete() +} + +// FlushIPAddresses method deletes all interface's unicast IP addresses. +func (luid LUID) FlushIPAddresses(family AddressFamily) error { + var tab *mibUnicastIPAddressTable + err := getUnicastIPAddressTable(family, &tab) + if err != nil { + return err + } + t := tab.get() + for i := range t { + if t[i].InterfaceLUID == luid { + t[i].Delete() + } + } + tab.free() + return nil +} + +// Route method returns route determined with the input arguments. Corresponds to GetIpForwardEntry2 function +// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipforwardentry2). +// NOTE: If the corresponding route isn't found, the method will return error. +func (luid LUID) Route(destination netip.Prefix, nextHop netip.Addr) (*MibIPforwardRow2, error) { + row := &MibIPforwardRow2{} + row.Init() + row.InterfaceLUID = luid + row.ValidLifetime = 0xffffffff + row.PreferredLifetime = 0xffffffff + err := row.DestinationPrefix.SetPrefix(destination) + if err != nil { + return nil, err + } + err = row.NextHop.SetAddr(nextHop) + if err != nil { + return nil, err + } + + err = row.get() + if err != nil { + return nil, err + } + return row, nil +} + +// AddRoute method adds a route to the interface. Corresponds to CreateIpForwardEntry2 function, with added splitDefault feature. +// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createipforwardentry2) +func (luid LUID) AddRoute(destination netip.Prefix, nextHop netip.Addr, metric uint32) error { + row := &MibIPforwardRow2{} + row.Init() + row.InterfaceLUID = luid + err := row.DestinationPrefix.SetPrefix(destination) + if err != nil { + return err + } + err = row.NextHop.SetAddr(nextHop) + if err != nil { + return err + } + row.Metric = metric + return row.Create() +} + +// AddRoutes method adds multiple routes to the interface. +func (luid LUID) AddRoutes(routesData []*RouteData) error { + for _, rd := range routesData { + err := luid.AddRoute(rd.Destination, rd.NextHop, rd.Metric) + if err != nil { + return err + } + } + return nil +} + +// SetRoutes method sets (flush than add) multiple routes to the interface. +func (luid LUID) SetRoutes(routesData []*RouteData) error { + err := luid.FlushRoutes(windows.AF_UNSPEC) + if err != nil { + return err + } + return luid.AddRoutes(routesData) +} + +// SetRoutesForFamily method sets (flush than add) multiple routes for a specific family to the interface. +func (luid LUID) SetRoutesForFamily(family AddressFamily, routesData []*RouteData) error { + err := luid.FlushRoutes(family) + if err != nil { + return err + } + for _, rd := range routesData { + if !rd.Destination.Addr().Is4() && family == windows.AF_INET { + continue + } else if !rd.Destination.Addr().Is6() && family == windows.AF_INET6 { + continue + } + err := luid.AddRoute(rd.Destination, rd.NextHop, rd.Metric) + if err != nil { + return err + } + } + return nil +} + +// DeleteRoute method deletes a route that matches the criteria. Corresponds to DeleteIpForwardEntry2 function +// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteipforwardentry2). +func (luid LUID) DeleteRoute(destination netip.Prefix, nextHop netip.Addr) error { + row := &MibIPforwardRow2{} + row.Init() + row.InterfaceLUID = luid + err := row.DestinationPrefix.SetPrefix(destination) + if err != nil { + return err + } + err = row.NextHop.SetAddr(nextHop) + if err != nil { + return err + } + err = row.get() + if err != nil { + return err + } + return row.Delete() +} + +// FlushRoutes method deletes all interface's routes. +// It continues on failures, and returns the last error afterwards. +func (luid LUID) FlushRoutes(family AddressFamily) error { + var tab *mibIPforwardTable2 + err := getIPForwardTable2(family, &tab) + if err != nil { + return err + } + t := tab.get() + for i := range t { + if t[i].InterfaceLUID == luid { + err2 := t[i].Delete() + if err2 != nil { + err = err2 + } + } + } + tab.free() + return err +} + +// DNS method returns all DNS server addresses associated with the adapter. +func (luid LUID) DNS() ([]netip.Addr, error) { + addresses, err := GetAdaptersAddresses(windows.AF_UNSPEC, GAAFlagDefault) + if err != nil { + return nil, err + } + r := make([]netip.Addr, 0, len(addresses)) + for _, addr := range addresses { + if addr.LUID == luid { + for dns := addr.FirstDNSServerAddress; dns != nil; dns = dns.Next { + if ip := dns.Address.IP(); ip != nil { + if a, ok := netip.AddrFromSlice(ip); ok { + r = append(r, a) + } + } else { + return nil, windows.ERROR_INVALID_PARAMETER + } + } + } + } + return r, nil +} + +// SetDNS method clears previous and associates new DNS servers and search domains with the adapter for a specific family. +func (luid LUID) SetDNS(family AddressFamily, servers []netip.Addr, domains []string) error { + if family != windows.AF_INET && family != windows.AF_INET6 { + return windows.ERROR_PROTOCOL_UNREACHABLE + } + + var filteredServers []string + for _, server := range servers { + if (server.Is4() && family == windows.AF_INET) || (server.Is6() && family == windows.AF_INET6) { + filteredServers = append(filteredServers, server.String()) + } + } + servers16, err := windows.UTF16PtrFromString(strings.Join(filteredServers, ",")) + if err != nil { + return err + } + domains16, err := windows.UTF16PtrFromString(strings.Join(domains, ",")) + if err != nil { + return err + } + guid, err := luid.GUID() + if err != nil { + return err + } + dnsInterfaceSettings := &DnsInterfaceSettings{ + Version: DnsInterfaceSettingsVersion1, + Flags: DnsInterfaceSettingsFlagNameserver | DnsInterfaceSettingsFlagSearchList, + NameServer: servers16, + SearchList: domains16, + } + if family == windows.AF_INET6 { + dnsInterfaceSettings.Flags |= DnsInterfaceSettingsFlagIPv6 + } + // For >= Windows 10 1809 + err = SetInterfaceDnsSettings(*guid, dnsInterfaceSettings) + if err == nil || !errors.Is(err, windows.ERROR_PROC_NOT_FOUND) { + return err + } + + // For < Windows 10 1809 + err = luid.fallbackSetDNSForFamily(family, servers) + if err != nil { + return err + } + if len(domains) > 0 { + return luid.fallbackSetDNSDomain(domains[0]) + } else { + return luid.fallbackSetDNSDomain("") + } +} + +// FlushDNS method clears all DNS servers associated with the adapter. +func (luid LUID) FlushDNS(family AddressFamily) error { + return luid.SetDNS(family, nil, nil) +} diff --git a/winipcfg/mksyscall.go b/winipcfg/mksyscall.go new file mode 100644 index 0000000..d62d38d --- /dev/null +++ b/winipcfg/mksyscall.go @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. + */ + +package winipcfg + +//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zwinipcfg_windows.go winipcfg.go diff --git a/winipcfg/netsh.go b/winipcfg/netsh.go new file mode 100644 index 0000000..4f8e5b1 --- /dev/null +++ b/winipcfg/netsh.go @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. + */ + +package winipcfg + +import ( + "bytes" + "errors" + "fmt" + "io" + "net/netip" + "os/exec" + "path/filepath" + "strings" + "syscall" + + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" +) + +func runNetsh(cmds []string) error { + system32, err := windows.GetSystemDirectory() + if err != nil { + return err + } + cmd := exec.Command(filepath.Join(system32, "netsh.exe")) + cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} + + stdin, err := cmd.StdinPipe() + if err != nil { + return fmt.Errorf("runNetsh stdin pipe - %w", err) + } + go func() { + defer stdin.Close() + io.WriteString(stdin, strings.Join(append(cmds, "exit\r\n"), "\r\n")) + }() + output, err := cmd.CombinedOutput() + // Horrible kludges, sorry. + cleaned := bytes.ReplaceAll(output, []byte{'\r', '\n'}, []byte{'\n'}) + cleaned = bytes.ReplaceAll(cleaned, []byte("netsh>"), []byte{}) + cleaned = bytes.ReplaceAll(cleaned, []byte("There are no Domain Name Servers (DNS) configured on this computer."), []byte{}) + cleaned = bytes.TrimSpace(cleaned) + if len(cleaned) != 0 && err == nil { + return fmt.Errorf("netsh: %#q", string(cleaned)) + } else if err != nil { + return fmt.Errorf("netsh: %v: %#q", err, string(cleaned)) + } + return nil +} + +const ( + netshCmdTemplateFlush4 = "interface ipv4 set dnsservers name=%d source=static address=none validate=no register=both" + netshCmdTemplateFlush6 = "interface ipv6 set dnsservers name=%d source=static address=none validate=no register=both" + netshCmdTemplateAdd4 = "interface ipv4 add dnsservers name=%d address=%s validate=no" + netshCmdTemplateAdd6 = "interface ipv6 add dnsservers name=%d address=%s validate=no" +) + +func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []netip.Addr) error { + var templateFlush string + if family == windows.AF_INET { + templateFlush = netshCmdTemplateFlush4 + } else if family == windows.AF_INET6 { + templateFlush = netshCmdTemplateFlush6 + } + + cmds := make([]string, 0, 1+len(dnses)) + ipif, err := luid.IPInterface(family) + if err != nil { + return err + } + cmds = append(cmds, fmt.Sprintf(templateFlush, ipif.InterfaceIndex)) + for i := 0; i < len(dnses); i++ { + if dnses[i].Is4() && family == windows.AF_INET { + cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd4, ipif.InterfaceIndex, dnses[i].String())) + } else if dnses[i].Is6() && family == windows.AF_INET6 { + cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd6, ipif.InterfaceIndex, dnses[i].String())) + } + } + return runNetsh(cmds) +} + +func (luid LUID) fallbackSetDNSDomain(domain string) error { + guid, err := luid.GUID() + if err != nil { + return fmt.Errorf("Error converting luid to guid: %w", err) + } + key, err := registry.OpenKey(registry.LOCAL_MACHINE, fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters\\%v", guid), registry.QUERY_VALUE) + if err != nil { + return fmt.Errorf("Error opening adapter-specific TCP/IP network registry key: %w", err) + } + paths, _, err := key.GetStringsValue("IpConfig") + key.Close() + if err != nil { + return fmt.Errorf("Error reading IpConfig registry key: %w", err) + } + if len(paths) == 0 { + return errors.New("No TCP/IP interfaces found on adapter") + } + key, err = registry.OpenKey(registry.LOCAL_MACHINE, fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\%s", paths[0]), registry.SET_VALUE) + if err != nil { + return fmt.Errorf("Unable to open TCP/IP network registry key: %w", err) + } + err = key.SetStringValue("Domain", domain) + key.Close() + return err +} diff --git a/winipcfg/types.go b/winipcfg/types.go new file mode 100644 index 0000000..8e8f4a5 --- /dev/null +++ b/winipcfg/types.go @@ -0,0 +1,1018 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. + */ + +package winipcfg + +import ( + "encoding/binary" + "fmt" + "net/netip" + "strconv" + "unsafe" + + "golang.org/x/sys/windows" +) + +const ( + anySize = 1 + maxDNSSuffixStringLength = 256 + maxDHCPv6DUIDLength = 130 + ifMaxStringSize = 256 + ifMaxPhysAddressLength = 32 +) + +// AddressFamily enumeration specifies protocol family and is one of the windows.AF_* constants. +type AddressFamily uint16 + +// IPAAFlags enumeration describes adapter addresses flags +// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_addresses_lh +type IPAAFlags uint32 + +const ( + IPAAFlagDdnsEnabled IPAAFlags = 1 << iota + IPAAFlagRegisterAdapterSuffix + IPAAFlagDhcpv4Enabled + IPAAFlagReceiveOnly + IPAAFlagNoMulticast + IPAAFlagIpv6OtherStatefulConfig + IPAAFlagNetbiosOverTcpipEnabled + IPAAFlagIpv4Enabled + IPAAFlagIpv6Enabled + IPAAFlagIpv6ManagedAddressConfigurationSupported +) + +// IfOperStatus enumeration specifies the operational status of an interface. +// https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-if_oper_status +type IfOperStatus uint32 + +const ( + IfOperStatusUp IfOperStatus = iota + 1 + IfOperStatusDown + IfOperStatusTesting + IfOperStatusUnknown + IfOperStatusDormant + IfOperStatusNotPresent + IfOperStatusLowerLayerDown +) + +// IfType enumeration specifies interface type. +type IfType uint32 + +const ( + IfTypeOther IfType = 1 // None of the below + IfTypeRegular1822 = 2 + IfTypeHdh1822 = 3 + IfTypeDdnX25 = 4 + IfTypeRfc877X25 = 5 + IfTypeEthernetCSMACD = 6 + IfTypeISO88023CSMACD = 7 + IfTypeISO88024Tokenbus = 8 + IfTypeISO88025Tokenring = 9 + IfTypeISO88026Man = 10 + IfTypeStarlan = 11 + IfTypeProteon10Mbit = 12 + IfTypeProteon80Mbit = 13 + IfTypeHyperchannel = 14 + IfTypeFddi = 15 + IfTypeLapB = 16 + IfTypeSdlc = 17 + IfTypeDs1 = 18 // DS1-MIB + IfTypeE1 = 19 // Obsolete; see DS1-MIB + IfTypeBasicISDN = 20 + IfTypePrimaryISDN = 21 + IfTypePropPoint2PointSerial = 22 // proprietary serial + IfTypePPP = 23 + IfTypeSoftwareLoopback = 24 + IfTypeEon = 25 // CLNP over IP + IfTypeEthernet3Mbit = 26 + IfTypeNsip = 27 // XNS over IP + IfTypeSlip = 28 // Generic Slip + IfTypeUltra = 29 // ULTRA Technologies + IfTypeDs3 = 30 // DS3-MIB + IfTypeSip = 31 // SMDS, coffee + IfTypeFramerelay = 32 // DTE only + IfTypeRs232 = 33 + IfTypePara = 34 // Parallel port + IfTypeArcnet = 35 + IfTypeArcnetPlus = 36 + IfTypeAtm = 37 // ATM cells + IfTypeMioX25 = 38 + IfTypeSonet = 39 // SONET or SDH + IfTypeX25Ple = 40 + IfTypeIso88022LLC = 41 + IfTypeLocaltalk = 42 + IfTypeSmdsDxi = 43 + IfTypeFramerelayService = 44 // FRNETSERV-MIB + IfTypeV35 = 45 + IfTypeHssi = 46 + IfTypeHippi = 47 + IfTypeModem = 48 // Generic Modem + IfTypeAal5 = 49 // AAL5 over ATM + IfTypeSonetPath = 50 + IfTypeSonetVt = 51 + IfTypeSmdsIcip = 52 // SMDS InterCarrier Interface + IfTypePropVirtual = 53 // Proprietary virtual/internal + IfTypePropMultiplexor = 54 // Proprietary multiplexing + IfTypeIEEE80212 = 55 // 100BaseVG + IfTypeFibrechannel = 56 + IfTypeHippiinterface = 57 + IfTypeFramerelayInterconnect = 58 // Obsolete, use 32 or 44 + IfTypeAflane8023 = 59 // ATM Emulated LAN for 802.3 + IfTypeAflane8025 = 60 // ATM Emulated LAN for 802.5 + IfTypeCctemul = 61 // ATM Emulated circuit + IfTypeFastether = 62 // Fast Ethernet (100BaseT) + IfTypeISDN = 63 // ISDN and X.25 + IfTypeV11 = 64 // CCITT V.11/X.21 + IfTypeV36 = 65 // CCITT V.36 + IfTypeG703_64k = 66 // CCITT G703 at 64Kbps + IfTypeG703_2mb = 67 // Obsolete; see DS1-MIB + IfTypeQllc = 68 // SNA QLLC + IfTypeFastetherFX = 69 // Fast Ethernet (100BaseFX) + IfTypeChannel = 70 + IfTypeIEEE80211 = 71 // Radio spread spectrum + IfTypeIBM370parchan = 72 // IBM System 360/370 OEMI Channel + IfTypeEscon = 73 // IBM Enterprise Systems Connection + IfTypeDlsw = 74 // Data Link Switching + IfTypeISDNS = 75 // ISDN S/T interface + IfTypeISDNU = 76 // ISDN U interface + IfTypeLapD = 77 // Link Access Protocol D + IfTypeIpswitch = 78 // IP Switching Objects + IfTypeRsrb = 79 // Remote Source Route Bridging + IfTypeAtmLogical = 80 // ATM Logical Port + IfTypeDs0 = 81 // Digital Signal Level 0 + IfTypeDs0Bundle = 82 // Group of ds0s on the same ds1 + IfTypeBsc = 83 // Bisynchronous Protocol + IfTypeAsync = 84 // Asynchronous Protocol + IfTypeCnr = 85 // Combat Net Radio + IfTypeIso88025rDtr = 86 // ISO 802.5r DTR + IfTypeEplrs = 87 // Ext Pos Loc Report Sys + IfTypeArap = 88 // Appletalk Remote Access Protocol + IfTypePropCnls = 89 // Proprietary Connectionless Proto + IfTypeHostpad = 90 // CCITT-ITU X.29 PAD Protocol + IfTypeTermpad = 91 // CCITT-ITU X.3 PAD Facility + IfTypeFramerelayMpi = 92 // Multiproto Interconnect over FR + IfTypeX213 = 93 // CCITT-ITU X213 + IfTypeAdsl = 94 // Asymmetric Digital Subscrbr Loop + IfTypeRadsl = 95 // Rate-Adapt Digital Subscrbr Loop + IfTypeSdsl = 96 // Symmetric Digital Subscriber Loop + IfTypeVdsl = 97 // Very H-Speed Digital Subscrb Loop + IfTypeIso88025Crfprint = 98 // ISO 802.5 CRFP + IfTypeMyrinet = 99 // Myricom Myrinet + IfTypeVoiceEm = 100 // Voice recEive and transMit + IfTypeVoiceFxo = 101 // Voice Foreign Exchange Office + IfTypeVoiceFxs = 102 // Voice Foreign Exchange Station + IfTypeVoiceEncap = 103 // Voice encapsulation + IfTypeVoiceOverip = 104 // Voice over IP encapsulation + IfTypeAtmDxi = 105 // ATM DXI + IfTypeAtmFuni = 106 // ATM FUNI + IfTypeAtmIma = 107 // ATM IMA + IfTypePPPmultilinkbundle = 108 // PPP Multilink Bundle + IfTypeIpoverCdlc = 109 // IBM ipOverCdlc + IfTypeIpoverClaw = 110 // IBM Common Link Access to Workstn + IfTypeStacktostack = 111 // IBM stackToStack + IfTypeVirtualipaddress = 112 // IBM VIPA + IfTypeMpc = 113 // IBM multi-proto channel support + IfTypeIpoverAtm = 114 // IBM ipOverAtm + IfTypeIso88025Fiber = 115 // ISO 802.5j Fiber Token Ring + IfTypeTdlc = 116 // IBM twinaxial data link control + IfTypeGigabitethernet = 117 + IfTypeHdlc = 118 + IfTypeLapF = 119 + IfTypeV37 = 120 + IfTypeX25Mlp = 121 // Multi-Link Protocol + IfTypeX25Huntgroup = 122 // X.25 Hunt Group + IfTypeTransphdlc = 123 + IfTypeInterleave = 124 // Interleave channel + IfTypeFast = 125 // Fast channel + IfTypeIP = 126 // IP (for APPN HPR in IP networks) + IfTypeDocscableMaclayer = 127 // CATV Mac Layer + IfTypeDocscableDownstream = 128 // CATV Downstream interface + IfTypeDocscableUpstream = 129 // CATV Upstream interface + IfTypeA12mppswitch = 130 // Avalon Parallel Processor + IfTypeTunnel = 131 // Encapsulation interface + IfTypeCoffee = 132 // Coffee pot + IfTypeCes = 133 // Circuit Emulation Service + IfTypeAtmSubinterface = 134 // ATM Sub Interface + IfTypeL2Vlan = 135 // Layer 2 Virtual LAN using 802.1Q + IfTypeL3Ipvlan = 136 // Layer 3 Virtual LAN using IP + IfTypeL3Ipxvlan = 137 // Layer 3 Virtual LAN using IPX + IfTypeDigitalpowerline = 138 // IP over Power Lines + IfTypeMediamailoverip = 139 // Multimedia Mail over IP + IfTypeDtm = 140 // Dynamic syncronous Transfer Mode + IfTypeDcn = 141 // Data Communications Network + IfTypeIpforward = 142 // IP Forwarding Interface + IfTypeMsdsl = 143 // Multi-rate Symmetric DSL + IfTypeIEEE1394 = 144 // IEEE1394 High Perf Serial Bus + IfTypeIfGsn = 145 + IfTypeDvbrccMaclayer = 146 + IfTypeDvbrccDownstream = 147 + IfTypeDvbrccUpstream = 148 + IfTypeAtmVirtual = 149 + IfTypeMplsTunnel = 150 + IfTypeSrp = 151 + IfTypeVoiceoveratm = 152 + IfTypeVoiceoverframerelay = 153 + IfTypeIdsl = 154 + IfTypeCompositelink = 155 + IfTypeSs7Siglink = 156 + IfTypePropWirelessP2P = 157 + IfTypeFrForward = 158 + IfTypeRfc1483 = 159 + IfTypeUsb = 160 + IfTypeIEEE8023adLag = 161 + IfTypeBgpPolicyAccounting = 162 + IfTypeFrf16MfrBundle = 163 + IfTypeH323Gatekeeper = 164 + IfTypeH323Proxy = 165 + IfTypeMpls = 166 + IfTypeMfSiglink = 167 + IfTypeHdsl2 = 168 + IfTypeShdsl = 169 + IfTypeDs1Fdl = 170 + IfTypePos = 171 + IfTypeDvbAsiIn = 172 + IfTypeDvbAsiOut = 173 + IfTypePlc = 174 + IfTypeNfas = 175 + IfTypeTr008 = 176 + IfTypeGr303Rdt = 177 + IfTypeGr303Idt = 178 + IfTypeIsup = 179 + IfTypePropDocsWirelessMaclayer = 180 + IfTypePropDocsWirelessDownstream = 181 + IfTypePropDocsWirelessUpstream = 182 + IfTypeHiperlan2 = 183 + IfTypePropBwaP2MP = 184 + IfTypeSonetOverheadChannel = 185 + IfTypeDigitalWrapperOverheadChannel = 186 + IfTypeAal2 = 187 + IfTypeRadioMac = 188 + IfTypeAtmRadio = 189 + IfTypeImt = 190 + IfTypeMvl = 191 + IfTypeReachDsl = 192 + IfTypeFrDlciEndpt = 193 + IfTypeAtmVciEndpt = 194 + IfTypeOpticalChannel = 195 + IfTypeOpticalTransport = 196 + IfTypeIEEE80216Wman = 237 + IfTypeWwanpp = 243 // WWAN devices based on GSM technology + IfTypeWwanpp2 = 244 // WWAN devices based on CDMA technology + IfTypeIEEE802154 = 259 // IEEE 802.15.4 WPAN interface + IfTypeXboxWireless = 281 +) + +// MibIfEntryLevel enumeration specifies level of interface information to retrieve in GetIfTable2Ex function call. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getifentry2ex +type MibIfEntryLevel uint32 + +const ( + MibIfEntryNormal MibIfEntryLevel = 0 + MibIfEntryNormalWithoutStatistics = 2 +) + +// NdisMedium enumeration type identifies the medium types that NDIS drivers support. +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddndis/ne-ntddndis-_ndis_medium +type NdisMedium uint32 + +const ( + NdisMedium802_3 NdisMedium = iota + NdisMedium802_5 + NdisMediumFddi + NdisMediumWan + NdisMediumLocalTalk + NdisMediumDix // defined for convenience, not a real medium + NdisMediumArcnetRaw + NdisMediumArcnet878_2 + NdisMediumAtm + NdisMediumWirelessWan + NdisMediumIrda + NdisMediumBpc + NdisMediumCoWan + NdisMedium1394 + NdisMediumInfiniBand + NdisMediumTunnel + NdisMediumNative802_11 + NdisMediumLoopback + NdisMediumWiMAX + NdisMediumIP + NdisMediumMax +) + +// NdisPhysicalMedium describes NDIS physical medium type. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_row2 +type NdisPhysicalMedium uint32 + +const ( + NdisPhysicalMediumUnspecified NdisPhysicalMedium = iota + NdisPhysicalMediumWirelessLan + NdisPhysicalMediumCableModem + NdisPhysicalMediumPhoneLine + NdisPhysicalMediumPowerLine + NdisPhysicalMediumDSL // includes ADSL and UADSL (G.Lite) + NdisPhysicalMediumFibreChannel + NdisPhysicalMedium1394 + NdisPhysicalMediumWirelessWan + NdisPhysicalMediumNative802_11 + NdisPhysicalMediumBluetooth + NdisPhysicalMediumInfiniband + NdisPhysicalMediumWiMax + NdisPhysicalMediumUWB + NdisPhysicalMedium802_3 + NdisPhysicalMedium802_5 + NdisPhysicalMediumIrda + NdisPhysicalMediumWiredWAN + NdisPhysicalMediumWiredCoWan + NdisPhysicalMediumOther + NdisPhysicalMediumNative802_15_4 + NdisPhysicalMediumMax +) + +// NetIfAccessType enumeration type specifies the NDIS network interface access type. +// https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-_net_if_access_type +type NetIfAccessType uint32 + +const ( + NetIfAccessLoopback NetIfAccessType = iota + 1 + NetIfAccessBroadcast + NetIfAccessPointToPoint + NetIfAccessPointToMultiPoint + NetIfAccessMax +) + +// NetIfAdminStatus enumeration type specifies the NDIS network interface administrative status, as described in RFC 2863. +// https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-net_if_admin_status +type NetIfAdminStatus uint32 + +const ( + NetIfAdminStatusUp NetIfAdminStatus = iota + 1 + NetIfAdminStatusDown + NetIfAdminStatusTesting +) + +// NetIfConnectionType enumeration type specifies the NDIS network interface connection type. +// https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-_net_if_connection_type +type NetIfConnectionType uint32 + +const ( + NetIfConnectionDedicated NetIfConnectionType = iota + 1 + NetIfConnectionPassive + NetIfConnectionDemand + NetIfConnectionMaximum +) + +// NetIfDirectionType enumeration type specifies the NDIS network interface direction type. +// https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-net_if_direction_type +type NetIfDirectionType uint32 + +const ( + NetIfDirectionSendReceive NetIfDirectionType = iota + NetIfDirectionSendOnly + NetIfDirectionReceiveOnly + NetIfDirectionMaximum +) + +// NetIfMediaConnectState enumeration type specifies the NDIS network interface connection state. +// https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-_net_if_media_connect_state +type NetIfMediaConnectState uint32 + +const ( + MediaConnectStateUnknown NetIfMediaConnectState = iota + MediaConnectStateConnected + MediaConnectStateDisconnected +) + +// DadState enumeration specifies information about the duplicate address detection (DAD) state for an IPv4 or IPv6 address. +// https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-nl_dad_state +type DadState uint32 + +const ( + DadStateInvalid DadState = iota + DadStateTentative + DadStateDuplicate + DadStateDeprecated + DadStatePreferred +) + +// PrefixOrigin enumeration specifies the origin of an IPv4 or IPv6 address prefix, and is used with the IP_ADAPTER_UNICAST_ADDRESS structure. +// https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-nl_prefix_origin +type PrefixOrigin uint32 + +const ( + PrefixOriginOther PrefixOrigin = iota + PrefixOriginManual + PrefixOriginWellKnown + PrefixOriginDHCP + PrefixOriginRouterAdvertisement + PrefixOriginUnchanged = 1 << 4 +) + +// LinkLocalAddressBehavior enumeration type defines the link local address behavior. +// https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-_nl_link_local_address_behavior +type LinkLocalAddressBehavior int32 + +const ( + LinkLocalAddressAlwaysOff LinkLocalAddressBehavior = iota // Never use link locals. + LinkLocalAddressDelayed // Use link locals only if no other addresses. (default for IPv4). Legacy mapping: IPAutoconfigurationEnabled. + LinkLocalAddressAlwaysOn // Always use link locals (default for IPv6). + LinkLocalAddressUnchanged = -1 +) + +// OffloadRod enumeration specifies a set of flags that indicate the offload capabilities for an IP interface. +// https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ns-nldef-_nl_interface_offload_rod +type OffloadRod uint8 + +const ( + ChecksumSupported OffloadRod = 1 << iota + OptionsSupported + DatagramChecksumSupported + StreamChecksumSupported + StreamOptionsSupported + FastPathCompatible + LargeSendOffloadSupported + GiantSendOffloadSupported +) + +// RouteOrigin enumeration type defines the origin of the IP route. +// https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-nl_route_origin +type RouteOrigin uint32 + +const ( + RouteOriginManual RouteOrigin = iota + RouteOriginWellKnown + RouteOriginDHCP + RouteOriginRouterAdvertisement + RouteOrigin6to4 +) + +// RouteProtocol enumeration type defines the routing mechanism that an IP route was added with, as described in RFC 4292. +// https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-nl_route_protocol +type RouteProtocol uint32 + +const ( + RouteProtocolOther RouteProtocol = iota + 1 + RouteProtocolLocal + RouteProtocolNetMgmt + RouteProtocolIcmp + RouteProtocolEgp + RouteProtocolGgp + RouteProtocolHello + RouteProtocolRip + RouteProtocolIsIs + RouteProtocolEsIs + RouteProtocolCisco + RouteProtocolBbn + RouteProtocolOspf + RouteProtocolBgp + RouteProtocolIdpr + RouteProtocolEigrp + RouteProtocolDvmrp + RouteProtocolRpl + RouteProtocolDHCP + RouteProtocolNTAutostatic = 10002 + RouteProtocolNTStatic = 10006 + RouteProtocolNTStaticNonDOD = 10007 +) + +// RouterDiscoveryBehavior enumeration type defines the router discovery behavior, as described in RFC 2461. +// https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-_nl_router_discovery_behavior +type RouterDiscoveryBehavior int32 + +const ( + RouterDiscoveryDisabled RouterDiscoveryBehavior = iota + RouterDiscoveryEnabled + RouterDiscoveryDHCP + RouterDiscoveryUnchanged = -1 +) + +// SuffixOrigin enumeration specifies the origin of an IPv4 or IPv6 address suffix, and is used with the IP_ADAPTER_UNICAST_ADDRESS structure. +// https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-nl_suffix_origin +type SuffixOrigin uint32 + +const ( + SuffixOriginOther SuffixOrigin = iota + SuffixOriginManual + SuffixOriginWellKnown + SuffixOriginDHCP + SuffixOriginLinkLayerAddress + SuffixOriginRandom + SuffixOriginUnchanged = 1 << 4 +) + +// MibNotificationType enumeration defines the notification type passed to a callback function when a notification occurs. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ne-netioapi-_mib_notification_type +type MibNotificationType uint32 + +const ( + MibParameterNotification MibNotificationType = iota // Parameter change + MibAddInstance // Addition + MibDeleteInstance // Deletion + MibInitialNotification // Initial notification +) + +type ChangeCallback interface { + Unregister() error +} + +// TunnelType enumeration type defines the encapsulation method used by a tunnel, as described by the Internet Assigned Names Authority (IANA). +// https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-tunnel_type +type TunnelType uint32 + +const ( + TunnelTypeNone TunnelType = 0 + TunnelTypeOther = 1 + TunnelTypeDirect = 2 + TunnelType6to4 = 11 + TunnelTypeIsatap = 13 + TunnelTypeTeredo = 14 + TunnelTypeIPHTTPS = 15 +) + +// InterfaceAndOperStatusFlags enumeration type defines interface and operation flags +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_row2 +type InterfaceAndOperStatusFlags uint8 + +const ( + IAOSFHardwareInterface InterfaceAndOperStatusFlags = 1 << iota + IAOSFFilterInterface + IAOSFConnectorPresent + IAOSFNotAuthenticated + IAOSFNotMediaConnected + IAOSFPaused + IAOSFLowPower + IAOSFEndPointInterface +) + +// GAAFlags enumeration defines flags used in GetAdaptersAddresses calls +// https://docs.microsoft.com/en-us/windows/desktop/api/iphlpapi/nf-iphlpapi-getadaptersaddresses +type GAAFlags uint32 + +const ( + GAAFlagSkipUnicast GAAFlags = 1 << iota + GAAFlagSkipAnycast + GAAFlagSkipMulticast + GAAFlagSkipDNSServer + GAAFlagIncludePrefix + GAAFlagSkipFriendlyName + GAAFlagIncludeWinsInfo + GAAFlagIncludeGateways + GAAFlagIncludeAllInterfaces + GAAFlagIncludeAllCompartments + GAAFlagIncludeTunnelBindingOrder + GAAFlagSkipDNSInfo + + GAAFlagDefault GAAFlags = 0 + GAAFlagSkipAll = GAAFlagSkipUnicast | GAAFlagSkipAnycast | GAAFlagSkipMulticast | GAAFlagSkipDNSServer | GAAFlagSkipFriendlyName | GAAFlagSkipDNSInfo + GAAFlagIncludeAll = GAAFlagIncludePrefix | GAAFlagIncludeWinsInfo | GAAFlagIncludeGateways | GAAFlagIncludeAllInterfaces | GAAFlagIncludeAllCompartments | GAAFlagIncludeTunnelBindingOrder +) + +// ScopeLevel enumeration is used with the IP_ADAPTER_ADDRESSES structure to identify scope levels for IPv6 addresses. +// https://docs.microsoft.com/en-us/windows/desktop/api/ws2def/ne-ws2def-scope_level +type ScopeLevel uint32 + +const ( + ScopeLevelInterface ScopeLevel = 1 + ScopeLevelLink = 2 + ScopeLevelSubnet = 3 + ScopeLevelAdmin = 4 + ScopeLevelSite = 5 + ScopeLevelOrganization = 8 + ScopeLevelGlobal = 14 + ScopeLevelCount = 16 +) + +// RouteData structure describes a route to add +type RouteData struct { + Destination netip.Prefix + NextHop netip.Addr + Metric uint32 +} + +func (routeData *RouteData) String() string { + return fmt.Sprintf("%+v", *routeData) +} + +// IPAdapterDNSSuffix structure stores a DNS suffix in a linked list of DNS suffixes for a particular adapter. +// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_dns_suffix +type IPAdapterDNSSuffix struct { + Next *IPAdapterDNSSuffix + str [maxDNSSuffixStringLength]uint16 +} + +// String method returns the DNS suffix for this DNS suffix entry. +func (obj *IPAdapterDNSSuffix) String() string { + return windows.UTF16ToString(obj.str[:]) +} + +// AdapterName method returns the name of the adapter with which these addresses are associated. +// Unlike an adapter's friendly name, the adapter name returned by AdapterName is permanent and cannot be modified by the user. +func (addr *IPAdapterAddresses) AdapterName() string { + return windows.BytePtrToString(addr.adapterName) +} + +// DNSSuffix method returns adapter DNS suffix associated with this adapter. +func (addr *IPAdapterAddresses) DNSSuffix() string { + if addr.dnsSuffix == nil { + return "" + } + return windows.UTF16PtrToString(addr.dnsSuffix) +} + +// Description method returns description for the adapter. +func (addr *IPAdapterAddresses) Description() string { + if addr.description == nil { + return "" + } + return windows.UTF16PtrToString(addr.description) +} + +// FriendlyName method returns a user-friendly name for the adapter. For example: "Local Area Connection 1." +// This name appears in contexts such as the ipconfig command line program and the Connection folder. +func (addr *IPAdapterAddresses) FriendlyName() string { + if addr.friendlyName == nil { + return "" + } + return windows.UTF16PtrToString(addr.friendlyName) +} + +// PhysicalAddress method returns the Media Access Control (MAC) address for the adapter. +// For example, on an Ethernet network this member would specify the Ethernet hardware address. +func (addr *IPAdapterAddresses) PhysicalAddress() []byte { + return addr.physicalAddress[:addr.physicalAddressLength] +} + +// DHCPv6ClientDUID method returns the DHCP unique identifier (DUID) for the DHCPv6 client. +// This information is only applicable to an IPv6 adapter address configured using DHCPv6. +func (addr *IPAdapterAddresses) DHCPv6ClientDUID() []byte { + return addr.dhcpv6ClientDUID[:addr.dhcpv6ClientDUIDLength] +} + +// Init method initializes the members of an MIB_IPINTERFACE_ROW entry with default values. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-initializeipinterfaceentry +func (row *MibIPInterfaceRow) Init() { + initializeIPInterfaceEntry(row) +} + +// get method retrieves IP information for the specified interface on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipinterfaceentry +func (row *MibIPInterfaceRow) get() error { + if err := getIPInterfaceEntry(row); err != nil { + return err + } + + // Patch that fixes SitePrefixLength issue + // https://stackoverflow.com/questions/54857292/setipinterfaceentry-returns-error-invalid-parameter?noredirect=1 + switch row.Family { + case windows.AF_INET: + if row.SitePrefixLength > 32 { + row.SitePrefixLength = 0 + } + case windows.AF_INET6: + if row.SitePrefixLength > 128 { + row.SitePrefixLength = 128 + } + } + + return nil +} + +// Set method sets the properties of an IP interface on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-setipinterfaceentry +func (row *MibIPInterfaceRow) Set() error { + return setIPInterfaceEntry(row) +} + +// get method returns all table rows as a Go slice. +func (tab *mibIPInterfaceTable) get() (s []MibIPInterfaceRow) { + return unsafe.Slice(&tab.table[0], tab.numEntries) +} + +// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-freemibtable +func (tab *mibIPInterfaceTable) free() { + freeMibTable(unsafe.Pointer(tab)) +} + +// Alias method returns a string that contains the alias name of the network interface. +func (row *MibIfRow2) Alias() string { + return windows.UTF16ToString(row.alias[:]) +} + +// Description method returns a string that contains a description of the network interface. +func (row *MibIfRow2) Description() string { + return windows.UTF16ToString(row.description[:]) +} + +// PhysicalAddress method returns the physical hardware address of the adapter for this network interface. +func (row *MibIfRow2) PhysicalAddress() []byte { + return row.physicalAddress[:row.physicalAddressLength] +} + +// PermanentPhysicalAddress method returns the permanent physical hardware address of the adapter for this network interface. +func (row *MibIfRow2) PermanentPhysicalAddress() []byte { + return row.permanentPhysicalAddress[:row.physicalAddressLength] +} + +// get method retrieves information for the specified interface on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getifentry2 +func (row *MibIfRow2) get() (ret error) { + return getIfEntry2(row) +} + +// get method returns all table rows as a Go slice. +func (tab *mibIfTable2) get() (s []MibIfRow2) { + return unsafe.Slice(&tab.table[0], tab.numEntries) +} + +// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-freemibtable +func (tab *mibIfTable2) free() { + freeMibTable(unsafe.Pointer(tab)) +} + +// RawSockaddrInet union contains an IPv4, an IPv6 address, or an address family. +// https://docs.microsoft.com/en-us/windows/desktop/api/ws2ipdef/ns-ws2ipdef-_sockaddr_inet +type RawSockaddrInet struct { + Family AddressFamily + data [26]byte +} + +func ntohs(i uint16) uint16 { + return binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&i))[:]) +} + +func htons(i uint16) uint16 { + b := make([]byte, 2) + binary.BigEndian.PutUint16(b, i) + return *(*uint16)(unsafe.Pointer(&b[0])) +} + +// SetAddrPort method sets family, address, and port to the given IPv4 or IPv6 address and port. +// All other members of the structure are set to zero. +func (addr *RawSockaddrInet) SetAddrPort(addrPort netip.AddrPort) error { + if addrPort.Addr().Is4() { + addr4 := (*windows.RawSockaddrInet4)(unsafe.Pointer(addr)) + addr4.Family = windows.AF_INET + addr4.Addr = addrPort.Addr().As4() + addr4.Port = htons(addrPort.Port()) + for i := 0; i < 8; i++ { + addr4.Zero[i] = 0 + } + return nil + } else if addrPort.Addr().Is6() { + addr6 := (*windows.RawSockaddrInet6)(unsafe.Pointer(addr)) + addr6.Family = windows.AF_INET6 + addr6.Addr = addrPort.Addr().As16() + addr6.Port = htons(addrPort.Port()) + addr6.Flowinfo = 0 + scopeId := uint32(0) + if z := addrPort.Addr().Zone(); z != "" { + if s, err := strconv.ParseUint(z, 10, 32); err == nil { + scopeId = uint32(s) + } + } + addr6.Scope_id = scopeId + return nil + } + return windows.ERROR_INVALID_PARAMETER +} + +// SetAddr method sets family and address to the given IPv4 or IPv6 address. +// All other members of the structure are set to zero. +func (addr *RawSockaddrInet) SetAddr(netAddr netip.Addr) error { + return addr.SetAddrPort(netip.AddrPortFrom(netAddr, 0)) +} + +// AddrPort returns the IP address and port. +func (addr *RawSockaddrInet) AddrPort() netip.AddrPort { + return netip.AddrPortFrom(addr.Addr(), addr.Port()) +} + +// Addr returns IPv4 or IPv6 address, or an invalid address if the address is neither. +func (addr *RawSockaddrInet) Addr() netip.Addr { + switch addr.Family { + case windows.AF_INET: + return netip.AddrFrom4((*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Addr) + case windows.AF_INET6: + raw := (*windows.RawSockaddrInet6)(unsafe.Pointer(addr)) + a := netip.AddrFrom16(raw.Addr) + if raw.Scope_id != 0 { + a = a.WithZone(strconv.FormatUint(uint64(raw.Scope_id), 10)) + } + return a + } + return netip.Addr{} +} + +// Port returns the port if the address if IPv4 or IPv6, or 0 if neither. +func (addr *RawSockaddrInet) Port() uint16 { + switch addr.Family { + case windows.AF_INET: + return ntohs((*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Port) + case windows.AF_INET6: + return ntohs((*windows.RawSockaddrInet6)(unsafe.Pointer(addr)).Port) + } + return 0 +} + +// Init method initializes a MibUnicastIPAddressRow structure with default values for a unicast IP address entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-initializeunicastipaddressentry +func (row *MibUnicastIPAddressRow) Init() { + initializeUnicastIPAddressEntry(row) +} + +// get method retrieves information for an existing unicast IP address entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getunicastipaddressentry +func (row *MibUnicastIPAddressRow) get() error { + return getUnicastIPAddressEntry(row) +} + +// Set method sets the properties of an existing unicast IP address entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-setunicastipaddressentry +func (row *MibUnicastIPAddressRow) Set() error { + return setUnicastIPAddressEntry(row) +} + +// Create method adds a new unicast IP address entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry +func (row *MibUnicastIPAddressRow) Create() error { + return createUnicastIPAddressEntry(row) +} + +// Delete method deletes an existing unicast IP address entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteunicastipaddressentry +func (row *MibUnicastIPAddressRow) Delete() error { + return deleteUnicastIPAddressEntry(row) +} + +// get method returns all table rows as a Go slice. +func (tab *mibUnicastIPAddressTable) get() (s []MibUnicastIPAddressRow) { + return unsafe.Slice(&tab.table[0], tab.numEntries) +} + +// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-freemibtable +func (tab *mibUnicastIPAddressTable) free() { + freeMibTable(unsafe.Pointer(tab)) +} + +// get method retrieves information for an existing anycast IP address entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getanycastipaddressentry +func (row *MibAnycastIPAddressRow) get() error { + return getAnycastIPAddressEntry(row) +} + +// Create method adds a new anycast IP address entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createanycastipaddressentry +func (row *MibAnycastIPAddressRow) Create() error { + return createAnycastIPAddressEntry(row) +} + +// Delete method deletes an existing anycast IP address entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteanycastipaddressentry +func (row *MibAnycastIPAddressRow) Delete() error { + return deleteAnycastIPAddressEntry(row) +} + +// get method returns all table rows as a Go slice. +func (tab *mibAnycastIPAddressTable) get() (s []MibAnycastIPAddressRow) { + return unsafe.Slice(&tab.table[0], tab.numEntries) +} + +// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-freemibtable +func (tab *mibAnycastIPAddressTable) free() { + freeMibTable(unsafe.Pointer(tab)) +} + +// IPAddressPrefix structure stores an IP address prefix. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_ip_address_prefix +type IPAddressPrefix struct { + RawPrefix RawSockaddrInet + PrefixLength uint8 + _ [2]byte +} + +// SetPrefix method sets IP address prefix using netip.Prefix. +func (prefix *IPAddressPrefix) SetPrefix(netPrefix netip.Prefix) error { + err := prefix.RawPrefix.SetAddr(netPrefix.Addr()) + if err != nil { + return err + } + prefix.PrefixLength = uint8(netPrefix.Bits()) + return nil +} + +// Prefix returns IP address prefix as netip.Prefix. +func (prefix *IPAddressPrefix) Prefix() netip.Prefix { + switch prefix.RawPrefix.Family { + case windows.AF_INET: + return netip.PrefixFrom(netip.AddrFrom4((*windows.RawSockaddrInet4)(unsafe.Pointer(&prefix.RawPrefix)).Addr), int(prefix.PrefixLength)) + case windows.AF_INET6: + return netip.PrefixFrom(netip.AddrFrom16((*windows.RawSockaddrInet6)(unsafe.Pointer(&prefix.RawPrefix)).Addr), int(prefix.PrefixLength)) + } + return netip.Prefix{} +} + +// MibIPforwardRow2 structure stores information about an IP route entry. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipforward_row2 +type MibIPforwardRow2 struct { + InterfaceLUID LUID + InterfaceIndex uint32 + DestinationPrefix IPAddressPrefix + NextHop RawSockaddrInet + SitePrefixLength uint8 + ValidLifetime uint32 + PreferredLifetime uint32 + Metric uint32 + Protocol RouteProtocol + Loopback bool + AutoconfigureAddress bool + Publish bool + Immortal bool + Age uint32 + Origin RouteOrigin +} + +// Init method initializes a MIB_IPFORWARD_ROW2 structure with default values for an IP route entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-initializeipforwardentry +func (row *MibIPforwardRow2) Init() { + initializeIPForwardEntry(row) +} + +// get method retrieves information for an IP route entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipforwardentry2 +func (row *MibIPforwardRow2) get() error { + return getIPForwardEntry2(row) +} + +// Set method sets the properties of an IP route entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-setipforwardentry2 +func (row *MibIPforwardRow2) Set() error { + return setIPForwardEntry2(row) +} + +// Create method creates a new IP route entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createipforwardentry2 +func (row *MibIPforwardRow2) Create() error { + return createIPForwardEntry2(row) +} + +// Delete method deletes an IP route entry on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteipforwardentry2 +func (row *MibIPforwardRow2) Delete() error { + return deleteIPForwardEntry2(row) +} + +// get method returns all table rows as a Go slice. +func (tab *mibIPforwardTable2) get() (s []MibIPforwardRow2) { + return unsafe.Slice(&tab.table[0], tab.numEntries) +} + +// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-freemibtable +func (tab *mibIPforwardTable2) free() { + freeMibTable(unsafe.Pointer(tab)) +} + +// +// DNS API +// + +// DnsInterfaceSettings is meant to be used with SetInterfaceDnsSettings +type DnsInterfaceSettings struct { + Version uint32 + _ [4]byte + Flags uint64 + Domain *uint16 + NameServer *uint16 + SearchList *uint16 + RegistrationEnabled uint32 + RegisterAdapterName uint32 + EnableLLMNR uint32 + QueryAdapterName uint32 + ProfileNameServer *uint16 +} + +const ( + DnsInterfaceSettingsVersion1 = 1 // for DnsInterfaceSettings + DnsInterfaceSettingsVersion2 = 2 // for DnsInterfaceSettingsEx + DnsInterfaceSettingsVersion3 = 3 // for DnsInterfaceSettings3 + + DnsInterfaceSettingsFlagIPv6 = 0x0001 + DnsInterfaceSettingsFlagNameserver = 0x0002 + DnsInterfaceSettingsFlagSearchList = 0x0004 + DnsInterfaceSettingsFlagRegistrationEnabled = 0x0008 + DnsInterfaceSettingsFlagRegisterAdapterName = 0x0010 + DnsInterfaceSettingsFlagDomain = 0x0020 + DnsInterfaceSettingsFlagHostname = 0x0040 + DnsInterfaceSettingsFlagEnableLLMNR = 0x0080 + DnsInterfaceSettingsFlagQueryAdapterName = 0x0100 + DnsInterfaceSettingsFlagProfileNameserver = 0x0200 + DnsInterfaceSettingsFlagDisableUnconstrainedQueries = 0x0400 // v2 only + DnsInterfaceSettingsFlagSupplementalSearchList = 0x0800 // v2 only + DnsInterfaceSettingsFlagDOH = 0x1000 // v3 only + DnsInterfaceSettingsFlagDOHProfile = 0x2000 // v3 only +) diff --git a/winipcfg/types_32.go b/winipcfg/types_32.go new file mode 100644 index 0000000..1a8d444 --- /dev/null +++ b/winipcfg/types_32.go @@ -0,0 +1,232 @@ +//go:build 386 || arm + +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. + */ + +package winipcfg + +import ( + "golang.org/x/sys/windows" +) + +// IPAdapterWINSServerAddress structure stores a single Windows Internet Name Service (WINS) server address in a linked list of WINS server addresses for a particular adapter. +// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_wins_server_address_lh +type IPAdapterWINSServerAddress struct { + Length uint32 + _ uint32 + Next *IPAdapterWINSServerAddress + Address windows.SocketAddress + _ [4]byte +} + +// IPAdapterGatewayAddress structure stores a single gateway address in a linked list of gateway addresses for a particular adapter. +// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_gateway_address_lh +type IPAdapterGatewayAddress struct { + Length uint32 + _ uint32 + Next *IPAdapterGatewayAddress + Address windows.SocketAddress + _ [4]byte +} + +// IPAdapterAddresses structure is the header node for a linked list of addresses for a particular adapter. This structure can simultaneously be used as part of a linked list of IP_ADAPTER_ADDRESSES structures. +// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_addresses_lh +// This is a modified and extended version of windows.IpAdapterAddresses. +type IPAdapterAddresses struct { + Length uint32 + IfIndex uint32 + Next *IPAdapterAddresses + adapterName *byte + FirstUnicastAddress *windows.IpAdapterUnicastAddress + FirstAnycastAddress *windows.IpAdapterAnycastAddress + FirstMulticastAddress *windows.IpAdapterMulticastAddress + FirstDNSServerAddress *windows.IpAdapterDnsServerAdapter + dnsSuffix *uint16 + description *uint16 + friendlyName *uint16 + physicalAddress [windows.MAX_ADAPTER_ADDRESS_LENGTH]byte + physicalAddressLength uint32 + Flags IPAAFlags + MTU uint32 + IfType IfType + OperStatus IfOperStatus + IPv6IfIndex uint32 + ZoneIndices [16]uint32 + FirstPrefix *windows.IpAdapterPrefix + TransmitLinkSpeed uint64 + ReceiveLinkSpeed uint64 + FirstWINSServerAddress *IPAdapterWINSServerAddress + FirstGatewayAddress *IPAdapterGatewayAddress + Ipv4Metric uint32 + Ipv6Metric uint32 + LUID LUID + DHCPv4Server windows.SocketAddress + CompartmentID uint32 + NetworkGUID windows.GUID + ConnectionType NetIfConnectionType + TunnelType TunnelType + DHCPv6Server windows.SocketAddress + dhcpv6ClientDUID [maxDHCPv6DUIDLength]byte + dhcpv6ClientDUIDLength uint32 + DHCPv6IAID uint32 + FirstDNSSuffix *IPAdapterDNSSuffix + _ [4]byte +} + +// MibIPInterfaceRow structure stores interface management information for a particular IP address family on a network interface. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_row +type MibIPInterfaceRow struct { + Family AddressFamily + _ [4]byte + InterfaceLUID LUID + InterfaceIndex uint32 + MaxReassemblySize uint32 + InterfaceIdentifier uint64 + MinRouterAdvertisementInterval uint32 + MaxRouterAdvertisementInterval uint32 + AdvertisingEnabled bool + ForwardingEnabled bool + WeakHostSend bool + WeakHostReceive bool + UseAutomaticMetric bool + UseNeighborUnreachabilityDetection bool + ManagedAddressConfigurationSupported bool + OtherStatefulConfigurationSupported bool + AdvertiseDefaultRoute bool + RouterDiscoveryBehavior RouterDiscoveryBehavior + DadTransmits uint32 + BaseReachableTime uint32 + RetransmitTime uint32 + PathMTUDiscoveryTimeout uint32 + LinkLocalAddressBehavior LinkLocalAddressBehavior + LinkLocalAddressTimeout uint32 + ZoneIndices [ScopeLevelCount]uint32 + SitePrefixLength uint32 + Metric uint32 + NLMTU uint32 + Connected bool + SupportsWakeUpPatterns bool + SupportsNeighborDiscovery bool + SupportsRouterDiscovery bool + ReachableTime uint32 + TransmitOffload OffloadRod + ReceiveOffload OffloadRod + DisableDefaultRoutes bool +} + +// mibIPInterfaceTable structure contains a table of IP interface entries. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_table +type mibIPInterfaceTable struct { + numEntries uint32 + _ [4]byte + table [anySize]MibIPInterfaceRow +} + +// MibIfRow2 structure stores information about a particular interface. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_row2 +type MibIfRow2 struct { + InterfaceLUID LUID + InterfaceIndex uint32 + InterfaceGUID windows.GUID + alias [ifMaxStringSize + 1]uint16 + description [ifMaxStringSize + 1]uint16 + physicalAddressLength uint32 + physicalAddress [ifMaxPhysAddressLength]byte + permanentPhysicalAddress [ifMaxPhysAddressLength]byte + MTU uint32 + Type IfType + TunnelType TunnelType + MediaType NdisMedium + PhysicalMediumType NdisPhysicalMedium + AccessType NetIfAccessType + DirectionType NetIfDirectionType + InterfaceAndOperStatusFlags InterfaceAndOperStatusFlags + OperStatus IfOperStatus + AdminStatus NetIfAdminStatus + MediaConnectState NetIfMediaConnectState + NetworkGUID windows.GUID + ConnectionType NetIfConnectionType + _ [4]byte + TransmitLinkSpeed uint64 + ReceiveLinkSpeed uint64 + InOctets uint64 + InUcastPkts uint64 + InNUcastPkts uint64 + InDiscards uint64 + InErrors uint64 + InUnknownProtos uint64 + InUcastOctets uint64 + InMulticastOctets uint64 + InBroadcastOctets uint64 + OutOctets uint64 + OutUcastPkts uint64 + OutNUcastPkts uint64 + OutDiscards uint64 + OutErrors uint64 + OutUcastOctets uint64 + OutMulticastOctets uint64 + OutBroadcastOctets uint64 + OutQLen uint64 +} + +// mibIfTable2 structure contains a table of logical and physical interface entries. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_table2 +type mibIfTable2 struct { + numEntries uint32 + _ [4]byte + table [anySize]MibIfRow2 +} + +// MibUnicastIPAddressRow structure stores information about a unicast IP address. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_row +type MibUnicastIPAddressRow struct { + Address RawSockaddrInet + _ [4]byte + InterfaceLUID LUID + InterfaceIndex uint32 + PrefixOrigin PrefixOrigin + SuffixOrigin SuffixOrigin + ValidLifetime uint32 + PreferredLifetime uint32 + OnLinkPrefixLength uint8 + SkipAsSource bool + DadState DadState + ScopeID uint32 + CreationTimeStamp int64 +} + +// mibUnicastIPAddressTable structure contains a table of unicast IP address entries. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_table +type mibUnicastIPAddressTable struct { + numEntries uint32 + _ [4]byte + table [anySize]MibUnicastIPAddressRow +} + +// MibAnycastIPAddressRow structure stores information about an anycast IP address. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_anycastipaddress_row +type MibAnycastIPAddressRow struct { + Address RawSockaddrInet + _ [4]byte + InterfaceLUID LUID + InterfaceIndex uint32 + ScopeID uint32 +} + +// mibAnycastIPAddressTable structure contains a table of anycast IP address entries. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-mib_anycastipaddress_table +type mibAnycastIPAddressTable struct { + numEntries uint32 + _ [4]byte + table [anySize]MibAnycastIPAddressRow +} + +// mibIPforwardTable2 structure contains a table of IP route entries. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipforward_table2 +type mibIPforwardTable2 struct { + numEntries uint32 + _ [4]byte + table [anySize]MibIPforwardRow2 +} diff --git a/winipcfg/types_64.go b/winipcfg/types_64.go new file mode 100644 index 0000000..3a1fe07 --- /dev/null +++ b/winipcfg/types_64.go @@ -0,0 +1,220 @@ +//go:build amd64 || arm64 + +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. + */ + +package winipcfg + +import ( + "golang.org/x/sys/windows" +) + +// IPAdapterWINSServerAddress structure stores a single Windows Internet Name Service (WINS) server address in a linked list of WINS server addresses for a particular adapter. +// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_wins_server_address_lh +type IPAdapterWINSServerAddress struct { + Length uint32 + _ uint32 + Next *IPAdapterWINSServerAddress + Address windows.SocketAddress +} + +// IPAdapterGatewayAddress structure stores a single gateway address in a linked list of gateway addresses for a particular adapter. +// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_gateway_address_lh +type IPAdapterGatewayAddress struct { + Length uint32 + _ uint32 + Next *IPAdapterGatewayAddress + Address windows.SocketAddress +} + +// IPAdapterAddresses structure is the header node for a linked list of addresses for a particular adapter. This structure can simultaneously be used as part of a linked list of IP_ADAPTER_ADDRESSES structures. +// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_addresses_lh +// This is a modified and extended version of windows.IpAdapterAddresses. +type IPAdapterAddresses struct { + Length uint32 + IfIndex uint32 + Next *IPAdapterAddresses + adapterName *byte + FirstUnicastAddress *windows.IpAdapterUnicastAddress + FirstAnycastAddress *windows.IpAdapterAnycastAddress + FirstMulticastAddress *windows.IpAdapterMulticastAddress + FirstDNSServerAddress *windows.IpAdapterDnsServerAdapter + dnsSuffix *uint16 + description *uint16 + friendlyName *uint16 + physicalAddress [windows.MAX_ADAPTER_ADDRESS_LENGTH]byte + physicalAddressLength uint32 + Flags IPAAFlags + MTU uint32 + IfType IfType + OperStatus IfOperStatus + IPv6IfIndex uint32 + ZoneIndices [16]uint32 + FirstPrefix *windows.IpAdapterPrefix + TransmitLinkSpeed uint64 + ReceiveLinkSpeed uint64 + FirstWINSServerAddress *IPAdapterWINSServerAddress + FirstGatewayAddress *IPAdapterGatewayAddress + Ipv4Metric uint32 + Ipv6Metric uint32 + LUID LUID + DHCPv4Server windows.SocketAddress + CompartmentID uint32 + NetworkGUID windows.GUID + ConnectionType NetIfConnectionType + TunnelType TunnelType + DHCPv6Server windows.SocketAddress + dhcpv6ClientDUID [maxDHCPv6DUIDLength]byte + dhcpv6ClientDUIDLength uint32 + DHCPv6IAID uint32 + FirstDNSSuffix *IPAdapterDNSSuffix +} + +// MibIPInterfaceRow structure stores interface management information for a particular IP address family on a network interface. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_row +type MibIPInterfaceRow struct { + Family AddressFamily + InterfaceLUID LUID + InterfaceIndex uint32 + MaxReassemblySize uint32 + InterfaceIdentifier uint64 + MinRouterAdvertisementInterval uint32 + MaxRouterAdvertisementInterval uint32 + AdvertisingEnabled bool + ForwardingEnabled bool + WeakHostSend bool + WeakHostReceive bool + UseAutomaticMetric bool + UseNeighborUnreachabilityDetection bool + ManagedAddressConfigurationSupported bool + OtherStatefulConfigurationSupported bool + AdvertiseDefaultRoute bool + RouterDiscoveryBehavior RouterDiscoveryBehavior + DadTransmits uint32 + BaseReachableTime uint32 + RetransmitTime uint32 + PathMTUDiscoveryTimeout uint32 + LinkLocalAddressBehavior LinkLocalAddressBehavior + LinkLocalAddressTimeout uint32 + ZoneIndices [ScopeLevelCount]uint32 + SitePrefixLength uint32 + Metric uint32 + NLMTU uint32 + Connected bool + SupportsWakeUpPatterns bool + SupportsNeighborDiscovery bool + SupportsRouterDiscovery bool + ReachableTime uint32 + TransmitOffload OffloadRod + ReceiveOffload OffloadRod + DisableDefaultRoutes bool +} + +// mibIPInterfaceTable structure contains a table of IP interface entries. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_table +type mibIPInterfaceTable struct { + numEntries uint32 + table [anySize]MibIPInterfaceRow +} + +// MibIfRow2 structure stores information about a particular interface. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_row2 +type MibIfRow2 struct { + InterfaceLUID LUID + InterfaceIndex uint32 + InterfaceGUID windows.GUID + alias [ifMaxStringSize + 1]uint16 + description [ifMaxStringSize + 1]uint16 + physicalAddressLength uint32 + physicalAddress [ifMaxPhysAddressLength]byte + permanentPhysicalAddress [ifMaxPhysAddressLength]byte + MTU uint32 + Type IfType + TunnelType TunnelType + MediaType NdisMedium + PhysicalMediumType NdisPhysicalMedium + AccessType NetIfAccessType + DirectionType NetIfDirectionType + InterfaceAndOperStatusFlags InterfaceAndOperStatusFlags + OperStatus IfOperStatus + AdminStatus NetIfAdminStatus + MediaConnectState NetIfMediaConnectState + NetworkGUID windows.GUID + ConnectionType NetIfConnectionType + TransmitLinkSpeed uint64 + ReceiveLinkSpeed uint64 + InOctets uint64 + InUcastPkts uint64 + InNUcastPkts uint64 + InDiscards uint64 + InErrors uint64 + InUnknownProtos uint64 + InUcastOctets uint64 + InMulticastOctets uint64 + InBroadcastOctets uint64 + OutOctets uint64 + OutUcastPkts uint64 + OutNUcastPkts uint64 + OutDiscards uint64 + OutErrors uint64 + OutUcastOctets uint64 + OutMulticastOctets uint64 + OutBroadcastOctets uint64 + OutQLen uint64 +} + +// mibIfTable2 structure contains a table of logical and physical interface entries. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_table2 +type mibIfTable2 struct { + numEntries uint32 + table [anySize]MibIfRow2 +} + +// MibUnicastIPAddressRow structure stores information about a unicast IP address. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_row +type MibUnicastIPAddressRow struct { + Address RawSockaddrInet + InterfaceLUID LUID + InterfaceIndex uint32 + PrefixOrigin PrefixOrigin + SuffixOrigin SuffixOrigin + ValidLifetime uint32 + PreferredLifetime uint32 + OnLinkPrefixLength uint8 + SkipAsSource bool + DadState DadState + ScopeID uint32 + CreationTimeStamp int64 +} + +// mibUnicastIPAddressTable structure contains a table of unicast IP address entries. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_table +type mibUnicastIPAddressTable struct { + numEntries uint32 + table [anySize]MibUnicastIPAddressRow +} + +// MibAnycastIPAddressRow structure stores information about an anycast IP address. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_anycastipaddress_row +type MibAnycastIPAddressRow struct { + Address RawSockaddrInet + InterfaceLUID LUID + InterfaceIndex uint32 + ScopeID uint32 +} + +// mibAnycastIPAddressTable structure contains a table of anycast IP address entries. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-mib_anycastipaddress_table +type mibAnycastIPAddressTable struct { + numEntries uint32 + table [anySize]MibAnycastIPAddressRow +} + +// mibIPforwardTable2 structure contains a table of IP route entries. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipforward_table2 +type mibIPforwardTable2 struct { + numEntries uint32 + table [anySize]MibIPforwardRow2 +} diff --git a/winipcfg/winipcfg.go b/winipcfg/winipcfg.go new file mode 100644 index 0000000..e24157b --- /dev/null +++ b/winipcfg/winipcfg.go @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. + */ + +package winipcfg + +import ( + "runtime" + "unsafe" + + "golang.org/x/sys/windows" +) + +// +// Common functions +// + +//sys freeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable + +// +// Interface-related functions +// + +//sys initializeIPInterfaceEntry(row *MibIPInterfaceRow) = iphlpapi.InitializeIpInterfaceEntry +//sys getIPInterfaceTable(family AddressFamily, table **mibIPInterfaceTable) (ret error) = iphlpapi.GetIpInterfaceTable +//sys getIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) = iphlpapi.GetIpInterfaceEntry +//sys setIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) = iphlpapi.SetIpInterfaceEntry +//sys getIfEntry2(row *MibIfRow2) (ret error) = iphlpapi.GetIfEntry2 +//sys getIfTable2Ex(level MibIfEntryLevel, table **mibIfTable2) (ret error) = iphlpapi.GetIfTable2Ex +//sys convertInterfaceLUIDToGUID(interfaceLUID *LUID, interfaceGUID *windows.GUID) (ret error) = iphlpapi.ConvertInterfaceLuidToGuid +//sys convertInterfaceGUIDToLUID(interfaceGUID *windows.GUID, interfaceLUID *LUID) (ret error) = iphlpapi.ConvertInterfaceGuidToLuid +//sys convertInterfaceIndexToLUID(interfaceIndex uint32, interfaceLUID *LUID) (ret error) = iphlpapi.ConvertInterfaceIndexToLuid + +// GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/iphlpapi/nf-iphlpapi-getadaptersaddresses +func GetAdaptersAddresses(family AddressFamily, flags GAAFlags) ([]*IPAdapterAddresses, error) { + var b []byte + size := uint32(15000) + + for { + b = make([]byte, size) + err := windows.GetAdaptersAddresses(uint32(family), uint32(flags), 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &size) + if err == nil { + break + } + if err != windows.ERROR_BUFFER_OVERFLOW || size <= uint32(len(b)) { + return nil, err + } + } + + result := make([]*IPAdapterAddresses, 0, uintptr(size)/unsafe.Sizeof(IPAdapterAddresses{})) + for wtiaa := (*IPAdapterAddresses)(unsafe.Pointer(&b[0])); wtiaa != nil; wtiaa = wtiaa.Next { + result = append(result, wtiaa) + } + + return result, nil +} + +// GetIPInterfaceTable function retrieves the IP interface entries on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipinterfacetable +func GetIPInterfaceTable(family AddressFamily) ([]MibIPInterfaceRow, error) { + var tab *mibIPInterfaceTable + err := getIPInterfaceTable(family, &tab) + if err != nil { + return nil, err + } + t := append(make([]MibIPInterfaceRow, 0, tab.numEntries), tab.get()...) + tab.free() + return t, nil +} + +// GetIfTable2Ex function retrieves the MIB-II interface table. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getiftable2ex +func GetIfTable2Ex(level MibIfEntryLevel) ([]MibIfRow2, error) { + var tab *mibIfTable2 + err := getIfTable2Ex(level, &tab) + if err != nil { + return nil, err + } + t := append(make([]MibIfRow2, 0, tab.numEntries), tab.get()...) + tab.free() + return t, nil +} + +// +// Unicast IP address-related functions +// + +//sys getUnicastIPAddressTable(family AddressFamily, table **mibUnicastIPAddressTable) (ret error) = iphlpapi.GetUnicastIpAddressTable +//sys initializeUnicastIPAddressEntry(row *MibUnicastIPAddressRow) = iphlpapi.InitializeUnicastIpAddressEntry +//sys getUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.GetUnicastIpAddressEntry +//sys setUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.SetUnicastIpAddressEntry +//sys createUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.CreateUnicastIpAddressEntry +//sys deleteUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.DeleteUnicastIpAddressEntry + +// GetUnicastIPAddressTable function retrieves the unicast IP address table on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getunicastipaddresstable +func GetUnicastIPAddressTable(family AddressFamily) ([]MibUnicastIPAddressRow, error) { + var tab *mibUnicastIPAddressTable + err := getUnicastIPAddressTable(family, &tab) + if err != nil { + return nil, err + } + t := append(make([]MibUnicastIPAddressRow, 0, tab.numEntries), tab.get()...) + tab.free() + return t, nil +} + +// +// Anycast IP address-related functions +// + +//sys getAnycastIPAddressTable(family AddressFamily, table **mibAnycastIPAddressTable) (ret error) = iphlpapi.GetAnycastIpAddressTable +//sys getAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) = iphlpapi.GetAnycastIpAddressEntry +//sys createAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) = iphlpapi.CreateAnycastIpAddressEntry +//sys deleteAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) = iphlpapi.DeleteAnycastIpAddressEntry + +// GetAnycastIPAddressTable function retrieves the anycast IP address table on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getanycastipaddresstable +func GetAnycastIPAddressTable(family AddressFamily) ([]MibAnycastIPAddressRow, error) { + var tab *mibAnycastIPAddressTable + err := getAnycastIPAddressTable(family, &tab) + if err != nil { + return nil, err + } + t := append(make([]MibAnycastIPAddressRow, 0, tab.numEntries), tab.get()...) + tab.free() + return t, nil +} + +// +// Routing-related functions +// + +//sys getIPForwardTable2(family AddressFamily, table **mibIPforwardTable2) (ret error) = iphlpapi.GetIpForwardTable2 +//sys initializeIPForwardEntry(route *MibIPforwardRow2) = iphlpapi.InitializeIpForwardEntry +//sys getIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.GetIpForwardEntry2 +//sys setIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.SetIpForwardEntry2 +//sys createIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.CreateIpForwardEntry2 +//sys deleteIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.DeleteIpForwardEntry2 + +// GetIPForwardTable2 function retrieves the IP route entries on the local computer. +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipforwardtable2 +func GetIPForwardTable2(family AddressFamily) ([]MibIPforwardRow2, error) { + var tab *mibIPforwardTable2 + err := getIPForwardTable2(family, &tab) + if err != nil { + return nil, err + } + t := append(make([]MibIPforwardRow2, 0, tab.numEntries), tab.get()...) + tab.free() + return t, nil +} + +// +// Notifications-related functions +// + +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-notifyipinterfacechange +//sys notifyIPInterfaceChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) = iphlpapi.NotifyIpInterfaceChange + +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-notifyunicastipaddresschange +//sys notifyUnicastIPAddressChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) = iphlpapi.NotifyUnicastIpAddressChange + +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-notifyroutechange2 +//sys notifyRouteChange2(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) = iphlpapi.NotifyRouteChange2 + +// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-cancelmibchangenotify2 +//sys cancelMibChangeNotify2(notificationHandle windows.Handle) (ret error) = iphlpapi.CancelMibChangeNotify2 + +// +// DNS-related functions +// + +//sys setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings? +//sys setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings? +//sys setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings? + +// The GUID is passed by value, not by reference, which means different +// things on different calling conventions. On amd64, this means it's +// passed by reference anyway, while on arm, arm64, and 386, it's split +// into words. +func SetInterfaceDnsSettings(guid windows.GUID, settings *DnsInterfaceSettings) error { + words := (*[4]uintptr)(unsafe.Pointer(&guid)) + switch runtime.GOARCH { + case "amd64": + return setInterfaceDnsSettingsByPtr(&guid, settings) + case "arm64": + return setInterfaceDnsSettingsByQwords(words[0], words[1], settings) + case "arm", "386": + return setInterfaceDnsSettingsByDwords(words[0], words[1], words[2], words[3], settings) + default: + panic("unknown calling convention") + } +} diff --git a/winipcfg/zwinipcfg_windows.go b/winipcfg/zwinipcfg_windows.go new file mode 100644 index 0000000..3a0d868 --- /dev/null +++ b/winipcfg/zwinipcfg_windows.go @@ -0,0 +1,350 @@ +// Code generated by 'go generate'; DO NOT EDIT. + +package winipcfg + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_EINVAL error = syscall.EINVAL +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return errERROR_EINVAL + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll") + + procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2") + procConvertInterfaceGuidToLuid = modiphlpapi.NewProc("ConvertInterfaceGuidToLuid") + procConvertInterfaceIndexToLuid = modiphlpapi.NewProc("ConvertInterfaceIndexToLuid") + procConvertInterfaceLuidToGuid = modiphlpapi.NewProc("ConvertInterfaceLuidToGuid") + procCreateAnycastIpAddressEntry = modiphlpapi.NewProc("CreateAnycastIpAddressEntry") + procCreateIpForwardEntry2 = modiphlpapi.NewProc("CreateIpForwardEntry2") + procCreateUnicastIpAddressEntry = modiphlpapi.NewProc("CreateUnicastIpAddressEntry") + procDeleteAnycastIpAddressEntry = modiphlpapi.NewProc("DeleteAnycastIpAddressEntry") + procDeleteIpForwardEntry2 = modiphlpapi.NewProc("DeleteIpForwardEntry2") + procDeleteUnicastIpAddressEntry = modiphlpapi.NewProc("DeleteUnicastIpAddressEntry") + procFreeMibTable = modiphlpapi.NewProc("FreeMibTable") + procGetAnycastIpAddressEntry = modiphlpapi.NewProc("GetAnycastIpAddressEntry") + procGetAnycastIpAddressTable = modiphlpapi.NewProc("GetAnycastIpAddressTable") + procGetIfEntry2 = modiphlpapi.NewProc("GetIfEntry2") + procGetIfTable2Ex = modiphlpapi.NewProc("GetIfTable2Ex") + procGetIpForwardEntry2 = modiphlpapi.NewProc("GetIpForwardEntry2") + procGetIpForwardTable2 = modiphlpapi.NewProc("GetIpForwardTable2") + procGetIpInterfaceEntry = modiphlpapi.NewProc("GetIpInterfaceEntry") + procGetIpInterfaceTable = modiphlpapi.NewProc("GetIpInterfaceTable") + procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry") + procGetUnicastIpAddressTable = modiphlpapi.NewProc("GetUnicastIpAddressTable") + procInitializeIpForwardEntry = modiphlpapi.NewProc("InitializeIpForwardEntry") + procInitializeIpInterfaceEntry = modiphlpapi.NewProc("InitializeIpInterfaceEntry") + procInitializeUnicastIpAddressEntry = modiphlpapi.NewProc("InitializeUnicastIpAddressEntry") + procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange") + procNotifyRouteChange2 = modiphlpapi.NewProc("NotifyRouteChange2") + procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange") + procSetInterfaceDnsSettings = modiphlpapi.NewProc("SetInterfaceDnsSettings") + procSetIpForwardEntry2 = modiphlpapi.NewProc("SetIpForwardEntry2") + procSetIpInterfaceEntry = modiphlpapi.NewProc("SetIpInterfaceEntry") + procSetUnicastIpAddressEntry = modiphlpapi.NewProc("SetUnicastIpAddressEntry") +) + +func cancelMibChangeNotify2(notificationHandle windows.Handle) (ret error) { + r0, _, _ := syscall.Syscall(procCancelMibChangeNotify2.Addr(), 1, uintptr(notificationHandle), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func convertInterfaceGUIDToLUID(interfaceGUID *windows.GUID, interfaceLUID *LUID) (ret error) { + r0, _, _ := syscall.Syscall(procConvertInterfaceGuidToLuid.Addr(), 2, uintptr(unsafe.Pointer(interfaceGUID)), uintptr(unsafe.Pointer(interfaceLUID)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func convertInterfaceIndexToLUID(interfaceIndex uint32, interfaceLUID *LUID) (ret error) { + r0, _, _ := syscall.Syscall(procConvertInterfaceIndexToLuid.Addr(), 2, uintptr(interfaceIndex), uintptr(unsafe.Pointer(interfaceLUID)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func convertInterfaceLUIDToGUID(interfaceLUID *LUID, interfaceGUID *windows.GUID) (ret error) { + r0, _, _ := syscall.Syscall(procConvertInterfaceLuidToGuid.Addr(), 2, uintptr(unsafe.Pointer(interfaceLUID)), uintptr(unsafe.Pointer(interfaceGUID)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func createAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) { + r0, _, _ := syscall.Syscall(procCreateAnycastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func createIPForwardEntry2(route *MibIPforwardRow2) (ret error) { + r0, _, _ := syscall.Syscall(procCreateIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func createUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) { + r0, _, _ := syscall.Syscall(procCreateUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func deleteAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) { + r0, _, _ := syscall.Syscall(procDeleteAnycastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func deleteIPForwardEntry2(route *MibIPforwardRow2) (ret error) { + r0, _, _ := syscall.Syscall(procDeleteIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func deleteUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) { + r0, _, _ := syscall.Syscall(procDeleteUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func freeMibTable(memory unsafe.Pointer) { + syscall.Syscall(procFreeMibTable.Addr(), 1, uintptr(memory), 0, 0) + return +} + +func getAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) { + r0, _, _ := syscall.Syscall(procGetAnycastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getAnycastIPAddressTable(family AddressFamily, table **mibAnycastIPAddressTable) (ret error) { + r0, _, _ := syscall.Syscall(procGetAnycastIpAddressTable.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getIfEntry2(row *MibIfRow2) (ret error) { + r0, _, _ := syscall.Syscall(procGetIfEntry2.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getIfTable2Ex(level MibIfEntryLevel, table **mibIfTable2) (ret error) { + r0, _, _ := syscall.Syscall(procGetIfTable2Ex.Addr(), 2, uintptr(level), uintptr(unsafe.Pointer(table)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getIPForwardEntry2(route *MibIPforwardRow2) (ret error) { + r0, _, _ := syscall.Syscall(procGetIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getIPForwardTable2(family AddressFamily, table **mibIPforwardTable2) (ret error) { + r0, _, _ := syscall.Syscall(procGetIpForwardTable2.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) { + r0, _, _ := syscall.Syscall(procGetIpInterfaceEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getIPInterfaceTable(family AddressFamily, table **mibIPInterfaceTable) (ret error) { + r0, _, _ := syscall.Syscall(procGetIpInterfaceTable.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) { + r0, _, _ := syscall.Syscall(procGetUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getUnicastIPAddressTable(family AddressFamily, table **mibUnicastIPAddressTable) (ret error) { + r0, _, _ := syscall.Syscall(procGetUnicastIpAddressTable.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func initializeIPForwardEntry(route *MibIPforwardRow2) { + syscall.Syscall(procInitializeIpForwardEntry.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0) + return +} + +func initializeIPInterfaceEntry(row *MibIPInterfaceRow) { + syscall.Syscall(procInitializeIpInterfaceEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + return +} + +func initializeUnicastIPAddressEntry(row *MibUnicastIPAddressRow) { + syscall.Syscall(procInitializeUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + return +} + +func notifyIPInterfaceChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) { + var _p0 uint32 + if initialNotification { + _p0 = 1 + } + r0, _, _ := syscall.Syscall6(procNotifyIpInterfaceChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func notifyRouteChange2(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) { + var _p0 uint32 + if initialNotification { + _p0 = 1 + } + r0, _, _ := syscall.Syscall6(procNotifyRouteChange2.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func notifyUnicastIPAddressChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) { + var _p0 uint32 + if initialNotification { + _p0 = 1 + } + r0, _, _ := syscall.Syscall6(procNotifyUnicastIpAddressChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *DnsInterfaceSettings) (ret error) { + ret = procSetInterfaceDnsSettings.Find() + if ret != nil { + return + } + r0, _, _ := syscall.Syscall6(procSetInterfaceDnsSettings.Addr(), 5, uintptr(guid1), uintptr(guid2), uintptr(guid3), uintptr(guid4), uintptr(unsafe.Pointer(settings)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *DnsInterfaceSettings) (ret error) { + ret = procSetInterfaceDnsSettings.Find() + if ret != nil { + return + } + r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 3, uintptr(guid1), uintptr(guid2), uintptr(unsafe.Pointer(settings))) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *DnsInterfaceSettings) (ret error) { + ret = procSetInterfaceDnsSettings.Find() + if ret != nil { + return + } + r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 2, uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(settings)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func setIPForwardEntry2(route *MibIPforwardRow2) (ret error) { + r0, _, _ := syscall.Syscall(procSetIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func setIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) { + r0, _, _ := syscall.Syscall(procSetIpInterfaceEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func setUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) { + r0, _, _ := syscall.Syscall(procSetUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +}