[sys] windows: add GetIfTable2Ex, GetIpInterface{Entry,Table}, GetUnicastIpAddressTable

3 views
Skip to first unread message

Ian Chen (Gerrit)

unread,
Feb 12, 2026, 5:18:52 AM (13 days ago) Feb 12
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Ian Chen has uploaded the change for review

Commit message

windows: add GetIfTable2Ex, GetIpInterface{Entry,Table}, GetUnicastIpAddressTable

GetIfTable2Ex retrieves the MIB-II interface table.

GetIpInterfaceEntry retrieves IP information for the specified interface.

GetIpInterfaceTable retrieves the IP interface entries.

GetUnicastIpAddressTable retrieves the unicast IP address table.
Change-Id: If9f619cb48da204da3bac8b429b3231432337b0a

Change diff

diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go
index d766436..9cab50a 100644
--- a/windows/syscall_windows.go
+++ b/windows/syscall_windows.go
@@ -892,9 +892,13 @@
//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
//sys getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx
//sys GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex
+//sys GetIfTable2Ex(level uint32, table **MibIfTable2) (errcode error) = iphlpapi.GetIfTable2Ex
//sys GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) = iphlpapi.GetIpForwardEntry2
//sys GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) = iphlpapi.GetIpForwardTable2
+//sys GetIpInterfaceEntry(row *MibIpInterfaceRow) (errcode error) = iphlpapi.GetIpInterfaceEntry
+//sys GetIpInterfaceTable(family uint16, table **MibIpInterfaceTable) (errcode error) = iphlpapi.GetIpInterfaceTable
//sys GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry
+//sys GetUnicastIpAddressTable(family uint16, table **MibUnicastIpAddressTable) (errcode error) = iphlpapi.GetUnicastIpAddressTable
//sys FreeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable
//sys NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange
//sys NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyRouteChange2
diff --git a/windows/types_windows.go b/windows/types_windows.go
index d5658a1..3324a92 100644
--- a/windows/types_windows.go
+++ b/windows/types_windows.go
@@ -2320,6 +2320,26 @@
OutQLen uint64
}

+// MIB_IF_TABLE_LEVEL enumeration from netioapi.h or
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ne-netioapi-mib_if_table_level.
+const (
+ MibIfTableNormal = 0
+ MibIfTableRaw = 1
+ MibIfTableNormalWithoutStatistics = 2
+)
+
+// MibIfTable2 contains a table of logical and physical interface entries. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_if_table2.
+type MibIfTable2 struct {
+ NumEntries uint32
+ Table [1]MibIfRow2
+}
+
+// Rows returns the logical and physical interface entries in the table.
+func (t *MibIfTable2) Rows() []MibIfRow2 {
+ return unsafe.Slice(&t.Table[0], t.NumEntries)
+}
+
// IP_ADDRESS_PREFIX stores an IP address prefix. See
// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-ip_address_prefix.
type IpAddressPrefix struct {
@@ -2413,6 +2433,18 @@
CreationTimeStamp Filetime
}

+// MibUnicastIpAddressTable contains a table of unicast IP address entries. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_table.
+type MibUnicastIpAddressTable struct {
+ NumEntries uint32
+ Table [1]MibUnicastIpAddressRow
+}
+
+// Rows returns the unicast IP address entries in the table.
+func (t *MibUnicastIpAddressTable) Rows() []MibUnicastIpAddressRow {
+ return unsafe.Slice(&t.Table[0], t.NumEntries)
+}
+
const ScopeLevelCount = 16

// MIB_IPINTERFACE_ROW stores interface management information for a particular IP address family on a network interface.
@@ -2455,6 +2487,18 @@
DisableDefaultRoutes uint8
}

+// MibIpInterfaceTable contains a table of IP interface entries. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipinterface_table.
+type MibIpInterfaceTable struct {
+ NumEntries uint32
+ Table [1]MibIpInterfaceRow
+}
+
+// Rows returns the IP interface entries in the table.
+func (t *MibIpInterfaceTable) Rows() []MibIpInterfaceRow {
+ return unsafe.Slice(&t.Table[0], t.NumEntries)
+}
+
// Console related constants used for the mode parameter to SetConsoleMode. See
// https://docs.microsoft.com/en-us/windows/console/setconsolemode for details.

diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go
index fe7a4ea..a506ac0 100644
--- a/windows/zsyscall_windows.go
+++ b/windows/zsyscall_windows.go
@@ -188,9 +188,13 @@
procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx")
procGetIfEntry = modiphlpapi.NewProc("GetIfEntry")
procGetIfEntry2Ex = modiphlpapi.NewProc("GetIfEntry2Ex")
+ procGetIfTable2Ex = modiphlpapi.NewProc("GetIfTable2Ex")
procGetIpForwardEntry2 = modiphlpapi.NewProc("GetIpForwardEntry2")
procGetIpForwardTable2 = modiphlpapi.NewProc("GetIpForwardTable2")
+ procGetIpInterfaceEntry = modiphlpapi.NewProc("GetIpInterfaceEntry")
+ procGetIpInterfaceTable = modiphlpapi.NewProc("GetIpInterfaceTable")
procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry")
+ procGetUnicastIpAddressTable = modiphlpapi.NewProc("GetUnicastIpAddressTable")
procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange")
procNotifyRouteChange2 = modiphlpapi.NewProc("NotifyRouteChange2")
procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange")
@@ -1674,6 +1678,14 @@
return
}

+func GetIfTable2Ex(level uint32, table **MibIfTable2) (errcode error) {
+ r0, _, _ := syscall.SyscallN(procGetIfTable2Ex.Addr(), uintptr(level), uintptr(unsafe.Pointer(table)))
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
func GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) {
r0, _, _ := syscall.SyscallN(procGetIpForwardEntry2.Addr(), uintptr(unsafe.Pointer(row)))
if r0 != 0 {
@@ -1690,6 +1702,22 @@
return
}

+func GetIpInterfaceEntry(row *MibIpInterfaceRow) (errcode error) {
+ r0, _, _ := syscall.SyscallN(procGetIpInterfaceEntry.Addr(), uintptr(unsafe.Pointer(row)))
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
+func GetIpInterfaceTable(family uint16, table **MibIpInterfaceTable) (errcode error) {
+ r0, _, _ := syscall.SyscallN(procGetIpInterfaceTable.Addr(), uintptr(family), uintptr(unsafe.Pointer(table)))
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) {
r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressEntry.Addr(), uintptr(unsafe.Pointer(row)))
if r0 != 0 {
@@ -1698,6 +1726,14 @@
return
}

+func GetUnicastIpAddressTable(family uint16, table **MibUnicastIpAddressTable) (errcode error) {
+ r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressTable.Addr(), uintptr(family), uintptr(unsafe.Pointer(table)))
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
func NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
var _p0 uint32
if initialNotification {

Change information

Files:
  • M windows/syscall_windows.go
  • M windows/types_windows.go
  • M windows/zsyscall_windows.go
Change size: M
Delta: 3 files changed, 84 insertions(+), 0 deletions(-)
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newchange
Gerrit-Project: sys
Gerrit-Branch: master
Gerrit-Change-Id: If9f619cb48da204da3bac8b429b3231432337b0a
Gerrit-Change-Number: 744880
Gerrit-PatchSet: 1
Gerrit-Owner: Ian Chen <databa...@gmail.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

Alex Brainman (Gerrit)

unread,
Feb 23, 2026, 11:10:46 PM (2 days ago) Feb 23
to Ian Chen, goph...@pubsubhelper.golang.org, Quim Muntal, Brad Fitzpatrick, Gopher Robot, golang-co...@googlegroups.com
Attention needed from Brad Fitzpatrick, Ian Chen and Quim Muntal

Alex Brainman voted and added 4 comments

Votes added by Alex Brainman

Commit-Queue+1

4 comments

Patchset-level comments
File-level comment, Patchset 1 (Latest):
Alex Brainman . resolved

Couple of corrections, otherwise LGTM.

Thank you.

Alex

File windows/types_windows.go
Line 2338, Patchset 1 (Latest):// Rows returns the logical and physical interface entries in the table.
Alex Brainman . unresolved

Remove this method. golang.org/x/sys/windows package should contain only real Windows APIs.

It is easy enough to add similar one line function in your code.

Line 2443, Patchset 1 (Latest):// Rows returns the unicast IP address entries in the table.
Alex Brainman . unresolved

Same. Remove the method.

Line 2497, Patchset 1 (Latest):// Rows returns the IP interface entries in the table.
Alex Brainman . unresolved

Same. Remove the method.

Open in Gerrit

Related details

Attention is currently required from:
  • Brad Fitzpatrick
  • Ian Chen
  • Quim Muntal
Submit Requirements:
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    • requirement is not satisfiedTryBots-Pass
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: sys
    Gerrit-Branch: master
    Gerrit-Change-Id: If9f619cb48da204da3bac8b429b3231432337b0a
    Gerrit-Change-Number: 744880
    Gerrit-PatchSet: 1
    Gerrit-Owner: Ian Chen <databa...@gmail.com>
    Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
    Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Reviewer: Quim Muntal <quimm...@gmail.com>
    Gerrit-CC: Gopher Robot <go...@golang.org>
    Gerrit-Attention: Quim Muntal <quimm...@gmail.com>
    Gerrit-Attention: Ian Chen <databa...@gmail.com>
    Gerrit-Attention: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Comment-Date: Tue, 24 Feb 2026 04:10:39 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    unsatisfied_requirement
    open
    diffy

    Ian Chen (Gerrit)

    unread,
    Feb 24, 2026, 1:18:35 AM (yesterday) Feb 24
    to goph...@pubsubhelper.golang.org, Go LUCI, Alex Brainman, Quim Muntal, Brad Fitzpatrick, Gopher Robot, golang-co...@googlegroups.com
    Attention needed from Alex Brainman, Brad Fitzpatrick and Quim Muntal

    Ian Chen added 1 comment

    File windows/types_windows.go
    Line 2338, Patchset 1 (Latest):// Rows returns the logical and physical interface entries in the table.
    Alex Brainman . unresolved

    Remove this method. golang.org/x/sys/windows package should contain only real Windows APIs.

    It is easy enough to add similar one line function in your code.

    Ian Chen

    In CL 695195, I included a helper method `(*MibIpForwardTable2).Rows`. The reviewers didn't object to that. In fact, they wanted me to add another helper method on `RawSockaddrInet`, which I didn't do and stated my reasons.

    Removing these helper methods would make the new types inconsistent with the existing `MibIpForwardTable2` I just added months ago. I agree that it's trivial to implement `Rows` in user code, but having `Rows` living in `x/sys/windows` makes the API much easier to use.

    If you still think these should be removed, let me know and I'll remove them.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Alex Brainman
    • Brad Fitzpatrick
    • Quim Muntal
    Submit Requirements:
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: sys
      Gerrit-Branch: master
      Gerrit-Change-Id: If9f619cb48da204da3bac8b429b3231432337b0a
      Gerrit-Change-Number: 744880
      Gerrit-PatchSet: 1
      Gerrit-Owner: Ian Chen <databa...@gmail.com>
      Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
      Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Reviewer: Quim Muntal <quimm...@gmail.com>
      Gerrit-CC: Gopher Robot <go...@golang.org>
      Gerrit-Attention: Quim Muntal <quimm...@gmail.com>
      Gerrit-Attention: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Attention: Alex Brainman <alex.b...@gmail.com>
      Gerrit-Comment-Date: Tue, 24 Feb 2026 06:18:31 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Alex Brainman <alex.b...@gmail.com>
      unsatisfied_requirement
      satisfied_requirement
      open
      diffy

      Alex Brainman (Gerrit)

      unread,
      Feb 24, 2026, 7:09:12 PM (10 hours ago) Feb 24
      to Ian Chen, goph...@pubsubhelper.golang.org, Ian Lance Taylor, Go LUCI, Quim Muntal, Brad Fitzpatrick, Gopher Robot, golang-co...@googlegroups.com
      Attention needed from Brad Fitzpatrick, Ian Chen, Ian Lance Taylor and Quim Muntal

      Alex Brainman added 1 comment

      File windows/types_windows.go
      Line 2338, Patchset 1 (Latest):// Rows returns the logical and physical interface entries in the table.
      Alex Brainman . unresolved

      Remove this method. golang.org/x/sys/windows package should contain only real Windows APIs.

      It is easy enough to add similar one line function in your code.

      Ian Chen

      In CL 695195, I included a helper method `(*MibIpForwardTable2).Rows`. The reviewers didn't object to that. In fact, they wanted me to add another helper method on `RawSockaddrInet`, which I didn't do and stated my reasons.

      Removing these helper methods would make the new types inconsistent with the existing `MibIpForwardTable2` I just added months ago. I agree that it's trivial to implement `Rows` in user code, but having `Rows` living in `x/sys/windows` makes the API much easier to use.

      If you still think these should be removed, let me know and I'll remove them.

      Alex Brainman

      This https://github.com/golang/proposal?tab=readme-ov-file#scope says

      The proposal process should be used for any notable change or addition to the > language, libraries and tools. “Notable” includes (but is not limited to):

      API changes in the main repo and all golang.org/x repos.
      ...

      There is a short list of changes that are typically not in scope for the proposal process:

      ...
      Adding new system call numbers or direct system call wrappers (//sys lines) in golang.org/x/sys.
      Adding new C-equivalent data structures to support those system calls.
      ...

      so my reading of that is that it is OK to add "C-equivalent data structures", but not fictitious methods that we add to "C-equivalent data structures".

      The reasoning for this restriction is that we cannot change the API once we add them.

      But I am OK, if @ia...@golang.org overrides me.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Brad Fitzpatrick
      • Ian Chen
      • Ian Lance Taylor
      • Quim Muntal
      Submit Requirements:
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: sys
      Gerrit-Branch: master
      Gerrit-Change-Id: If9f619cb48da204da3bac8b429b3231432337b0a
      Gerrit-Change-Number: 744880
      Gerrit-PatchSet: 1
      Gerrit-Owner: Ian Chen <databa...@gmail.com>
      Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
      Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Reviewer: Quim Muntal <quimm...@gmail.com>
      Gerrit-CC: Gopher Robot <go...@golang.org>
      Gerrit-CC: Ian Lance Taylor <ia...@golang.org>
      Gerrit-Attention: Quim Muntal <quimm...@gmail.com>
      Gerrit-Attention: Ian Chen <databa...@gmail.com>
      Gerrit-Attention: Ian Lance Taylor <ia...@golang.org>
      Gerrit-Attention: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Comment-Date: Wed, 25 Feb 2026 00:09:02 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Ian Chen <databa...@gmail.com>
      Comment-In-Reply-To: Alex Brainman <alex.b...@gmail.com>
      unsatisfied_requirement
      satisfied_requirement
      open
      diffy
      Reply all
      Reply to author
      Forward
      0 new messages