Skip to content

Commit 8e53e52

Browse files
committed
feat: use net_get_interfaces to read network adapter
Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
1 parent b6741b0 commit 8e53e52

File tree

14 files changed

+513
-201
lines changed

14 files changed

+513
-201
lines changed

.gitignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
# PHP Coding Style
2-
vendor/
3-
.php_cs.cache
1+
/.php_cs.cache
2+
/tests/.phpunit.result.cache
3+
/vendor

lib/OperatingSystems/DefaultOs.php

Lines changed: 61 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,13 @@
2525

2626
use OCA\ServerInfo\Resources\Disk;
2727
use OCA\ServerInfo\Resources\Memory;
28+
use OCA\ServerInfo\Resources\NetInterface;
29+
use RuntimeException;
2830

2931
class DefaultOs implements IOperatingSystem {
32+
private const AF_INET = 2;
33+
private const AF_INET6 = 10;
34+
3035
public function supported(): bool {
3136
return true;
3237
}
@@ -36,7 +41,7 @@ public function getMemory(): Memory {
3641

3742
try {
3843
$meminfo = $this->readContent('/proc/meminfo');
39-
} catch (\RuntimeException $e) {
44+
} catch (RuntimeException $e) {
4045
return $data;
4146
}
4247

@@ -79,7 +84,7 @@ public function getCpuName(): string {
7984

8085
try {
8186
$cpuinfo = $this->readContent('/proc/cpuinfo');
82-
} catch (\RuntimeException $e) {
87+
} catch (RuntimeException $e) {
8388
return $data;
8489
}
8590

@@ -100,7 +105,7 @@ public function getCpuName(): string {
100105

101106
$pattern = '/processor\s+:\s(.+)/';
102107

103-
$result = preg_match_all($pattern, $cpuinfo, $matches);
108+
preg_match_all($pattern, $cpuinfo, $matches);
104109
$cores = count($matches[1]);
105110

106111
if ($cores === 1) {
@@ -121,7 +126,7 @@ public function getUptime(): int {
121126

122127
try {
123128
$uptime = $this->readContent('/proc/uptime');
124-
} catch (\RuntimeException $e) {
129+
} catch (RuntimeException $e) {
125130
return $data;
126131
}
127132

@@ -141,50 +146,52 @@ public function getNetworkInfo(): array {
141146
}
142147

143148
public function getNetworkInterfaces(): array {
144-
$interfaces = glob('/sys/class/net/*') ?: [];
145-
$result = [];
149+
$data = [];
146150

147-
foreach ($interfaces as $interface) {
148-
$iface = [];
149-
$iface['interface'] = basename($interface);
150-
$iface['mac'] = shell_exec('ip addr show dev ' . $iface['interface'] . ' | grep "link/ether " | cut -d \' \' -f 6 | cut -f 1 -d \'/\'');
151-
$iface['ipv4'] = shell_exec('ip addr show dev ' . $iface['interface'] . ' | grep "inet " | cut -d \' \' -f 6 | cut -f 1 -d \'/\'');
152-
$iface['ipv6'] = shell_exec('ip -o -6 addr show ' . $iface['interface'] . ' | sed -e \'s/^.*inet6 \([^ ]\+\).*/\1/\'');
153-
if ($iface['interface'] !== 'lo') {
154-
$iface['status'] = shell_exec('cat /sys/class/net/' . $iface['interface'] . '/operstate');
155-
$iface['speed'] = (int)shell_exec('cat /sys/class/net/' . $iface['interface'] . '/speed');
156-
if (isset($iface['speed']) && $iface['speed'] > 0) {
157-
if ($iface['speed'] >= 1000) {
158-
$iface['speed'] = $iface['speed'] / 1000 . ' Gbps';
159-
} else {
160-
$iface['speed'] = $iface['speed'] . ' Mbps';
161-
}
162-
} else {
163-
$iface['speed'] = 'unknown';
151+
foreach ($this->getNetInterfaces() as $interfaceName => $interface) {
152+
$netInterface = new NetInterface($interfaceName, $interface['up']);
153+
$data[] = $netInterface;
154+
155+
foreach ($interface['unicast'] as $unicast) {
156+
if ($unicast['family'] === self::AF_INET) {
157+
$netInterface->addIPv4($unicast['address']);
164158
}
165-
$duplex = shell_exec('cat /sys/class/net/' . $iface['interface'] . '/duplex');
166-
if (isset($duplex) && $duplex !== '') {
167-
$iface['duplex'] = 'Duplex: ' . $duplex;
159+
if ($unicast['family'] === self::AF_INET6) {
160+
$netInterface->addIPv6($unicast['address']);
161+
}
162+
}
163+
164+
if ($netInterface->isLoopback()) {
165+
continue;
166+
}
167+
168+
$interfacePath = '/sys/class/net/' . $interfaceName;
169+
170+
try {
171+
$netInterface->setMAC($this->readContent($interfacePath . '/address'));
172+
173+
$speed = (int)$this->readContent($interfacePath . '/speed');
174+
if ($speed >= 1000) {
175+
$netInterface->setSpeed($speed / 1000 . ' Gbps');
168176
} else {
169-
$iface['duplex'] = '';
177+
$netInterface->setSpeed($speed . ' Mbps');
170178
}
171-
} else {
172-
$iface['status'] = 'up';
173-
$iface['speed'] = 'unknown';
174-
$iface['duplex'] = '';
179+
180+
$netInterface->setDuplex($this->readContent($interfacePath . '/duplex'));
181+
} catch (RuntimeException $e) {
182+
// unable to read interface data
175183
}
176-
$result[] = $iface;
177184
}
178185

179-
return $result;
186+
return $data;
180187
}
181188

182189
public function getDiskInfo(): array {
183190
$data = [];
184191

185192
try {
186193
$disks = $this->executeCommand('df -TPk');
187-
} catch (\RuntimeException $e) {
194+
} catch (RuntimeException $e) {
188195
return $data;
189196
}
190197

@@ -227,7 +234,7 @@ public function getThermalZones(): array {
227234
$tzone['hash'] = md5($thermalZone);
228235
$tzone['type'] = $this->readContent($thermalZone . '/type');
229236
$tzone['temp'] = (float)((int)($this->readContent($thermalZone . '/temp')) / 1000);
230-
} catch (\RuntimeException $e) {
237+
} catch (RuntimeException $e) {
231238
continue;
232239
}
233240
$result[] = $tzone;
@@ -236,19 +243,35 @@ public function getThermalZones(): array {
236243
return $result;
237244
}
238245

246+
/**
247+
* @throws RuntimeException
248+
*/
239249
protected function readContent(string $filename): string {
240250
$data = @file_get_contents($filename);
241251
if ($data === false || $data === '') {
242-
throw new \RuntimeException('Unable to read: "' . $filename . '"');
252+
throw new RuntimeException('Unable to read: "' . $filename . '"');
243253
}
244-
return $data;
254+
return trim($data);
245255
}
246256

247257
protected function executeCommand(string $command): string {
248258
$output = @shell_exec(escapeshellcmd($command));
249259
if ($output === false || $output === null || $output === '') {
250-
throw new \RuntimeException('No output for command: "' . $command . '"');
260+
throw new RuntimeException('No output for command: "' . $command . '"');
251261
}
252262
return $output;
253263
}
264+
265+
/**
266+
* Wrapper for net_get_interfaces
267+
*
268+
* @throws RuntimeException
269+
*/
270+
protected function getNetInterfaces(): array {
271+
$data = net_get_interfaces();
272+
if ($data === false) {
273+
throw new RuntimeException('Unable to get network interfaces');
274+
}
275+
return $data;
276+
}
254277
}

lib/OperatingSystems/FreeBSD.php

Lines changed: 59 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,13 @@
2525

2626
use OCA\ServerInfo\Resources\Disk;
2727
use OCA\ServerInfo\Resources\Memory;
28+
use OCA\ServerInfo\Resources\NetInterface;
29+
use RuntimeException;
2830

2931
class FreeBSD implements IOperatingSystem {
32+
private const AF_INET = 2;
33+
private const AF_INET6 = 28;
34+
3035
public function supported(): bool {
3136
return false;
3237
}
@@ -36,7 +41,7 @@ public function getMemory(): Memory {
3641

3742
try {
3843
$swapinfo = $this->executeCommand('/usr/sbin/swapinfo -k');
39-
} catch (\RuntimeException $e) {
44+
} catch (RuntimeException $e) {
4045
$swapinfo = '';
4146
}
4247

@@ -53,7 +58,7 @@ public function getMemory(): Memory {
5358

5459
try {
5560
$meminfo = $this->executeCommand('/sbin/sysctl -n hw.realmem hw.pagesize vm.stats.vm.v_inactive_count vm.stats.vm.v_cache_count vm.stats.vm.v_free_count');
56-
} catch (\RuntimeException $e) {
61+
} catch (RuntimeException $e) {
5762
$meminfo = '';
5863
}
5964

@@ -80,7 +85,7 @@ public function getCpuName(): string {
8085
} else {
8186
$data = $model . ' (' . $cores . ' cores)';
8287
}
83-
} catch (\RuntimeException $e) {
88+
} catch (RuntimeException $e) {
8489
return $data;
8590
}
8691
return $data;
@@ -89,7 +94,7 @@ public function getCpuName(): string {
8994
public function getTime(): string {
9095
try {
9196
return $this->executeCommand('date');
92-
} catch (\RuntimeException $e) {
97+
} catch (RuntimeException $e) {
9398
return '';
9499
}
95100
}
@@ -102,7 +107,7 @@ public function getUptime(): int {
102107
preg_match("/[\d]+/", $shell_boot, $boottime);
103108
$time = $this->executeCommand('date +%s');
104109
$uptime = (int)$time - (int)$boottime[0];
105-
} catch (\RuntimeException $e) {
110+
} catch (RuntimeException $e) {
106111
return $uptime;
107112
}
108113
return $uptime;
@@ -122,91 +127,69 @@ public function getNetworkInfo(): array {
122127
if (count($gw[0]) > 0) {
123128
$result['gateway'] = implode(", ", array_map("trim", $gw[0]));
124129
}
125-
} catch (\RuntimeException $e) {
130+
} catch (RuntimeException $e) {
126131
return $result;
127132
}
128133
return $result;
129134
}
130135

131136
public function getNetworkInterfaces(): array {
132-
$result = [];
137+
$data = [];
133138

134-
try {
135-
$ifconfig = $this->executeCommand('/sbin/ifconfig -a');
136-
} catch (\RuntimeException $e) {
137-
return $result;
138-
}
139+
foreach ($this->getNetInterfaces() as $interfaceName => $interface) {
140+
$netInterface = new NetInterface($interfaceName, $interface['up']);
141+
$data[] = $netInterface;
139142

140-
preg_match_all("/^(?<=(?!\t)).*(?=:)/m", $ifconfig, $interfaces);
143+
foreach ($interface['unicast'] as $unicast) {
144+
if ($unicast['family'] === self::AF_INET) {
145+
$netInterface->addIPv4($unicast['address']);
146+
}
147+
if ($unicast['family'] === self::AF_INET6) {
148+
$netInterface->addIPv6($unicast['address']);
149+
}
150+
}
141151

142-
foreach ($interfaces[0] as $interface) {
143-
$iface = [];
144-
$iface['interface'] = $interface;
152+
if ($netInterface->isLoopback()) {
153+
continue;
154+
}
145155

146156
try {
147-
$intface = $this->executeCommand('/sbin/ifconfig ' . $iface['interface']);
148-
} catch (\RuntimeException $e) {
157+
$details = $this->executeCommand('/sbin/ifconfig ' . $interfaceName);
158+
} catch (RuntimeException $e) {
149159
continue;
150160
}
151161

152-
preg_match_all("/(?<=inet ).\S*/m", $intface, $ipv4);
153-
preg_match_all("/(?<=inet6 )((.*(?=%))|(.\S*))/m", $intface, $ipv6);
154-
$iface['ipv4'] = implode(' ', $ipv4[0]);
155-
$iface['ipv6'] = implode(' ', $ipv6[0]);
156-
157-
if ($iface['interface'] !== 'lo0') {
158-
preg_match_all("/(?<=ether ).*/m", $intface, $mac);
159-
preg_match("/(?<=status: ).*/m", $intface, $status);
160-
preg_match("/\b[0-9].*?(?=base)/m", $intface, $speed);
161-
preg_match("/(?<=\<).*(?=-)/m", $intface, $duplex);
162-
163-
if (isset($mac[0])) {
164-
$iface['mac'] = implode(' ', $mac[0]);
165-
}
166-
167-
if (isset($speed[0])) {
168-
$iface['speed'] = $speed[0];
169-
}
170-
171-
if (isset($status[0])) {
172-
$iface['status'] = $status[0];
173-
} else {
174-
$iface['status'] = 'active';
175-
}
162+
preg_match("/(?<=ether ).*/m", $details, $mac);
163+
if (isset($mac[0])) {
164+
$netInterface->setMAC($mac[0]);
165+
}
176166

177-
if (isset($iface['speed'])) {
178-
if (strpos($iface['speed'], 'G')) {
179-
$iface['speed'] = rtrim($iface['speed'], 'G');
180-
$iface['speed'] = $iface['speed'] . ' Gbps';
181-
} else {
182-
$iface['speed'] = $iface['speed'] . ' Mbps';
183-
}
167+
preg_match("/\b[0-9].*?(?=base)/m", $details, $speed);
168+
if (isset($speed[0])) {
169+
if (substr($speed[0], -1) === 'G') {
170+
$netInterface->setSpeed(rtrim($speed[0], 'G') . ' Gbps');
184171
} else {
185-
$iface['speed'] = 'unknown';
172+
$netInterface->setSpeed($speed[0] . ' Mbps');
186173
}
174+
}
187175

188-
if (isset($duplex[0])) {
189-
$iface['duplex'] = 'Duplex: ' . $duplex[0];
190-
} else {
191-
$iface['duplex'] = '';
192-
}
193-
} else {
194-
$iface['status'] = 'active';
195-
$iface['speed'] = 'unknown';
196-
$iface['duplex'] = '';
176+
preg_match("/(?<=\<).*(?=-)/m", $details, $duplex);
177+
if (isset($duplex[0])) {
178+
$netInterface->setDuplex($duplex[0]);
197179
}
198-
$result[] = $iface;
180+
181+
unset($mac, $speed, $duplex);
199182
}
200183

201-
return $result;
184+
return $data;
202185
}
203186

204187
public function getDiskInfo(): array {
205188
$data = [];
206189

207190
try {
208191
$disks = $this->executeCommand('df -TPk');
209-
} catch (\RuntimeException $e) {
192+
} catch (RuntimeException $e) {
210193
return $data;
211194
}
212195

@@ -245,8 +228,21 @@ public function getThermalZones(): array {
245228
protected function executeCommand(string $command): string {
246229
$output = @shell_exec(escapeshellcmd($command));
247230
if ($output === null || $output === '' || $output === false) {
248-
throw new \RuntimeException('No output for command: "' . $command . '"');
231+
throw new RuntimeException('No output for command: "' . $command . '"');
249232
}
250233
return $output;
251234
}
235+
236+
/**
237+
* Wrapper for net_get_interfaces
238+
*
239+
* @throws RuntimeException
240+
*/
241+
protected function getNetInterfaces(): array {
242+
$data = net_get_interfaces();
243+
if ($data === false) {
244+
throw new RuntimeException('Unable to get network interfaces');
245+
}
246+
return $data;
247+
}
252248
}

0 commit comments

Comments
 (0)