// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// Copyright (c) 2001-2007 International Computer Science Institute
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software")
// to deal in the Software without restriction, subject to the conditions
// listed in the XORP LICENSE file. These conditions include: you must
// preserve this copyright notice, and you cannot mention the copyright
// holders in advertising related to the Software without their permission.
// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
// notice is a summary of the XORP LICENSE file; the license in that file is
// legally binding.
#ident "$XORP: xorp/fea/ifconfig.cc,v 1.52 2007/02/16 22:45:41 pavlin Exp $"
#include "fea_module.h"
#include "libxorp/xorp.h"
#include "libxorp/xlog.h"
#include "libxorp/debug.h"
#include "libcomm/comm_api.h"
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include "ifconfig.hh"
//
// Network interfaces related configuration.
//
static bool
map_changes(const IfTreeItem::State& fci,
IfConfigUpdateReporterBase::Update& u)
{
switch (fci) {
case IfTreeItem::NO_CHANGE:
return false;
case IfTreeItem::CREATED:
u = IfConfigUpdateReporterBase::CREATED;
break;
case IfTreeItem::DELETED:
u = IfConfigUpdateReporterBase::DELETED;
break;
case IfTreeItem::CHANGED:
u = IfConfigUpdateReporterBase::CHANGED;
break;
default:
XLOG_FATAL("Unknown IfTreeItem::State");
break;
}
return true;
}
IfConfig::IfConfig(EventLoop& eventloop,
IfConfigUpdateReporterBase& ur,
IfConfigErrorReporterBase& er,
NexthopPortMapper& nexthop_port_mapper)
: _eventloop(eventloop), _ur(ur), _er(er),
_nexthop_port_mapper(nexthop_port_mapper),
_restore_original_config_on_shutdown(false),
_local_config(NULL),
_ifc_get_primary(NULL),
_ifc_set_primary(NULL),
_ifc_observer_primary(NULL),
_ifc_get_dummy(*this),
_ifc_get_ioctl(*this),
_ifc_get_sysctl(*this),
_ifc_get_getifaddrs(*this),
_ifc_get_proc_linux(*this),
_ifc_get_netlink(*this),
_ifc_get_iphelper(*this),
_ifc_get_click(*this),
_ifc_set_dummy(*this),
_ifc_set_ioctl(*this),
_ifc_set_netlink(*this),
_ifc_set_iphelper(*this),
_ifc_set_click(*this),
_ifc_observer_dummy(*this),
_ifc_observer_rtsock(*this),
_ifc_observer_netlink(*this),
_ifc_observer_iphelper(*this),
_have_ipv4(false),
_have_ipv6(false),
_is_dummy(false),
_is_running(false)
{
//
// Check that all necessary mechanisms to interact with the
// underlying system are in place.
//
if (_ifc_get_primary == NULL) {
XLOG_FATAL("No primary mechanism to get the network interface "
"information from the underlying system");
}
if (_ifc_set_primary == NULL) {
XLOG_FATAL("No primary mechanism to set the network interface "
"information into the underlying system");
}
if (_ifc_observer_primary == NULL) {
XLOG_FATAL("No primary mechanism to observe the network interface "
"information from the underlying system");
}
//
// Test if the system supports IPv4 and IPv6 respectively
//
_have_ipv4 = test_have_ipv4();
_have_ipv6 = test_have_ipv6();
}
IfConfig::~IfConfig()
{
string error_msg;
if (stop(error_msg) != XORP_OK) {
XLOG_ERROR("Cannot stop the mechanism for manipulating "
"the network interfaces: %s",
error_msg.c_str());
}
}
int
IfConfig::register_ifc_get_primary(IfConfigGet *ifc_get)
{
_ifc_get_primary = ifc_get;
if (ifc_get != NULL)
ifc_get->set_primary();
return (XORP_OK);
}
int
IfConfig::register_ifc_set_primary(IfConfigSet *ifc_set)
{
_ifc_set_primary = ifc_set;
if (ifc_set != NULL)
ifc_set->set_primary();
return (XORP_OK);
}
int
IfConfig::register_ifc_observer_primary(IfConfigObserver *ifc_observer)
{
_ifc_observer_primary = ifc_observer;
if (ifc_observer != NULL)
ifc_observer->set_primary();
return (XORP_OK);
}
int
IfConfig::register_ifc_get_secondary(IfConfigGet *ifc_get)
{
if (ifc_get != NULL) {
_ifc_gets_secondary.push_back(ifc_get);
ifc_get->set_secondary();
}
return (XORP_OK);
}
int
IfConfig::register_ifc_set_secondary(IfConfigSet *ifc_set)
{
if (ifc_set != NULL) {
_ifc_sets_secondary.push_back(ifc_set);
ifc_set->set_secondary();
}
return (XORP_OK);
}
int
IfConfig::register_ifc_observer_secondary(IfConfigObserver *ifc_observer)
{
if (ifc_observer != NULL) {
_ifc_observers_secondary.push_back(ifc_observer);
ifc_observer->set_secondary();
}
return (XORP_OK);
}
int
IfConfig::set_dummy()
{
register_ifc_get_primary(&_ifc_get_dummy);
register_ifc_set_primary(&_ifc_set_dummy);
register_ifc_observer_primary(&_ifc_observer_dummy);
//
// XXX: if we are dummy FEA, then we always have IPv4 and IPv6
//
_have_ipv4 = true;
_have_ipv6 = true;
_is_dummy = true;
return (XORP_OK);
}
int
IfConfig::start(string& error_msg)
{
list<IfConfigGet*>::iterator ifc_get_iter;
list<IfConfigSet*>::iterator ifc_set_iter;
list<IfConfigObserver*>::iterator ifc_observer_iter;
if (_is_running)
return (XORP_OK);
//
// Start the IfConfigGet methods
//
if (_ifc_get_primary != NULL) {
if (_ifc_get_primary->start(error_msg) < 0)
return (XORP_ERROR);
}
for (ifc_get_iter = _ifc_gets_secondary.begin();
ifc_get_iter != _ifc_gets_secondary.end();
++ifc_get_iter) {
IfConfigGet* ifc_get = *ifc_get_iter;
if (ifc_get->start(error_msg) < 0)
return (XORP_ERROR);
}
//
// Start the IfConfigSet methods
//
if (_ifc_set_primary != NULL) {
if (_ifc_set_primary->start(error_msg) < 0)
return (XORP_ERROR);
}
for (ifc_set_iter = _ifc_sets_secondary.begin();
ifc_set_iter != _ifc_sets_secondary.end();
++ifc_set_iter) {
IfConfigSet* ifc_set = *ifc_set_iter;
if (ifc_set->start(error_msg) < 0)
return (XORP_ERROR);
}
//
// Start the IfConfigObserver methods
//
if (_ifc_observer_primary != NULL) {
if (_ifc_observer_primary->start(error_msg) < 0)
return (XORP_ERROR);
}
for (ifc_observer_iter = _ifc_observers_secondary.begin();
ifc_observer_iter != _ifc_observers_secondary.end();
++ifc_observer_iter) {
IfConfigObserver* ifc_observer = *ifc_observer_iter;
if (ifc_observer->start(error_msg) < 0)
return (XORP_ERROR);
}
_live_config = pull_config();
_live_config.finalize_state();
_original_config = _live_config;
_original_config.finalize_state();
debug_msg("Start configuration read: %s\n", _live_config.str().c_str());
debug_msg("\nEnd configuration read.\n");
_is_running = true;
return (XORP_OK);
}
int
IfConfig::stop(string& error_msg)
{
list<IfConfigGet*>::iterator ifc_get_iter;
list<IfConfigSet*>::iterator ifc_set_iter;
list<IfConfigObserver*>::iterator ifc_observer_iter;
int ret_value = XORP_OK;
string error_msg2;
if (! _is_running)
return (XORP_OK);
error_msg.erase();
//
// Restore the original config
//
if (restore_original_config_on_shutdown()) {
pull_config();
IfTree tmp_push_tree = _original_config;
tmp_push_tree.prepare_replacement_state(_pulled_config);
if (push_config(tmp_push_tree) != true) {
error_msg2 = push_error();
if (error_msg.empty())
error_msg = error_msg2;
}
}
//
// Stop the IfConfigObserver methods
//
for (ifc_observer_iter = _ifc_observers_secondary.begin();
ifc_observer_iter != _ifc_observers_secondary.end();
++ifc_observer_iter) {
IfConfigObserver* ifc_observer = *ifc_observer_iter;
if (ifc_observer->stop(error_msg2) < 0) {
ret_value = XORP_ERROR;
if (error_msg.empty())
error_msg = error_msg2;
}
}
if (_ifc_observer_primary != NULL) {
if (_ifc_observer_primary->stop(error_msg2) < 0) {
ret_value = XORP_ERROR;
if (error_msg.empty())
error_msg = error_msg2;
}
}
//
// Stop the IfConfigSet methods
//
for (ifc_set_iter = _ifc_sets_secondary.begin();
ifc_set_iter != _ifc_sets_secondary.end();
++ifc_set_iter) {
IfConfigSet* ifc_set = *ifc_set_iter;
if (ifc_set->stop(error_msg2) < 0) {
ret_value = XORP_ERROR;
if (error_msg.empty())
error_msg = error_msg2;
}
}
if (_ifc_set_primary != NULL) {
if (_ifc_set_primary->stop(error_msg2) < 0) {
ret_value = XORP_ERROR;
if (error_msg.empty())
error_msg = error_msg2;
}
}
//
// Stop the IfConfigGet methods
//
for (ifc_get_iter = _ifc_gets_secondary.begin();
ifc_get_iter != _ifc_gets_secondary.end();
++ifc_get_iter) {
IfConfigGet* ifc_get = *ifc_get_iter;
if (ifc_get->stop(error_msg2) < 0) {
ret_value = XORP_ERROR;
if (error_msg.empty())
error_msg = error_msg2;
}
}
if (_ifc_get_primary != NULL) {
if (_ifc_get_primary->stop(error_msg2) < 0) {
ret_value = XORP_ERROR;
if (error_msg.empty())
error_msg = error_msg2;
}
}
_is_running = false;
return (ret_value);
}
/**
* Test if the underlying system supports IPv4.
*
* @return true if the underlying system supports IPv4, otherwise false.
*/
bool
IfConfig::test_have_ipv4() const
{
// XXX: always return true if running in dummy mode
if (is_dummy())
return true;
XorpFd s = comm_sock_open(AF_INET, SOCK_DGRAM, 0, 0);
if (!s.is_valid())
return (false);
comm_close(s);
return (true);
}
/**
* Test if the underlying system supports IPv6.
*
* @return true if the underlying system supports IPv6, otherwise false.
*/
bool
IfConfig::test_have_ipv6() const
{
// XXX: always return true if running in dummy mode
if (is_dummy())
return true;
#ifndef HAVE_IPV6
return (false);
#else
XorpFd s = comm_sock_open(AF_INET6, SOCK_DGRAM, 0, 0);
if (!s.is_valid())
return (false);
comm_close(s);
return (true);
#endif // HAVE_IPV6
}
/**
* Enable/disable Click support.
*
* @param enable if true, then enable Click support, otherwise disable it.
*/
void
IfConfig::enable_click(bool enable)
{
_ifc_get_click.enable_click(enable);
_ifc_set_click.enable_click(enable);
}
/**
* Start Click support.
*
* @param error_msg the error message (if error).
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int
IfConfig::start_click(string& error_msg)
{
if (_ifc_get_click.start(error_msg) < 0) {
return (XORP_ERROR);
}
if (_ifc_set_click.start(error_msg) < 0) {
string error_msg2;
_ifc_get_click.stop(error_msg2);
return (XORP_ERROR);
}
return (XORP_OK);
}
/**
* Stop Click support.
*
* @param error_msg the error message (if error).
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int
IfConfig::stop_click(string& error_msg)
{
if (_ifc_get_click.stop(error_msg) < 0) {
string error_msg2;
_ifc_set_click.stop(error_msg2);
return (XORP_ERROR);
}
if (_ifc_set_click.stop(error_msg) < 0) {
return (XORP_ERROR);
}
return (XORP_OK);
}
/**
* Specify the external program to generate the kernel-level Click
* configuration.
*
* @param v the name of the external program to generate the kernel-level
* Click configuration.
*/
void
IfConfig::set_kernel_click_config_generator_file(const string& v)
{
_ifc_get_click.set_kernel_click_config_generator_file(v);
_ifc_set_click.set_kernel_click_config_generator_file(v);
}
/**
* Enable/disable kernel-level Click support.
*
* @param enable if true, then enable the kernel-level Click support,
* otherwise disable it.
*/
void
IfConfig::enable_kernel_click(bool enable)
{
_ifc_get_click.enable_kernel_click(enable);
_ifc_set_click.enable_kernel_click(enable);
}
/**
* Enable/disable installing kernel-level Click on startup.
*
* @param enable if true, then install kernel-level Click on startup.
*/
void
IfConfig::enable_kernel_click_install_on_startup(bool enable)
{
// XXX: only IfConfigGet should install the kernel-level Click
_ifc_get_click.enable_kernel_click_install_on_startup(enable);
_ifc_set_click.enable_kernel_click_install_on_startup(false);
}
/**
* Specify the list of kernel Click modules to load on startup if
* installing kernel-level Click on startup is enabled.
*
* @param modules the list of kernel Click modules to load.
*/
void
IfConfig::set_kernel_click_modules(const list<string>& modules)
{
_ifc_get_click.set_kernel_click_modules(modules);
_ifc_set_click.set_kernel_click_modules(modules);
}
/**
* Specify the kernel-level Click mount directory.
*
* @param directory the kernel-level Click mount directory.
*/
void
IfConfig::set_kernel_click_mount_directory(const string& directory)
{
_ifc_get_click.set_kernel_click_mount_directory(directory);
_ifc_set_click.set_kernel_click_mount_directory(directory);
}
/**
* Enable/disable user-level Click support.
*
* @param enable if true, then enable the user-level Click support,
* otherwise disable it.
*/
void
IfConfig::enable_user_click(bool enable)
{
_ifc_get_click.enable_user_click(enable);
_ifc_set_click.enable_user_click(enable);
}
/**
* Specify the user-level Click command file.
*
* @param v the name of the user-level Click command file.
*/
void
IfConfig::set_user_click_command_file(const string& v)
{
_ifc_get_click.set_user_click_command_file(v);
_ifc_set_click.set_user_click_command_file(v);
}
/**
* Specify the extra arguments to the user-level Click command.
*
* @param v the extra arguments to the user-level Click command.
*/
void
IfConfig::set_user_click_command_extra_arguments(const string& v)
{
_ifc_get_click.set_user_click_command_extra_arguments(v);
_ifc_set_click.set_user_click_command_extra_arguments(v);
}
/**
* Specify whether to execute on startup the user-level Click command.
*
* @param v if true, then execute the user-level Click command on startup.
*/
void
IfConfig::set_user_click_command_execute_on_startup(bool v)
{
// XXX: only IfConfigGet should execute the user-level Click command
_ifc_get_click.set_user_click_command_execute_on_startup(v);
_ifc_set_click.set_user_click_command_execute_on_startup(false);
}
/**
* Specify the address to use for control access to the user-level
* Click.
*
* @param v the address to use for control access to the user-level Click.
*/
void
IfConfig::set_user_click_control_address(const IPv4& v)
{
_ifc_get_click.set_user_click_control_address(v);
_ifc_set_click.set_user_click_control_address(v);
}
/**
* Specify the socket port to use for control access to the user-level
* Click.
*
* @param v the socket port to use for control access to the user-level
* Click.
*/
void
IfConfig::set_user_click_control_socket_port(uint32_t v)
{
_ifc_get_click.set_user_click_control_socket_port(v);
_ifc_set_click.set_user_click_control_socket_port(v);
}
/**
* Specify the configuration file to be used by user-level Click on
* startup.
*
* @param v the name of the configuration file to be used by user-level
* Click on startup.
*/
void
IfConfig::set_user_click_startup_config_file(const string& v)
{
_ifc_get_click.set_user_click_startup_config_file(v);
_ifc_set_click.set_user_click_startup_config_file(v);
}
/**
* Specify the external program to generate the user-level Click
* configuration.
*
* @param v the name of the external program to generate the user-level
* Click configuration.
*/
void
IfConfig::set_user_click_config_generator_file(const string& v)
{
_ifc_get_click.set_user_click_config_generator_file(v);
_ifc_set_click.set_user_click_config_generator_file(v);
}
bool
IfConfig::push_config(IfTree& config)
{
bool ret_value = false;
list<IfConfigSet*>::iterator ifc_set_iter;
if ((_ifc_set_primary == NULL) && _ifc_sets_secondary.empty())
goto ret_label;
//
// XXX: explicitly pull the current config so we can align
// the new config with the current config.
//
pull_config();
if (_ifc_set_primary != NULL) {
if (_ifc_set_primary->push_config(config) != true)
goto ret_label;
}
for (ifc_set_iter = _ifc_sets_secondary.begin();
ifc_set_iter != _ifc_sets_secondary.end();
++ifc_set_iter) {
IfConfigSet* ifc_set = *ifc_set_iter;
if (ifc_set->push_config(config) != true)
goto ret_label;
}
ret_value = true; // Success
ret_label:
//
// Save a copy of the pushed config
//
if (ret_value == true)
_pushed_config = config;
return ret_value;
}
const IfTree&
IfConfig::pull_config()
{
// Clear the old state
_pulled_config.clear();
if (_ifc_get_primary != NULL)
_ifc_get_primary->pull_config(_pulled_config);
return _pulled_config;
}
bool
IfConfig::report_update(const IfTreeInterface& fi,
bool is_system_interfaces_reportee)
{
IfConfigUpdateReporterBase::Update u;
if (map_changes(fi.state(), u)) {
_ur.interface_update(fi.ifname(), u, is_system_interfaces_reportee);
return true;
}
return false;
}
bool
IfConfig::report_update(const IfTreeInterface& fi,
const IfTreeVif& fv,
bool is_system_interfaces_reportee)
{
IfConfigUpdateReporterBase::Update u;
if (map_changes(fv.state(), u)) {
_ur.vif_update(fi.ifname(), fv.vifname(), u,
is_system_interfaces_reportee);
return true;
}
return false;
}
bool
IfConfig::report_update(const IfTreeInterface& fi,
const IfTreeVif& fv,
const IfTreeAddr4& fa,
bool is_system_interfaces_reportee)
{
IfConfigUpdateReporterBase::Update u;
if (map_changes(fa.state(), u)) {
_ur.vifaddr4_update(fi.ifname(), fv.vifname(), fa.addr(), u,
is_system_interfaces_reportee);
return true;
}
return false;
}
bool
IfConfig::report_update(const IfTreeInterface& fi,
const IfTreeVif& fv,
const IfTreeAddr6& fa,
bool is_system_interfaces_reportee)
{
IfConfigUpdateReporterBase::Update u;
if (map_changes(fa.state(), u)) {
_ur.vifaddr6_update(fi.ifname(), fv.ifname(), fa.addr(), u,
is_system_interfaces_reportee);
return true;
}
return false;
}
void
IfConfig::report_updates_completed(bool is_system_interfaces_reportee)
{
_ur.updates_completed(is_system_interfaces_reportee);
}
void
IfConfig::report_updates(IfTree& it, bool is_system_interfaces_reportee)
{
bool updated = false;
//
// Walk config looking for changes to report
//
for (IfTree::IfMap::const_iterator ii = it.ifs().begin();
ii != it.ifs().end(); ++ii) {
const IfTreeInterface& interface = ii->second;
updated |= report_update(interface, is_system_interfaces_reportee);
IfTreeInterface::VifMap::const_iterator vi;
for (vi = interface.vifs().begin();
vi != interface.vifs().end(); ++vi) {
const IfTreeVif& vif = vi->second;
updated |= report_update(interface, vif,
is_system_interfaces_reportee);
for (IfTreeVif::V4Map::const_iterator ai = vif.v4addrs().begin();
ai != vif.v4addrs().end(); ai++) {
const IfTreeAddr4& addr = ai->second;
updated |= report_update(interface, vif, addr,
is_system_interfaces_reportee);
}
for (IfTreeVif::V6Map::const_iterator ai = vif.v6addrs().begin();
ai != vif.v6addrs().end(); ai++) {
const IfTreeAddr6& addr = ai->second;
updated |= report_update(interface, vif, addr,
is_system_interfaces_reportee);
}
}
}
if (updated) {
// Complete the update
report_updates_completed(is_system_interfaces_reportee);
}
//
// Walk again and flip the enable flag for the corresponding interfaces.
//
// First, disable all interfaces that were flipped, and are still enabled,
// and report the changes.
// Then, enable those interfaces and report again the changes.
// The main idea is to inform all interested parties about the fact
// that an interface was disabled and enabled internally during the
// process of writing the information to the kernel.
//
// Disable all flipped interfaces
updated = false;
for (IfTree::IfMap::iterator ii = it.ifs().begin();
ii != it.ifs().end(); ++ii) {
IfTreeInterface& interface = ii->second;
if (! interface.flipped())
continue;
if (! interface.enabled()) {
interface.set_flipped(false);
continue;
}
interface.set_enabled(false);
updated |= report_update(interface, is_system_interfaces_reportee);
}
if (updated) {
// Complete the update
report_updates_completed(is_system_interfaces_reportee);
}
// Enable all flipped interfaces
updated = false;
for (IfTree::IfMap::iterator ii = it.ifs().begin();
ii != it.ifs().end(); ++ii) {
IfTreeInterface& interface = ii->second;
if (! interface.flipped())
continue;
interface.set_flipped(false);
if (interface.enabled()) {
continue;
}
interface.set_enabled(true);
updated |= report_update(interface, is_system_interfaces_reportee);
}
if (updated) {
// Complete the update
report_updates_completed(is_system_interfaces_reportee);
}
}
const string&
IfConfig::push_error() const
{
return _er.first_error();
}
void
IfConfig::map_ifindex(uint32_t ifindex, const string& ifname)
{
_ifnames[ifindex] = ifname;
}
void
IfConfig::unmap_ifindex(uint32_t ifindex)
{
IfIndex2NameMap::iterator i = _ifnames.find(ifindex);
if (_ifnames.end() != i)
_ifnames.erase(i);
}
const char *
IfConfig::find_ifname(uint32_t ifindex) const
{
IfIndex2NameMap::const_iterator i = _ifnames.find(ifindex);
if (_ifnames.end() == i)
return NULL;
return i->second.c_str();
}
uint32_t
IfConfig::find_ifindex(const string& ifname) const
{
IfIndex2NameMap::const_iterator i;
for (i = _ifnames.begin(); i != _ifnames.end(); ++i) {
if (i->second == ifname)
return i->first;
}
return 0;
}
const char *
IfConfig::get_insert_ifname(uint32_t ifindex)
{
IfIndex2NameMap::const_iterator i = _ifnames.find(ifindex);
if (_ifnames.end() == i) {
#ifdef HAVE_IF_INDEXTONAME
char name_buf[IF_NAMESIZE];
const char* ifname = if_indextoname(ifindex, name_buf);
if (ifname != NULL)
map_ifindex(ifindex, ifname);
return ifname;
#else
return NULL;
#endif // ! HAVE_IF_INDEXTONAME
}
return i->second.c_str();
}
uint32_t
IfConfig::get_insert_ifindex(const string& ifname)
{
IfIndex2NameMap::const_iterator i;
for (i = _ifnames.begin(); i != _ifnames.end(); ++i) {
if (i->second == ifname)
return i->first;
}
#ifdef HAVE_IF_NAMETOINDEX
uint32_t ifindex = if_nametoindex(ifname.c_str());
if (ifindex > 0)
map_ifindex(ifindex, ifname);
return ifindex;
#else
return 0;
#endif // ! HAVE_IF_NAMETOINDEX
}
IfTreeInterface *
IfConfig::get_if(IfTree& it, const string& ifname)
{
IfTree::IfMap::iterator ii = it.get_if(ifname);
if (it.ifs().end() == ii)
return NULL;
return &ii->second;
}
IfTreeVif *
IfConfig::get_vif(IfTree& it, const string& ifname, const string& vifname)
{
IfTreeInterface* fi = get_if(it, ifname);
if (NULL == fi)
return NULL;
IfTreeInterface::VifMap::iterator vi = fi->get_vif(vifname);
if (fi->vifs().end() == vi)
return NULL;
return &vi->second;
}
// ----------------------------------------------------------------------------
// IfConfigUpdateReplicator
IfConfigUpdateReplicator::~IfConfigUpdateReplicator()
{
}
bool
IfConfigUpdateReplicator::add_reporter(IfConfigUpdateReporterBase* rp)
{
if (find(_reporters.begin(), _reporters.end(), rp) != _reporters.end())
return false;
_reporters.push_back(rp);
return true;
}
bool
IfConfigUpdateReplicator::remove_reporter(IfConfigUpdateReporterBase* rp)
{
list<IfConfigUpdateReporterBase*>::iterator i = find(_reporters.begin(),
_reporters.end(),
rp);
if (i == _reporters.end())
return false;
_reporters.erase(i);
return true;
}
void
IfConfigUpdateReplicator::interface_update(const string& ifname,
const Update& update,
bool system)
{
list<IfConfigUpdateReporterBase*>::iterator i = _reporters.begin();
while (i != _reporters.end()) {
IfConfigUpdateReporterBase*& r = *i;
r->interface_update(ifname, update, system);
++i;
}
}
void
IfConfigUpdateReplicator::vif_update(const string& ifname,
const string& vifname,
const Update& update,
bool system)
{
list<IfConfigUpdateReporterBase*>::iterator i = _reporters.begin();
while (i != _reporters.end()) {
IfConfigUpdateReporterBase*& r = *i;
r->vif_update(ifname, vifname, update, system);
++i;
}
}
void
IfConfigUpdateReplicator::vifaddr4_update(const string& ifname,
const string& vifname,
const IPv4& addr,
const Update& update,
bool system)
{
list<IfConfigUpdateReporterBase*>::iterator i = _reporters.begin();
while (i != _reporters.end()) {
IfConfigUpdateReporterBase*& r = *i;
r->vifaddr4_update(ifname, vifname, addr, update, system);
++i;
}
}
void
IfConfigUpdateReplicator::vifaddr6_update(const string& ifname,
const string& vifname,
const IPv6& addr,
const Update& update,
bool system)
{
list<IfConfigUpdateReporterBase*>::iterator i = _reporters.begin();
while (i != _reporters.end()) {
IfConfigUpdateReporterBase*& r = *i;
r->vifaddr6_update(ifname, vifname, addr, update, system);
++i;
}
}
void
IfConfigUpdateReplicator::updates_completed(bool system)
{
list<IfConfigUpdateReporterBase*>::iterator i = _reporters.begin();
while (i != _reporters.end()) {
IfConfigUpdateReporterBase*& r = *i;
r->updates_completed(system);
++i;
}
}
// ----------------------------------------------------------------------------
// IfConfigErrorReporter methods
IfConfigErrorReporter::IfConfigErrorReporter()
{
}
void
IfConfigErrorReporter::config_error(const string& error_msg)
{
string preamble(c_format("Config error: "));
log_error(preamble + error_msg);
}
void
IfConfigErrorReporter::interface_error(const string& ifname,
const string& error_msg)
{
string preamble(c_format("Interface error on %s: ", ifname.c_str()));
log_error(preamble + error_msg);
}
void
IfConfigErrorReporter::vif_error(const string& ifname,
const string& vifname,
const string& error_msg)
{
string preamble(c_format("Interface/Vif error on %s/%s: ",
ifname.c_str(), vifname.c_str()));
log_error(preamble + error_msg);
}
void
IfConfigErrorReporter::vifaddr_error(const string& ifname,
const string& vifname,
const IPv4& addr,
const string& error_msg)
{
string preamble(c_format("Interface/Vif/Address error on %s/%s/%s: ",
ifname.c_str(),
vifname.c_str(),
addr.str().c_str()));
log_error(preamble + error_msg);
}
void
IfConfigErrorReporter::vifaddr_error(const string& ifname,
const string& vifname,
const IPv6& addr,
const string& error_msg)
{
string preamble(c_format("Interface/Vif/Address error on %s/%s/%s: ",
ifname.c_str(),
vifname.c_str(),
addr.str().c_str()));
log_error(preamble + error_msg);
}
syntax highlighted by Code2HTML, v. 0.9.1