* Spotted a few reference counting bugs that were probably responsible for

, although I could not reproduce the exact problem.
* net_datalink::is_local_[link_]address() now releases a previous reference if
  the _interfaceAddress arguments does not point to NULL.
* When a buffer is received from a device, it's interface_address should be NULL
  already.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38118 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2010-08-15 13:21:42 +00:00
parent 11eccb54e2
commit 44a3d0d1f6
2 changed files with 29 additions and 12 deletions
src/add-ons/kernel/network/stack

@ -164,7 +164,17 @@ get_interface_name_or_index(net_domain* domain, int32 option, void* value,
}
status_t
static void
set_interface_address(net_interface_address*& target, InterfaceAddress* address)
{
if (target != NULL)
static_cast<InterfaceAddress*>(target)->ReleaseReference();
target = address;
}
static status_t
fill_address(const sockaddr* from, sockaddr* to, size_t maxLength)
{
if (from != NULL) {
@ -260,7 +270,7 @@ datalink_control(net_domain* _domain, int32 option, void* value,
return status;
}
case SIOCGIFCOUNT:
{
// count number of interfaces
@ -340,7 +350,7 @@ datalink_send_routed_data(struct net_route* route, net_buffer* buffer)
{
TRACE("%s(route %p, buffer %p)\n", __FUNCTION__, route, buffer);
net_interface_address* address = route->interface_address;
InterfaceAddress* address = (InterfaceAddress*)route->interface_address;
Interface* interface = (Interface*)address->interface;
//dprintf("send buffer (%ld bytes) to interface %s (route flags %lx)\n",
@ -356,7 +366,8 @@ datalink_send_routed_data(struct net_route* route, net_buffer* buffer)
// We set the interface address here, so the buffer is delivered
// directly to the domain in interfaces.cpp:device_consumer_thread()
buffer->interface_address = address;
address->AcquireReference();
set_interface_address(buffer->interface_address, address);
// this one goes back to the domain directly
return fifo_enqueue_buffer(
@ -408,7 +419,7 @@ datalink_send_data(net_protocol* protocol, net_domain* domain,
&route);
} else
status = get_buffer_route(domain, buffer, &route);
TRACE(" route status: %s\n", strerror(status));
if (status != B_OK)
@ -422,8 +433,10 @@ datalink_send_data(net_protocol* protocol, net_domain* domain,
/*! Tests if \a address is a local address in the domain.
\param _interface will be set to the interface belonging to that address
if non-NULL.
\param _interfaceAddress will be set to the interface address belonging to
that address if non-NULL. If the address \a _interfaceAddress points to
is not NULL, it is assumed that it already points to an address, which
is then released before the new address is assigned.
\param _matchedType will be set to either zero or MSG_BCAST if non-NULL.
*/
static bool
@ -457,7 +470,7 @@ datalink_is_local_address(net_domain* domain, const struct sockaddr* address,
TRACE(" it is, interface address %p\n", interfaceAddress);
if (_interfaceAddress != NULL)
*_interfaceAddress = interfaceAddress;
set_interface_address(*_interfaceAddress, interfaceAddress);
else
interfaceAddress->ReleaseReference();
@ -472,7 +485,10 @@ datalink_is_local_address(net_domain* domain, const struct sockaddr* address,
\param unconfiguredOnly only unconfigured interfaces are taken into account.
\param _interfaceAddress will be set to the first address of the interface
and domain belonging to that address if non-NULL.
and domain belonging to that address if non-NULL. If the address
\a _interfaceAddress points to is not NULL, it is assumed that it
already points to an address, which is then released before the new
address is assigned.
*/
static bool
datalink_is_local_link_address(net_domain* domain, bool unconfiguredOnly,
@ -496,7 +512,7 @@ datalink_is_local_link_address(net_domain* domain, bool unconfiguredOnly,
}
if (_interfaceAddress != NULL)
*_interfaceAddress = interfaceAddress;
set_interface_address(*_interfaceAddress, interfaceAddress);
else
interfaceAddress->ReleaseReference();

@ -59,7 +59,8 @@ device_reader_thread(void* _interface)
if (atomic_get(&interface->monitor_count) > 0)
device_interface_monitor_receive(interface, buffer);
buffer->interface_address = NULL;
ASSERT(buffer->interface_address == NULL);
if (interface->deframe_func(interface->device, buffer) != B_OK) {
gNetBufferModule.free(buffer);
continue;
@ -307,7 +308,7 @@ get_device_interface_address(net_device_interface* interface,
address.sdl_alen = interface->device->address.length;
memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen);
address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data)
address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data)
+ address.sdl_nlen + address.sdl_alen;
}