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:
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user