Skip to content

Commit 426c292

Browse files
bors[bot]Gleb Pomykalov
and
Gleb Pomykalov
committed
Merge #1031
1031: Add AF_ALG socket types and related control mesages and sockopts on Linux and Andorid r=asomers a=glebpom Co-authored-by: Gleb Pomykalov <[email protected]>
2 parents 2d0d360 + 6968cb4 commit 426c292

File tree

5 files changed

+381
-11
lines changed

5 files changed

+381
-11
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
77
### Added
88
- Add IP_RECVIF & IP_RECVDSTADDR. Enable IP_PKTINFO and IP6_PKTINFO on netbsd/openbsd.
99
([#1002](https://github.com/nix-rust/nix/pull/1002))
10-
1110
- Added `inotify_init1`, `inotify_add_watch` and `inotify_rm_watch` wrappers for
1211
Android and Linux. ([#1016](https://github.com/nix-rust/nix/pull/1016))
12+
- Add `ALG_SET_IV`, `ALG_SET_OP` and `ALG_SET_AEAD_ASSOCLEN` control messages and `AF_ALG`
13+
socket types on Linux and Android ([#1031](https://github.com/nix-rust/nix/pull/1031))
1314

1415
### Changed
1516
- `PollFd` event flags renamed to `PollFlags` ([#1024](https://github.com/nix-rust/nix/pull/1024/))

src/sys/socket/addr.rs

+80
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use std::path::Path;
88
use std::os::unix::ffi::OsStrExt;
99
#[cfg(any(target_os = "android", target_os = "linux"))]
1010
use ::sys::socket::addr::netlink::NetlinkAddr;
11+
#[cfg(any(target_os = "android", target_os = "linux"))]
12+
use ::sys::socket::addr::alg::AlgAddr;
1113
#[cfg(any(target_os = "ios", target_os = "macos"))]
1214
use std::os::unix::io::RawFd;
1315
#[cfg(any(target_os = "ios", target_os = "macos"))]
@@ -740,6 +742,8 @@ pub enum SockAddr {
740742
Unix(UnixAddr),
741743
#[cfg(any(target_os = "android", target_os = "linux"))]
742744
Netlink(NetlinkAddr),
745+
#[cfg(any(target_os = "android", target_os = "linux"))]
746+
Alg(AlgAddr),
743747
#[cfg(any(target_os = "ios", target_os = "macos"))]
744748
SysControl(SysControlAddr),
745749
/// Datalink address (MAC)
@@ -768,6 +772,11 @@ impl SockAddr {
768772
SockAddr::Netlink(NetlinkAddr::new(pid, groups))
769773
}
770774

775+
#[cfg(any(target_os = "android", target_os = "linux"))]
776+
pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr {
777+
SockAddr::Alg(AlgAddr::new(alg_type, alg_name))
778+
}
779+
771780
#[cfg(any(target_os = "ios", target_os = "macos"))]
772781
pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
773782
SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a))
@@ -780,6 +789,8 @@ impl SockAddr {
780789
SockAddr::Unix(..) => AddressFamily::Unix,
781790
#[cfg(any(target_os = "android", target_os = "linux"))]
782791
SockAddr::Netlink(..) => AddressFamily::Netlink,
792+
#[cfg(any(target_os = "android", target_os = "linux"))]
793+
SockAddr::Alg(..) => AddressFamily::Alg,
783794
#[cfg(any(target_os = "ios", target_os = "macos"))]
784795
SockAddr::SysControl(..) => AddressFamily::System,
785796
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -856,6 +867,8 @@ impl SockAddr {
856867
SockAddr::Unix(UnixAddr(ref addr, len)) => (mem::transmute(addr), (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t),
857868
#[cfg(any(target_os = "android", target_os = "linux"))]
858869
SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t),
870+
#[cfg(any(target_os = "android", target_os = "linux"))]
871+
SockAddr::Alg(AlgAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t),
859872
#[cfg(any(target_os = "ios", target_os = "macos"))]
860873
SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t),
861874
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -910,6 +923,8 @@ impl hash::Hash for SockAddr {
910923
SockAddr::Unix(ref a) => a.hash(s),
911924
#[cfg(any(target_os = "android", target_os = "linux"))]
912925
SockAddr::Netlink(ref a) => a.hash(s),
926+
#[cfg(any(target_os = "android", target_os = "linux"))]
927+
SockAddr::Alg(ref a) => a.hash(s),
913928
#[cfg(any(target_os = "ios", target_os = "macos"))]
914929
SockAddr::SysControl(ref a) => a.hash(s),
915930
#[cfg(any(target_os = "android",
@@ -938,6 +953,8 @@ impl fmt::Display for SockAddr {
938953
SockAddr::Unix(ref unix) => unix.fmt(f),
939954
#[cfg(any(target_os = "android", target_os = "linux"))]
940955
SockAddr::Netlink(ref nl) => nl.fmt(f),
956+
#[cfg(any(target_os = "android", target_os = "linux"))]
957+
SockAddr::Alg(ref nl) => nl.fmt(f),
941958
#[cfg(any(target_os = "ios", target_os = "macos"))]
942959
SockAddr::SysControl(ref sc) => sc.fmt(f),
943960
#[cfg(any(target_os = "android",
@@ -1014,6 +1031,69 @@ pub mod netlink {
10141031
}
10151032
}
10161033

1034+
#[cfg(any(target_os = "android", target_os = "linux"))]
1035+
pub mod alg {
1036+
use libc::{AF_ALG, sockaddr_alg, c_char};
1037+
use std::{fmt, mem, str};
1038+
use std::hash::{Hash, Hasher};
1039+
use std::ffi::CStr;
1040+
1041+
#[derive(Copy, Clone)]
1042+
pub struct AlgAddr(pub sockaddr_alg);
1043+
1044+
// , PartialEq, Eq, Debug, Hash
1045+
impl PartialEq for AlgAddr {
1046+
fn eq(&self, other: &Self) -> bool {
1047+
let (inner, other) = (self.0, other.0);
1048+
(inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) ==
1049+
(other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..])
1050+
}
1051+
}
1052+
1053+
impl Eq for AlgAddr {}
1054+
1055+
impl Hash for AlgAddr {
1056+
fn hash<H: Hasher>(&self, s: &mut H) {
1057+
let inner = self.0;
1058+
(inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s);
1059+
}
1060+
}
1061+
1062+
impl AlgAddr {
1063+
pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
1064+
let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
1065+
addr.salg_family = AF_ALG as u16;
1066+
addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes());
1067+
addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes());
1068+
1069+
AlgAddr(addr)
1070+
}
1071+
1072+
1073+
pub fn alg_type(&self) -> &CStr {
1074+
unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) }
1075+
}
1076+
1077+
pub fn alg_name(&self) -> &CStr {
1078+
unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) }
1079+
}
1080+
}
1081+
1082+
impl fmt::Display for AlgAddr {
1083+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1084+
write!(f, "type: {} alg: {}",
1085+
self.alg_name().to_string_lossy(),
1086+
self.alg_type().to_string_lossy())
1087+
}
1088+
}
1089+
1090+
impl fmt::Debug for AlgAddr {
1091+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1092+
fmt::Display::fmt(self, f)
1093+
}
1094+
}
1095+
}
1096+
10171097
#[cfg(any(target_os = "ios", target_os = "macos"))]
10181098
pub mod sys_control {
10191099
use ::sys::socket::addr::AddressFamily;

src/sys/socket/mod.rs

+101-10
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ pub use self::addr::{
3131
};
3232
#[cfg(any(target_os = "android", target_os = "linux"))]
3333
pub use ::sys::socket::addr::netlink::NetlinkAddr;
34+
#[cfg(any(target_os = "android", target_os = "linux"))]
35+
pub use sys::socket::addr::alg::AlgAddr;
3436

3537
pub use libc::{
3638
cmsghdr,
@@ -700,6 +702,37 @@ pub enum ControlMessage<'a> {
700702
// and put that in here instead of a raw ucred.
701703
#[cfg(any(target_os = "android", target_os = "linux"))]
702704
ScmCredentials(&'a libc::ucred),
705+
706+
/// Set IV for `AF_ALG` crypto API.
707+
///
708+
/// For further information, please refer to the
709+
/// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
710+
#[cfg(any(
711+
target_os = "android",
712+
target_os = "linux",
713+
))]
714+
AlgSetIv(&'a [u8]),
715+
/// Set crypto operation for `AF_ALG` crypto API. It may be one of
716+
/// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT`
717+
///
718+
/// For further information, please refer to the
719+
/// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
720+
#[cfg(any(
721+
target_os = "android",
722+
target_os = "linux",
723+
))]
724+
AlgSetOp(&'a libc::c_int),
725+
/// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms)
726+
/// for `AF_ALG` crypto API.
727+
///
728+
/// For further information, please refer to the
729+
/// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
730+
#[cfg(any(
731+
target_os = "android",
732+
target_os = "linux",
733+
))]
734+
AlgSetAeadAssoclen(&'a u32),
735+
703736
}
704737

705738
// An opaque structure used to prevent cmsghdr from being a public type
@@ -729,16 +762,44 @@ impl<'a> ControlMessage<'a> {
729762
}
730763

731764
/// Return a reference to the payload data as a byte pointer
732-
fn data(&self) -> *const u8 {
733-
match self {
765+
fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) {
766+
let data_ptr = match self {
734767
&ControlMessage::ScmRights(fds) => {
735768
fds as *const _ as *const u8
736769
},
737770
#[cfg(any(target_os = "android", target_os = "linux"))]
738771
&ControlMessage::ScmCredentials(creds) => {
739772
creds as *const libc::ucred as *const u8
740773
}
741-
}
774+
#[cfg(any(target_os = "android", target_os = "linux"))]
775+
&ControlMessage::AlgSetIv(iv) => {
776+
unsafe {
777+
let alg_iv = cmsg_data as *mut libc::af_alg_iv;
778+
(*alg_iv).ivlen = iv.len() as u32;
779+
ptr::copy_nonoverlapping(
780+
iv.as_ptr(),
781+
(*alg_iv).iv.as_mut_ptr(),
782+
iv.len()
783+
);
784+
};
785+
return
786+
},
787+
#[cfg(any(target_os = "android", target_os = "linux"))]
788+
&ControlMessage::AlgSetOp(op) => {
789+
op as *const _ as *const u8
790+
},
791+
#[cfg(any(target_os = "android", target_os = "linux"))]
792+
&ControlMessage::AlgSetAeadAssoclen(len) => {
793+
len as *const _ as *const u8
794+
},
795+
};
796+
unsafe {
797+
ptr::copy_nonoverlapping(
798+
data_ptr,
799+
cmsg_data,
800+
self.len()
801+
)
802+
};
742803
}
743804

744805
/// The size of the payload, excluding its cmsghdr
@@ -751,6 +812,18 @@ impl<'a> ControlMessage<'a> {
751812
&ControlMessage::ScmCredentials(creds) => {
752813
mem::size_of_val(creds)
753814
}
815+
#[cfg(any(target_os = "android", target_os = "linux"))]
816+
&ControlMessage::AlgSetIv(iv) => {
817+
mem::size_of::<libc::af_alg_iv>() + iv.len()
818+
},
819+
#[cfg(any(target_os = "android", target_os = "linux"))]
820+
&ControlMessage::AlgSetOp(op) => {
821+
mem::size_of_val(op)
822+
},
823+
#[cfg(any(target_os = "android", target_os = "linux"))]
824+
&ControlMessage::AlgSetAeadAssoclen(len) => {
825+
mem::size_of_val(len)
826+
},
754827
}
755828
}
756829

@@ -760,6 +833,10 @@ impl<'a> ControlMessage<'a> {
760833
&ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
761834
#[cfg(any(target_os = "android", target_os = "linux"))]
762835
&ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
836+
#[cfg(any(target_os = "android", target_os = "linux"))]
837+
&ControlMessage::AlgSetIv(_) | &ControlMessage::AlgSetOp(_) | &ControlMessage::AlgSetAeadAssoclen(_) => {
838+
libc::SOL_ALG
839+
},
763840
}
764841
}
765842

@@ -769,6 +846,18 @@ impl<'a> ControlMessage<'a> {
769846
&ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
770847
#[cfg(any(target_os = "android", target_os = "linux"))]
771848
&ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
849+
#[cfg(any(target_os = "android", target_os = "linux"))]
850+
&ControlMessage::AlgSetIv(_) => {
851+
libc::ALG_SET_IV
852+
},
853+
#[cfg(any(target_os = "android", target_os = "linux"))]
854+
&ControlMessage::AlgSetOp(_) => {
855+
libc::ALG_SET_OP
856+
},
857+
#[cfg(any(target_os = "android", target_os = "linux"))]
858+
&ControlMessage::AlgSetAeadAssoclen(_) => {
859+
libc::ALG_SET_AEAD_ASSOCLEN
860+
},
772861
}
773862
}
774863

@@ -778,12 +867,7 @@ impl<'a> ControlMessage<'a> {
778867
(*cmsg).cmsg_level = self.cmsg_level();
779868
(*cmsg).cmsg_type = self.cmsg_type();
780869
(*cmsg).cmsg_len = self.cmsg_len();
781-
let data = self.data();
782-
ptr::copy_nonoverlapping(
783-
data,
784-
CMSG_DATA(cmsg),
785-
self.len()
786-
);
870+
self.copy_to_cmsg_data(CMSG_DATA(cmsg));
787871
}
788872
}
789873

@@ -1098,6 +1182,8 @@ pub enum SockLevel {
10981182
Udp = libc::IPPROTO_UDP,
10991183
#[cfg(any(target_os = "android", target_os = "linux"))]
11001184
Netlink = libc::SOL_NETLINK,
1185+
#[cfg(any(target_os = "android", target_os = "linux"))]
1186+
Alg = libc::SOL_ALG,
11011187
}
11021188

11031189
/// Represents a socket option that can be accessed or set. Used as an argument
@@ -1111,7 +1197,7 @@ pub trait GetSockOpt : Copy {
11111197

11121198
/// Represents a socket option that can be accessed or set. Used as an argument
11131199
/// to `setsockopt`
1114-
pub trait SetSockOpt : Copy {
1200+
pub trait SetSockOpt : Clone {
11151201
type Val;
11161202

11171203
#[doc(hidden)]
@@ -1212,6 +1298,11 @@ pub unsafe fn sockaddr_storage_to_addr(
12121298
use libc::sockaddr_nl;
12131299
Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl))))
12141300
}
1301+
#[cfg(any(target_os = "android", target_os = "linux"))]
1302+
libc::AF_ALG => {
1303+
use libc::sockaddr_alg;
1304+
Ok(SockAddr::Alg(AlgAddr(*(addr as *const _ as *const sockaddr_alg))))
1305+
}
12151306
af => panic!("unexpected address family {}", af),
12161307
}
12171308
}

src/sys/socket/sockopt.rs

+49
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,55 @@ sockopt_impl!(Both, Ipv4RecvIf, libc::IPPROTO_IP, libc::IP_RECVIF, bool);
307307
sockopt_impl!(Both, Ipv4RecvDstAddr, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, bool);
308308

309309

310+
#[cfg(any(target_os = "android", target_os = "linux"))]
311+
#[derive(Copy, Clone, Debug)]
312+
pub struct AlgSetAeadAuthSize;
313+
314+
// ALG_SET_AEAD_AUTH_SIZE read the length from passed `option_len`
315+
// See https://elixir.bootlin.com/linux/v4.4/source/crypto/af_alg.c#L222
316+
#[cfg(any(target_os = "android", target_os = "linux"))]
317+
impl SetSockOpt for AlgSetAeadAuthSize {
318+
type Val = usize;
319+
320+
fn set(&self, fd: RawFd, val: &usize) -> Result<()> {
321+
unsafe {
322+
let res = libc::setsockopt(fd,
323+
libc::SOL_ALG,
324+
libc::ALG_SET_AEAD_AUTHSIZE,
325+
::std::ptr::null(),
326+
*val as libc::socklen_t);
327+
Errno::result(res).map(drop)
328+
}
329+
}
330+
}
331+
332+
#[cfg(any(target_os = "android", target_os = "linux"))]
333+
#[derive(Clone, Debug)]
334+
pub struct AlgSetKey<T>(::std::marker::PhantomData<T>);
335+
336+
#[cfg(any(target_os = "android", target_os = "linux"))]
337+
impl<T> Default for AlgSetKey<T> {
338+
fn default() -> Self {
339+
AlgSetKey(Default::default())
340+
}
341+
}
342+
343+
#[cfg(any(target_os = "android", target_os = "linux"))]
344+
impl<T> SetSockOpt for AlgSetKey<T> where T: AsRef<[u8]> + Clone {
345+
type Val = T;
346+
347+
fn set(&self, fd: RawFd, val: &T) -> Result<()> {
348+
unsafe {
349+
let res = libc::setsockopt(fd,
350+
libc::SOL_ALG,
351+
libc::ALG_SET_KEY,
352+
val.as_ref().as_ptr() as *const _,
353+
val.as_ref().len() as libc::socklen_t);
354+
Errno::result(res).map(drop)
355+
}
356+
}
357+
}
358+
310359
/*
311360
*
312361
* ===== Accessor helpers =====

0 commit comments

Comments
 (0)