socket.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. use alloc::vec::Vec;
  2. use core::{cmp, mem, ptr, slice, str};
  3. use syscall::{self, flag::*, Result};
  4. use super::{
  5. super::{errno, types::*, Pal, PalSocket},
  6. e, Sys,
  7. };
  8. use crate::header::{
  9. arpa_inet::inet_aton,
  10. netinet_in::{in_port_t, sockaddr_in, in_addr},
  11. string::strnlen,
  12. sys_socket::{constants::*, sa_family_t, sockaddr, socklen_t},
  13. sys_time::timeval,
  14. sys_un::sockaddr_un,
  15. };
  16. macro_rules! bind_or_connect {
  17. (bind $path:expr) => {
  18. concat!("/", $path)
  19. };
  20. (connect $path:expr) => {
  21. $path
  22. };
  23. ($mode:ident into, $socket:expr, $address:expr, $address_len:expr) => {{
  24. let fd = bind_or_connect!($mode copy, $socket, $address, $address_len);
  25. let result = syscall::dup2(fd, $socket as usize, &[]);
  26. let _ = syscall::close(fd);
  27. if (e(result) as c_int) < 0 {
  28. return -1;
  29. }
  30. 0
  31. }};
  32. ($mode:ident copy, $socket:expr, $address:expr, $address_len:expr) => {{
  33. if ($address_len as usize) < mem::size_of::<sa_family_t>() {
  34. errno = syscall::EINVAL;
  35. return -1;
  36. }
  37. let path = match (*$address).sa_family as c_int {
  38. AF_INET => {
  39. if ($address_len as usize) != mem::size_of::<sockaddr_in>() {
  40. errno = syscall::EINVAL;
  41. return -1;
  42. }
  43. let data = &*($address as *const sockaddr_in);
  44. let addr = slice::from_raw_parts(
  45. &data.sin_addr.s_addr as *const _ as *const u8,
  46. mem::size_of_val(&data.sin_addr.s_addr),
  47. );
  48. let port = in_port_t::from_be(data.sin_port);
  49. let path = format!(
  50. bind_or_connect!($mode "{}.{}.{}.{}:{}"),
  51. addr[0],
  52. addr[1],
  53. addr[2],
  54. addr[3],
  55. port
  56. );
  57. path
  58. },
  59. AF_UNIX => {
  60. let data = &*($address as *const sockaddr_un);
  61. // NOTE: It's UB to access data in given address that exceeds
  62. // the given address length.
  63. let maxlen = cmp::min(
  64. // Max path length of the full-sized struct
  65. data.sun_path.len(),
  66. // Length inferred from given addrlen
  67. $address_len as usize - data.path_offset()
  68. );
  69. let len = cmp::min(
  70. // The maximum length of the address
  71. maxlen,
  72. // The first NUL byte, if any
  73. strnlen(&data.sun_path as *const _, maxlen as size_t),
  74. );
  75. let addr = slice::from_raw_parts(
  76. &data.sun_path as *const _ as *const u8,
  77. len,
  78. );
  79. let path = format!(
  80. "{}",
  81. str::from_utf8(addr).unwrap()
  82. );
  83. trace!("path: {:?}", path);
  84. path
  85. },
  86. _ => {
  87. errno = syscall::EAFNOSUPPORT;
  88. return -1;
  89. },
  90. };
  91. // Duplicate the socket, and then duplicate the copy back to the original fd
  92. let fd = e(syscall::dup($socket as usize, path.as_bytes()));
  93. if (fd as c_int) < 0 {
  94. return -1;
  95. }
  96. fd
  97. }};
  98. }
  99. unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut socklen_t) {
  100. let data = &mut *(address as *mut sockaddr_un);
  101. data.sun_family = AF_UNIX as c_ushort;
  102. let path = slice::from_raw_parts_mut(
  103. &mut data.sun_path as *mut _ as *mut u8,
  104. data.sun_path.len(),
  105. );
  106. let len = cmp::min(path.len(), buf.len());
  107. path[..len].copy_from_slice(&buf[..len]);
  108. *address_len = len as socklen_t;
  109. }
  110. unsafe fn inner_af_inet(
  111. local: bool,
  112. buf: &[u8],
  113. address: *mut sockaddr,
  114. address_len: *mut socklen_t,
  115. ) {
  116. let mut parts = buf.split(|c| *c == b'/');
  117. if local {
  118. // Skip the remote part
  119. parts.next();
  120. }
  121. let mut unparsed_addr = Vec::from(parts.next().expect("missing address"));
  122. let sep = memchr::memchr(b':', &unparsed_addr).expect("missing port");
  123. let (raw_addr, rest) = unparsed_addr.split_at_mut(sep);
  124. let (colon, raw_port) = rest.split_at_mut(1);
  125. let port = str::from_utf8(raw_port).expect("non-utf8 port").parse().expect("invalid port");
  126. // Make address be followed by a NUL-byte
  127. colon[0] = b'\0';
  128. trace!("address: {:?}, port: {:?}", str::from_utf8(&raw_addr), port);
  129. let mut addr = in_addr::default();
  130. assert_eq!(inet_aton(raw_addr.as_ptr() as *mut i8, &mut addr), 1, "inet_aton might be broken, failed to parse netstack address");
  131. let ret = sockaddr_in {
  132. sin_family: AF_INET as sa_family_t,
  133. sin_port: port,
  134. sin_addr: addr,
  135. ..sockaddr_in::default()
  136. };
  137. let len = cmp::min(*address_len as usize, mem::size_of_val(&ret));
  138. ptr::copy_nonoverlapping(&ret as *const _ as *const u8, address as *mut u8, len);
  139. *address_len = len as socklen_t;
  140. }
  141. unsafe fn inner_get_name(
  142. local: bool,
  143. socket: c_int,
  144. address: *mut sockaddr,
  145. address_len: *mut socklen_t,
  146. ) -> Result<usize> {
  147. // Format: [udp|tcp:]remote/local, chan:path
  148. let mut buf = [0; 256];
  149. let len = syscall::fpath(socket as usize, &mut buf)?;
  150. let buf = &buf[..len];
  151. if buf.starts_with(b"tcp:") || buf.starts_with(b"udp:") {
  152. inner_af_inet(local, &buf[4..], address, address_len);
  153. } else if buf.starts_with(b"chan:") {
  154. inner_af_unix(&buf[5..], address, address_len);
  155. } else {
  156. // Socket doesn't belong to any scheme
  157. panic!(
  158. "socket {:?} doesn't match either tcp, udp or chan schemes",
  159. str::from_utf8(buf)
  160. );
  161. }
  162. Ok(0)
  163. }
  164. fn socket_kind(mut kind: c_int) -> (c_int, usize) {
  165. let mut flags = O_RDWR;
  166. if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
  167. kind &= !SOCK_NONBLOCK;
  168. flags |= O_NONBLOCK;
  169. }
  170. if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
  171. kind &= !SOCK_CLOEXEC;
  172. flags |= O_CLOEXEC;
  173. }
  174. (kind, flags)
  175. }
  176. impl PalSocket for Sys {
  177. unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
  178. let stream = e(syscall::dup(socket as usize, b"listen")) as c_int;
  179. if stream < 0 {
  180. return -1;
  181. }
  182. if address != ptr::null_mut()
  183. && address_len != ptr::null_mut()
  184. && Self::getpeername(stream, address, address_len) < 0
  185. {
  186. return -1;
  187. }
  188. stream
  189. }
  190. unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
  191. bind_or_connect!(bind into, socket, address, address_len)
  192. }
  193. unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
  194. bind_or_connect!(connect into, socket, address, address_len)
  195. }
  196. unsafe fn getpeername(
  197. socket: c_int,
  198. address: *mut sockaddr,
  199. address_len: *mut socklen_t,
  200. ) -> c_int {
  201. e(inner_get_name(false, socket, address, address_len)) as c_int
  202. }
  203. unsafe fn getsockname(
  204. socket: c_int,
  205. address: *mut sockaddr,
  206. address_len: *mut socklen_t,
  207. ) -> c_int {
  208. e(inner_get_name(true, socket, address, address_len)) as c_int
  209. }
  210. fn getsockopt(
  211. socket: c_int,
  212. level: c_int,
  213. option_name: c_int,
  214. option_value: *mut c_void,
  215. option_len: *mut socklen_t,
  216. ) -> c_int {
  217. match level {
  218. SOL_SOCKET => match option_name {
  219. SO_ERROR => {
  220. if option_value.is_null() {
  221. return e(Err(syscall::Error::new(syscall::EFAULT))) as c_int;
  222. }
  223. if (option_len as usize) < mem::size_of::<c_int>() {
  224. return e(Err(syscall::Error::new(syscall::EINVAL))) as c_int;
  225. }
  226. let error = unsafe { &mut *(option_value as *mut c_int) };
  227. //TODO: Socket nonblock connection error
  228. *error = 0;
  229. return 0;
  230. }
  231. _ => (),
  232. },
  233. _ => (),
  234. }
  235. eprintln!(
  236. "getsockopt({}, {}, {}, {:p}, {:p})",
  237. socket, level, option_name, option_value, option_len
  238. );
  239. e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int
  240. }
  241. fn listen(socket: c_int, backlog: c_int) -> c_int {
  242. // Redox has no need to listen
  243. 0
  244. }
  245. unsafe fn recvfrom(
  246. socket: c_int,
  247. buf: *mut c_void,
  248. len: size_t,
  249. flags: c_int,
  250. address: *mut sockaddr,
  251. address_len: *mut socklen_t,
  252. ) -> ssize_t {
  253. if flags != 0 {
  254. errno = syscall::EOPNOTSUPP;
  255. return -1;
  256. }
  257. if address == ptr::null_mut() || address_len == ptr::null_mut() {
  258. Self::read(socket, slice::from_raw_parts_mut(buf as *mut u8, len))
  259. } else {
  260. let fd = e(syscall::dup(socket as usize, b"listen"));
  261. if fd == !0 {
  262. return -1;
  263. }
  264. if Self::getpeername(fd as c_int, address, address_len) < 0 {
  265. let _ = syscall::close(fd);
  266. return -1;
  267. }
  268. let ret = Self::read(fd as c_int, slice::from_raw_parts_mut(buf as *mut u8, len));
  269. let _ = syscall::close(fd);
  270. ret
  271. }
  272. }
  273. unsafe fn sendto(
  274. socket: c_int,
  275. buf: *const c_void,
  276. len: size_t,
  277. flags: c_int,
  278. dest_addr: *const sockaddr,
  279. dest_len: socklen_t,
  280. ) -> ssize_t {
  281. if flags != 0 {
  282. errno = syscall::EOPNOTSUPP;
  283. return -1;
  284. }
  285. if dest_addr == ptr::null() || dest_len == 0 {
  286. Self::write(socket, slice::from_raw_parts(buf as *const u8, len))
  287. } else {
  288. let fd = bind_or_connect!(connect copy, socket, dest_addr, dest_len);
  289. let ret = Self::write(fd as c_int, slice::from_raw_parts(buf as *const u8, len));
  290. let _ = syscall::close(fd);
  291. ret
  292. }
  293. }
  294. fn setsockopt(
  295. socket: c_int,
  296. level: c_int,
  297. option_name: c_int,
  298. option_value: *const c_void,
  299. option_len: socklen_t,
  300. ) -> c_int {
  301. let set_timeout = |timeout_name: &[u8]| -> c_int {
  302. if option_value.is_null() {
  303. return e(Err(syscall::Error::new(syscall::EFAULT))) as c_int;
  304. }
  305. if (option_len as usize) < mem::size_of::<timeval>() {
  306. return e(Err(syscall::Error::new(syscall::EINVAL))) as c_int;
  307. }
  308. let timeval = unsafe { &*(option_value as *const timeval) };
  309. let fd = e(syscall::dup(socket as usize, timeout_name));
  310. if fd == !0 {
  311. return -1;
  312. }
  313. let timespec = syscall::TimeSpec {
  314. tv_sec: timeval.tv_sec,
  315. tv_nsec: timeval.tv_usec * 1000,
  316. };
  317. let ret = Self::write(fd as c_int, &timespec);
  318. let _ = syscall::close(fd);
  319. if ret >= 0 {
  320. 0
  321. } else {
  322. -1
  323. }
  324. };
  325. match level {
  326. SOL_SOCKET => match option_name {
  327. SO_RCVTIMEO => return set_timeout(b"read_timeout"),
  328. SO_SNDTIMEO => return set_timeout(b"write_timeout"),
  329. _ => (),
  330. },
  331. _ => (),
  332. }
  333. eprintln!(
  334. "setsockopt({}, {}, {}, {:p}, {}) - unknown option",
  335. socket, level, option_name, option_value, option_len
  336. );
  337. 0
  338. }
  339. fn shutdown(socket: c_int, how: c_int) -> c_int {
  340. eprintln!("shutdown({}, {})", socket, how);
  341. e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int
  342. }
  343. unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int {
  344. if domain != AF_INET && domain != AF_UNIX {
  345. errno = syscall::EAFNOSUPPORT;
  346. return -1;
  347. }
  348. // if protocol != 0 {
  349. // errno = syscall::EPROTONOSUPPORT;
  350. // return -1;
  351. // }
  352. let (kind, flags) = socket_kind(kind);
  353. // The tcp: and udp: schemes allow using no path,
  354. // and later specifying one using `dup`.
  355. match (domain, kind) {
  356. (AF_INET, SOCK_STREAM) => e(syscall::open("tcp:", flags)) as c_int,
  357. (AF_INET, SOCK_DGRAM) => e(syscall::open("udp:", flags)) as c_int,
  358. (AF_UNIX, SOCK_STREAM) => e(syscall::open("chan:", flags | O_CREAT)) as c_int,
  359. _ => {
  360. errno = syscall::EPROTONOSUPPORT;
  361. -1
  362. },
  363. }
  364. }
  365. fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> c_int {
  366. let (kind, flags) = socket_kind(kind);
  367. match (domain, kind) {
  368. (AF_UNIX, SOCK_STREAM) => {
  369. let listener = e(syscall::open("chan:", flags | O_CREAT));
  370. if listener == !0 {
  371. return -1;
  372. }
  373. // For now, chan: lets connects be instant, and instead blocks
  374. // on any I/O performed. So we don't need to mark this as
  375. // nonblocking.
  376. let fd0 = e(syscall::dup(listener, b"connect"));
  377. if fd0 == !0 {
  378. let _ = syscall::close(listener);
  379. return -1;
  380. }
  381. let fd1 = e(syscall::dup(listener, b"listen"));
  382. if fd1 == !0 {
  383. let _ = syscall::close(fd0);
  384. let _ = syscall::close(listener);
  385. return -1;
  386. }
  387. sv[0] = fd0 as c_int;
  388. sv[1] = fd1 as c_int;
  389. 0
  390. },
  391. _ => unsafe {
  392. eprintln!(
  393. "socketpair({}, {}, {}, {:p})",
  394. domain,
  395. kind,
  396. protocol,
  397. sv.as_mut_ptr()
  398. );
  399. errno = syscall::EPROTONOSUPPORT;
  400. -1
  401. },
  402. }
  403. }
  404. }