Files
poco/Net/src/Route.cpp
2012-11-08 22:56:25 -06:00

266 lines
6.7 KiB
C++

//
// Route.cpp
//
// $Id: //poco/1.4/Foundation/src/Route.cpp#2 $
//
// Library: Net
// Package: NetCore
// Module: Route
//
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/Route.h"
#ifdef POCO_NET_HAS_ROUTE
#include "Poco/Net/IPAddress.h"
#include "Poco/Net/NetException.h"
#if defined(POCO_OS_FAMILY_WINDOWS)
#include <iphlpapi.h>
#include "Route_WIN32.cpp"
#elif defined(POCO_OS_FAMILY_BSD)
#include "Route_BSD.cpp"
#elif defined(POCO_OS_FAMILY_UNIX) && (POCO_OS == POCO_OS_LINUX)
#include "Route_Linux.cpp"
#endif
namespace Poco {
namespace Net {
Route::Route(const IPAddress& dst, const IPAddress& netmask, const IPAddress& nextHop, unsigned ifIndex, RouteType type) :
_dst(dst),
_netmask(netmask),
_nextHop(nextHop),
_ifIndex(ifIndex),
_type(type),
_metric(ROUTE_METRIC_UNKNOWN),
_mtu(ROUTE_MTU_UNKNOWN),
_hops(ROUTE_HOPS_UNKNOWN),
_use(~ROUTE_USE_UNKNOWN),
_proto(ROUTE_PROTO_NONE),
_created(ROUTE_CREATED_UNKNOWN)
{
if (_dst.family() != _nextHop.family())
throw InvalidArgumentException("Destination and nextHop have different families");
}
Route::Route(const IPAddress& dst, const IPAddress& netmask, unsigned ifIndex, RouteType type) :
_dst(dst),
_netmask(netmask),
_nextHop(IPAddress(dst.family())),
_ifIndex(ifIndex),
_type(type),
_metric(ROUTE_METRIC_UNKNOWN),
_mtu(ROUTE_MTU_UNKNOWN),
_hops(ROUTE_HOPS_UNKNOWN),
_use(~ROUTE_USE_UNKNOWN),
_proto(ROUTE_PROTO_NONE),
_created(ROUTE_CREATED_UNKNOWN)
{
if (_dst.family() != _nextHop.family())
throw InvalidArgumentException("Destination and nextHop have different families");
}
Route::Route(const IPAddress& dst, unsigned prefix, const IPAddress& nextHop, unsigned ifIndex, RouteType type) :
_dst(dst),
_netmask(IPAddress(prefix, dst.family())),
_nextHop(nextHop),
_ifIndex(ifIndex),
_type(type),
_metric(ROUTE_METRIC_UNKNOWN),
_mtu(ROUTE_MTU_UNKNOWN),
_hops(ROUTE_HOPS_UNKNOWN),
_use(~ROUTE_USE_UNKNOWN),
_proto(ROUTE_PROTO_NONE),
_created(ROUTE_CREATED_UNKNOWN)
{
if (_dst.family() != _nextHop.family())
throw InvalidArgumentException("Destination and nextHop have different families");
}
Route::Route(const IPAddress& dst, unsigned prefix, unsigned ifIndex, RouteType type) :
_dst(dst),
_netmask(IPAddress(prefix, dst.family())),
_nextHop(IPAddress(dst.family())),
_ifIndex(ifIndex),
_type(type),
_metric(ROUTE_METRIC_UNKNOWN),
_mtu(ROUTE_MTU_UNKNOWN),
_hops(ROUTE_HOPS_UNKNOWN),
_use(~ROUTE_USE_UNKNOWN),
_proto(ROUTE_PROTO_NONE),
_created(ROUTE_CREATED_UNKNOWN)
{
if (_dst.family() != _nextHop.family())
throw InvalidArgumentException("Destination and nextHop have different families");
}
Route::~Route()
{
}
std::time_t Route::getAge() const
{
std::time_t now = std::time(NULL);
return ((_created != 0) ? (now - _created.epochTime()) : 0);
}
void Route::setAge(std::time_t created)
{
std::time_t now;
time(&now);
if (_created > now)
throw std::invalid_argument("Creation time can't be in future");
_created = Timestamp::fromEpochTime(created);
}
void Route::setProto(RouteProto proto)
{
#if defined(_WIN32)
if (proto > ROUTE_PROTO_BGP) proto = ROUTE_PROTO_OTHER;
#endif
_proto = proto;
}
Route::RouteList Route::defaults(IPAddress::Family family)
{
Route::RouteList defaults, routes = Route::list(family);
RouteList::const_iterator it = routes.begin();
RouteList::const_iterator end = routes.end();
for (; it != end; ++it)
{
if (it->getPrefix() != 0) continue;
// look for insertion point
Route::RouteList::iterator it2 = defaults.begin();
Route::RouteList::const_iterator end = defaults.end();
while (it2 != end && it2->getMetric() <= it->getMetric())
++it2;
defaults.insert(it2, *it);
}
return defaults;
}
Route::RouteList Route::match(IPAddress target)
{
Route::RouteList targets, routes = Route::list(target.family());
RouteList::const_iterator it = routes.begin();
RouteList::const_iterator end = routes.end();
for (; it != end; ++it)
{
if ((target & it->getNetmask()) != it->getDest()) continue;
// look for insertion point
Route::RouteList::iterator it2 = targets.begin();
while (it2 != targets.end()
&& (it2->getPrefix() > it->getPrefix()
|| (it2->getPrefix() == it->getPrefix() &&
it2->getMetric() <= it->getMetric())))
{
++it2;
}
targets.insert(it2, *it);
}
return targets;
}
const IPAddress Route::getDefaultAddress(IPAddress::Family family)
{
Route::RouteList routes = Route::defaults(family);
if (! routes.empty()) {
Route::RouteList::const_iterator it = routes.begin();
IPAddress addr = it->getNetworkInterface().firstAddress(family);
return addr;
}
return IPAddress::wildcard(family);
}
std::string Route::protocolName(Route::RouteProto proto)
{
switch (proto) {
default:
return "unknown";
case ROUTE_PROTO_OTHER:
return "other";
case ROUTE_PROTO_LOCAL:
return "local";
case ROUTE_PROTO_NET_MGMT:
return "netmgmt";
case ROUTE_PROTO_ICMP:
return "icmp";
case ROUTE_PROTO_EGP:
return "egp";
case ROUTE_PROTO_GGP:
return "ggp";
case ROUTE_PROTO_HELLO:
return "hello";
case ROUTE_PROTO_RIP:
return "rip";
case ROUTE_PROTO_ISIS:
return "isis";
case ROUTE_PROTO_ESIS:
return "esis";
case ROUTE_PROTO_CISCO:
return "cisco";
case ROUTE_PROTO_BBN:
return "bbn";
case ROUTE_PROTO_OSPF:
return "ospf";
case ROUTE_PROTO_BGP:
return "bgp";
}
}
}} // namespace Poco::Net
#endif // POCO_NET_HAS_ROUTE