consolidate all RECV/SEND ioctls into a single RECEIVE/SEND pair
- changed the socket module to use thew new RECEIVE/SEND in all forms of recv() and send() - changed libnetwork to use the new RECEIVE/SEND - remove transfer_args processing from strace since the structure was removed git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20581 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -89,14 +89,10 @@ struct net_socket_module_info {
|
|||||||
int (*getsockopt)(net_socket *socket, int level, int option,
|
int (*getsockopt)(net_socket *socket, int level, int option,
|
||||||
void *optionValue, int *_optionLength);
|
void *optionValue, int *_optionLength);
|
||||||
int (*listen)(net_socket *socket, int backlog);
|
int (*listen)(net_socket *socket, int backlog);
|
||||||
ssize_t (*recv)(net_socket *socket, void *data, size_t length, int flags);
|
ssize_t (*receive)(net_socket *socket, struct msghdr *, void *data,
|
||||||
ssize_t (*recvfrom)(net_socket *socket, void *data, size_t length, int flags,
|
size_t length, int flags);
|
||||||
struct sockaddr *address, socklen_t *_addressLength);
|
ssize_t (*send)(net_socket *socket, struct msghdr *, const void *data,
|
||||||
ssize_t (*recvmsg)(net_socket *socket, msghdr *header, int flags);
|
size_t length, 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);
|
|
||||||
int (*setsockopt)(net_socket *socket, int level, int option,
|
int (*setsockopt)(net_socket *socket, int level, int option,
|
||||||
const void *optionValue, int optionLength);
|
const void *optionValue, int optionLength);
|
||||||
int (*shutdown)(net_socket *socket, int direction);
|
int (*shutdown)(net_socket *socket, int direction);
|
||||||
|
|||||||
@@ -29,12 +29,8 @@ enum {
|
|||||||
|
|
||||||
// ops acting on an existing socket
|
// ops acting on an existing socket
|
||||||
NET_STACK_BIND, // sockaddr_args *
|
NET_STACK_BIND, // sockaddr_args *
|
||||||
NET_STACK_RECVFROM, // struct msghdr *
|
NET_STACK_RECEIVE, // message_args *
|
||||||
NET_STACK_RECV, // transfer_args *
|
NET_STACK_SEND, // message_args *
|
||||||
NET_STACK_RECVMSG, // msghdr_args *
|
|
||||||
NET_STACK_SENDTO, // struct msghdr *
|
|
||||||
NET_STACK_SEND, // transfer_args *
|
|
||||||
NET_STACK_SENDMSG, // msghdr_args *
|
|
||||||
NET_STACK_LISTEN, // int_args * (value = backlog)
|
NET_STACK_LISTEN, // int_args * (value = backlog)
|
||||||
NET_STACK_ACCEPT, // sockaddr_args *
|
NET_STACK_ACCEPT, // sockaddr_args *
|
||||||
NET_STACK_CONNECT, // sockaddr_args *
|
NET_STACK_CONNECT, // sockaddr_args *
|
||||||
@@ -62,16 +58,10 @@ struct sockopt_args { // used by NET_STACK_SETSOCKOPT/_GETSOCKOPT
|
|||||||
int length;
|
int length;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct transfer_args { // used by NET_STACK_SEND/_RECV
|
struct message_args {
|
||||||
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 msghdr *header;
|
struct msghdr *header;
|
||||||
|
void *data;
|
||||||
|
size_t length;
|
||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -90,35 +90,40 @@ check_args_and_address(ArgType &args, sockaddr_storage &address, void *data, siz
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
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)
|
void *data, size_t length, sockaddr **originalAddress)
|
||||||
{
|
{
|
||||||
if (length < sizeof(msghdr_args))
|
if (length < sizeof(message_args))
|
||||||
return B_BAD_VALUE;
|
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)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = user_memcpy(&header, args.header, sizeof(msghdr));
|
if (args.header != NULL) {
|
||||||
if (status < B_OK)
|
status = user_memcpy(&header, args.header, sizeof(msghdr));
|
||||||
return status;
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
if (originalAddress == NULL) {
|
if (header.msg_name == NULL)
|
||||||
if (header.msg_namelen > sizeof(address))
|
return B_OK;
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
if (header.msg_name != NULL) {
|
if (originalAddress == NULL) {
|
||||||
status = user_memcpy(&address, header.msg_name, header.msg_namelen);
|
if (header.msg_namelen > sizeof(address))
|
||||||
if (status < B_OK)
|
return B_BAD_VALUE;
|
||||||
return B_BAD_ADDRESS;
|
|
||||||
|
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;
|
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);
|
return sSocket->shutdown(cookie->socket, (int)data);
|
||||||
|
|
||||||
case NET_STACK_SEND:
|
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;
|
sockaddr_storage address;
|
||||||
transfer_args args;
|
message_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;
|
|
||||||
msghdr header;
|
msghdr header;
|
||||||
|
|
||||||
status = check_msghdr_args(args, header, address, data,
|
status = check_message_args(args, header, address, data,
|
||||||
length, NULL);
|
length, NULL);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
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:
|
case NET_STACK_RECEIVE:
|
||||||
{
|
|
||||||
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:
|
|
||||||
{
|
{
|
||||||
|
sockaddr *originalAddress = NULL;
|
||||||
sockaddr_storage address;
|
sockaddr_storage address;
|
||||||
transfer_args args;
|
message_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;
|
|
||||||
msghdr header;
|
msghdr header;
|
||||||
|
|
||||||
status = check_msghdr_args(args, header, address, data,
|
status = check_message_args(args, header, address, data,
|
||||||
length, &originalAddress);
|
length, &originalAddress);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
ssize_t bytesRead = sSocket->recvmsg(cookie->socket, &header,
|
ssize_t bytesRead = sSocket->receive(cookie->socket,
|
||||||
args.flags);
|
args.header ? &header : NULL, args.data,
|
||||||
|
args.length, args.flags);
|
||||||
if (bytesRead < B_OK)
|
if (bytesRead < B_OK)
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
|
|
||||||
if (header.msg_name != NULL) {
|
if (args.header != NULL) {
|
||||||
if (user_memcpy(originalAddress, header.msg_name,
|
if (header.msg_name != NULL) {
|
||||||
header.msg_namelen) < B_OK)
|
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;
|
return B_BAD_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user_memcpy(&args.header->msg_flags, &header.msg_flags,
|
|
||||||
sizeof(int)) < B_OK)
|
|
||||||
return B_BAD_ADDRESS;
|
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,7 +532,7 @@ net_stack_read(void *_cookie, off_t /*offset*/, void *buffer, size_t *_length)
|
|||||||
if (cookie->socket == NULL)
|
if (cookie->socket == NULL)
|
||||||
return B_BAD_VALUE;
|
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) {
|
if (bytesRead < 0) {
|
||||||
*_length = 0;
|
*_length = 0;
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
@@ -608,7 +568,7 @@ net_stack_write(void *_cookie, off_t /*offset*/, const void *buffer, size_t *_le
|
|||||||
if (cookie->socket == NULL)
|
if (cookie->socket == NULL)
|
||||||
return B_BAD_VALUE;
|
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) {
|
if (bytesWritten < 0) {
|
||||||
*_length = 0;
|
*_length = 0;
|
||||||
return bytesWritten;
|
return bytesWritten;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <net_stack_driver.h>
|
#include <net_stack_driver.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@@ -113,14 +114,13 @@ accept(int socket, struct sockaddr *address, socklen_t *_addressLength)
|
|||||||
ssize_t
|
ssize_t
|
||||||
recv(int socket, void *data, size_t length, int flags)
|
recv(int socket, void *data, size_t length, int flags)
|
||||||
{
|
{
|
||||||
transfer_args args;
|
message_args args;
|
||||||
args.data = data;
|
args.data = data;
|
||||||
args.data_length = length;
|
args.length = length;
|
||||||
args.flags = flags;
|
args.flags = flags;
|
||||||
args.address = NULL;
|
args.header = NULL;
|
||||||
args.address_length = 0;
|
|
||||||
|
|
||||||
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,
|
recvfrom(int socket, void *data, size_t length, int flags,
|
||||||
struct sockaddr *address, socklen_t *_addressLength)
|
struct sockaddr *address, socklen_t *_addressLength)
|
||||||
{
|
{
|
||||||
transfer_args args;
|
message_args args;
|
||||||
args.data = data;
|
msghdr header;
|
||||||
args.data_length = length;
|
|
||||||
args.flags = flags;
|
|
||||||
args.address = address;
|
|
||||||
args.address_length = _addressLength ? *_addressLength : 0;
|
|
||||||
|
|
||||||
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)
|
if (bytesReceived < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (_addressLength != NULL)
|
if (_addressLength != NULL)
|
||||||
*_addressLength = args.address_length;
|
*_addressLength = header.msg_namelen;
|
||||||
|
|
||||||
return bytesReceived;
|
return bytesReceived;
|
||||||
}
|
}
|
||||||
@@ -149,20 +155,34 @@ recvfrom(int socket, void *data, size_t length, int flags,
|
|||||||
ssize_t
|
ssize_t
|
||||||
recvmsg(int socket, struct msghdr *message, int flags)
|
recvmsg(int socket, struct msghdr *message, int flags)
|
||||||
{
|
{
|
||||||
msghdr_args args = { message, flags };
|
message_args args;
|
||||||
return ioctl(socket, NET_STACK_RECVMSG, &args, sizeof(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
|
ssize_t
|
||||||
send(int socket, const void *data, size_t length, int flags)
|
send(int socket, const void *data, size_t length, int flags)
|
||||||
{
|
{
|
||||||
transfer_args args;
|
message_args args;
|
||||||
args.data = const_cast<void *>(data);
|
args.data = const_cast<void *>(data);
|
||||||
args.data_length = length;
|
args.length = length;
|
||||||
args.flags = flags;
|
args.flags = flags;
|
||||||
args.address = NULL;
|
args.header = NULL;
|
||||||
args.address_length = 0;
|
|
||||||
|
|
||||||
return ioctl(socket, NET_STACK_SEND, &args, sizeof(args));
|
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,
|
sendto(int socket, const void *data, size_t length, int flags,
|
||||||
const struct sockaddr *address, socklen_t addressLength)
|
const struct sockaddr *address, socklen_t addressLength)
|
||||||
{
|
{
|
||||||
transfer_args args;
|
message_args args;
|
||||||
args.data = const_cast<void *>(data);
|
msghdr header;
|
||||||
args.data_length = length;
|
memset(&header, 0, sizeof(header));
|
||||||
args.flags = flags;
|
|
||||||
args.address = const_cast<sockaddr *>(address);
|
|
||||||
args.address_length = addressLength;
|
|
||||||
|
|
||||||
return ioctl(socket, NET_STACK_SENDTO, &args, sizeof(args));
|
args.data = const_cast<void *>(data);
|
||||||
|
args.length = length;
|
||||||
|
args.flags = flags;
|
||||||
|
args.header = &header;
|
||||||
|
header.msg_name = (char *)const_cast<sockaddr *>(address);
|
||||||
|
header.msg_namelen = addressLength;
|
||||||
|
|
||||||
|
return ioctl(socket, NET_STACK_SEND, &args, sizeof(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
sendmsg(int socket, const struct msghdr *message, int flags)
|
sendmsg(int socket, const struct msghdr *message, int flags)
|
||||||
{
|
{
|
||||||
msghdr_args args = { (msghdr *)message, flags };
|
message_args args;
|
||||||
return ioctl(socket, NET_STACK_SENDMSG, &args, sizeof(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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ struct net_socket_private : net_socket {
|
|||||||
|
|
||||||
void socket_delete(net_socket *socket);
|
void socket_delete(net_socket *socket);
|
||||||
int socket_bind(net_socket *socket, const struct sockaddr *address, socklen_t addressLength);
|
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;
|
struct list sSocketList;
|
||||||
benaphore sSocketLock;
|
benaphore sSocketLock;
|
||||||
@@ -735,180 +733,113 @@ socket_listen(net_socket *socket, int backlog)
|
|||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
socket_recv(net_socket *socket, void *data, size_t length, int flags)
|
socket_receive(net_socket *socket, msghdr *header, 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)
|
|
||||||
{
|
{
|
||||||
|
size_t totalLength = length;
|
||||||
net_buffer *buffer;
|
net_buffer *buffer;
|
||||||
iovec tmp;
|
iovec tmp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
size_t length = 0;
|
// the convention to this function is that have header been
|
||||||
for (i = 0; i < header->msg_iovlen; i++) {
|
// present, { data, length } would have been iovec[0] and is
|
||||||
if (user_memcpy(&tmp, header->msg_iov + i, sizeof(iovec)) < B_OK)
|
// always considered like that
|
||||||
return B_BAD_ADDRESS;
|
|
||||||
if (tmp.iov_len > 0 && tmp.iov_base == NULL)
|
if (header) {
|
||||||
return B_BAD_ADDRESS;
|
// calculate the length considering all of the extra buffers
|
||||||
length += tmp.iov_len;
|
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(
|
status_t status = socket->first_info->read_data(
|
||||||
socket->first_protocol, length, flags, &buffer);
|
socket->first_protocol, totalLength, flags, &buffer);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
// TODO: - consider the control buffer options
|
// TODO: - datagram based protocols should return the
|
||||||
// - datagram based protocols should return the
|
|
||||||
// full datagram so we can cut it here with MSG_TRUNC
|
// full datagram so we can cut it here with MSG_TRUNC
|
||||||
// - returning a NULL buffer when received 0 bytes
|
// - returning a NULL buffer when received 0 bytes
|
||||||
// may not make much sense as we still need the address
|
// may not make much sense as we still need the address
|
||||||
// - gNetBufferModule.read() uses memcpy() instead of user_memcpy
|
// - gNetBufferModule.read() uses memcpy() instead of user_memcpy
|
||||||
|
|
||||||
size_t nameLen = header->msg_namelen;
|
size_t nameLen = 0;
|
||||||
header->msg_namelen = 0;
|
|
||||||
header->msg_flags = 0;
|
if (header) {
|
||||||
|
// TODO: - consider the control buffer options
|
||||||
|
nameLen = header->msg_namelen;
|
||||||
|
header->msg_namelen = 0;
|
||||||
|
header->msg_flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
size_t bufferSize = buffer->size, bytesReceived = 0;
|
size_t bytesReceived = buffer->size, bytesCopied = 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 toRead = min_c(bufferSize - bytesReceived, tmp.iov_len);
|
length = min_c(bytesReceived, length);
|
||||||
if (gNetBufferModule.read(buffer, bytesReceived, tmp.iov_base,
|
if (gNetBufferModule.read(buffer, 0, data, length) < B_OK) {
|
||||||
toRead) < B_OK)
|
gNetBufferModule.free(buffer);
|
||||||
break;
|
return ENOBUFS;
|
||||||
|
|
||||||
bytesReceived += toRead;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytesReceived == bufferSize && header->msg_name != NULL) {
|
// if first copy was a success, proceed to following
|
||||||
header->msg_namelen = min_c(nameLen, buffer->source.ss_len);
|
// copies as required
|
||||||
memcpy(header->msg_name, &buffer->source, header->msg_namelen);
|
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);
|
gNetBufferModule.free(buffer);
|
||||||
|
|
||||||
if (bytesReceived < bufferSize)
|
if (bytesCopied < bytesReceived)
|
||||||
return ENOBUFS;
|
return ENOBUFS;
|
||||||
|
|
||||||
return bytesReceived;
|
return bytesCopied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
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)
|
const sockaddr *address = NULL;
|
||||||
return EDESTADDRREQ;
|
socklen_t addressLength = 0;
|
||||||
|
|
||||||
if (socket->address.ss_len == 0) {
|
// the convention to this function is that have header been
|
||||||
// try to bind first
|
// present, { data, length } would have been iovec[0] and is
|
||||||
status_t status = socket_bind(socket, NULL, 0);
|
// always considered like that
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
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)
|
if (addressLength == 0)
|
||||||
address = NULL;
|
address = NULL;
|
||||||
else 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;
|
address = (struct sockaddr *)&socket->peer;
|
||||||
addressLength = socket->peer.ss_len;
|
addressLength = socket->peer.ss_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address == NULL || addressLength == 0) {
|
if (address == NULL || addressLength == 0) {
|
||||||
// don't know where to send to:
|
// don't know where to send to:
|
||||||
return EDESTADDRREQ;
|
return EDESTADDRREQ;
|
||||||
@@ -939,18 +871,23 @@ socket_sendmsg(net_socket *socket, msghdr *header, int flags)
|
|||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return ENOBUFS;
|
return ENOBUFS;
|
||||||
|
|
||||||
size_t length = 0;
|
if (gNetBufferModule.append(buffer, data, length) < B_OK) {
|
||||||
|
gNetBufferModule.free(buffer);
|
||||||
|
return ENOBUFS;
|
||||||
|
}
|
||||||
|
|
||||||
// copy data into buffer
|
if (header) {
|
||||||
for (int i = 0; i < header->msg_iovlen; i++) {
|
// copy additional data into buffer
|
||||||
iovec tmp;
|
for (int i = 1; i < header->msg_iovlen; i++) {
|
||||||
if (user_memcpy(&tmp, header->msg_iov + i, sizeof(iovec)) < B_OK ||
|
iovec tmp;
|
||||||
gNetBufferModule.append(buffer, tmp.iov_base, tmp.iov_len) < B_OK) {
|
if (user_memcpy(&tmp, header->msg_iov + i, sizeof(iovec)) < B_OK ||
|
||||||
gNetBufferModule.free(buffer);
|
gNetBufferModule.append(buffer, tmp.iov_base, tmp.iov_len) < B_OK) {
|
||||||
return ENOBUFS;
|
gNetBufferModule.free(buffer);
|
||||||
|
return ENOBUFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
length += tmp.iov_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
length += tmp.iov_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer->flags = flags;
|
buffer->flags = flags;
|
||||||
@@ -1167,12 +1104,8 @@ net_socket_module_info gNetSocketModule = {
|
|||||||
socket_getsockname,
|
socket_getsockname,
|
||||||
socket_getsockopt,
|
socket_getsockopt,
|
||||||
socket_listen,
|
socket_listen,
|
||||||
socket_recv,
|
socket_receive,
|
||||||
socket_recvfrom,
|
|
||||||
socket_recvmsg,
|
|
||||||
socket_send,
|
socket_send,
|
||||||
socket_sendto,
|
|
||||||
socket_sendmsg,
|
|
||||||
socket_setsockopt,
|
socket_setsockopt,
|
||||||
socket_shutdown,
|
socket_shutdown,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -226,19 +226,6 @@ format_pointer(Context &context, sockaddr_args *args)
|
|||||||
return r;
|
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<sockaddr>(context, args->address);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct socket_option_info {
|
struct socket_option_info {
|
||||||
int level;
|
int level;
|
||||||
int option;
|
int option;
|
||||||
@@ -475,7 +462,6 @@ class SpecializedPointerTypeHandler : public TypeHandler {
|
|||||||
|
|
||||||
DEFINE_TYPE(fdset_ptr, fd_set *);
|
DEFINE_TYPE(fdset_ptr, fd_set *);
|
||||||
POINTER_TYPE(sockaddr_args_ptr, sockaddr_args);
|
POINTER_TYPE(sockaddr_args_ptr, sockaddr_args);
|
||||||
POINTER_TYPE(transfer_args_ptr, transfer_args);
|
|
||||||
POINTER_TYPE(sockopt_args_ptr, sockopt_args);
|
POINTER_TYPE(sockopt_args_ptr, sockopt_args);
|
||||||
POINTER_TYPE(socket_args_ptr, socket_args);
|
POINTER_TYPE(socket_args_ptr, socket_args);
|
||||||
POINTER_TYPE(msghdr_ptr, msghdr);
|
POINTER_TYPE(msghdr_ptr, msghdr);
|
||||||
|
|||||||
@@ -103,11 +103,9 @@ struct ifreq;
|
|||||||
struct sockaddr_args;
|
struct sockaddr_args;
|
||||||
struct socket_args;
|
struct socket_args;
|
||||||
struct sockopt_args;
|
struct sockopt_args;
|
||||||
struct transfer_args;
|
|
||||||
|
|
||||||
DEFINE_FACTORY(fdset_ptr, fd_set *);
|
DEFINE_FACTORY(fdset_ptr, fd_set *);
|
||||||
DEFINE_FACTORY(sockaddr_args_ptr, sockaddr_args *);
|
DEFINE_FACTORY(sockaddr_args_ptr, sockaddr_args *);
|
||||||
DEFINE_FACTORY(transfer_args_ptr, transfer_args *);
|
|
||||||
DEFINE_FACTORY(sockopt_args_ptr, sockopt_args *);
|
DEFINE_FACTORY(sockopt_args_ptr, sockopt_args *);
|
||||||
DEFINE_FACTORY(socket_args_ptr, socket_args *);
|
DEFINE_FACTORY(socket_args_ptr, socket_args *);
|
||||||
DEFINE_FACTORY(ifreq_ptr, ifreq *);
|
DEFINE_FACTORY(ifreq_ptr, ifreq *);
|
||||||
|
|||||||
@@ -33,10 +33,8 @@ static const ioctl_info kIOCtls[] = {
|
|||||||
IOCTL_INFO_ENTRY(NET_STACK_CONTROL_NET_MODULE),
|
IOCTL_INFO_ENTRY(NET_STACK_CONTROL_NET_MODULE),
|
||||||
IOCTL_INFO_ENTRY(NET_STACK_GET_NEXT_STAT),
|
IOCTL_INFO_ENTRY(NET_STACK_GET_NEXT_STAT),
|
||||||
IOCTL_INFO_ENTRY_TYPE(NET_STACK_BIND, struct sockaddr_args *),
|
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_RECEIVE, struct message_args *),
|
||||||
IOCTL_INFO_ENTRY_TYPE(NET_STACK_RECV, struct transfer_args *),
|
IOCTL_INFO_ENTRY_TYPE(NET_STACK_SEND, struct message_args *),
|
||||||
IOCTL_INFO_ENTRY_TYPE(NET_STACK_SENDTO, struct transfer_args *),
|
|
||||||
IOCTL_INFO_ENTRY_TYPE(NET_STACK_SEND, struct transfer_args *),
|
|
||||||
IOCTL_INFO_ENTRY(NET_STACK_LISTEN),
|
IOCTL_INFO_ENTRY(NET_STACK_LISTEN),
|
||||||
IOCTL_INFO_ENTRY(NET_STACK_ACCEPT),
|
IOCTL_INFO_ENTRY(NET_STACK_ACCEPT),
|
||||||
IOCTL_INFO_ENTRY_TYPE(NET_STACK_CONNECT, struct sockaddr_args *),
|
IOCTL_INFO_ENTRY_TYPE(NET_STACK_CONNECT, struct sockaddr_args *),
|
||||||
|
|||||||
+64
-28
@@ -292,14 +292,13 @@ accept(int socket, struct sockaddr *address, socklen_t *_addressLength)
|
|||||||
extern "C" ssize_t
|
extern "C" ssize_t
|
||||||
recv(int socket, void *data, size_t length, int flags)
|
recv(int socket, void *data, size_t length, int flags)
|
||||||
{
|
{
|
||||||
transfer_args args;
|
message_args args;
|
||||||
args.data = data;
|
args.data = data;
|
||||||
args.data_length = length;
|
args.length = length;
|
||||||
args.flags = flags;
|
args.flags = flags;
|
||||||
args.address = NULL;
|
args.header = NULL;
|
||||||
args.address_length = 0;
|
|
||||||
|
|
||||||
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();
|
bool r5compatible = check_r5_compatibility();
|
||||||
struct sockaddr r5addr;
|
struct sockaddr r5addr;
|
||||||
|
|
||||||
transfer_args args;
|
message_args args;
|
||||||
args.data = data;
|
args.data = data;
|
||||||
args.data_length = length;
|
args.length = length;
|
||||||
args.flags = flags;
|
args.flags = flags;
|
||||||
|
|
||||||
|
msghdr header;
|
||||||
|
memset(&header, 0, sizeof(header));
|
||||||
|
args.header = &header;
|
||||||
|
|
||||||
if (r5compatible) {
|
if (r5compatible) {
|
||||||
args.address = &r5addr;
|
header.msg_name = (char *)&r5addr;
|
||||||
args.address_length = sizeof(r5addr);
|
header.msg_namelen = sizeof(r5addr);
|
||||||
} else {
|
} else {
|
||||||
args.address = address;
|
header.msg_name = (char *)address;
|
||||||
args.address_length = _addressLength ? *_addressLength : 0;
|
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)
|
if (bytesReceived < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -332,7 +335,7 @@ recvfrom(int socket, void *data, size_t length, int flags,
|
|||||||
if (_addressLength != NULL)
|
if (_addressLength != NULL)
|
||||||
*_addressLength = sizeof(struct r5_sockaddr_in);
|
*_addressLength = sizeof(struct r5_sockaddr_in);
|
||||||
} else if (_addressLength != NULL)
|
} else if (_addressLength != NULL)
|
||||||
*_addressLength = args.address_length;
|
*_addressLength = header.msg_namelen;
|
||||||
|
|
||||||
return bytesReceived;
|
return bytesReceived;
|
||||||
}
|
}
|
||||||
@@ -341,20 +344,34 @@ recvfrom(int socket, void *data, size_t length, int flags,
|
|||||||
extern "C" ssize_t
|
extern "C" ssize_t
|
||||||
recvmsg(int socket, struct msghdr *message, int flags)
|
recvmsg(int socket, struct msghdr *message, int flags)
|
||||||
{
|
{
|
||||||
msghdr_args args = { message, flags };
|
message_args args;
|
||||||
return ioctl(socket, NET_STACK_RECVMSG, &args, sizeof(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
|
extern "C" ssize_t
|
||||||
send(int socket, const void *data, size_t length, int flags)
|
send(int socket, const void *data, size_t length, int flags)
|
||||||
{
|
{
|
||||||
transfer_args args;
|
message_args args;
|
||||||
args.data = const_cast<void *>(data);
|
args.data = const_cast<void *>(data);
|
||||||
args.data_length = length;
|
args.length = length;
|
||||||
args.flags = flags;
|
args.flags = flags;
|
||||||
args.address = NULL;
|
args.header = NULL;
|
||||||
args.address_length = 0;
|
|
||||||
|
|
||||||
return ioctl(socket, NET_STACK_SEND, &args, sizeof(args));
|
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);
|
addressLength = sizeof(struct sockaddr_in);
|
||||||
}
|
}
|
||||||
|
|
||||||
transfer_args args;
|
message_args args;
|
||||||
args.data = const_cast<void *>(data);
|
msghdr header;
|
||||||
args.data_length = length;
|
memset(&header, 0, sizeof(header));
|
||||||
args.flags = flags;
|
|
||||||
args.address = const_cast<sockaddr *>(address);
|
|
||||||
args.address_length = addressLength;
|
|
||||||
|
|
||||||
return ioctl(socket, NET_STACK_SENDTO, &args, sizeof(args));
|
args.header = &header;
|
||||||
|
args.data = const_cast<void *>(data);
|
||||||
|
args.length = length;
|
||||||
|
args.flags = flags;
|
||||||
|
header.msg_name = (char *)const_cast<sockaddr *>(address);
|
||||||
|
header.msg_namelen = addressLength;
|
||||||
|
|
||||||
|
return ioctl(socket, NET_STACK_SEND, &args, sizeof(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" ssize_t
|
extern "C" ssize_t
|
||||||
sendmsg(int socket, const struct msghdr *message, int flags)
|
sendmsg(int socket, const struct msghdr *message, int flags)
|
||||||
{
|
{
|
||||||
msghdr_args args = { (msghdr *)message, flags };
|
message_args args;
|
||||||
return ioctl(socket, NET_STACK_SENDMSG, &args, sizeof(args));
|
|
||||||
|
if (message == NULL || (message->msg_iovlen > 0 && message->msg_iov == NULL))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
args.header = const_cast<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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user