* Minor cleanup.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31079 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
75557e0ac3
commit
e5c5e337e4
@ -100,15 +100,18 @@ class FragmentPacket {
|
|||||||
FragmentPacket(const ipv4_packet_key &key);
|
FragmentPacket(const ipv4_packet_key &key);
|
||||||
~FragmentPacket();
|
~FragmentPacket();
|
||||||
|
|
||||||
status_t AddFragment(uint16 start, uint16 end, net_buffer *buffer,
|
status_t AddFragment(uint16 start, uint16 end,
|
||||||
bool lastFragment);
|
net_buffer *buffer, bool lastFragment);
|
||||||
status_t Reassemble(net_buffer *to);
|
status_t Reassemble(net_buffer *to);
|
||||||
|
|
||||||
bool IsComplete() const { return fReceivedLastFragment && fBytesLeft == 0; }
|
bool IsComplete() const
|
||||||
|
{ return fReceivedLastFragment
|
||||||
|
&& fBytesLeft == 0; }
|
||||||
|
|
||||||
static uint32 Hash(void *_packet, const void *_key, uint32 range);
|
static uint32 Hash(void *_packet, const void *_key, uint32 range);
|
||||||
static int Compare(void *_packet, const void *_key);
|
static int Compare(void *_packet, const void *_key);
|
||||||
static int32 NextOffset() { return offsetof(FragmentPacket, fNext); }
|
static int32 NextOffset()
|
||||||
|
{ return offsetof(FragmentPacket, fNext); }
|
||||||
static void StaleTimer(struct net_timer *timer, void *data);
|
static void StaleTimer(struct net_timer *timer, void *data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -121,7 +124,8 @@ class FragmentPacket {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class RawSocket : public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSocket<> {
|
class RawSocket
|
||||||
|
: public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSocket<> {
|
||||||
public:
|
public:
|
||||||
RawSocket(net_socket *socket);
|
RawSocket(net_socket *socket);
|
||||||
};
|
};
|
||||||
@ -152,7 +156,10 @@ struct MulticastStateHash {
|
|||||||
|
|
||||||
struct ipv4_protocol : net_protocol {
|
struct ipv4_protocol : net_protocol {
|
||||||
ipv4_protocol()
|
ipv4_protocol()
|
||||||
: multicast_filter(this) {}
|
:
|
||||||
|
multicast_filter(this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
RawSocket *raw;
|
RawSocket *raw;
|
||||||
uint8 service_type;
|
uint8 service_type;
|
||||||
@ -301,7 +308,7 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
|
|||||||
|
|
||||||
status_t status = gBufferModule->merge(buffer, previous, false);
|
status_t status = gBufferModule->merge(buffer, previous, false);
|
||||||
TRACE(" merge previous: %s", strerror(status));
|
TRACE(" merge previous: %s", strerror(status));
|
||||||
if (status < B_OK) {
|
if (status != B_OK) {
|
||||||
fFragments.Insert(next, previous);
|
fFragments.Insert(next, previous);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -327,7 +334,7 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
|
|||||||
|
|
||||||
status_t status = gBufferModule->merge(buffer, next, true);
|
status_t status = gBufferModule->merge(buffer, next, true);
|
||||||
TRACE(" merge next: %s", strerror(status));
|
TRACE(" merge next: %s", strerror(status));
|
||||||
if (status < B_OK) {
|
if (status != B_OK) {
|
||||||
fFragments.Insert((net_buffer *)previous->link.next, next);
|
fFragments.Insert((net_buffer *)previous->link.next, next);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -389,7 +396,7 @@ FragmentPacket::Reassemble(net_buffer *to)
|
|||||||
buffer = fragment;
|
buffer = fragment;
|
||||||
} else
|
} else
|
||||||
status = gBufferModule->merge(buffer, fragment, true);
|
status = gBufferModule->merge(buffer, fragment, true);
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
} else
|
} else
|
||||||
buffer = fragment;
|
buffer = fragment;
|
||||||
@ -484,8 +491,39 @@ dump_ipv4_header(ipv4_header &header)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*!
|
static int
|
||||||
Attempts to re-assemble fragmented packets.
|
dump_ipv4_multicast(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
MulticastState::Iterator it = sMulticastState->GetIterator();
|
||||||
|
|
||||||
|
while (it.HasNext()) {
|
||||||
|
IPv4GroupInterface *state = it.Next();
|
||||||
|
|
||||||
|
char addressBuffer[64];
|
||||||
|
|
||||||
|
kprintf("%p: group <%s, %s, %s {", state, state->Interface()->name,
|
||||||
|
print_address(&state->Address(), addressBuffer,
|
||||||
|
sizeof(addressBuffer)),
|
||||||
|
state->Mode() == IPv4GroupInterface::kExclude
|
||||||
|
? "Exclude" : "Include");
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
IPv4GroupInterface::AddressSet::Iterator it
|
||||||
|
= state->Sources().GetIterator();
|
||||||
|
while (it.HasNext()) {
|
||||||
|
kprintf("%s%s", count > 0 ? ", " : "", print_address(&it.Next(),
|
||||||
|
addressBuffer, sizeof(addressBuffer)));
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
kprintf("}> sock %p\n", state->Parent()->Socket());
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Attempts to re-assemble fragmented packets.
|
||||||
\return B_OK if everything went well; if it could reassemble the packet, \a _buffer
|
\return B_OK if everything went well; if it could reassemble the packet, \a _buffer
|
||||||
will point to its buffer, otherwise, it will be \c NULL.
|
will point to its buffer, otherwise, it will be \c NULL.
|
||||||
\return various error codes if something went wrong (mostly B_NO_MEMORY)
|
\return various error codes if something went wrong (mostly B_NO_MEMORY)
|
||||||
@ -538,7 +576,8 @@ reassemble_fragments(const ipv4_header &header, net_buffer **_buffer)
|
|||||||
|
|
||||||
if (packet->IsComplete()) {
|
if (packet->IsComplete()) {
|
||||||
hash_remove(sFragmentHash, packet);
|
hash_remove(sFragmentHash, packet);
|
||||||
// no matter if reassembling succeeds, we won't need this packet anymore
|
// no matter if reassembling succeeds, we won't need this packet
|
||||||
|
// anymore
|
||||||
|
|
||||||
status = packet->Reassemble(buffer);
|
status = packet->Reassemble(buffer);
|
||||||
delete packet;
|
delete packet;
|
||||||
@ -553,8 +592,7 @@ reassemble_fragments(const ipv4_header &header, net_buffer **_buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Fragments the incoming buffer and send all fragments via the specified
|
||||||
Fragments the incoming buffer and send all fragments via the specified
|
|
||||||
\a route.
|
\a route.
|
||||||
*/
|
*/
|
||||||
static status_t
|
static status_t
|
||||||
@ -564,7 +602,7 @@ send_fragments(ipv4_protocol *protocol, struct net_route *route,
|
|||||||
TRACE_SK(protocol, "SendFragments(%lu bytes, mtu %lu)", buffer->size, mtu);
|
TRACE_SK(protocol, "SendFragments(%lu bytes, mtu %lu)", buffer->size, mtu);
|
||||||
|
|
||||||
NetBufferHeaderReader<ipv4_header> originalHeader(buffer);
|
NetBufferHeaderReader<ipv4_header> originalHeader(buffer);
|
||||||
if (originalHeader.Status() < B_OK)
|
if (originalHeader.Status() != B_OK)
|
||||||
return originalHeader.Status();
|
return originalHeader.Status();
|
||||||
|
|
||||||
uint16 headerLength = originalHeader->HeaderLength();
|
uint16 headerLength = originalHeader->HeaderLength();
|
||||||
@ -576,12 +614,13 @@ send_fragments(ipv4_protocol *protocol, struct net_route *route,
|
|||||||
if (headerBuffer == NULL)
|
if (headerBuffer == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
// TODO we need to make sure ipv4_header is contiguous or
|
// TODO: we need to make sure ipv4_header is contiguous or
|
||||||
// use another construct.
|
// use another construct.
|
||||||
NetBufferHeaderReader<ipv4_header> bufferHeader(headerBuffer);
|
NetBufferHeaderReader<ipv4_header> bufferHeader(headerBuffer);
|
||||||
ipv4_header *header = &bufferHeader.Data();
|
ipv4_header *header = &bufferHeader.Data();
|
||||||
|
|
||||||
// adapt MTU to be a multiple of 8 (fragment offsets can only be specified this way)
|
// Adapt MTU to be a multiple of 8 (fragment offsets can only be specified
|
||||||
|
// this way)
|
||||||
mtu -= headerLength;
|
mtu -= headerLength;
|
||||||
mtu &= ~7;
|
mtu &= ~7;
|
||||||
TRACE(" adjusted MTU to %ld\n", mtu);
|
TRACE(" adjusted MTU to %ld\n", mtu);
|
||||||
@ -596,7 +635,8 @@ send_fragments(ipv4_protocol *protocol, struct net_route *route,
|
|||||||
header->fragment_offset = htons((lastFragment ? 0 : IP_MORE_FRAGMENTS)
|
header->fragment_offset = htons((lastFragment ? 0 : IP_MORE_FRAGMENTS)
|
||||||
| (fragmentOffset >> 3));
|
| (fragmentOffset >> 3));
|
||||||
header->checksum = 0;
|
header->checksum = 0;
|
||||||
header->checksum = gStackModule->checksum((uint8 *)header, headerLength);
|
header->checksum = gStackModule->checksum((uint8 *)header,
|
||||||
|
headerLength);
|
||||||
// TODO: compute the checksum only for those parts that changed?
|
// TODO: compute the checksum only for those parts that changed?
|
||||||
|
|
||||||
TRACE(" send fragment of %ld bytes (%ld bytes left)\n", fragmentLength, bytesLeft);
|
TRACE(" send fragment of %ld bytes (%ld bytes left)\n", fragmentLength, bytesLeft);
|
||||||
@ -625,7 +665,7 @@ send_fragments(ipv4_protocol *protocol, struct net_route *route,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status < B_OK) {
|
if (status != B_OK) {
|
||||||
gBufferModule->free(fragmentBuffer);
|
gBufferModule->free(fragmentBuffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -660,8 +700,8 @@ deliver_multicast(net_protocol_module_info *module, net_buffer *buffer,
|
|||||||
// as Multicast filters are installed with an IPv4 protocol
|
// as Multicast filters are installed with an IPv4 protocol
|
||||||
// reference, we need to go and find the appropriate instance
|
// reference, we need to go and find the appropriate instance
|
||||||
// related to the 'receiving protocol' with module 'module'.
|
// related to the 'receiving protocol' with module 'module'.
|
||||||
net_protocol *proto =
|
net_protocol *proto
|
||||||
state->Parent()->Socket()->socket->first_protocol;
|
= state->Parent()->Socket()->socket->first_protocol;
|
||||||
|
|
||||||
while (proto && proto->module != module)
|
while (proto && proto->module != module)
|
||||||
proto = proto->next;
|
proto = proto->next;
|
||||||
@ -725,7 +765,7 @@ IPv4Multicast::JoinGroup(IPv4GroupInterface *state)
|
|||||||
|
|
||||||
status_t status = intf->first_info->join_multicast(intf->first_protocol,
|
status_t status = intf->first_info->join_multicast(intf->first_protocol,
|
||||||
fill_sockaddr_in(&groupAddr, state->Address()));
|
fill_sockaddr_in(&groupAddr, state->Address()));
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
sMulticastState->Insert(state);
|
sMulticastState->Insert(state);
|
||||||
@ -761,7 +801,8 @@ receiving_protocol(uint8 protocol)
|
|||||||
if (module != NULL)
|
if (module != NULL)
|
||||||
return module;
|
return module;
|
||||||
|
|
||||||
if (gStackModule->get_domain_receiving_protocol(sDomain, protocol, &module) == B_OK)
|
if (gStackModule->get_domain_receiving_protocol(sDomain, protocol,
|
||||||
|
&module) == B_OK)
|
||||||
sReceivingProtocol[protocol] = module;
|
sReceivingProtocol[protocol] = module;
|
||||||
|
|
||||||
return module;
|
return module;
|
||||||
@ -826,13 +867,13 @@ ipv4_delta_membership(ipv4_protocol *protocol, int option,
|
|||||||
if (option == IP_DROP_MEMBERSHIP
|
if (option == IP_DROP_MEMBERSHIP
|
||||||
|| option == IP_DROP_SOURCE_MEMBERSHIP)
|
|| option == IP_DROP_SOURCE_MEMBERSHIP)
|
||||||
return EADDRNOTAVAIL;
|
return EADDRNOTAVAIL;
|
||||||
else
|
|
||||||
return EINVAL;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = ipv4_delta_group(state, option, interface, sourceAddr);
|
status = ipv4_delta_group(state, option, interface, sourceAddr);
|
||||||
@ -930,6 +971,32 @@ ipv4_generic_delta_membership(ipv4_protocol *protocol, int option,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
get_int_option(void *target, size_t length, int value)
|
||||||
|
{
|
||||||
|
if (length != sizeof(int))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
return user_memcpy(target, &value, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Type> static status_t
|
||||||
|
set_int_option(Type &target, const void *_value, size_t length)
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
|
||||||
|
if (length != sizeof(int))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (user_memcpy(&value, _value, sizeof(int)) != B_OK)
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
target = value;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@ -960,8 +1027,7 @@ ipv4_uninit_protocol(net_protocol *_protocol)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Since open() is only called on the top level protocol, when we get here
|
||||||
Since open() is only called on the top level protocol, when we get here
|
|
||||||
it means we are on a SOCK_RAW socket.
|
it means we are on a SOCK_RAW socket.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
@ -974,7 +1040,7 @@ ipv4_open(net_protocol *_protocol)
|
|||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t status = raw->InitCheck();
|
status_t status = raw->InitCheck();
|
||||||
if (status < B_OK) {
|
if (status != B_OK) {
|
||||||
delete raw;
|
delete raw;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -1029,32 +1095,6 @@ ipv4_accept(net_protocol *protocol, struct net_socket **_acceptedSocket)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
get_int_option(void *target, size_t length, int value)
|
|
||||||
{
|
|
||||||
if (length != sizeof(int))
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
return user_memcpy(target, &value, sizeof(int));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Type> static status_t
|
|
||||||
set_int_option(Type &target, const void *_value, size_t length)
|
|
||||||
{
|
|
||||||
int value;
|
|
||||||
|
|
||||||
if (length != sizeof(int))
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
if (user_memcpy(&value, _value, sizeof(int)) < B_OK)
|
|
||||||
return B_BAD_ADDRESS;
|
|
||||||
|
|
||||||
target = value;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ipv4_control(net_protocol *_protocol, int level, int option, void *value,
|
ipv4_control(net_protocol *_protocol, int level, int option, void *value,
|
||||||
size_t *_length)
|
size_t *_length)
|
||||||
@ -1073,17 +1113,19 @@ ipv4_getsockopt(net_protocol *_protocol, int level, int option, void *value,
|
|||||||
ipv4_protocol *protocol = (ipv4_protocol *)_protocol;
|
ipv4_protocol *protocol = (ipv4_protocol *)_protocol;
|
||||||
|
|
||||||
if (level == IPPROTO_IP) {
|
if (level == IPPROTO_IP) {
|
||||||
if (option == IP_HDRINCL)
|
if (option == IP_HDRINCL) {
|
||||||
return get_int_option(value, *_length,
|
return get_int_option(value, *_length,
|
||||||
(protocol->flags & IP_FLAG_HEADER_INCLUDED) != 0);
|
(protocol->flags & IP_FLAG_HEADER_INCLUDED) != 0);
|
||||||
else if (option == IP_TTL)
|
}
|
||||||
|
if (option == IP_TTL)
|
||||||
return get_int_option(value, *_length, protocol->time_to_live);
|
return get_int_option(value, *_length, protocol->time_to_live);
|
||||||
else if (option == IP_TOS)
|
if (option == IP_TOS)
|
||||||
return get_int_option(value, *_length, protocol->service_type);
|
return get_int_option(value, *_length, protocol->service_type);
|
||||||
else if (IP_MULTICAST_TTL)
|
if (IP_MULTICAST_TTL) {
|
||||||
return get_int_option(value, *_length,
|
return get_int_option(value, *_length,
|
||||||
protocol->multicast_time_to_live);
|
protocol->multicast_time_to_live);
|
||||||
else if (option == IP_ADD_MEMBERSHIP
|
}
|
||||||
|
if (option == IP_ADD_MEMBERSHIP
|
||||||
|| option == IP_DROP_MEMBERSHIP
|
|| option == IP_DROP_MEMBERSHIP
|
||||||
|| option == IP_BLOCK_SOURCE
|
|| option == IP_BLOCK_SOURCE
|
||||||
|| option == IP_UNBLOCK_SOURCE
|
|| option == IP_UNBLOCK_SOURCE
|
||||||
@ -1099,11 +1141,11 @@ ipv4_getsockopt(net_protocol *_protocol, int level, int option, void *value,
|
|||||||
// ``An error of EOPNOTSUPP is returned if these options are
|
// ``An error of EOPNOTSUPP is returned if these options are
|
||||||
// used with getsockopt().''
|
// used with getsockopt().''
|
||||||
return EOPNOTSUPP;
|
return EOPNOTSUPP;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
dprintf("IPv4::getsockopt(): get unknown option: %d\n", option);
|
dprintf("IPv4::getsockopt(): get unknown option: %d\n", option);
|
||||||
return ENOPROTOOPT;
|
return ENOPROTOOPT;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return sSocketModule->get_option(protocol->socket, level, option, value,
|
return sSocketModule->get_option(protocol->socket, level, option, value,
|
||||||
_length);
|
_length);
|
||||||
@ -1121,70 +1163,75 @@ ipv4_setsockopt(net_protocol *_protocol, int level, int option,
|
|||||||
int headerIncluded;
|
int headerIncluded;
|
||||||
if (length != sizeof(int))
|
if (length != sizeof(int))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (user_memcpy(&headerIncluded, value, sizeof(headerIncluded)) < B_OK)
|
if (user_memcpy(&headerIncluded, value, sizeof(headerIncluded))
|
||||||
|
!= B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
if (headerIncluded)
|
if (headerIncluded)
|
||||||
protocol->flags |= IP_FLAG_HEADER_INCLUDED;
|
protocol->flags |= IP_FLAG_HEADER_INCLUDED;
|
||||||
else
|
else
|
||||||
protocol->flags &= ~IP_FLAG_HEADER_INCLUDED;
|
protocol->flags &= ~IP_FLAG_HEADER_INCLUDED;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} else if (option == IP_TTL) {
|
}
|
||||||
|
if (option == IP_TTL)
|
||||||
return set_int_option(protocol->time_to_live, value, length);
|
return set_int_option(protocol->time_to_live, value, length);
|
||||||
} else if (option == IP_TOS) {
|
if (option == IP_TOS)
|
||||||
return set_int_option(protocol->service_type, value, length);
|
return set_int_option(protocol->service_type, value, length);
|
||||||
} else if (option == IP_MULTICAST_TTL) {
|
if (option == IP_MULTICAST_TTL) {
|
||||||
return set_int_option(protocol->multicast_time_to_live, value,
|
return set_int_option(protocol->multicast_time_to_live, value,
|
||||||
length);
|
length);
|
||||||
} else if (option == IP_ADD_MEMBERSHIP
|
}
|
||||||
|| option == IP_DROP_MEMBERSHIP) {
|
if (option == IP_ADD_MEMBERSHIP || option == IP_DROP_MEMBERSHIP) {
|
||||||
ip_mreq mreq;
|
ip_mreq mreq;
|
||||||
if (length != sizeof(ip_mreq))
|
if (length != sizeof(ip_mreq))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (user_memcpy(&mreq, value, sizeof(ip_mreq)) < B_OK)
|
if (user_memcpy(&mreq, value, sizeof(ip_mreq)) != B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
return ipv4_delta_membership(protocol, option, &mreq.imr_interface,
|
return ipv4_delta_membership(protocol, option, &mreq.imr_interface,
|
||||||
&mreq.imr_multiaddr, NULL);
|
&mreq.imr_multiaddr, NULL);
|
||||||
} else if (option == IP_BLOCK_SOURCE
|
}
|
||||||
|
if (option == IP_BLOCK_SOURCE
|
||||||
|| option == IP_UNBLOCK_SOURCE
|
|| option == IP_UNBLOCK_SOURCE
|
||||||
|| option == IP_ADD_SOURCE_MEMBERSHIP
|
|| option == IP_ADD_SOURCE_MEMBERSHIP
|
||||||
|| option == IP_DROP_SOURCE_MEMBERSHIP) {
|
|| option == IP_DROP_SOURCE_MEMBERSHIP) {
|
||||||
ip_mreq_source mreq;
|
ip_mreq_source mreq;
|
||||||
if (length != sizeof(ip_mreq_source))
|
if (length != sizeof(ip_mreq_source))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (user_memcpy(&mreq, value, sizeof(ip_mreq_source)) < B_OK)
|
if (user_memcpy(&mreq, value, sizeof(ip_mreq_source)) != B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
return ipv4_delta_membership(protocol, option, &mreq.imr_interface,
|
return ipv4_delta_membership(protocol, option, &mreq.imr_interface,
|
||||||
&mreq.imr_multiaddr, &mreq.imr_sourceaddr);
|
&mreq.imr_multiaddr, &mreq.imr_sourceaddr);
|
||||||
} else if (option == MCAST_LEAVE_GROUP
|
}
|
||||||
|| option == MCAST_JOIN_GROUP) {
|
if (option == MCAST_LEAVE_GROUP || option == MCAST_JOIN_GROUP) {
|
||||||
group_req greq;
|
group_req greq;
|
||||||
if (length != sizeof(group_req))
|
if (length != sizeof(group_req))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (user_memcpy(&greq, value, sizeof(group_req)) < B_OK)
|
if (user_memcpy(&greq, value, sizeof(group_req)) != B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
return ipv4_generic_delta_membership(protocol, option,
|
return ipv4_generic_delta_membership(protocol, option,
|
||||||
greq.gr_interface, &greq.gr_group, NULL);
|
greq.gr_interface, &greq.gr_group, NULL);
|
||||||
} else if (option == MCAST_BLOCK_SOURCE
|
}
|
||||||
|
if (option == MCAST_BLOCK_SOURCE
|
||||||
|| option == MCAST_UNBLOCK_SOURCE
|
|| option == MCAST_UNBLOCK_SOURCE
|
||||||
|| option == MCAST_JOIN_SOURCE_GROUP
|
|| option == MCAST_JOIN_SOURCE_GROUP
|
||||||
|| option == MCAST_LEAVE_SOURCE_GROUP) {
|
|| option == MCAST_LEAVE_SOURCE_GROUP) {
|
||||||
group_source_req greq;
|
group_source_req greq;
|
||||||
if (length != sizeof(group_source_req))
|
if (length != sizeof(group_source_req))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (user_memcpy(&greq, value, sizeof(group_source_req)) < B_OK)
|
if (user_memcpy(&greq, value, sizeof(group_source_req)) != B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
return ipv4_generic_delta_membership(protocol, option,
|
return ipv4_generic_delta_membership(protocol, option,
|
||||||
greq.gsr_interface, &greq.gsr_group, &greq.gsr_source);
|
greq.gsr_interface, &greq.gsr_group, &greq.gsr_source);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
dprintf("IPv4::setsockopt(): set unknown option: %d\n", option);
|
dprintf("IPv4::setsockopt(): set unknown option: %d\n", option);
|
||||||
return ENOPROTOOPT;
|
return ENOPROTOOPT;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return sSocketModule->set_option(protocol->socket, level, option,
|
return sSocketModule->set_option(protocol->socket, level, option,
|
||||||
value, length);
|
value, length);
|
||||||
@ -1260,22 +1307,22 @@ ipv4_send_routed_data(net_protocol *_protocol, struct net_route *route,
|
|||||||
|
|
||||||
if (destination.sin_addr.s_addr == INADDR_ANY)
|
if (destination.sin_addr.s_addr == INADDR_ANY)
|
||||||
return EDESTADDRREQ;
|
return EDESTADDRREQ;
|
||||||
else if ((interface->device->flags & IFF_BROADCAST) != 0
|
|
||||||
|
if ((interface->device->flags & IFF_BROADCAST) != 0
|
||||||
&& (destination.sin_addr.s_addr == INADDR_BROADCAST
|
&& (destination.sin_addr.s_addr == INADDR_BROADCAST
|
||||||
|| destination.sin_addr.s_addr
|
|| destination.sin_addr.s_addr
|
||||||
== broadcastAddress.sin_addr.s_addr)) {
|
== broadcastAddress.sin_addr.s_addr)) {
|
||||||
if (protocol && !(protocol->socket->options & SO_BROADCAST))
|
if (protocol && !(protocol->socket->options & SO_BROADCAST))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
buffer->flags |= MSG_BCAST;
|
buffer->flags |= MSG_BCAST;
|
||||||
} else if (IN_MULTICAST(ntohl(destination.sin_addr.s_addr))) {
|
} else if (IN_MULTICAST(ntohl(destination.sin_addr.s_addr)))
|
||||||
buffer->flags |= MSG_MCAST;
|
buffer->flags |= MSG_MCAST;
|
||||||
}
|
|
||||||
|
|
||||||
// Add IP header (if needed)
|
// Add IP header (if needed)
|
||||||
|
|
||||||
if (!headerIncluded) {
|
if (!headerIncluded) {
|
||||||
NetBufferPrepend<ipv4_header> header(buffer);
|
NetBufferPrepend<ipv4_header> header(buffer);
|
||||||
if (header.Status() < B_OK)
|
if (header.Status() != B_OK)
|
||||||
return header.Status();
|
return header.Status();
|
||||||
|
|
||||||
header->version = IP_VERSION;
|
header->version = IP_VERSION;
|
||||||
@ -1284,13 +1331,15 @@ ipv4_send_routed_data(net_protocol *_protocol, struct net_route *route,
|
|||||||
header->total_length = htons(buffer->size);
|
header->total_length = htons(buffer->size);
|
||||||
header->id = htons(atomic_add(&sPacketID, 1));
|
header->id = htons(atomic_add(&sPacketID, 1));
|
||||||
header->fragment_offset = 0;
|
header->fragment_offset = 0;
|
||||||
if (protocol)
|
if (protocol) {
|
||||||
header->time_to_live = (buffer->flags & MSG_MCAST) ?
|
header->time_to_live = (buffer->flags & MSG_MCAST)
|
||||||
protocol->multicast_time_to_live : protocol->time_to_live;
|
? protocol->multicast_time_to_live : protocol->time_to_live;
|
||||||
else
|
} else {
|
||||||
header->time_to_live = (buffer->flags & MSG_MCAST) ?
|
header->time_to_live = (buffer->flags & MSG_MCAST)
|
||||||
kDefaultMulticastTTL : kDefaultTTL;
|
? kDefaultMulticastTTL : kDefaultTTL;
|
||||||
header->protocol = protocol ? protocol->socket->protocol : buffer->protocol;
|
}
|
||||||
|
header->protocol = protocol
|
||||||
|
? protocol->socket->protocol : buffer->protocol;
|
||||||
header->checksum = 0;
|
header->checksum = 0;
|
||||||
|
|
||||||
header->source = source.sin_addr.s_addr;
|
header->source = source.sin_addr.s_addr;
|
||||||
@ -1298,7 +1347,7 @@ ipv4_send_routed_data(net_protocol *_protocol, struct net_route *route,
|
|||||||
} else {
|
} else {
|
||||||
// if IP_HDRINCL, check if the source address is set
|
// if IP_HDRINCL, check if the source address is set
|
||||||
NetBufferHeaderReader<ipv4_header> header(buffer);
|
NetBufferHeaderReader<ipv4_header> header(buffer);
|
||||||
if (header.Status() < B_OK)
|
if (header.Status() != B_OK)
|
||||||
return header.Status();
|
return header.Status();
|
||||||
|
|
||||||
if (header->source == 0) {
|
if (header->source == 0) {
|
||||||
@ -1312,11 +1361,13 @@ ipv4_send_routed_data(net_protocol *_protocol, struct net_route *route,
|
|||||||
if (buffer->size > 0xffff)
|
if (buffer->size > 0xffff)
|
||||||
return EMSGSIZE;
|
return EMSGSIZE;
|
||||||
|
|
||||||
if (checksumNeeded)
|
if (checksumNeeded) {
|
||||||
*IPChecksumField(buffer) = gBufferModule->checksum(buffer, 0,
|
*IPChecksumField(buffer) = gBufferModule->checksum(buffer, 0,
|
||||||
sizeof(ipv4_header), true);
|
sizeof(ipv4_header), true);
|
||||||
|
}
|
||||||
|
|
||||||
TRACE_SK(protocol, " SendRoutedData(): header chksum: %ld, buffer checksum: %ld",
|
TRACE_SK(protocol, " SendRoutedData(): header chksum: %ld, buffer "
|
||||||
|
"checksum: %ld",
|
||||||
gBufferModule->checksum(buffer, 0, sizeof(ipv4_header), true),
|
gBufferModule->checksum(buffer, 0, sizeof(ipv4_header), true),
|
||||||
gBufferModule->checksum(buffer, 0, buffer->size, true));
|
gBufferModule->checksum(buffer, 0, buffer->size, true));
|
||||||
|
|
||||||
@ -1342,7 +1393,7 @@ ipv4_send_data(net_protocol *_protocol, net_buffer *buffer)
|
|||||||
|
|
||||||
if (protocol && (protocol->flags & IP_FLAG_HEADER_INCLUDED)) {
|
if (protocol && (protocol->flags & IP_FLAG_HEADER_INCLUDED)) {
|
||||||
if (buffer->size < sizeof(ipv4_header))
|
if (buffer->size < sizeof(ipv4_header))
|
||||||
return EINVAL;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
sockaddr_in *source = (sockaddr_in *)buffer->source;
|
sockaddr_in *source = (sockaddr_in *)buffer->source;
|
||||||
sockaddr_in *destination = (sockaddr_in *)buffer->destination;
|
sockaddr_in *destination = (sockaddr_in *)buffer->destination;
|
||||||
@ -1422,7 +1473,7 @@ ipv4_receive_data(net_buffer *buffer)
|
|||||||
TRACE("ReceiveData(%p [%ld bytes])", buffer, buffer->size);
|
TRACE("ReceiveData(%p [%ld bytes])", buffer, buffer->size);
|
||||||
|
|
||||||
NetBufferHeaderReader<ipv4_header> bufferHeader(buffer);
|
NetBufferHeaderReader<ipv4_header> bufferHeader(buffer);
|
||||||
if (bufferHeader.Status() < B_OK)
|
if (bufferHeader.Status() != B_OK)
|
||||||
return bufferHeader.Status();
|
return bufferHeader.Status();
|
||||||
|
|
||||||
ipv4_header &header = bufferHeader.Data();
|
ipv4_header &header = bufferHeader.Data();
|
||||||
@ -1442,7 +1493,8 @@ ipv4_receive_data(net_buffer *buffer)
|
|||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
struct sockaddr_in &source = *(struct sockaddr_in *)buffer->source;
|
struct sockaddr_in &source = *(struct sockaddr_in *)buffer->source;
|
||||||
struct sockaddr_in &destination = *(struct sockaddr_in *)buffer->destination;
|
struct sockaddr_in &destination
|
||||||
|
= *(struct sockaddr_in *)buffer->destination;
|
||||||
|
|
||||||
fill_sockaddr_in(&source, header.source);
|
fill_sockaddr_in(&source, header.source);
|
||||||
fill_sockaddr_in(&destination, header.destination);
|
fill_sockaddr_in(&destination, header.destination);
|
||||||
@ -1472,7 +1524,7 @@ ipv4_receive_data(net_buffer *buffer)
|
|||||||
|
|
||||||
// remove any trailing/padding data
|
// remove any trailing/padding data
|
||||||
status_t status = gBufferModule->trim(buffer, packetLength);
|
status_t status = gBufferModule->trim(buffer, packetLength);
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
// check for fragmentation
|
// check for fragmentation
|
||||||
@ -1509,7 +1561,7 @@ ipv4_receive_data(net_buffer *buffer)
|
|||||||
return EAFNOSUPPORT;
|
return EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer->flags & MSG_MCAST) {
|
if ((buffer->flags & MSG_MCAST) != 0) {
|
||||||
// Unfortunely historical reasons dictate that the IP multicast
|
// Unfortunely historical reasons dictate that the IP multicast
|
||||||
// model be a little different from the unicast one. We deliver
|
// model be a little different from the unicast one. We deliver
|
||||||
// this frame directly to all sockets registered with interest
|
// this frame directly to all sockets registered with interest
|
||||||
@ -1548,37 +1600,6 @@ ipv4_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
dump_ipv4_multicast(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
MulticastState::Iterator it = sMulticastState->GetIterator();
|
|
||||||
|
|
||||||
while (it.HasNext()) {
|
|
||||||
IPv4GroupInterface *state = it.Next();
|
|
||||||
|
|
||||||
char addrBuf[64];
|
|
||||||
|
|
||||||
kprintf("%p: group <%s, %s, %s {", state, state->Interface()->name,
|
|
||||||
print_address(&state->Address(), addrBuf, sizeof(addrBuf)),
|
|
||||||
state->Mode() == IPv4GroupInterface::kExclude ? "Exclude" :
|
|
||||||
"Include");
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
IPv4GroupInterface::AddressSet::Iterator it =
|
|
||||||
state->Sources().GetIterator();
|
|
||||||
while (it.HasNext()) {
|
|
||||||
kprintf("%s%s", count > 0 ? ", " : "", print_address(&it.Next(),
|
|
||||||
addrBuf, sizeof(addrBuf)));
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
kprintf("}> sock %p\n", state->Parent()->Socket());
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@ -1601,7 +1622,7 @@ init_ipv4()
|
|||||||
}
|
}
|
||||||
|
|
||||||
status = sMulticastState->Init();
|
status = sMulticastState->Init();
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
goto err5;
|
goto err5;
|
||||||
|
|
||||||
sFragmentHash = hash_init(MAX_HASH_FRAGMENTS, FragmentPacket::NextOffset(),
|
sFragmentHash = hash_init(MAX_HASH_FRAGMENTS, FragmentPacket::NextOffset(),
|
||||||
@ -1616,12 +1637,12 @@ init_ipv4()
|
|||||||
|
|
||||||
status = gStackModule->register_domain_protocols(AF_INET, SOCK_RAW, 0,
|
status = gStackModule->register_domain_protocols(AF_INET, SOCK_RAW, 0,
|
||||||
"network/protocols/ipv4/v1", NULL);
|
"network/protocols/ipv4/v1", NULL);
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
goto err6;
|
goto err6;
|
||||||
|
|
||||||
status = gStackModule->register_domain(AF_INET, "internet", &gIPv4Module,
|
status = gStackModule->register_domain(AF_INET, "internet", &gIPv4Module,
|
||||||
&gIPv4AddressModule, &sDomain);
|
&gIPv4AddressModule, &sDomain);
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
goto err6;
|
goto err6;
|
||||||
|
|
||||||
add_debugger_command("ipv4_multicast", dump_ipv4_multicast,
|
add_debugger_command("ipv4_multicast", dump_ipv4_multicast,
|
||||||
|
Loading…
Reference in New Issue
Block a user