Support getting route information for a specific destination
using SIOCGETRT. Patch by Hugo Santos. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20494 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
694e5de9b0
commit
2d55afcdf7
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _NET_ROUTE_H
|
||||
@ -27,6 +27,7 @@ struct route_entry {
|
||||
struct sockaddr *destination;
|
||||
struct sockaddr *mask;
|
||||
struct sockaddr *gateway;
|
||||
struct sockaddr *source;
|
||||
uint32_t flags;
|
||||
uint32_t mtu;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006, Haiku Inc. All Rights Reserved.
|
||||
* Copyright 2002-2007, Haiku Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _SYS_SOCKIO_H
|
||||
@ -36,6 +36,7 @@ enum {
|
||||
|
||||
SIOCGRTSIZE, /* get route table size */
|
||||
SIOCGRTTABLE, /* get route table */
|
||||
SIOCGETRT, /* get route information for destination */
|
||||
|
||||
SIOCGIFSTATS, /* get interface stats */
|
||||
SIOCGIFPARAM, /* get interface parameter */
|
||||
|
@ -305,6 +305,8 @@ datalink_control(net_domain *_domain, int32 option, void *value,
|
||||
|
||||
return list_routes(domain, config.ifc_buf, config.ifc_len);
|
||||
}
|
||||
case SIOCGETRT:
|
||||
return get_route_information(domain, value, *_length);
|
||||
|
||||
default:
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@ -35,6 +35,51 @@
|
||||
#endif
|
||||
|
||||
|
||||
class UserRouteBuffer {
|
||||
public:
|
||||
UserRouteBuffer(uint8 *buffer, size_t available)
|
||||
:
|
||||
fBuffer(buffer),
|
||||
fAvailable(available),
|
||||
fStatus(B_OK)
|
||||
{
|
||||
}
|
||||
|
||||
sockaddr *
|
||||
Copy(sockaddr *source)
|
||||
{
|
||||
sockaddr *target = (sockaddr *)fBuffer;
|
||||
|
||||
if (source == NULL || (fStatus = _Copy(source)) != B_OK)
|
||||
return NULL;
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
status_t Status() const { return fStatus; }
|
||||
|
||||
private:
|
||||
status_t
|
||||
_Copy(sockaddr *source)
|
||||
{
|
||||
if (fAvailable < source->sa_len)
|
||||
return ENOBUFS;
|
||||
|
||||
if (user_memcpy(fBuffer, source, source->sa_len) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
fAvailable -= source->sa_len;
|
||||
fBuffer += source->sa_len;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
uint8 *fBuffer;
|
||||
size_t fAvailable;
|
||||
status_t fStatus;
|
||||
};
|
||||
|
||||
|
||||
net_route_private::net_route_private()
|
||||
{
|
||||
destination = mask = gateway = NULL;
|
||||
@ -78,6 +123,25 @@ user_copy_address(const sockaddr *from, sockaddr **to)
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
user_copy_address(const sockaddr *from, sockaddr_storage *to)
|
||||
{
|
||||
if (from == NULL)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
if (user_memcpy(to, from, sizeof(sockaddr)) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
if (to->ss_len > sizeof(sockaddr)) {
|
||||
if (to->ss_len > sizeof(sockaddr_storage))
|
||||
return B_BAD_VALUE;
|
||||
if (user_memcpy(to, from, to->ss_len) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
static net_route_private *
|
||||
find_route(struct net_domain *_domain, const net_route *description)
|
||||
{
|
||||
@ -415,6 +479,55 @@ remove_route(struct net_domain *_domain, const struct net_route *removeRoute)
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
fill_route_entry(route_entry *target, void *_buffer, size_t bufferSize,
|
||||
net_route *route)
|
||||
{
|
||||
UserRouteBuffer buffer(((uint8 *)_buffer) + sizeof(route_entry),
|
||||
bufferSize - sizeof(route_entry));
|
||||
|
||||
target->destination = buffer.Copy(route->destination);
|
||||
target->mask = buffer.Copy(route->mask);
|
||||
target->gateway = buffer.Copy(route->gateway);
|
||||
target->source = buffer.Copy(route->interface->address);
|
||||
target->flags = route->flags;
|
||||
target->mtu = route->mtu;
|
||||
|
||||
return buffer.Status();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
get_route_information(struct net_domain *_domain, void *value, size_t length)
|
||||
{
|
||||
struct net_domain_private *domain = (net_domain_private *)_domain;
|
||||
|
||||
if (length < sizeof(route_entry))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
route_entry entry;
|
||||
if (user_memcpy(&entry, value, sizeof(route_entry)) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
sockaddr_storage destination;
|
||||
status_t status = user_copy_address(entry.destination, &destination);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
BenaphoreLocker locker(domain->lock);
|
||||
|
||||
net_route_private *route = find_route(domain, (sockaddr *)&destination);
|
||||
if (route == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
status = fill_route_entry(&entry, value, length, route);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
return user_memcpy(value, &entry, sizeof(route_entry));
|
||||
}
|
||||
|
||||
|
||||
struct net_route *
|
||||
get_route(struct net_domain *_domain, const struct sockaddr *address)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@ -23,11 +23,13 @@ struct net_route_private : net_route, public DoublyLinkedListLinkImpl<net_route_
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<net_route_private> RouteList;
|
||||
typedef DoublyLinkedList<net_route_info, DoublyLinkedListCLink<net_route_info> > RouteInfoList;
|
||||
typedef DoublyLinkedList<net_route_info,
|
||||
DoublyLinkedListCLink<net_route_info> > RouteInfoList;
|
||||
|
||||
|
||||
uint32 route_table_size(struct net_domain_private *domain);
|
||||
status_t list_routes(struct net_domain_private *domain, void *buffer, size_t size);
|
||||
status_t list_routes(struct net_domain_private *domain, void *buffer,
|
||||
size_t size);
|
||||
status_t control_routes(struct net_interface *interface,
|
||||
int32 option, void *argument, size_t length);
|
||||
|
||||
@ -35,7 +37,10 @@ status_t add_route(struct net_domain *domain,
|
||||
const struct net_route *route);
|
||||
status_t remove_route(struct net_domain *domain,
|
||||
const struct net_route *route);
|
||||
struct net_route *get_route(struct net_domain *domain, const struct sockaddr *address);
|
||||
status_t get_route_information(struct net_domain *domain, void *buffer,
|
||||
size_t length);
|
||||
struct net_route *get_route(struct net_domain *domain,
|
||||
const struct sockaddr *address);
|
||||
void put_route(struct net_domain *domain, struct net_route *route);
|
||||
|
||||
status_t register_route_info(struct net_domain *domain,
|
||||
|
Loading…
x
Reference in New Issue
Block a user