diff --git a/libc-test/build.rs b/libc-test/build.rs
index 1d1f953080bb1c1a595d1bd129ef6d813c034d88..1e602618ae7204e434abf30a02ef078e90786e5f 100644
--- a/libc-test/build.rs
+++ b/libc-test/build.rs
@@ -8,9 +8,16 @@ use std::env;
 fn do_cc() {
     let target = env::var("TARGET").unwrap();
     if cfg!(unix) {
-        let exclude = ["wasi", "solaris", "illumos"];
+        let exclude = ["wasi"];
         if !exclude.iter().any(|x| target.contains(x)) {
-            cc::Build::new().file("src/cmsg.c").compile("cmsg");
+            let mut cmsg = cc::Build::new();
+
+            cmsg.file("src/cmsg.c");
+
+            if target.contains("solaris") || target.contains("illumos") {
+                cmsg.define("_XOPEN_SOURCE", "700");
+            }
+            cmsg.compile("cmsg");
         }
     }
     if target.contains("android") || target.contains("linux") {
diff --git a/libc-test/test/cmsg.rs b/libc-test/test/cmsg.rs
index c95899cef516c48e73fa88f57f39cc15b1a3ab35..38a8ce15089011dd7748af93dc9bc56f64632f43 100644
--- a/libc-test/test/cmsg.rs
+++ b/libc-test/test/cmsg.rs
@@ -4,7 +4,6 @@
 extern crate libc;
 
 #[cfg(unix)]
-#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
 mod t {
 
     use libc::{self, c_uchar, c_uint, c_void, cmsghdr, msghdr};
diff --git a/src/unix/solarish/mod.rs b/src/unix/solarish/mod.rs
index c30e11593d69498ac9d0ea02f1b688f80de7247f..c60e678040037e3981a8788b815b6bbbd7a60273 100644
--- a/src/unix/solarish/mod.rs
+++ b/src/unix/solarish/mod.rs
@@ -1998,7 +1998,63 @@ pub const PRIO_PROCESS: ::c_int = 0;
 pub const PRIO_PGRP: ::c_int = 1;
 pub const PRIO_USER: ::c_int = 2;
 
+// As per sys/socket.h, header alignment must be 8 bytes on SPARC
+// and 4 bytes everywhere else:
+#[cfg(target_arch = "sparc64")]
+const _CMSG_HDR_ALIGNMENT: usize = 8;
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+const _CMSG_HDR_ALIGNMENT: usize = 4;
+
+const _CMSG_DATA_ALIGNMENT: usize = ::mem::size_of::<::c_int>();
+
+fn _CMSG_HDR_ALIGN(p: usize) -> usize {
+    (p + _CMSG_HDR_ALIGNMENT - 1) & !(_CMSG_HDR_ALIGNMENT - 1)
+}
+
+fn _CMSG_DATA_ALIGN(p: usize) -> usize {
+    (p + _CMSG_DATA_ALIGNMENT - 1) & !(_CMSG_DATA_ALIGNMENT - 1)
+}
+
 f! {
+    pub fn CMSG_DATA(cmsg: *const ::cmsghdr) -> *mut ::c_uchar {
+        _CMSG_DATA_ALIGN(cmsg.offset(1) as usize) as *mut ::c_uchar
+    }
+
+    pub fn CMSG_LEN(length: ::c_uint) -> ::c_uint {
+        _CMSG_DATA_ALIGN(::mem::size_of::<::cmsghdr>()) as ::c_uint + length
+    }
+
+    pub fn CMSG_FIRSTHDR(mhdr: *const ::msghdr) -> *mut ::cmsghdr {
+        if ((*mhdr).msg_controllen as usize) < ::mem::size_of::<::cmsghdr>() {
+            0 as *mut ::cmsghdr
+        } else {
+            (*mhdr).msg_control as *mut ::cmsghdr
+        }
+    }
+
+    pub fn CMSG_NXTHDR(mhdr: *const ::msghdr, cmsg: *const ::cmsghdr)
+        -> *mut ::cmsghdr
+    {
+        if cmsg.is_null() {
+            return ::CMSG_FIRSTHDR(mhdr);
+        };
+        let next = _CMSG_HDR_ALIGN(cmsg as usize + (*cmsg).cmsg_len as usize
+            + ::mem::size_of::<::cmsghdr>());
+        let max = (*mhdr).msg_control as usize
+            + (*mhdr).msg_controllen as usize;
+        if next > max {
+            0 as *mut ::cmsghdr
+        } else {
+            _CMSG_HDR_ALIGN(cmsg as usize + (*cmsg).cmsg_len as usize)
+                as *mut ::cmsghdr
+        }
+    }
+
+    pub fn CMSG_SPACE(length: ::c_uint) -> ::c_uint {
+        _CMSG_HDR_ALIGN(::mem::size_of::<::cmsghdr>() as usize
+            + length as usize) as ::c_uint
+    }
+
     pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () {
         let bits = ::mem::size_of_val(&(*set).fds_bits[0]) * 8;
         let fd = fd as usize;