77#include <linux/rtnetlink.h>
88#include <net/if.h>
99
10- #define FF_STR_INDIR (x ) #x
11- #define FF_STR (x ) FF_STR_INDIR(x)
12-
1310bool ffNetifGetDefaultRouteImplV4 (FFNetifDefaultRouteResult * result )
1411{
1512 FF_DEBUG ("Starting IPv4 default route detection" );
1613
1714 FF_AUTO_CLOSE_FD int sock_fd = socket (AF_NETLINK , SOCK_RAW | SOCK_CLOEXEC , NETLINK_ROUTE );
1815 if (sock_fd < 0 )
1916 {
20- FF_DEBUG ("Failed to create netlink socket: errno=%d " , errno );
17+ FF_DEBUG ("Failed to create netlink socket: %s " , strerror ( errno ) );
2118 return false;
2219 }
2320 FF_DEBUG ("Created netlink socket: fd=%d" , sock_fd );
@@ -28,17 +25,17 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
2825 // Bind socket
2926 struct sockaddr_nl addr = {
3027 .nl_family = AF_NETLINK ,
31- .nl_pid = pid ,
28+ .nl_pid = 0 , // Let kernel choose PID
3229 .nl_groups = 0 , // No multicast groups
3330 };
3431
3532 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 ) );
3734 return false;
3835 }
3936 FF_DEBUG ("Successfully bound socket" );
4037
41- struct {
38+ struct __attribute__(( __packed__ )) {
4239 struct nlmsghdr nlh ;
4340 struct rtmsg rtm ;
4441 struct rtattr rta ;
@@ -90,27 +87,18 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
9087 struct sockaddr_nl src_addr = {};
9188 socklen_t src_addr_len = sizeof (src_addr );
9289
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 );
10094
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 ));
10497 return false;
10598 }
106- FF_DEBUG ("Message size: %zd bytes" , peek_size );
107-
108- FF_AUTO_FREE uint8_t * buffer = malloc ((size_t )peek_size );
10999
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)" );
114102 return false;
115103 }
116104 FF_DEBUG ("Received netlink response: %zd bytes" , received );
@@ -134,6 +122,12 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
134122 break ;
135123 }
136124
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+
137131 if (nlh -> nlmsg_type != RTM_NEWROUTE )
138132 continue ;
139133
@@ -146,7 +140,7 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
146140 continue ;
147141
148142 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)
150144
151145 // Parse route attributes
152146 size_t rtm_len = RTM_PAYLOAD (nlh );
@@ -160,21 +154,20 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
160154 uint32_t rta_data = * (uint32_t * ) RTA_DATA (rta );
161155 switch (rta -> rta_type ) {
162156 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 ;
166159 case RTA_OIF :
167160 entry .ifindex = rta_data ;
168161 FF_DEBUG ("Found interface index: %u" , entry .ifindex );
169162 break ;
170163 case RTA_GATEWAY :
171- if (rta_data == 0 ) goto next ;
172164 FF_DEBUG ("Found gateway: %s" , inet_ntoa (* (struct in_addr * )& rta_data ));
165+ if (rta_data == 0 ) goto next ;
173166 break ;
174167 case RTA_PRIORITY :
168+ FF_DEBUG ("Found metric: %u" , rta_data );
175169 if (rta_data >= minMetric ) goto next ;
176170 entry .metric = rta_data ;
177- FF_DEBUG ("Found metric: %u" , entry .metric );
178171 break ;
179172 case RTA_PREFSRC :
180173 entry .prefsrc = rta_data ;
@@ -183,15 +176,21 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
183176 }
184177 }
185178
186- if (entry .metric >= minMetric )
179+ if (entry .ifindex == 0 || entry . metric >= minMetric )
187180 {
188181 next :
182+ FF_DEBUG ("Skipping route: ifindex=%u, metric=%u" , entry .ifindex , entry .metric );
189183 continue ;
190184 }
191185 minMetric = entry .metric ;
192186 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+ }
195194 }
196195
197196 if (minMetric < UINT32_MAX )
@@ -211,7 +210,7 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
211210 FF_AUTO_CLOSE_FD int sock_fd = socket (AF_NETLINK , SOCK_RAW | SOCK_CLOEXEC , NETLINK_ROUTE );
212211 if (sock_fd < 0 )
213212 {
214- FF_DEBUG ("Failed to create netlink socket: errno=%d " , errno );
213+ FF_DEBUG ("Failed to create netlink socket: %s " , strerror ( errno ) );
215214 return false;
216215 }
217216 FF_DEBUG ("Created netlink socket: fd=%d" , sock_fd );
@@ -222,17 +221,17 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
222221 // Bind socket
223222 struct sockaddr_nl addr = {
224223 .nl_family = AF_NETLINK ,
225- .nl_pid = pid ,
224+ .nl_pid = 0 , // Let kernel choose PID
226225 .nl_groups = 0 , // No multicast groups
227226 };
228227
229228 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 ) );
231230 return false;
232231 }
233232 FF_DEBUG ("Successfully bound socket" );
234233
235- struct {
234+ struct __attribute__(( __packed__ )) {
236235 struct nlmsghdr nlh ;
237236 struct rtmsg rtm ;
238237 struct rtattr rta ;
@@ -284,30 +283,20 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
284283 struct sockaddr_nl src_addr = {};
285284 socklen_t src_addr_len = sizeof (src_addr );
286285
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
294287
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 ));
298293 return false;
299294 }
300- FF_DEBUG ("Message size: %zd bytes" , peek_size );
301-
302- FF_AUTO_FREE uint8_t * buffer = malloc ((size_t )peek_size );
303295
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)" );
308298 return false;
309299 }
310- FF_DEBUG ("Received netlink response: %zd bytes" , received );
311300
312301 struct {
313302 uint32_t metric ;
@@ -327,6 +316,12 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
327316 break ;
328317 }
329318
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+
330325 if (nlh -> nlmsg_type != RTM_NEWROUTE )
331326 continue ;
332327
@@ -339,7 +334,7 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
339334 continue ;
340335
341336 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)
343338
344339 // Parse route attributes
345340 size_t rtm_len = RTM_PAYLOAD (nlh );
@@ -351,9 +346,8 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
351346 case RTA_DST :
352347 if (RTA_PAYLOAD (rta ) >= sizeof (struct in6_addr )) {
353348 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 ;
357351 }
358352 break ;
359353 case RTA_OIF :
@@ -373,22 +367,29 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
373367 case RTA_PRIORITY :
374368 if (RTA_PAYLOAD (rta ) >= sizeof (uint32_t )) {
375369 uint32_t metric = * (uint32_t * ) RTA_DATA (rta );
370+ FF_DEBUG ("Found metric: %u" , metric );
376371 if (metric >= minMetric ) goto next ;
377372 entry .metric = metric ;
378- FF_DEBUG ("Found metric: %u" , entry .metric );
379373 }
380374 break ;
381375 }
382376 }
383377
384- if (entry .metric >= minMetric )
378+ if (entry .ifindex == 0 || entry . metric >= minMetric )
385379 {
386380 next :
381+ FF_DEBUG ("Skipping route: ifindex=%u, metric=%u" , entry .ifindex , entry .metric );
387382 continue ;
388383 }
389384 minMetric = entry .metric ;
390385 result -> ifIndex = entry .ifindex ;
391386 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+ }
392393 }
393394
394395 if (minMetric < UINT32_MAX )
0 commit comments