Route OSX compile and tests

This commit is contained in:
Alex
2012-11-08 22:56:25 -06:00
parent 67a27ac2fa
commit fefe3b5d7a
6 changed files with 325 additions and 271 deletions

View File

@@ -28,7 +28,7 @@ objects = \
FTPClientSession FTPStreamFactory PartHandler PartSource NullPartHandler \ FTPClientSession FTPStreamFactory PartHandler PartSource NullPartHandler \
SocketReactor SocketNotifier SocketNotification AbstractHTTPRequestHandler \ SocketReactor SocketNotifier SocketNotification AbstractHTTPRequestHandler \
MailRecipient MailMessage MailStream SMTPClientSession POP3ClientSession \ MailRecipient MailMessage MailStream SMTPClientSession POP3ClientSession \
RawSocket RawSocketImpl ICMPClient ICMPEventArgs ICMPPacket ICMPPacketImpl \ RawSocket RawSocketImpl Route ICMPClient ICMPEventArgs ICMPPacket ICMPPacketImpl \
ICMPSocket ICMPSocketImpl ICMPv4PacketImpl \ ICMPSocket ICMPSocketImpl ICMPv4PacketImpl \
RemoteSyslogChannel RemoteSyslogListener SMTPChannel \ RemoteSyslogChannel RemoteSyslogListener SMTPChannel \
WebSocket WebSocketImpl WebSocket WebSocketImpl

View File

@@ -82,166 +82,169 @@ class RouteHelper;
class Net_API Route class Net_API Route
{ {
public: public:
typedef std::list<Route> RouteList; typedef std::list<Route> RouteList;
enum RouteType static const unsigned int ROUTE_METRIC_UNKNOWN = ~0;
{ static const unsigned int ROUTE_MTU_UNKNOWN = 0;
ROUTE_NONE = 0, static const unsigned int ROUTE_HOPS_UNKNOWN = ~0;
ROUTE_OTHER = 1, static const unsigned int ROUTE_USE_UNKNOWN = ~1;
ROUTE_INVALID = 2, static const unsigned int ROUTE_CREATED_UNKNOWN = 0;
ROUTE_DIRECT = 3,
ROUTE_INDIRECT = 4 enum RouteType
}; {
ROUTE_NONE = 0,
ROUTE_OTHER = 1,
ROUTE_INVALID = 2,
ROUTE_DIRECT = 3,
ROUTE_INDIRECT = 4
};
enum RouteProto enum RouteProto
{ {
ROUTE_PROTO_NONE = 0, ROUTE_PROTO_NONE = 0,
ROUTE_PROTO_OTHER = 1, ROUTE_PROTO_OTHER = 1,
ROUTE_PROTO_LOCAL = 2, ROUTE_PROTO_LOCAL = 2,
ROUTE_PROTO_NET_MGMT = 3, ROUTE_PROTO_NET_MGMT = 3,
ROUTE_PROTO_ICMP = 4, ROUTE_PROTO_ICMP = 4,
ROUTE_PROTO_EGP = 5, ROUTE_PROTO_EGP = 5,
ROUTE_PROTO_GGP = 6, ROUTE_PROTO_GGP = 6,
ROUTE_PROTO_HELLO = 7, ROUTE_PROTO_HELLO = 7,
ROUTE_PROTO_RIP = 8, ROUTE_PROTO_RIP = 8,
ROUTE_PROTO_ISIS = 9, ROUTE_PROTO_ISIS = 9,
ROUTE_PROTO_ESIS = 10, ROUTE_PROTO_ESIS = 10,
ROUTE_PROTO_CISCO = 11, // EIGRP? ROUTE_PROTO_CISCO = 11, // EIGRP?
ROUTE_PROTO_BBN = 12, ROUTE_PROTO_BBN = 12,
ROUTE_PROTO_OSPF = 13, ROUTE_PROTO_OSPF = 13,
ROUTE_PROTO_BGP = 14, ROUTE_PROTO_BGP = 14,
}; };
~Route(); Route(const IPAddress& dst, const IPAddress& netmask, const IPAddress& nextHop, unsigned ifIndex, RouteType type);
/// Destroys Route. /// Creates Route.
Route(const IPAddress& dst, const IPAddress& netmask, unsigned ifIndex, RouteType type);
/// Creates Route.
Route(const IPAddress& dst, unsigned prefix, const IPAddress& nextHop, unsigned ifIndex, RouteType type);
/// Creates Route.
Route(const IPAddress& dst, unsigned prefix, unsigned ifIndex, RouteType type);
/// Creates Route.
~Route();
/// Destroys Route.
const IPAddress getDest() const; const IPAddress getDest() const;
/// Returns destination. /// Returns destination.
unsigned getPrefix() const; unsigned getPrefix() const;
/// Returns prefix. /// Returns prefix.
const IPAddress getNetmask() const; const IPAddress getNetmask() const;
/// Returns net mask (IPv4 only). /// Returns net mask (IPv4 only).
const IPAddress getNextHop() const; const IPAddress getNextHop() const;
/// Returns next hop. /// Returns next hop.
unsigned getIfIndex() const; unsigned getIfIndex() const;
/// Returns interface index. /// Returns interface index.
const NetworkInterface getNetworkInterface() const; const NetworkInterface getNetworkInterface() const;
/// Returns netwrok interface. /// Returns netwrok interface.
RouteType getType() const; RouteType getType() const;
/// Returns route type. /// Returns route type.
unsigned getMetric() const; unsigned getMetric() const;
/// Returns metric; not available on all platforms. /// Returns metric; not available on all platforms.
unsigned getHops() const; unsigned getHops() const;
/// Returns hops count; not available on all platforms. /// Returns hops count; not available on all platforms.
unsigned getMTU() const; unsigned getMTU() const;
/// Returns MTU; not available on all platforms. /// Returns MTU; not available on all platforms.
unsigned getUsage() const; unsigned getUsage() const;
/// Returns usage; not available on all platforms. /// Returns usage; not available on all platforms.
RouteProto getProto() const; RouteProto getProto() const;
/// Returns proto; not available on all platforms. /// Returns proto; not available on all platforms.
std::time_t getAge() const; std::time_t getAge() const;
/// Returns age; not available on all platforms. /// Returns age; not available on all platforms.
bool validMetric() const; bool validMetric() const;
/// Returns true if metric is valid; not available on all platforms. /// Returns true if metric is valid; not available on all platforms.
bool validHops() const; bool validHops() const;
/// Returns true if hops are valid; not available on all platforms. /// Returns true if hops are valid; not available on all platforms.
bool validMTU() const; bool validMTU() const;
/// Returns true if MTU is valid; not available on all platforms. /// Returns true if MTU is valid; not available on all platforms.
bool validUsage() const; bool validUsage() const;
/// Returns true if usage is valid; not available on all platforms. /// Returns true if usage is valid; not available on all platforms.
bool validProto() const; bool validProto() const;
/// Returns true if proto is valid; not available on all platforms. /// Returns true if proto is valid; not available on all platforms.
bool validAge() const; bool validAge() const;
/// Returns true if age is valid; not available on all platforms. /// Returns true if age is valid; not available on all platforms.
bool operator == (const Route& other) const; bool operator == (const Route& other) const;
/// Return strue if this route is equal to other. /// Return strue if this route is equal to other.
bool operator != (const Route& other) const; bool operator != (const Route& other) const;
/// Return strue if this route is not equal to other. /// Return strue if this route is not equal to other.
static RouteList list(IPAddress::Family family); static RouteList list(IPAddress::Family family);
/// Retruns the list of routes. /// Retruns the list of routes.
static RouteList defaults(IPAddress::Family family); static RouteList defaults(IPAddress::Family family);
/// Returns default routes. /// Returns default routes.
static RouteList match(IPAddress target); static RouteList match(IPAddress target);
/// Retruns routes matching target. /// Retruns routes matching target.
static const IPAddress getDefaultAddress(IPAddress::Family family); static const IPAddress getDefaultAddress(IPAddress::Family family);
/// Returns default IP address for the family. /// Returns default IP address for the family.
static std::string protocolName(RouteProto proto); static std::string protocolName(RouteProto proto);
/// Returns protocol as string. /// Returns protocol as string.
protected: void setMTU(unsigned mtu);
void setMTU(unsigned mtu); /// Sets the MTU to specified value.
/// Sets the MTU to specified value.
void setAge(std::time_t created); void setAge(std::time_t created);
/// Sets MTU to specified value. /// Sets MTU to specified value.
void setProto(RouteProto proto); void setProto(RouteProto proto);
/// Sets proto to specified value. /// Sets proto to specified value.
void setMetric(unsigned metric); void setMetric(unsigned metric);
/// Sets metric to specified value. /// Sets metric to specified value.
void setHops(unsigned hops); void setHops(unsigned hops);
/// Sets hops to specified value. /// Sets hops to specified value.
void setUsage(unsigned use); void setUsage(unsigned use);
/// Sets usage to specified value. /// Sets usage to specified value.
private: private:
Route(const IPAddress& dst, const IPAddress& netmask, const IPAddress& nextHop, unsigned ifIndex, RouteType type); // portable attributes
/// Creates Route. IPAddress _dst;
IPAddress _netmask;
IPAddress _nextHop;
unsigned _ifIndex;
RouteType _type;
Route(const IPAddress& dst, const IPAddress& netmask, unsigned ifIndex, RouteType type); // optional attributes supported on some platforms
/// Creates Route. unsigned _metric;
unsigned _mtu;
Route(const IPAddress& dst, unsigned prefix, const IPAddress& nextHop, unsigned ifIndex, RouteType type); unsigned _hops;
/// Creates Route. unsigned _use;
RouteProto _proto;
Route(const IPAddress& dst, unsigned prefix, unsigned ifIndex, RouteType type); Timestamp _created;
/// Creates Route.
// portable attributes
IPAddress _dst;
IPAddress _netmask;
IPAddress _nextHop;
unsigned _ifIndex;
RouteType _type;
// optional attributes supported on some platforms
unsigned _metric;
unsigned _mtu;
unsigned _hops;
unsigned _use;
RouteProto _proto;
Timestamp _created;
friend class RouteHelper;
}; };

View File

@@ -42,10 +42,10 @@
#include "Poco/Net/IPAddress.h" #include "Poco/Net/IPAddress.h"
#include "Poco/Net/NetException.h" #include "Poco/Net/NetException.h"
#include <iphlpapi.h>
#if defined(POCO_OS_FAMILY_WINDOWS) #if defined(POCO_OS_FAMILY_WINDOWS)
#include <iphlpapi.h>
#include "Route_WIN32.cpp" #include "Route_WIN32.cpp"
#elif defined(POCO_OS_FAMILY_BSD) #elif defined(POCO_OS_FAMILY_BSD)
#include "Route_BSD.cpp" #include "Route_BSD.cpp"
@@ -57,20 +57,19 @@
namespace Poco { namespace Poco {
namespace Net { namespace Net {
Route::Route(const IPAddress& dst, const IPAddress& netmask, const IPAddress& nextHop, unsigned ifIndex, RouteType type) : Route::Route(const IPAddress& dst, const IPAddress& netmask, const IPAddress& nextHop, unsigned ifIndex, RouteType type) :
_dst(dst), _dst(dst),
_netmask(netmask), _netmask(netmask),
_nextHop(nextHop), _nextHop(nextHop),
_ifIndex(ifIndex), _ifIndex(ifIndex),
_type(type), _type(type),
// attributes that might not be available on all platforms are set to sentinel values. _metric(ROUTE_METRIC_UNKNOWN),
_metric(~0), _mtu(ROUTE_MTU_UNKNOWN),
_hops(~0), _hops(ROUTE_HOPS_UNKNOWN),
_mtu(0), _use(~ROUTE_USE_UNKNOWN),
_use(~1),
_proto(ROUTE_PROTO_NONE), _proto(ROUTE_PROTO_NONE),
_created(0) _created(ROUTE_CREATED_UNKNOWN)
{ {
if (_dst.family() != _nextHop.family()) if (_dst.family() != _nextHop.family())
throw InvalidArgumentException("Destination and nextHop have different families"); throw InvalidArgumentException("Destination and nextHop have different families");
@@ -83,13 +82,12 @@ Route::Route(const IPAddress& dst, const IPAddress& netmask, unsigned ifIndex, R
_nextHop(IPAddress(dst.family())), _nextHop(IPAddress(dst.family())),
_ifIndex(ifIndex), _ifIndex(ifIndex),
_type(type), _type(type),
// attributes that might not be available on all platforms are set to sentinel values. _metric(ROUTE_METRIC_UNKNOWN),
_metric(~0), _mtu(ROUTE_MTU_UNKNOWN),
_hops(~0), _hops(ROUTE_HOPS_UNKNOWN),
_mtu(0), _use(~ROUTE_USE_UNKNOWN),
_use(~1),
_proto(ROUTE_PROTO_NONE), _proto(ROUTE_PROTO_NONE),
_created(0) _created(ROUTE_CREATED_UNKNOWN)
{ {
if (_dst.family() != _nextHop.family()) if (_dst.family() != _nextHop.family())
throw InvalidArgumentException("Destination and nextHop have different families"); throw InvalidArgumentException("Destination and nextHop have different families");
@@ -102,31 +100,30 @@ Route::Route(const IPAddress& dst, unsigned prefix, const IPAddress& nextHop, un
_nextHop(nextHop), _nextHop(nextHop),
_ifIndex(ifIndex), _ifIndex(ifIndex),
_type(type), _type(type),
// attributes that might not be available on all platforms are set to sentinel values. _metric(ROUTE_METRIC_UNKNOWN),
_metric(~0), _mtu(ROUTE_MTU_UNKNOWN),
_hops(~0), _hops(ROUTE_HOPS_UNKNOWN),
_mtu(0), _use(~ROUTE_USE_UNKNOWN),
_use(~1),
_proto(ROUTE_PROTO_NONE), _proto(ROUTE_PROTO_NONE),
_created(0) _created(ROUTE_CREATED_UNKNOWN)
{ {
if (_dst.family() != _nextHop.family()) if (_dst.family() != _nextHop.family())
throw InvalidArgumentException("Destination and nextHop have different families"); throw InvalidArgumentException("Destination and nextHop have different families");
} }
Route::Route(const IPAddress& dst, unsigned prefix, unsigned ifIndex, RouteType type) : Route::Route(const IPAddress& dst, unsigned prefix, unsigned ifIndex, RouteType type) :
_dst(dst), _dst(dst),
_netmask(IPAddress(prefix, dst.family())), _netmask(IPAddress(prefix, dst.family())),
_nextHop(IPAddress(dst.family())), _nextHop(IPAddress(dst.family())),
_ifIndex(ifIndex), _ifIndex(ifIndex),
_type(type), _type(type),
// attributes that might not be available on all platforms are set to sentinel values. _metric(ROUTE_METRIC_UNKNOWN),
_metric(~0), _mtu(ROUTE_MTU_UNKNOWN),
_hops(~0), _hops(ROUTE_HOPS_UNKNOWN),
_mtu(0), _use(~ROUTE_USE_UNKNOWN),
_use(~1),
_proto(ROUTE_PROTO_NONE), _proto(ROUTE_PROTO_NONE),
_created(0) _created(ROUTE_CREATED_UNKNOWN)
{ {
if (_dst.family() != _nextHop.family()) if (_dst.family() != _nextHop.family())
throw InvalidArgumentException("Destination and nextHop have different families"); throw InvalidArgumentException("Destination and nextHop have different families");
@@ -167,16 +164,17 @@ void Route::setProto(RouteProto proto)
Route::RouteList Route::defaults(IPAddress::Family family) Route::RouteList Route::defaults(IPAddress::Family family)
{ {
Route::RouteList defaults, routes = Route::list(family); Route::RouteList defaults, routes = Route::list(family);
RouteList::const_iterator it = routes.begin();
for (Route::RouteList::const_iterator it = routes.begin(); RouteList::const_iterator end = routes.end();
it != routes.end(); it++) { for (; it != end; ++it)
{
if (it->getPrefix() != 0) continue; if (it->getPrefix() != 0) continue;
// look for insertion point // look for insertion point
Route::RouteList::iterator it2 = defaults.begin(); Route::RouteList::iterator it2 = defaults.begin();
Route::RouteList::const_iterator end = defaults.end(); Route::RouteList::const_iterator end = defaults.end();
while (it2 != end && it2->getMetric() <= it->getMetric()) while (it2 != end && it2->getMetric() <= it->getMetric())
it2++; ++it2;
defaults.insert(it2, *it); defaults.insert(it2, *it);
} }
@@ -187,17 +185,21 @@ Route::RouteList Route::defaults(IPAddress::Family family)
Route::RouteList Route::match(IPAddress target) Route::RouteList Route::match(IPAddress target)
{ {
Route::RouteList targets, routes = Route::list(target.family()); Route::RouteList targets, routes = Route::list(target.family());
RouteList::const_iterator it = routes.begin();
for (Route::RouteList::const_iterator it = routes.begin(); RouteList::const_iterator end = routes.end();
it != routes.end(); it++) { for (; it != end; ++it)
{
if ((target & it->getNetmask()) != it->getDest()) continue; if ((target & it->getNetmask()) != it->getDest()) continue;
// look for insertion point // look for insertion point
Route::RouteList::iterator it2 = targets.begin(); Route::RouteList::iterator it2 = targets.begin();
while (it2 != targets.end() while (it2 != targets.end()
&& (it2->getPrefix() > it->getPrefix() && (it2->getPrefix() > it->getPrefix()
|| (it2->getPrefix() == it->getPrefix() && it2->getMetric() <= it->getMetric()))) || (it2->getPrefix() == it->getPrefix() &&
it2++; it2->getMetric() <= it->getMetric())))
{
++it2;
}
targets.insert(it2, *it); targets.insert(it2, *it);
} }

View File

@@ -41,7 +41,6 @@
#include <net/route.h> #include <net/route.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <string> #include <string>
@@ -53,14 +52,20 @@
} }
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
#define SIN_OFFSET (offsetof(sockaddr_in,sin_addr)) #define SIN_OFFSET (offsetof(sockaddr_in,sin_addr))
#define SIN_LENGTH (sizeof(struct in_addr)) #define SIN_LENGTH (sizeof(struct in_addr))
#define SIN6_OFFSET (offsetof(sockaddr_in6,sin6_addr)) #define SIN6_OFFSET (offsetof(sockaddr_in6,sin6_addr))
#define SIN6_LENGTH (sizeof(struct in6_addr)) #define SIN6_LENGTH (sizeof(struct in6_addr))
namespace Poco {
namespace Net {
static int seq = rand(); static int seq = rand();
static void get_rtaddrs(unsigned addrs, struct sockaddr *sa, struct sockaddr **rti_info) static void get_rtaddrs(unsigned addrs, struct sockaddr *sa, struct sockaddr **rti_info)
{ {
for (unsigned i = 0; i < RTAX_MAX; i++) { for (unsigned i = 0; i < RTAX_MAX; i++) {
@@ -73,6 +78,7 @@ static void get_rtaddrs(unsigned addrs, struct sockaddr *sa, struct sockaddr **r
} }
} }
static IPAddress unpack_sockaddr_inX(struct sockaddr *sa, bool ipv4) static IPAddress unpack_sockaddr_inX(struct sockaddr *sa, bool ipv4)
{ {
const unsigned offset = (ipv4 ? SIN_OFFSET : SIN6_OFFSET); const unsigned offset = (ipv4 ? SIN_OFFSET : SIN6_OFFSET);
@@ -90,37 +96,34 @@ static IPAddress unpack_sockaddr_inX(struct sockaddr *sa, bool ipv4)
return ip; return ip;
} }
class RouteHelper { static Route createRoute(struct rt_msghdr2 *rtm, struct sockaddr **rti_info)
public:
static Route* createRoute(struct rt_msghdr2 *rtm, struct sockaddr **rti_info);
private:
RouteHelper();
~RouteHelper();
};
Route* RouteHelper::createRoute(struct rt_msghdr2 *rtm, struct sockaddr **rti_info)
{ {
IPAddress dest, netmask, nexthop; IPAddress dest, netmask, nexthop;
int ifIndex = rtm->rtm_index; int ifIndex = rtm->rtm_index;
bool adjacent = false; bool adjacent = false;
sa_family_t family = AF_MAX; sa_family_t family = AF_MAX;
char macaddr[16]; // should be plenty, right? char macaddr[16];
for (unsigned i = 0; i < RTAX_MAX; i++) { for (unsigned i = 0; i < RTAX_MAX; i++)
{
sockaddr* sa = (struct sockaddr*)rti_info[i]; sockaddr* sa = (struct sockaddr*)rti_info[i];
if (sa == NULL) continue; if (sa == 0) continue;
switch (i) { switch (i)
{
case RTAX_DST: case RTAX_DST:
poco_assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); poco_assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6);
family = sa->sa_family; family = sa->sa_family;
if (family == AF_INET) { if (family == AF_INET)
{
struct sockaddr_in *sin = (struct sockaddr_in *)sa; struct sockaddr_in *sin = (struct sockaddr_in *)sa;
dest = IPAddress(&sin->sin_addr, SIN_LENGTH); dest = IPAddress(&sin->sin_addr, SIN_LENGTH);
} else { }
else
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
dest = IPAddress(&sin6->sin6_addr, SIN6_LENGTH, rtm->rtm_index); dest = IPAddress(&sin6->sin6_addr, SIN6_LENGTH, rtm->rtm_index);
} }
@@ -128,27 +131,28 @@ Route* RouteHelper::createRoute(struct rt_msghdr2 *rtm, struct sockaddr **rti_in
case RTAX_GATEWAY: case RTAX_GATEWAY:
poco_assert((sa->sa_family == family || sa->sa_family == AF_LINK)); poco_assert((sa->sa_family == family || sa->sa_family == AF_LINK));
switch (sa->sa_family) { switch (sa->sa_family)
{
case AF_INET: case AF_INET:
{ {
struct sockaddr_in *sin = (struct sockaddr_in *)sa; struct sockaddr_in *sin = (struct sockaddr_in *)sa;
nexthop = IPAddress(&sin->sin_addr, SIN_LENGTH); nexthop = IPAddress(&sin->sin_addr, SIN_LENGTH);
break; break;
} }
case AF_INET6: case AF_INET6:
{ {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
nexthop = IPAddress(&sin6->sin6_addr, SIN6_LENGTH, rtm->rtm_index); nexthop = IPAddress(&sin6->sin6_addr, SIN6_LENGTH, rtm->rtm_index);
break; break;
} }
case AF_LINK: case AF_LINK:
{ {
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
adjacent = true; adjacent = true;
ifIndex = sdl->sdl_index; ifIndex = sdl->sdl_index;
memcpy(macaddr, sdl->sdl_data, sdl->sdl_alen); memcpy(macaddr, sdl->sdl_data, sdl->sdl_alen);
break; break;
} }
default: default:
break; break;
} }
@@ -168,28 +172,52 @@ Route* RouteHelper::createRoute(struct rt_msghdr2 *rtm, struct sockaddr **rti_in
} }
} }
if (rtm->rtm_flags & RTF_HOST) { if (rtm->rtm_flags & RTF_HOST)
poco_assert(! (rtm->rtm_addrs & RTA_NETMASK)); {
poco_assert(!(rtm->rtm_addrs & RTA_NETMASK));
if (family == AF_INET) if (family == AF_INET)
netmask = IPAddress(32, IPAddress::IPv4); netmask = IPAddress(32, IPAddress::IPv4);
else else
netmask = IPAddress(128, IPAddress::IPv6); netmask = IPAddress(128, IPAddress::IPv6);
} }
Route *route;
if (adjacent) if (adjacent)
route = new Route(dest, netmask, ifIndex, Route::ROUTE_DIRECT); {
Route route(dest, netmask, ifIndex, Route::ROUTE_DIRECT);
route.setMTU(rtm->rtm_rmx.rmx_mtu);
route.setHops(rtm->rtm_rmx.rmx_hopcount);
route.setUsage(rtm->rtm_use);
// OSX uses expire, not metric; we reuse metric member here
if (rtm->rtm_rmx.rmx_expire)
{
time_t expTime;
if ((expTime = rtm->rtm_rmx.rmx_expire - ::time(0)) > 0)
route.setMetric(expTime);
else route.setMetric(Route::ROUTE_METRIC_UNKNOWN);
}
else route.setMetric(Route::ROUTE_METRIC_UNKNOWN);
return route;
}
else else
route = new Route(dest, netmask, nexthop, ifIndex, Route::ROUTE_INDIRECT); {
Route route(dest, netmask, nexthop, ifIndex, Route::ROUTE_INDIRECT);
route->setMTU(rtm->rtm_rmx.rmx_mtu); route.setMTU(rtm->rtm_rmx.rmx_mtu);
route->setHops(rtm->rtm_rmx.rmx_hopcount); route.setHops(rtm->rtm_rmx.rmx_hopcount);
route->setUsage(rtm->rtm_use); route.setUsage(rtm->rtm_use);
// OSX uses expire, not metric; we reuse metric member here
return route; if (rtm->rtm_rmx.rmx_expire)
{
time_t expTime;
if ((expTime = rtm->rtm_rmx.rmx_expire - ::time(0)) > 0)
route.setMetric(expTime);
else route.setMetric(Route::ROUTE_METRIC_UNKNOWN);
}
else route.setMetric(Route::ROUTE_METRIC_UNKNOWN);
return route;
}
} }
Route::RouteList Route::list(IPAddress::Family family) Route::RouteList Route::list(IPAddress::Family family)
{ {
Route::RouteList routes; Route::RouteList routes;
@@ -208,10 +236,11 @@ Route::RouteList Route::list(IPAddress::Family family)
char *buf = new char[needed]; char *buf = new char[needed];
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
throw std::runtime_error("sysctl faield to populate routing table"); throw std::runtime_error("sysctl failed to populate routing table");
struct rt_msghdr2 *rtm = NULL; struct rt_msghdr2 *rtm = NULL;
for (char *next = buf, *lim = &buf[needed]; next < lim; next += rtm->rtm_msglen) { for (char *next = buf, *lim = &buf[needed]; next < lim; next += rtm->rtm_msglen)
{
rtm = (struct rt_msghdr2 *)next; rtm = (struct rt_msghdr2 *)next;
struct sockaddr_in *sin = (struct sockaddr_in*)(rtm + 1); struct sockaddr_in *sin = (struct sockaddr_in*)(rtm + 1);
@@ -224,14 +253,15 @@ Route::RouteList Route::list(IPAddress::Family family)
struct sockaddr* rti_info[RTAX_MAX]; struct sockaddr* rti_info[RTAX_MAX];
get_rtaddrs(rtm->rtm_addrs, (struct sockaddr *)sin, rti_info); get_rtaddrs(rtm->rtm_addrs, (struct sockaddr *)sin, rti_info);
Route *route = RouteHelper::createRoute(rtm, rti_info);
// RTF_IFSCOPE? // RTF_IFSCOPE?
routes.push_back(route); routes.push_back(createRoute(rtm, rti_info));
} }
delete[] buf; delete[] buf;
return routes; return routes;
} }
}} // namespace Poco::Net

View File

@@ -24,7 +24,7 @@ objects = \
SocketReactorTest ReactorTestSuite \ SocketReactorTest ReactorTestSuite \
MailTestSuite MailMessageTest MailStreamTest \ MailTestSuite MailMessageTest MailStreamTest \
SMTPClientSessionTest POP3ClientSessionTest \ SMTPClientSessionTest POP3ClientSessionTest \
RawSocketTest ICMPClientTest ICMPSocketTest ICMPClientTestSuite \ RawSocketTest RouteTest ICMPClientTest ICMPSocketTest ICMPClientTestSuite \
WebSocketTest WebSocketTestSuite \ WebSocketTest WebSocketTestSuite \
SyslogTest SyslogTest

View File

@@ -36,6 +36,7 @@
#include "Poco/Net/IPAddress.h" #include "Poco/Net/IPAddress.h"
#include "Poco/Net/Route.h" #include "Poco/Net/Route.h"
#include "Poco/Net/NetException.h" #include "Poco/Net/NetException.h"
#include <iostream>
#include <iomanip> #include <iomanip>
@@ -67,63 +68,6 @@ RouteTest::~RouteTest()
// with results we get back from NetworkInterface::list(). // with results we get back from NetworkInterface::list().
// //
void RouteTest::testAllRoutes()
{
Route::RouteList routes = Route::list(IPAddress::IPv4);
assert(routes.size() >= 3);
std::cout << "Active IPv4 Routes:" << std::endl;
std::cout << "=============================================================================" << std::endl;
std::cout << std::setw(17) << "Destinaton"
<< std::setw(17) << "Netmask"
<< std::setw(17) << "Gateway"
<< std::setw(17) << "Interface"
<< std::setw(8) << "Metric" << std::endl;
Route::RouteList::const_iterator it = routes.begin();
Route::RouteList::const_iterator end = routes.end();
for (; it != end; ++it)
{
IPAddress ip = it->getNetworkInterface().firstAddress(IPAddress::IPv4);
if (!ip.isLinkLocal())
{
std::string gateway = it->getNextHop().isWildcard() ? "On-link" : it->getNextHop().toString();
std::cout << std::setw(17) << it->getDest().toString()
<< std::setw(17) << it->getNetmask().toString()
<< std::setw(17) << gateway
<< std::setw(17) << ip.toString()
<< std::setw(8) << it->getMetric() << std::endl;
}
}
std::cout << "=============================================================================" << std::endl;
routes = Route::list(IPAddress::IPv6);
assert(routes.size() >= 3);
std::cout << std::endl << "Active IPv6 Routes:" << std::endl;
std::cout << "=============================================================" << std::endl;
std::cout << std::setw(4) << "If"
<< std::setw(7) << "Metric"
<< std::setw(41) << "Destinaton"
<< std::setw(8) << "Gateway"
<< std::endl;
it = routes.begin();
for (; it != end; ++it)
{
IPAddress ip = it->getNetworkInterface().firstAddress(IPAddress::IPv6);
if (!ip.isLinkLocal())
{
std::string gateway = it->getNextHop().isWildcard() ? "On-link" : it->getNextHop().toString();
std::cout << std::setw(4) << it->getIfIndex()
<< std::setw(7) << it->getMetric()
<< std::setw(41) << it->getDest().toString()
<< std::setw(8) << gateway << std::endl;
}
}
std::cout << "=============================================================" << std::endl;
}
void RouteTest::testDefaultRoute() void RouteTest::testDefaultRoute()
{ {
@@ -158,6 +102,81 @@ void RouteTest::tearDown()
} }
void RouteTest::testAllRoutes()
{
std::string metric = "Metric";
#if defined(POCO_OS_FAMILY_BSD)
metric = "Expire";
#endif
Route::RouteList routes = Route::list(IPAddress::IPv4);
assert(routes.size() >= 3);
std::cout << std::endl << "Active IPv4 Routes:" << std::endl;
std::cout << "=============================================================================" << std::endl;
std::cout << std::setw(17) << "Destinaton"
<< std::setw(17) << "Netmask"
<< std::setw(17) << "Gateway"
<< std::setw(17) << "Interface"
<< std::setw(8) << metric << std::endl;
Route::RouteList::const_iterator it = routes.begin();
Route::RouteList::const_iterator end = routes.end();
for (; it != end; ++it)
{
IPAddress ip = it->getNetworkInterface().firstAddress(IPAddress::IPv4);
if (!ip.isLinkLocal())
{
std::string gateway = it->getNextHop().isWildcard() ? "On-link" : it->getNextHop().toString();
std::cout << std::setw(17) << it->getDest().toString()
<< std::setw(17) << it->getNetmask().toString()
<< std::setw(17) << gateway
#if defined(POCO_OS_FAMILY_BSD)
<< std::setw(17) << it->getNetworkInterface().name();
#else
<< std::setw(17) << ip.toString();
#endif
if (it->getMetric() != Route::ROUTE_METRIC_UNKNOWN)
std::cout << std::setw(8) << it->getMetric();
std::cout << std::endl;
}
}
std::cout << "=============================================================================" << std::endl;
routes = Route::list(IPAddress::IPv6);
assert(routes.size() >= 3);
std::cout << std::endl << "Active IPv6 Routes:" << std::endl;
std::cout << "=============================================================" << std::endl;
std::cout << std::setw(4) << "If"
<< std::setw(7) << metric
<< std::setw(41) << "Destinaton"
<< std::setw(41) << "Gateway"
<< std::endl;
it = routes.begin();
for (; it != end; ++it)
{
IPAddress ip = it->getNetworkInterface().firstAddress(IPAddress::IPv6);
if (!ip.isLinkLocal())
{
std::string gateway = it->getNextHop().isWildcard() ? "On-link" : it->getNextHop().toString();
#if defined(POCO_OS_FAMILY_BSD)
std::cout << std::setw(4) << it->getNetworkInterface().name();
#else
std::cout << std::setw(4) << it->getIfIndex();
#endif
if (it->getMetric() != Route::ROUTE_METRIC_UNKNOWN)
std::cout << std::setw(7) << it->getMetric();
else
std::cout << std::setw(7) << "";
std::cout << std::setw(41) << it->getDest().toString()
<< std::setw(41) << gateway << std::endl;
}
}
std::cout << "=============================================================" << std::endl;
}
CppUnit::Test* RouteTest::suite() CppUnit::Test* RouteTest::suite()
{ {
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("RouteTest"); CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("RouteTest");