Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0-only */
2 : /*
3 : * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
4 : */
5 :
6 : // clang-format off
7 : // Include net/if.h before any kernel header to avoid conflicts.
8 : #include <net/if.h>
9 : // clang-format on
10 :
11 : #include "core/if.h"
12 :
13 : #include <errno.h>
14 : #include <limits.h>
15 : #include <stdlib.h>
16 : #include <string.h>
17 : #include <sys/types.h>
18 :
19 : #include "core/helper.h"
20 : #include "core/logger.h"
21 :
22 : static char _bf_if_name[IFNAMSIZ];
23 :
24 0 : int bf_if_index_from_name(const char *name)
25 : {
26 : unsigned int r;
27 :
28 0 : bf_assert(name);
29 :
30 0 : r = if_nametoindex(name);
31 0 : if (r == 0) {
32 0 : return bf_err_r(errno, "failed to get ifindex for interface '%s'",
33 : name);
34 : }
35 :
36 0 : if (r > INT_MAX)
37 0 : return bf_err_r(-E2BIG, "ifindex is too big: %d", r);
38 :
39 : return (int)r;
40 : }
41 :
42 0 : const char *bf_if_name_from_index(int index)
43 : {
44 0 : if (!if_indextoname(index, _bf_if_name)) {
45 0 : bf_warn_r(errno, "failed to get ifname for interface '%d'", index);
46 0 : strncpy(_bf_if_name, "<unknown>", IFNAMSIZ);
47 : }
48 :
49 0 : return _bf_if_name;
50 : }
51 :
52 0 : ssize_t bf_if_get_ifaces(struct bf_if_iface **ifaces)
53 : {
54 : _cleanup_free_ struct bf_if_iface *_ifaces = NULL;
55 : struct if_nameindex *if_ni, *it;
56 : ssize_t n_ifaces = 0;
57 : size_t i = 0;
58 :
59 0 : bf_assert(ifaces);
60 :
61 0 : if_ni = if_nameindex();
62 0 : if (!if_ni)
63 0 : return bf_err_r(errno, "failed to fetch interfaces details");
64 :
65 : // Gather the number of interfaces to allocate the memory.
66 0 : for (it = if_ni; it->if_index != 0 || it->if_name != NULL; ++it)
67 0 : ++n_ifaces;
68 :
69 0 : if (n_ifaces == 0)
70 : return 0;
71 :
72 0 : _ifaces = malloc(n_ifaces * sizeof(*_ifaces));
73 0 : if (!_ifaces) {
74 0 : if_freenameindex(if_ni);
75 0 : return bf_err_r(-ENOMEM,
76 : "failed to allocate memory for interfaces buffer");
77 : }
78 :
79 0 : for (it = if_ni; it->if_index != 0 || it->if_name != NULL; ++it) {
80 0 : _ifaces[i].index = it->if_index;
81 :
82 0 : if (it->if_index)
83 0 : strncpy(_ifaces[i].name, it->if_name, IF_NAMESIZE);
84 : else
85 0 : bf_warn("interface %d has no name", it->if_index);
86 :
87 0 : ++i;
88 : }
89 :
90 0 : *ifaces = TAKE_PTR(_ifaces);
91 :
92 0 : if_freenameindex(if_ni);
93 :
94 0 : return n_ifaces;
95 : }
|