diff --git a/src/unix/bsd/mod.rs b/src/unix/bsd/mod.rs
index 98d91d046c08a43b82a033fbcbdab5424a9b6c7f..05cf8fee4de175f2ec3ce38aa916cd779bb7fc59 100644
--- a/src/unix/bsd/mod.rs
+++ b/src/unix/bsd/mod.rs
@@ -332,6 +332,43 @@ pub const POLLRDBAND: ::c_short = 0x080;
 pub const POLLWRBAND: ::c_short = 0x100;
 
 f! {
+    pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr {
+        if (*mhdr).msg_controllen as usize >= mem::size_of::<cmsghdr>() {
+            (*mhdr).msg_control as *mut cmsghdr
+        } else {
+            0 as *mut cmsghdr
+        }
+    }
+
+    pub fn CMSG_NXTHDR(mhdr: *const msghdr,
+                       cmsg: *const cmsghdr) -> *mut cmsghdr {
+        if cmsg.is_null() {
+            return CMSG_FIRSTHDR(mhdr);
+        };
+        let pad = mem::align_of::<cmsghdr>() - 1;
+        let next = cmsg as usize + (*cmsg).cmsg_len as usize + pad & !pad;
+        let max = (*mhdr).msg_control as usize
+            + (*mhdr).msg_controllen as usize;
+        if next < max {
+            next as *mut cmsghdr
+        } else {
+            0 as *mut cmsghdr
+        }
+    }
+
+    pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut ::c_uchar {
+        cmsg.offset(1) as *mut ::c_uchar
+    }
+
+    pub fn CMSG_SPACE(length: ::c_uint) -> ::c_uint {
+        let pad = mem::align_of::<cmsghdr>() as ::c_uint - 1;
+        mem::size_of::<cmsghdr>() as ::c_uint + ((length + pad) & !pad)
+    }
+
+    pub fn CMSG_LEN(length: ::c_uint) -> ::c_uint {
+        mem::size_of::<cmsghdr>() as ::c_uint + length
+    }
+
     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;
diff --git a/src/unix/notbsd/mod.rs b/src/unix/notbsd/mod.rs
index eead3fd84724f9b7057650065014e8e21aa3f971..6e4500684e136b06c7ccd6ce634e7894f3354e77 100644
--- a/src/unix/notbsd/mod.rs
+++ b/src/unix/notbsd/mod.rs
@@ -977,6 +977,43 @@ pub const ARPHRD_VOID: u16 = 0xFFFF;
 pub const ARPHRD_NONE: u16 = 0xFFFE;
 
 f! {
+    pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr {
+        if (*mhdr).msg_controllen as usize >= mem::size_of::<cmsghdr>() {
+            (*mhdr).msg_control as *mut cmsghdr
+        } else {
+            0 as *mut cmsghdr
+        }
+    }
+
+    pub fn CMSG_NXTHDR(mhdr: *const msghdr,
+                       cmsg: *const cmsghdr) -> *mut cmsghdr {
+        if cmsg.is_null() {
+            return CMSG_FIRSTHDR(mhdr);
+        };
+        let pad = mem::align_of::<cmsghdr>() - 1;
+        let next = cmsg as usize + (*cmsg).cmsg_len as usize + pad & !pad;
+        let max = (*mhdr).msg_control as usize
+            + (*mhdr).msg_controllen as usize;
+        if next < max {
+            next as *mut cmsghdr
+        } else {
+            0 as *mut cmsghdr
+        }
+    }
+
+    pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut ::c_uchar {
+        cmsg.offset(1) as *mut ::c_uchar
+    }
+
+    pub fn CMSG_SPACE(length: ::c_uint) -> ::c_uint {
+        let pad = mem::align_of::<cmsghdr>() as ::c_uint - 1;
+        mem::size_of::<cmsghdr>() as ::c_uint + ((length + pad) & !pad)
+    }
+
+    pub fn CMSG_LEN(length: ::c_uint) -> ::c_uint {
+        mem::size_of::<cmsghdr>() as ::c_uint + length
+    }
+
     pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () {
         let fd = fd as usize;
         let size = mem::size_of_val(&(*set).fds_bits[0]) * 8;