Skip to content

Commit 4dfba31

Browse files
authored
Merge pull request #1911 from fastfetch-cli/dev
Release: v2.50.2
2 parents 7bacf20 + 3004f29 commit 4dfba31

File tree

11 files changed

+655
-261
lines changed

11 files changed

+655
-261
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ on:
44
- push
55
- pull_request
66

7+
env:
8+
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
9+
710
jobs:
811
spellcheck:
912
runs-on: ubuntu-latest

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# 2.50.2
2+
3+
Bugfixes:
4+
* Fixes linglong package detection V2 (#1903, Packages, Linux)
5+
* Fixes building with `-DENABLE_SYSTEM_YYJSON=ON` (#1904)
6+
* Fixes `showMac` does not honor `defaultRouteOnly` (#1902, LocalIP, Linux)
7+
* Fixes failing to acquire default route on Linux in certain cases (#1902, LocalIP, Linux)
8+
19
# 2.50.1
210

311
Bugfixes:

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
22

33
project(fastfetch
4-
VERSION 2.50.1
4+
VERSION 2.50.2
55
LANGUAGES C
66
DESCRIPTION "Fast neofetch-like system information tool"
77
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"

src/common/netif/netif_linux.c

Lines changed: 104 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,41 @@
11
#include "netif.h"
22
#include "common/io/io.h"
33
#include "util/mallocHelper.h"
4+
#include "util/debug.h"
45

56
#include <arpa/inet.h>
67
#include <linux/rtnetlink.h>
78
#include <net/if.h>
89

9-
#define FF_STR_INDIR(x) #x
10-
#define FF_STR(x) FF_STR_INDIR(x)
11-
1210
bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
1311
{
12+
FF_DEBUG("Starting IPv4 default route detection");
13+
1414
FF_AUTO_CLOSE_FD int sock_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
1515
if (sock_fd < 0)
16+
{
17+
FF_DEBUG("Failed to create netlink socket: %s", strerror(errno));
1618
return false;
19+
}
20+
FF_DEBUG("Created netlink socket: fd=%d", sock_fd);
1721

1822
unsigned pid = (unsigned) getpid();
23+
FF_DEBUG("Process PID: %u", pid);
1924

2025
// Bind socket
2126
struct sockaddr_nl addr = {
2227
.nl_family = AF_NETLINK,
23-
.nl_pid = pid,
28+
.nl_pid = 0, // Let kernel choose PID
2429
.nl_groups = 0, // No multicast groups
2530
};
2631

2732
if (bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
33+
FF_DEBUG("Failed to bind socket: %s", strerror(errno));
2834
return false;
2935
}
36+
FF_DEBUG("Successfully bound socket");
3037

31-
struct {
38+
struct __attribute__((__packed__)) {
3239
struct nlmsghdr nlh;
3340
struct rtmsg rtm;
3441
struct rtattr rta;
@@ -72,59 +79,68 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
7279
(struct sockaddr*)&dest_addr, sizeof(dest_addr));
7380

7481
if (sent != sizeof(req)) {
82+
FF_DEBUG("Failed to send netlink request: sent=%zd, expected=%zu", sent, sizeof(req));
7583
return false;
7684
}
85+
FF_DEBUG("Sent netlink request: %zd bytes", sent);
7786

7887
struct sockaddr_nl src_addr = {};
7988
socklen_t src_addr_len = sizeof(src_addr);
8089

81-
struct iovec iov = {};
82-
struct msghdr msg = {
83-
.msg_name = &src_addr,
84-
.msg_namelen = sizeof(src_addr),
85-
.msg_iov = &iov,
86-
.msg_iovlen = 1,
87-
};
90+
uint8_t buffer[1024 * 16]; // 16 KB buffer should be sufficient
91+
92+
ssize_t received = recvfrom(sock_fd, buffer, sizeof(buffer), 0,
93+
(struct sockaddr*)&src_addr, &src_addr_len);
8894

89-
ssize_t peek_size = recvmsg(sock_fd, &msg, MSG_PEEK | MSG_TRUNC);
90-
if (peek_size < 0) {
95+
if (received < 0) {
96+
FF_DEBUG("Failed to receive netlink response: %s", strerror(errno));
9197
return false;
9298
}
9399

94-
FF_AUTO_FREE uint8_t* buffer = malloc((size_t)peek_size);
95-
96-
ssize_t received = recvfrom(sock_fd, buffer, (size_t)peek_size, 0,
97-
(struct sockaddr*)&src_addr, &src_addr_len);
98-
if (received != peek_size) {
100+
if (received >= (ssize_t)sizeof(buffer)) {
101+
FF_DEBUG("Failed to receive complete message (possible truncation)");
99102
return false;
100103
}
104+
FF_DEBUG("Received netlink response: %zd bytes", received);
101105

102106
struct {
103107
uint32_t metric;
104108
uint32_t ifindex;
105109
uint32_t prefsrc;
106110
} entry;
107111
uint32_t minMetric = UINT32_MAX;
112+
int routeCount = 0;
108113

109114
for (const struct nlmsghdr* nlh = (struct nlmsghdr*)buffer;
110115
NLMSG_OK(nlh, received);
111116
nlh = NLMSG_NEXT(nlh, received)) {
112117
if (nlh->nlmsg_seq != 1 || nlh->nlmsg_pid != pid)
113118
continue;
114119
if (nlh->nlmsg_type == NLMSG_DONE)
120+
{
121+
FF_DEBUG("Received NLMSG_DONE, processed %d routes", routeCount);
115122
break;
123+
}
124+
125+
if (nlh->nlmsg_type == NLMSG_ERROR) {
126+
struct nlmsgerr* err = (struct nlmsgerr*)NLMSG_DATA(nlh);
127+
FF_DEBUG("Netlink reports error: %s", strerror(-err->error));
128+
continue;
129+
}
116130

117131
if (nlh->nlmsg_type != RTM_NEWROUTE)
118132
continue;
119133

134+
routeCount++;
120135
struct rtmsg* rtm = (struct rtmsg*)NLMSG_DATA(nlh);
121136
if (rtm->rtm_family != AF_INET)
122137
continue;
123138

124139
if (rtm->rtm_dst_len != 0)
125140
continue;
126141

127-
entry = (__typeof__(entry)) { .metric = UINT32_MAX };
142+
FF_DEBUG("Processing IPv4 default route candidate #%d", routeCount);
143+
entry = (__typeof__(entry)) { }; // Default to zero metric (no RTA_PRIORITY found)
128144

129145
// Parse route attributes
130146
size_t rtm_len = RTM_PAYLOAD(nlh);
@@ -138,62 +154,84 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
138154
uint32_t rta_data = *(uint32_t*) RTA_DATA(rta);
139155
switch (rta->rta_type) {
140156
case RTA_DST:
141-
if (rta_data != 0) goto next;
142-
break;
157+
FF_DEBUG("Unexpected RTA_DST: %s (len=%u)", inet_ntoa((struct in_addr) { .s_addr = rta_data }), rtm->rtm_dst_len);
158+
goto next;
143159
case RTA_OIF:
144160
entry.ifindex = rta_data;
161+
FF_DEBUG("Found interface index: %u", entry.ifindex);
145162
break;
146163
case RTA_GATEWAY:
164+
FF_DEBUG("Found gateway: %s", inet_ntoa(*(struct in_addr*)&rta_data));
147165
if (rta_data == 0) goto next;
148166
break;
149167
case RTA_PRIORITY:
168+
FF_DEBUG("Found metric: %u", rta_data);
150169
if (rta_data >= minMetric) goto next;
151170
entry.metric = rta_data;
152171
break;
153172
case RTA_PREFSRC:
154173
entry.prefsrc = rta_data;
174+
FF_DEBUG("Found preferred source: %s", inet_ntoa(*(struct in_addr*)&rta_data));
155175
break;
156176
}
157177
}
158178

159-
if (entry.metric >= minMetric)
179+
if (entry.ifindex == 0 || entry.metric >= minMetric)
160180
{
161181
next:
182+
FF_DEBUG("Skipping route: ifindex=%u, metric=%u", entry.ifindex, entry.metric);
162183
continue;
163184
}
164185
minMetric = entry.metric;
165186
result->ifIndex = entry.ifindex;
187+
FF_DEBUG("Updated best route: ifindex=%u, metric=%u, prefsrc=%x", entry.ifindex, entry.metric, entry.prefsrc);
166188
result->preferredSourceAddrV4 = entry.prefsrc;
189+
if (minMetric == 0)
190+
{
191+
FF_DEBUG("Found zero metric route, stopping further processing");
192+
break; // Stop processing if we found a zero metric route
193+
}
167194
}
168195

169196
if (minMetric < UINT32_MAX)
170197
{
171198
if_indextoname(result->ifIndex, result->ifName);
199+
FF_DEBUG("Found default IPv4 route: interface=%s, index=%u, metric=%u", result->ifName, result->ifIndex, minMetric);
172200
return true;
173201
}
202+
FF_DEBUG("No IPv4 default route found");
174203
return false;
175204
}
176205

177206
bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
178207
{
208+
FF_DEBUG("Starting IPv6 default route detection");
209+
179210
FF_AUTO_CLOSE_FD int sock_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
180211
if (sock_fd < 0)
212+
{
213+
FF_DEBUG("Failed to create netlink socket: %s", strerror(errno));
181214
return false;
215+
}
216+
FF_DEBUG("Created netlink socket: fd=%d", sock_fd);
182217

183218
unsigned pid = (unsigned) getpid();
219+
FF_DEBUG("Process PID: %u", pid);
184220

185221
// Bind socket
186222
struct sockaddr_nl addr = {
187223
.nl_family = AF_NETLINK,
188-
.nl_pid = pid,
224+
.nl_pid = 0, // Let kernel choose PID
189225
.nl_groups = 0, // No multicast groups
190226
};
191227

192228
if (bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
229+
FF_DEBUG("Failed to bind socket: %s", strerror(errno));
193230
return false;
194231
}
232+
FF_DEBUG("Successfully bound socket");
195233

196-
struct {
234+
struct __attribute__((__packed__)) {
197235
struct nlmsghdr nlh;
198236
struct rtmsg rtm;
199237
struct rtattr rta;
@@ -237,30 +275,26 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
237275
(struct sockaddr*)&dest_addr, sizeof(dest_addr));
238276

239277
if (sent != sizeof(req)) {
278+
FF_DEBUG("Failed to send netlink request: sent=%zd, expected=%zu", sent, sizeof(req));
240279
return false;
241280
}
281+
FF_DEBUG("Sent netlink request: %zd bytes", sent);
242282

243283
struct sockaddr_nl src_addr = {};
244284
socklen_t src_addr_len = sizeof(src_addr);
245285

246-
struct iovec iov = {};
247-
struct msghdr msg = {
248-
.msg_name = &src_addr,
249-
.msg_namelen = sizeof(src_addr),
250-
.msg_iov = &iov,
251-
.msg_iovlen = 1,
252-
};
286+
uint8_t buffer[1024 * 16]; // 16 KB buffer should be sufficient
253287

254-
ssize_t peek_size = recvmsg(sock_fd, &msg, MSG_PEEK | MSG_TRUNC);
255-
if (peek_size < 0) {
288+
ssize_t received = recvfrom(sock_fd, buffer, sizeof(buffer), 0,
289+
(struct sockaddr*)&src_addr, &src_addr_len);
290+
291+
if (received < 0) {
292+
FF_DEBUG("Failed to receive netlink response: %s", strerror(errno));
256293
return false;
257294
}
258295

259-
FF_AUTO_FREE uint8_t* buffer = malloc((size_t)peek_size);
260-
261-
ssize_t received = recvfrom(sock_fd, buffer, (size_t)peek_size, 0,
262-
(struct sockaddr*)&src_addr, &src_addr_len);
263-
if (received != peek_size) {
296+
if (received >= (ssize_t)sizeof(buffer)) {
297+
FF_DEBUG("Failed to receive complete message (possible truncation)");
264298
return false;
265299
}
266300

@@ -269,26 +303,38 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
269303
uint32_t ifindex;
270304
} entry;
271305
uint32_t minMetric = UINT32_MAX;
306+
int routeCount = 0;
272307

273308
for (const struct nlmsghdr* nlh = (struct nlmsghdr*)buffer;
274309
NLMSG_OK(nlh, received);
275310
nlh = NLMSG_NEXT(nlh, received)) {
276311
if (nlh->nlmsg_seq != 1 || nlh->nlmsg_pid != pid)
277312
continue;
278313
if (nlh->nlmsg_type == NLMSG_DONE)
314+
{
315+
FF_DEBUG("Received NLMSG_DONE, processed %d routes", routeCount);
279316
break;
317+
}
318+
319+
if (nlh->nlmsg_type == NLMSG_ERROR) {
320+
struct nlmsgerr* err = (struct nlmsgerr*)NLMSG_DATA(nlh);
321+
FF_DEBUG("Netlink reports error: %s", strerror(-err->error));
322+
continue;
323+
}
280324

281325
if (nlh->nlmsg_type != RTM_NEWROUTE)
282326
continue;
283327

328+
routeCount++;
284329
struct rtmsg* rtm = (struct rtmsg*)NLMSG_DATA(nlh);
285330
if (rtm->rtm_family != AF_INET6)
286331
continue;
287332

288333
if (rtm->rtm_dst_len != 0)
289334
continue;
290335

291-
entry = (__typeof__(entry)) { .metric = UINT32_MAX };
336+
FF_DEBUG("Processing IPv6 default route candidate #%d", routeCount);
337+
entry = (__typeof__(entry)) { }; // Default to zero metric (no RTA_PRIORITY found)
292338

293339
// Parse route attributes
294340
size_t rtm_len = RTM_PAYLOAD(nlh);
@@ -299,44 +345,59 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
299345
switch (rta->rta_type) {
300346
case RTA_DST:
301347
if (RTA_PAYLOAD(rta) >= sizeof(struct in6_addr)) {
302-
struct in6_addr* dst = (struct in6_addr*) RTA_DATA(rta);
303-
if (!IN6_IS_ADDR_UNSPECIFIED(dst)) goto next;
348+
FF_MAYBE_UNUSED char str[INET6_ADDRSTRLEN];
349+
FF_DEBUG("Unexpected RTA_DST: %s", inet_ntop(AF_INET6, RTA_DATA(rta), str, sizeof(str)));
350+
goto next;
304351
}
305352
break;
306353
case RTA_OIF:
307354
if (RTA_PAYLOAD(rta) >= sizeof(uint32_t)) {
308355
entry.ifindex = *(uint32_t*) RTA_DATA(rta);
356+
FF_DEBUG("Found interface index: %u", entry.ifindex);
309357
}
310358
break;
311359
case RTA_GATEWAY:
312360
if (RTA_PAYLOAD(rta) >= sizeof(struct in6_addr)) {
313361
struct in6_addr* gw = (struct in6_addr*) RTA_DATA(rta);
314362
if (IN6_IS_ADDR_UNSPECIFIED(gw)) goto next;
363+
FF_MAYBE_UNUSED char str[INET6_ADDRSTRLEN];
364+
FF_DEBUG("Found gateway: %s", inet_ntop(AF_INET6, gw, str, sizeof(str)));
315365
}
316366
break;
317367
case RTA_PRIORITY:
318368
if (RTA_PAYLOAD(rta) >= sizeof(uint32_t)) {
319369
uint32_t metric = *(uint32_t*) RTA_DATA(rta);
370+
FF_DEBUG("Found metric: %u", metric);
320371
if (metric >= minMetric) goto next;
321372
entry.metric = metric;
322373
}
323374
break;
324375
}
325376
}
326377

327-
if (entry.metric >= minMetric)
378+
if (entry.ifindex == 0 || entry.metric >= minMetric)
328379
{
329380
next:
381+
FF_DEBUG("Skipping route: ifindex=%u, metric=%u", entry.ifindex, entry.metric);
330382
continue;
331383
}
332384
minMetric = entry.metric;
333385
result->ifIndex = entry.ifindex;
386+
FF_DEBUG("Updated best route: ifindex=%u, metric=%u", entry.ifindex, entry.metric);
387+
388+
if (minMetric == 0)
389+
{
390+
FF_DEBUG("Found zero metric route, stopping further processing");
391+
break; // Stop processing if we found a zero metric route
392+
}
334393
}
335394

336395
if (minMetric < UINT32_MAX)
337396
{
338397
if_indextoname(result->ifIndex, result->ifName);
398+
FF_DEBUG("Found default IPv6 route: interface=%s, index=%u, metric=%u", result->ifName, result->ifIndex, minMetric);
339399
return true;
340400
}
401+
FF_DEBUG("No IPv6 default route found");
341402
return false;
342403
}

0 commit comments

Comments
 (0)