直播:后台 JWT 推流、前台画中画;WebRTC 服务与 Nginx WebSocket 代理
Made-with: Cursor
This commit is contained in:
1
server/vendor/github.com/wlynxg/anet/.gitignore
generated
vendored
Normal file
1
server/vendor/github.com/wlynxg/anet/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.idea
|
||||
28
server/vendor/github.com/wlynxg/anet/LICENSE
generated
vendored
Normal file
28
server/vendor/github.com/wlynxg/anet/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2023, wlynxg
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
119
server/vendor/github.com/wlynxg/anet/README.md
generated
vendored
Normal file
119
server/vendor/github.com/wlynxg/anet/README.md
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
## Introduction
|
||||
In response to the modifications made to the permissions for accessing system MAC addresses in Android 11, ordinary applications encounter several main issues when using NETLINK sockets:
|
||||
|
||||
- Not allowing bind operations on `NETLINK` sockets.
|
||||
- Not permitting the use of the `RTM_GETLINK` functionality.
|
||||
|
||||
For detailed information, please refer to: https://developer.android.com/training/articles/user-data-ids#mac-11-plus
|
||||
|
||||
As a result of the aforementioned reasons, using `net.Interfaces()` and `net.InterfaceAddrs()` from the Go net package in the Android environment leads to the `route ip+net: netlinkrib: permission denied` error.
|
||||
|
||||
You can find specific issue details here: https://github.com/golang/go/issues/40569
|
||||
|
||||
To address the issue of using the Go net package in the Android environment, we have made partial modifications to its source code to ensure proper functionality on Android.
|
||||
|
||||
I have fully resolved the issues with `net.InterfaceAddrs()`.
|
||||
|
||||
However, for `net.Interfaces()`, we have only addressed some problems, as the following issues still remain:
|
||||
- It can only return interfaces with IP addresses.
|
||||
- It cannot return hardware MAC addresses.
|
||||
|
||||
Nevertheless, the fixed `net.Interfaces()` function now aligns with the Android API's `NetworkInterface.getNetworkInterfaces()` and can be used normally in most scenarios.
|
||||
|
||||
The specific fix logic includes:
|
||||
|
||||
Removing the `Bind()` operation on `Netlink` sockets in the `NetlinkRIB()` function.
|
||||
Using `ioctl` based on the Index number returned by `RTM_GETADDR` to retrieve the network card's name, MTU, and flags.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Test Code
|
||||
### net.Interface()
|
||||
use `net.Interface()`:
|
||||
```go
|
||||
func RawInterface() {
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, i := range interfaces {
|
||||
log.Println(i)
|
||||
}
|
||||
}
|
||||
```
|
||||
result:
|
||||
```
|
||||
panic: route ip+net: netlinkrib: permission denied
|
||||
```
|
||||
|
||||
use `anet.Interface()`:
|
||||
```go
|
||||
func AnetInterface() {
|
||||
interfaces, err := anet.Interfaces()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, i := range interfaces {
|
||||
log.Println(i)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
result:
|
||||
```
|
||||
{1 65536 lo up|loopback|running}
|
||||
{15 1400 rmnet_data1 up|running}
|
||||
{24 1500 wlan0 up|broadcast|multicast|running}
|
||||
{3 1500 dummy0 up|broadcast|running}
|
||||
{4 1500 ifb0 up|broadcast|running}
|
||||
{5 1500 ifb1 up|broadcast|running}
|
||||
{12 1500 ifb2 up|broadcast|running}
|
||||
{14 1500 rmnet_data0 up|running}
|
||||
{16 1400 rmnet_data2 up|running}
|
||||
{17 1400 rmnet_data3 up|running}
|
||||
```
|
||||
|
||||
### net.InterfaceAddrs()
|
||||
use `net.InterfaceAddrs()`:
|
||||
```go
|
||||
func NetInterfaceAddrs() {
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
log.Println(addr)
|
||||
}
|
||||
}
|
||||
```
|
||||
result:
|
||||
```
|
||||
panic: route ip+net: netlinkrib: permission denied
|
||||
```
|
||||
|
||||
use `anet.InterfaceAddrs()`:
|
||||
```go
|
||||
func AnetInterfaceAddrs() {
|
||||
addrs, err := anet.InterfaceAddrs()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
log.Println(addr)
|
||||
}
|
||||
}
|
||||
```
|
||||
result:
|
||||
```
|
||||
127.0.0.1/8
|
||||
::1/128
|
||||
...
|
||||
192.168.6.143/24
|
||||
fe80::7e4f:4446:eb3:1eb8/64
|
||||
```
|
||||
22
server/vendor/github.com/wlynxg/anet/README_zh.md
generated
vendored
Normal file
22
server/vendor/github.com/wlynxg/anet/README_zh.md
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
针对Android 11之后对访问系统MAC地址的权限进行了修改的问题,导致普通应用在调用`NETLINK`套接字时会遇到以下几个主要问题:
|
||||
- 不允许对`NETLINK`套接字进行`bind`操作。
|
||||
- 不允许调用`RTM_GETLINK`功能。
|
||||
|
||||
详细说明可以在此链接找到:https://developer.android.com/training/articles/user-data-ids#mac-11-plus
|
||||
|
||||
由于上述两个原因,导致在安卓环境下使用Go net包中的`net.Interfaces()`和`net.InterfaceAddrs()`时会抛出`route ip+net: netlinkrib: permission denied`错误。
|
||||
具体 issue 可见:https://github.com/golang/go/issues/40569
|
||||
|
||||
为了解决在安卓环境下使用Go net包的问题,我们对其源代码进行了部分改造,以使其能够在Android上正常工作。
|
||||
|
||||
对于`net.InterfaceAddrs()`,我已经完全解决了其中的问题;
|
||||
对于`net.Interfaces()`,我只解决了部分问题,目前仍存在以下问题:
|
||||
- 只能返回具有IP地址的接口。
|
||||
- 不能返回硬件的MAC地址。
|
||||
|
||||
但是修复后的`net.Interfaces()`函数现在与Android API的`NetworkInterface.getNetworkInterfaces()`保持一致,在大多数情况下可正常使用。
|
||||
|
||||
具体修复逻辑包括:
|
||||
|
||||
- 取消了`NetlinkRIB()`函数中对`Netlink`套接字的`Bind()`操作。
|
||||
- 根据`RTM_GETADDR`返回的Index号,使用`ioctl`获取其网卡的名称、MTU和标志位。
|
||||
30
server/vendor/github.com/wlynxg/anet/interface.go
generated
vendored
Normal file
30
server/vendor/github.com/wlynxg/anet/interface.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
//go:build !android
|
||||
// +build !android
|
||||
|
||||
package anet
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// Interfaces returns a list of the system's network interfaces.
|
||||
func Interfaces() ([]net.Interface, error) {
|
||||
return net.Interfaces()
|
||||
}
|
||||
|
||||
// InterfaceAddrs returns a list of the system's unicast interface
|
||||
// addresses.
|
||||
//
|
||||
// The returned list does not identify the associated interface; use
|
||||
// Interfaces and Interface.Addrs for more detail.
|
||||
func InterfaceAddrs() ([]net.Addr, error) {
|
||||
return net.InterfaceAddrs()
|
||||
}
|
||||
|
||||
// InterfaceAddrsByInterface returns a list of the system's unicast
|
||||
// interface addresses by specific interface.
|
||||
func InterfaceAddrsByInterface(ifi *net.Interface) ([]net.Addr, error) {
|
||||
return ifi.Addrs()
|
||||
}
|
||||
|
||||
func SetAndroidVersion(version uint) {}
|
||||
419
server/vendor/github.com/wlynxg/anet/interface_android.go
generated
vendored
Normal file
419
server/vendor/github.com/wlynxg/anet/interface_android.go
generated
vendored
Normal file
@@ -0,0 +1,419 @@
|
||||
package anet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
android11 = 11
|
||||
)
|
||||
|
||||
var (
|
||||
androidVersion uint
|
||||
errInvalidInterface = errors.New("invalid network interface")
|
||||
errInvalidInterfaceIndex = errors.New("invalid network interface index")
|
||||
errInvalidInterfaceName = errors.New("invalid network interface name")
|
||||
errNoSuchInterface = errors.New("no such network interface")
|
||||
errNoSuchMulticastInterface = errors.New("no such multicast network interface")
|
||||
)
|
||||
|
||||
type ifReq [40]byte
|
||||
|
||||
// Interfaces returns a list of the system's network interfaces.
|
||||
func Interfaces() ([]net.Interface, error) {
|
||||
if androidVersion < android11 {
|
||||
return net.Interfaces()
|
||||
}
|
||||
|
||||
ift, err := interfaceTable(0)
|
||||
if err != nil {
|
||||
return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
|
||||
}
|
||||
if len(ift) != 0 {
|
||||
zoneCache.update(ift, false)
|
||||
}
|
||||
return ift, nil
|
||||
}
|
||||
|
||||
// InterfaceAddrs returns a list of the system's unicast interface
|
||||
// addresses.
|
||||
//
|
||||
// The returned list does not identify the associated interface; use
|
||||
// Interfaces and Interface.Addrs for more detail.
|
||||
func InterfaceAddrs() ([]net.Addr, error) {
|
||||
if androidVersion < android11 {
|
||||
return net.InterfaceAddrs()
|
||||
}
|
||||
|
||||
ifat, err := interfaceAddrTable(nil)
|
||||
if err != nil {
|
||||
err = &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
|
||||
}
|
||||
return ifat, err
|
||||
}
|
||||
|
||||
// InterfaceByIndex returns the interface specified by index.
|
||||
//
|
||||
// On Solaris, it returns one of the logical network interfaces
|
||||
// sharing the logical data link; for more precision use
|
||||
// InterfaceByName.
|
||||
func InterfaceByIndex(index int) (*net.Interface, error) {
|
||||
if androidVersion < android11 {
|
||||
return net.InterfaceByIndex(index)
|
||||
}
|
||||
|
||||
if index <= 0 {
|
||||
return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceIndex}
|
||||
}
|
||||
ift, err := interfaceTable(index)
|
||||
if err != nil {
|
||||
return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
|
||||
}
|
||||
ifi, err := interfaceByIndex(ift, index)
|
||||
if err != nil {
|
||||
err = &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
|
||||
}
|
||||
return ifi, err
|
||||
}
|
||||
|
||||
// InterfaceByName returns the interface specified by name.
|
||||
func InterfaceByName(name string) (*net.Interface, error) {
|
||||
if name == "" {
|
||||
return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceName}
|
||||
}
|
||||
ift, err := interfaceTable(0)
|
||||
if err != nil {
|
||||
return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
|
||||
}
|
||||
if len(ift) != 0 {
|
||||
zoneCache.update(ift, false)
|
||||
}
|
||||
for _, ifi := range ift {
|
||||
if name == ifi.Name {
|
||||
return &ifi, nil
|
||||
}
|
||||
}
|
||||
return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errNoSuchInterface}
|
||||
}
|
||||
|
||||
// InterfaceAddrsByInterface returns a list of the system's unicast
|
||||
// interface addresses by specific interface.
|
||||
func InterfaceAddrsByInterface(ifi *net.Interface) ([]net.Addr, error) {
|
||||
if ifi == nil {
|
||||
return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
|
||||
}
|
||||
|
||||
if androidVersion < android11 {
|
||||
return ifi.Addrs()
|
||||
}
|
||||
|
||||
ifat, err := interfaceAddrTable(ifi)
|
||||
if err != nil {
|
||||
err = &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
|
||||
}
|
||||
return ifat, err
|
||||
}
|
||||
|
||||
// SetAndroidVersion set the Android environment in which the program runs.
|
||||
// The Android system version number can be obtained through
|
||||
// `android.os.Build.VERSION.RELEASE` of the Android framework.
|
||||
func SetAndroidVersion(version uint) {
|
||||
androidVersion = version
|
||||
}
|
||||
|
||||
// An ipv6ZoneCache represents a cache holding partial network
|
||||
// interface information. It is used for reducing the cost of IPv6
|
||||
// addressing scope zone resolution.
|
||||
//
|
||||
// Multiple names sharing the index are managed by first-come
|
||||
// first-served basis for consistency.
|
||||
type ipv6ZoneCache struct {
|
||||
sync.RWMutex // guard the following
|
||||
lastFetched time.Time // last time routing information was fetched
|
||||
toIndex map[string]int // interface name to its index
|
||||
toName map[int]string // interface index to its name
|
||||
}
|
||||
|
||||
//go:linkname zoneCache net.zoneCache
|
||||
var zoneCache ipv6ZoneCache
|
||||
|
||||
// update refreshes the network interface information if the cache was last
|
||||
// updated more than 1 minute ago, or if force is set. It reports whether the
|
||||
// cache was updated.
|
||||
func (zc *ipv6ZoneCache) update(ift []net.Interface, force bool) (updated bool) {
|
||||
zc.Lock()
|
||||
defer zc.Unlock()
|
||||
now := time.Now()
|
||||
if !force && zc.lastFetched.After(now.Add(-60*time.Second)) {
|
||||
return false
|
||||
}
|
||||
zc.lastFetched = now
|
||||
if len(ift) == 0 {
|
||||
var err error
|
||||
if ift, err = interfaceTable(0); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
zc.toIndex = make(map[string]int, len(ift))
|
||||
zc.toName = make(map[int]string, len(ift))
|
||||
for _, ifi := range ift {
|
||||
zc.toIndex[ifi.Name] = ifi.Index
|
||||
if _, ok := zc.toName[ifi.Index]; !ok {
|
||||
zc.toName[ifi.Index] = ifi.Name
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// If the ifindex is zero, interfaceTable returns mappings of all
|
||||
// network interfaces. Otherwise it returns a mapping of a specific
|
||||
// interface.
|
||||
func interfaceTable(ifindex int) ([]net.Interface, error) {
|
||||
tab, err := 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 []net.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 := newLink(ifam)
|
||||
if ifi != nil {
|
||||
ift = append(ift, *ifi)
|
||||
}
|
||||
if ifindex == int(ifam.Index) {
|
||||
break loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ift, nil
|
||||
}
|
||||
|
||||
func newLink(ifam *syscall.IfAddrmsg) *net.Interface {
|
||||
ift := &net.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 linkFlags(rawFlags uint32) net.Flags {
|
||||
var f net.Flags
|
||||
if rawFlags&syscall.IFF_UP != 0 {
|
||||
f |= net.FlagUp
|
||||
}
|
||||
if rawFlags&syscall.IFF_RUNNING != 0 {
|
||||
f |= net.FlagRunning
|
||||
}
|
||||
if rawFlags&syscall.IFF_BROADCAST != 0 {
|
||||
f |= net.FlagBroadcast
|
||||
}
|
||||
if rawFlags&syscall.IFF_LOOPBACK != 0 {
|
||||
f |= net.FlagLoopback
|
||||
}
|
||||
if rawFlags&syscall.IFF_POINTOPOINT != 0 {
|
||||
f |= net.FlagPointToPoint
|
||||
}
|
||||
if rawFlags&syscall.IFF_MULTICAST != 0 {
|
||||
f |= net.FlagMulticast
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// If the ifi is nil, interfaceAddrTable returns addresses for all
|
||||
// network interfaces. Otherwise it returns addresses for a specific
|
||||
// interface.
|
||||
func interfaceAddrTable(ifi *net.Interface) ([]net.Addr, error) {
|
||||
tab, err := 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 []net.Interface
|
||||
if ifi == nil {
|
||||
var err error
|
||||
ift, err = interfaceTable(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
ifat, err := addrTable(ift, ifi, msgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ifat, nil
|
||||
}
|
||||
|
||||
func addrTable(ift []net.Interface, ifi *net.Interface, msgs []syscall.NetlinkMessage) ([]net.Addr, error) {
|
||||
var ifat []net.Addr
|
||||
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 len(ift) != 0 || ifi.Index == int(ifam.Index) {
|
||||
attrs, err := syscall.ParseNetlinkRouteAttr(&m)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("parsenetlinkrouteattr", err)
|
||||
}
|
||||
ifa := newAddr(ifam, attrs)
|
||||
if ifa != nil {
|
||||
ifat = append(ifat, ifa)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ifat, nil
|
||||
}
|
||||
|
||||
func newAddr(ifam *syscall.IfAddrmsg, attrs []syscall.NetlinkRouteAttr) net.Addr {
|
||||
var ipPointToPoint bool
|
||||
// Seems like we need to make sure whether the IP interface
|
||||
// stack consists of IP point-to-point numbered or unnumbered
|
||||
// addressing.
|
||||
for _, a := range attrs {
|
||||
if a.Attr.Type == syscall.IFA_LOCAL {
|
||||
ipPointToPoint = true
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, a := range attrs {
|
||||
if ipPointToPoint && a.Attr.Type == syscall.IFA_ADDRESS {
|
||||
continue
|
||||
}
|
||||
switch ifam.Family {
|
||||
case syscall.AF_INET:
|
||||
return &net.IPNet{IP: net.IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3]), Mask: net.CIDRMask(int(ifam.Prefixlen), 8*net.IPv4len)}
|
||||
case syscall.AF_INET6:
|
||||
ifa := &net.IPNet{IP: make(net.IP, net.IPv6len), Mask: net.CIDRMask(int(ifam.Prefixlen), 8*net.IPv6len)}
|
||||
copy(ifa.IP, a.Value[:])
|
||||
return ifa
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func interfaceByIndex(ift []net.Interface, index int) (*net.Interface, error) {
|
||||
for _, ifi := range ift {
|
||||
if index == ifi.Index {
|
||||
return &ifi, nil
|
||||
}
|
||||
}
|
||||
return nil, errNoSuchInterface
|
||||
}
|
||||
|
||||
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 -1, syscall.EINVAL
|
||||
}
|
||||
|
||||
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer syscall.Close(fd)
|
||||
|
||||
var ifr ifReq
|
||||
copy(ifr[:], name)
|
||||
err = ioctl(fd, syscall.SIOCGIFMTU, unsafe.Pointer(&ifr[0]))
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
return int(*(*int32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ]))), nil
|
||||
}
|
||||
|
||||
func nameToFlags(name string) (net.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
|
||||
}
|
||||
179
server/vendor/github.com/wlynxg/anet/netlink_android.go
generated
vendored
Normal file
179
server/vendor/github.com/wlynxg/anet/netlink_android.go
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
// 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.
|
||||
|
||||
// Netlink sockets and messages
|
||||
|
||||
package anet
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Round the length of a netlink message up to align it properly.
|
||||
func nlmAlignOf(msglen int) int {
|
||||
return (msglen + syscall.NLMSG_ALIGNTO - 1) & ^(syscall.NLMSG_ALIGNTO - 1)
|
||||
}
|
||||
|
||||
// Round the length of a netlink route attribute up to align it
|
||||
// properly.
|
||||
func rtaAlignOf(attrlen int) int {
|
||||
return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
|
||||
}
|
||||
|
||||
// NetlinkRouteRequest represents a request message to receive routing
|
||||
// and link states from the kernel.
|
||||
type NetlinkRouteRequest struct {
|
||||
Header syscall.NlMsghdr
|
||||
Data syscall.RtGenmsg
|
||||
}
|
||||
|
||||
func (rr *NetlinkRouteRequest) toWireFormat() []byte {
|
||||
b := make([]byte, rr.Header.Len)
|
||||
*(*uint32)(unsafe.Pointer(&b[0:4][0])) = rr.Header.Len
|
||||
*(*uint16)(unsafe.Pointer(&b[4:6][0])) = rr.Header.Type
|
||||
*(*uint16)(unsafe.Pointer(&b[6:8][0])) = rr.Header.Flags
|
||||
*(*uint32)(unsafe.Pointer(&b[8:12][0])) = rr.Header.Seq
|
||||
*(*uint32)(unsafe.Pointer(&b[12:16][0])) = rr.Header.Pid
|
||||
b[16] = byte(rr.Data.Family)
|
||||
return b
|
||||
}
|
||||
|
||||
func newNetlinkRouteRequest(proto, seq, family int) []byte {
|
||||
rr := &NetlinkRouteRequest{}
|
||||
rr.Header.Len = uint32(syscall.NLMSG_HDRLEN + syscall.SizeofRtGenmsg)
|
||||
rr.Header.Type = uint16(proto)
|
||||
rr.Header.Flags = syscall.NLM_F_DUMP | syscall.NLM_F_REQUEST
|
||||
rr.Header.Seq = uint32(seq)
|
||||
rr.Data.Family = uint8(family)
|
||||
return rr.toWireFormat()
|
||||
}
|
||||
|
||||
// NetlinkRIB returns routing information base, as known as RIB, which
|
||||
// consists of network facility information, states and parameters.
|
||||
func NetlinkRIB(proto, family int) ([]byte, error) {
|
||||
s, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW|syscall.SOCK_CLOEXEC, syscall.NETLINK_ROUTE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.Close(s)
|
||||
sa := &syscall.SockaddrNetlink{Family: syscall.AF_NETLINK}
|
||||
|
||||
wb := newNetlinkRouteRequest(proto, 1, family)
|
||||
if err := syscall.Sendto(s, wb, 0, sa); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lsa, err := syscall.Getsockname(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lsanl, ok := lsa.(*syscall.SockaddrNetlink)
|
||||
if !ok {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
var tab []byte
|
||||
rbNew := make([]byte, syscall.Getpagesize())
|
||||
done:
|
||||
for {
|
||||
rb := rbNew
|
||||
nr, _, err := syscall.Recvfrom(s, rb, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if nr < syscall.NLMSG_HDRLEN {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
rb = rb[:nr]
|
||||
tab = append(tab, rb...)
|
||||
msgs, err := ParseNetlinkMessage(rb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, m := range msgs {
|
||||
if m.Header.Seq != 1 || m.Header.Pid != lsanl.Pid {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
if m.Header.Type == syscall.NLMSG_DONE {
|
||||
break done
|
||||
}
|
||||
if m.Header.Type == syscall.NLMSG_ERROR {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
}
|
||||
}
|
||||
return tab, nil
|
||||
}
|
||||
|
||||
// NetlinkMessage represents a netlink message.
|
||||
type NetlinkMessage struct {
|
||||
Header syscall.NlMsghdr
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// ParseNetlinkMessage parses b as an array of netlink messages and
|
||||
// returns the slice containing the NetlinkMessage structures.
|
||||
func ParseNetlinkMessage(b []byte) ([]NetlinkMessage, error) {
|
||||
var msgs []NetlinkMessage
|
||||
for len(b) >= syscall.NLMSG_HDRLEN {
|
||||
h, dbuf, dlen, err := netlinkMessageHeaderAndData(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := NetlinkMessage{Header: *h, Data: dbuf[:int(h.Len)-syscall.NLMSG_HDRLEN]}
|
||||
msgs = append(msgs, m)
|
||||
b = b[dlen:]
|
||||
}
|
||||
return msgs, nil
|
||||
}
|
||||
|
||||
func netlinkMessageHeaderAndData(b []byte) (*syscall.NlMsghdr, []byte, int, error) {
|
||||
h := (*syscall.NlMsghdr)(unsafe.Pointer(&b[0]))
|
||||
l := nlmAlignOf(int(h.Len))
|
||||
if int(h.Len) < syscall.NLMSG_HDRLEN || l > len(b) {
|
||||
return nil, nil, 0, syscall.EINVAL
|
||||
}
|
||||
return h, b[syscall.NLMSG_HDRLEN:], l, nil
|
||||
}
|
||||
|
||||
// NetlinkRouteAttr represents a netlink route attribute.
|
||||
type NetlinkRouteAttr struct {
|
||||
Attr syscall.RtAttr
|
||||
Value []byte
|
||||
}
|
||||
|
||||
// ParseNetlinkRouteAttr parses m's payload as an array of netlink
|
||||
// route attributes and returns the slice containing the
|
||||
// NetlinkRouteAttr structures.
|
||||
func ParseNetlinkRouteAttr(m *NetlinkMessage) ([]NetlinkRouteAttr, error) {
|
||||
var b []byte
|
||||
switch m.Header.Type {
|
||||
case syscall.RTM_NEWLINK, syscall.RTM_DELLINK:
|
||||
b = m.Data[syscall.SizeofIfInfomsg:]
|
||||
case syscall.RTM_NEWADDR, syscall.RTM_DELADDR:
|
||||
b = m.Data[syscall.SizeofIfAddrmsg:]
|
||||
case syscall.RTM_NEWROUTE, syscall.RTM_DELROUTE:
|
||||
b = m.Data[syscall.SizeofRtMsg:]
|
||||
default:
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
var attrs []NetlinkRouteAttr
|
||||
for len(b) >= syscall.SizeofRtAttr {
|
||||
a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ra := NetlinkRouteAttr{Attr: *a, Value: vbuf[:int(a.Len)-syscall.SizeofRtAttr]}
|
||||
attrs = append(attrs, ra)
|
||||
b = b[alen:]
|
||||
}
|
||||
return attrs, nil
|
||||
}
|
||||
|
||||
func netlinkRouteAttrAndValue(b []byte) (*syscall.RtAttr, []byte, int, error) {
|
||||
a := (*syscall.RtAttr)(unsafe.Pointer(&b[0]))
|
||||
if int(a.Len) < syscall.SizeofRtAttr || int(a.Len) > len(b) {
|
||||
return nil, nil, 0, syscall.EINVAL
|
||||
}
|
||||
return a, b[syscall.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
|
||||
}
|
||||
Reference in New Issue
Block a user