From 24a6efa22793321dd9e10a557870039b7beaf6b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 16:26:15 +0800 Subject: [PATCH] NetUsage: finish first working version --- CMakeLists.txt | 7 + src/common/commandoption.c | 3 + src/common/init.c | 2 + src/common/modules.c | 1 + src/common/netif/netif.h | 9 ++ src/common/netif/netif_bsd.c | 96 ++++++++++++++ src/common/netif/netif_linux.c | 25 ++++ src/common/netif/netif_windows.c | 27 ++++ src/detection/localip/localip_linux.c | 120 +---------------- src/detection/localip/localip_windows.c | 39 ++---- src/detection/netusage/netusage.c | 65 +++++++++ src/detection/netusage/netusage.h | 2 +- src/detection/netusage/netusage_bsd.c | 23 ++-- src/detection/netusage/netusage_linux.c | 2 +- src/detection/netusage/netusage_windows.c | 2 +- src/fastfetch.h | 1 + src/modules/localip/localip.c | 10 +- src/modules/modules.h | 1 + src/modules/netusage/netusage.c | 155 ++++++++++++++++++++++ src/modules/netusage/netusage.h | 14 ++ src/modules/netusage/option.h | 11 ++ src/modules/options.h | 1 + 22 files changed, 453 insertions(+), 163 deletions(-) create mode 100644 src/common/netif/netif.h create mode 100644 src/common/netif/netif_bsd.c create mode 100644 src/common/netif/netif_linux.c create mode 100644 src/common/netif/netif_windows.c create mode 100644 src/detection/netusage/netusage.c create mode 100644 src/modules/netusage/netusage.c create mode 100644 src/modules/netusage/netusage.h create mode 100644 src/modules/netusage/option.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4390f3bc0..c3b47e5cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -277,6 +277,7 @@ set(LIBFASTFETCH_SRC src/detection/gpu/gpu.c src/detection/locale/locale.c src/detection/media/media.c + src/detection/netusage/netusage.c src/detection/opencl/opencl.c src/detection/os/os.c src/detection/packages/packages.c @@ -319,6 +320,7 @@ set(LIBFASTFETCH_SRC src/modules/localip/localip.c src/modules/memory/memory.c src/modules/monitor/monitor.c + src/modules/netusage/netusage.c src/modules/opencl/opencl.c src/modules/opengl/opengl.c src/modules/os/os.c @@ -359,6 +361,7 @@ if(LINUX) list(APPEND LIBFASTFETCH_SRC src/common/dbus.c src/common/io/io_unix.c + src/common/netif/netif_linux.c src/common/networking_linux.c src/common/processing_linux.c src/detection/battery/battery_linux.c @@ -411,6 +414,7 @@ if(LINUX) elseif(ANDROID) list(APPEND LIBFASTFETCH_SRC src/common/io/io_unix.c + src/common/netif/netif_linux.c src/common/networking_linux.c src/common/processing_linux.c src/detection/battery/battery_android.c @@ -457,6 +461,7 @@ elseif(BSD) list(APPEND LIBFASTFETCH_SRC src/common/dbus.c src/common/io/io_unix.c + src/common/netif/netif_bsd.c src/common/networking_linux.c src/common/processing_linux.c src/common/sysctl.c @@ -510,6 +515,7 @@ elseif(BSD) elseif(APPLE) list(APPEND LIBFASTFETCH_SRC src/common/io/io_unix.c + src/common/netif/netif_bsd.c src/common/networking_linux.c src/common/processing_linux.c src/common/sysctl.c @@ -559,6 +565,7 @@ elseif(APPLE) elseif(WIN32) list(APPEND LIBFASTFETCH_SRC src/common/io/io_windows.c + src/common/netif/netif_windows.c src/common/networking_windows.c src/common/processing_windows.c src/detection/battery/battery_windows.c diff --git a/src/common/commandoption.c b/src/common/commandoption.c index 5b6f8013b..6454f51e9 100644 --- a/src/common/commandoption.c +++ b/src/common/commandoption.c @@ -60,6 +60,9 @@ void ffPrepareCommandOption(FFdata* data) if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME)) ffPrepareCPUUsage(); + if(ffStrbufContainIgnCaseS(&data->structure, FF_NETUSAGE_MODULE_NAME)) + ffPrepareNetUsage(); + if(instance.config.multithreading) { if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME)) diff --git a/src/common/init.c b/src/common/init.c index a501ed348..490e4d0b5 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -106,6 +106,7 @@ static void defaultConfig(void) ffInitMediaOptions(&instance.config.media); ffInitMemoryOptions(&instance.config.memory); ffInitMonitorOptions(&instance.config.monitor); + ffInitNetUsageOptions(&instance.config.netUsage); ffInitOSOptions(&instance.config.os); ffInitOpenCLOptions(&instance.config.openCL); ffInitOpenGLOptions(&instance.config.openGL); @@ -319,6 +320,7 @@ static void destroyConfig(void) ffDestroyMediaOptions(&instance.config.media); ffDestroyMemoryOptions(&instance.config.memory); ffDestroyMonitorOptions(&instance.config.monitor); + ffDestroyNetUsageOptions(&instance.config.netUsage); ffDestroyOSOptions(&instance.config.os); ffDestroyOpenCLOptions(&instance.config.openCL); ffDestroyOpenGLOptions(&instance.config.openGL); diff --git a/src/common/modules.c b/src/common/modules.c index 1c4cd108a..b83588992 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -82,6 +82,7 @@ static FFModuleBaseInfo* M[] = { }; static FFModuleBaseInfo* N[] = { + (void*) &instance.config.netUsage, NULL, }; diff --git a/src/common/netif/netif.h b/src/common/netif/netif.h new file mode 100644 index 000000000..c515df279 --- /dev/null +++ b/src/common/netif/netif.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#ifndef _WIN32 +bool ffNetifGetDefaultRoute(FFstrbuf* iface); +#else +bool ffNetifGetDefaultRoute(uint32_t* ifIndex); +#endif diff --git a/src/common/netif/netif_bsd.c b/src/common/netif/netif_bsd.c new file mode 100644 index 000000000..f00177392 --- /dev/null +++ b/src/common/netif/netif_bsd.c @@ -0,0 +1,96 @@ +#include "netif.h" + +#include "common/io/io.h" + +#include +#include +#include +#include + +#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n)) + +#if defined(__APPLE__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) +#elif defined(__NetBSD__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t)) +#elif defined(__FreeBSD__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) +#elif defined(__OpenBSD__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) +#else +# error unknown platform +#endif + +static struct sockaddr * +get_rt_address(struct rt_msghdr *rtm, int desired) +{ + struct sockaddr *sa = (struct sockaddr *)(rtm + 1); + + for (int i = 0; i < RTAX_MAX; i++) + { + if (rtm->rtm_addrs & (1 << i)) + { + if ((1 <sa_len) + (char *)sa); + } + } + return NULL; +} + + + +bool ffNetifGetDefaultRoute(FFstrbuf* iface) +{ + //https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104 + + FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET); + if (pfRoute < 0) + return false; + + { + struct timeval timeout = {1, 0}; + setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); + setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); + } + + int pid = getpid(); + + struct { + struct rt_msghdr hdr; + struct sockaddr_in dst; + uint8_t data[512]; + } rtmsg = { + .hdr = { + .rtm_type = RTM_GET, + .rtm_flags = RTF_UP | RTF_GATEWAY, + .rtm_version = RTM_VERSION, + .rtm_addrs = RTA_DST | RTA_IFP, + .rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst), + .rtm_pid = pid, + .rtm_seq = 1, + }, + .dst = { + .sin_family = AF_INET, + .sin_len = sizeof(rtmsg.dst), + }, + }; + + if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen) + return false; + + while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0) + { + if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid) + { + struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP); + if (sdl) + { + ffStrbufSetNS(iface, sdl->sdl_nlen, sdl->sdl_data); + return true; + } + return false; + } + } + return false; +} diff --git a/src/common/netif/netif_linux.c b/src/common/netif/netif_linux.c new file mode 100644 index 000000000..299fd6034 --- /dev/null +++ b/src/common/netif/netif_linux.c @@ -0,0 +1,25 @@ +#include "netif.h" +#include "common/io/io.h" + +#include + +bool ffNetifGetDefaultRoute(FFstrbuf* iface) +{ + FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r"); + if (!netRoute) return false; + + // skip first line + flockfile(netRoute); + while (getc_unlocked(netRoute) != '\n'); + funlockfile(netRoute); + unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, + + char buf[16 /*IF_NAMESIZE*/ + 1]; + while (fscanf(netRoute, "%16s%llx%*[^\n]", buf, &destination) == 2) + { + if (destination != 0) continue; + ffStrbufSetS(iface, buf); + return true; + } + return false; +} diff --git a/src/common/netif/netif_windows.c b/src/common/netif/netif_windows.c new file mode 100644 index 000000000..d48cdbac8 --- /dev/null +++ b/src/common/netif/netif_windows.c @@ -0,0 +1,27 @@ +#include "netif.h" +#include "util/mallocHelper.h" + +#include + +bool ffNetifGetDefaultRoute(uint32_t* ifIndex) +{ + ULONG size = 0; + if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER) + return false; + + FF_AUTO_FREE MIB_IPFORWARDTABLE* pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(size); + if (GetIpForwardTable(pIpForwardTable, &size, TRUE) != ERROR_SUCCESS) + return false; + + for (uint32_t i = 0; i < pIpForwardTable->dwNumEntries; ++i) + { + MIB_IPFORWARDROW* ipForwardRow = &pIpForwardTable->table[i]; + if (ipForwardRow->dwForwardDest == 0 && ipForwardRow->dwForwardMask == 0) + { + *ifIndex = ipForwardRow->dwForwardIfIndex; + break; + } + } + + return true; +} diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index e70234735..233d42500 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -1,5 +1,6 @@ #include "localip.h" #include "common/io/io.h" +#include "common/netif/netif.h" #include #include @@ -11,123 +12,10 @@ #if defined(__FreeBSD__) || defined(__APPLE__) #include -#include -#include #else #include #endif -#if defined(__linux__) -static bool getDefaultRoute(char iface[IF_NAMESIZE + 1]) -{ - FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r"); - if (!netRoute) return false; - - // skip first line - flockfile(netRoute); - while (getc_unlocked(netRoute) != '\n'); - funlockfile(netRoute); - unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, - - static_assert(IF_NAMESIZE >= 16, "IF_NAMESIZE is too small"); - while (fscanf(netRoute, "%16s%llx%*[^\n]", iface, &destination) == 2) - { - if (destination == 0) - return true; - } - return false; -} -#elif defined(__FreeBSD__) || defined(__APPLE__) - -#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n)) - -#if defined(__APPLE__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) -#elif defined(__NetBSD__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t)) -#elif defined(__FreeBSD__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) -#elif defined(__OpenBSD__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) -#else -# error unknown platform -#endif - -static struct sockaddr * -get_rt_address(struct rt_msghdr *rtm, int desired) -{ - struct sockaddr *sa = (struct sockaddr *)(rtm + 1); - - for (int i = 0; i < RTAX_MAX; i++) - { - if (rtm->rtm_addrs & (1 << i)) - { - if ((1 <sa_len) + (char *)sa); - } - } - return NULL; -} - -static bool getDefaultRoute(char iface[IF_NAMESIZE + 1]) -{ - //https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104 - - FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET); - if (pfRoute < 0) - return false; - - { - struct timeval timeout = {1, 0}; - setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); - setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); - } - - int pid = getpid(); - - struct { - struct rt_msghdr hdr; - struct sockaddr_in dst; - uint8_t data[512]; - } rtmsg = { - .hdr = { - .rtm_type = RTM_GET, - .rtm_flags = RTF_UP | RTF_GATEWAY, - .rtm_version = RTM_VERSION, - .rtm_addrs = RTA_DST | RTA_IFP, - .rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst), - .rtm_pid = pid, - .rtm_seq = 1, - }, - .dst = { - .sin_family = AF_INET, - .sin_len = sizeof(rtmsg.dst), - }, - }; - - if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen) - return false; - - while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0) - { - if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid) - { - struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP); - if (sdl) - { - assert(sdl->sdl_nlen <= IF_NAMESIZE); - memcpy(iface, sdl->sdl_data, sdl->sdl_nlen); - iface[sdl->sdl_nlen] = 0; - return true; - } - return false; - } - } - return false; -} -#endif - static void addNewIp(FFlist* list, const char* name, const char* addr, int type) { FFLocalIpResult* ip = NULL; @@ -228,11 +116,11 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (ifAddrStruct) freeifaddrs(ifAddrStruct); - char iface[16 /*IF_NAMESIZE*/ + 1]; - if (getDefaultRoute(iface)) + FF_STRBUF_AUTO_DESTROY iface = ffStrbufCreate(); + if (ffNetifGetDefaultRoute(&iface)) { FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results) - ip->defaultRoute = ffStrbufEqualS(&ip->name, iface); + ip->defaultRoute = ffStrbufEqual(&ip->name, &iface); } return NULL; } diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index 841a608e3..82323fd11 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -1,38 +1,11 @@ -#include #include #include +#include "common/netif/netif.h" #include "util/mallocHelper.h" #include "util/windows/unicode.h" #include "localip.h" -static void setDefaultRoute(FFlist* ips) -{ - ULONG size = 0; - if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER) - return; - - FF_AUTO_FREE MIB_IPFORWARDTABLE* pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(size); - if (GetIpForwardTable(pIpForwardTable, &size, TRUE) != ERROR_SUCCESS) - return; - - for (uint32_t i = 0; i < pIpForwardTable->dwNumEntries; ++i) - { - MIB_IPFORWARDROW* ipForwardRow = &pIpForwardTable->table[i]; - if (ipForwardRow->dwForwardDest == 0 && ipForwardRow->dwForwardMask == 0) - { - FF_LIST_FOR_EACH(FFLocalIpResult, ip, *ips) - { - if (ip->ifIndex == ipForwardRow->dwForwardIfIndex) - { - ip->defaultRoute = true; - break; - } - } - } - } -} - static void addNewIp(FFlist* list, const char* name, const char* value, int type, bool newIp, uint32_t ifIndex) { FFLocalIpResult* ip = NULL; @@ -143,7 +116,15 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) } } - setDefaultRoute(results); + uint32_t ifIndex; + if (ffNetifGetDefaultRoute(&ifIndex)) + { + FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results) + { + if (ip->ifIndex != ifIndex) continue; + ip->defaultRoute = true; + } + } return NULL; } diff --git a/src/detection/netusage/netusage.c b/src/detection/netusage/netusage.c new file mode 100644 index 000000000..af885edb2 --- /dev/null +++ b/src/detection/netusage/netusage.c @@ -0,0 +1,65 @@ +#include "netusage.h" + +#include "common/time.h" + +const char* ffNetUsageGetIoCounters(FFlist* result); + +static FFlist ioCounters1; +static uint64_t time1; + +void ffPrepareNetUsage(void) +{ + ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters)); + ffNetUsageGetIoCounters(&ioCounters1); + time1 = ffTimeGetNow(); +} + +const char* ffDetectNetUsage(FFlist* result) +{ + const char* error = NULL; + if (time1 == 0) + { + ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters)); + error = ffNetUsageGetIoCounters(&ioCounters1); + if (error) + return error; + time1 = ffTimeGetNow(); + ffTimeSleep(1000); + } + + uint64_t time2 = ffTimeGetNow(); + while (time2 - time1 < 1000) + { + ffTimeSleep((uint32_t) (1000 - (time2 - time1))); + time2 = ffTimeGetNow(); + } + + error = ffNetUsageGetIoCounters(result); + if (error) + return error; + + if (result->length != ioCounters1.length) + return "Different number of network interfaces. Network change?"; + + for (uint32_t i = 0; i < result->length; ++i) + { + FFNetUsageIoCounters* icPrev = (FFNetUsageIoCounters*)ffListGet(&ioCounters1, i); + FFNetUsageIoCounters* icCurr = (FFNetUsageIoCounters*)ffListGet(result, i); + if (!ffStrbufEqual(&icPrev->name, &icCurr->name)) + return "Network interface name changed"; + + static_assert(sizeof(FFNetUsageIoCounters) - offsetof(FFNetUsageIoCounters, txBytes) == sizeof(uint64_t) * 8, "Unexpected struct FFNetUsageIoCounters layout"); + for (size_t off = offsetof(FFNetUsageIoCounters, txBytes); off < sizeof(FFNetUsageIoCounters); off += sizeof(uint64_t)) + { + uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off); + uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off); + uint64_t temp = *currValue; + *currValue -= *prevValue; + *currValue /= (time2 - time1) / 1000 /* seconds */; + *prevValue = temp; + } + } + time1 = time2; + + return NULL; +} diff --git a/src/detection/netusage/netusage.h b/src/detection/netusage/netusage.h index a754f3917..35a95367f 100644 --- a/src/detection/netusage/netusage.h +++ b/src/detection/netusage/netusage.h @@ -13,4 +13,4 @@ typedef struct FFNetUsageIoCounters uint64_t txDrops; } FFNetUsageIoCounters; -const char* ffGetNetIoCounter(FFlist* result /* list of FFNetUsageIoCounters */); +const char* ffDetectNetUsage(FFlist* result); diff --git a/src/detection/netusage/netusage_bsd.c b/src/detection/netusage/netusage_bsd.c index 1d8515863..ffd430dfa 100644 --- a/src/detection/netusage/netusage_bsd.c +++ b/src/detection/netusage/netusage_bsd.c @@ -5,27 +5,30 @@ #include #include +#include #include #include #include -const char* ffGetNetIoCounter(FFlist* result) +const char* ffNetUsageGetIoCounters(FFlist* result) { size_t bufSize = 0; - if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) < 0) - return "sysctl({ CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) failed"; + if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) < 0) + return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) failed"; - FF_AUTO_FREE uint8_t *buf = NULL; - if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, &buf, &bufSize, 0, 0) < 0) - return "sysctl({ CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, &buf, &bufSize, 0, 0) failed"; + FF_AUTO_FREE struct if_msghdr2* buf = (struct if_msghdr2*) malloc(bufSize); + if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) < 0) + return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) failed"; - for (struct if_msghdr2* ifm = (struct if_msghdr2*)buf; - ifm < (struct if_msghdr2*) (buf + bufSize); - ifm = (struct if_msghdr2*) ((uint8_t *)ifm + ifm->ifm_msglen)) + for (struct if_msghdr2* ifm = buf; + ifm < (struct if_msghdr2*) ((uint8_t*) buf + bufSize); + ifm = (struct if_msghdr2*) ((uint8_t*) ifm + ifm->ifm_msglen)) { - if (ifm->ifm_type != RTM_IFINFO2) continue; + if (ifm->ifm_type != RTM_IFINFO2 || !(ifm->ifm_flags & IFF_RUNNING) || (ifm->ifm_flags & IFF_NOARP)) continue; struct sockaddr_dl* sdl = (struct sockaddr_dl*) (ifm + 1); + assert(sdl->sdl_family == AF_LINK); + if (sdl->sdl_type != IFT_ETHER && !(ifm->ifm_flags & IFF_LOOPBACK)) continue; FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); *counters = (FFNetUsageIoCounters) { diff --git a/src/detection/netusage/netusage_linux.c b/src/detection/netusage/netusage_linux.c index c430a1f47..aea66b463 100644 --- a/src/detection/netusage/netusage_linux.c +++ b/src/detection/netusage/netusage_linux.c @@ -4,7 +4,7 @@ #include -const char* ffGetNetIoCounter(FFlist* result) +const char* ffNetUsageGetIoCounters(FFlist* result) { FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/net"); if (!dirp) return "opendir(\"/sys/class/net\") == NULL"; diff --git a/src/detection/netusage/netusage_windows.c b/src/detection/netusage/netusage_windows.c index 8facefcf5..1604b61de 100644 --- a/src/detection/netusage/netusage_windows.c +++ b/src/detection/netusage/netusage_windows.c @@ -7,7 +7,7 @@ #include #include -const char* ffGetNetIoCounter(FFlist* result) +const char* ffNetUsageGetIoCounters(FFlist* result) { IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL; diff --git a/src/fastfetch.h b/src/fastfetch.h index 8ba9158e9..c9cbfbb62 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -108,6 +108,7 @@ typedef struct FFconfig FFMediaOptions media; FFMemoryOptions memory; FFMonitorOptions monitor; + FFNetUsageOptions netUsage; FFOSOptions os; FFOpenCLOptions openCL; FFOpenGLOptions openGL; diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 28139c1d6..705a6c902 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -13,14 +13,14 @@ static int sortIps(const FFLocalIpResult* left, const FFLocalIpResult* right) return ffStrbufComp(&left->name, &right->name); } -static void formatKey(const FFLocalIpOptions* options, const FFLocalIpResult* ip, uint32_t index, FFstrbuf* key) +static void formatKey(const FFLocalIpOptions* options, FFLocalIpResult* ip, uint32_t index, FFstrbuf* key) { if(options->moduleArgs.key.length == 0) { - if(ip->name.length) - ffStrbufSetF(key, FF_LOCALIP_DISPLAY_NAME " (%s)", ip->name.chars); - else - ffStrbufSetS(key, FF_LOCALIP_DISPLAY_NAME); + if(!ip->name.length) + ffStrbufSetF(&ip->name, "unknown %u", (unsigned) index); + + ffStrbufSetF(key, FF_LOCALIP_DISPLAY_NAME " (%s)", ip->name.chars); } else { diff --git a/src/modules/modules.h b/src/modules/modules.h index 1f7669c10..2ab14bc60 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -31,6 +31,7 @@ #include "modules/media/media.h" #include "modules/memory/memory.h" #include "modules/monitor/monitor.h" +#include "modules/netusage/netusage.h" #include "modules/opengl/opengl.h" #include "modules/opencl/opencl.h" #include "modules/os/os.h" diff --git a/src/modules/netusage/netusage.c b/src/modules/netusage/netusage.c new file mode 100644 index 000000000..51a3c1f6b --- /dev/null +++ b/src/modules/netusage/netusage.c @@ -0,0 +1,155 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "common/parsing.h" +#include "detection/netusage/netusage.h" +#include "modules/netusage/netusage.h" +#include "util/stringUtils.h" + +#define FF_NETUSAGE_DISPLAY_NAME "Net Usage" +#define FF_NETUSAGE_NUM_FORMAT_ARGS 1 + +static int sortInfs(const FFNetUsageIoCounters* left, const FFNetUsageIoCounters* right) +{ + return ffStrbufComp(&left->name, &right->name); +} + +static void formatKey(const FFNetUsageOptions* options, FFNetUsageIoCounters* inf, uint32_t index, FFstrbuf* key) +{ + if(options->moduleArgs.key.length == 0) + { + if(!inf->name.length) + ffStrbufSetF(&inf->name, "unknown %u", (unsigned) index); + + ffStrbufSetF(key, FF_NETUSAGE_DISPLAY_NAME " (%s)", inf->name.chars); + } + else + { + ffStrbufClear(key); + ffParseFormatString(key, &options->moduleArgs.key, 2, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_UINT, &index}, + {FF_FORMAT_ARG_TYPE_STRBUF, &inf->name}, + }); + } +} + +void ffPrintNetUsage(FFNetUsageOptions* options) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters)); + const char* error = ffDetectNetUsage(&result); + + if(error) + { + ffPrintError(FF_NETUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, "%s", error); + return; + } + + ffListSort(&result, (const void*) sortInfs); + + uint32_t index = 0; + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate(); + + FF_LIST_FOR_EACH(FFNetUsageIoCounters, inf, result) + { + formatKey(options, inf, result.length == 1 ? 0 : index + 1, &key); + ffStrbufClear(&buffer); + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + + ffParseSize(inf->rxBytes, &buffer); + ffStrbufAppendS(&buffer, "/s (in) - "); + ffParseSize(inf->txBytes, &buffer); + ffStrbufAppendS(&buffer, "/s (out)"); + ffStrbufPutTo(&buffer, stdout); + } + else + { + ffStrbufClear(&buffer2); + ffParseSize(inf->rxBytes, &buffer); + ffParseSize(inf->txBytes, &buffer2); + ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_NETUSAGE_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &inf->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &buffer}, + {FF_FORMAT_ARG_TYPE_STRBUF, &buffer2}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->txBytes}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->rxBytes}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->txPackets}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->rxPackets}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->rxErrors}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->txErrors}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->rxDrops}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->txDrops}, + }); + } + ++index; + } +} + +void ffInitNetUsageOptions(FFNetUsageOptions* options) +{ + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_NETUSAGE_MODULE_NAME, ffParseNetUsageCommandOptions, ffParseNetUsageJsonObject, ffPrintNetUsage, ffGenerateNetUsageJson); + ffOptionInitModuleArg(&options->moduleArgs); +} + +bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_NETUSAGE_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffDestroyNetUsageOptions(FFNetUsageOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_NETUSAGE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); + } +} + +void ffGenerateNetUsageJson(FF_MAYBE_UNUSED FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters)); + const char* error = ffDetectNetUsage(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFNetUsageIoCounters, counter, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &counter->name); + yyjson_mut_obj_add_uint(doc, obj, "txBytes", counter->txBytes); + yyjson_mut_obj_add_uint(doc, obj, "rxBytes", counter->rxBytes); + yyjson_mut_obj_add_uint(doc, obj, "txPackets", counter->txPackets); + yyjson_mut_obj_add_uint(doc, obj, "rxPackets", counter->rxPackets); + yyjson_mut_obj_add_uint(doc, obj, "rxErrors", counter->rxErrors); + yyjson_mut_obj_add_uint(doc, obj, "txErrors", counter->txErrors); + yyjson_mut_obj_add_uint(doc, obj, "rxDrops", counter->rxDrops); + yyjson_mut_obj_add_uint(doc, obj, "txDrops", counter->txDrops); + + } +} diff --git a/src/modules/netusage/netusage.h b/src/modules/netusage/netusage.h new file mode 100644 index 000000000..4067d6899 --- /dev/null +++ b/src/modules/netusage/netusage.h @@ -0,0 +1,14 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_NETUSAGE_MODULE_NAME "NetUsage" + +void ffPrepareNetUsage(); + +void ffPrintNetUsage(FFNetUsageOptions* options); +void ffInitNetUsageOptions(FFNetUsageOptions* options); +bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, const char* value); +void ffDestroyNetUsageOptions(FFNetUsageOptions* options); +void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module); +void ffGenerateNetUsageJson(FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); diff --git a/src/modules/netusage/option.h b/src/modules/netusage/option.h new file mode 100644 index 000000000..59463249f --- /dev/null +++ b/src/modules/netusage/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFNetUsageOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFNetUsageOptions; diff --git a/src/modules/options.h b/src/modules/options.h index 12041ce5b..77c6cf855 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -31,6 +31,7 @@ #include "modules/media/option.h" #include "modules/memory/option.h" #include "modules/monitor/option.h" +#include "modules/netusage/option.h" #include "modules/opengl/option.h" #include "modules/opencl/option.h" #include "modules/os/option.h"