diff --git a/src/platform/src/lib.rs b/src/platform/src/lib.rs
index 8a4326e6004e9097aa11c984c453d656eeb6a87e..b0891fd25af35abc739e256734fa5f7dbec7d955 100644
--- a/src/platform/src/lib.rs
+++ b/src/platform/src/lib.rs
@@ -12,7 +12,6 @@ extern crate alloc;
 extern crate sc;
 
 #[cfg(all(not(feature = "no_std"), target_os = "redox"))]
-#[macro_use]
 pub extern crate syscall;
 
 pub use allocator::*;
diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs
index d08ff25833cbeed81370ce4df5eded6da6aa15ab..6121d939430758a5b7e7fb0cae79e9b5e05de145 100644
--- a/src/platform/src/linux/mod.rs
+++ b/src/platform/src/linux/mod.rs
@@ -19,6 +19,10 @@ pub fn e(sys: usize) -> usize {
     }
 }
 
+pub unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
+    e(syscall!(ACCEPT, socket, address, address_len)) as c_int
+}
+
 pub unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
     e(syscall!(BIND, socket, address, address_len)) as c_int
 }
@@ -119,6 +123,10 @@ pub fn getgid() -> gid_t {
     e(unsafe { syscall!(GETGID) })
 }
 
+pub unsafe fn getpeername(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
+    e(unsafe { syscall!(GETPEERNAME, socket, address, address_len) }) as c_int
+}
+
 pub fn getpgid(pid: pid_t) -> pid_t {
     e(unsafe { syscall!(GETPGID, pid) })
 }
@@ -131,6 +139,10 @@ pub fn getppid() -> pid_t {
     e(unsafe { syscall!(GETPPID) })
 }
 
+pub unsafe fn getsockname(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
+    e(unsafe { syscall!(GETSOCKNAME, socket, address, address_len) }) as c_int
+}
+
 pub fn getuid() -> uid_t {
     e(unsafe { syscall!(GETUID) })
 }
diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs
index dd48ef5d47055a58f3ebbcc90e23d68224b04974..0ba0697b29af10ff9bacba009fb4273ec0f60d69 100644
--- a/src/platform/src/redox/mod.rs
+++ b/src/platform/src/redox/mod.rs
@@ -1,8 +1,9 @@
-use alloc;
+//! sys/socket implementation, following http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/socket.h.html
+
 use core::mem;
 use core::ptr;
 use core::slice;
-use syscall;
+use syscall::{self, Result};
 use syscall::data::Stat as redox_stat;
 use syscall::data::TimeSpec as redox_timespec;
 use syscall::flag::*;
@@ -17,7 +18,7 @@ struct SockData {
     _pad: [c_char; 8],
 }
 
-pub fn e(sys: Result<usize, syscall::Error>) -> usize {
+pub fn e(sys: Result<usize>) -> usize {
     match sys {
         Ok(ok) => ok,
         Err(err) => {
@@ -64,6 +65,18 @@ macro_rules! bind_or_connect {
     }}
 }
 
+pub unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
+    let stream = e(syscall::dup(socket as usize, b"listen")) as c_int;
+    if stream < 0 {
+        return -1;
+    }
+    if address != ptr::null_mut() && address_len != ptr::null_mut()
+            && getpeername(stream, address, address_len) < 0 {
+        return -1;
+    }
+    stream
+}
+
 pub unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
     bind_or_connect!(bind socket, address, address_len)
 }
@@ -268,6 +281,40 @@ pub fn getgid() -> gid_t {
     e(syscall::getgid()) as gid_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: 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
+        parts.next();
+    }
+    let part = parts.next().expect("Invalid reply from netstack");
+
+    let data = slice::from_raw_parts_mut(
+        &mut (*address).data as *mut _ as *mut u8,
+        (*address).data.len()
+    );
+
+    let len = data.len().min(part.len());
+    data[..len].copy_from_slice(&part[..len]);
+
+    *address_len = len as socklen_t;
+    Ok(0)
+}
+
+pub unsafe fn getpeername(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
+    e(inner_get_name(false, socket, address, address_len)) as c_int
+}
+
 pub fn getpgid(pid: pid_t) -> pid_t {
     e(syscall::getpgid(pid as usize)) as pid_t
 }
@@ -280,6 +327,10 @@ pub fn getppid() -> pid_t {
     e(syscall::getppid()) as pid_t
 }
 
+pub unsafe fn getsockname(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
+    e(inner_get_name(true, socket, address, address_len)) as c_int
+}
+
 pub fn getuid() -> uid_t {
     e(syscall::getuid()) as pid_t
 }
@@ -393,15 +444,10 @@ pub unsafe fn recvfrom(
         errno = syscall::EOPNOTSUPP;
         return -1;
     }
-    let data = slice::from_raw_parts_mut(
-        &mut (*address).data as *mut _ as *mut u8,
-        (*address).data.len(),
-    );
-    let pathlen = e(syscall::fpath(socket as usize, data));
-    if pathlen < 0 {
+    if address != ptr::null_mut() && address_len != ptr::null_mut()
+            && getpeername(socket, address, address_len) < 0 {
         return -1;
     }
-    *address_len = pathlen as socklen_t;
     read(socket, slice::from_raw_parts_mut(buf as *mut u8, len))
 }
 
@@ -427,10 +473,13 @@ pub unsafe fn sendto(
     buf: *const c_void,
     len: size_t,
     flags: c_int,
-    _dest_addr: *const sockaddr,
-    _dest_len: socklen_t,
+    dest_addr: *const sockaddr,
+    dest_len: socklen_t,
 ) -> ssize_t {
-    // TODO: Use dest_addr and dest_len
+    if dest_addr != ptr::null() || dest_len != 0 {
+        errno = syscall::EISCONN;
+        return -1;
+    }
     if flags != 0 {
         errno = syscall::EOPNOTSUPP;
         return -1;
diff --git a/src/sys_socket/src/constants.rs b/src/sys_socket/src/constants.rs
new file mode 100644
index 0000000000000000000000000000000000000000..6abb1b8e64daaeaf6b79a35fb8c405d2d23e23c7
--- /dev/null
+++ b/src/sys_socket/src/constants.rs
@@ -0,0 +1,60 @@
+use platform::types::*;
+
+// These constants also exist in platform. They need to match.
+// Reason they are not just re-exported is cbindgen.
+pub const SOCK_STREAM: c_int = 1;
+pub const SOCK_DGRAM: c_int = 2;
+pub const SOCK_NONBLOCK: c_int = 0o4000;
+pub const SOCK_CLOEXEC: c_int = 0o2000000;
+pub const AF_INET: c_int = 2;
+
+// Other constants
+pub const SOCK_SEQPACKET: c_int = 5;
+
+pub const SOL_SOCKET: c_int = 1;
+
+pub const SO_DEBUG: c_int = 1;
+pub const SO_REUSEADDR: c_int = 2;
+pub const SO_TYPE: c_int = 3;
+pub const SO_ERROR: c_int = 4;
+pub const SO_DONTROUTE: c_int = 5;
+pub const SO_BROADCAST: c_int = 6;
+pub const SO_SNDBUF: c_int = 7;
+pub const SO_RCVBUF: c_int = 8;
+pub const SO_KEEPALIVE: c_int = 9;
+pub const SO_OOBINLINE: c_int = 10;
+pub const SO_NO_CHECK: c_int = 11;
+pub const SO_PRIORITY: c_int = 12;
+pub const SO_LINGER: c_int = 13;
+pub const SO_BSDCOMPAT: c_int = 14;
+pub const SO_REUSEPORT: c_int = 15;
+pub const SO_PASSCRED: c_int = 16;
+pub const SO_PEERCRED: c_int = 17;
+pub const SO_RCVLOWAT: c_int = 18;
+pub const SO_SNDLOWAT: c_int = 19;
+pub const SO_RCVTIMEO: c_int = 20;
+pub const SO_SNDTIMEO: c_int = 21;
+pub const SO_ACCEPTCONN: c_int = 30;
+pub const SO_PEERSEC: c_int = 31;
+pub const SO_SNDBUFFORCE: c_int = 32;
+pub const SO_RCVBUFFORCE: c_int = 33;
+pub const SO_PROTOCOL: c_int = 38;
+pub const SO_DOMAIN: c_int = 39;
+
+pub const SOMAXCONN: c_int = 128;
+
+pub const MSG_CTRUNC: c_int = 1 << 3;
+pub const MSG_DONTROUTE: c_int = 1 << 2;
+pub const MSG_EOR: c_int = 1 << 7;
+pub const MSG_OOB: c_int = 1;
+pub const MSG_PEEK: c_int = 1 << 1;
+pub const MSG_TRUNC: c_int = 1 << 5;
+pub const MSG_WAITALL: c_int = 1 << 8;
+
+pub const AF_INET6: c_int = 10;
+pub const AF_UNIX: c_int = 1;
+pub const AF_UNSPEC: c_int = 0;
+
+pub const SHUT_RD: c_int = 0;
+pub const SHUT_RDWR: c_int = 2;
+pub const SHUT_WR: c_int = 1;
diff --git a/src/sys_socket/src/lib.rs b/src/sys_socket/src/lib.rs
index 01fd0c5bcd2108ad44413ec68b1124dd5f7d74f9..c360c9721c95d346ae525f0aa35af4aed8012807 100644
--- a/src/sys_socket/src/lib.rs
+++ b/src/sys_socket/src/lib.rs
@@ -8,6 +8,9 @@ extern crate platform;
 use core::ptr;
 use platform::types::*;
 
+mod constants;
+use constants::*;
+
 pub type in_addr_t = [u8; 4];
 pub type in_port_t = u16;
 pub type sa_family_t = u16;
@@ -19,19 +22,13 @@ pub struct sockaddr {
     data: [c_char; 14],
 }
 
-pub const AF_INET: c_int = 2;
-pub const SOCK_STREAM: c_int = 1;
-pub const SOCK_DGRAM: c_int = 2;
-pub const SOCK_NONBLOCK: c_int = 0o4000;
-pub const SOCK_CLOEXEC: c_int = 0o2000000;
-
 #[no_mangle]
 pub unsafe extern "C" fn accept(
     socket: c_int,
     address: *mut sockaddr,
     address_len: *mut socklen_t,
 ) -> c_int {
-    unimplemented!();
+    platform::accept(socket, address as *mut platform::sockaddr, address_len)
 }
 
 #[no_mangle]
@@ -55,10 +52,10 @@ pub unsafe extern "C" fn connect(
 #[no_mangle]
 pub unsafe extern "C" fn getpeername(
     socket: c_int,
-    address: *const sockaddr,
-    address_len: socklen_t,
+    address: *mut sockaddr,
+    address_len: *mut socklen_t,
 ) -> c_int {
-    unimplemented!();
+    platform::getpeername(socket, address as *mut platform::sockaddr, address_len)
 }
 
 #[no_mangle]
@@ -67,7 +64,7 @@ pub unsafe extern "C" fn getsockname(
     address: *mut sockaddr,
     address_len: *mut socklen_t,
 ) -> c_int {
-    unimplemented!();
+    platform::getsockname(socket, address as *mut platform::sockaddr, address_len)
 }
 
 #[no_mangle]