blob: cce34f2017334cd31abb870a39dca2f7d27d11f8 [file] [log] [blame]
Seungjae Yoo529d53c2024-05-14 14:36:18 +09001// Copyright 2024, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Implementation of the AIDL interface of Vmnic.
16
Seungjae Yoo0a442662024-05-20 16:35:49 +090017use anyhow::{anyhow, Context, Result};
Seungjae Yoo529d53c2024-05-14 14:36:18 +090018use android_system_virtualizationservice_internal::aidl::android::system::virtualizationservice_internal::IVmnic::IVmnic;
Seungjae Yoo0a442662024-05-20 16:35:49 +090019use binder::{self, Interface, IntoBinderResult, ParcelFileDescriptor};
Seungjae Yoo986d7a42024-05-28 14:06:58 +090020use libc::{c_char, c_int, c_short, ifreq, IFF_NO_PI, IFF_TAP, IFF_UP, IFF_VNET_HDR, IFNAMSIZ};
Seungjae Yoo13af0b62024-05-20 14:15:13 +090021use log::info;
Seungjae Yoo0a442662024-05-20 16:35:49 +090022use nix::{ioctl_write_int_bad, ioctl_write_ptr_bad};
23use nix::sys::ioctl::ioctl_num_type;
24use nix::sys::socket::{socket, AddressFamily, SockFlag, SockType};
Seungjae Yoo3271f172024-06-11 10:14:07 +090025use std::ffi::{CStr, CString};
Seungjae Yoo0a442662024-05-20 16:35:49 +090026use std::fs::File;
27use std::os::fd::{AsRawFd, RawFd};
28use std::slice::from_raw_parts;
29
Seungjae Yood3f76422024-06-14 15:26:51 +090030const TUNGETIFF: ioctl_num_type = 0x800454d2u32 as ioctl_num_type;
Seungjae Yoo0a442662024-05-20 16:35:49 +090031const TUNSETIFF: ioctl_num_type = 0x400454ca;
32const TUNSETPERSIST: ioctl_num_type = 0x400454cb;
Seungjae Yoo0a442662024-05-20 16:35:49 +090033const SIOCSIFFLAGS: ioctl_num_type = 0x00008914;
34
Seungjae Yoo3271f172024-06-11 10:14:07 +090035ioctl_write_ptr_bad!(ioctl_tungetiff, TUNGETIFF, ifreq);
Seungjae Yoo0a442662024-05-20 16:35:49 +090036ioctl_write_ptr_bad!(ioctl_tunsetiff, TUNSETIFF, ifreq);
37ioctl_write_int_bad!(ioctl_tunsetpersist, TUNSETPERSIST);
Seungjae Yoo0a442662024-05-20 16:35:49 +090038ioctl_write_ptr_bad!(ioctl_siocsifflags, SIOCSIFFLAGS, ifreq);
39
40fn validate_ifname(ifname: &[c_char]) -> Result<()> {
41 if ifname.len() >= IFNAMSIZ {
42 return Err(anyhow!(format!("Interface name is too long")));
43 }
44 Ok(())
45}
46
Seungjae Yoo3271f172024-06-11 10:14:07 +090047fn create_tap_interface(fd: RawFd, sockfd: c_int, ifname: &[c_char]) -> Result<()> {
Seungjae Yoo0a442662024-05-20 16:35:49 +090048 // SAFETY: All-zero is a valid value for the ifreq type.
49 let mut ifr: ifreq = unsafe { std::mem::zeroed() };
Seungjae Yoo986d7a42024-05-28 14:06:58 +090050 ifr.ifr_ifru.ifru_flags = (IFF_TAP | IFF_NO_PI | IFF_VNET_HDR) as c_short;
Seungjae Yoo0a442662024-05-20 16:35:49 +090051 ifr.ifr_name[..ifname.len()].copy_from_slice(ifname);
Seungjae Yoo3271f172024-06-11 10:14:07 +090052 // SAFETY: It modifies the state in the kernel, not the state of this process in any way.
Seungjae Yoo0a442662024-05-20 16:35:49 +090053 unsafe { ioctl_tunsetiff(fd, &ifr) }.context("Failed to ioctl TUNSETIFF")?;
Seungjae Yoo3271f172024-06-11 10:14:07 +090054 // SAFETY: It modifies the state in the kernel, not the state of this process in any way.
Seungjae Yoo0a442662024-05-20 16:35:49 +090055 unsafe { ioctl_tunsetpersist(fd, 1) }.context("Failed to ioctl TUNSETPERSIST")?;
Seungjae Yoo3271f172024-06-11 10:14:07 +090056 // SAFETY: ifr_ifru holds ifru_flags in its union field.
57 unsafe { ifr.ifr_ifru.ifru_flags |= IFF_UP as c_short };
58 // SAFETY: It modifies the state in the kernel, not the state of this process in any way.
59 unsafe { ioctl_siocsifflags(sockfd, &ifr) }.context("Failed to ioctl SIOCSIFFLAGS")?;
Seungjae Yoo0a442662024-05-20 16:35:49 +090060 Ok(())
61}
62
Seungjae Yoo3271f172024-06-11 10:14:07 +090063fn get_tap_ifreq(fd: RawFd) -> Result<ifreq> {
Seungjae Yoo0a442662024-05-20 16:35:49 +090064 // SAFETY: All-zero is a valid value for the ifreq type.
Seungjae Yoo3271f172024-06-11 10:14:07 +090065 let ifr: ifreq = unsafe { std::mem::zeroed() };
66 // SAFETY: Returned `ifr` of given file descriptor is set from TUNSETIFF ioctl while executing
67 // create_tap_interface(fd, sockfd, ifname). So the variable `ifr` should be safe.
68 unsafe { ioctl_tungetiff(fd, &ifr) }.context("Failed to ioctl TUNGETIFF")?;
69 Ok(ifr)
70}
71
72fn delete_tap_interface(fd: RawFd, sockfd: c_int, ifr: &mut ifreq) -> Result<()> {
73 // SAFETY: After calling TUNGETIFF, ifr_ifru holds ifru_flags in its union field.
74 unsafe { ifr.ifr_ifru.ifru_flags &= !IFF_UP as c_short };
75 // SAFETY: It modifies the state in the kernel, not the state of this process in any way.
76 unsafe { ioctl_siocsifflags(sockfd, ifr) }.context("Failed to ioctl SIOCSIFFLAGS")?;
77 // SAFETY: It modifies the state in the kernel, not the state of this process in any way.
78 unsafe { ioctl_tunsetpersist(fd, 0) }.context("Failed to ioctl TUNSETPERSIST")?;
Seungjae Yoo0a442662024-05-20 16:35:49 +090079 Ok(())
80}
Seungjae Yoo529d53c2024-05-14 14:36:18 +090081
82#[derive(Debug, Default)]
83pub struct Vmnic {}
84
85impl Vmnic {
86 pub fn init() -> Vmnic {
87 Vmnic::default()
88 }
89}
90
91impl Interface for Vmnic {}
92
93impl IVmnic for Vmnic {
Seungjae Yoo13af0b62024-05-20 14:15:13 +090094 fn createTapInterface(&self, iface_name_suffix: &str) -> binder::Result<ParcelFileDescriptor> {
Seungjae Yoo0a442662024-05-20 16:35:49 +090095 let ifname = CString::new(format!("avf_tap_{iface_name_suffix}"))
96 .context(format!(
97 "Failed to construct TAP interface name as CString: avf_tap_{iface_name_suffix}"
98 ))
99 .or_service_specific_exception(-1)?;
100 let ifname_bytes = ifname.as_bytes_with_nul();
101 // SAFETY: Converting from &[u8] into &[c_char].
102 let ifname_bytes =
103 unsafe { from_raw_parts(ifname_bytes.as_ptr().cast::<c_char>(), ifname_bytes.len()) };
104 validate_ifname(ifname_bytes)
105 .context(format!("Invalid interface name: {ifname:#?}"))
106 .or_service_specific_exception(-1)?;
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900107
Seungjae Yoo0a442662024-05-20 16:35:49 +0900108 let tunfd = File::open("/dev/tun")
109 .context("Failed to open /dev/tun")
110 .or_service_specific_exception(-1)?;
Seungjae Yoo0a442662024-05-20 16:35:49 +0900111 let sock = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None)
112 .context("Failed to create socket")
113 .or_service_specific_exception(-1)?;
Seungjae Yoo3271f172024-06-11 10:14:07 +0900114 create_tap_interface(tunfd.as_raw_fd(), sock.as_raw_fd(), ifname_bytes)
115 .context(format!("Failed to create TAP interface: {ifname:#?}"))
Seungjae Yoo0a442662024-05-20 16:35:49 +0900116 .or_service_specific_exception(-1)?;
117
118 info!("Created TAP network interface: {ifname:#?}");
119 Ok(ParcelFileDescriptor::new(tunfd))
Seungjae Yoo529d53c2024-05-14 14:36:18 +0900120 }
Seungjae Yoo3271f172024-06-11 10:14:07 +0900121
122 fn deleteTapInterface(&self, tapfd: &ParcelFileDescriptor) -> binder::Result<()> {
123 let tap = tapfd.as_raw_fd();
124 let mut tap_ifreq = get_tap_ifreq(tap)
125 .context("Failed to get ifreq of TAP interface")
126 .or_service_specific_exception(-1)?;
127 // SAFETY: tap_ifreq.ifr_name is null-terminated within IFNAMSIZ, validated when creating
128 // TAP interface.
129 let ifname = unsafe { CStr::from_ptr(tap_ifreq.ifr_name.as_ptr()) };
130
131 let sock = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None)
132 .context("Failed to create socket")
133 .or_service_specific_exception(-1)?;
134 delete_tap_interface(tap, sock.as_raw_fd(), &mut tap_ifreq)
135 .context(format!("Failed to create TAP interface: {ifname:#?}"))
136 .or_service_specific_exception(-1)?;
137
138 info!("Deleted TAP network interface: {ifname:#?}");
139 Ok(())
140 }
Seungjae Yoo529d53c2024-05-14 14:36:18 +0900141}