├── .gitignore ├── go.mod ├── go.sum ├── main.go ├── test ├── README.md ├── read │ ├── app │ │ └── main.go │ └── tester │ │ └── main.go └── send │ └── main.go ├── winipcfg ├── luid.go ├── mksyscall.go ├── netsh.go ├── types.go ├── types_32.go ├── types_64.go ├── winipcfg.go └── zwinipcfg_windows.go └── wintun.dll /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /.deps 3 | /.distfiles 4 | 5 | # Build Output 6 | /x86 7 | /amd64 8 | /arm 9 | /arm64 10 | 11 | # Misc 12 | /locales/*/out.gotext.json 13 | /sign.bat 14 | *.swp 15 | *.bak 16 | *.syso 17 | .idea 18 | *.ico 19 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module simpletun 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/google/gopacket v1.1.19 // indirect 7 | golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect 8 | golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect 9 | golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 // indirect 10 | golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect 11 | golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6 // indirect 12 | ) 13 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 2 | github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 3 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 4 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 5 | golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= 6 | golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 7 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 8 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 9 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 10 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 11 | golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= 12 | golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 13 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 14 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 15 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 16 | golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 h1:A9i04dxx7Cribqbs8jf3FQLogkL/CV2YN7hj9KWJCkc= 17 | golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 18 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 19 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 20 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 21 | golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY= 22 | golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= 23 | golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6 h1:kgBK1EGuTIYbwoKROmsoV0FQp08gnCcVa110A4Unqhk= 24 | golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U= 25 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "golang.org/x/net/icmp" 5 | "golang.org/x/net/ipv4" 6 | "golang.org/x/sys/windows" 7 | "golang.zx2c4.com/wireguard/tun" 8 | "log" 9 | "net/netip" 10 | "simpletun/winipcfg" 11 | ) 12 | 13 | func main() { 14 | id := &windows.GUID{ 15 | 0x0000000, 16 | 0xFFFF, 17 | 0xFFFF, 18 | [8]byte{0xFF, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}, 19 | } 20 | ifname := "MyNIC" 21 | dev, err := tun.CreateTUNWithRequestedGUID(ifname, id, 0) 22 | if err != nil { 23 | panic(err) 24 | } 25 | defer dev.Close() 26 | // 保存原始设备句柄 27 | nativeTunDevice := dev.(*tun.NativeTun) 28 | 29 | // 获取LUID用于配置网络 30 | link := winipcfg.LUID(nativeTunDevice.LUID()) 31 | 32 | ip, err := netip.ParsePrefix("10.0.0.77/24") 33 | if err != nil { 34 | panic(err) 35 | } 36 | err = link.SetIPAddresses([]netip.Prefix{ip}) 37 | if err != nil { 38 | panic(err) 39 | } 40 | 41 | n := 2048 42 | buf := make([]byte, n) 43 | 44 | for { 45 | n = 2048 46 | n, err = dev.Read(buf, 0) 47 | if err != nil { 48 | panic(err) 49 | } 50 | const ProtocolICMP = 1 51 | header, err := ipv4.ParseHeader(buf[:n]) 52 | if err != nil { 53 | continue 54 | } 55 | if header.Protocol == ProtocolICMP { 56 | log.Println("Src:", header.Src, " dst:", header.Dst) 57 | msg, _ := icmp.ParseMessage(ProtocolICMP, buf[header.Len:]) 58 | log.Println(">> ICMP:", msg.Type) 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # Wintun 性能测试 2 | 3 | ## 读性能 4 | 5 | 1. 开启Wintun虚拟网卡后设置IP, 6 | 2. 持续从虚拟网卡中读取数据并丢弃。 7 | 3. 启动UDP客户端向虚拟网卡所在网段发送数据。 8 | 4. 统计虚拟网卡每秒数据包读取数量,并计算传输速度。 9 | 10 | READ SPEED 11 | 12 | | 数据包大小 | 每秒读取数据包数量 | 每秒传输数据量 | 13 | |:------|:-------------|:---------| 14 | | 1420B | 232985 pkt/s | 310 MB/s | 15 | | 512B | 174902 pkt/s | 88 MB/s | 16 | | 128B | 172194 pkt/s | 25 MB/s | 17 | | 32B | 171812 pkt/s | 9 MB/s | 18 | 19 | 结论: 20 | 21 | - 在单个在小于1420B时数据包处理速度,约为 17W 个每秒,可以推断小数据包时传输速率固定。 22 | - 收数据包处理速度影响,单个数据包大小将影响数据传输速率,数据包越大传输速度越大。 23 | 24 | ## 写性能 25 | 26 | 1. 开启Wintun虚拟网卡后设置IP, 27 | 2. 持续向虚拟网卡写入数据。 28 | 3. 统计虚拟网卡每秒数据包写入数量,并计算传输速度。 29 | 30 | WRITE SPEED 31 | 32 | | 数据包大小 | 每秒写入数据包数量 | 每秒传输数据量 | 33 | |:------|:--------------|:----------| 34 | | 1420B | 3494478 pkt/s | 662 MB/s | 35 | | 512B | 3705535 pkt/s | 1837 MB/s | 36 | | 128B | 3826026 pkt/s | 496 MB/s | 37 | | 32B | 3714086 pkt/s | 141 MB/s | 38 | 39 | 结论: 40 | 41 | - 数据包写入速度约为 300W左右,写入速度受数据包大小影响。 42 | -------------------------------------------------------------------------------- /test/read/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "golang.org/x/sys/windows" 5 | "golang.zx2c4.com/wintun" 6 | "golang.zx2c4.com/wireguard/tun" 7 | "log" 8 | "net/netip" 9 | "simpletun/winipcfg" 10 | "sync/atomic" 11 | "time" 12 | ) 13 | 14 | func main() { 15 | id := &windows.GUID{ 16 | 0x0000000, 17 | 0xFFFF, 18 | 0xFFFF, 19 | [8]byte{0xFF, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}, 20 | } 21 | _ = wintun.Uninstall() 22 | ifname := "MyNIC" 23 | dev, err := tun.CreateTUNWithRequestedGUID(ifname, id, 0) 24 | if err != nil { 25 | panic(err) 26 | } 27 | defer dev.Close() 28 | // 保存原始设备句柄 29 | nativeTunDevice := dev.(*tun.NativeTun) 30 | 31 | // 获取LUID用于配置网络 32 | link := winipcfg.LUID(nativeTunDevice.LUID()) 33 | 34 | ip, err := netip.ParsePrefix("10.0.0.77/24") 35 | if err != nil { 36 | panic(err) 37 | } 38 | err = link.SetIPAddresses([]netip.Prefix{ip}) 39 | if err != nil { 40 | panic(err) 41 | } 42 | 43 | n := 2048 44 | buf := make([]byte, n) 45 | log.Println(">> running...") 46 | ticker := time.NewTicker(time.Second) 47 | var cnt uint32 = 0 48 | var total uint32 = 0 49 | go func() { 50 | for { 51 | <-ticker.C 52 | log.Printf(">> %6d pkt/s %6d MB/s\n", atomic.LoadUint32(&cnt), total/1024/1024) 53 | atomic.StoreUint32(&cnt, 0) 54 | atomic.StoreUint32(&total, 0) 55 | } 56 | }() 57 | for { 58 | n = 2048 59 | n, err = dev.Read(buf, 0) 60 | if err != nil { 61 | panic(err) 62 | } 63 | atomic.AddUint32(&cnt, 1) 64 | atomic.AddUint32(&total, uint32(n)) 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /test/read/tester/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "net" 6 | ) 7 | 8 | const DataSize = 32 9 | 10 | //const DataSize = 128 11 | //const DataSize = 516 12 | //const DataSize = 1420 13 | 14 | func main() { 15 | dst, err := net.ResolveUDPAddr("udp", "192.168.0.220:7878") 16 | if err != nil { 17 | panic(err) 18 | } 19 | conn, err := net.DialUDP("udp", nil, dst) 20 | if err != nil { 21 | panic(err) 22 | } 23 | buf := make([]byte, DataSize) 24 | _, _ = rand.Reader.Read(buf) 25 | for { 26 | _, err := conn.Write(buf) 27 | if err != nil { 28 | panic(err) 29 | } 30 | //fmt.Println(">> Send data") 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/send/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | "github.com/google/gopacket" 7 | "github.com/google/gopacket/layers" 8 | "golang.org/x/sys/windows" 9 | "golang.zx2c4.com/wintun" 10 | "golang.zx2c4.com/wireguard/tun" 11 | "log" 12 | "net" 13 | "net/netip" 14 | "simpletun/winipcfg" 15 | "sync/atomic" 16 | "time" 17 | ) 18 | 19 | const DataSize = 1420 20 | 21 | // const DataSize = 128 22 | // const DataSize = 512 23 | // const DataSize = 1420 24 | 25 | func main() { 26 | id := &windows.GUID{ 27 | 0x0000000, 28 | 0xFFFF, 29 | 0xFFFF, 30 | [8]byte{0xFF, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}, 31 | } 32 | _ = wintun.Uninstall() 33 | ifname := "MyNIC" 34 | dev, err := tun.CreateTUNWithRequestedGUID(ifname, id, 0) 35 | if err != nil { 36 | panic(err) 37 | } 38 | defer dev.Close() 39 | // 保存原始设备句柄 40 | nativeTunDevice := dev.(*tun.NativeTun) 41 | 42 | // 获取LUID用于配置网络 43 | link := winipcfg.LUID(nativeTunDevice.LUID()) 44 | 45 | ip, err := netip.ParsePrefix("10.0.0.77/24") 46 | if err != nil { 47 | panic(err) 48 | } 49 | err = link.SetIPAddresses([]netip.Prefix{ip}) 50 | if err != nil { 51 | panic(err) 52 | } 53 | 54 | log.Println(">> running...") 55 | ticker := time.NewTicker(time.Second) 56 | var cnt uint32 = 0 57 | var total uint32 = 0 58 | go func() { 59 | for { 60 | <-ticker.C 61 | log.Printf(">> %6d pkt/s %6d MB/s\n", atomic.LoadUint32(&cnt), total/1024/1024) 62 | atomic.StoreUint32(&cnt, 0) 63 | atomic.StoreUint32(&total, 0) 64 | } 65 | }() 66 | buf := makeData() 67 | n := 0 68 | for { 69 | n, err = dev.Write(buf, 0) 70 | if err != nil { 71 | panic(err) 72 | } 73 | 74 | if n < len(buf) { 75 | fmt.Println(">> Len !!!") 76 | } 77 | atomic.AddUint32(&cnt, 1) 78 | atomic.AddUint32(&total, uint32(n)) 79 | } 80 | 81 | } 82 | 83 | func makeData() []byte { 84 | buf := gopacket.NewSerializeBuffer() 85 | ip4 := layers.IPv4{ 86 | Version: 4, 87 | TTL: 64, 88 | Protocol: layers.IPProtocolUDP, 89 | SrcIP: net.ParseIP("10.0.0.77"), 90 | DstIP: net.ParseIP("127.0.0.1"), 91 | } 92 | u := layers.UDP{ 93 | SrcPort: 30123, 94 | DstPort: 7878, 95 | } 96 | var payload gopacket.Payload 97 | payload = make([]byte, DataSize) 98 | _, _ = rand.Reader.Read(payload) 99 | _ = gopacket.SerializeLayers(buf, gopacket.SerializeOptions{ 100 | FixLengths: true, 101 | ComputeChecksums: true, 102 | }, &ip4, &u, &payload) 103 | return buf.Bytes() 104 | } 105 | -------------------------------------------------------------------------------- /winipcfg/luid.go: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT 2 | * 3 | * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 4 | */ 5 | 6 | package winipcfg 7 | 8 | import ( 9 | "errors" 10 | "net/netip" 11 | "strings" 12 | 13 | "golang.org/x/sys/windows" 14 | ) 15 | 16 | // LUID represents a network interface. 17 | type LUID uint64 18 | 19 | // IPInterface method retrieves IP information for the specified interface on the local computer. 20 | func (luid LUID) IPInterface(family AddressFamily) (*MibIPInterfaceRow, error) { 21 | row := &MibIPInterfaceRow{} 22 | row.Init() 23 | row.InterfaceLUID = luid 24 | row.Family = family 25 | err := row.get() 26 | if err != nil { 27 | return nil, err 28 | } 29 | return row, nil 30 | } 31 | 32 | // Interface method retrieves information for the specified adapter on the local computer. 33 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getifentry2 34 | func (luid LUID) Interface() (*MibIfRow2, error) { 35 | row := &MibIfRow2{} 36 | row.InterfaceLUID = luid 37 | err := row.get() 38 | if err != nil { 39 | return nil, err 40 | } 41 | return row, nil 42 | } 43 | 44 | // GUID method converts a locally unique identifier (LUID) for a network interface to a globally unique identifier (GUID) for the interface. 45 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-convertinterfaceluidtoguid 46 | func (luid LUID) GUID() (*windows.GUID, error) { 47 | guid := &windows.GUID{} 48 | err := convertInterfaceLUIDToGUID(&luid, guid) 49 | if err != nil { 50 | return nil, err 51 | } 52 | return guid, nil 53 | } 54 | 55 | // LUIDFromGUID function converts a globally unique identifier (GUID) for a network interface to the locally unique identifier (LUID) for the interface. 56 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-convertinterfaceguidtoluid 57 | func LUIDFromGUID(guid *windows.GUID) (LUID, error) { 58 | var luid LUID 59 | err := convertInterfaceGUIDToLUID(guid, &luid) 60 | if err != nil { 61 | return 0, err 62 | } 63 | return luid, nil 64 | } 65 | 66 | // LUIDFromIndex function converts a local index for a network interface to the locally unique identifier (LUID) for the interface. 67 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-convertinterfaceindextoluid 68 | func LUIDFromIndex(index uint32) (LUID, error) { 69 | var luid LUID 70 | err := convertInterfaceIndexToLUID(index, &luid) 71 | if err != nil { 72 | return 0, err 73 | } 74 | return luid, nil 75 | } 76 | 77 | // IPAddress method returns MibUnicastIPAddressRow struct that matches to provided 'ip' argument. Corresponds to GetUnicastIpAddressEntry 78 | // (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getunicastipaddressentry) 79 | func (luid LUID) IPAddress(addr netip.Addr) (*MibUnicastIPAddressRow, error) { 80 | row := &MibUnicastIPAddressRow{InterfaceLUID: luid} 81 | 82 | err := row.Address.SetAddr(addr) 83 | if err != nil { 84 | return nil, err 85 | } 86 | 87 | err = row.get() 88 | if err != nil { 89 | return nil, err 90 | } 91 | 92 | return row, nil 93 | } 94 | 95 | // AddIPAddress method adds new unicast IP address to the interface. Corresponds to CreateUnicastIpAddressEntry function 96 | // (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry). 97 | func (luid LUID) AddIPAddress(address netip.Prefix) error { 98 | row := &MibUnicastIPAddressRow{} 99 | row.Init() 100 | row.InterfaceLUID = luid 101 | row.DadState = DadStatePreferred 102 | row.ValidLifetime = 0xffffffff 103 | row.PreferredLifetime = 0xffffffff 104 | err := row.Address.SetAddr(address.Addr()) 105 | if err != nil { 106 | return err 107 | } 108 | row.OnLinkPrefixLength = uint8(address.Bits()) 109 | return row.Create() 110 | } 111 | 112 | // AddIPAddresses method adds multiple new unicast IP addresses to the interface. Corresponds to CreateUnicastIpAddressEntry function 113 | // (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry). 114 | func (luid LUID) AddIPAddresses(addresses []netip.Prefix) error { 115 | for i := range addresses { 116 | err := luid.AddIPAddress(addresses[i]) 117 | if err != nil { 118 | return err 119 | } 120 | } 121 | return nil 122 | } 123 | 124 | // SetIPAddresses method sets new unicast IP addresses to the interface. 125 | func (luid LUID) SetIPAddresses(addresses []netip.Prefix) error { 126 | err := luid.FlushIPAddresses(windows.AF_UNSPEC) 127 | if err != nil { 128 | return err 129 | } 130 | return luid.AddIPAddresses(addresses) 131 | } 132 | 133 | // SetIPAddressesForFamily method sets new unicast IP addresses for a specific family to the interface. 134 | func (luid LUID) SetIPAddressesForFamily(family AddressFamily, addresses []netip.Prefix) error { 135 | err := luid.FlushIPAddresses(family) 136 | if err != nil { 137 | return err 138 | } 139 | for i := range addresses { 140 | if !addresses[i].Addr().Is4() && family == windows.AF_INET { 141 | continue 142 | } else if !addresses[i].Addr().Is6() && family == windows.AF_INET6 { 143 | continue 144 | } 145 | err := luid.AddIPAddress(addresses[i]) 146 | if err != nil { 147 | return err 148 | } 149 | } 150 | return nil 151 | } 152 | 153 | // DeleteIPAddress method deletes interface's unicast IP address. Corresponds to DeleteUnicastIpAddressEntry function 154 | // (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteunicastipaddressentry). 155 | func (luid LUID) DeleteIPAddress(address netip.Prefix) error { 156 | row := &MibUnicastIPAddressRow{} 157 | row.Init() 158 | row.InterfaceLUID = luid 159 | err := row.Address.SetAddr(address.Addr()) 160 | if err != nil { 161 | return err 162 | } 163 | // Note: OnLinkPrefixLength member is ignored by DeleteUnicastIpAddressEntry(). 164 | row.OnLinkPrefixLength = uint8(address.Bits()) 165 | return row.Delete() 166 | } 167 | 168 | // FlushIPAddresses method deletes all interface's unicast IP addresses. 169 | func (luid LUID) FlushIPAddresses(family AddressFamily) error { 170 | var tab *mibUnicastIPAddressTable 171 | err := getUnicastIPAddressTable(family, &tab) 172 | if err != nil { 173 | return err 174 | } 175 | t := tab.get() 176 | for i := range t { 177 | if t[i].InterfaceLUID == luid { 178 | t[i].Delete() 179 | } 180 | } 181 | tab.free() 182 | return nil 183 | } 184 | 185 | // Route method returns route determined with the input arguments. Corresponds to GetIpForwardEntry2 function 186 | // (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipforwardentry2). 187 | // NOTE: If the corresponding route isn't found, the method will return error. 188 | func (luid LUID) Route(destination netip.Prefix, nextHop netip.Addr) (*MibIPforwardRow2, error) { 189 | row := &MibIPforwardRow2{} 190 | row.Init() 191 | row.InterfaceLUID = luid 192 | row.ValidLifetime = 0xffffffff 193 | row.PreferredLifetime = 0xffffffff 194 | err := row.DestinationPrefix.SetPrefix(destination) 195 | if err != nil { 196 | return nil, err 197 | } 198 | err = row.NextHop.SetAddr(nextHop) 199 | if err != nil { 200 | return nil, err 201 | } 202 | 203 | err = row.get() 204 | if err != nil { 205 | return nil, err 206 | } 207 | return row, nil 208 | } 209 | 210 | // AddRoute method adds a route to the interface. Corresponds to CreateIpForwardEntry2 function, with added splitDefault feature. 211 | // (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createipforwardentry2) 212 | func (luid LUID) AddRoute(destination netip.Prefix, nextHop netip.Addr, metric uint32) error { 213 | row := &MibIPforwardRow2{} 214 | row.Init() 215 | row.InterfaceLUID = luid 216 | err := row.DestinationPrefix.SetPrefix(destination) 217 | if err != nil { 218 | return err 219 | } 220 | err = row.NextHop.SetAddr(nextHop) 221 | if err != nil { 222 | return err 223 | } 224 | row.Metric = metric 225 | return row.Create() 226 | } 227 | 228 | // AddRoutes method adds multiple routes to the interface. 229 | func (luid LUID) AddRoutes(routesData []*RouteData) error { 230 | for _, rd := range routesData { 231 | err := luid.AddRoute(rd.Destination, rd.NextHop, rd.Metric) 232 | if err != nil { 233 | return err 234 | } 235 | } 236 | return nil 237 | } 238 | 239 | // SetRoutes method sets (flush than add) multiple routes to the interface. 240 | func (luid LUID) SetRoutes(routesData []*RouteData) error { 241 | err := luid.FlushRoutes(windows.AF_UNSPEC) 242 | if err != nil { 243 | return err 244 | } 245 | return luid.AddRoutes(routesData) 246 | } 247 | 248 | // SetRoutesForFamily method sets (flush than add) multiple routes for a specific family to the interface. 249 | func (luid LUID) SetRoutesForFamily(family AddressFamily, routesData []*RouteData) error { 250 | err := luid.FlushRoutes(family) 251 | if err != nil { 252 | return err 253 | } 254 | for _, rd := range routesData { 255 | if !rd.Destination.Addr().Is4() && family == windows.AF_INET { 256 | continue 257 | } else if !rd.Destination.Addr().Is6() && family == windows.AF_INET6 { 258 | continue 259 | } 260 | err := luid.AddRoute(rd.Destination, rd.NextHop, rd.Metric) 261 | if err != nil { 262 | return err 263 | } 264 | } 265 | return nil 266 | } 267 | 268 | // DeleteRoute method deletes a route that matches the criteria. Corresponds to DeleteIpForwardEntry2 function 269 | // (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteipforwardentry2). 270 | func (luid LUID) DeleteRoute(destination netip.Prefix, nextHop netip.Addr) error { 271 | row := &MibIPforwardRow2{} 272 | row.Init() 273 | row.InterfaceLUID = luid 274 | err := row.DestinationPrefix.SetPrefix(destination) 275 | if err != nil { 276 | return err 277 | } 278 | err = row.NextHop.SetAddr(nextHop) 279 | if err != nil { 280 | return err 281 | } 282 | err = row.get() 283 | if err != nil { 284 | return err 285 | } 286 | return row.Delete() 287 | } 288 | 289 | // FlushRoutes method deletes all interface's routes. 290 | // It continues on failures, and returns the last error afterwards. 291 | func (luid LUID) FlushRoutes(family AddressFamily) error { 292 | var tab *mibIPforwardTable2 293 | err := getIPForwardTable2(family, &tab) 294 | if err != nil { 295 | return err 296 | } 297 | t := tab.get() 298 | for i := range t { 299 | if t[i].InterfaceLUID == luid { 300 | err2 := t[i].Delete() 301 | if err2 != nil { 302 | err = err2 303 | } 304 | } 305 | } 306 | tab.free() 307 | return err 308 | } 309 | 310 | // DNS method returns all DNS server addresses associated with the adapter. 311 | func (luid LUID) DNS() ([]netip.Addr, error) { 312 | addresses, err := GetAdaptersAddresses(windows.AF_UNSPEC, GAAFlagDefault) 313 | if err != nil { 314 | return nil, err 315 | } 316 | r := make([]netip.Addr, 0, len(addresses)) 317 | for _, addr := range addresses { 318 | if addr.LUID == luid { 319 | for dns := addr.FirstDNSServerAddress; dns != nil; dns = dns.Next { 320 | if ip := dns.Address.IP(); ip != nil { 321 | if a, ok := netip.AddrFromSlice(ip); ok { 322 | r = append(r, a) 323 | } 324 | } else { 325 | return nil, windows.ERROR_INVALID_PARAMETER 326 | } 327 | } 328 | } 329 | } 330 | return r, nil 331 | } 332 | 333 | // SetDNS method clears previous and associates new DNS servers and search domains with the adapter for a specific family. 334 | func (luid LUID) SetDNS(family AddressFamily, servers []netip.Addr, domains []string) error { 335 | if family != windows.AF_INET && family != windows.AF_INET6 { 336 | return windows.ERROR_PROTOCOL_UNREACHABLE 337 | } 338 | 339 | var filteredServers []string 340 | for _, server := range servers { 341 | if (server.Is4() && family == windows.AF_INET) || (server.Is6() && family == windows.AF_INET6) { 342 | filteredServers = append(filteredServers, server.String()) 343 | } 344 | } 345 | servers16, err := windows.UTF16PtrFromString(strings.Join(filteredServers, ",")) 346 | if err != nil { 347 | return err 348 | } 349 | domains16, err := windows.UTF16PtrFromString(strings.Join(domains, ",")) 350 | if err != nil { 351 | return err 352 | } 353 | guid, err := luid.GUID() 354 | if err != nil { 355 | return err 356 | } 357 | dnsInterfaceSettings := &DnsInterfaceSettings{ 358 | Version: DnsInterfaceSettingsVersion1, 359 | Flags: DnsInterfaceSettingsFlagNameserver | DnsInterfaceSettingsFlagSearchList, 360 | NameServer: servers16, 361 | SearchList: domains16, 362 | } 363 | if family == windows.AF_INET6 { 364 | dnsInterfaceSettings.Flags |= DnsInterfaceSettingsFlagIPv6 365 | } 366 | // For >= Windows 10 1809 367 | err = SetInterfaceDnsSettings(*guid, dnsInterfaceSettings) 368 | if err == nil || !errors.Is(err, windows.ERROR_PROC_NOT_FOUND) { 369 | return err 370 | } 371 | 372 | // For < Windows 10 1809 373 | err = luid.fallbackSetDNSForFamily(family, servers) 374 | if err != nil { 375 | return err 376 | } 377 | if len(domains) > 0 { 378 | return luid.fallbackSetDNSDomain(domains[0]) 379 | } else { 380 | return luid.fallbackSetDNSDomain("") 381 | } 382 | } 383 | 384 | // FlushDNS method clears all DNS servers associated with the adapter. 385 | func (luid LUID) FlushDNS(family AddressFamily) error { 386 | return luid.SetDNS(family, nil, nil) 387 | } 388 | -------------------------------------------------------------------------------- /winipcfg/mksyscall.go: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT 2 | * 3 | * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 4 | */ 5 | 6 | package winipcfg 7 | 8 | //go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zwinipcfg_windows.go winipcfg.go 9 | -------------------------------------------------------------------------------- /winipcfg/netsh.go: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT 2 | * 3 | * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 4 | */ 5 | 6 | package winipcfg 7 | 8 | import ( 9 | "bytes" 10 | "errors" 11 | "fmt" 12 | "io" 13 | "net/netip" 14 | "os/exec" 15 | "path/filepath" 16 | "strings" 17 | "syscall" 18 | 19 | "golang.org/x/sys/windows" 20 | "golang.org/x/sys/windows/registry" 21 | ) 22 | 23 | func runNetsh(cmds []string) error { 24 | system32, err := windows.GetSystemDirectory() 25 | if err != nil { 26 | return err 27 | } 28 | cmd := exec.Command(filepath.Join(system32, "netsh.exe")) 29 | cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 30 | 31 | stdin, err := cmd.StdinPipe() 32 | if err != nil { 33 | return fmt.Errorf("runNetsh stdin pipe - %w", err) 34 | } 35 | go func() { 36 | defer stdin.Close() 37 | io.WriteString(stdin, strings.Join(append(cmds, "exit\r\n"), "\r\n")) 38 | }() 39 | output, err := cmd.CombinedOutput() 40 | // Horrible kludges, sorry. 41 | cleaned := bytes.ReplaceAll(output, []byte{'\r', '\n'}, []byte{'\n'}) 42 | cleaned = bytes.ReplaceAll(cleaned, []byte("netsh>"), []byte{}) 43 | cleaned = bytes.ReplaceAll(cleaned, []byte("There are no Domain Name Servers (DNS) configured on this computer."), []byte{}) 44 | cleaned = bytes.TrimSpace(cleaned) 45 | if len(cleaned) != 0 && err == nil { 46 | return fmt.Errorf("netsh: %#q", string(cleaned)) 47 | } else if err != nil { 48 | return fmt.Errorf("netsh: %v: %#q", err, string(cleaned)) 49 | } 50 | return nil 51 | } 52 | 53 | const ( 54 | netshCmdTemplateFlush4 = "interface ipv4 set dnsservers name=%d source=static address=none validate=no register=both" 55 | netshCmdTemplateFlush6 = "interface ipv6 set dnsservers name=%d source=static address=none validate=no register=both" 56 | netshCmdTemplateAdd4 = "interface ipv4 add dnsservers name=%d address=%s validate=no" 57 | netshCmdTemplateAdd6 = "interface ipv6 add dnsservers name=%d address=%s validate=no" 58 | ) 59 | 60 | func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []netip.Addr) error { 61 | var templateFlush string 62 | if family == windows.AF_INET { 63 | templateFlush = netshCmdTemplateFlush4 64 | } else if family == windows.AF_INET6 { 65 | templateFlush = netshCmdTemplateFlush6 66 | } 67 | 68 | cmds := make([]string, 0, 1+len(dnses)) 69 | ipif, err := luid.IPInterface(family) 70 | if err != nil { 71 | return err 72 | } 73 | cmds = append(cmds, fmt.Sprintf(templateFlush, ipif.InterfaceIndex)) 74 | for i := 0; i < len(dnses); i++ { 75 | if dnses[i].Is4() && family == windows.AF_INET { 76 | cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd4, ipif.InterfaceIndex, dnses[i].String())) 77 | } else if dnses[i].Is6() && family == windows.AF_INET6 { 78 | cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd6, ipif.InterfaceIndex, dnses[i].String())) 79 | } 80 | } 81 | return runNetsh(cmds) 82 | } 83 | 84 | func (luid LUID) fallbackSetDNSDomain(domain string) error { 85 | guid, err := luid.GUID() 86 | if err != nil { 87 | return fmt.Errorf("Error converting luid to guid: %w", err) 88 | } 89 | key, err := registry.OpenKey(registry.LOCAL_MACHINE, fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters\\%v", guid), registry.QUERY_VALUE) 90 | if err != nil { 91 | return fmt.Errorf("Error opening adapter-specific TCP/IP network registry key: %w", err) 92 | } 93 | paths, _, err := key.GetStringsValue("IpConfig") 94 | key.Close() 95 | if err != nil { 96 | return fmt.Errorf("Error reading IpConfig registry key: %w", err) 97 | } 98 | if len(paths) == 0 { 99 | return errors.New("No TCP/IP interfaces found on adapter") 100 | } 101 | key, err = registry.OpenKey(registry.LOCAL_MACHINE, fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\%s", paths[0]), registry.SET_VALUE) 102 | if err != nil { 103 | return fmt.Errorf("Unable to open TCP/IP network registry key: %w", err) 104 | } 105 | err = key.SetStringValue("Domain", domain) 106 | key.Close() 107 | return err 108 | } 109 | -------------------------------------------------------------------------------- /winipcfg/types.go: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT 2 | * 3 | * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 4 | */ 5 | 6 | package winipcfg 7 | 8 | import ( 9 | "encoding/binary" 10 | "fmt" 11 | "net/netip" 12 | "strconv" 13 | "unsafe" 14 | 15 | "golang.org/x/sys/windows" 16 | ) 17 | 18 | const ( 19 | anySize = 1 20 | maxDNSSuffixStringLength = 256 21 | maxDHCPv6DUIDLength = 130 22 | ifMaxStringSize = 256 23 | ifMaxPhysAddressLength = 32 24 | ) 25 | 26 | // AddressFamily enumeration specifies protocol family and is one of the windows.AF_* constants. 27 | type AddressFamily uint16 28 | 29 | // IPAAFlags enumeration describes adapter addresses flags 30 | // https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_addresses_lh 31 | type IPAAFlags uint32 32 | 33 | const ( 34 | IPAAFlagDdnsEnabled IPAAFlags = 1 << iota 35 | IPAAFlagRegisterAdapterSuffix 36 | IPAAFlagDhcpv4Enabled 37 | IPAAFlagReceiveOnly 38 | IPAAFlagNoMulticast 39 | IPAAFlagIpv6OtherStatefulConfig 40 | IPAAFlagNetbiosOverTcpipEnabled 41 | IPAAFlagIpv4Enabled 42 | IPAAFlagIpv6Enabled 43 | IPAAFlagIpv6ManagedAddressConfigurationSupported 44 | ) 45 | 46 | // IfOperStatus enumeration specifies the operational status of an interface. 47 | // https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-if_oper_status 48 | type IfOperStatus uint32 49 | 50 | const ( 51 | IfOperStatusUp IfOperStatus = iota + 1 52 | IfOperStatusDown 53 | IfOperStatusTesting 54 | IfOperStatusUnknown 55 | IfOperStatusDormant 56 | IfOperStatusNotPresent 57 | IfOperStatusLowerLayerDown 58 | ) 59 | 60 | // IfType enumeration specifies interface type. 61 | type IfType uint32 62 | 63 | const ( 64 | IfTypeOther IfType = 1 // None of the below 65 | IfTypeRegular1822 = 2 66 | IfTypeHdh1822 = 3 67 | IfTypeDdnX25 = 4 68 | IfTypeRfc877X25 = 5 69 | IfTypeEthernetCSMACD = 6 70 | IfTypeISO88023CSMACD = 7 71 | IfTypeISO88024Tokenbus = 8 72 | IfTypeISO88025Tokenring = 9 73 | IfTypeISO88026Man = 10 74 | IfTypeStarlan = 11 75 | IfTypeProteon10Mbit = 12 76 | IfTypeProteon80Mbit = 13 77 | IfTypeHyperchannel = 14 78 | IfTypeFddi = 15 79 | IfTypeLapB = 16 80 | IfTypeSdlc = 17 81 | IfTypeDs1 = 18 // DS1-MIB 82 | IfTypeE1 = 19 // Obsolete; see DS1-MIB 83 | IfTypeBasicISDN = 20 84 | IfTypePrimaryISDN = 21 85 | IfTypePropPoint2PointSerial = 22 // proprietary serial 86 | IfTypePPP = 23 87 | IfTypeSoftwareLoopback = 24 88 | IfTypeEon = 25 // CLNP over IP 89 | IfTypeEthernet3Mbit = 26 90 | IfTypeNsip = 27 // XNS over IP 91 | IfTypeSlip = 28 // Generic Slip 92 | IfTypeUltra = 29 // ULTRA Technologies 93 | IfTypeDs3 = 30 // DS3-MIB 94 | IfTypeSip = 31 // SMDS, coffee 95 | IfTypeFramerelay = 32 // DTE only 96 | IfTypeRs232 = 33 97 | IfTypePara = 34 // Parallel port 98 | IfTypeArcnet = 35 99 | IfTypeArcnetPlus = 36 100 | IfTypeAtm = 37 // ATM cells 101 | IfTypeMioX25 = 38 102 | IfTypeSonet = 39 // SONET or SDH 103 | IfTypeX25Ple = 40 104 | IfTypeIso88022LLC = 41 105 | IfTypeLocaltalk = 42 106 | IfTypeSmdsDxi = 43 107 | IfTypeFramerelayService = 44 // FRNETSERV-MIB 108 | IfTypeV35 = 45 109 | IfTypeHssi = 46 110 | IfTypeHippi = 47 111 | IfTypeModem = 48 // Generic Modem 112 | IfTypeAal5 = 49 // AAL5 over ATM 113 | IfTypeSonetPath = 50 114 | IfTypeSonetVt = 51 115 | IfTypeSmdsIcip = 52 // SMDS InterCarrier Interface 116 | IfTypePropVirtual = 53 // Proprietary virtual/internal 117 | IfTypePropMultiplexor = 54 // Proprietary multiplexing 118 | IfTypeIEEE80212 = 55 // 100BaseVG 119 | IfTypeFibrechannel = 56 120 | IfTypeHippiinterface = 57 121 | IfTypeFramerelayInterconnect = 58 // Obsolete, use 32 or 44 122 | IfTypeAflane8023 = 59 // ATM Emulated LAN for 802.3 123 | IfTypeAflane8025 = 60 // ATM Emulated LAN for 802.5 124 | IfTypeCctemul = 61 // ATM Emulated circuit 125 | IfTypeFastether = 62 // Fast Ethernet (100BaseT) 126 | IfTypeISDN = 63 // ISDN and X.25 127 | IfTypeV11 = 64 // CCITT V.11/X.21 128 | IfTypeV36 = 65 // CCITT V.36 129 | IfTypeG703_64k = 66 // CCITT G703 at 64Kbps 130 | IfTypeG703_2mb = 67 // Obsolete; see DS1-MIB 131 | IfTypeQllc = 68 // SNA QLLC 132 | IfTypeFastetherFX = 69 // Fast Ethernet (100BaseFX) 133 | IfTypeChannel = 70 134 | IfTypeIEEE80211 = 71 // Radio spread spectrum 135 | IfTypeIBM370parchan = 72 // IBM System 360/370 OEMI Channel 136 | IfTypeEscon = 73 // IBM Enterprise Systems Connection 137 | IfTypeDlsw = 74 // Data Link Switching 138 | IfTypeISDNS = 75 // ISDN S/T interface 139 | IfTypeISDNU = 76 // ISDN U interface 140 | IfTypeLapD = 77 // Link Access Protocol D 141 | IfTypeIpswitch = 78 // IP Switching Objects 142 | IfTypeRsrb = 79 // Remote Source Route Bridging 143 | IfTypeAtmLogical = 80 // ATM Logical Port 144 | IfTypeDs0 = 81 // Digital Signal Level 0 145 | IfTypeDs0Bundle = 82 // Group of ds0s on the same ds1 146 | IfTypeBsc = 83 // Bisynchronous Protocol 147 | IfTypeAsync = 84 // Asynchronous Protocol 148 | IfTypeCnr = 85 // Combat Net Radio 149 | IfTypeIso88025rDtr = 86 // ISO 802.5r DTR 150 | IfTypeEplrs = 87 // Ext Pos Loc Report Sys 151 | IfTypeArap = 88 // Appletalk Remote Access Protocol 152 | IfTypePropCnls = 89 // Proprietary Connectionless Proto 153 | IfTypeHostpad = 90 // CCITT-ITU X.29 PAD Protocol 154 | IfTypeTermpad = 91 // CCITT-ITU X.3 PAD Facility 155 | IfTypeFramerelayMpi = 92 // Multiproto Interconnect over FR 156 | IfTypeX213 = 93 // CCITT-ITU X213 157 | IfTypeAdsl = 94 // Asymmetric Digital Subscrbr Loop 158 | IfTypeRadsl = 95 // Rate-Adapt Digital Subscrbr Loop 159 | IfTypeSdsl = 96 // Symmetric Digital Subscriber Loop 160 | IfTypeVdsl = 97 // Very H-Speed Digital Subscrb Loop 161 | IfTypeIso88025Crfprint = 98 // ISO 802.5 CRFP 162 | IfTypeMyrinet = 99 // Myricom Myrinet 163 | IfTypeVoiceEm = 100 // Voice recEive and transMit 164 | IfTypeVoiceFxo = 101 // Voice Foreign Exchange Office 165 | IfTypeVoiceFxs = 102 // Voice Foreign Exchange Station 166 | IfTypeVoiceEncap = 103 // Voice encapsulation 167 | IfTypeVoiceOverip = 104 // Voice over IP encapsulation 168 | IfTypeAtmDxi = 105 // ATM DXI 169 | IfTypeAtmFuni = 106 // ATM FUNI 170 | IfTypeAtmIma = 107 // ATM IMA 171 | IfTypePPPmultilinkbundle = 108 // PPP Multilink Bundle 172 | IfTypeIpoverCdlc = 109 // IBM ipOverCdlc 173 | IfTypeIpoverClaw = 110 // IBM Common Link Access to Workstn 174 | IfTypeStacktostack = 111 // IBM stackToStack 175 | IfTypeVirtualipaddress = 112 // IBM VIPA 176 | IfTypeMpc = 113 // IBM multi-proto channel support 177 | IfTypeIpoverAtm = 114 // IBM ipOverAtm 178 | IfTypeIso88025Fiber = 115 // ISO 802.5j Fiber Token Ring 179 | IfTypeTdlc = 116 // IBM twinaxial data link control 180 | IfTypeGigabitethernet = 117 181 | IfTypeHdlc = 118 182 | IfTypeLapF = 119 183 | IfTypeV37 = 120 184 | IfTypeX25Mlp = 121 // Multi-Link Protocol 185 | IfTypeX25Huntgroup = 122 // X.25 Hunt Group 186 | IfTypeTransphdlc = 123 187 | IfTypeInterleave = 124 // Interleave channel 188 | IfTypeFast = 125 // Fast channel 189 | IfTypeIP = 126 // IP (for APPN HPR in IP networks) 190 | IfTypeDocscableMaclayer = 127 // CATV Mac Layer 191 | IfTypeDocscableDownstream = 128 // CATV Downstream interface 192 | IfTypeDocscableUpstream = 129 // CATV Upstream interface 193 | IfTypeA12mppswitch = 130 // Avalon Parallel Processor 194 | IfTypeTunnel = 131 // Encapsulation interface 195 | IfTypeCoffee = 132 // Coffee pot 196 | IfTypeCes = 133 // Circuit Emulation Service 197 | IfTypeAtmSubinterface = 134 // ATM Sub Interface 198 | IfTypeL2Vlan = 135 // Layer 2 Virtual LAN using 802.1Q 199 | IfTypeL3Ipvlan = 136 // Layer 3 Virtual LAN using IP 200 | IfTypeL3Ipxvlan = 137 // Layer 3 Virtual LAN using IPX 201 | IfTypeDigitalpowerline = 138 // IP over Power Lines 202 | IfTypeMediamailoverip = 139 // Multimedia Mail over IP 203 | IfTypeDtm = 140 // Dynamic syncronous Transfer Mode 204 | IfTypeDcn = 141 // Data Communications Network 205 | IfTypeIpforward = 142 // IP Forwarding Interface 206 | IfTypeMsdsl = 143 // Multi-rate Symmetric DSL 207 | IfTypeIEEE1394 = 144 // IEEE1394 High Perf Serial Bus 208 | IfTypeIfGsn = 145 209 | IfTypeDvbrccMaclayer = 146 210 | IfTypeDvbrccDownstream = 147 211 | IfTypeDvbrccUpstream = 148 212 | IfTypeAtmVirtual = 149 213 | IfTypeMplsTunnel = 150 214 | IfTypeSrp = 151 215 | IfTypeVoiceoveratm = 152 216 | IfTypeVoiceoverframerelay = 153 217 | IfTypeIdsl = 154 218 | IfTypeCompositelink = 155 219 | IfTypeSs7Siglink = 156 220 | IfTypePropWirelessP2P = 157 221 | IfTypeFrForward = 158 222 | IfTypeRfc1483 = 159 223 | IfTypeUsb = 160 224 | IfTypeIEEE8023adLag = 161 225 | IfTypeBgpPolicyAccounting = 162 226 | IfTypeFrf16MfrBundle = 163 227 | IfTypeH323Gatekeeper = 164 228 | IfTypeH323Proxy = 165 229 | IfTypeMpls = 166 230 | IfTypeMfSiglink = 167 231 | IfTypeHdsl2 = 168 232 | IfTypeShdsl = 169 233 | IfTypeDs1Fdl = 170 234 | IfTypePos = 171 235 | IfTypeDvbAsiIn = 172 236 | IfTypeDvbAsiOut = 173 237 | IfTypePlc = 174 238 | IfTypeNfas = 175 239 | IfTypeTr008 = 176 240 | IfTypeGr303Rdt = 177 241 | IfTypeGr303Idt = 178 242 | IfTypeIsup = 179 243 | IfTypePropDocsWirelessMaclayer = 180 244 | IfTypePropDocsWirelessDownstream = 181 245 | IfTypePropDocsWirelessUpstream = 182 246 | IfTypeHiperlan2 = 183 247 | IfTypePropBwaP2MP = 184 248 | IfTypeSonetOverheadChannel = 185 249 | IfTypeDigitalWrapperOverheadChannel = 186 250 | IfTypeAal2 = 187 251 | IfTypeRadioMac = 188 252 | IfTypeAtmRadio = 189 253 | IfTypeImt = 190 254 | IfTypeMvl = 191 255 | IfTypeReachDsl = 192 256 | IfTypeFrDlciEndpt = 193 257 | IfTypeAtmVciEndpt = 194 258 | IfTypeOpticalChannel = 195 259 | IfTypeOpticalTransport = 196 260 | IfTypeIEEE80216Wman = 237 261 | IfTypeWwanpp = 243 // WWAN devices based on GSM technology 262 | IfTypeWwanpp2 = 244 // WWAN devices based on CDMA technology 263 | IfTypeIEEE802154 = 259 // IEEE 802.15.4 WPAN interface 264 | IfTypeXboxWireless = 281 265 | ) 266 | 267 | // MibIfEntryLevel enumeration specifies level of interface information to retrieve in GetIfTable2Ex function call. 268 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getifentry2ex 269 | type MibIfEntryLevel uint32 270 | 271 | const ( 272 | MibIfEntryNormal MibIfEntryLevel = 0 273 | MibIfEntryNormalWithoutStatistics = 2 274 | ) 275 | 276 | // NdisMedium enumeration type identifies the medium types that NDIS drivers support. 277 | // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddndis/ne-ntddndis-_ndis_medium 278 | type NdisMedium uint32 279 | 280 | const ( 281 | NdisMedium802_3 NdisMedium = iota 282 | NdisMedium802_5 283 | NdisMediumFddi 284 | NdisMediumWan 285 | NdisMediumLocalTalk 286 | NdisMediumDix // defined for convenience, not a real medium 287 | NdisMediumArcnetRaw 288 | NdisMediumArcnet878_2 289 | NdisMediumAtm 290 | NdisMediumWirelessWan 291 | NdisMediumIrda 292 | NdisMediumBpc 293 | NdisMediumCoWan 294 | NdisMedium1394 295 | NdisMediumInfiniBand 296 | NdisMediumTunnel 297 | NdisMediumNative802_11 298 | NdisMediumLoopback 299 | NdisMediumWiMAX 300 | NdisMediumIP 301 | NdisMediumMax 302 | ) 303 | 304 | // NdisPhysicalMedium describes NDIS physical medium type. 305 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_row2 306 | type NdisPhysicalMedium uint32 307 | 308 | const ( 309 | NdisPhysicalMediumUnspecified NdisPhysicalMedium = iota 310 | NdisPhysicalMediumWirelessLan 311 | NdisPhysicalMediumCableModem 312 | NdisPhysicalMediumPhoneLine 313 | NdisPhysicalMediumPowerLine 314 | NdisPhysicalMediumDSL // includes ADSL and UADSL (G.Lite) 315 | NdisPhysicalMediumFibreChannel 316 | NdisPhysicalMedium1394 317 | NdisPhysicalMediumWirelessWan 318 | NdisPhysicalMediumNative802_11 319 | NdisPhysicalMediumBluetooth 320 | NdisPhysicalMediumInfiniband 321 | NdisPhysicalMediumWiMax 322 | NdisPhysicalMediumUWB 323 | NdisPhysicalMedium802_3 324 | NdisPhysicalMedium802_5 325 | NdisPhysicalMediumIrda 326 | NdisPhysicalMediumWiredWAN 327 | NdisPhysicalMediumWiredCoWan 328 | NdisPhysicalMediumOther 329 | NdisPhysicalMediumNative802_15_4 330 | NdisPhysicalMediumMax 331 | ) 332 | 333 | // NetIfAccessType enumeration type specifies the NDIS network interface access type. 334 | // https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-_net_if_access_type 335 | type NetIfAccessType uint32 336 | 337 | const ( 338 | NetIfAccessLoopback NetIfAccessType = iota + 1 339 | NetIfAccessBroadcast 340 | NetIfAccessPointToPoint 341 | NetIfAccessPointToMultiPoint 342 | NetIfAccessMax 343 | ) 344 | 345 | // NetIfAdminStatus enumeration type specifies the NDIS network interface administrative status, as described in RFC 2863. 346 | // https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-net_if_admin_status 347 | type NetIfAdminStatus uint32 348 | 349 | const ( 350 | NetIfAdminStatusUp NetIfAdminStatus = iota + 1 351 | NetIfAdminStatusDown 352 | NetIfAdminStatusTesting 353 | ) 354 | 355 | // NetIfConnectionType enumeration type specifies the NDIS network interface connection type. 356 | // https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-_net_if_connection_type 357 | type NetIfConnectionType uint32 358 | 359 | const ( 360 | NetIfConnectionDedicated NetIfConnectionType = iota + 1 361 | NetIfConnectionPassive 362 | NetIfConnectionDemand 363 | NetIfConnectionMaximum 364 | ) 365 | 366 | // NetIfDirectionType enumeration type specifies the NDIS network interface direction type. 367 | // https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-net_if_direction_type 368 | type NetIfDirectionType uint32 369 | 370 | const ( 371 | NetIfDirectionSendReceive NetIfDirectionType = iota 372 | NetIfDirectionSendOnly 373 | NetIfDirectionReceiveOnly 374 | NetIfDirectionMaximum 375 | ) 376 | 377 | // NetIfMediaConnectState enumeration type specifies the NDIS network interface connection state. 378 | // https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-_net_if_media_connect_state 379 | type NetIfMediaConnectState uint32 380 | 381 | const ( 382 | MediaConnectStateUnknown NetIfMediaConnectState = iota 383 | MediaConnectStateConnected 384 | MediaConnectStateDisconnected 385 | ) 386 | 387 | // DadState enumeration specifies information about the duplicate address detection (DAD) state for an IPv4 or IPv6 address. 388 | // https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-nl_dad_state 389 | type DadState uint32 390 | 391 | const ( 392 | DadStateInvalid DadState = iota 393 | DadStateTentative 394 | DadStateDuplicate 395 | DadStateDeprecated 396 | DadStatePreferred 397 | ) 398 | 399 | // PrefixOrigin enumeration specifies the origin of an IPv4 or IPv6 address prefix, and is used with the IP_ADAPTER_UNICAST_ADDRESS structure. 400 | // https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-nl_prefix_origin 401 | type PrefixOrigin uint32 402 | 403 | const ( 404 | PrefixOriginOther PrefixOrigin = iota 405 | PrefixOriginManual 406 | PrefixOriginWellKnown 407 | PrefixOriginDHCP 408 | PrefixOriginRouterAdvertisement 409 | PrefixOriginUnchanged = 1 << 4 410 | ) 411 | 412 | // LinkLocalAddressBehavior enumeration type defines the link local address behavior. 413 | // https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-_nl_link_local_address_behavior 414 | type LinkLocalAddressBehavior int32 415 | 416 | const ( 417 | LinkLocalAddressAlwaysOff LinkLocalAddressBehavior = iota // Never use link locals. 418 | LinkLocalAddressDelayed // Use link locals only if no other addresses. (default for IPv4). Legacy mapping: IPAutoconfigurationEnabled. 419 | LinkLocalAddressAlwaysOn // Always use link locals (default for IPv6). 420 | LinkLocalAddressUnchanged = -1 421 | ) 422 | 423 | // OffloadRod enumeration specifies a set of flags that indicate the offload capabilities for an IP interface. 424 | // https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ns-nldef-_nl_interface_offload_rod 425 | type OffloadRod uint8 426 | 427 | const ( 428 | ChecksumSupported OffloadRod = 1 << iota 429 | OptionsSupported 430 | DatagramChecksumSupported 431 | StreamChecksumSupported 432 | StreamOptionsSupported 433 | FastPathCompatible 434 | LargeSendOffloadSupported 435 | GiantSendOffloadSupported 436 | ) 437 | 438 | // RouteOrigin enumeration type defines the origin of the IP route. 439 | // https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-nl_route_origin 440 | type RouteOrigin uint32 441 | 442 | const ( 443 | RouteOriginManual RouteOrigin = iota 444 | RouteOriginWellKnown 445 | RouteOriginDHCP 446 | RouteOriginRouterAdvertisement 447 | RouteOrigin6to4 448 | ) 449 | 450 | // RouteProtocol enumeration type defines the routing mechanism that an IP route was added with, as described in RFC 4292. 451 | // https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-nl_route_protocol 452 | type RouteProtocol uint32 453 | 454 | const ( 455 | RouteProtocolOther RouteProtocol = iota + 1 456 | RouteProtocolLocal 457 | RouteProtocolNetMgmt 458 | RouteProtocolIcmp 459 | RouteProtocolEgp 460 | RouteProtocolGgp 461 | RouteProtocolHello 462 | RouteProtocolRip 463 | RouteProtocolIsIs 464 | RouteProtocolEsIs 465 | RouteProtocolCisco 466 | RouteProtocolBbn 467 | RouteProtocolOspf 468 | RouteProtocolBgp 469 | RouteProtocolIdpr 470 | RouteProtocolEigrp 471 | RouteProtocolDvmrp 472 | RouteProtocolRpl 473 | RouteProtocolDHCP 474 | RouteProtocolNTAutostatic = 10002 475 | RouteProtocolNTStatic = 10006 476 | RouteProtocolNTStaticNonDOD = 10007 477 | ) 478 | 479 | // RouterDiscoveryBehavior enumeration type defines the router discovery behavior, as described in RFC 2461. 480 | // https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-_nl_router_discovery_behavior 481 | type RouterDiscoveryBehavior int32 482 | 483 | const ( 484 | RouterDiscoveryDisabled RouterDiscoveryBehavior = iota 485 | RouterDiscoveryEnabled 486 | RouterDiscoveryDHCP 487 | RouterDiscoveryUnchanged = -1 488 | ) 489 | 490 | // SuffixOrigin enumeration specifies the origin of an IPv4 or IPv6 address suffix, and is used with the IP_ADAPTER_UNICAST_ADDRESS structure. 491 | // https://docs.microsoft.com/en-us/windows/desktop/api/nldef/ne-nldef-nl_suffix_origin 492 | type SuffixOrigin uint32 493 | 494 | const ( 495 | SuffixOriginOther SuffixOrigin = iota 496 | SuffixOriginManual 497 | SuffixOriginWellKnown 498 | SuffixOriginDHCP 499 | SuffixOriginLinkLayerAddress 500 | SuffixOriginRandom 501 | SuffixOriginUnchanged = 1 << 4 502 | ) 503 | 504 | // MibNotificationType enumeration defines the notification type passed to a callback function when a notification occurs. 505 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ne-netioapi-_mib_notification_type 506 | type MibNotificationType uint32 507 | 508 | const ( 509 | MibParameterNotification MibNotificationType = iota // Parameter change 510 | MibAddInstance // Addition 511 | MibDeleteInstance // Deletion 512 | MibInitialNotification // Initial notification 513 | ) 514 | 515 | type ChangeCallback interface { 516 | Unregister() error 517 | } 518 | 519 | // TunnelType enumeration type defines the encapsulation method used by a tunnel, as described by the Internet Assigned Names Authority (IANA). 520 | // https://docs.microsoft.com/en-us/windows/desktop/api/ifdef/ne-ifdef-tunnel_type 521 | type TunnelType uint32 522 | 523 | const ( 524 | TunnelTypeNone TunnelType = 0 525 | TunnelTypeOther = 1 526 | TunnelTypeDirect = 2 527 | TunnelType6to4 = 11 528 | TunnelTypeIsatap = 13 529 | TunnelTypeTeredo = 14 530 | TunnelTypeIPHTTPS = 15 531 | ) 532 | 533 | // InterfaceAndOperStatusFlags enumeration type defines interface and operation flags 534 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_row2 535 | type InterfaceAndOperStatusFlags uint8 536 | 537 | const ( 538 | IAOSFHardwareInterface InterfaceAndOperStatusFlags = 1 << iota 539 | IAOSFFilterInterface 540 | IAOSFConnectorPresent 541 | IAOSFNotAuthenticated 542 | IAOSFNotMediaConnected 543 | IAOSFPaused 544 | IAOSFLowPower 545 | IAOSFEndPointInterface 546 | ) 547 | 548 | // GAAFlags enumeration defines flags used in GetAdaptersAddresses calls 549 | // https://docs.microsoft.com/en-us/windows/desktop/api/iphlpapi/nf-iphlpapi-getadaptersaddresses 550 | type GAAFlags uint32 551 | 552 | const ( 553 | GAAFlagSkipUnicast GAAFlags = 1 << iota 554 | GAAFlagSkipAnycast 555 | GAAFlagSkipMulticast 556 | GAAFlagSkipDNSServer 557 | GAAFlagIncludePrefix 558 | GAAFlagSkipFriendlyName 559 | GAAFlagIncludeWinsInfo 560 | GAAFlagIncludeGateways 561 | GAAFlagIncludeAllInterfaces 562 | GAAFlagIncludeAllCompartments 563 | GAAFlagIncludeTunnelBindingOrder 564 | GAAFlagSkipDNSInfo 565 | 566 | GAAFlagDefault GAAFlags = 0 567 | GAAFlagSkipAll = GAAFlagSkipUnicast | GAAFlagSkipAnycast | GAAFlagSkipMulticast | GAAFlagSkipDNSServer | GAAFlagSkipFriendlyName | GAAFlagSkipDNSInfo 568 | GAAFlagIncludeAll = GAAFlagIncludePrefix | GAAFlagIncludeWinsInfo | GAAFlagIncludeGateways | GAAFlagIncludeAllInterfaces | GAAFlagIncludeAllCompartments | GAAFlagIncludeTunnelBindingOrder 569 | ) 570 | 571 | // ScopeLevel enumeration is used with the IP_ADAPTER_ADDRESSES structure to identify scope levels for IPv6 addresses. 572 | // https://docs.microsoft.com/en-us/windows/desktop/api/ws2def/ne-ws2def-scope_level 573 | type ScopeLevel uint32 574 | 575 | const ( 576 | ScopeLevelInterface ScopeLevel = 1 577 | ScopeLevelLink = 2 578 | ScopeLevelSubnet = 3 579 | ScopeLevelAdmin = 4 580 | ScopeLevelSite = 5 581 | ScopeLevelOrganization = 8 582 | ScopeLevelGlobal = 14 583 | ScopeLevelCount = 16 584 | ) 585 | 586 | // RouteData structure describes a route to add 587 | type RouteData struct { 588 | Destination netip.Prefix 589 | NextHop netip.Addr 590 | Metric uint32 591 | } 592 | 593 | func (routeData *RouteData) String() string { 594 | return fmt.Sprintf("%+v", *routeData) 595 | } 596 | 597 | // IPAdapterDNSSuffix structure stores a DNS suffix in a linked list of DNS suffixes for a particular adapter. 598 | // https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_dns_suffix 599 | type IPAdapterDNSSuffix struct { 600 | Next *IPAdapterDNSSuffix 601 | str [maxDNSSuffixStringLength]uint16 602 | } 603 | 604 | // String method returns the DNS suffix for this DNS suffix entry. 605 | func (obj *IPAdapterDNSSuffix) String() string { 606 | return windows.UTF16ToString(obj.str[:]) 607 | } 608 | 609 | // AdapterName method returns the name of the adapter with which these addresses are associated. 610 | // Unlike an adapter's friendly name, the adapter name returned by AdapterName is permanent and cannot be modified by the user. 611 | func (addr *IPAdapterAddresses) AdapterName() string { 612 | return windows.BytePtrToString(addr.adapterName) 613 | } 614 | 615 | // DNSSuffix method returns adapter DNS suffix associated with this adapter. 616 | func (addr *IPAdapterAddresses) DNSSuffix() string { 617 | if addr.dnsSuffix == nil { 618 | return "" 619 | } 620 | return windows.UTF16PtrToString(addr.dnsSuffix) 621 | } 622 | 623 | // Description method returns description for the adapter. 624 | func (addr *IPAdapterAddresses) Description() string { 625 | if addr.description == nil { 626 | return "" 627 | } 628 | return windows.UTF16PtrToString(addr.description) 629 | } 630 | 631 | // FriendlyName method returns a user-friendly name for the adapter. For example: "Local Area Connection 1." 632 | // This name appears in contexts such as the ipconfig command line program and the Connection folder. 633 | func (addr *IPAdapterAddresses) FriendlyName() string { 634 | if addr.friendlyName == nil { 635 | return "" 636 | } 637 | return windows.UTF16PtrToString(addr.friendlyName) 638 | } 639 | 640 | // PhysicalAddress method returns the Media Access Control (MAC) address for the adapter. 641 | // For example, on an Ethernet network this member would specify the Ethernet hardware address. 642 | func (addr *IPAdapterAddresses) PhysicalAddress() []byte { 643 | return addr.physicalAddress[:addr.physicalAddressLength] 644 | } 645 | 646 | // DHCPv6ClientDUID method returns the DHCP unique identifier (DUID) for the DHCPv6 client. 647 | // This information is only applicable to an IPv6 adapter address configured using DHCPv6. 648 | func (addr *IPAdapterAddresses) DHCPv6ClientDUID() []byte { 649 | return addr.dhcpv6ClientDUID[:addr.dhcpv6ClientDUIDLength] 650 | } 651 | 652 | // Init method initializes the members of an MIB_IPINTERFACE_ROW entry with default values. 653 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-initializeipinterfaceentry 654 | func (row *MibIPInterfaceRow) Init() { 655 | initializeIPInterfaceEntry(row) 656 | } 657 | 658 | // get method retrieves IP information for the specified interface on the local computer. 659 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipinterfaceentry 660 | func (row *MibIPInterfaceRow) get() error { 661 | if err := getIPInterfaceEntry(row); err != nil { 662 | return err 663 | } 664 | 665 | // Patch that fixes SitePrefixLength issue 666 | // https://stackoverflow.com/questions/54857292/setipinterfaceentry-returns-error-invalid-parameter?noredirect=1 667 | switch row.Family { 668 | case windows.AF_INET: 669 | if row.SitePrefixLength > 32 { 670 | row.SitePrefixLength = 0 671 | } 672 | case windows.AF_INET6: 673 | if row.SitePrefixLength > 128 { 674 | row.SitePrefixLength = 128 675 | } 676 | } 677 | 678 | return nil 679 | } 680 | 681 | // Set method sets the properties of an IP interface on the local computer. 682 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-setipinterfaceentry 683 | func (row *MibIPInterfaceRow) Set() error { 684 | return setIPInterfaceEntry(row) 685 | } 686 | 687 | // get method returns all table rows as a Go slice. 688 | func (tab *mibIPInterfaceTable) get() (s []MibIPInterfaceRow) { 689 | return unsafe.Slice(&tab.table[0], tab.numEntries) 690 | } 691 | 692 | // free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes. 693 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-freemibtable 694 | func (tab *mibIPInterfaceTable) free() { 695 | freeMibTable(unsafe.Pointer(tab)) 696 | } 697 | 698 | // Alias method returns a string that contains the alias name of the network interface. 699 | func (row *MibIfRow2) Alias() string { 700 | return windows.UTF16ToString(row.alias[:]) 701 | } 702 | 703 | // Description method returns a string that contains a description of the network interface. 704 | func (row *MibIfRow2) Description() string { 705 | return windows.UTF16ToString(row.description[:]) 706 | } 707 | 708 | // PhysicalAddress method returns the physical hardware address of the adapter for this network interface. 709 | func (row *MibIfRow2) PhysicalAddress() []byte { 710 | return row.physicalAddress[:row.physicalAddressLength] 711 | } 712 | 713 | // PermanentPhysicalAddress method returns the permanent physical hardware address of the adapter for this network interface. 714 | func (row *MibIfRow2) PermanentPhysicalAddress() []byte { 715 | return row.permanentPhysicalAddress[:row.physicalAddressLength] 716 | } 717 | 718 | // get method retrieves information for the specified interface on the local computer. 719 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getifentry2 720 | func (row *MibIfRow2) get() (ret error) { 721 | return getIfEntry2(row) 722 | } 723 | 724 | // get method returns all table rows as a Go slice. 725 | func (tab *mibIfTable2) get() (s []MibIfRow2) { 726 | return unsafe.Slice(&tab.table[0], tab.numEntries) 727 | } 728 | 729 | // free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes. 730 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-freemibtable 731 | func (tab *mibIfTable2) free() { 732 | freeMibTable(unsafe.Pointer(tab)) 733 | } 734 | 735 | // RawSockaddrInet union contains an IPv4, an IPv6 address, or an address family. 736 | // https://docs.microsoft.com/en-us/windows/desktop/api/ws2ipdef/ns-ws2ipdef-_sockaddr_inet 737 | type RawSockaddrInet struct { 738 | Family AddressFamily 739 | data [26]byte 740 | } 741 | 742 | func ntohs(i uint16) uint16 { 743 | return binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&i))[:]) 744 | } 745 | 746 | func htons(i uint16) uint16 { 747 | b := make([]byte, 2) 748 | binary.BigEndian.PutUint16(b, i) 749 | return *(*uint16)(unsafe.Pointer(&b[0])) 750 | } 751 | 752 | // SetAddrPort method sets family, address, and port to the given IPv4 or IPv6 address and port. 753 | // All other members of the structure are set to zero. 754 | func (addr *RawSockaddrInet) SetAddrPort(addrPort netip.AddrPort) error { 755 | if addrPort.Addr().Is4() { 756 | addr4 := (*windows.RawSockaddrInet4)(unsafe.Pointer(addr)) 757 | addr4.Family = windows.AF_INET 758 | addr4.Addr = addrPort.Addr().As4() 759 | addr4.Port = htons(addrPort.Port()) 760 | for i := 0; i < 8; i++ { 761 | addr4.Zero[i] = 0 762 | } 763 | return nil 764 | } else if addrPort.Addr().Is6() { 765 | addr6 := (*windows.RawSockaddrInet6)(unsafe.Pointer(addr)) 766 | addr6.Family = windows.AF_INET6 767 | addr6.Addr = addrPort.Addr().As16() 768 | addr6.Port = htons(addrPort.Port()) 769 | addr6.Flowinfo = 0 770 | scopeId := uint32(0) 771 | if z := addrPort.Addr().Zone(); z != "" { 772 | if s, err := strconv.ParseUint(z, 10, 32); err == nil { 773 | scopeId = uint32(s) 774 | } 775 | } 776 | addr6.Scope_id = scopeId 777 | return nil 778 | } 779 | return windows.ERROR_INVALID_PARAMETER 780 | } 781 | 782 | // SetAddr method sets family and address to the given IPv4 or IPv6 address. 783 | // All other members of the structure are set to zero. 784 | func (addr *RawSockaddrInet) SetAddr(netAddr netip.Addr) error { 785 | return addr.SetAddrPort(netip.AddrPortFrom(netAddr, 0)) 786 | } 787 | 788 | // AddrPort returns the IP address and port. 789 | func (addr *RawSockaddrInet) AddrPort() netip.AddrPort { 790 | return netip.AddrPortFrom(addr.Addr(), addr.Port()) 791 | } 792 | 793 | // Addr returns IPv4 or IPv6 address, or an invalid address if the address is neither. 794 | func (addr *RawSockaddrInet) Addr() netip.Addr { 795 | switch addr.Family { 796 | case windows.AF_INET: 797 | return netip.AddrFrom4((*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Addr) 798 | case windows.AF_INET6: 799 | raw := (*windows.RawSockaddrInet6)(unsafe.Pointer(addr)) 800 | a := netip.AddrFrom16(raw.Addr) 801 | if raw.Scope_id != 0 { 802 | a = a.WithZone(strconv.FormatUint(uint64(raw.Scope_id), 10)) 803 | } 804 | return a 805 | } 806 | return netip.Addr{} 807 | } 808 | 809 | // Port returns the port if the address if IPv4 or IPv6, or 0 if neither. 810 | func (addr *RawSockaddrInet) Port() uint16 { 811 | switch addr.Family { 812 | case windows.AF_INET: 813 | return ntohs((*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Port) 814 | case windows.AF_INET6: 815 | return ntohs((*windows.RawSockaddrInet6)(unsafe.Pointer(addr)).Port) 816 | } 817 | return 0 818 | } 819 | 820 | // Init method initializes a MibUnicastIPAddressRow structure with default values for a unicast IP address entry on the local computer. 821 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-initializeunicastipaddressentry 822 | func (row *MibUnicastIPAddressRow) Init() { 823 | initializeUnicastIPAddressEntry(row) 824 | } 825 | 826 | // get method retrieves information for an existing unicast IP address entry on the local computer. 827 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getunicastipaddressentry 828 | func (row *MibUnicastIPAddressRow) get() error { 829 | return getUnicastIPAddressEntry(row) 830 | } 831 | 832 | // Set method sets the properties of an existing unicast IP address entry on the local computer. 833 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-setunicastipaddressentry 834 | func (row *MibUnicastIPAddressRow) Set() error { 835 | return setUnicastIPAddressEntry(row) 836 | } 837 | 838 | // Create method adds a new unicast IP address entry on the local computer. 839 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry 840 | func (row *MibUnicastIPAddressRow) Create() error { 841 | return createUnicastIPAddressEntry(row) 842 | } 843 | 844 | // Delete method deletes an existing unicast IP address entry on the local computer. 845 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteunicastipaddressentry 846 | func (row *MibUnicastIPAddressRow) Delete() error { 847 | return deleteUnicastIPAddressEntry(row) 848 | } 849 | 850 | // get method returns all table rows as a Go slice. 851 | func (tab *mibUnicastIPAddressTable) get() (s []MibUnicastIPAddressRow) { 852 | return unsafe.Slice(&tab.table[0], tab.numEntries) 853 | } 854 | 855 | // free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes. 856 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-freemibtable 857 | func (tab *mibUnicastIPAddressTable) free() { 858 | freeMibTable(unsafe.Pointer(tab)) 859 | } 860 | 861 | // get method retrieves information for an existing anycast IP address entry on the local computer. 862 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getanycastipaddressentry 863 | func (row *MibAnycastIPAddressRow) get() error { 864 | return getAnycastIPAddressEntry(row) 865 | } 866 | 867 | // Create method adds a new anycast IP address entry on the local computer. 868 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createanycastipaddressentry 869 | func (row *MibAnycastIPAddressRow) Create() error { 870 | return createAnycastIPAddressEntry(row) 871 | } 872 | 873 | // Delete method deletes an existing anycast IP address entry on the local computer. 874 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteanycastipaddressentry 875 | func (row *MibAnycastIPAddressRow) Delete() error { 876 | return deleteAnycastIPAddressEntry(row) 877 | } 878 | 879 | // get method returns all table rows as a Go slice. 880 | func (tab *mibAnycastIPAddressTable) get() (s []MibAnycastIPAddressRow) { 881 | return unsafe.Slice(&tab.table[0], tab.numEntries) 882 | } 883 | 884 | // free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes. 885 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-freemibtable 886 | func (tab *mibAnycastIPAddressTable) free() { 887 | freeMibTable(unsafe.Pointer(tab)) 888 | } 889 | 890 | // IPAddressPrefix structure stores an IP address prefix. 891 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_ip_address_prefix 892 | type IPAddressPrefix struct { 893 | RawPrefix RawSockaddrInet 894 | PrefixLength uint8 895 | _ [2]byte 896 | } 897 | 898 | // SetPrefix method sets IP address prefix using netip.Prefix. 899 | func (prefix *IPAddressPrefix) SetPrefix(netPrefix netip.Prefix) error { 900 | err := prefix.RawPrefix.SetAddr(netPrefix.Addr()) 901 | if err != nil { 902 | return err 903 | } 904 | prefix.PrefixLength = uint8(netPrefix.Bits()) 905 | return nil 906 | } 907 | 908 | // Prefix returns IP address prefix as netip.Prefix. 909 | func (prefix *IPAddressPrefix) Prefix() netip.Prefix { 910 | switch prefix.RawPrefix.Family { 911 | case windows.AF_INET: 912 | return netip.PrefixFrom(netip.AddrFrom4((*windows.RawSockaddrInet4)(unsafe.Pointer(&prefix.RawPrefix)).Addr), int(prefix.PrefixLength)) 913 | case windows.AF_INET6: 914 | return netip.PrefixFrom(netip.AddrFrom16((*windows.RawSockaddrInet6)(unsafe.Pointer(&prefix.RawPrefix)).Addr), int(prefix.PrefixLength)) 915 | } 916 | return netip.Prefix{} 917 | } 918 | 919 | // MibIPforwardRow2 structure stores information about an IP route entry. 920 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipforward_row2 921 | type MibIPforwardRow2 struct { 922 | InterfaceLUID LUID 923 | InterfaceIndex uint32 924 | DestinationPrefix IPAddressPrefix 925 | NextHop RawSockaddrInet 926 | SitePrefixLength uint8 927 | ValidLifetime uint32 928 | PreferredLifetime uint32 929 | Metric uint32 930 | Protocol RouteProtocol 931 | Loopback bool 932 | AutoconfigureAddress bool 933 | Publish bool 934 | Immortal bool 935 | Age uint32 936 | Origin RouteOrigin 937 | } 938 | 939 | // Init method initializes a MIB_IPFORWARD_ROW2 structure with default values for an IP route entry on the local computer. 940 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-initializeipforwardentry 941 | func (row *MibIPforwardRow2) Init() { 942 | initializeIPForwardEntry(row) 943 | } 944 | 945 | // get method retrieves information for an IP route entry on the local computer. 946 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipforwardentry2 947 | func (row *MibIPforwardRow2) get() error { 948 | return getIPForwardEntry2(row) 949 | } 950 | 951 | // Set method sets the properties of an IP route entry on the local computer. 952 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-setipforwardentry2 953 | func (row *MibIPforwardRow2) Set() error { 954 | return setIPForwardEntry2(row) 955 | } 956 | 957 | // Create method creates a new IP route entry on the local computer. 958 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createipforwardentry2 959 | func (row *MibIPforwardRow2) Create() error { 960 | return createIPForwardEntry2(row) 961 | } 962 | 963 | // Delete method deletes an IP route entry on the local computer. 964 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteipforwardentry2 965 | func (row *MibIPforwardRow2) Delete() error { 966 | return deleteIPForwardEntry2(row) 967 | } 968 | 969 | // get method returns all table rows as a Go slice. 970 | func (tab *mibIPforwardTable2) get() (s []MibIPforwardRow2) { 971 | return unsafe.Slice(&tab.table[0], tab.numEntries) 972 | } 973 | 974 | // free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes. 975 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-freemibtable 976 | func (tab *mibIPforwardTable2) free() { 977 | freeMibTable(unsafe.Pointer(tab)) 978 | } 979 | 980 | // 981 | // DNS API 982 | // 983 | 984 | // DnsInterfaceSettings is meant to be used with SetInterfaceDnsSettings 985 | type DnsInterfaceSettings struct { 986 | Version uint32 987 | _ [4]byte 988 | Flags uint64 989 | Domain *uint16 990 | NameServer *uint16 991 | SearchList *uint16 992 | RegistrationEnabled uint32 993 | RegisterAdapterName uint32 994 | EnableLLMNR uint32 995 | QueryAdapterName uint32 996 | ProfileNameServer *uint16 997 | } 998 | 999 | const ( 1000 | DnsInterfaceSettingsVersion1 = 1 // for DnsInterfaceSettings 1001 | DnsInterfaceSettingsVersion2 = 2 // for DnsInterfaceSettingsEx 1002 | DnsInterfaceSettingsVersion3 = 3 // for DnsInterfaceSettings3 1003 | 1004 | DnsInterfaceSettingsFlagIPv6 = 0x0001 1005 | DnsInterfaceSettingsFlagNameserver = 0x0002 1006 | DnsInterfaceSettingsFlagSearchList = 0x0004 1007 | DnsInterfaceSettingsFlagRegistrationEnabled = 0x0008 1008 | DnsInterfaceSettingsFlagRegisterAdapterName = 0x0010 1009 | DnsInterfaceSettingsFlagDomain = 0x0020 1010 | DnsInterfaceSettingsFlagHostname = 0x0040 1011 | DnsInterfaceSettingsFlagEnableLLMNR = 0x0080 1012 | DnsInterfaceSettingsFlagQueryAdapterName = 0x0100 1013 | DnsInterfaceSettingsFlagProfileNameserver = 0x0200 1014 | DnsInterfaceSettingsFlagDisableUnconstrainedQueries = 0x0400 // v2 only 1015 | DnsInterfaceSettingsFlagSupplementalSearchList = 0x0800 // v2 only 1016 | DnsInterfaceSettingsFlagDOH = 0x1000 // v3 only 1017 | DnsInterfaceSettingsFlagDOHProfile = 0x2000 // v3 only 1018 | ) 1019 | -------------------------------------------------------------------------------- /winipcfg/types_32.go: -------------------------------------------------------------------------------- 1 | //go:build 386 || arm 2 | 3 | /* SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 6 | */ 7 | 8 | package winipcfg 9 | 10 | import ( 11 | "golang.org/x/sys/windows" 12 | ) 13 | 14 | // IPAdapterWINSServerAddress structure stores a single Windows Internet Name Service (WINS) server address in a linked list of WINS server addresses for a particular adapter. 15 | // https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_wins_server_address_lh 16 | type IPAdapterWINSServerAddress struct { 17 | Length uint32 18 | _ uint32 19 | Next *IPAdapterWINSServerAddress 20 | Address windows.SocketAddress 21 | _ [4]byte 22 | } 23 | 24 | // IPAdapterGatewayAddress structure stores a single gateway address in a linked list of gateway addresses for a particular adapter. 25 | // https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_gateway_address_lh 26 | type IPAdapterGatewayAddress struct { 27 | Length uint32 28 | _ uint32 29 | Next *IPAdapterGatewayAddress 30 | Address windows.SocketAddress 31 | _ [4]byte 32 | } 33 | 34 | // 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. 35 | // https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_addresses_lh 36 | // This is a modified and extended version of windows.IpAdapterAddresses. 37 | type IPAdapterAddresses struct { 38 | Length uint32 39 | IfIndex uint32 40 | Next *IPAdapterAddresses 41 | adapterName *byte 42 | FirstUnicastAddress *windows.IpAdapterUnicastAddress 43 | FirstAnycastAddress *windows.IpAdapterAnycastAddress 44 | FirstMulticastAddress *windows.IpAdapterMulticastAddress 45 | FirstDNSServerAddress *windows.IpAdapterDnsServerAdapter 46 | dnsSuffix *uint16 47 | description *uint16 48 | friendlyName *uint16 49 | physicalAddress [windows.MAX_ADAPTER_ADDRESS_LENGTH]byte 50 | physicalAddressLength uint32 51 | Flags IPAAFlags 52 | MTU uint32 53 | IfType IfType 54 | OperStatus IfOperStatus 55 | IPv6IfIndex uint32 56 | ZoneIndices [16]uint32 57 | FirstPrefix *windows.IpAdapterPrefix 58 | TransmitLinkSpeed uint64 59 | ReceiveLinkSpeed uint64 60 | FirstWINSServerAddress *IPAdapterWINSServerAddress 61 | FirstGatewayAddress *IPAdapterGatewayAddress 62 | Ipv4Metric uint32 63 | Ipv6Metric uint32 64 | LUID LUID 65 | DHCPv4Server windows.SocketAddress 66 | CompartmentID uint32 67 | NetworkGUID windows.GUID 68 | ConnectionType NetIfConnectionType 69 | TunnelType TunnelType 70 | DHCPv6Server windows.SocketAddress 71 | dhcpv6ClientDUID [maxDHCPv6DUIDLength]byte 72 | dhcpv6ClientDUIDLength uint32 73 | DHCPv6IAID uint32 74 | FirstDNSSuffix *IPAdapterDNSSuffix 75 | _ [4]byte 76 | } 77 | 78 | // MibIPInterfaceRow structure stores interface management information for a particular IP address family on a network interface. 79 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_row 80 | type MibIPInterfaceRow struct { 81 | Family AddressFamily 82 | _ [4]byte 83 | InterfaceLUID LUID 84 | InterfaceIndex uint32 85 | MaxReassemblySize uint32 86 | InterfaceIdentifier uint64 87 | MinRouterAdvertisementInterval uint32 88 | MaxRouterAdvertisementInterval uint32 89 | AdvertisingEnabled bool 90 | ForwardingEnabled bool 91 | WeakHostSend bool 92 | WeakHostReceive bool 93 | UseAutomaticMetric bool 94 | UseNeighborUnreachabilityDetection bool 95 | ManagedAddressConfigurationSupported bool 96 | OtherStatefulConfigurationSupported bool 97 | AdvertiseDefaultRoute bool 98 | RouterDiscoveryBehavior RouterDiscoveryBehavior 99 | DadTransmits uint32 100 | BaseReachableTime uint32 101 | RetransmitTime uint32 102 | PathMTUDiscoveryTimeout uint32 103 | LinkLocalAddressBehavior LinkLocalAddressBehavior 104 | LinkLocalAddressTimeout uint32 105 | ZoneIndices [ScopeLevelCount]uint32 106 | SitePrefixLength uint32 107 | Metric uint32 108 | NLMTU uint32 109 | Connected bool 110 | SupportsWakeUpPatterns bool 111 | SupportsNeighborDiscovery bool 112 | SupportsRouterDiscovery bool 113 | ReachableTime uint32 114 | TransmitOffload OffloadRod 115 | ReceiveOffload OffloadRod 116 | DisableDefaultRoutes bool 117 | } 118 | 119 | // mibIPInterfaceTable structure contains a table of IP interface entries. 120 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_table 121 | type mibIPInterfaceTable struct { 122 | numEntries uint32 123 | _ [4]byte 124 | table [anySize]MibIPInterfaceRow 125 | } 126 | 127 | // MibIfRow2 structure stores information about a particular interface. 128 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_row2 129 | type MibIfRow2 struct { 130 | InterfaceLUID LUID 131 | InterfaceIndex uint32 132 | InterfaceGUID windows.GUID 133 | alias [ifMaxStringSize + 1]uint16 134 | description [ifMaxStringSize + 1]uint16 135 | physicalAddressLength uint32 136 | physicalAddress [ifMaxPhysAddressLength]byte 137 | permanentPhysicalAddress [ifMaxPhysAddressLength]byte 138 | MTU uint32 139 | Type IfType 140 | TunnelType TunnelType 141 | MediaType NdisMedium 142 | PhysicalMediumType NdisPhysicalMedium 143 | AccessType NetIfAccessType 144 | DirectionType NetIfDirectionType 145 | InterfaceAndOperStatusFlags InterfaceAndOperStatusFlags 146 | OperStatus IfOperStatus 147 | AdminStatus NetIfAdminStatus 148 | MediaConnectState NetIfMediaConnectState 149 | NetworkGUID windows.GUID 150 | ConnectionType NetIfConnectionType 151 | _ [4]byte 152 | TransmitLinkSpeed uint64 153 | ReceiveLinkSpeed uint64 154 | InOctets uint64 155 | InUcastPkts uint64 156 | InNUcastPkts uint64 157 | InDiscards uint64 158 | InErrors uint64 159 | InUnknownProtos uint64 160 | InUcastOctets uint64 161 | InMulticastOctets uint64 162 | InBroadcastOctets uint64 163 | OutOctets uint64 164 | OutUcastPkts uint64 165 | OutNUcastPkts uint64 166 | OutDiscards uint64 167 | OutErrors uint64 168 | OutUcastOctets uint64 169 | OutMulticastOctets uint64 170 | OutBroadcastOctets uint64 171 | OutQLen uint64 172 | } 173 | 174 | // mibIfTable2 structure contains a table of logical and physical interface entries. 175 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_table2 176 | type mibIfTable2 struct { 177 | numEntries uint32 178 | _ [4]byte 179 | table [anySize]MibIfRow2 180 | } 181 | 182 | // MibUnicastIPAddressRow structure stores information about a unicast IP address. 183 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_row 184 | type MibUnicastIPAddressRow struct { 185 | Address RawSockaddrInet 186 | _ [4]byte 187 | InterfaceLUID LUID 188 | InterfaceIndex uint32 189 | PrefixOrigin PrefixOrigin 190 | SuffixOrigin SuffixOrigin 191 | ValidLifetime uint32 192 | PreferredLifetime uint32 193 | OnLinkPrefixLength uint8 194 | SkipAsSource bool 195 | DadState DadState 196 | ScopeID uint32 197 | CreationTimeStamp int64 198 | } 199 | 200 | // mibUnicastIPAddressTable structure contains a table of unicast IP address entries. 201 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_table 202 | type mibUnicastIPAddressTable struct { 203 | numEntries uint32 204 | _ [4]byte 205 | table [anySize]MibUnicastIPAddressRow 206 | } 207 | 208 | // MibAnycastIPAddressRow structure stores information about an anycast IP address. 209 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_anycastipaddress_row 210 | type MibAnycastIPAddressRow struct { 211 | Address RawSockaddrInet 212 | _ [4]byte 213 | InterfaceLUID LUID 214 | InterfaceIndex uint32 215 | ScopeID uint32 216 | } 217 | 218 | // mibAnycastIPAddressTable structure contains a table of anycast IP address entries. 219 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-mib_anycastipaddress_table 220 | type mibAnycastIPAddressTable struct { 221 | numEntries uint32 222 | _ [4]byte 223 | table [anySize]MibAnycastIPAddressRow 224 | } 225 | 226 | // mibIPforwardTable2 structure contains a table of IP route entries. 227 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipforward_table2 228 | type mibIPforwardTable2 struct { 229 | numEntries uint32 230 | _ [4]byte 231 | table [anySize]MibIPforwardRow2 232 | } 233 | -------------------------------------------------------------------------------- /winipcfg/types_64.go: -------------------------------------------------------------------------------- 1 | //go:build amd64 || arm64 2 | 3 | /* SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 6 | */ 7 | 8 | package winipcfg 9 | 10 | import ( 11 | "golang.org/x/sys/windows" 12 | ) 13 | 14 | // IPAdapterWINSServerAddress structure stores a single Windows Internet Name Service (WINS) server address in a linked list of WINS server addresses for a particular adapter. 15 | // https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_wins_server_address_lh 16 | type IPAdapterWINSServerAddress struct { 17 | Length uint32 18 | _ uint32 19 | Next *IPAdapterWINSServerAddress 20 | Address windows.SocketAddress 21 | } 22 | 23 | // IPAdapterGatewayAddress structure stores a single gateway address in a linked list of gateway addresses for a particular adapter. 24 | // https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_gateway_address_lh 25 | type IPAdapterGatewayAddress struct { 26 | Length uint32 27 | _ uint32 28 | Next *IPAdapterGatewayAddress 29 | Address windows.SocketAddress 30 | } 31 | 32 | // 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. 33 | // https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_addresses_lh 34 | // This is a modified and extended version of windows.IpAdapterAddresses. 35 | type IPAdapterAddresses struct { 36 | Length uint32 37 | IfIndex uint32 38 | Next *IPAdapterAddresses 39 | adapterName *byte 40 | FirstUnicastAddress *windows.IpAdapterUnicastAddress 41 | FirstAnycastAddress *windows.IpAdapterAnycastAddress 42 | FirstMulticastAddress *windows.IpAdapterMulticastAddress 43 | FirstDNSServerAddress *windows.IpAdapterDnsServerAdapter 44 | dnsSuffix *uint16 45 | description *uint16 46 | friendlyName *uint16 47 | physicalAddress [windows.MAX_ADAPTER_ADDRESS_LENGTH]byte 48 | physicalAddressLength uint32 49 | Flags IPAAFlags 50 | MTU uint32 51 | IfType IfType 52 | OperStatus IfOperStatus 53 | IPv6IfIndex uint32 54 | ZoneIndices [16]uint32 55 | FirstPrefix *windows.IpAdapterPrefix 56 | TransmitLinkSpeed uint64 57 | ReceiveLinkSpeed uint64 58 | FirstWINSServerAddress *IPAdapterWINSServerAddress 59 | FirstGatewayAddress *IPAdapterGatewayAddress 60 | Ipv4Metric uint32 61 | Ipv6Metric uint32 62 | LUID LUID 63 | DHCPv4Server windows.SocketAddress 64 | CompartmentID uint32 65 | NetworkGUID windows.GUID 66 | ConnectionType NetIfConnectionType 67 | TunnelType TunnelType 68 | DHCPv6Server windows.SocketAddress 69 | dhcpv6ClientDUID [maxDHCPv6DUIDLength]byte 70 | dhcpv6ClientDUIDLength uint32 71 | DHCPv6IAID uint32 72 | FirstDNSSuffix *IPAdapterDNSSuffix 73 | } 74 | 75 | // MibIPInterfaceRow structure stores interface management information for a particular IP address family on a network interface. 76 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_row 77 | type MibIPInterfaceRow struct { 78 | Family AddressFamily 79 | InterfaceLUID LUID 80 | InterfaceIndex uint32 81 | MaxReassemblySize uint32 82 | InterfaceIdentifier uint64 83 | MinRouterAdvertisementInterval uint32 84 | MaxRouterAdvertisementInterval uint32 85 | AdvertisingEnabled bool 86 | ForwardingEnabled bool 87 | WeakHostSend bool 88 | WeakHostReceive bool 89 | UseAutomaticMetric bool 90 | UseNeighborUnreachabilityDetection bool 91 | ManagedAddressConfigurationSupported bool 92 | OtherStatefulConfigurationSupported bool 93 | AdvertiseDefaultRoute bool 94 | RouterDiscoveryBehavior RouterDiscoveryBehavior 95 | DadTransmits uint32 96 | BaseReachableTime uint32 97 | RetransmitTime uint32 98 | PathMTUDiscoveryTimeout uint32 99 | LinkLocalAddressBehavior LinkLocalAddressBehavior 100 | LinkLocalAddressTimeout uint32 101 | ZoneIndices [ScopeLevelCount]uint32 102 | SitePrefixLength uint32 103 | Metric uint32 104 | NLMTU uint32 105 | Connected bool 106 | SupportsWakeUpPatterns bool 107 | SupportsNeighborDiscovery bool 108 | SupportsRouterDiscovery bool 109 | ReachableTime uint32 110 | TransmitOffload OffloadRod 111 | ReceiveOffload OffloadRod 112 | DisableDefaultRoutes bool 113 | } 114 | 115 | // mibIPInterfaceTable structure contains a table of IP interface entries. 116 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_table 117 | type mibIPInterfaceTable struct { 118 | numEntries uint32 119 | table [anySize]MibIPInterfaceRow 120 | } 121 | 122 | // MibIfRow2 structure stores information about a particular interface. 123 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_row2 124 | type MibIfRow2 struct { 125 | InterfaceLUID LUID 126 | InterfaceIndex uint32 127 | InterfaceGUID windows.GUID 128 | alias [ifMaxStringSize + 1]uint16 129 | description [ifMaxStringSize + 1]uint16 130 | physicalAddressLength uint32 131 | physicalAddress [ifMaxPhysAddressLength]byte 132 | permanentPhysicalAddress [ifMaxPhysAddressLength]byte 133 | MTU uint32 134 | Type IfType 135 | TunnelType TunnelType 136 | MediaType NdisMedium 137 | PhysicalMediumType NdisPhysicalMedium 138 | AccessType NetIfAccessType 139 | DirectionType NetIfDirectionType 140 | InterfaceAndOperStatusFlags InterfaceAndOperStatusFlags 141 | OperStatus IfOperStatus 142 | AdminStatus NetIfAdminStatus 143 | MediaConnectState NetIfMediaConnectState 144 | NetworkGUID windows.GUID 145 | ConnectionType NetIfConnectionType 146 | TransmitLinkSpeed uint64 147 | ReceiveLinkSpeed uint64 148 | InOctets uint64 149 | InUcastPkts uint64 150 | InNUcastPkts uint64 151 | InDiscards uint64 152 | InErrors uint64 153 | InUnknownProtos uint64 154 | InUcastOctets uint64 155 | InMulticastOctets uint64 156 | InBroadcastOctets uint64 157 | OutOctets uint64 158 | OutUcastPkts uint64 159 | OutNUcastPkts uint64 160 | OutDiscards uint64 161 | OutErrors uint64 162 | OutUcastOctets uint64 163 | OutMulticastOctets uint64 164 | OutBroadcastOctets uint64 165 | OutQLen uint64 166 | } 167 | 168 | // mibIfTable2 structure contains a table of logical and physical interface entries. 169 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_table2 170 | type mibIfTable2 struct { 171 | numEntries uint32 172 | table [anySize]MibIfRow2 173 | } 174 | 175 | // MibUnicastIPAddressRow structure stores information about a unicast IP address. 176 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_row 177 | type MibUnicastIPAddressRow struct { 178 | Address RawSockaddrInet 179 | InterfaceLUID LUID 180 | InterfaceIndex uint32 181 | PrefixOrigin PrefixOrigin 182 | SuffixOrigin SuffixOrigin 183 | ValidLifetime uint32 184 | PreferredLifetime uint32 185 | OnLinkPrefixLength uint8 186 | SkipAsSource bool 187 | DadState DadState 188 | ScopeID uint32 189 | CreationTimeStamp int64 190 | } 191 | 192 | // mibUnicastIPAddressTable structure contains a table of unicast IP address entries. 193 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_table 194 | type mibUnicastIPAddressTable struct { 195 | numEntries uint32 196 | table [anySize]MibUnicastIPAddressRow 197 | } 198 | 199 | // MibAnycastIPAddressRow structure stores information about an anycast IP address. 200 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_anycastipaddress_row 201 | type MibAnycastIPAddressRow struct { 202 | Address RawSockaddrInet 203 | InterfaceLUID LUID 204 | InterfaceIndex uint32 205 | ScopeID uint32 206 | } 207 | 208 | // mibAnycastIPAddressTable structure contains a table of anycast IP address entries. 209 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-mib_anycastipaddress_table 210 | type mibAnycastIPAddressTable struct { 211 | numEntries uint32 212 | table [anySize]MibAnycastIPAddressRow 213 | } 214 | 215 | // mibIPforwardTable2 structure contains a table of IP route entries. 216 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipforward_table2 217 | type mibIPforwardTable2 struct { 218 | numEntries uint32 219 | table [anySize]MibIPforwardRow2 220 | } 221 | -------------------------------------------------------------------------------- /winipcfg/winipcfg.go: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT 2 | * 3 | * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 4 | */ 5 | 6 | package winipcfg 7 | 8 | import ( 9 | "runtime" 10 | "unsafe" 11 | 12 | "golang.org/x/sys/windows" 13 | ) 14 | 15 | // 16 | // Common functions 17 | // 18 | 19 | //sys freeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable 20 | 21 | // 22 | // Interface-related functions 23 | // 24 | 25 | //sys initializeIPInterfaceEntry(row *MibIPInterfaceRow) = iphlpapi.InitializeIpInterfaceEntry 26 | //sys getIPInterfaceTable(family AddressFamily, table **mibIPInterfaceTable) (ret error) = iphlpapi.GetIpInterfaceTable 27 | //sys getIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) = iphlpapi.GetIpInterfaceEntry 28 | //sys setIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) = iphlpapi.SetIpInterfaceEntry 29 | //sys getIfEntry2(row *MibIfRow2) (ret error) = iphlpapi.GetIfEntry2 30 | //sys getIfTable2Ex(level MibIfEntryLevel, table **mibIfTable2) (ret error) = iphlpapi.GetIfTable2Ex 31 | //sys convertInterfaceLUIDToGUID(interfaceLUID *LUID, interfaceGUID *windows.GUID) (ret error) = iphlpapi.ConvertInterfaceLuidToGuid 32 | //sys convertInterfaceGUIDToLUID(interfaceGUID *windows.GUID, interfaceLUID *LUID) (ret error) = iphlpapi.ConvertInterfaceGuidToLuid 33 | //sys convertInterfaceIndexToLUID(interfaceIndex uint32, interfaceLUID *LUID) (ret error) = iphlpapi.ConvertInterfaceIndexToLuid 34 | 35 | // GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer. 36 | // https://docs.microsoft.com/en-us/windows/desktop/api/iphlpapi/nf-iphlpapi-getadaptersaddresses 37 | func GetAdaptersAddresses(family AddressFamily, flags GAAFlags) ([]*IPAdapterAddresses, error) { 38 | var b []byte 39 | size := uint32(15000) 40 | 41 | for { 42 | b = make([]byte, size) 43 | err := windows.GetAdaptersAddresses(uint32(family), uint32(flags), 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &size) 44 | if err == nil { 45 | break 46 | } 47 | if err != windows.ERROR_BUFFER_OVERFLOW || size <= uint32(len(b)) { 48 | return nil, err 49 | } 50 | } 51 | 52 | result := make([]*IPAdapterAddresses, 0, uintptr(size)/unsafe.Sizeof(IPAdapterAddresses{})) 53 | for wtiaa := (*IPAdapterAddresses)(unsafe.Pointer(&b[0])); wtiaa != nil; wtiaa = wtiaa.Next { 54 | result = append(result, wtiaa) 55 | } 56 | 57 | return result, nil 58 | } 59 | 60 | // GetIPInterfaceTable function retrieves the IP interface entries on the local computer. 61 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipinterfacetable 62 | func GetIPInterfaceTable(family AddressFamily) ([]MibIPInterfaceRow, error) { 63 | var tab *mibIPInterfaceTable 64 | err := getIPInterfaceTable(family, &tab) 65 | if err != nil { 66 | return nil, err 67 | } 68 | t := append(make([]MibIPInterfaceRow, 0, tab.numEntries), tab.get()...) 69 | tab.free() 70 | return t, nil 71 | } 72 | 73 | // GetIfTable2Ex function retrieves the MIB-II interface table. 74 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getiftable2ex 75 | func GetIfTable2Ex(level MibIfEntryLevel) ([]MibIfRow2, error) { 76 | var tab *mibIfTable2 77 | err := getIfTable2Ex(level, &tab) 78 | if err != nil { 79 | return nil, err 80 | } 81 | t := append(make([]MibIfRow2, 0, tab.numEntries), tab.get()...) 82 | tab.free() 83 | return t, nil 84 | } 85 | 86 | // 87 | // Unicast IP address-related functions 88 | // 89 | 90 | //sys getUnicastIPAddressTable(family AddressFamily, table **mibUnicastIPAddressTable) (ret error) = iphlpapi.GetUnicastIpAddressTable 91 | //sys initializeUnicastIPAddressEntry(row *MibUnicastIPAddressRow) = iphlpapi.InitializeUnicastIpAddressEntry 92 | //sys getUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.GetUnicastIpAddressEntry 93 | //sys setUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.SetUnicastIpAddressEntry 94 | //sys createUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.CreateUnicastIpAddressEntry 95 | //sys deleteUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.DeleteUnicastIpAddressEntry 96 | 97 | // GetUnicastIPAddressTable function retrieves the unicast IP address table on the local computer. 98 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getunicastipaddresstable 99 | func GetUnicastIPAddressTable(family AddressFamily) ([]MibUnicastIPAddressRow, error) { 100 | var tab *mibUnicastIPAddressTable 101 | err := getUnicastIPAddressTable(family, &tab) 102 | if err != nil { 103 | return nil, err 104 | } 105 | t := append(make([]MibUnicastIPAddressRow, 0, tab.numEntries), tab.get()...) 106 | tab.free() 107 | return t, nil 108 | } 109 | 110 | // 111 | // Anycast IP address-related functions 112 | // 113 | 114 | //sys getAnycastIPAddressTable(family AddressFamily, table **mibAnycastIPAddressTable) (ret error) = iphlpapi.GetAnycastIpAddressTable 115 | //sys getAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) = iphlpapi.GetAnycastIpAddressEntry 116 | //sys createAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) = iphlpapi.CreateAnycastIpAddressEntry 117 | //sys deleteAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) = iphlpapi.DeleteAnycastIpAddressEntry 118 | 119 | // GetAnycastIPAddressTable function retrieves the anycast IP address table on the local computer. 120 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getanycastipaddresstable 121 | func GetAnycastIPAddressTable(family AddressFamily) ([]MibAnycastIPAddressRow, error) { 122 | var tab *mibAnycastIPAddressTable 123 | err := getAnycastIPAddressTable(family, &tab) 124 | if err != nil { 125 | return nil, err 126 | } 127 | t := append(make([]MibAnycastIPAddressRow, 0, tab.numEntries), tab.get()...) 128 | tab.free() 129 | return t, nil 130 | } 131 | 132 | // 133 | // Routing-related functions 134 | // 135 | 136 | //sys getIPForwardTable2(family AddressFamily, table **mibIPforwardTable2) (ret error) = iphlpapi.GetIpForwardTable2 137 | //sys initializeIPForwardEntry(route *MibIPforwardRow2) = iphlpapi.InitializeIpForwardEntry 138 | //sys getIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.GetIpForwardEntry2 139 | //sys setIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.SetIpForwardEntry2 140 | //sys createIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.CreateIpForwardEntry2 141 | //sys deleteIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.DeleteIpForwardEntry2 142 | 143 | // GetIPForwardTable2 function retrieves the IP route entries on the local computer. 144 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipforwardtable2 145 | func GetIPForwardTable2(family AddressFamily) ([]MibIPforwardRow2, error) { 146 | var tab *mibIPforwardTable2 147 | err := getIPForwardTable2(family, &tab) 148 | if err != nil { 149 | return nil, err 150 | } 151 | t := append(make([]MibIPforwardRow2, 0, tab.numEntries), tab.get()...) 152 | tab.free() 153 | return t, nil 154 | } 155 | 156 | // 157 | // Notifications-related functions 158 | // 159 | 160 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-notifyipinterfacechange 161 | //sys notifyIPInterfaceChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) = iphlpapi.NotifyIpInterfaceChange 162 | 163 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-notifyunicastipaddresschange 164 | //sys notifyUnicastIPAddressChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) = iphlpapi.NotifyUnicastIpAddressChange 165 | 166 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-notifyroutechange2 167 | //sys notifyRouteChange2(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) = iphlpapi.NotifyRouteChange2 168 | 169 | // https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-cancelmibchangenotify2 170 | //sys cancelMibChangeNotify2(notificationHandle windows.Handle) (ret error) = iphlpapi.CancelMibChangeNotify2 171 | 172 | // 173 | // DNS-related functions 174 | // 175 | 176 | //sys setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings? 177 | //sys setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings? 178 | //sys setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings? 179 | 180 | // The GUID is passed by value, not by reference, which means different 181 | // things on different calling conventions. On amd64, this means it's 182 | // passed by reference anyway, while on arm, arm64, and 386, it's split 183 | // into words. 184 | func SetInterfaceDnsSettings(guid windows.GUID, settings *DnsInterfaceSettings) error { 185 | words := (*[4]uintptr)(unsafe.Pointer(&guid)) 186 | switch runtime.GOARCH { 187 | case "amd64": 188 | return setInterfaceDnsSettingsByPtr(&guid, settings) 189 | case "arm64": 190 | return setInterfaceDnsSettingsByQwords(words[0], words[1], settings) 191 | case "arm", "386": 192 | return setInterfaceDnsSettingsByDwords(words[0], words[1], words[2], words[3], settings) 193 | default: 194 | panic("unknown calling convention") 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /winipcfg/zwinipcfg_windows.go: -------------------------------------------------------------------------------- 1 | // Code generated by 'go generate'; DO NOT EDIT. 2 | 3 | package winipcfg 4 | 5 | import ( 6 | "syscall" 7 | "unsafe" 8 | 9 | "golang.org/x/sys/windows" 10 | ) 11 | 12 | var _ unsafe.Pointer 13 | 14 | // Do the interface allocations only once for common 15 | // Errno values. 16 | const ( 17 | errnoERROR_IO_PENDING = 997 18 | ) 19 | 20 | var ( 21 | errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) 22 | errERROR_EINVAL error = syscall.EINVAL 23 | ) 24 | 25 | // errnoErr returns common boxed Errno values, to prevent 26 | // allocations at runtime. 27 | func errnoErr(e syscall.Errno) error { 28 | switch e { 29 | case 0: 30 | return errERROR_EINVAL 31 | case errnoERROR_IO_PENDING: 32 | return errERROR_IO_PENDING 33 | } 34 | // TODO: add more here, after collecting data on the common 35 | // error values see on Windows. (perhaps when running 36 | // all.bat?) 37 | return e 38 | } 39 | 40 | var ( 41 | modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll") 42 | 43 | procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2") 44 | procConvertInterfaceGuidToLuid = modiphlpapi.NewProc("ConvertInterfaceGuidToLuid") 45 | procConvertInterfaceIndexToLuid = modiphlpapi.NewProc("ConvertInterfaceIndexToLuid") 46 | procConvertInterfaceLuidToGuid = modiphlpapi.NewProc("ConvertInterfaceLuidToGuid") 47 | procCreateAnycastIpAddressEntry = modiphlpapi.NewProc("CreateAnycastIpAddressEntry") 48 | procCreateIpForwardEntry2 = modiphlpapi.NewProc("CreateIpForwardEntry2") 49 | procCreateUnicastIpAddressEntry = modiphlpapi.NewProc("CreateUnicastIpAddressEntry") 50 | procDeleteAnycastIpAddressEntry = modiphlpapi.NewProc("DeleteAnycastIpAddressEntry") 51 | procDeleteIpForwardEntry2 = modiphlpapi.NewProc("DeleteIpForwardEntry2") 52 | procDeleteUnicastIpAddressEntry = modiphlpapi.NewProc("DeleteUnicastIpAddressEntry") 53 | procFreeMibTable = modiphlpapi.NewProc("FreeMibTable") 54 | procGetAnycastIpAddressEntry = modiphlpapi.NewProc("GetAnycastIpAddressEntry") 55 | procGetAnycastIpAddressTable = modiphlpapi.NewProc("GetAnycastIpAddressTable") 56 | procGetIfEntry2 = modiphlpapi.NewProc("GetIfEntry2") 57 | procGetIfTable2Ex = modiphlpapi.NewProc("GetIfTable2Ex") 58 | procGetIpForwardEntry2 = modiphlpapi.NewProc("GetIpForwardEntry2") 59 | procGetIpForwardTable2 = modiphlpapi.NewProc("GetIpForwardTable2") 60 | procGetIpInterfaceEntry = modiphlpapi.NewProc("GetIpInterfaceEntry") 61 | procGetIpInterfaceTable = modiphlpapi.NewProc("GetIpInterfaceTable") 62 | procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry") 63 | procGetUnicastIpAddressTable = modiphlpapi.NewProc("GetUnicastIpAddressTable") 64 | procInitializeIpForwardEntry = modiphlpapi.NewProc("InitializeIpForwardEntry") 65 | procInitializeIpInterfaceEntry = modiphlpapi.NewProc("InitializeIpInterfaceEntry") 66 | procInitializeUnicastIpAddressEntry = modiphlpapi.NewProc("InitializeUnicastIpAddressEntry") 67 | procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange") 68 | procNotifyRouteChange2 = modiphlpapi.NewProc("NotifyRouteChange2") 69 | procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange") 70 | procSetInterfaceDnsSettings = modiphlpapi.NewProc("SetInterfaceDnsSettings") 71 | procSetIpForwardEntry2 = modiphlpapi.NewProc("SetIpForwardEntry2") 72 | procSetIpInterfaceEntry = modiphlpapi.NewProc("SetIpInterfaceEntry") 73 | procSetUnicastIpAddressEntry = modiphlpapi.NewProc("SetUnicastIpAddressEntry") 74 | ) 75 | 76 | func cancelMibChangeNotify2(notificationHandle windows.Handle) (ret error) { 77 | r0, _, _ := syscall.Syscall(procCancelMibChangeNotify2.Addr(), 1, uintptr(notificationHandle), 0, 0) 78 | if r0 != 0 { 79 | ret = syscall.Errno(r0) 80 | } 81 | return 82 | } 83 | 84 | func convertInterfaceGUIDToLUID(interfaceGUID *windows.GUID, interfaceLUID *LUID) (ret error) { 85 | r0, _, _ := syscall.Syscall(procConvertInterfaceGuidToLuid.Addr(), 2, uintptr(unsafe.Pointer(interfaceGUID)), uintptr(unsafe.Pointer(interfaceLUID)), 0) 86 | if r0 != 0 { 87 | ret = syscall.Errno(r0) 88 | } 89 | return 90 | } 91 | 92 | func convertInterfaceIndexToLUID(interfaceIndex uint32, interfaceLUID *LUID) (ret error) { 93 | r0, _, _ := syscall.Syscall(procConvertInterfaceIndexToLuid.Addr(), 2, uintptr(interfaceIndex), uintptr(unsafe.Pointer(interfaceLUID)), 0) 94 | if r0 != 0 { 95 | ret = syscall.Errno(r0) 96 | } 97 | return 98 | } 99 | 100 | func convertInterfaceLUIDToGUID(interfaceLUID *LUID, interfaceGUID *windows.GUID) (ret error) { 101 | r0, _, _ := syscall.Syscall(procConvertInterfaceLuidToGuid.Addr(), 2, uintptr(unsafe.Pointer(interfaceLUID)), uintptr(unsafe.Pointer(interfaceGUID)), 0) 102 | if r0 != 0 { 103 | ret = syscall.Errno(r0) 104 | } 105 | return 106 | } 107 | 108 | func createAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) { 109 | r0, _, _ := syscall.Syscall(procCreateAnycastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 110 | if r0 != 0 { 111 | ret = syscall.Errno(r0) 112 | } 113 | return 114 | } 115 | 116 | func createIPForwardEntry2(route *MibIPforwardRow2) (ret error) { 117 | r0, _, _ := syscall.Syscall(procCreateIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0) 118 | if r0 != 0 { 119 | ret = syscall.Errno(r0) 120 | } 121 | return 122 | } 123 | 124 | func createUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) { 125 | r0, _, _ := syscall.Syscall(procCreateUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 126 | if r0 != 0 { 127 | ret = syscall.Errno(r0) 128 | } 129 | return 130 | } 131 | 132 | func deleteAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) { 133 | r0, _, _ := syscall.Syscall(procDeleteAnycastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 134 | if r0 != 0 { 135 | ret = syscall.Errno(r0) 136 | } 137 | return 138 | } 139 | 140 | func deleteIPForwardEntry2(route *MibIPforwardRow2) (ret error) { 141 | r0, _, _ := syscall.Syscall(procDeleteIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0) 142 | if r0 != 0 { 143 | ret = syscall.Errno(r0) 144 | } 145 | return 146 | } 147 | 148 | func deleteUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) { 149 | r0, _, _ := syscall.Syscall(procDeleteUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 150 | if r0 != 0 { 151 | ret = syscall.Errno(r0) 152 | } 153 | return 154 | } 155 | 156 | func freeMibTable(memory unsafe.Pointer) { 157 | syscall.Syscall(procFreeMibTable.Addr(), 1, uintptr(memory), 0, 0) 158 | return 159 | } 160 | 161 | func getAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) { 162 | r0, _, _ := syscall.Syscall(procGetAnycastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 163 | if r0 != 0 { 164 | ret = syscall.Errno(r0) 165 | } 166 | return 167 | } 168 | 169 | func getAnycastIPAddressTable(family AddressFamily, table **mibAnycastIPAddressTable) (ret error) { 170 | r0, _, _ := syscall.Syscall(procGetAnycastIpAddressTable.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0) 171 | if r0 != 0 { 172 | ret = syscall.Errno(r0) 173 | } 174 | return 175 | } 176 | 177 | func getIfEntry2(row *MibIfRow2) (ret error) { 178 | r0, _, _ := syscall.Syscall(procGetIfEntry2.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 179 | if r0 != 0 { 180 | ret = syscall.Errno(r0) 181 | } 182 | return 183 | } 184 | 185 | func getIfTable2Ex(level MibIfEntryLevel, table **mibIfTable2) (ret error) { 186 | r0, _, _ := syscall.Syscall(procGetIfTable2Ex.Addr(), 2, uintptr(level), uintptr(unsafe.Pointer(table)), 0) 187 | if r0 != 0 { 188 | ret = syscall.Errno(r0) 189 | } 190 | return 191 | } 192 | 193 | func getIPForwardEntry2(route *MibIPforwardRow2) (ret error) { 194 | r0, _, _ := syscall.Syscall(procGetIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0) 195 | if r0 != 0 { 196 | ret = syscall.Errno(r0) 197 | } 198 | return 199 | } 200 | 201 | func getIPForwardTable2(family AddressFamily, table **mibIPforwardTable2) (ret error) { 202 | r0, _, _ := syscall.Syscall(procGetIpForwardTable2.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0) 203 | if r0 != 0 { 204 | ret = syscall.Errno(r0) 205 | } 206 | return 207 | } 208 | 209 | func getIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) { 210 | r0, _, _ := syscall.Syscall(procGetIpInterfaceEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 211 | if r0 != 0 { 212 | ret = syscall.Errno(r0) 213 | } 214 | return 215 | } 216 | 217 | func getIPInterfaceTable(family AddressFamily, table **mibIPInterfaceTable) (ret error) { 218 | r0, _, _ := syscall.Syscall(procGetIpInterfaceTable.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0) 219 | if r0 != 0 { 220 | ret = syscall.Errno(r0) 221 | } 222 | return 223 | } 224 | 225 | func getUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) { 226 | r0, _, _ := syscall.Syscall(procGetUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 227 | if r0 != 0 { 228 | ret = syscall.Errno(r0) 229 | } 230 | return 231 | } 232 | 233 | func getUnicastIPAddressTable(family AddressFamily, table **mibUnicastIPAddressTable) (ret error) { 234 | r0, _, _ := syscall.Syscall(procGetUnicastIpAddressTable.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0) 235 | if r0 != 0 { 236 | ret = syscall.Errno(r0) 237 | } 238 | return 239 | } 240 | 241 | func initializeIPForwardEntry(route *MibIPforwardRow2) { 242 | syscall.Syscall(procInitializeIpForwardEntry.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0) 243 | return 244 | } 245 | 246 | func initializeIPInterfaceEntry(row *MibIPInterfaceRow) { 247 | syscall.Syscall(procInitializeIpInterfaceEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 248 | return 249 | } 250 | 251 | func initializeUnicastIPAddressEntry(row *MibUnicastIPAddressRow) { 252 | syscall.Syscall(procInitializeUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 253 | return 254 | } 255 | 256 | func notifyIPInterfaceChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) { 257 | var _p0 uint32 258 | if initialNotification { 259 | _p0 = 1 260 | } 261 | r0, _, _ := syscall.Syscall6(procNotifyIpInterfaceChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0) 262 | if r0 != 0 { 263 | ret = syscall.Errno(r0) 264 | } 265 | return 266 | } 267 | 268 | func notifyRouteChange2(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) { 269 | var _p0 uint32 270 | if initialNotification { 271 | _p0 = 1 272 | } 273 | r0, _, _ := syscall.Syscall6(procNotifyRouteChange2.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0) 274 | if r0 != 0 { 275 | ret = syscall.Errno(r0) 276 | } 277 | return 278 | } 279 | 280 | func notifyUnicastIPAddressChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) { 281 | var _p0 uint32 282 | if initialNotification { 283 | _p0 = 1 284 | } 285 | r0, _, _ := syscall.Syscall6(procNotifyUnicastIpAddressChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0) 286 | if r0 != 0 { 287 | ret = syscall.Errno(r0) 288 | } 289 | return 290 | } 291 | 292 | func setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *DnsInterfaceSettings) (ret error) { 293 | ret = procSetInterfaceDnsSettings.Find() 294 | if ret != nil { 295 | return 296 | } 297 | r0, _, _ := syscall.Syscall6(procSetInterfaceDnsSettings.Addr(), 5, uintptr(guid1), uintptr(guid2), uintptr(guid3), uintptr(guid4), uintptr(unsafe.Pointer(settings)), 0) 298 | if r0 != 0 { 299 | ret = syscall.Errno(r0) 300 | } 301 | return 302 | } 303 | 304 | func setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *DnsInterfaceSettings) (ret error) { 305 | ret = procSetInterfaceDnsSettings.Find() 306 | if ret != nil { 307 | return 308 | } 309 | r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 3, uintptr(guid1), uintptr(guid2), uintptr(unsafe.Pointer(settings))) 310 | if r0 != 0 { 311 | ret = syscall.Errno(r0) 312 | } 313 | return 314 | } 315 | 316 | func setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *DnsInterfaceSettings) (ret error) { 317 | ret = procSetInterfaceDnsSettings.Find() 318 | if ret != nil { 319 | return 320 | } 321 | r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 2, uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(settings)), 0) 322 | if r0 != 0 { 323 | ret = syscall.Errno(r0) 324 | } 325 | return 326 | } 327 | 328 | func setIPForwardEntry2(route *MibIPforwardRow2) (ret error) { 329 | r0, _, _ := syscall.Syscall(procSetIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0) 330 | if r0 != 0 { 331 | ret = syscall.Errno(r0) 332 | } 333 | return 334 | } 335 | 336 | func setIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) { 337 | r0, _, _ := syscall.Syscall(procSetIpInterfaceEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 338 | if r0 != 0 { 339 | ret = syscall.Errno(r0) 340 | } 341 | return 342 | } 343 | 344 | func setUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) { 345 | r0, _, _ := syscall.Syscall(procSetUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) 346 | if r0 != 0 { 347 | ret = syscall.Errno(r0) 348 | } 349 | return 350 | } 351 | -------------------------------------------------------------------------------- /wintun.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Trisia/simpletun/35a5d952394dfaaa24ec240fd7d8727cf2b3640a/wintun.dll --------------------------------------------------------------------------------