7
7
#include <linux/rtnetlink.h>
8
8
#include <net/if.h>
9
9
10
- #define FF_STR_INDIR (x ) #x
11
- #define FF_STR (x ) FF_STR_INDIR(x)
12
-
13
10
bool ffNetifGetDefaultRouteImplV4 (FFNetifDefaultRouteResult * result )
14
11
{
15
12
FF_DEBUG ("Starting IPv4 default route detection" );
16
13
17
14
FF_AUTO_CLOSE_FD int sock_fd = socket (AF_NETLINK , SOCK_RAW | SOCK_CLOEXEC , NETLINK_ROUTE );
18
15
if (sock_fd < 0 )
19
16
{
20
- FF_DEBUG ("Failed to create netlink socket: errno=%d " , errno );
17
+ FF_DEBUG ("Failed to create netlink socket: %s " , strerror ( errno ) );
21
18
return false;
22
19
}
23
20
FF_DEBUG ("Created netlink socket: fd=%d" , sock_fd );
@@ -28,17 +25,17 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
28
25
// Bind socket
29
26
struct sockaddr_nl addr = {
30
27
.nl_family = AF_NETLINK ,
31
- .nl_pid = pid ,
28
+ .nl_pid = 0 , // Let kernel choose PID
32
29
.nl_groups = 0 , // No multicast groups
33
30
};
34
31
35
32
if (bind (sock_fd , (struct sockaddr * )& addr , sizeof (addr )) < 0 ) {
36
- FF_DEBUG ("Failed to bind socket: errno=%d " , errno );
33
+ FF_DEBUG ("Failed to bind socket: %s " , strerror ( errno ) );
37
34
return false;
38
35
}
39
36
FF_DEBUG ("Successfully bound socket" );
40
37
41
- struct {
38
+ struct __attribute__(( __packed__ )) {
42
39
struct nlmsghdr nlh ;
43
40
struct rtmsg rtm ;
44
41
struct rtattr rta ;
@@ -90,27 +87,18 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
90
87
struct sockaddr_nl src_addr = {};
91
88
socklen_t src_addr_len = sizeof (src_addr );
92
89
93
- struct iovec iov = {};
94
- struct msghdr msg = {
95
- .msg_name = & src_addr ,
96
- .msg_namelen = sizeof (src_addr ),
97
- .msg_iov = & iov ,
98
- .msg_iovlen = 1 ,
99
- };
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 );
100
94
101
- ssize_t peek_size = recvmsg (sock_fd , & msg , MSG_PEEK | MSG_TRUNC );
102
- if (peek_size < 0 ) {
103
- FF_DEBUG ("Failed to peek message size: errno=%d" , errno );
95
+ if (received < 0 ) {
96
+ FF_DEBUG ("Failed to receive netlink response: %s" , strerror (errno ));
104
97
return false;
105
98
}
106
- FF_DEBUG ("Message size: %zd bytes" , peek_size );
107
-
108
- FF_AUTO_FREE uint8_t * buffer = malloc ((size_t )peek_size );
109
99
110
- ssize_t received = recvfrom (sock_fd , buffer , (size_t )peek_size , 0 ,
111
- (struct sockaddr * )& src_addr , & src_addr_len );
112
- if (received != peek_size ) {
113
- FF_DEBUG ("Failed to receive complete message: received=%zd, expected=%zd" , received , peek_size );
100
+ if (received >= (ssize_t )sizeof (buffer )) {
101
+ FF_DEBUG ("Failed to receive complete message (possible truncation)" );
114
102
return false;
115
103
}
116
104
FF_DEBUG ("Received netlink response: %zd bytes" , received );
@@ -134,6 +122,12 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
134
122
break ;
135
123
}
136
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
+ }
130
+
137
131
if (nlh -> nlmsg_type != RTM_NEWROUTE )
138
132
continue ;
139
133
@@ -146,7 +140,7 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
146
140
continue ;
147
141
148
142
FF_DEBUG ("Processing IPv4 default route candidate #%d" , routeCount );
149
- entry = (__typeof__ (entry )) { . metric = UINT32_MAX };
143
+ entry = (__typeof__ (entry )) { }; // Default to zero metric (no RTA_PRIORITY found)
150
144
151
145
// Parse route attributes
152
146
size_t rtm_len = RTM_PAYLOAD (nlh );
@@ -160,21 +154,20 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
160
154
uint32_t rta_data = * (uint32_t * ) RTA_DATA (rta );
161
155
switch (rta -> rta_type ) {
162
156
case RTA_DST :
163
- FF_DEBUG ("Found destination: %s" , inet_ntoa (* (struct in_addr * )& rta_data ));
164
- if (rta_data != 0 ) goto next ;
165
- 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 ;
166
159
case RTA_OIF :
167
160
entry .ifindex = rta_data ;
168
161
FF_DEBUG ("Found interface index: %u" , entry .ifindex );
169
162
break ;
170
163
case RTA_GATEWAY :
171
- if (rta_data == 0 ) goto next ;
172
164
FF_DEBUG ("Found gateway: %s" , inet_ntoa (* (struct in_addr * )& rta_data ));
165
+ if (rta_data == 0 ) goto next ;
173
166
break ;
174
167
case RTA_PRIORITY :
168
+ FF_DEBUG ("Found metric: %u" , rta_data );
175
169
if (rta_data >= minMetric ) goto next ;
176
170
entry .metric = rta_data ;
177
- FF_DEBUG ("Found metric: %u" , entry .metric );
178
171
break ;
179
172
case RTA_PREFSRC :
180
173
entry .prefsrc = rta_data ;
@@ -183,15 +176,21 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
183
176
}
184
177
}
185
178
186
- if (entry .metric >= minMetric )
179
+ if (entry .ifindex == 0 || entry . metric >= minMetric )
187
180
{
188
181
next :
182
+ FF_DEBUG ("Skipping route: ifindex=%u, metric=%u" , entry .ifindex , entry .metric );
189
183
continue ;
190
184
}
191
185
minMetric = entry .metric ;
192
186
result -> ifIndex = entry .ifindex ;
193
- FF_DEBUG ("Updated best route: ifindex=%u, metric=%u" , entry .ifindex , entry .metric );
194
- // result->preferredSourceAddrV4 = entry.prefsrc;
187
+ FF_DEBUG ("Updated best route: ifindex=%u, metric=%u, prefsrc=%x" , entry .ifindex , entry .metric , entry .prefsrc );
188
+ 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
+ }
195
194
}
196
195
197
196
if (minMetric < UINT32_MAX )
@@ -211,7 +210,7 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
211
210
FF_AUTO_CLOSE_FD int sock_fd = socket (AF_NETLINK , SOCK_RAW | SOCK_CLOEXEC , NETLINK_ROUTE );
212
211
if (sock_fd < 0 )
213
212
{
214
- FF_DEBUG ("Failed to create netlink socket: errno=%d " , errno );
213
+ FF_DEBUG ("Failed to create netlink socket: %s " , strerror ( errno ) );
215
214
return false;
216
215
}
217
216
FF_DEBUG ("Created netlink socket: fd=%d" , sock_fd );
@@ -222,17 +221,17 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
222
221
// Bind socket
223
222
struct sockaddr_nl addr = {
224
223
.nl_family = AF_NETLINK ,
225
- .nl_pid = pid ,
224
+ .nl_pid = 0 , // Let kernel choose PID
226
225
.nl_groups = 0 , // No multicast groups
227
226
};
228
227
229
228
if (bind (sock_fd , (struct sockaddr * )& addr , sizeof (addr )) < 0 ) {
230
- FF_DEBUG ("Failed to bind socket: errno=%d " , errno );
229
+ FF_DEBUG ("Failed to bind socket: %s " , strerror ( errno ) );
231
230
return false;
232
231
}
233
232
FF_DEBUG ("Successfully bound socket" );
234
233
235
- struct {
234
+ struct __attribute__(( __packed__ )) {
236
235
struct nlmsghdr nlh ;
237
236
struct rtmsg rtm ;
238
237
struct rtattr rta ;
@@ -284,30 +283,20 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
284
283
struct sockaddr_nl src_addr = {};
285
284
socklen_t src_addr_len = sizeof (src_addr );
286
285
287
- struct iovec iov = {};
288
- struct msghdr msg = {
289
- .msg_name = & src_addr ,
290
- .msg_namelen = sizeof (src_addr ),
291
- .msg_iov = & iov ,
292
- .msg_iovlen = 1 ,
293
- };
286
+ uint8_t buffer [1024 * 16 ]; // 16 KB buffer should be sufficient
294
287
295
- ssize_t peek_size = recvmsg (sock_fd , & msg , MSG_PEEK | MSG_TRUNC );
296
- if (peek_size < 0 ) {
297
- FF_DEBUG ("Failed to peek message size: errno=%d" , errno );
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 ));
298
293
return false;
299
294
}
300
- FF_DEBUG ("Message size: %zd bytes" , peek_size );
301
-
302
- FF_AUTO_FREE uint8_t * buffer = malloc ((size_t )peek_size );
303
295
304
- ssize_t received = recvfrom (sock_fd , buffer , (size_t )peek_size , 0 ,
305
- (struct sockaddr * )& src_addr , & src_addr_len );
306
- if (received != peek_size ) {
307
- FF_DEBUG ("Failed to receive complete message: received=%zd, expected=%zd" , received , peek_size );
296
+ if (received >= (ssize_t )sizeof (buffer )) {
297
+ FF_DEBUG ("Failed to receive complete message (possible truncation)" );
308
298
return false;
309
299
}
310
- FF_DEBUG ("Received netlink response: %zd bytes" , received );
311
300
312
301
struct {
313
302
uint32_t metric ;
@@ -327,6 +316,12 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
327
316
break ;
328
317
}
329
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
+ }
324
+
330
325
if (nlh -> nlmsg_type != RTM_NEWROUTE )
331
326
continue ;
332
327
@@ -339,7 +334,7 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
339
334
continue ;
340
335
341
336
FF_DEBUG ("Processing IPv6 default route candidate #%d" , routeCount );
342
- entry = (__typeof__ (entry )) { . metric = UINT32_MAX };
337
+ entry = (__typeof__ (entry )) { }; // Default to zero metric (no RTA_PRIORITY found)
343
338
344
339
// Parse route attributes
345
340
size_t rtm_len = RTM_PAYLOAD (nlh );
@@ -351,9 +346,8 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
351
346
case RTA_DST :
352
347
if (RTA_PAYLOAD (rta ) >= sizeof (struct in6_addr )) {
353
348
FF_MAYBE_UNUSED char str [INET6_ADDRSTRLEN ];
354
- FF_DEBUG ("Found destination: %s" , inet_ntop (AF_INET6 , RTA_DATA (rta ), str , sizeof (str )));
355
- struct in6_addr * dst = (struct in6_addr * ) RTA_DATA (rta );
356
- if (!IN6_IS_ADDR_UNSPECIFIED (dst )) goto next ;
349
+ FF_DEBUG ("Unexpected RTA_DST: %s" , inet_ntop (AF_INET6 , RTA_DATA (rta ), str , sizeof (str )));
350
+ goto next ;
357
351
}
358
352
break ;
359
353
case RTA_OIF :
@@ -373,22 +367,29 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
373
367
case RTA_PRIORITY :
374
368
if (RTA_PAYLOAD (rta ) >= sizeof (uint32_t )) {
375
369
uint32_t metric = * (uint32_t * ) RTA_DATA (rta );
370
+ FF_DEBUG ("Found metric: %u" , metric );
376
371
if (metric >= minMetric ) goto next ;
377
372
entry .metric = metric ;
378
- FF_DEBUG ("Found metric: %u" , entry .metric );
379
373
}
380
374
break ;
381
375
}
382
376
}
383
377
384
- if (entry .metric >= minMetric )
378
+ if (entry .ifindex == 0 || entry . metric >= minMetric )
385
379
{
386
380
next :
381
+ FF_DEBUG ("Skipping route: ifindex=%u, metric=%u" , entry .ifindex , entry .metric );
387
382
continue ;
388
383
}
389
384
minMetric = entry .metric ;
390
385
result -> ifIndex = entry .ifindex ;
391
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
+ }
392
393
}
393
394
394
395
if (minMetric < UINT32_MAX )
0 commit comments