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:
Axel Dörfler
2007-04-01 12:06:16 +00:00
parent 694e5de9b0
commit 2d55afcdf7
5 changed files with 130 additions and 8 deletions
+2 -1
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _NET_ROUTE_H #ifndef _NET_ROUTE_H
@@ -27,6 +27,7 @@ struct route_entry {
struct sockaddr *destination; struct sockaddr *destination;
struct sockaddr *mask; struct sockaddr *mask;
struct sockaddr *gateway; struct sockaddr *gateway;
struct sockaddr *source;
uint32_t flags; uint32_t flags;
uint32_t mtu; uint32_t mtu;
}; };
+3 -2
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _SYS_SOCKIO_H #ifndef _SYS_SOCKIO_H
@@ -36,6 +36,7 @@ enum {
SIOCGRTSIZE, /* get route table size */ SIOCGRTSIZE, /* get route table size */
SIOCGRTTABLE, /* get route table */ SIOCGRTTABLE, /* get route table */
SIOCGETRT, /* get route information for destination */
SIOCGIFSTATS, /* get interface stats */ SIOCGIFSTATS, /* get interface stats */
SIOCGIFPARAM, /* get interface parameter */ SIOCGIFPARAM, /* get interface parameter */
@@ -53,4 +54,4 @@ enum {
SIOCGPGRP /* get process group */ SIOCGPGRP /* get process group */
}; };
#endif /* _SYS_SOCKIO_H */ #endif /* _SYS_SOCKIO_H */
@@ -305,6 +305,8 @@ datalink_control(net_domain *_domain, int32 option, void *value,
return list_routes(domain, config.ifc_buf, config.ifc_len); return list_routes(domain, config.ifc_buf, config.ifc_len);
} }
case SIOCGETRT:
return get_route_information(domain, value, *_length);
default: default:
{ {
+114 -1
View File
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -35,6 +35,51 @@
#endif #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() net_route_private::net_route_private()
{ {
destination = mask = gateway = NULL; 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 * static net_route_private *
find_route(struct net_domain *_domain, const net_route *description) 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 * struct net_route *
get_route(struct net_domain *_domain, const struct sockaddr *address) get_route(struct net_domain *_domain, const struct sockaddr *address)
{ {
+9 -4
View File
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * 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_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); 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, status_t control_routes(struct net_interface *interface,
int32 option, void *argument, size_t length); int32 option, void *argument, size_t length);
@@ -35,7 +37,10 @@ status_t add_route(struct net_domain *domain,
const struct net_route *route); const struct net_route *route);
status_t remove_route(struct net_domain *domain, status_t remove_route(struct net_domain *domain,
const struct net_route *route); 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); void put_route(struct net_domain *domain, struct net_route *route);
status_t register_route_info(struct net_domain *domain, status_t register_route_info(struct net_domain *domain,