@@ -23,11 +23,13 @@ struct UTMAppleConfigurationNetwork: Codable, Identifiable {
2323    enum  NetworkMode :  String ,  CaseIterable ,  QEMUConstant  { 
2424        case  shared =  " Shared " 
2525        case  bridged =  " Bridged " 
26+         case  host =  " Host " 
2627
2728        var  prettyValue :  String  { 
2829            switch  self  { 
2930            case  . shared:  return  NSLocalizedString ( " Shared Network " ,  comment:  " UTMAppleConfigurationNetwork " ) 
3031            case  . bridged:  return  NSLocalizedString ( " Bridged (Advanced) " ,  comment:  " UTMAppleConfigurationNetwork " ) 
32+             case  . host:  return  NSLocalizedString ( " Host (Advanced) " ,  comment:  " UTMAppleConfigurationNetwork " ) 
3133            } 
3234        } 
3335    } 
@@ -40,12 +42,16 @@ struct UTMAppleConfigurationNetwork: Codable, Identifiable {
4042    /// In bridged mode this is the physical interface to bridge.
4143    var  bridgeInterface :  String ? 
4244
45+     /// Network UUID to attach to in host mode
46+     var  hostNetUuid :  String ? 
47+     
4348    let  id =  UUID ( ) 
4449
4550    enum  CodingKeys :  String ,  CodingKey  { 
4651        case  mode =  " Mode " 
4752        case  macAddress =  " MacAddress " 
4853        case  bridgeInterface =  " BridgeInterface " 
54+         case  hostNetUuid =  " HostNetUuid " 
4955    } 
5056
5157    init ( )  { 
@@ -56,6 +62,7 @@ struct UTMAppleConfigurationNetwork: Codable, Identifiable {
5662        mode =  try . decode ( NetworkMode . self,  forKey:  . mode) 
5763        macAddress =  try . decode ( String . self,  forKey:  . macAddress) 
5864        bridgeInterface =  try . decodeIfPresent ( String . self,  forKey:  . bridgeInterface) 
65+         hostNetUuid =  try . decodeIfPresent ( UUID . self,  forKey:  . hostNetUuid) ? . uuidString
5966    } 
6067
6168    func  encode( to encoder:  Encoder )  throws  { 
@@ -65,6 +72,9 @@ struct UTMAppleConfigurationNetwork: Codable, Identifiable {
6572        if  mode ==  . bridged { 
6673            try . encodeIfPresent ( bridgeInterface,  forKey:  . bridgeInterface) 
6774        } 
75+         if  mode ==  . host { 
76+             try . encodeIfPresent ( hostNetUuid,  forKey:  . hostNetUuid) 
77+         } 
6878    } 
6979
7080    init ? ( from config:  VZNetworkDeviceConfiguration )  { 
@@ -77,9 +87,26 @@ struct UTMAppleConfigurationNetwork: Codable, Identifiable {
7787            bridgeInterface =  attachment. interface. identifier
7888        }  else  if  let  _ =  virtioConfig. attachment as?  VZNATNetworkDeviceAttachment  { 
7989            mode =  . shared
80-         }  else  { 
81-             return  nil 
90+         }  else  if  #available( macOS 26 . 0 ,  * )  { 
91+             if  let  attachment =  virtioConfig. attachment as?  VZVmnetNetworkDeviceAttachment  { 
92+                 mode =  . host
93+                 var  status :  vmnet_return_t  =  . VMNET_SUCCESS
94+                 guard  let  vmnetConfig =  vmnet_network_copy_serialization ( attachment. network,  & status) ,  status ==  . VMNET_SUCCESS else  { 
95+                     return  nil 
96+                 } 
97+                 if  let  uuidPtr =  xpc_dictionary_get_uuid ( vmnetConfig,  vmnet. vmnet_network_identifier_key)  { 
98+                     let  uuidBytes  =  UnsafeRawPointer ( uuidPtr) . assumingMemoryBound ( to:  UInt8 . self) 
99+                     let  uuid  =  UUID ( uuid:  ( 
100+                         uuidBytes [ 0 ] ,  uuidBytes [ 1 ] ,  uuidBytes [ 2 ] ,  uuidBytes [ 3 ] , 
101+                         uuidBytes [ 4 ] ,  uuidBytes [ 5 ] ,  uuidBytes [ 6 ] ,  uuidBytes [ 7 ] , 
102+                         uuidBytes [ 8 ] ,  uuidBytes [ 9 ] ,  uuidBytes [ 10 ] ,  uuidBytes [ 11 ] , 
103+                         uuidBytes [ 12 ] ,  uuidBytes [ 13 ] ,  uuidBytes [ 14 ] ,  uuidBytes [ 15 ] 
104+                     ) ) 
105+                     hostNetUuid =  uuid. uuidString
106+                 } 
107+             } 
82108        } 
109+         return  nil 
83110    } 
84111
85112    func  vzNetworking( )  ->  VZNetworkDeviceConfiguration ? { 
@@ -109,7 +136,24 @@ struct UTMAppleConfigurationNetwork: Codable, Identifiable {
109136                let  attachment  =  VZBridgedNetworkDeviceAttachment ( interface:  found) 
110137                config. attachment =  attachment
111138            } 
139+         case  . host: 
140+             if  #available( macOS 26 . 0 ,  * )  { 
141+                 if  let  netUuid =  hostNetUuid { 
142+                     let  vmnetConfig  =  xpc_dictionary_create_empty ( ) 
143+                     xpc_dictionary_set_uint64 ( vmnetConfig,  vmnet. vmnet_operation_mode_key,  UInt64 ( vmnet. vmnet_mode_t. VMNET_HOST_MODE. rawValue) ) 
144+                     xpc_dictionary_set_uuid ( vmnetConfig,  vmnet. vmnet_network_identifier_key,  netUuid) 
145+ 
146+                     var  status :  vmnet_return_t  =  . VMNET_SUCCESS
147+                     guard  let  vmnetNetwork =  vmnet_network_create_with_serialization ( vmnetConfig,  & status) ,  status ==  . VMNET_SUCCESS else  { 
148+                         return  nil 
149+                     } 
150+ 
151+                     let  attachment  =  VZVmnetNetworkDeviceAttachment ( network:  vmnetNetwork) 
152+                     config. attachment =  attachment
153+                 } 
154+             } 
112155        } 
156+ 
113157        return  config
114158    } 
115159} 
0 commit comments