github.com/apernet/sing-tun@v0.2.6-0.20240323130332-b9f6511036ad/internal/winipcfg/winipcfg.go (about) 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 }