master ohmu/fastfetch-openbsd / src / common / impl / netif_haiku.c
ohmu  ·  2026-10-15
  1#include "common/netif.h"
  2#include "common/io.h"
  3#include "common/mallocHelper.h"
  4
  5#include <arpa/inet.h>
  6#include <net/if.h>
  7#include <net/route.h>
  8#include <sys/socket.h>
  9#include <sys/sockio.h>
 10#include <stdio.h>
 11
 12// loosely based on Haiku's src/bin/network/route/route.cpp
 13
 14bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result) {
 15    FF_AUTO_CLOSE_FD int pfRoute = socket(AF_INET, SOCK_RAW, AF_INET);
 16    if (pfRoute < 0) {
 17        return false;
 18    }
 19
 20    struct ifconf config;
 21    config.ifc_len = sizeof(config.ifc_value);
 22    if (ioctl(pfRoute, SIOCGRTSIZE, &config, sizeof(struct ifconf)) < 0) {
 23        return false;
 24    }
 25
 26    int size = config.ifc_value;
 27    if (size <= 0) {
 28        return false;
 29    }
 30
 31    FF_AUTO_FREE void* buffer = malloc((size_t) size);
 32    if (buffer == nullptr) {
 33        return false;
 34    }
 35
 36    config.ifc_len = size;
 37    config.ifc_buf = buffer;
 38    if (ioctl(pfRoute, SIOCGRTTABLE, &config, sizeof(struct ifconf)) < 0) {
 39        return false;
 40    }
 41
 42    struct ifreq* interface = (struct ifreq*) buffer;
 43    struct ifreq* end = (struct ifreq*) ((uint8_t*) buffer + size);
 44
 45    while (interface < end) {
 46        if (interface->ifr_route.flags & RTF_DEFAULT) {
 47            // interface->ifr_metric?
 48            strlcpy(result->ifName, interface->ifr_name, IF_NAMESIZE);
 49            result->ifIndex = if_nametoindex(interface->ifr_name);
 50            if (interface->ifr_route.source) {
 51                result->preferredSourceAddrV4 = ((struct sockaddr_in*) interface->ifr_route.source)->sin_addr.s_addr;
 52            }
 53            return true;
 54        }
 55
 56        size_t addressSize = 0;
 57        if (interface->ifr_route.destination != nullptr) {
 58            addressSize += interface->ifr_route.destination->sa_len;
 59        }
 60        if (interface->ifr_route.mask != nullptr) {
 61            addressSize += interface->ifr_route.mask->sa_len;
 62        }
 63        if (interface->ifr_route.gateway != nullptr) {
 64            addressSize += interface->ifr_route.gateway->sa_len;
 65        }
 66
 67        interface = (struct ifreq*) ((addr_t) interface + IF_NAMESIZE + sizeof(struct route_entry) + addressSize);
 68    }
 69
 70    return false;
 71}
 72
 73bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result) {
 74    FF_AUTO_CLOSE_FD int pfRoute = socket(AF_INET6, SOCK_RAW, AF_INET6);
 75    if (pfRoute < 0) {
 76        return false;
 77    }
 78
 79    struct ifconf config;
 80    config.ifc_len = sizeof(config.ifc_value);
 81    if (ioctl(pfRoute, SIOCGRTSIZE, &config, sizeof(struct ifconf)) < 0) {
 82        return false;
 83    }
 84
 85    int size = config.ifc_value;
 86    if (size <= 0) {
 87        return false;
 88    }
 89
 90    FF_AUTO_FREE void* buffer = malloc((size_t) size);
 91    if (buffer == nullptr) {
 92        return false;
 93    }
 94
 95    config.ifc_len = size;
 96    config.ifc_buf = buffer;
 97    if (ioctl(pfRoute, SIOCGRTTABLE, &config, sizeof(struct ifconf)) < 0) {
 98        return false;
 99    }
100
101    struct ifreq* interface = (struct ifreq*) buffer;
102    struct ifreq* end = (struct ifreq*) ((uint8_t*) buffer + size);
103
104    while (interface < end) {
105        if (interface->ifr_route.flags & RTF_DEFAULT) {
106            strlcpy(result->ifName, interface->ifr_name, IF_NAMESIZE);
107            result->ifIndex = if_nametoindex(interface->ifr_name);
108            return true;
109        }
110
111        size_t addressSize = 0;
112        if (interface->ifr_route.destination != nullptr) {
113            addressSize += interface->ifr_route.destination->sa_len;
114        }
115        if (interface->ifr_route.mask != nullptr) {
116            addressSize += interface->ifr_route.mask->sa_len;
117        }
118        if (interface->ifr_route.gateway != nullptr) {
119            addressSize += interface->ifr_route.gateway->sa_len;
120        }
121
122        interface = (struct ifreq*) ((addr_t) interface + IF_NAMESIZE + sizeof(struct route_entry) + addressSize);
123    }
124    return false;
125}