Applied patch by Ma Jie adding functionality needed by mDNSResponder:
* added new protocol method process_ancillary_data_no_container() that does not need a container to fill the cmsghdr data. * Added support for the IP_RECVDSTADDR option using this call. * Implemented support for IP_MULTICAST_IF. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31585 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
ecece29dd8
commit
78888c44da
@ -79,6 +79,8 @@ struct net_protocol_module_info {
|
||||
ssize_t (*process_ancillary_data)(net_protocol *self,
|
||||
const ancillary_data_header *header, const void *data,
|
||||
void *buffer, size_t bufferSize);
|
||||
ssize_t (*process_ancillary_data_no_container)(net_protocol *self,
|
||||
net_buffer *buffer, void *buffer, size_t bufferSize);
|
||||
|
||||
ssize_t (*send_data_no_buffer)(net_protocol *self, const iovec *vecs,
|
||||
size_t vecCount, ancillary_data_container *ancillaryData,
|
||||
|
@ -374,6 +374,7 @@ net_protocol_module_info sICMPModule = {
|
||||
icmp_error_reply,
|
||||
NULL, // add_ancillary_data()
|
||||
NULL, // process_ancillary_data()
|
||||
NULL, // process_ancillary_data_no_container()
|
||||
NULL, // send_data_no_buffer()
|
||||
NULL // read_data_no_buffer()
|
||||
};
|
||||
|
@ -166,12 +166,14 @@ struct ipv4_protocol : net_protocol {
|
||||
uint8 time_to_live;
|
||||
uint8 multicast_time_to_live;
|
||||
uint32 flags;
|
||||
struct sockaddr* interface_address; // for IP_MULTICAST_IF
|
||||
|
||||
IPv4MulticastFilter multicast_filter;
|
||||
};
|
||||
|
||||
// protocol flags
|
||||
#define IP_FLAG_HEADER_INCLUDED 0x01
|
||||
#define IP_FLAG_HEADER_INCLUDED 0x01
|
||||
#define IP_FLAG_RECEIVE_DEST_ADDR 0x02
|
||||
|
||||
|
||||
static const int kDefaultTTL = 254;
|
||||
@ -214,7 +216,8 @@ print_address(const in_addr* address, char* buf, size_t bufLen)
|
||||
|
||||
|
||||
RawSocket::RawSocket(net_socket* socket)
|
||||
: DatagramSocket<>("ipv4 raw socket", socket)
|
||||
:
|
||||
DatagramSocket<>("ipv4 raw socket", socket)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1013,6 +1016,7 @@ ipv4_init_protocol(net_socket* socket)
|
||||
protocol->time_to_live = kDefaultTTL;
|
||||
protocol->multicast_time_to_live = kDefaultMulticastTTL;
|
||||
protocol->flags = 0;
|
||||
protocol->interface_address = NULL;
|
||||
return protocol;
|
||||
}
|
||||
|
||||
@ -1023,6 +1027,7 @@ ipv4_uninit_protocol(net_protocol* _protocol)
|
||||
ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
|
||||
|
||||
delete protocol->raw;
|
||||
delete protocol->interface_address;
|
||||
delete protocol;
|
||||
return B_OK;
|
||||
}
|
||||
@ -1118,6 +1123,10 @@ ipv4_getsockopt(net_protocol* _protocol, int level, int option, void* value,
|
||||
return get_int_option(value, *_length,
|
||||
(protocol->flags & IP_FLAG_HEADER_INCLUDED) != 0);
|
||||
}
|
||||
if (option == IP_RECVDSTADDR) {
|
||||
return get_int_option(value, *_length,
|
||||
(protocol->flags & IP_FLAG_RECEIVE_DEST_ADDR) != 0);
|
||||
}
|
||||
if (option == IP_TTL)
|
||||
return get_int_option(value, *_length, protocol->time_to_live);
|
||||
if (option == IP_TOS)
|
||||
@ -1175,10 +1184,59 @@ ipv4_setsockopt(net_protocol* _protocol, int level, int option,
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
if (option == IP_RECVDSTADDR) {
|
||||
int getAddress;
|
||||
if (length != sizeof(int))
|
||||
return B_BAD_VALUE;
|
||||
if (user_memcpy(&getAddress, value, sizeof(int)) != B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
if (getAddress && (protocol->socket->type == SOCK_DGRAM
|
||||
|| protocol->socket->type == SOCK_RAW))
|
||||
protocol->flags |= IP_FLAG_RECEIVE_DEST_ADDR;
|
||||
else
|
||||
protocol->flags &= ~IP_FLAG_RECEIVE_DEST_ADDR;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
if (option == IP_TTL)
|
||||
return set_int_option(protocol->time_to_live, value, length);
|
||||
if (option == IP_TOS)
|
||||
return set_int_option(protocol->service_type, value, length);
|
||||
if (option == IP_MULTICAST_IF) {
|
||||
if (length != sizeof(struct in_addr))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
struct sockaddr_in* address = new (std::nothrow) sockaddr_in;
|
||||
if (address == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (user_memcpy(&address->sin_addr, value, sizeof(struct in_addr))
|
||||
!= B_OK) {
|
||||
delete address;
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
// Using INADDR_ANY to remove the previous setting.
|
||||
if (address->sin_addr.s_addr == htonl(INADDR_ANY)) {
|
||||
delete address;
|
||||
delete protocol->interface_address;
|
||||
protocol->interface_address = NULL;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
struct net_interface* interface
|
||||
= sDatalinkModule->get_interface_with_address(sDomain,
|
||||
(struct sockaddr*)address);
|
||||
if (interface == NULL) {
|
||||
delete address;
|
||||
return EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
delete protocol->interface_address;
|
||||
protocol->interface_address = (struct sockaddr*)address;
|
||||
return B_OK;
|
||||
}
|
||||
if (option == IP_MULTICAST_TTL) {
|
||||
return set_int_option(protocol->multicast_time_to_live, value,
|
||||
length);
|
||||
@ -1405,6 +1463,25 @@ ipv4_send_data(net_protocol* _protocol, net_buffer* buffer)
|
||||
offsetof(ipv4_header, destination)>(buffer));
|
||||
}
|
||||
|
||||
// handle IP_MULTICAST_IF
|
||||
if (IN_MULTICAST(ntohl(((sockaddr_in*)buffer->destination)->
|
||||
sin_addr.s_addr)) && protocol->interface_address != NULL) {
|
||||
net_interface* interface
|
||||
= sDatalinkModule->get_interface_with_address(sDomain,
|
||||
protocol->interface_address);
|
||||
if (interface == NULL || (interface->flags & IFF_UP) == 0)
|
||||
return EADDRNOTAVAIL;
|
||||
|
||||
buffer->interface = interface;
|
||||
|
||||
net_route* route = sDatalinkModule->get_route(sDomain,
|
||||
interface->address);
|
||||
if (route == NULL)
|
||||
return ENETUNREACH;
|
||||
|
||||
return sDatalinkModule->send_data(route, buffer);
|
||||
}
|
||||
|
||||
return sDatalinkModule->send_datagram(protocol, sDomain, buffer);
|
||||
}
|
||||
|
||||
@ -1600,6 +1677,32 @@ ipv4_error_reply(net_protocol* protocol, net_buffer* causedError, uint32 code,
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ipv4_process_ancillary_data_no_container(net_protocol* protocol,
|
||||
net_buffer* buffer, void* msgControl, size_t msgControlLen)
|
||||
{
|
||||
ssize_t bytesWritten = 0;
|
||||
|
||||
if ((((ipv4_protocol*)protocol)->flags & IP_FLAG_RECEIVE_DEST_ADDR) != 0) {
|
||||
if (msgControlLen < CMSG_SPACE(sizeof(struct in_addr)))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
cmsghdr* messageHeader = (cmsghdr*)msgControl;
|
||||
messageHeader->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
|
||||
messageHeader->cmsg_level = IPPROTO_IP;
|
||||
messageHeader->cmsg_type = IP_RECVDSTADDR;
|
||||
|
||||
memcpy(CMSG_DATA(messageHeader),
|
||||
&((struct sockaddr_in*)buffer->destination)->sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
|
||||
bytesWritten += CMSG_SPACE(sizeof(struct in_addr));
|
||||
}
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
@ -1741,6 +1844,7 @@ net_protocol_module_info gIPv4Module = {
|
||||
ipv4_error_reply,
|
||||
NULL, // add_ancillary_data()
|
||||
NULL, // process_ancillary_data()
|
||||
ipv4_process_ancillary_data_no_container,
|
||||
NULL, // send_data_no_buffer()
|
||||
NULL // read_data_no_buffer()
|
||||
};
|
||||
|
@ -383,6 +383,7 @@ net_protocol_module_info gL2CAPModule = {
|
||||
l2cap_error_reply,
|
||||
NULL, // add_ancillary_data()
|
||||
NULL, // process_ancillary_data()
|
||||
NULL, // process_ancillary_data_no_container()
|
||||
NULL, // send_data_no_buffer()
|
||||
NULL // read_data_no_buffer()
|
||||
};
|
||||
|
@ -846,6 +846,7 @@ net_protocol_module_info sTCPModule = {
|
||||
tcp_error_reply,
|
||||
NULL, // add_ancillary_data()
|
||||
NULL, // process_ancillary_data()
|
||||
NULL, // process_ancillary_data_no_container()
|
||||
NULL, // send_data_no_buffer()
|
||||
NULL // read_data_no_buffer()
|
||||
};
|
||||
|
@ -1146,6 +1146,15 @@ udp_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
udp_process_ancillary_data_no_container(net_protocol *protocol,
|
||||
net_buffer* buffer, void *data, size_t dataSize)
|
||||
{
|
||||
return protocol->next->module->process_ancillary_data_no_container(
|
||||
protocol, buffer, data, dataSize);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - module interface
|
||||
|
||||
|
||||
@ -1256,6 +1265,7 @@ net_protocol_module_info sUDPModule = {
|
||||
udp_error_reply,
|
||||
NULL, // add_ancillary_data()
|
||||
NULL, // process_ancillary_data()
|
||||
udp_process_ancillary_data_no_container,
|
||||
NULL, // send_data_no_buffer()
|
||||
NULL // read_data_no_buffer()
|
||||
};
|
||||
|
@ -508,6 +508,7 @@ net_protocol_module_info gUnixModule = {
|
||||
unix_error_reply,
|
||||
unix_add_ancillary_data,
|
||||
unix_process_ancillary_data,
|
||||
NULL,
|
||||
unix_send_data_no_buffer,
|
||||
unix_read_data_no_buffer
|
||||
};
|
||||
|
@ -255,6 +255,32 @@ process_ancillary_data(net_socket* socket, ancillary_data_container* container,
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
process_ancillary_data(net_socket* socket,
|
||||
net_buffer* buffer, msghdr* messageHeader)
|
||||
{
|
||||
void *dataBuffer = messageHeader->msg_control;
|
||||
ssize_t bytesWritten;
|
||||
|
||||
if (dataBuffer == NULL) {
|
||||
messageHeader->msg_controllen = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (socket->first_info->process_ancillary_data_no_container == NULL)
|
||||
return EOPNOTSUPP;
|
||||
|
||||
bytesWritten = socket->first_info->process_ancillary_data_no_container(
|
||||
socket->first_protocol, buffer, dataBuffer,
|
||||
messageHeader->msg_controllen);
|
||||
if (bytesWritten < 0)
|
||||
return bytesWritten;
|
||||
messageHeader->msg_controllen = bytesWritten;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
socket_receive_no_buffer(net_socket* socket, msghdr* header, void* data,
|
||||
size_t length, int flags)
|
||||
@ -1171,8 +1197,12 @@ socket_receive(net_socket* socket, msghdr* header, void* data, size_t length,
|
||||
// process ancillary data
|
||||
if (header != NULL) {
|
||||
if (buffer != NULL && header->msg_control != NULL) {
|
||||
status = process_ancillary_data(socket,
|
||||
gNetBufferModule.get_ancillary_data(buffer), header);
|
||||
ancillary_data_container* container
|
||||
= gNetBufferModule.get_ancillary_data(buffer);
|
||||
if (container != NULL)
|
||||
status = process_ancillary_data(socket, container, header);
|
||||
else
|
||||
status = process_ancillary_data(socket, buffer, header);
|
||||
if (status != B_OK) {
|
||||
gNetBufferModule.free(buffer);
|
||||
return status;
|
||||
|
Loading…
Reference in New Issue
Block a user