diff --git a/src/header/sys_un/mod.rs b/src/header/sys_un/mod.rs
index 69f0e6f662f273b4955c86af099cd5e2ac889882..6399f74bd239f2245013a928525611bf943f30aa 100644
--- a/src/header/sys_un/mod.rs
+++ b/src/header/sys_un/mod.rs
@@ -2,6 +2,6 @@ use crate::{header::sys_socket::sa_family_t, platform::types::*};
 
 #[repr(C)]
 pub struct sockaddr_un {
-    sun_family: sa_family_t,
-    sun_path: [c_char; 108],
+    pub sun_family: sa_family_t,
+    pub sun_path: [c_char; 108],
 }
diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs
index 56aa5532cbdb8b3aa79528ddf480a117fe2a511d..80eb515e8ba837b8404747d7d424c22220afac24 100644
--- a/src/platform/redox/socket.rs
+++ b/src/platform/redox/socket.rs
@@ -1,4 +1,4 @@
-use core::{mem, ptr, slice};
+use core::{mem, ptr, slice, str};
 use syscall::{self, flag::*, Result};
 
 use super::{
@@ -9,6 +9,7 @@ use crate::header::{
     netinet_in::{in_port_t, sockaddr_in},
     sys_socket::{constants::*, sockaddr, socklen_t},
     sys_time::timeval,
+    sys_un::sockaddr_un,
 };
 
 macro_rules! bind_or_connect {
@@ -29,28 +30,48 @@ macro_rules! bind_or_connect {
         0
     }};
     ($mode:ident copy, $socket:expr, $address:expr, $address_len:expr) => {{
-        if (*$address).sa_family as c_int != AF_INET {
-            errno = syscall::EAFNOSUPPORT;
-            return -1;
-        }
         if ($address_len as usize) < mem::size_of::<sockaddr>() {
             errno = syscall::EINVAL;
             return -1;
         }
-        let data = &*($address as *const sockaddr_in);
-        let addr = slice::from_raw_parts(
-            &data.sin_addr.s_addr as *const _ as *const u8,
-            mem::size_of_val(&data.sin_addr.s_addr),
-        );
-        let port = in_port_t::from_be(data.sin_port);
-        let path = format!(
-            bind_or_connect!($mode "{}.{}.{}.{}:{}"),
-            addr[0],
-            addr[1],
-            addr[2],
-            addr[3],
-            port
-        );
+
+        let path = match (*$address).sa_family as c_int {
+            AF_INET => {
+                let data = &*($address as *const sockaddr_in);
+                let addr = slice::from_raw_parts(
+                    &data.sin_addr.s_addr as *const _ as *const u8,
+                    mem::size_of_val(&data.sin_addr.s_addr),
+                );
+                let port = in_port_t::from_be(data.sin_port);
+                let path = format!(
+                    bind_or_connect!($mode "{}.{}.{}.{}:{}"),
+                    addr[0],
+                    addr[1],
+                    addr[2],
+                    addr[3],
+                    port
+                );
+
+                path
+            },
+            AF_UNIX => {
+                let data = &*($address as *const sockaddr_un);
+                let addr = slice::from_raw_parts(
+                    &data.sun_path as *const _ as *const u8,
+                    mem::size_of_val(&data.sun_path),
+                );
+                let path = format!(
+                    "{}",
+                    str::from_utf8(addr).unwrap()
+                );
+
+                path
+            },
+            _ => {
+                errno = syscall::EAFNOSUPPORT;
+                return -1;
+            },
+        };
 
         // Duplicate the socket, and then duplicate the copy back to the original fd
         let fd = e(syscall::dup($socket as usize, path.as_bytes()));
@@ -61,21 +82,28 @@ macro_rules! bind_or_connect {
     }};
 }
 
-unsafe fn inner_get_name(
+unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut socklen_t) {
+    let data = &mut *(address as *mut sockaddr_un);
+
+    data.sun_family = AF_UNIX as c_ushort;
+
+    let path = slice::from_raw_parts_mut(
+        &mut data.sun_path as *mut _ as *mut u8,
+        mem::size_of_val(&data.sun_path),
+    );
+
+    let len = path.len().min(buf.len());
+    path[..len].copy_from_slice(&buf[..len]);
+
+    *address_len = len as socklen_t;
+}
+
+unsafe fn inner_af_inet(
     local: bool,
-    socket: c_int,
+    buf: &[u8],
     address: *mut sockaddr,
     address_len: *mut socklen_t,
-) -> Result<usize> {
-    // 32 should probably be large enough.
-    // Format: tcp:remote/local
-    // and since we only yet support IPv4 (I think)...
-    let mut buf = [0; 32];
-    let len = syscall::fpath(socket as usize, &mut buf)?;
-    let buf = &buf[..len];
-    assert!(&buf[..4] == b"tcp:" || &buf[..4] == b"udp:");
-    let buf = &buf[4..];
-
+) {
     let mut parts = buf.split(|c| *c == b'/');
     if local {
         // Skip the remote part
@@ -96,6 +124,32 @@ unsafe fn inner_get_name(
     data[..len].copy_from_slice(&part[..len]);
 
     *address_len = len as socklen_t;
+}
+
+unsafe fn inner_get_name(
+    local: bool,
+    socket: c_int,
+    address: *mut sockaddr,
+    address_len: *mut socklen_t,
+) -> Result<usize> {
+    // 32 should probably be large enough.
+    // Format: [udp|tcp:]remote/local, chan:path
+    let mut buf = [0; 32];
+    let len = syscall::fpath(socket as usize, &mut buf)?;
+    let buf = &buf[..len];
+    assert!(&buf[..4] == b"tcp:" || &buf[..4] == b"udp:" || &buf[..5] == b"chan:");
+
+    match &buf[..5] {
+        b"tcp:" | b"udp:" => {
+            inner_af_inet(local, &buf[4..], address, address_len);
+        }
+        b"chan:" => {
+            inner_af_unix(&buf[5..], address, address_len);
+        }
+        // Socket doesn't belong to any scheme
+        _ => panic!("socket doesn't match either tcp, udp or chan schemes"),
+    };
+
     Ok(0)
 }
 
@@ -292,7 +346,7 @@ impl PalSocket for Sys {
     }
 
     unsafe fn socket(domain: c_int, mut kind: c_int, protocol: c_int) -> c_int {
-        if domain != AF_INET {
+        if domain != AF_INET && domain != AF_UNIX {
             errno = syscall::EAFNOSUPPORT;
             return -1;
         }
@@ -313,9 +367,10 @@ impl PalSocket for Sys {
 
         // The tcp: and udp: schemes allow using no path,
         // and later specifying one using `dup`.
-        match kind {
-            SOCK_STREAM => e(syscall::open("tcp:", flags)) as c_int,
-            SOCK_DGRAM => e(syscall::open("udp:", flags)) as c_int,
+        match (domain, kind) {
+            (AF_INET, SOCK_STREAM) => e(syscall::open("tcp:", flags)) as c_int,
+            (AF_INET, SOCK_DGRAM) => e(syscall::open("udp:", flags)) as c_int,
+            (AF_UNIX, SOCK_STREAM) => e(syscall::open("chan:", flags | O_CREAT)) as c_int,
             _ => {
                 errno = syscall::EPROTONOSUPPORT;
                 -1