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
|
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* Copyright (c) 2022-2023 Brett Sheffield <bacs@librecast.net> */
#include "test.h"
#include <errno.h>
#include <ifaddrs.h>
#ifdef __linux__
# include <librecast.h>
# include <librecast/if.h>
#endif
#include <limits.h>
#include <net/if.h>
#include <sys/types.h>
#ifndef AF_LINK
# ifdef AF_PACKET
# define AF_LINK AF_PACKET
# endif
#endif
unsigned int get_invalid_ifx(void)
{
char ifname[IF_NAMESIZE];
for (unsigned int ifx = 1; ifx < UINT_MAX; ifx++) {
if (!if_indextoname(ifx, ifname)) return ifx;
}
return 0;
}
/* find an interface that supports multicast */
unsigned get_multicast_if(void)
{
unsigned ifidx = 0;
/* create tap interface and bring it up */
char ifname[IFNAMSIZ] = {0};
#ifdef __linux__
lc_tuntap_create(ifname, IFF_TAP | IFF_NO_PI);
lc_ctx_t *lctx = lc_ctx_new();
lc_link_set(lctx, ifname, 1);
lc_ctx_free(lctx);
ifidx = if_nametoindex(ifname);
#endif
if (!ifidx) {
test_log("unable to create tap device: %s\n", strerror(errno));
/* failed to create tap, find multicast capable interface */
struct ifaddrs *ifa = NULL, *ifap = NULL;
test_assert(getifaddrs(&ifa) != -1, "getifaddrs(): %s", strerror(errno));
for (ifap = ifa; ifap; ifap = ifap->ifa_next) {
if (!(ifap->ifa_flags & IFF_MULTICAST)) continue;
/* we don't want the loopback interface */
if (ifap->ifa_flags & IFF_LOOPBACK) continue;
if (ifap->ifa_addr == NULL) continue;
if (ifap->ifa_addr->sa_family != AF_INET6) continue;
ifidx = if_nametoindex(ifap->ifa_name);
test_log("found multicast interface %s [%u]\n", ifap->ifa_name, ifidx);
break;
}
freeifaddrs(ifa);
}
else {
test_log("tap %s created\n", ifname);
}
return ifidx;
}
int test_net_level(void)
{
struct ifaddrs *ifaddr;
int ifaces = 0;
int ifup = 0;
int mcast = 0;
int addr6 = 0;
int addr4 = 0;
int level = 0;
int mroutes = 0;
char * have_multicast = getenv("HAVE_MULTICAST_ROUTES");
test_init();
test_log("Checking network connectivity...\n");
if (getifaddrs(&ifaddr) == -1) return -1;
for (struct ifaddrs *ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
switch (ifa->ifa_addr->sa_family) {
case AF_LINK:
ifaces++;
if (ifa->ifa_flags & IFF_UP) {
ifup++;
/* test MULTICAST flag, skip loopback interfaces */
if (ifa->ifa_flags & IFF_LOOPBACK) break;
if (ifa->ifa_flags & IFF_MULTICAST) mcast++;
}
break;
case AF_INET6:
if (ifa->ifa_flags & IFF_UP) addr6++;
break;
case AF_INET:
if (ifa->ifa_flags & IFF_UP) addr4++;
break;
}
}
freeifaddrs(ifaddr);
test_log("have_multicast: %s\n", have_multicast);
if (have_multicast) mroutes = atoi(have_multicast);
test_log(" %i network interfaces found\n", ifaces);
test_log(" %i network interfaces up\n", ifup);
test_log(" %i MULTICAST interfaces up\n", mcast);
test_log(" %i IPv6 addresses\n", addr6);
test_log(" %i IPv4 addresses\n", addr4);
test_log(" %i multicast routes\n", mroutes);
level |= (ifaces > 0);
level |= (ifup > 0) << 1;
level |= (addr4 > 0) << 2;
level |= (addr6 > 0) << 3;
level |= (mcast > 0) << 4;
level |= (mroutes > 0) << 5;
test_log("connectivity level = %i (%06b)\n", level, level);
return level;
}
int test_require_net(int required)
{
int lvl = test_net_level();
if ((lvl & required) != required) {
test_log("------------------------------------------------------\n");
test_log("Required network level not met. Skipping test. \n");
test_log("(%06b/%06b)\n", lvl, required);
test_log("------------------------------------------------------\n");
exit(TEST_WARN);
}
return lvl;
}
|