// // 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 #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