diff --git a/headers/private/net/net_socket.h b/headers/private/net/net_socket.h index e9cf4079d4..ef3fcd3b99 100644 --- a/headers/private/net/net_socket.h +++ b/headers/private/net/net_socket.h @@ -89,14 +89,10 @@ struct net_socket_module_info { int (*getsockopt)(net_socket *socket, int level, int option, void *optionValue, int *_optionLength); int (*listen)(net_socket *socket, int backlog); - ssize_t (*recv)(net_socket *socket, void *data, size_t length, int flags); - ssize_t (*recvfrom)(net_socket *socket, void *data, size_t length, int flags, - struct sockaddr *address, socklen_t *_addressLength); - ssize_t (*recvmsg)(net_socket *socket, msghdr *header, int flags); - ssize_t (*send)(net_socket *socket, const void *data, size_t length, int flags); - ssize_t (*sendto)(net_socket *socket, const void *data, size_t length, - int flags, const struct sockaddr *address, socklen_t addressLength); - ssize_t (*sendmsg)(net_socket *socket, msghdr *header, int flags); + ssize_t (*receive)(net_socket *socket, struct msghdr *, void *data, + size_t length, int flags); + ssize_t (*send)(net_socket *socket, struct msghdr *, const void *data, + size_t length, int flags); int (*setsockopt)(net_socket *socket, int level, int option, const void *optionValue, int optionLength); int (*shutdown)(net_socket *socket, int direction); diff --git a/headers/private/net/net_stack_driver.h b/headers/private/net/net_stack_driver.h index df887010c3..7ffd52cef3 100644 --- a/headers/private/net/net_stack_driver.h +++ b/headers/private/net/net_stack_driver.h @@ -29,12 +29,8 @@ enum { // ops acting on an existing socket NET_STACK_BIND, // sockaddr_args * - NET_STACK_RECVFROM, // struct msghdr * - NET_STACK_RECV, // transfer_args * - NET_STACK_RECVMSG, // msghdr_args * - NET_STACK_SENDTO, // struct msghdr * - NET_STACK_SEND, // transfer_args * - NET_STACK_SENDMSG, // msghdr_args * + NET_STACK_RECEIVE, // message_args * + NET_STACK_SEND, // message_args * NET_STACK_LISTEN, // int_args * (value = backlog) NET_STACK_ACCEPT, // sockaddr_args * NET_STACK_CONNECT, // sockaddr_args * @@ -62,16 +58,10 @@ struct sockopt_args { // used by NET_STACK_SETSOCKOPT/_GETSOCKOPT int length; }; -struct transfer_args { // used by NET_STACK_SEND/_RECV - void *data; - size_t data_length; - int flags; - struct sockaddr *address; // only used for recvfrom() and sendto() - socklen_t address_length; // "" -}; - -struct msghdr_args { +struct message_args { struct msghdr *header; + void *data; + size_t length; int flags; }; diff --git a/src/add-ons/kernel/drivers/network/stack/kernel_stack.cpp b/src/add-ons/kernel/drivers/network/stack/kernel_stack.cpp index 83e4c391f2..54cc9ee1ac 100644 --- a/src/add-ons/kernel/drivers/network/stack/kernel_stack.cpp +++ b/src/add-ons/kernel/drivers/network/stack/kernel_stack.cpp @@ -90,35 +90,40 @@ check_args_and_address(ArgType &args, sockaddr_storage &address, void *data, siz static status_t -check_msghdr_args(msghdr_args &args, msghdr &header, sockaddr_storage &address, +check_message_args(message_args &args, msghdr &header, sockaddr_storage &address, void *data, size_t length, sockaddr **originalAddress) { - if (length < sizeof(msghdr_args)) + if (length < sizeof(message_args)) return B_BAD_VALUE; - status_t status = user_memcpy(&args, data, sizeof(msghdr_args)); + status_t status = user_memcpy(&args, data, sizeof(message_args)); if (status < B_OK) return status; - status = user_memcpy(&header, args.header, sizeof(msghdr)); - if (status < B_OK) - return status; + if (args.header != NULL) { + status = user_memcpy(&header, args.header, sizeof(msghdr)); + if (status < B_OK) + return status; - if (originalAddress == NULL) { - if (header.msg_namelen > sizeof(address)) - return B_BAD_VALUE; + if (header.msg_name == NULL) + return B_OK; - if (header.msg_name != NULL) { - status = user_memcpy(&address, header.msg_name, header.msg_namelen); - if (status < B_OK) - return B_BAD_ADDRESS; + if (originalAddress == NULL) { + if (header.msg_namelen > sizeof(address)) + return B_BAD_VALUE; + + if (header.msg_name != NULL) { + status = user_memcpy(&address, header.msg_name, header.msg_namelen); + if (status < B_OK) + return B_BAD_ADDRESS; + } + } else { + *originalAddress = (sockaddr *)header.msg_name; } - } else { - originalAddress = (sockaddr **)&header.msg_name; + + header.msg_name = (char *)&address; } - if (header.msg_name != NULL) - header.msg_name = (char *)&address; return B_OK; } @@ -368,96 +373,51 @@ net_stack_control(void *_cookie, uint32 op, void *data, size_t length) return sSocket->shutdown(cookie->socket, (int)data); case NET_STACK_SEND: - { - transfer_args args; - status = check_args(args, data, length); - if (status < B_OK) - return status; - - return sSocket->send(cookie->socket, args.data, args.data_length, args.flags); - } - case NET_STACK_SENDTO: { sockaddr_storage address; - transfer_args args; - status = check_args_and_address(args, address, data, length); - if (status < B_OK) - return status; - - return sSocket->sendto(cookie->socket, args.data, args.data_length, - args.flags, args.address, args.address_length); - } - - case NET_STACK_SENDMSG: - { - sockaddr_storage address; - msghdr_args args; + message_args args; msghdr header; - status = check_msghdr_args(args, header, address, data, + status = check_message_args(args, header, address, data, length, NULL); if (status < B_OK) return status; - return sSocket->sendmsg(cookie->socket, &header, args.flags); + return sSocket->send(cookie->socket, + args.header ? &header : NULL, + args.data, args.length, args.flags); } - case NET_STACK_RECV: - { - transfer_args args; - status = check_args(args, data, length); - if (status < B_OK) - return status; - - return sSocket->recv(cookie->socket, args.data, args.data_length, args.flags); - } - case NET_STACK_RECVFROM: + case NET_STACK_RECEIVE: { + sockaddr *originalAddress = NULL; sockaddr_storage address; - transfer_args args; - status = check_args_and_address(args, address, data, length, false); - if (status < B_OK) - return status; - - ssize_t bytesRead = sSocket->recvfrom(cookie->socket, args.data, - args.data_length, args.flags, args.address, &args.address_length); - if (bytesRead < B_OK) - return bytesRead; - - status = return_address(args, data); - if (status < B_OK) - return status; - - return bytesRead; - } - - case NET_STACK_RECVMSG: - { - sockaddr *originalAddress; - sockaddr_storage address; - msghdr_args args; + message_args args; msghdr header; - status = check_msghdr_args(args, header, address, data, + status = check_message_args(args, header, address, data, length, &originalAddress); if (status < B_OK) return status; - ssize_t bytesRead = sSocket->recvmsg(cookie->socket, &header, - args.flags); + ssize_t bytesRead = sSocket->receive(cookie->socket, + args.header ? &header : NULL, args.data, + args.length, args.flags); if (bytesRead < B_OK) return bytesRead; - if (header.msg_name != NULL) { - if (user_memcpy(originalAddress, header.msg_name, - header.msg_namelen) < B_OK) + if (args.header != NULL) { + if (header.msg_name != NULL) { + if (user_memcpy(originalAddress, header.msg_name, + header.msg_namelen) < B_OK) + return B_BAD_ADDRESS; + } + + if (user_memcpy(&args.header->msg_flags, &header.msg_flags, + sizeof(int)) < B_OK) return B_BAD_ADDRESS; } - if (user_memcpy(&args.header->msg_flags, &header.msg_flags, - sizeof(int)) < B_OK) - return B_BAD_ADDRESS; - return bytesRead; } @@ -572,7 +532,7 @@ net_stack_read(void *_cookie, off_t /*offset*/, void *buffer, size_t *_length) if (cookie->socket == NULL) return B_BAD_VALUE; - ssize_t bytesRead = sSocket->recv(cookie->socket, buffer, *_length, 0); + ssize_t bytesRead = sSocket->receive(cookie->socket, NULL, buffer, *_length, 0); if (bytesRead < 0) { *_length = 0; return bytesRead; @@ -608,7 +568,7 @@ net_stack_write(void *_cookie, off_t /*offset*/, const void *buffer, size_t *_le if (cookie->socket == NULL) return B_BAD_VALUE; - ssize_t bytesWritten = sSocket->send(cookie->socket, buffer, *_length, 0); + ssize_t bytesWritten = sSocket->send(cookie->socket, NULL, buffer, *_length, 0); if (bytesWritten < 0) { *_length = 0; return bytesWritten; diff --git a/src/add-ons/kernel/network/socket/socket.cpp b/src/add-ons/kernel/network/socket/socket.cpp index 3dec39747b..85f23f1528 100644 --- a/src/add-ons/kernel/network/socket/socket.cpp +++ b/src/add-ons/kernel/network/socket/socket.cpp @@ -15,6 +15,7 @@ #include +#include #include #include @@ -113,14 +114,13 @@ accept(int socket, struct sockaddr *address, socklen_t *_addressLength) ssize_t recv(int socket, void *data, size_t length, int flags) { - transfer_args args; + message_args args; args.data = data; - args.data_length = length; + args.length = length; args.flags = flags; - args.address = NULL; - args.address_length = 0; + args.header = NULL; - return ioctl(socket, NET_STACK_RECV, &args, sizeof(args)); + return ioctl(socket, NET_STACK_RECEIVE, &args, sizeof(args)); } @@ -128,19 +128,25 @@ ssize_t recvfrom(int socket, void *data, size_t length, int flags, struct sockaddr *address, socklen_t *_addressLength) { - transfer_args args; - args.data = data; - args.data_length = length; - args.flags = flags; - args.address = address; - args.address_length = _addressLength ? *_addressLength : 0; + message_args args; + msghdr header; - ssize_t bytesReceived = ioctl(socket, NET_STACK_RECVFROM, &args, sizeof(args)); + memset(&header, 0, sizeof(header)); + + args.data = data; + args.length = length; + args.flags = flags; + args.header = &header; + + header.msg_name = (char *)address; + header.msg_namelen = _addressLength ? *_addressLength : 0; + + ssize_t bytesReceived = ioctl(socket, NET_STACK_RECEIVE, &args, sizeof(args)); if (bytesReceived < 0) return -1; if (_addressLength != NULL) - *_addressLength = args.address_length; + *_addressLength = header.msg_namelen; return bytesReceived; } @@ -149,20 +155,34 @@ recvfrom(int socket, void *data, size_t length, int flags, ssize_t recvmsg(int socket, struct msghdr *message, int flags) { - msghdr_args args = { message, flags }; - return ioctl(socket, NET_STACK_RECVMSG, &args, sizeof(args)); + message_args args; + + if (message == NULL || (message->msg_iovlen > 0 && message->msg_iov == NULL)) + return B_BAD_VALUE; + + args.header = message; + args.flags = flags; + + if (message->msg_iovlen > 0) { + args.data = message->msg_iov[0].iov_base; + args.length = message->msg_iov[0].iov_len; + } else { + args.data = NULL; + args.length = 0; + } + + return ioctl(socket, NET_STACK_RECEIVE, &args, sizeof(args)); } ssize_t send(int socket, const void *data, size_t length, int flags) { - transfer_args args; + message_args args; args.data = const_cast(data); - args.data_length = length; + args.length = length; args.flags = flags; - args.address = NULL; - args.address_length = 0; + args.header = NULL; return ioctl(socket, NET_STACK_SEND, &args, sizeof(args)); } @@ -172,22 +192,41 @@ ssize_t sendto(int socket, const void *data, size_t length, int flags, const struct sockaddr *address, socklen_t addressLength) { - transfer_args args; - args.data = const_cast(data); - args.data_length = length; - args.flags = flags; - args.address = const_cast(address); - args.address_length = addressLength; + message_args args; + msghdr header; + memset(&header, 0, sizeof(header)); - return ioctl(socket, NET_STACK_SENDTO, &args, sizeof(args)); + args.data = const_cast(data); + args.length = length; + args.flags = flags; + args.header = &header; + header.msg_name = (char *)const_cast(address); + header.msg_namelen = addressLength; + + return ioctl(socket, NET_STACK_SEND, &args, sizeof(args)); } ssize_t sendmsg(int socket, const struct msghdr *message, int flags) { - msghdr_args args = { (msghdr *)message, flags }; - return ioctl(socket, NET_STACK_SENDMSG, &args, sizeof(args)); + message_args args; + + if (message == NULL || (message->msg_iovlen > 0 && message->msg_iov == NULL)) + return B_BAD_VALUE; + + args.header = (msghdr *)message; + args.flags = flags; + + if (message->msg_iovlen > 0) { + args.data = message->msg_iov[0].iov_base; + args.length = message->msg_iov[0].iov_len; + } else { + args.data = NULL; + args.length = 0; + } + + return ioctl(socket, NET_STACK_SEND, &args, sizeof(args)); } diff --git a/src/add-ons/kernel/network/stack/net_socket.cpp b/src/add-ons/kernel/network/stack/net_socket.cpp index 7a01c16014..c8fc1e2f24 100644 --- a/src/add-ons/kernel/network/stack/net_socket.cpp +++ b/src/add-ons/kernel/network/stack/net_socket.cpp @@ -40,8 +40,6 @@ struct net_socket_private : net_socket { void socket_delete(net_socket *socket); int socket_bind(net_socket *socket, const struct sockaddr *address, socklen_t addressLength); -ssize_t socket_recvmsg(net_socket *, msghdr *header, int flags); -ssize_t socket_sendmsg(net_socket *, msghdr *header, int flags); struct list sSocketList; benaphore sSocketLock; @@ -735,180 +733,113 @@ socket_listen(net_socket *socket, int backlog) ssize_t -socket_recv(net_socket *socket, void *data, size_t length, int flags) -{ - net_buffer *buffer; - status_t status = socket->first_info->read_data( - socket->first_protocol, length, flags, &buffer); - if (status < B_OK) - return status; - - // if 0 bytes we're received, no buffer will be created - if (buffer == NULL) - return 0; - - ssize_t bytesReceived = buffer->size; - gNetBufferModule.read(buffer, 0, data, bytesReceived); - gNetBufferModule.free(buffer); - - return bytesReceived; -} - - -ssize_t -socket_recvfrom(net_socket *socket, void *data, size_t length, int flags, - struct sockaddr *address, socklen_t *_addressLength) -{ - iovec iov = { data, length }; - msghdr header; - - memset(&header, 0, sizeof(header)); - header.msg_name = (char *)address; - header.msg_iov = &iov; - header.msg_iovlen = 1; - - if (_addressLength != NULL) - header.msg_namelen = *_addressLength; - - ssize_t bytesReceived = socket_recvmsg(socket, &header, flags); - if (_addressLength != NULL) - *_addressLength = header.msg_namelen; - - return bytesReceived; -} - - -ssize_t -socket_recvmsg(net_socket *socket, msghdr *header, int flags) +socket_receive(net_socket *socket, msghdr *header, void *data, size_t length, + int flags) { + size_t totalLength = length; net_buffer *buffer; iovec tmp; int i; - size_t length = 0; - for (i = 0; i < header->msg_iovlen; i++) { - if (user_memcpy(&tmp, header->msg_iov + i, sizeof(iovec)) < B_OK) - return B_BAD_ADDRESS; - if (tmp.iov_len > 0 && tmp.iov_base == NULL) - return B_BAD_ADDRESS; - length += tmp.iov_len; + // the convention to this function is that have header been + // present, { data, length } would have been iovec[0] and is + // always considered like that + + if (header) { + // calculate the length considering all of the extra buffers + for (i = 1; i < header->msg_iovlen; i++) { + if (user_memcpy(&tmp, header->msg_iov + i, sizeof(iovec)) < B_OK) + return B_BAD_ADDRESS; + if (tmp.iov_len > 0 && tmp.iov_base == NULL) + return B_BAD_ADDRESS; + totalLength += tmp.iov_len; + } } status_t status = socket->first_info->read_data( - socket->first_protocol, length, flags, &buffer); + socket->first_protocol, totalLength, flags, &buffer); if (status < B_OK) return status; - // TODO: - consider the control buffer options - // - datagram based protocols should return the + // TODO: - datagram based protocols should return the // full datagram so we can cut it here with MSG_TRUNC // - returning a NULL buffer when received 0 bytes // may not make much sense as we still need the address // - gNetBufferModule.read() uses memcpy() instead of user_memcpy - size_t nameLen = header->msg_namelen; - header->msg_namelen = 0; - header->msg_flags = 0; + size_t nameLen = 0; + + if (header) { + // TODO: - consider the control buffer options + nameLen = header->msg_namelen; + header->msg_namelen = 0; + header->msg_flags = 0; + } if (buffer == NULL) return 0; - size_t bufferSize = buffer->size, bytesReceived = 0; - for (i = 0; i < header->msg_iovlen && bytesReceived < bufferSize; i++) { - if (user_memcpy(&tmp, header->msg_iov + i, sizeof(iovec)) < B_OK) - break; + size_t bytesReceived = buffer->size, bytesCopied = 0; - size_t toRead = min_c(bufferSize - bytesReceived, tmp.iov_len); - if (gNetBufferModule.read(buffer, bytesReceived, tmp.iov_base, - toRead) < B_OK) - break; - - bytesReceived += toRead; + length = min_c(bytesReceived, length); + if (gNetBufferModule.read(buffer, 0, data, length) < B_OK) { + gNetBufferModule.free(buffer); + return ENOBUFS; } - if (bytesReceived == bufferSize && header->msg_name != NULL) { - header->msg_namelen = min_c(nameLen, buffer->source.ss_len); - memcpy(header->msg_name, &buffer->source, header->msg_namelen); + // if first copy was a success, proceed to following + // copies as required + bytesCopied += length; + + if (header) { + // we only start considering at iovec[1] + // as { data, length } is iovec[0] + for (i = 1; i < header->msg_iovlen && bytesCopied < bytesReceived; i++) { + if (user_memcpy(&tmp, header->msg_iov + i, sizeof(iovec)) < B_OK) + break; + + size_t toRead = min_c(bytesReceived - bytesCopied, tmp.iov_len); + if (gNetBufferModule.read(buffer, bytesCopied, tmp.iov_base, + toRead) < B_OK) + break; + + bytesCopied += toRead; + } + + if (bytesCopied == bytesReceived && header->msg_name != NULL) { + header->msg_namelen = min_c(nameLen, buffer->source.ss_len); + memcpy(header->msg_name, &buffer->source, header->msg_namelen); + } } gNetBufferModule.free(buffer); - if (bytesReceived < bufferSize) + if (bytesCopied < bytesReceived) return ENOBUFS; - return bytesReceived; + return bytesCopied; } ssize_t -socket_send(net_socket *socket, const void *data, size_t length, int flags) +socket_send(net_socket *socket, msghdr *header, const void *data, + size_t length, int flags) { - if (socket->peer.ss_len == 0) - return EDESTADDRREQ; + const sockaddr *address = NULL; + socklen_t addressLength = 0; - if (socket->address.ss_len == 0) { - // try to bind first - status_t status = socket_bind(socket, NULL, 0); - if (status < B_OK) - return status; + // the convention to this function is that have header been + // present, { data, length } would have been iovec[0] and is + // always considered like that + + if (header != NULL) { + address = (const sockaddr *)header->msg_name; + addressLength = header->msg_namelen; + + if (header->msg_iovlen <= 1) + header = NULL; } - // TODO: useful, maybe even computed header space! - net_buffer *buffer = gNetBufferModule.create(256); - if (buffer == NULL) - return ENOBUFS; - - // copy data into buffer - if (gNetBufferModule.append(buffer, data, length) < B_OK) { - gNetBufferModule.free(buffer); - return ENOBUFS; - } - - buffer->flags = flags; - memcpy(&buffer->source, &socket->address, socket->address.ss_len); - memcpy(&buffer->destination, &socket->peer, socket->peer.ss_len); - - status_t status = socket->first_info->send_data(socket->first_protocol, - buffer); - if (status < B_OK) { - size_t size = buffer->size; - gNetBufferModule.free(buffer); - - if (size != length && (status == B_INTERRUPTED || status == B_WOULD_BLOCK)) { - // this appears to be a partial write - return length - size; - } - - return status; - } - - return length; -} - - -ssize_t -socket_sendto(net_socket *socket, const void *data, size_t length, int flags, - const struct sockaddr *address, socklen_t addressLength) -{ - iovec iov = { (void *)data, length }; - msghdr header; - - memset(&header, 0, sizeof(header)); - header.msg_name = (char *)address; - header.msg_namelen = addressLength; - header.msg_iov = &iov; - header.msg_iovlen = 1; - - return socket_sendmsg(socket, &header, flags); -} - - -ssize_t -socket_sendmsg(net_socket *socket, msghdr *header, int flags) -{ - const sockaddr *address = (const sockaddr *)header->msg_name; - socklen_t addressLength = header->msg_namelen; - if (addressLength == 0) address = NULL; else if (addressLength != 0 && address == NULL) @@ -922,6 +853,7 @@ socket_sendmsg(net_socket *socket, msghdr *header, int flags) address = (struct sockaddr *)&socket->peer; addressLength = socket->peer.ss_len; } + if (address == NULL || addressLength == 0) { // don't know where to send to: return EDESTADDRREQ; @@ -939,18 +871,23 @@ socket_sendmsg(net_socket *socket, msghdr *header, int flags) if (buffer == NULL) return ENOBUFS; - size_t length = 0; + if (gNetBufferModule.append(buffer, data, length) < B_OK) { + gNetBufferModule.free(buffer); + return ENOBUFS; + } - // copy data into buffer - for (int i = 0; i < header->msg_iovlen; i++) { - iovec tmp; - if (user_memcpy(&tmp, header->msg_iov + i, sizeof(iovec)) < B_OK || - gNetBufferModule.append(buffer, tmp.iov_base, tmp.iov_len) < B_OK) { - gNetBufferModule.free(buffer); - return ENOBUFS; + if (header) { + // copy additional data into buffer + for (int i = 1; i < header->msg_iovlen; i++) { + iovec tmp; + if (user_memcpy(&tmp, header->msg_iov + i, sizeof(iovec)) < B_OK || + gNetBufferModule.append(buffer, tmp.iov_base, tmp.iov_len) < B_OK) { + gNetBufferModule.free(buffer); + return ENOBUFS; + } + + length += tmp.iov_len; } - - length += tmp.iov_len; } buffer->flags = flags; @@ -1167,12 +1104,8 @@ net_socket_module_info gNetSocketModule = { socket_getsockname, socket_getsockopt, socket_listen, - socket_recv, - socket_recvfrom, - socket_recvmsg, + socket_receive, socket_send, - socket_sendto, - socket_sendmsg, socket_setsockopt, socket_shutdown, }; diff --git a/src/bin/strace/NetworkTypes.cpp b/src/bin/strace/NetworkTypes.cpp index 38702758d6..1cf9875a85 100644 --- a/src/bin/strace/NetworkTypes.cpp +++ b/src/bin/strace/NetworkTypes.cpp @@ -226,19 +226,6 @@ format_pointer(Context &context, sockaddr_args *args) return r; } -static string -format_pointer(Context &context, transfer_args *args) -{ - string r; - - r = "data = " + context.FormatPointer(args->data); - r += ", len = " + context.FormatUnsigned(args->data_length); - r += ", flags = " + context.FormatFlags(args->flags); - r += ", addr = " + format_pointer_value(context, args->address); - - return r; -} - struct socket_option_info { int level; int option; @@ -475,7 +462,6 @@ class SpecializedPointerTypeHandler : public TypeHandler { DEFINE_TYPE(fdset_ptr, fd_set *); POINTER_TYPE(sockaddr_args_ptr, sockaddr_args); -POINTER_TYPE(transfer_args_ptr, transfer_args); POINTER_TYPE(sockopt_args_ptr, sockopt_args); POINTER_TYPE(socket_args_ptr, socket_args); POINTER_TYPE(msghdr_ptr, msghdr); diff --git a/src/bin/strace/TypeHandler.h b/src/bin/strace/TypeHandler.h index 71a51dd009..5bd4306895 100644 --- a/src/bin/strace/TypeHandler.h +++ b/src/bin/strace/TypeHandler.h @@ -103,11 +103,9 @@ struct ifreq; struct sockaddr_args; struct socket_args; struct sockopt_args; -struct transfer_args; DEFINE_FACTORY(fdset_ptr, fd_set *); DEFINE_FACTORY(sockaddr_args_ptr, sockaddr_args *); -DEFINE_FACTORY(transfer_args_ptr, transfer_args *); DEFINE_FACTORY(sockopt_args_ptr, sockopt_args *); DEFINE_FACTORY(socket_args_ptr, socket_args *); DEFINE_FACTORY(ifreq_ptr, ifreq *); diff --git a/src/bin/strace/ioctl.cpp b/src/bin/strace/ioctl.cpp index fa47568e3a..18b1d1307e 100644 --- a/src/bin/strace/ioctl.cpp +++ b/src/bin/strace/ioctl.cpp @@ -33,10 +33,8 @@ static const ioctl_info kIOCtls[] = { IOCTL_INFO_ENTRY(NET_STACK_CONTROL_NET_MODULE), IOCTL_INFO_ENTRY(NET_STACK_GET_NEXT_STAT), IOCTL_INFO_ENTRY_TYPE(NET_STACK_BIND, struct sockaddr_args *), - IOCTL_INFO_ENTRY_TYPE(NET_STACK_RECVFROM, struct transfer_args *), - IOCTL_INFO_ENTRY_TYPE(NET_STACK_RECV, struct transfer_args *), - IOCTL_INFO_ENTRY_TYPE(NET_STACK_SENDTO, struct transfer_args *), - IOCTL_INFO_ENTRY_TYPE(NET_STACK_SEND, struct transfer_args *), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_RECEIVE, struct message_args *), + IOCTL_INFO_ENTRY_TYPE(NET_STACK_SEND, struct message_args *), IOCTL_INFO_ENTRY(NET_STACK_LISTEN), IOCTL_INFO_ENTRY(NET_STACK_ACCEPT), IOCTL_INFO_ENTRY_TYPE(NET_STACK_CONNECT, struct sockaddr_args *), diff --git a/src/kits/network/socket.cpp b/src/kits/network/socket.cpp index ac779835d7..00f59907e1 100644 --- a/src/kits/network/socket.cpp +++ b/src/kits/network/socket.cpp @@ -292,14 +292,13 @@ accept(int socket, struct sockaddr *address, socklen_t *_addressLength) extern "C" ssize_t recv(int socket, void *data, size_t length, int flags) { - transfer_args args; + message_args args; args.data = data; - args.data_length = length; + args.length = length; args.flags = flags; - args.address = NULL; - args.address_length = 0; + args.header = NULL; - return ioctl(socket, NET_STACK_RECV, &args, sizeof(args)); + return ioctl(socket, NET_STACK_RECEIVE, &args, sizeof(args)); } @@ -310,20 +309,24 @@ recvfrom(int socket, void *data, size_t length, int flags, bool r5compatible = check_r5_compatibility(); struct sockaddr r5addr; - transfer_args args; + message_args args; args.data = data; - args.data_length = length; + args.length = length; args.flags = flags; + msghdr header; + memset(&header, 0, sizeof(header)); + args.header = &header; + if (r5compatible) { - args.address = &r5addr; - args.address_length = sizeof(r5addr); + header.msg_name = (char *)&r5addr; + header.msg_namelen = sizeof(r5addr); } else { - args.address = address; - args.address_length = _addressLength ? *_addressLength : 0; + header.msg_name = (char *)address; + header.msg_namelen = _addressLength ? *_addressLength : 0; } - ssize_t bytesReceived = ioctl(socket, NET_STACK_RECVFROM, &args, sizeof(args)); + ssize_t bytesReceived = ioctl(socket, NET_STACK_RECEIVE, &args, sizeof(args)); if (bytesReceived < 0) return -1; @@ -332,7 +335,7 @@ recvfrom(int socket, void *data, size_t length, int flags, if (_addressLength != NULL) *_addressLength = sizeof(struct r5_sockaddr_in); } else if (_addressLength != NULL) - *_addressLength = args.address_length; + *_addressLength = header.msg_namelen; return bytesReceived; } @@ -341,20 +344,34 @@ recvfrom(int socket, void *data, size_t length, int flags, extern "C" ssize_t recvmsg(int socket, struct msghdr *message, int flags) { - msghdr_args args = { message, flags }; - return ioctl(socket, NET_STACK_RECVMSG, &args, sizeof(args)); + message_args args; + + if (message == NULL || (message->msg_iovlen > 0 && message->msg_iov == NULL)) + return B_BAD_VALUE; + + args.header = message; + args.flags = flags; + + if (message->msg_iovlen > 0) { + args.data = message->msg_iov[0].iov_base; + args.length = message->msg_iov[0].iov_len; + } else { + args.data = NULL; + args.length = 0; + } + + return ioctl(socket, NET_STACK_RECEIVE, &args, sizeof(args)); } extern "C" ssize_t send(int socket, const void *data, size_t length, int flags) { - transfer_args args; + message_args args; args.data = const_cast(data); - args.data_length = length; + args.length = length; args.flags = flags; - args.address = NULL; - args.address_length = 0; + args.header = NULL; return ioctl(socket, NET_STACK_SEND, &args, sizeof(args)); } @@ -372,22 +389,41 @@ sendto(int socket, const void *data, size_t length, int flags, addressLength = sizeof(struct sockaddr_in); } - transfer_args args; - args.data = const_cast(data); - args.data_length = length; - args.flags = flags; - args.address = const_cast(address); - args.address_length = addressLength; + message_args args; + msghdr header; + memset(&header, 0, sizeof(header)); - return ioctl(socket, NET_STACK_SENDTO, &args, sizeof(args)); + args.header = &header; + args.data = const_cast(data); + args.length = length; + args.flags = flags; + header.msg_name = (char *)const_cast(address); + header.msg_namelen = addressLength; + + return ioctl(socket, NET_STACK_SEND, &args, sizeof(args)); } extern "C" ssize_t sendmsg(int socket, const struct msghdr *message, int flags) { - msghdr_args args = { (msghdr *)message, flags }; - return ioctl(socket, NET_STACK_SENDMSG, &args, sizeof(args)); + message_args args; + + if (message == NULL || (message->msg_iovlen > 0 && message->msg_iov == NULL)) + return B_BAD_VALUE; + + args.header = const_cast(message); + args.flags = flags; + + if (message->msg_iovlen > 0) { + args.data = message->msg_iov[0].iov_base; + args.length = message->msg_iov[0].iov_len; + } else { + args.data = NULL; + args.length = 0; + } + + return ioctl(socket, NET_STACK_SEND, &args, sizeof(args)); }