diff --git a/headers/private/net/net_protocol.h b/headers/private/net/net_protocol.h index b01a36b739..8d0a26239d 100644 --- a/headers/private/net/net_protocol.h +++ b/headers/private/net/net_protocol.h @@ -101,7 +101,7 @@ struct net_protocol_module_info { status_t (*add_ancillary_data)(net_protocol* self, ancillary_data_container* container, const cmsghdr* header); ssize_t (*process_ancillary_data)(net_protocol* self, - const ancillary_data_header* header, const void* data, + const ancillary_data_container* container, void* buffer, size_t bufferSize); ssize_t (*process_ancillary_data_no_container)(net_protocol* self, net_buffer* buffer, void* data, size_t bufferSize); diff --git a/headers/private/net/net_stack.h b/headers/private/net/net_stack.h index 1ec5e87f01..7120bd096c 100644 --- a/headers/private/net/net_stack.h +++ b/headers/private/net/net_stack.h @@ -180,7 +180,7 @@ struct net_stack_module_info { void* data, bool destroy); void* (*move_ancillary_data)(ancillary_data_container* from, ancillary_data_container* to); - void* (*next_ancillary_data)(ancillary_data_container* container, + void* (*next_ancillary_data)(const ancillary_data_container* container, void* previousData, ancillary_data_header* _header); }; diff --git a/src/add-ons/kernel/network/protocols/unix/unix.cpp b/src/add-ons/kernel/network/protocols/unix/unix.cpp index a7a1d0907c..8f156d8deb 100644 --- a/src/add-ons/kernel/network/protocols/unix/unix.cpp +++ b/src/add-ons/kernel/network/protocols/unix/unix.cpp @@ -353,52 +353,65 @@ unix_add_ancillary_data(net_protocol *self, ancillary_data_container *container, ssize_t unix_process_ancillary_data(net_protocol *self, - const ancillary_data_header *header, const void *data, void *buffer, + const ancillary_data_container *container, void *buffer, size_t bufferSize) { - TRACE("[%" B_PRId32 "] unix_process_ancillary_data(%p, %p (level: %d, " - "type: %d, len: %lu), %p, %p, %lu)\n", find_thread(NULL), self, header, - header->level, header->type, header->len, data, buffer, bufferSize); + TRACE("[%" B_PRId32 "] unix_process_ancillary_data(%p, %p, %p, %p, %lu)\n", + find_thread(NULL), self, container, buffer, bufferSize); - // we support only SCM_RIGHTS - if (header->level != SOL_SOCKET || header->type != SCM_RIGHTS) - return B_BAD_VALUE; + int totalCount = 0; - int count = header->len / sizeof(file_descriptor*); - file_descriptor** descriptors = (file_descriptor**)data; + ancillary_data_header header; + void* data = NULL; + while ((data = gStackModule->next_ancillary_data(container, data, &header)) != NULL) { + // we support only SCM_RIGHTS + if (header.level != SOL_SOCKET || header.type != SCM_RIGHTS) + return B_BAD_VALUE; + + totalCount += header.len / sizeof(file_descriptor*); + } // check if there's enough space in the buffer - size_t neededBufferSpace = CMSG_SPACE(sizeof(int) * count); + size_t neededBufferSpace = CMSG_SPACE(sizeof(int) * totalCount); if (bufferSize < neededBufferSpace) return B_BAD_VALUE; // init header cmsghdr* messageHeader = (cmsghdr*)buffer; - messageHeader->cmsg_level = header->level; - messageHeader->cmsg_type = header->type; - messageHeader->cmsg_len = CMSG_LEN(sizeof(int) * count); + messageHeader->cmsg_level = SOL_SOCKET; + messageHeader->cmsg_type = SCM_RIGHTS; + messageHeader->cmsg_len = CMSG_LEN(sizeof(int) * totalCount); // create FDs for the current process int* fds = (int*)CMSG_DATA(messageHeader); io_context* ioContext = get_current_io_context(!gStackModule->is_syscall()); status_t error = B_OK; - for (int i = 0; i < count; i++) { - // Get an additional reference which will go to the FD table index. The - // reference and open reference acquired in unix_add_ancillary_data() - // will be released when the container is destroyed. - inc_fd_ref_count(descriptors[i]); - fds[i] = new_fd(ioContext, descriptors[i]); + int i = 0; + data = NULL; + while ((data = gStackModule->next_ancillary_data(container, data, &header)) != NULL) { + int count = header.len / sizeof(file_descriptor*); + file_descriptor** descriptors = (file_descriptor**)data; - if (fds[i] < 0) { - error = fds[i]; - put_fd(descriptors[i]); + for (int k = 0; k < count; k++, i++) { + // Get an additional reference which will go to the FD table index. The + // reference and open reference acquired in unix_add_ancillary_data() + // will be released when the container is destroyed. + inc_fd_ref_count(descriptors[k]); + fds[i] = new_fd(ioContext, descriptors[k]); - // close FD indices - for (int k = i - 1; k >= 0; k--) - close_fd_index(ioContext, fds[k]); - break; + if (fds[i] < 0) { + error = fds[i]; + put_fd(descriptors[k]); + + // close FD indices + for (int j = i - 1; j >= 0; j--) + close_fd_index(ioContext, fds[j]); + break; + } } + if (error != B_OK) + break; } return error == B_OK ? neededBufferSpace : error; diff --git a/src/add-ons/kernel/network/stack/ancillary_data.cpp b/src/add-ons/kernel/network/stack/ancillary_data.cpp index d5baf68375..ba1e276d94 100644 --- a/src/add-ons/kernel/network/stack/ancillary_data.cpp +++ b/src/add-ons/kernel/network/stack/ancillary_data.cpp @@ -183,7 +183,7 @@ move_ancillary_data(ancillary_data_container* from, the last one. */ void* -next_ancillary_data(ancillary_data_container* container, void* previousData, +next_ancillary_data(const ancillary_data_container* container, void* previousData, ancillary_data_header* _header) { ancillary_data *ancillaryData; diff --git a/src/add-ons/kernel/network/stack/ancillary_data.h b/src/add-ons/kernel/network/stack/ancillary_data.h index cd194ccffb..fd012ba983 100644 --- a/src/add-ons/kernel/network/stack/ancillary_data.h +++ b/src/add-ons/kernel/network/stack/ancillary_data.h @@ -22,7 +22,7 @@ status_t remove_ancillary_data(ancillary_data_container* container, void* data, void* move_ancillary_data(ancillary_data_container* from, ancillary_data_container* to); -void* next_ancillary_data(ancillary_data_container* container, +void* next_ancillary_data(const ancillary_data_container* container, void* previousData, ancillary_data_header* _header); diff --git a/src/add-ons/kernel/network/stack/net_socket.cpp b/src/add-ons/kernel/network/stack/net_socket.cpp index f6d588f509..e431c4d6cd 100644 --- a/src/add-ons/kernel/network/stack/net_socket.cpp +++ b/src/add-ons/kernel/network/stack/net_socket.cpp @@ -243,24 +243,15 @@ process_ancillary_data(net_socket* socket, ancillary_data_container* container, return B_OK; } - ancillary_data_header header; - void* data = NULL; + if (socket->first_info->process_ancillary_data == NULL) + return B_NOT_SUPPORTED; - while ((data = next_ancillary_data(container, data, &header)) != NULL) { - if (socket->first_info->process_ancillary_data == NULL) - return B_NOT_SUPPORTED; - - ssize_t bytesWritten = socket->first_info->process_ancillary_data( - socket->first_protocol, &header, data, dataBuffer, dataBufferLen); - if (bytesWritten < 0) - return bytesWritten; - - dataBuffer += bytesWritten; - dataBufferLen -= bytesWritten; - } - - messageHeader->msg_controllen -= dataBufferLen; + ssize_t bytesWritten = socket->first_info->process_ancillary_data( + socket->first_protocol, container, dataBuffer, dataBufferLen); + if (bytesWritten < 0) + return bytesWritten; + messageHeader->msg_controllen = bytesWritten; return B_OK; }