mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 16:48:06 +02:00
266 lines
6.7 KiB
C++
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
|