master ohmu/fastfetch-openbsd / src / detection / netio / netio_sunos.c
ohmu  ·  2026-10-15
 1#include "netio.h"
 2#include "common/debug.h"
 3#include "common/netif.h"
 4#include "common/strutil.h"
 5
 6#include <kstat.h>
 7
 8static inline void kstatFreeWrap(kstat_ctl_t** pkc) {
 9    assert(pkc);
10    if (*pkc) {
11        kstat_close(*pkc);
12    }
13}
14
15const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) {
16    [[gnu::cleanup(kstatFreeWrap)]] kstat_ctl_t* kc = kstat_open();
17    if (!kc) {
18        FF_DEBUG("kstat_open() failed");
19        return "kstat_open() failed";
20    }
21
22    const char* defaultRouteIfName = ffNetifGetDefaultRouteV4()->ifName;
23
24    for (kstat_t* ks = kc->kc_chain; ks; ks = ks->ks_next) {
25        if (!ffStrEquals(ks->ks_class, "net") || !ffStrEquals(ks->ks_module, "link")) {
26            continue;
27        }
28
29        if (options->namePrefix.length && strncmp(ks->ks_name, options->namePrefix.chars, options->namePrefix.length) != 0) {
30            continue;
31        }
32
33        bool isDefaultRoute = ffStrEquals(ks->ks_name, defaultRouteIfName);
34        if (options->defaultRouteOnly && !isDefaultRoute) {
35            continue;
36        }
37
38        if (kstat_read(kc, ks, nullptr) < 0) {
39            continue;
40        }
41
42        FFNetIOResult* counters = FF_LIST_ADD(FFNetIOResult, *result);
43
44        kstat_named_t* wbytes = (kstat_named_t*) kstat_data_lookup(ks, "obytes64");
45        kstat_named_t* rbytes = (kstat_named_t*) kstat_data_lookup(ks, "rbytes64");
46        kstat_named_t* wpkts = (kstat_named_t*) kstat_data_lookup(ks, "opackets64");
47        kstat_named_t* rpkts = (kstat_named_t*) kstat_data_lookup(ks, "ipackets64");
48        kstat_named_t* werrs = (kstat_named_t*) kstat_data_lookup(ks, "oerrors");
49        kstat_named_t* rerrs = (kstat_named_t*) kstat_data_lookup(ks, "ierrors");
50
51        *counters = (FFNetIOResult) {
52            .name = ffStrbufCreateS(ks->ks_name),
53            .txBytes = wbytes->value.ui64,
54            .rxBytes = rbytes->value.ui64,
55            .txPackets = wpkts->value.ui64,
56            .rxPackets = rpkts->value.ui64,
57            .txErrors = werrs->value.ui64,
58            .rxErrors = rerrs->value.ui64,
59            .txDrops = 0, // unsupported
60            .rxDrops = 0,
61            .defaultRoute = isDefaultRoute,
62        };
63
64        if (options->defaultRouteOnly) {
65            break;
66        }
67    }
68
69    return nullptr;
70}