Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ffi/src/provider.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Jackson Coxson

use idevice::provider::{IdeviceProvider, TcpProvider, UsbmuxdProvider};
use std::net::IpAddr;
use std::os::raw::c_char;
use std::{ffi::CStr, ptr::null_mut};

Expand Down Expand Up @@ -35,7 +34,7 @@ pub unsafe extern "C" fn idevice_tcp_provider_new(
provider: *mut *mut IdeviceProviderHandle,
) -> *mut IdeviceFfiError {
let ip = ip as *const SockAddr;
let addr: IpAddr = match util::c_addr_to_rust(ip) {
let (addr, scope_id) = match util::c_addr_to_rust(ip) {
Ok(i) => i,
Err(e) => return ffi_err!(e),
};
Expand All @@ -50,6 +49,7 @@ pub unsafe extern "C" fn idevice_tcp_provider_new(

let t = TcpProvider {
addr,
scope_id,
pairing_file: pairing_file.0,
label,
};
Expand Down
19 changes: 12 additions & 7 deletions ffi/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ pub(crate) fn c_socket_to_rust(
}
}

pub(crate) fn c_addr_to_rust(addr: *const SockAddr) -> Result<IpAddr, IdeviceError> {
pub(crate) fn c_addr_to_rust(addr: *const SockAddr) -> Result<(IpAddr, Option<u32>), IdeviceError> {
if addr.is_null() {
tracing::error!("null sockaddr");
return invalid_arg();
Expand All @@ -148,13 +148,17 @@ pub(crate) fn c_addr_to_rust(addr: *const SockAddr) -> Result<IpAddr, IdeviceErr
libc::AF_INET => {
let a = &*(addr as *const sockaddr_in);
let octets = u32::from_be(a.sin_addr.s_addr).to_be_bytes();
Ok(IpAddr::V4(Ipv4Addr::new(
octets[0], octets[1], octets[2], octets[3],
)))
Ok((
IpAddr::V4(Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])),
None,
))
}
libc::AF_INET6 => {
let a = &*(addr as *const sockaddr_in6);
Ok(IpAddr::V6(Ipv6Addr::from(a.sin6_addr.s6_addr)))
Ok((
IpAddr::V6(Ipv6Addr::from(a.sin6_addr.s6_addr)),
Some(a.sin6_scope_id),
))
}
_ => {
tracing::error!(
Expand All @@ -170,12 +174,13 @@ pub(crate) fn c_addr_to_rust(addr: *const SockAddr) -> Result<IpAddr, IdeviceErr
AF_INET => {
let a = &*(addr as *const sockaddr_in);
let ip_be = a.sin_addr.S_un.S_addr;
Ok(IpAddr::V4(Ipv4Addr::from(u32::from_be(ip_be))))
Ok((IpAddr::V4(Ipv4Addr::from(u32::from_be(ip_be))), None))
}
AF_INET6 => {
let a = &*(addr as *const sockaddr_in6);
let bytes: [u8; 16] = a.sin6_addr.u.Byte;
Ok(IpAddr::V6(Ipv6Addr::from(bytes)))
let scope_id: u32 = a.Anonymous.sin6_scope_id;
Ok((IpAddr::V6(Ipv6Addr::from(bytes)), Some(scope_id)))
}
_ => {
tracing::error!("Unsupported socket address family: {}", (*addr).sa_family);
Expand Down
14 changes: 13 additions & 1 deletion idevice/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ obfstr = { version = "0.4", optional = true }

async_zip = { version = "0.0.18", optional = true }

[target.'cfg(not(windows))'.dependencies]
libc = "0.2"

[dev-dependencies]
tokio = { version = "1.43", features = ["full"] }
tun-rs = { version = "2.0.8", features = ["async_tokio"] }
Expand Down Expand Up @@ -108,7 +111,16 @@ installation_proxy = [
"tokio/fs",
]
installcoordination_proxy = []
xctest = ["dvt", "installation_proxy", "afc", "dep:uuid", "dep:ns-keyed-archive", "tunnel_tcp_stack", "rsd", "core_device_proxy"]
xctest = [
"dvt",
"installation_proxy",
"afc",
"dep:uuid",
"dep:ns-keyed-archive",
"tunnel_tcp_stack",
"rsd",
"core_device_proxy",
]
springboardservices = []
misagent = []
mobile_image_mounter = ["dep:sha2"]
Expand Down
11 changes: 10 additions & 1 deletion idevice/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

use std::{future::Future, pin::Pin};

use std::net::IpAddr;
use std::net::{SocketAddr, SocketAddrV6};

#[cfg(feature = "tcp")]
use tokio::net::TcpStream;

Expand Down Expand Up @@ -55,6 +58,8 @@ pub trait RsdProvider: Unpin + Send + Sync + std::fmt::Debug {
pub struct TcpProvider {
/// IP address of the device
pub addr: std::net::IpAddr,
/// An optional scope ID may be provided for IPv6 addresses.
pub scope_id: Option<u32>,
/// Pairing file for secure communication
pub pairing_file: PairingFile,
/// Label identifying this connection
Expand All @@ -76,8 +81,12 @@ impl IdeviceProvider for TcpProvider {
) -> Pin<Box<dyn Future<Output = Result<Idevice, IdeviceError>> + Send>> {
let addr = self.addr;
let label = self.label.clone();
let scope_id = self.scope_id.unwrap_or(0);
Box::pin(async move {
let socket_addr = std::net::SocketAddr::new(addr, port);
let socket_addr = match addr {
IpAddr::V4(_) => SocketAddr::new(addr, port),
IpAddr::V6(ipv6) => SocketAddr::V6(SocketAddrV6::new(ipv6, port, 0, scope_id)),
};
let stream = TcpStream::connect(socket_addr).await?;
Ok(Idevice::new(Box::new(stream), label))
})
Expand Down
16 changes: 12 additions & 4 deletions idevice/src/usbmuxd/des.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use serde::Deserialize;
use tracing::{debug, warn};

#[cfg(not(windows))]
use libc::{AF_INET, AF_INET6};

#[cfg(windows)]
const AF_INET: i32 = 2;
#[cfg(windows)]
const AF_INET6: i32 = 23;

use crate::{
IdeviceError,
usbmuxd::{Connection, UsbmuxdDevice},
Expand Down Expand Up @@ -55,14 +63,14 @@ impl TryFrom<DeviceListResponse> for UsbmuxdDevice {
));
}

match addr[0] {
0x02 => {
match addr[0] as _ {
AF_INET => {
// IPv4
Connection::Network(IpAddr::V4(Ipv4Addr::new(
addr[4], addr[5], addr[6], addr[7],
)))
}
0x1E => {
AF_INET6 => {
// IPv6
if addr.len() < 24 {
warn!("IPv6 address is less than 24 bytes");
Expand Down Expand Up @@ -91,7 +99,7 @@ impl TryFrom<DeviceListResponse> for UsbmuxdDevice {
.into(),
));
}
if addr[1] == 0x1E {
if addr[1] == AF_INET6 as u8 {
// IPv6 address starts at offset 8 in sockaddr_in6
Connection::Network(IpAddr::V6(Ipv6Addr::new(
u16::from_be_bytes([addr[8], addr[9]]),
Expand Down
12 changes: 11 additions & 1 deletion tools/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,16 @@ async fn get_provider(
} else if let Some(host) = host
&& let Some(pairing_file) = pairing_file
{
let host = match IpAddr::from_str(host.as_str()) {
// split host and the optional scope_id (e.g., "fe80::1%3") if IPv6
let (host_str, scope_id) = match host.rsplit_once('%') {
Some((h, scope_id)) => {
let scope_id = scope_id.parse::<u32>().ok();
(h, scope_id)
}
None => (host.as_str(), None),
};

let host = match IpAddr::from_str(host_str) {
Ok(h) => h,
Err(e) => {
return Err(format!("Invalid host: {e:?}"));
Expand All @@ -345,6 +354,7 @@ async fn get_provider(

Box::new(TcpProvider {
addr: host,
scope_id,
pairing_file,
label: label.to_string(),
})
Expand Down
Loading