@@ -22,6 +22,38 @@ use nix::sys::socket::{accept, bind, getsockname, socket, AddressFamily, SockFla
2222use tracing:: { debug, trace, warn} ;
2323use vsock:: VsockAddr ;
2424
25+ /// Read DNS servers from /etc/resolv.conf
26+ /// Returns a vector of DNS server IP addresses, or None if unable to read/parse
27+ pub fn read_dns_servers ( ) -> Option < Vec < String > > {
28+ let resolv_conf = match std:: fs:: read_to_string ( "/etc/resolv.conf" ) {
29+ Ok ( content) => content,
30+ Err ( e) => {
31+ debug ! ( "Failed to read /etc/resolv.conf: {}" , e) ;
32+ return None ;
33+ }
34+ } ;
35+
36+ let mut dns_servers = Vec :: new ( ) ;
37+ for line in resolv_conf. lines ( ) {
38+ let line = line. trim ( ) ;
39+ // Parse lines like "nameserver 8.8.8.8" or "nameserver 2001:4860:4860::8888"
40+ if let Some ( server) = line. strip_prefix ( "nameserver " ) {
41+ let server = server. trim ( ) ;
42+ if !server. is_empty ( ) {
43+ dns_servers. push ( server. to_string ( ) ) ;
44+ }
45+ }
46+ }
47+
48+ if dns_servers. is_empty ( ) {
49+ debug ! ( "No DNS servers found in /etc/resolv.conf" ) ;
50+ None
51+ } else {
52+ debug ! ( "Found DNS servers: {:?}" , dns_servers) ;
53+ Some ( dns_servers)
54+ }
55+ }
56+
2557/// The device for vsock allocation
2658pub const VHOST_VSOCK : & str = "/dev/vhost-vsock" ;
2759
@@ -80,12 +112,17 @@ pub enum NetworkMode {
80112 User {
81113 /// Port forwarding rules: "tcp::2222-:22" format
82114 hostfwd : Vec < String > ,
115+ /// DNS servers to use (if None, QEMU's default 10.0.2.3 will be used)
116+ dns_servers : Option < Vec < String > > ,
83117 } ,
84118}
85119
86120impl Default for NetworkMode {
87121 fn default ( ) -> Self {
88- NetworkMode :: User { hostfwd : vec ! [ ] }
122+ NetworkMode :: User {
123+ hostfwd : vec ! [ ] ,
124+ dns_servers : None ,
125+ }
89126 }
90127}
91128
@@ -322,8 +359,13 @@ impl QemuConfig {
322359 pub fn enable_ssh_access ( & mut self , host_port : Option < u16 > ) -> & mut Self {
323360 let port = host_port. unwrap_or ( 2222 ) ; // Default to port 2222 on host
324361 let hostfwd = format ! ( "tcp::{}-:22" , port) ; // Forward host port to guest port 22
362+ // Preserve existing DNS servers if any
363+ let dns_servers = match & self . network_mode {
364+ NetworkMode :: User { dns_servers, .. } => dns_servers. clone ( ) ,
365+ } ;
325366 self . network_mode = NetworkMode :: User {
326367 hostfwd : vec ! [ hostfwd] ,
368+ dns_servers,
327369 } ;
328370 self
329371 }
@@ -522,23 +564,29 @@ fn spawn(
522564
523565 // Configure network (only User mode supported now)
524566 match & config. network_mode {
525- NetworkMode :: User { hostfwd } => {
526- if hostfwd. is_empty ( ) {
527- cmd. args ( [
528- "-netdev" ,
529- "user,id=net0" ,
530- "-device" ,
531- "virtio-net-pci,netdev=net0" ,
532- ] ) ;
533- } else {
534- let hostfwd_arg = format ! ( "user,id=net0,hostfwd={}" , hostfwd. join( ",hostfwd=" ) ) ;
535- cmd. args ( [
536- "-netdev" ,
537- & hostfwd_arg,
538- "-device" ,
539- "virtio-net-pci,netdev=net0" ,
540- ] ) ;
567+ NetworkMode :: User { hostfwd, dns_servers } => {
568+ let mut netdev_parts = vec ! [ "user" . to_string( ) , "id=net0" . to_string( ) ] ;
569+
570+ // Add DNS servers if specified
571+ if let Some ( dns_list) = dns_servers {
572+ if !dns_list. is_empty ( ) {
573+ let dns_arg = format ! ( "dns={}" , dns_list. join( "," ) ) ;
574+ netdev_parts. push ( dns_arg) ;
575+ }
541576 }
577+
578+ // Add port forwarding rules
579+ for fwd in hostfwd {
580+ netdev_parts. push ( format ! ( "hostfwd={}" , fwd) ) ;
581+ }
582+
583+ let netdev_arg = netdev_parts. join ( "," ) ;
584+ cmd. args ( [
585+ "-netdev" ,
586+ & netdev_arg,
587+ "-device" ,
588+ "virtio-net-pci,netdev=net0" ,
589+ ] ) ;
542590 }
543591 }
544592
0 commit comments