respect SO_BROADCAST for received and sent datagrams.
- check if the destination address is specified in IPv4's SendData() - minor cleanups to IPv4's TRACE()s. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20681 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
7e99a484fb
commit
49f3c71e21
@ -50,13 +50,14 @@ public:
|
||||
status_t InitCheck() const;
|
||||
|
||||
status_t Enqueue(net_buffer *buffer);
|
||||
status_t EnqueueClone(net_buffer *buffer);
|
||||
net_buffer *Dequeue(bool clone);
|
||||
status_t BlockingDequeue(bool clone, bigtime_t timeout,
|
||||
net_buffer **_buffer);
|
||||
status_t SocketDequeue(uint32 flags, net_buffer **_buffer);
|
||||
void Clear();
|
||||
|
||||
status_t SocketEnqueue(net_buffer *buffer);
|
||||
status_t SocketDequeue(uint32 flags, net_buffer **_buffer);
|
||||
|
||||
size_t AvailableData() const;
|
||||
|
||||
void WakeAll();
|
||||
@ -65,7 +66,7 @@ public:
|
||||
|
||||
protected:
|
||||
status_t _Enqueue(net_buffer *buffer);
|
||||
status_t _EnqueueClone(net_buffer *buffer);
|
||||
status_t _SocketEnqueue(net_buffer *buffer);
|
||||
net_buffer *_Dequeue(bool clone);
|
||||
void _Clear();
|
||||
|
||||
@ -141,15 +142,22 @@ DECL_DATAGRAM_SOCKET(inline status_t)::_Enqueue(net_buffer *buffer)
|
||||
}
|
||||
|
||||
|
||||
DECL_DATAGRAM_SOCKET(inline status_t)::EnqueueClone(net_buffer *_buffer)
|
||||
DECL_DATAGRAM_SOCKET(inline status_t)::SocketEnqueue(net_buffer *_buffer)
|
||||
{
|
||||
AutoLocker _(fLock);
|
||||
return _EnqueueClone(_buffer);
|
||||
return _SocketEnqueue(_buffer);
|
||||
}
|
||||
|
||||
|
||||
DECL_DATAGRAM_SOCKET(inline status_t)::_EnqueueClone(net_buffer *_buffer)
|
||||
DECL_DATAGRAM_SOCKET(inline status_t)::_SocketEnqueue(net_buffer *_buffer)
|
||||
{
|
||||
if (_buffer->flags & MSG_BCAST) {
|
||||
// only deliver datagrams sent to a broadcast address
|
||||
// to sockets with SO_BROADCAST on.
|
||||
if (!(fSocket->options & SO_BROADCAST))
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
net_buffer *buffer = ModuleBundle::Buffer()->clone(_buffer, false);
|
||||
if (buffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
@ -31,9 +31,14 @@
|
||||
|
||||
//#define TRACE_IPV4
|
||||
#ifdef TRACE_IPV4
|
||||
# define TRACE(x) dprintf x
|
||||
# define TRACE(format, args...) \
|
||||
dprintf("IPv4 [%llu] " format "\n", system_time() , ##args)
|
||||
# define TRACE_SK(protocol, format, args...) \
|
||||
dprintf("IPv4 [%llu] %p " format "\n", system_time(), \
|
||||
protocol , ##args)
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
# define TRACE(args...) do { } while (0)
|
||||
# define TRACE_SK(args...) do { } while (0)
|
||||
#endif
|
||||
|
||||
struct ipv4_header {
|
||||
@ -211,17 +216,17 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
TRACE((" previous: %p, next: %p\n", previous, next));
|
||||
TRACE(" previous: %p, next: %p", previous, next);
|
||||
|
||||
// If we have parts of the data already, truncate as needed
|
||||
|
||||
if (previous != NULL && previous->fragment.end > start) {
|
||||
TRACE((" remove header %d bytes\n", previous->fragment.end - start));
|
||||
TRACE(" remove header %d bytes", previous->fragment.end - start);
|
||||
gBufferModule->remove_header(buffer, previous->fragment.end - start);
|
||||
start = previous->fragment.end;
|
||||
}
|
||||
if (next != NULL && next->fragment.start < end) {
|
||||
TRACE((" remove trailer %d bytes\n", next->fragment.start - end));
|
||||
TRACE(" remove trailer %d bytes", next->fragment.start - end);
|
||||
gBufferModule->remove_trailer(buffer, next->fragment.start - end);
|
||||
end = next->fragment.start;
|
||||
}
|
||||
@ -238,7 +243,7 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
|
||||
buffer->fragment.end = end;
|
||||
|
||||
status_t status = gBufferModule->merge(buffer, previous, false);
|
||||
TRACE((" merge previous: %s\n", strerror(status)));
|
||||
TRACE(" merge previous: %s", strerror(status));
|
||||
if (status < B_OK) {
|
||||
fFragments.Insert(next, previous);
|
||||
return status;
|
||||
@ -254,7 +259,7 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
|
||||
fBytesLeft -= IP_MAXPACKET - end;
|
||||
}
|
||||
|
||||
TRACE((" hole length: %d\n", (int)fBytesLeft));
|
||||
TRACE(" hole length: %d", (int)fBytesLeft);
|
||||
|
||||
return B_OK;
|
||||
} else if (next != NULL && next->fragment.start == end) {
|
||||
@ -264,7 +269,7 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
|
||||
buffer->fragment.end = next->fragment.end;
|
||||
|
||||
status_t status = gBufferModule->merge(buffer, next, true);
|
||||
TRACE((" merge next: %s\n", strerror(status)));
|
||||
TRACE(" merge next: %s", strerror(status));
|
||||
if (status < B_OK) {
|
||||
fFragments.Insert((net_buffer *)previous->link.next, next);
|
||||
return status;
|
||||
@ -280,14 +285,14 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
|
||||
fBytesLeft -= IP_MAXPACKET - end;
|
||||
}
|
||||
|
||||
TRACE((" hole length: %d\n", (int)fBytesLeft));
|
||||
TRACE(" hole length: %d", (int)fBytesLeft);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// We couldn't merge the fragments, so we need to add it as is
|
||||
|
||||
TRACE((" new fragment: %p, bytes %d-%d\n", buffer, start, end));
|
||||
TRACE(" new fragment: %p, bytes %d-%d", buffer, start, end);
|
||||
|
||||
buffer->fragment.start = start;
|
||||
buffer->fragment.end = end;
|
||||
@ -301,7 +306,7 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
|
||||
fBytesLeft -= IP_MAXPACKET - end;
|
||||
}
|
||||
|
||||
TRACE((" hole length: %d\n", (int)fBytesLeft));
|
||||
TRACE(" hole length: %d", (int)fBytesLeft);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@ -373,7 +378,7 @@ FragmentPacket::Hash(void *_packet, const void *_key, uint32 range)
|
||||
FragmentPacket::StaleTimer(struct net_timer *timer, void *data)
|
||||
{
|
||||
FragmentPacket *packet = (FragmentPacket *)data;
|
||||
TRACE(("Assembling FragmentPacket %p timed out!\n", packet));
|
||||
TRACE("Assembling FragmentPacket %p timed out!", packet);
|
||||
|
||||
BenaphoreLocker locker(&sFragmentLock);
|
||||
|
||||
@ -464,8 +469,8 @@ reassemble_fragments(const ipv4_header &header, net_buffer **_buffer)
|
||||
uint16 end = start + header.TotalLength() - header.HeaderLength();
|
||||
bool lastFragment = (fragmentOffset & IP_MORE_FRAGMENTS) == 0;
|
||||
|
||||
TRACE((" Received IPv4 %sfragment of size %d, offset %d.\n",
|
||||
lastFragment ? "last ": "", end - start, start));
|
||||
TRACE(" Received IPv4 %sfragment of size %d, offset %d.",
|
||||
lastFragment ? "last ": "", end - start, start);
|
||||
|
||||
// Remove header unless this is the first fragment
|
||||
if (start != 0)
|
||||
@ -500,8 +505,7 @@ static status_t
|
||||
send_fragments(ipv4_protocol *protocol, struct net_route *route,
|
||||
net_buffer *buffer, uint32 mtu)
|
||||
{
|
||||
TRACE(("ipv4 needs to fragment (size %lu, MTU %lu)...\n",
|
||||
buffer->size, mtu));
|
||||
TRACE_SK(protocol, "SendFragments(%lu bytes, mtu %lu)", buffer->size, mtu);
|
||||
|
||||
NetBufferHeaderReader<ipv4_header> originalHeader(buffer);
|
||||
if (originalHeader.Status() < B_OK)
|
||||
@ -581,7 +585,7 @@ raw_receive_data(net_buffer *buffer)
|
||||
{
|
||||
BenaphoreLocker locker(sRawSocketsLock);
|
||||
|
||||
TRACE(("ipv4:raw_receive_data(): protocol %i\n", buffer->protocol));
|
||||
TRACE("RawReceiveData(%i)", buffer->protocol);
|
||||
|
||||
RawSocketList::Iterator iterator = sRawSockets.GetIterator();
|
||||
|
||||
@ -589,7 +593,7 @@ raw_receive_data(net_buffer *buffer)
|
||||
RawSocket *raw = iterator.Next();
|
||||
|
||||
if (raw->Socket()->protocol == buffer->protocol)
|
||||
raw->EnqueueClone(buffer);
|
||||
raw->SocketEnqueue(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -662,6 +666,8 @@ ipv4_open(net_protocol *_protocol)
|
||||
return status;
|
||||
}
|
||||
|
||||
TRACE_SK(protocol, "Open()");
|
||||
|
||||
protocol->raw = raw;
|
||||
|
||||
BenaphoreLocker locker(sRawSocketsLock);
|
||||
@ -678,6 +684,8 @@ ipv4_close(net_protocol *_protocol)
|
||||
if (raw == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
TRACE_SK(protocol, "Close()");
|
||||
|
||||
BenaphoreLocker locker(sRawSocketsLock);
|
||||
sRawSockets.Remove(raw);
|
||||
delete raw;
|
||||
@ -859,7 +867,8 @@ ipv4_send_routed_data(net_protocol *_protocol, struct net_route *route,
|
||||
ipv4_protocol *protocol = (ipv4_protocol *)_protocol;
|
||||
net_interface *interface = route->interface;
|
||||
|
||||
TRACE(("someone tries to send some actual routed data!\n"));
|
||||
TRACE_SK(protocol, "SendRoutedData(%p, %p [%ld bytes])", route, buffer,
|
||||
buffer->size);
|
||||
|
||||
sockaddr_in &source = *(sockaddr_in *)&buffer->source;
|
||||
sockaddr_in &destination = *(sockaddr_in *)&buffer->destination;
|
||||
@ -908,12 +917,12 @@ ipv4_send_routed_data(net_protocol *_protocol, struct net_route *route,
|
||||
*IPChecksumField(buffer) = gBufferModule->checksum(buffer, 0,
|
||||
sizeof(ipv4_header), true);
|
||||
|
||||
TRACE(("header chksum: %ld, buffer checksum: %ld\n",
|
||||
TRACE_SK(protocol, " SendRoutedData(): header chksum: %ld, buffer checksum: %ld",
|
||||
gBufferModule->checksum(buffer, 0, sizeof(ipv4_header), true),
|
||||
gBufferModule->checksum(buffer, 0, buffer->size, true)));
|
||||
gBufferModule->checksum(buffer, 0, buffer->size, true));
|
||||
|
||||
TRACE(("destination-IP: buffer=%p addr=%p %08lx\n", buffer, &buffer->destination,
|
||||
ntohl(destination.sin_addr.s_addr)));
|
||||
TRACE_SK(protocol, " SendRoutedData(): destination: %08lx",
|
||||
ntohl(destination.sin_addr.s_addr));
|
||||
|
||||
uint32 mtu = route->mtu ? route->mtu : interface->mtu;
|
||||
if (buffer->size > mtu) {
|
||||
@ -928,7 +937,17 @@ ipv4_send_routed_data(net_protocol *_protocol, struct net_route *route,
|
||||
status_t
|
||||
ipv4_send_data(net_protocol *protocol, net_buffer *buffer)
|
||||
{
|
||||
TRACE(("someone tries to send some actual data!\n"));
|
||||
TRACE_SK(protocol, "SendData(%p [%ld bytes])", buffer, buffer->size);
|
||||
|
||||
sockaddr_in &destination = *(sockaddr_in *)&buffer->destination;
|
||||
|
||||
if (destination.sin_len == 0 || destination.sin_addr.s_addr == INADDR_ANY)
|
||||
return EDESTADDRREQ;
|
||||
else if (destination.sin_addr.s_addr == INADDR_BROADCAST) {
|
||||
// TODO check for local broadcast addresses as well?
|
||||
if (protocol && !(protocol->socket->options & SO_BROADCAST))
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
net_route *route = NULL;
|
||||
status_t status = sDatalinkModule->get_buffer_route(sDomain, buffer,
|
||||
@ -958,7 +977,8 @@ ipv4_read_data(net_protocol *_protocol, size_t numBytes, uint32 flags,
|
||||
if (raw == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
TRACE(("read is waiting for data...\n"));
|
||||
TRACE_SK(protocol, "ReadData(%lu, 0x%lx)", numBytes, flags);
|
||||
|
||||
return raw->SocketDequeue(flags, _buffer);
|
||||
}
|
||||
|
||||
@ -1003,7 +1023,7 @@ ipv4_get_mtu(net_protocol *protocol, const struct sockaddr *address)
|
||||
status_t
|
||||
ipv4_receive_data(net_buffer *buffer)
|
||||
{
|
||||
TRACE(("IPv4 received a packet (%p) of %ld size!\n", buffer, buffer->size));
|
||||
TRACE("ReceiveData(%p [%ld bytes])", buffer, buffer->size);
|
||||
|
||||
NetBufferHeaderReader<ipv4_header> bufferHeader(buffer);
|
||||
if (bufferHeader.Status() < B_OK)
|
||||
@ -1038,10 +1058,10 @@ ipv4_receive_data(net_buffer *buffer)
|
||||
|
||||
// test if the packet is really for us
|
||||
uint32 matchedAddressType;
|
||||
if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
|
||||
if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
|
||||
&buffer->interface, &matchedAddressType)) {
|
||||
TRACE(("this packet was not for us %lx -> %lx\n",
|
||||
ntohl(header.source), ntohl(header.destination)));
|
||||
TRACE(" ReceiveData(): packet was not for us %lx -> %lx",
|
||||
ntohl(header.source), ntohl(header.destination));
|
||||
return B_ERROR;
|
||||
}
|
||||
if (matchedAddressType != 0) {
|
||||
@ -1061,15 +1081,15 @@ ipv4_receive_data(net_buffer *buffer)
|
||||
if ((fragmentOffset & IP_MORE_FRAGMENTS) != 0
|
||||
|| (fragmentOffset & IP_FRAGMENT_OFFSET_MASK) != 0) {
|
||||
// this is a fragment
|
||||
TRACE((" Found a Fragment!\n"));
|
||||
TRACE(" ReceiveData(): Found a Fragment!");
|
||||
status = reassemble_fragments(header, &buffer);
|
||||
TRACE((" -> %s!\n", strerror(status)));
|
||||
TRACE(" ReceiveData(): -> %s", strerror(status));
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
if (buffer == NULL) {
|
||||
// buffer was put into fragment packet
|
||||
TRACE((" Not yet assembled...\n"));
|
||||
TRACE(" ReceiveData(): Not yet assembled.");
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
|
@ -938,7 +938,7 @@ UdpEndpoint::StoreData(net_buffer *buffer)
|
||||
{
|
||||
TRACE_EP("StoreData(%p [%ld bytes])", buffer, buffer->size);
|
||||
|
||||
return EnqueueClone(buffer);
|
||||
return SocketEnqueue(buffer);
|
||||
}
|
||||
|
||||
|
||||
|
@ -169,7 +169,7 @@ LinkProtocol::_Unregister()
|
||||
status_t
|
||||
LinkProtocol::_MonitorData(net_device_monitor *monitor, net_buffer *packet)
|
||||
{
|
||||
return ((LinkProtocol *)monitor->cookie)->EnqueueClone(packet);
|
||||
return ((LinkProtocol *)monitor->cookie)->SocketEnqueue(packet);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user