-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
563 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
diff --git a/mobile/golang-issue-no-40569-workaround/interface_linux.go b/mobile/golang-issue-no-40569-workaround/interface_linux.go | ||
index 441ab2f..ed7300d 100644 | ||
--- a/mobile/golang-issue-no-40569-workaround/interface_linux.go | ||
+++ b/mobile/golang-issue-no-40569-workaround/interface_linux.go | ||
@@ -6,6 +6,7 @@ package net | ||
|
||
import ( | ||
"os" | ||
+ "runtime" | ||
"syscall" | ||
"unsafe" | ||
) | ||
@@ -130,7 +131,7 @@ func interfaceAddrTable(ifi *Interface) ([]Addr, error) { | ||
if ifi == nil { | ||
var err error | ||
ift, err = interfaceTable(0) | ||
- if err != nil { | ||
+ if err != nil && (runtime.GOOS != "android" || err != syscall.EACCES) { | ||
return nil, err | ||
} | ||
} | ||
@@ -150,6 +151,16 @@ loop: | ||
break loop | ||
case syscall.RTM_NEWADDR: | ||
ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0])) | ||
+ if ifi == nil && len(ift) == 0 { | ||
+ 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) | ||
+ } | ||
+ } | ||
if len(ift) != 0 || ifi.Index == int(ifam.Index) { | ||
if len(ift) != 0 { | ||
var err error |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
diff --git a/mobile/golang-issue-no-40569-workaround/netlink_linux.go b/mobile/golang-issue-no-40569-workaround/netlink_linux.go | ||
index 2d81070..c16229b 100644 | ||
--- a/mobile/golang-issue-no-40569-workaround/netlink_linux.go | ||
+++ b/mobile/golang-issue-no-40569-workaround/netlink_linux.go | ||
@@ -6,7 +6,10 @@ | ||
|
||
package syscall | ||
|
||
-import "unsafe" | ||
+import ( | ||
+ "runtime" | ||
+ "unsafe" | ||
+) | ||
|
||
// Round the length of a netlink message up to align it properly. | ||
func nlmAlignOf(msglen int) int { | ||
@@ -57,7 +60,9 @@ func NetlinkRIB(proto, family int) ([]byte, error) { | ||
defer Close(s) | ||
sa := &SockaddrNetlink{Family: AF_NETLINK} | ||
if err := Bind(s, sa); err != nil { | ||
- return nil, err | ||
+ if runtime.GOOS != "android" || err != EACCES { | ||
+ return nil, err | ||
+ } | ||
} | ||
wb := newNetlinkRouteRequest(proto, 1, family) | ||
if err := Sendto(s, wb, 0, sa); err != nil { |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#!/bin/bash | ||
set -e | ||
GOSRCDIR=$(dirname $(dirname $(which go)))/src | ||
GOBIN=$(dirname $(dirname $(which go)))/bin/go | ||
INTERFACE_SRC_FILE=$GOSRCDIR/net/interface_linux.go | ||
NETLINK_SRC_FILE=$GOSRCDIR/syscall/netlink_linux.go | ||
sudo cp $INTERFACE_SRC_FILE orig/interface_linux.go.bak | ||
sudo cp $NETLINK_SRC_FILE orig/netlink_linux.go.bak | ||
sudo cp $INTERFACE_SRC_FILE interface_linux.go | ||
sudo cp $NETLINK_SRC_FILE netlink_linux.go | ||
sudo git apply -C1 --recount netlink_linux.patch | ||
sudo git apply -C1 --recount interface_linux.patch | ||
sudo cp interface_linux.go $INTERFACE_SRC_FILE | ||
sudo cp netlink_linux.go $NETLINK_SRC_FILE | ||
sudo rm -rf interface_linux.go netlink_linux.go | ||
sudo $GOBIN install -a net | ||
sudo $GOBIN install -a syscall |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
Adapted from: https://github.com/yan12125/go/blob/7e31413c7a031193a06e8dd4c3f50452f49a6c36/src/net/interface_linux.go | ||
|
||
## Steps to build using gomobile | ||
```sh | ||
$ bash patch.sh | ||
$ gomobile build ... | ||
$ bash unpatch.sh | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#!/bin/bash | ||
set -e | ||
GOSRCDIR=$(dirname $(dirname $(which go)))/src | ||
GOBIN=$(dirname $(dirname $(which go)))/bin/go | ||
INTERFACE_SRC_FILE=$GOSRCDIR/net/interface_linux.go | ||
NETLINK_SRC_FILE=$GOSRCDIR/syscall/netlink_linux.go | ||
sudo cp orig/interface_linux.go.bak $INTERFACE_SRC_FILE | ||
sudo cp orig/netlink_linux.go.bak $NETLINK_SRC_FILE | ||
sudo $GOBIN install -a net | ||
sudo $GOBIN install -a syscall |
280 changes: 280 additions & 0 deletions
280
golang-issue-no-40569-workaround/workaround/interface_linux.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,280 @@ | ||
// 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 ( | ||
"os" | ||
"runtime" | ||
"syscall" | ||
"unsafe" | ||
) | ||
|
||
// 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) ([]Interface, error) { | ||
tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, 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 | ||
loop: | ||
for _, m := range msgs { | ||
switch m.Header.Type { | ||
case syscall.NLMSG_DONE: | ||
break loop | ||
case syscall.RTM_NEWLINK: | ||
ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0])) | ||
if ifindex == 0 || ifindex == int(ifim.Index) { | ||
attrs, err := syscall.ParseNetlinkRouteAttr(&m) | ||
if err != nil { | ||
return nil, os.NewSyscallError("parsenetlinkrouteattr", err) | ||
} | ||
ift = append(ift, *newLink(ifim, attrs)) | ||
if ifindex == int(ifim.Index) { | ||
break loop | ||
} | ||
} | ||
} | ||
} | ||
return ift, nil | ||
} | ||
|
||
const ( | ||
// See linux/if_arp.h. | ||
// Note that Linux doesn't support IPv4 over IPv6 tunneling. | ||
sysARPHardwareIPv4IPv4 = 768 // IPv4 over IPv4 tunneling | ||
sysARPHardwareIPv6IPv6 = 769 // IPv6 over IPv6 tunneling | ||
sysARPHardwareIPv6IPv4 = 776 // IPv6 over IPv4 tunneling | ||
sysARPHardwareGREIPv4 = 778 // any over GRE over IPv4 tunneling | ||
sysARPHardwareGREIPv6 = 823 // any over GRE over IPv6 tunneling | ||
) | ||
|
||
func newLink(ifim *syscall.IfInfomsg, attrs []syscall.NetlinkRouteAttr) *Interface { | ||
ifi := &Interface{Index: int(ifim.Index), Flags: linkFlags(ifim.Flags)} | ||
for _, a := range attrs { | ||
switch a.Attr.Type { | ||
case syscall.IFLA_ADDRESS: | ||
// We never return any /32 or /128 IP address | ||
// prefix on any IP tunnel interface as the | ||
// hardware address. | ||
switch len(a.Value) { | ||
case IPv4len: | ||
switch ifim.Type { | ||
case sysARPHardwareIPv4IPv4, sysARPHardwareGREIPv4, sysARPHardwareIPv6IPv4: | ||
continue | ||
} | ||
case IPv6len: | ||
switch ifim.Type { | ||
case sysARPHardwareIPv6IPv6, sysARPHardwareGREIPv6: | ||
continue | ||
} | ||
} | ||
var nonzero bool | ||
for _, b := range a.Value { | ||
if b != 0 { | ||
nonzero = true | ||
break | ||
} | ||
} | ||
if nonzero { | ||
ifi.HardwareAddr = a.Value[:] | ||
} | ||
case syscall.IFLA_IFNAME: | ||
ifi.Name = string(a.Value[:len(a.Value)-1]) | ||
case syscall.IFLA_MTU: | ||
ifi.MTU = int(*(*uint32)(unsafe.Pointer(&a.Value[:4][0]))) | ||
} | ||
} | ||
return ifi | ||
} | ||
|
||
func linkFlags(rawFlags uint32) Flags { | ||
var f Flags | ||
if rawFlags&syscall.IFF_UP != 0 { | ||
f |= FlagUp | ||
} | ||
if rawFlags&syscall.IFF_BROADCAST != 0 { | ||
f |= FlagBroadcast | ||
} | ||
if rawFlags&syscall.IFF_LOOPBACK != 0 { | ||
f |= FlagLoopback | ||
} | ||
if rawFlags&syscall.IFF_POINTOPOINT != 0 { | ||
f |= FlagPointToPoint | ||
} | ||
if rawFlags&syscall.IFF_MULTICAST != 0 { | ||
f |= 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 *Interface) ([]Addr, 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 | ||
if ifi == nil { | ||
var err error | ||
ift, err = interfaceTable(0) | ||
if err != nil && (runtime.GOOS != "android" || err != syscall.EACCES) { | ||
return nil, err | ||
} | ||
} | ||
ifat, err := addrTable(ift, ifi, msgs) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return ifat, nil | ||
} | ||
|
||
func addrTable(ift []Interface, ifi *Interface, msgs []syscall.NetlinkMessage) ([]Addr, error) { | ||
var ifat []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 ifi == nil && len(ift) == 0 { | ||
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) | ||
} | ||
} | ||
if len(ift) != 0 || ifi.Index == int(ifam.Index) { | ||
if len(ift) != 0 { | ||
var err error | ||
ifi, err = interfaceByIndex(ift, int(ifam.Index)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
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) 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 &IPNet{IP: IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3]), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv4len)} | ||
case syscall.AF_INET6: | ||
ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv6len)} | ||
copy(ifa.IP, a.Value[:]) | ||
return ifa | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// interfaceMulticastAddrTable returns addresses for a specific | ||
// interface. | ||
func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) { | ||
ifmat4 := parseProcNetIGMP("/proc/net/igmp", ifi) | ||
ifmat6 := parseProcNetIGMP6("/proc/net/igmp6", ifi) | ||
return append(ifmat4, ifmat6...), nil | ||
} | ||
|
||
func parseProcNetIGMP(path string, ifi *Interface) []Addr { | ||
fd, err := open(path) | ||
if err != nil { | ||
return nil | ||
} | ||
defer fd.close() | ||
var ( | ||
ifmat []Addr | ||
name string | ||
) | ||
fd.readLine() // skip first line | ||
b := make([]byte, IPv4len) | ||
for l, ok := fd.readLine(); ok; l, ok = fd.readLine() { | ||
f := splitAtBytes(l, " :\r\t\n") | ||
if len(f) < 4 { | ||
continue | ||
} | ||
switch { | ||
case l[0] != ' ' && l[0] != '\t': // new interface line | ||
name = f[1] | ||
case len(f[0]) == 8: | ||
if ifi == nil || name == ifi.Name { | ||
// The Linux kernel puts the IP | ||
// address in /proc/net/igmp in native | ||
// endianness. | ||
for i := 0; i+1 < len(f[0]); i += 2 { | ||
b[i/2], _ = xtoi2(f[0][i:i+2], 0) | ||
} | ||
i := *(*uint32)(unsafe.Pointer(&b[:4][0])) | ||
ifma := &IPAddr{IP: IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i))} | ||
ifmat = append(ifmat, ifma) | ||
} | ||
} | ||
} | ||
return ifmat | ||
} | ||
|
||
func parseProcNetIGMP6(path string, ifi *Interface) []Addr { | ||
fd, err := open(path) | ||
if err != nil { | ||
return nil | ||
} | ||
defer fd.close() | ||
var ifmat []Addr | ||
b := make([]byte, IPv6len) | ||
for l, ok := fd.readLine(); ok; l, ok = fd.readLine() { | ||
f := splitAtBytes(l, " \r\t\n") | ||
if len(f) < 6 { | ||
continue | ||
} | ||
if ifi == nil || f[1] == ifi.Name { | ||
for i := 0; i+1 < len(f[2]); i += 2 { | ||
b[i/2], _ = xtoi2(f[2][i:i+2], 0) | ||
} | ||
ifma := &IPAddr{IP: IP{b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]}} | ||
ifmat = append(ifmat, ifma) | ||
} | ||
} | ||
return ifmat | ||
} |
Oops, something went wrong.