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-
1210bool 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
177206bool 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