-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.go
More file actions
151 lines (132 loc) · 4.39 KB
/
main.go
File metadata and controls
151 lines (132 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Query tethering and network interface status via INetworkManagementService.
//
// Uses the "network_management" system service to list network interfaces,
// check tethering status, and query interface configurations.
// Replaces the previous vendor offload HAL approach with system-level APIs.
//
// Note: Some tethering methods were removed in Android API 36+.
//
// Build:
//
// GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o build/softap_tether_offload ./examples/softap_tether_offload/
// adb push softap_tether_offload /data/local/tmp/ && adb shell /data/local/tmp/softap_tether_offload
package main
import (
"context"
"fmt"
"os"
"strings"
genOs "github.com/AndroidGoLab/binder/android/os"
"github.com/AndroidGoLab/binder/binder"
"github.com/AndroidGoLab/binder/binder/versionaware"
"github.com/AndroidGoLab/binder/kernelbinder"
"github.com/AndroidGoLab/binder/servicemanager"
)
func main() {
ctx := context.Background()
driver, err := kernelbinder.Open(ctx, binder.WithMapSize(128*1024))
if err != nil {
fmt.Fprintf(os.Stderr, "open binder: %v\n", err)
os.Exit(1)
}
defer driver.Close(ctx)
transport, err := versionaware.NewTransport(ctx, driver, 0)
if err != nil {
fmt.Fprintf(os.Stderr, "version-aware transport: %v\n", err)
os.Exit(1)
}
sm := servicemanager.New(transport)
svc, err := sm.GetService(ctx, servicemanager.NetworkmanagementService)
if err != nil {
fmt.Fprintf(os.Stderr, "get network_management service: %v\n", err)
os.Exit(1)
}
netMgr := genOs.NewNetworkManagementServiceProxy(svc)
// List all network interfaces.
ifaces, err := netMgr.ListInterfaces(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "ListInterfaces: %v\n", err)
} else {
fmt.Printf("Network interfaces (%d):\n", len(ifaces))
for _, iface := range ifaces {
fmt.Printf(" %s\n", iface)
}
}
// Check tethering status (may be removed in API 36+).
fmt.Println()
tethering, err := netMgr.IsTetheringStarted(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "IsTetheringStarted: %v\n", err)
fmt.Fprintf(os.Stderr, " (this method was removed in Android API 36)\n")
} else {
fmt.Printf("Tethering active: %v\n", tethering)
}
// List tethered interfaces (may be removed in API 36+).
tethered, err := netMgr.ListTetheredInterfaces(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "ListTetheredInterfaces: %v\n", err)
fmt.Fprintf(os.Stderr, " (this method was removed in Android API 36)\n")
} else if len(tethered) == 0 {
fmt.Println("Tethered interfaces: (none)")
} else {
fmt.Printf("Tethered interfaces: %v\n", tethered)
}
// Check bandwidth control.
fmt.Println()
bwCtrl, err := netMgr.IsBandwidthControlEnabled(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "IsBandwidthControlEnabled: %v\n", err)
} else {
fmt.Printf("Bandwidth control enabled: %v\n", bwCtrl)
}
// Check IP forwarding (may be removed in API 36+).
fwd, err := netMgr.GetIpForwardingEnabled(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "GetIpForwardingEnabled: %v\n", err)
} else {
fmt.Printf("IP forwarding enabled: %v\n", fwd)
}
// Try to read network statistics from procfs as a complement.
fmt.Println()
printNetStats(ifaces)
}
// printNetStats reads basic traffic counters from /proc/net/dev for the
// given interfaces.
func printNetStats(ifaces []string) {
data, err := os.ReadFile("/proc/net/dev")
if err != nil {
fmt.Fprintf(os.Stderr, "read /proc/net/dev: %v\n", err)
return
}
// Build a set of interfaces we care about.
ifaceSet := make(map[string]bool, len(ifaces))
for _, iface := range ifaces {
ifaceSet[iface] = true
}
fmt.Println("Network traffic statistics:")
fmt.Printf(" %-15s %15s %15s\n", "Interface", "RX bytes", "TX bytes")
fmt.Printf(" %-15s %15s %15s\n", "---------", "--------", "--------")
lines := strings.Split(string(data), "\n")
for _, line := range lines[2:] { // skip header lines
var iface string
var rxBytes, txBytes int64
var dummy int64
// Format: iface: rx_bytes rx_packets ... tx_bytes tx_packets ...
n, _ := fmt.Sscanf(line, " %s %d %d %d %d %d %d %d %d %d",
&iface, &rxBytes, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &txBytes)
if n < 10 {
continue
}
// Remove trailing colon from iface name.
if len(iface) > 0 && iface[len(iface)-1] == ':' {
iface = iface[:len(iface)-1]
}
if !ifaceSet[iface] {
continue
}
if rxBytes == 0 && txBytes == 0 {
continue
}
fmt.Printf(" %-15s %15d %15d\n", iface, rxBytes, txBytes)
}
}