fix: package reference causes compilation failure

This commit is contained in:
wlynxg 2023-11-14 16:48:59 +08:00
parent ad4f8ff11f
commit bff8d409eb
3 changed files with 162 additions and 159 deletions

View File

@ -1,154 +0,0 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package net
import (
"bytes"
"os"
"syscall"
"unsafe"
)
type ifReq [40]byte
// Starting from Android 11, it is no longer possible to retrieve network card information
// using the RTM_GETLINK method.
// As a result, alternative methods need to be employed.
// After considering the Android NetworkInterface.getNetworkInterfaces() method,
// I opted to utilize the RTM_GETADDR + ioctl approach to obtain network card information.
// However, it appears that retrieving the
// HWAddr (hardware address) of the network card is currently not achievable.
func interfaceTableAndroid(ifindex int) ([]Interface, error) {
tab, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
if err != nil {
return nil, os.NewSyscallError("netlinkrib", err)
}
msgs, err := syscall.ParseNetlinkMessage(tab)
if err != nil {
return nil, os.NewSyscallError("parsenetlinkmessage", err)
}
var ift []Interface
im := make(map[uint32]struct{})
loop:
for _, m := range msgs {
switch m.Header.Type {
case syscall.NLMSG_DONE:
break loop
case syscall.RTM_NEWADDR:
ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
if _, ok := im[ifam.Index]; ok {
continue
} else {
im[ifam.Index] = struct{}{}
}
if ifindex == 0 || ifindex == int(ifam.Index) {
ifi := newLinkAndroid(ifam)
if ifi != nil {
ift = append(ift, *ifi)
}
if ifindex == int(ifam.Index) {
break loop
}
}
}
}
return ift, nil
}
// According to the network card Index, get the Name, MTU and Flags of the network card through ioctl
func newLinkAndroid(ifam *syscall.IfAddrmsg) *Interface {
ift := &Interface{Index: int(ifam.Index)}
name, err := indexToName(ifam.Index)
if err != nil {
return nil
}
ift.Name = name
mtu, err := nameToMTU(name)
if err != nil {
return nil
}
ift.MTU = mtu
flags, err := nameToFlags(name)
if err != nil {
return nil
}
ift.Flags = flags
return ift
}
func ioctl(fd int, req uint, arg unsafe.Pointer) error {
_, _, e1 := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 {
return e1
}
return nil
}
func indexToName(index uint32) (string, error) {
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0)
if err != nil {
return "", err
}
defer syscall.Close(fd)
var ifr ifReq
*(*uint32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ])) = index
err = ioctl(fd, syscall.SIOCGIFNAME, unsafe.Pointer(&ifr[0]))
if err != nil {
return "", err
}
return string(bytes.Trim(ifr[:syscall.IFNAMSIZ], "\x00")), nil
}
func nameToMTU(name string) (int, error) {
// Leave room for terminating NULL byte.
if len(name) >= syscall.IFNAMSIZ {
return 0, syscall.EINVAL
}
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0)
if err != nil {
return 0, err
}
defer syscall.Close(fd)
var ifr ifReq
copy(ifr[:], name)
err = ioctl(fd, syscall.SIOCGIFMTU, unsafe.Pointer(&ifr[0]))
if err != nil {
return 0, err
}
return int(*(*int32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ]))), nil
}
func nameToFlags(name string) (Flags, error) {
// Leave room for terminating NULL byte.
if len(name) >= syscall.IFNAMSIZ {
return 0, syscall.EINVAL
}
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0)
if err != nil {
return 0, err
}
defer syscall.Close(fd)
var ifr ifReq
copy(ifr[:], name)
err = ioctl(fd, syscall.SIOCGIFFLAGS, unsafe.Pointer(&ifr[0]))
if err != nil {
return 0, err
}
return linkFlags(*(*uint32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ]))), nil
}

View File

@ -12,12 +12,12 @@ import (
)
// If the ifindex is zero, interfaceTable returns mappings of all
// network interfaces. Otherwise it returns a mapping of a specific
// network interfaces. Otherwise, it returns a mapping of a specific
// interface.
func interfaceTable(ifindex int) ([]Interface, error) {
tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
if err != nil {
if os.IsPermission(err) && runtime.GOOS == "android" {
if runtime.GOOS == "android" && os.IsPermission(err) {
return interfaceTableAndroid(ifindex)
}
return nil, os.NewSyscallError("netlinkrib", err)
@ -274,3 +274,157 @@ func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
}
return ifmat
}
// Starting from Android 11, it is no longer possible to retrieve network card information
// using the RTM_GETLINK method.
// As a result, alternative methods need to be employed.
// After considering the Android NetworkInterface.getNetworkInterfaces() method,
// I opted to utilize the RTM_GETADDR + ioctl approach to obtain network card information.
// However, it appears that retrieving the
// HWAddr (hardware address) of the network card is currently not achievable.
func interfaceTableAndroid(ifindex int) ([]Interface, error) {
tab, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
if err != nil {
return nil, os.NewSyscallError("netlinkrib", err)
}
msgs, err := syscall.ParseNetlinkMessage(tab)
if err != nil {
return nil, os.NewSyscallError("parsenetlinkmessage", err)
}
var ift []Interface
im := make(map[uint32]struct{})
loop:
for _, m := range msgs {
switch m.Header.Type {
case syscall.NLMSG_DONE:
break loop
case syscall.RTM_NEWADDR:
ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
if _, ok := im[ifam.Index]; ok {
continue
} else {
im[ifam.Index] = struct{}{}
}
if ifindex == 0 || ifindex == int(ifam.Index) {
ifi := newLinkAndroid(ifam)
if ifi != nil {
ift = append(ift, *ifi)
}
if ifindex == int(ifam.Index) {
break loop
}
}
}
}
return ift, nil
}
// According to the network card Index, get the Name, MTU and Flags of the network card through ioctl
func newLinkAndroid(ifam *syscall.IfAddrmsg) *Interface {
ift := &Interface{Index: int(ifam.Index)}
name, err := indexToName(ifam.Index)
if err != nil {
return nil
}
ift.Name = name
mtu, err := nameToMTU(name)
if err != nil {
return nil
}
ift.MTU = mtu
flags, err := nameToFlags(name)
if err != nil {
return nil
}
ift.Flags = flags
return ift
}
func ioctl(fd int, req uint, arg unsafe.Pointer) error {
_, _, e1 := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 {
return e1
}
return nil
}
func indexToName(index uint32) (string, error) {
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0)
if err != nil {
return "", err
}
defer syscall.Close(fd)
var ifr [40]byte
*(*uint32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ])) = index
err = ioctl(fd, syscall.SIOCGIFNAME, unsafe.Pointer(&ifr[0]))
if err != nil {
return "", err
}
return string(trim(ifr[:syscall.IFNAMSIZ])), nil
}
func nameToMTU(name string) (int, error) {
// Leave room for terminating NULL byte.
if len(name) >= syscall.IFNAMSIZ {
return 0, syscall.EINVAL
}
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0)
if err != nil {
return 0, err
}
defer syscall.Close(fd)
var ifr [40]byte
copy(ifr[:], name)
err = ioctl(fd, syscall.SIOCGIFMTU, unsafe.Pointer(&ifr[0]))
if err != nil {
return 0, err
}
return int(*(*int32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ]))), nil
}
func nameToFlags(name string) (Flags, error) {
// Leave room for terminating NULL byte.
if len(name) >= syscall.IFNAMSIZ {
return 0, syscall.EINVAL
}
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0)
if err != nil {
return 0, err
}
defer syscall.Close(fd)
var ifr [40]byte
copy(ifr[:], name)
err = ioctl(fd, syscall.SIOCGIFFLAGS, unsafe.Pointer(&ifr[0]))
if err != nil {
return 0, err
}
return linkFlags(*(*uint32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ]))), nil
}
func trim(data []byte) []byte {
if len(data) == 0 {
return nil
}
index := len(data) - 1
for ; index > 0 && data[index] == 0; index-- {
}
result := make([]byte, index+1)
copy(result, data)
return result
}

View File

@ -7,8 +7,7 @@
package syscall
import (
err2 "errors"
"io/fs"
"internal/oserror"
"runtime"
"sync"
"unsafe"
@ -69,7 +68,11 @@ func NetlinkRIB(proto, family int) ([]byte, error) {
sa := &SockaddrNetlink{Family: AF_NETLINK}
if err := Bind(s, sa); err != nil {
// Bind operation of Netlink socket is prohibited in Android11 and later versions
if !(runtime.GOOS == "android" && err2.Is(err, fs.ErrPermission)) {
if runtime.GOOS != "android" {
return nil, err
}
if e, ok := err.(Errno); !ok && !e.Is(oserror.ErrPermission) {
return nil, err
}
}