@@ -164,4 +164,120 @@ static inline abi_long do_bsd_getsockname(int fd, abi_ulong target_addr,
return ret;
}
+/* socketpair(2) */
+static inline abi_long do_bsd_socketpair(int domain, int type, int protocol,
+ abi_ulong target_tab_addr)
+{
+ int tab[2];
+ abi_long ret;
+
+ if (!access_ok(VERIFY_WRITE, target_tab_addr, sizeof(tab[0]) * 2)) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(socketpair(domain, type, protocol, tab));
+ if (!is_error(ret)) {
+ if (put_user_s32(tab[0], target_tab_addr) ||
+ put_user_s32(tab[1], target_tab_addr + sizeof(tab[0]))) {
+ ret = -TARGET_EFAULT;
+ }
+ }
+ return ret;
+}
+
+/* sendto(2) */
+static inline abi_long do_bsd_sendto(int fd, abi_ulong msg, size_t len,
+ int flags, abi_ulong target_addr,
+ socklen_t addrlen)
+{
+ struct sockaddr *saddr;
+ void *host_msg;
+ abi_long ret;
+
+ if ((int)addrlen < 0) {
+ return -TARGET_EINVAL;
+ }
+ if (len != 0) {
+ host_msg = lock_user(VERIFY_READ, msg, len, 1);
+ if (!host_msg) {
+ return -TARGET_EFAULT;
+ }
+ } else {
+ host_msg = NULL;
+ }
+ if (target_addr) {
+ saddr = alloca(addrlen + 1);
+ ret = target_to_host_sockaddr(saddr, target_addr, addrlen);
+ if (is_error(ret)) {
+ unlock_user(host_msg, msg, 0);
+ return ret;
+ }
+ ret = get_errno(safe_sendto(fd, host_msg, len, flags, saddr, addrlen));
+ } else {
+ ret = get_errno(send(fd, host_msg, len, flags));
+ }
+ unlock_user(host_msg, msg, 0);
+ return ret;
+}
+
+/* recvfrom(2) */
+static inline abi_long do_bsd_recvfrom(int fd, abi_ulong msg, size_t len,
+ int flags, abi_ulong target_addr,
+ abi_ulong target_addrlen)
+{
+ socklen_t addrlen;
+ struct sockaddr *saddr;
+ void *host_msg;
+ abi_long ret;
+
+ host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
+ if (!host_msg) {
+ return -TARGET_EFAULT;
+ }
+ if (target_addr) {
+ if (get_user_u32(addrlen, target_addrlen)) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ if ((int)addrlen < 0) {
+ ret = -TARGET_EINVAL;
+ goto fail;
+ }
+ saddr = alloca(addrlen + 1);
+ ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, saddr,
+ &addrlen));
+ } else {
+ saddr = NULL; /* To keep compiler quiet. */
+ ret = get_errno(recv(fd, host_msg, len, flags));
+ }
+ if (!is_error(ret)) {
+ if (target_addr) {
+ if (is_error(host_to_target_sockaddr(target_addr, saddr, addrlen))) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ } else if (put_user_u32(addrlen, target_addrlen)) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ }
+ unlock_user(host_msg, msg, len);
+ } else {
+fail:
+ unlock_user(host_msg, msg, 0);
+ }
+ return ret;
+}
+
+/* socket(2) */
+static inline abi_long do_bsd_socket(abi_long domain, abi_long type,
+ abi_long protocol)
+{
+ return get_errno(socket(domain, type, protocol));
+}
+
+/* shutdown(2) */
+static inline abi_long do_bsd_shutdown(abi_long s, abi_long how)
+{
+ return get_errno(shutdown(s, how));
+}
+
#endif /* BSD_SOCKET_H */