@@ -27,6 +27,7 @@ LOG_MODULE_REGISTER(net_dns_resolve, CONFIG_DNS_RESOLVER_LOG_LEVEL);
2727#include <zephyr/net/net_mgmt.h>
2828#include <zephyr/net/dns_resolve.h>
2929#include <zephyr/net/socket_service.h>
30+ #include "../../ip/net_private.h"
3031#include "dns_pack.h"
3132#include "dns_internal.h"
3233#include "dns_cache.h"
@@ -319,6 +320,31 @@ static int register_dispatcher(struct dns_resolve_context *ctx,
319320 return dns_dispatcher_register (& server -> dispatcher );
320321}
321322
323+ static int bind_to_iface (int sock , const struct sockaddr * addr , int if_index )
324+ {
325+ struct ifreq ifreq = { 0 };
326+ int ret ;
327+
328+ ret = net_if_get_name (net_if_get_by_index (if_index ), ifreq .ifr_name ,
329+ sizeof (ifreq .ifr_name ));
330+ if (ret < 0 ) {
331+ LOG_DBG ("Cannot get interface name for %d (%d)" , if_index , ret );
332+ return ret ;
333+ }
334+
335+ ret = zsock_setsockopt (sock , SOL_SOCKET , SO_BINDTODEVICE ,
336+ & ifreq , sizeof (ifreq ));
337+ if (ret < 0 ) {
338+ ret = - errno ;
339+
340+ NET_DBG ("Cannot bind %s to %d (%d)" ,
341+ net_sprint_addr (addr -> sa_family , & net_sin (addr )-> sin_addr ),
342+ if_index , ret );
343+ }
344+
345+ return ret ;
346+ }
347+
322348/* Must be invoked with context lock held */
323349static int dns_resolve_init_locked (struct dns_resolve_context * ctx ,
324350 const char * servers [],
@@ -363,24 +389,56 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx,
363389
364390 if (servers ) {
365391 for (i = 0 ; idx < SERVER_COUNT && servers [i ]; i ++ ) {
392+ const char * iface_str ;
393+ size_t server_len ;
394+
366395 struct sockaddr * addr = & ctx -> servers [idx ].dns_server ;
367396
397+ iface_str = strstr (servers [i ], "%" );
398+ if (iface_str ) {
399+ server_len = iface_str - servers [i ];
400+ iface_str ++ ;
401+
402+ if (server_len == 0 ) {
403+ NET_DBG ("Empty server name" );
404+ continue ;
405+ }
406+
407+ /* Skip empty interface name */
408+ if (iface_str [0 ] == '\0' ) {
409+ ctx -> servers [idx ].if_index = 0 ;
410+ iface_str = NULL ;
411+ } else {
412+ ctx -> servers [idx ].if_index =
413+ net_if_get_by_name (iface_str );
414+ }
415+
416+ } else {
417+ server_len = strlen (servers [i ]);
418+ ctx -> servers [idx ].if_index = 0 ;
419+ }
420+
368421 (void )memset (addr , 0 , sizeof (* addr ));
369422
370- ret = net_ipaddr_parse (servers [i ], strlen (servers [i ]),
371- addr );
423+ ret = net_ipaddr_parse (servers [i ], server_len , addr );
372424 if (!ret ) {
425+ if (servers [i ] != NULL && servers [i ][0 ] != '\0' ) {
426+ NET_DBG ("Invalid server address %.*s" ,
427+ server_len , servers [i ]);
428+ }
429+
373430 continue ;
374431 }
375432
376433 dns_postprocess_server (ctx , idx );
377434
378- NET_DBG ("[%d] %s%s%s" , i , servers [i ],
435+ NET_DBG ("[%d] %.* s%s%s%s%s " , i , server_len , servers [i ],
379436 IS_ENABLED (CONFIG_MDNS_RESOLVER ) ?
380437 (ctx -> servers [i ].is_mdns ? " mDNS" : "" ) : "" ,
381438 IS_ENABLED (CONFIG_LLMNR_RESOLVER ) ?
382- (ctx -> servers [i ].is_llmnr ?
383- " LLMNR" : "" ) : "" );
439+ (ctx -> servers [i ].is_llmnr ? " LLMNR" : "" ) : "" ,
440+ iface_str != NULL ? " via " : "" ,
441+ iface_str != NULL ? iface_str : "" );
384442 idx ++ ;
385443 }
386444 }
@@ -441,14 +499,40 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx,
441499
442500 ctx -> servers [i ].sock = ret ;
443501
502+ /* Try to bind to the interface if it is set */
503+ if (ctx -> servers [i ].if_index > 0 ) {
504+ ret = bind_to_iface (ctx -> servers [i ].sock ,
505+ & ctx -> servers [i ].dns_server ,
506+ ctx -> servers [i ].if_index );
507+ if (ret < 0 ) {
508+ zsock_close (ctx -> servers [i ].sock );
509+ ctx -> servers [i ].sock = -1 ;
510+ continue ;
511+ }
512+
513+ iface = net_if_get_by_index (ctx -> servers [i ].if_index );
514+ NET_DBG ("Binding %s to %d" ,
515+ net_sprint_addr (ctx -> servers [i ].dns_server .sa_family ,
516+ & net_sin (& ctx -> servers [i ].dns_server )-> sin_addr ),
517+ ctx -> servers [i ].if_index );
518+ } else {
519+ iface = NULL ;
520+ }
521+
444522 if (ctx -> servers [i ].dns_server .sa_family == AF_INET6 ) {
445- iface = net_if_ipv6_select_src_iface (
523+ if (iface == NULL ) {
524+ iface = net_if_ipv6_select_src_iface (
446525 & net_sin6 (& ctx -> servers [i ].dns_server )-> sin6_addr );
526+ }
527+
447528 addr6 = net_if_ipv6_select_src_addr (iface ,
448529 & net_sin6 (& ctx -> servers [i ].dns_server )-> sin6_addr );
449530 } else {
450- iface = net_if_ipv4_select_src_iface (
531+ if (iface == NULL ) {
532+ iface = net_if_ipv4_select_src_iface (
451533 & net_sin (& ctx -> servers [i ].dns_server )-> sin_addr );
534+ }
535+
452536 addr4 = net_if_ipv4_select_src_addr (iface ,
453537 & net_sin (& ctx -> servers [i ].dns_server )-> sin_addr );
454538 }
0 commit comments