1
1
#include "netif.h"
2
2
#include "common/io/io.h"
3
3
#include "util/mallocHelper.h"
4
+ #include "util/debug.h"
4
5
5
6
#include <arpa/inet.h>
6
7
#include <linux/rtnetlink.h>
7
8
#include <net/if.h>
8
9
9
- #define FF_STR_INDIR (x ) #x
10
- #define FF_STR (x ) FF_STR_INDIR(x)
11
-
12
10
bool ffNetifGetDefaultRouteImplV4 (FFNetifDefaultRouteResult * result )
13
11
{
12
+ FF_DEBUG ("Starting IPv4 default route detection" );
13
+
14
14
FF_AUTO_CLOSE_FD int sock_fd = socket (AF_NETLINK , SOCK_RAW | SOCK_CLOEXEC , NETLINK_ROUTE );
15
15
if (sock_fd < 0 )
16
+ {
17
+ FF_DEBUG ("Failed to create netlink socket: %s" , strerror (errno ));
16
18
return false;
19
+ }
20
+ FF_DEBUG ("Created netlink socket: fd=%d" , sock_fd );
17
21
18
22
unsigned pid = (unsigned ) getpid ();
23
+ FF_DEBUG ("Process PID: %u" , pid );
19
24
20
25
// Bind socket
21
26
struct sockaddr_nl addr = {
22
27
.nl_family = AF_NETLINK ,
23
- .nl_pid = pid ,
28
+ .nl_pid = 0 , // Let kernel choose PID
24
29
.nl_groups = 0 , // No multicast groups
25
30
};
26
31
27
32
if (bind (sock_fd , (struct sockaddr * )& addr , sizeof (addr )) < 0 ) {
33
+ FF_DEBUG ("Failed to bind socket: %s" , strerror (errno ));
28
34
return false;
29
35
}
36
+ FF_DEBUG ("Successfully bound socket" );
30
37
31
- struct {
38
+ struct __attribute__(( __packed__ )) {
32
39
struct nlmsghdr nlh ;
33
40
struct rtmsg rtm ;
34
41
struct rtattr rta ;
@@ -72,59 +79,68 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
72
79
(struct sockaddr * )& dest_addr , sizeof (dest_addr ));
73
80
74
81
if (sent != sizeof (req )) {
82
+ FF_DEBUG ("Failed to send netlink request: sent=%zd, expected=%zu" , sent , sizeof (req ));
75
83
return false;
76
84
}
85
+ FF_DEBUG ("Sent netlink request: %zd bytes" , sent );
77
86
78
87
struct sockaddr_nl src_addr = {};
79
88
socklen_t src_addr_len = sizeof (src_addr );
80
89
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 );
88
94
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 ));
91
97
return false;
92
98
}
93
99
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)" );
99
102
return false;
100
103
}
104
+ FF_DEBUG ("Received netlink response: %zd bytes" , received );
101
105
102
106
struct {
103
107
uint32_t metric ;
104
108
uint32_t ifindex ;
105
109
uint32_t prefsrc ;
106
110
} entry ;
107
111
uint32_t minMetric = UINT32_MAX ;
112
+ int routeCount = 0 ;
108
113
109
114
for (const struct nlmsghdr * nlh = (struct nlmsghdr * )buffer ;
110
115
NLMSG_OK (nlh , received );
111
116
nlh = NLMSG_NEXT (nlh , received )) {
112
117
if (nlh -> nlmsg_seq != 1 || nlh -> nlmsg_pid != pid )
113
118
continue ;
114
119
if (nlh -> nlmsg_type == NLMSG_DONE )
120
+ {
121
+ FF_DEBUG ("Received NLMSG_DONE, processed %d routes" , routeCount );
115
122
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
+ }
116
130
117
131
if (nlh -> nlmsg_type != RTM_NEWROUTE )
118
132
continue ;
119
133
134
+ routeCount ++ ;
120
135
struct rtmsg * rtm = (struct rtmsg * )NLMSG_DATA (nlh );
121
136
if (rtm -> rtm_family != AF_INET )
122
137
continue ;
123
138
124
139
if (rtm -> rtm_dst_len != 0 )
125
140
continue ;
126
141
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)
128
144
129
145
// Parse route attributes
130
146
size_t rtm_len = RTM_PAYLOAD (nlh );
@@ -138,62 +154,84 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
138
154
uint32_t rta_data = * (uint32_t * ) RTA_DATA (rta );
139
155
switch (rta -> rta_type ) {
140
156
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 ;
143
159
case RTA_OIF :
144
160
entry .ifindex = rta_data ;
161
+ FF_DEBUG ("Found interface index: %u" , entry .ifindex );
145
162
break ;
146
163
case RTA_GATEWAY :
164
+ FF_DEBUG ("Found gateway: %s" , inet_ntoa (* (struct in_addr * )& rta_data ));
147
165
if (rta_data == 0 ) goto next ;
148
166
break ;
149
167
case RTA_PRIORITY :
168
+ FF_DEBUG ("Found metric: %u" , rta_data );
150
169
if (rta_data >= minMetric ) goto next ;
151
170
entry .metric = rta_data ;
152
171
break ;
153
172
case RTA_PREFSRC :
154
173
entry .prefsrc = rta_data ;
174
+ FF_DEBUG ("Found preferred source: %s" , inet_ntoa (* (struct in_addr * )& rta_data ));
155
175
break ;
156
176
}
157
177
}
158
178
159
- if (entry .metric >= minMetric )
179
+ if (entry .ifindex == 0 || entry . metric >= minMetric )
160
180
{
161
181
next :
182
+ FF_DEBUG ("Skipping route: ifindex=%u, metric=%u" , entry .ifindex , entry .metric );
162
183
continue ;
163
184
}
164
185
minMetric = entry .metric ;
165
186
result -> ifIndex = entry .ifindex ;
187
+ FF_DEBUG ("Updated best route: ifindex=%u, metric=%u, prefsrc=%x" , entry .ifindex , entry .metric , entry .prefsrc );
166
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
+ }
167
194
}
168
195
169
196
if (minMetric < UINT32_MAX )
170
197
{
171
198
if_indextoname (result -> ifIndex , result -> ifName );
199
+ FF_DEBUG ("Found default IPv4 route: interface=%s, index=%u, metric=%u" , result -> ifName , result -> ifIndex , minMetric );
172
200
return true;
173
201
}
202
+ FF_DEBUG ("No IPv4 default route found" );
174
203
return false;
175
204
}
176
205
177
206
bool ffNetifGetDefaultRouteImplV6 (FFNetifDefaultRouteResult * result )
178
207
{
208
+ FF_DEBUG ("Starting IPv6 default route detection" );
209
+
179
210
FF_AUTO_CLOSE_FD int sock_fd = socket (AF_NETLINK , SOCK_RAW | SOCK_CLOEXEC , NETLINK_ROUTE );
180
211
if (sock_fd < 0 )
212
+ {
213
+ FF_DEBUG ("Failed to create netlink socket: %s" , strerror (errno ));
181
214
return false;
215
+ }
216
+ FF_DEBUG ("Created netlink socket: fd=%d" , sock_fd );
182
217
183
218
unsigned pid = (unsigned ) getpid ();
219
+ FF_DEBUG ("Process PID: %u" , pid );
184
220
185
221
// Bind socket
186
222
struct sockaddr_nl addr = {
187
223
.nl_family = AF_NETLINK ,
188
- .nl_pid = pid ,
224
+ .nl_pid = 0 , // Let kernel choose PID
189
225
.nl_groups = 0 , // No multicast groups
190
226
};
191
227
192
228
if (bind (sock_fd , (struct sockaddr * )& addr , sizeof (addr )) < 0 ) {
229
+ FF_DEBUG ("Failed to bind socket: %s" , strerror (errno ));
193
230
return false;
194
231
}
232
+ FF_DEBUG ("Successfully bound socket" );
195
233
196
- struct {
234
+ struct __attribute__(( __packed__ )) {
197
235
struct nlmsghdr nlh ;
198
236
struct rtmsg rtm ;
199
237
struct rtattr rta ;
@@ -237,30 +275,26 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
237
275
(struct sockaddr * )& dest_addr , sizeof (dest_addr ));
238
276
239
277
if (sent != sizeof (req )) {
278
+ FF_DEBUG ("Failed to send netlink request: sent=%zd, expected=%zu" , sent , sizeof (req ));
240
279
return false;
241
280
}
281
+ FF_DEBUG ("Sent netlink request: %zd bytes" , sent );
242
282
243
283
struct sockaddr_nl src_addr = {};
244
284
socklen_t src_addr_len = sizeof (src_addr );
245
285
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
253
287
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 ));
256
293
return false;
257
294
}
258
295
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)" );
264
298
return false;
265
299
}
266
300
@@ -269,26 +303,38 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
269
303
uint32_t ifindex ;
270
304
} entry ;
271
305
uint32_t minMetric = UINT32_MAX ;
306
+ int routeCount = 0 ;
272
307
273
308
for (const struct nlmsghdr * nlh = (struct nlmsghdr * )buffer ;
274
309
NLMSG_OK (nlh , received );
275
310
nlh = NLMSG_NEXT (nlh , received )) {
276
311
if (nlh -> nlmsg_seq != 1 || nlh -> nlmsg_pid != pid )
277
312
continue ;
278
313
if (nlh -> nlmsg_type == NLMSG_DONE )
314
+ {
315
+ FF_DEBUG ("Received NLMSG_DONE, processed %d routes" , routeCount );
279
316
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
+ }
280
324
281
325
if (nlh -> nlmsg_type != RTM_NEWROUTE )
282
326
continue ;
283
327
328
+ routeCount ++ ;
284
329
struct rtmsg * rtm = (struct rtmsg * )NLMSG_DATA (nlh );
285
330
if (rtm -> rtm_family != AF_INET6 )
286
331
continue ;
287
332
288
333
if (rtm -> rtm_dst_len != 0 )
289
334
continue ;
290
335
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)
292
338
293
339
// Parse route attributes
294
340
size_t rtm_len = RTM_PAYLOAD (nlh );
@@ -299,44 +345,59 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
299
345
switch (rta -> rta_type ) {
300
346
case RTA_DST :
301
347
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 ;
304
351
}
305
352
break ;
306
353
case RTA_OIF :
307
354
if (RTA_PAYLOAD (rta ) >= sizeof (uint32_t )) {
308
355
entry .ifindex = * (uint32_t * ) RTA_DATA (rta );
356
+ FF_DEBUG ("Found interface index: %u" , entry .ifindex );
309
357
}
310
358
break ;
311
359
case RTA_GATEWAY :
312
360
if (RTA_PAYLOAD (rta ) >= sizeof (struct in6_addr )) {
313
361
struct in6_addr * gw = (struct in6_addr * ) RTA_DATA (rta );
314
362
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 )));
315
365
}
316
366
break ;
317
367
case RTA_PRIORITY :
318
368
if (RTA_PAYLOAD (rta ) >= sizeof (uint32_t )) {
319
369
uint32_t metric = * (uint32_t * ) RTA_DATA (rta );
370
+ FF_DEBUG ("Found metric: %u" , metric );
320
371
if (metric >= minMetric ) goto next ;
321
372
entry .metric = metric ;
322
373
}
323
374
break ;
324
375
}
325
376
}
326
377
327
- if (entry .metric >= minMetric )
378
+ if (entry .ifindex == 0 || entry . metric >= minMetric )
328
379
{
329
380
next :
381
+ FF_DEBUG ("Skipping route: ifindex=%u, metric=%u" , entry .ifindex , entry .metric );
330
382
continue ;
331
383
}
332
384
minMetric = entry .metric ;
333
385
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
+ }
334
393
}
335
394
336
395
if (minMetric < UINT32_MAX )
337
396
{
338
397
if_indextoname (result -> ifIndex , result -> ifName );
398
+ FF_DEBUG ("Found default IPv6 route: interface=%s, index=%u, metric=%u" , result -> ifName , result -> ifIndex , minMetric );
339
399
return true;
340
400
}
401
+ FF_DEBUG ("No IPv6 default route found" );
341
402
return false;
342
403
}
0 commit comments