diff options
author | Michael Larson <slioch@eng-140.vyatta.com> | 2008-03-30 11:36:53 -0700 |
---|---|---|
committer | Michael Larson <slioch@eng-140.vyatta.com> | 2008-03-30 11:36:53 -0700 |
commit | 9357f49cd9387b9111c3ae7d03f149dfbd1e73f8 (patch) | |
tree | 845c3aab18dbfc5d80bcc060439c9e036cfa2985 | |
parent | 8ef1c8ee0c694c0bf93e89368796ec212a6d710d (diff) | |
download | quagga-9357f49cd9387b9111c3ae7d03f149dfbd1e73f8.tar.bz2 quagga-9357f49cd9387b9111c3ae7d03f149dfbd1e73f8.tar.xz |
added interface/address exclusion support to watchlink. The correct format is:
[interface]
[interface] [ip/mask]
It should also accept a plain IP--but I haven't tested this yet.
Also added syslogging at the info level on interface up/down events.
This change provides support for HA to work with interface cable event. HA and VRRP will need to
populate the /var/linkstatus/exclude file with the VIPs under their management.
In addition to circumvent an additional problem in HA there needs to be an additional address on
the monitored interface, otherwise HA will admin down the interface when the cable is pulled
-rw-r--r-- | watchlink/netlink_event.cc | 2 | ||||
-rw-r--r-- | watchlink/netlink_event.hh | 56 | ||||
-rw-r--r-- | watchlink/netlink_linkstatus.cc | 2 | ||||
-rw-r--r-- | watchlink/netlink_listener.cc | 23 | ||||
-rw-r--r-- | watchlink/netlink_listener.hh | 4 | ||||
-rw-r--r-- | watchlink/watchlink.cc | 21 |
6 files changed, 91 insertions, 17 deletions
diff --git a/watchlink/netlink_event.cc b/watchlink/netlink_event.cc index 2880f83d..7db07764 100644 --- a/watchlink/netlink_event.cc +++ b/watchlink/netlink_event.cc @@ -6,7 +6,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. */ -#include <sys/types.h> +#include <linux/types.h> #include <sys/socket.h> #include <linux/rtnetlink.h> #include <net/if.h> diff --git a/watchlink/netlink_event.hh b/watchlink/netlink_event.hh index 7a1cdcba..91ab8f33 100644 --- a/watchlink/netlink_event.hh +++ b/watchlink/netlink_event.hh @@ -32,10 +32,12 @@ class IPv4 public: IPv4() : _addr(-1) {} IPv4(uint32_t addr) : _addr(addr) {} + virtual ~IPv4() {} uint32_t get() {return _addr;} + virtual std::string str() { @@ -44,9 +46,61 @@ public: char* buf = inet_ntoa(addr); return std::string(buf); } + +protected: + uint32_t _addr; +}; + + +class IPv4net : protected IPv4 +{ +public: + IPv4net() : IPv4(-1),_mask_length(32) {} + IPv4net(uint32_t addr, char mask_len) : IPv4(addr),_mask_length(mask_len) {} + IPv4net(std::string &net) { + int pos = net.find("/"); + if (pos == std::string::npos) { + pos = net.length(); + _mask_length = 32; + } + else { + uint32_t m_val = strtoul(net.substr(pos+1,net.length()-1).c_str(),NULL,10); + if (m_val > 32) { + m_val = 32; + } + _mask_length = m_val; + } + uint32_t a_val = inet_addr(net.substr(0,pos).c_str()); + if (a_val == INADDR_NONE) { + this->_addr = 0; + return; + } + this->_addr = a_val; + } + + uint32_t + get_addr() {return get();} + + char + get_mask_length() {return _mask_length;} + + std::string + str() + { + in_addr addr; + addr.s_addr = _addr; + char *buf = inet_ntoa(addr); + + std::string tmp(buf); + + char buf2[80]; + sprintf(buf2,"%d",_mask_length); + tmp += std::string("/") + buf2; + return tmp; + } private: - uint32_t _addr; + char _mask_length; }; diff --git a/watchlink/netlink_linkstatus.cc b/watchlink/netlink_linkstatus.cc index c03c03b2..191625f7 100644 --- a/watchlink/netlink_linkstatus.cc +++ b/watchlink/netlink_linkstatus.cc @@ -130,6 +130,7 @@ NetlinkLinkStatus::process_going_up(const NetlinkEvent &event) if (_debug) { cout << "NetlinkLinkStatus::process_going_up(): " << event.get_iface() << endl; } + syslog(LOG_INFO,"Interface is now active: %s",event.get_iface().c_str()); //check for link status file, otherwise return char buf[40]; @@ -289,6 +290,7 @@ NetlinkLinkStatus::process_going_down(const NetlinkEvent &event) if (_debug) { cout << "NetlinkLinkStatus::process_going_down(): " << event.get_iface() << "(" << event.get_index() << ")" << endl; } + syslog(LOG_INFO,"Interface is now inactive: %s",event.get_iface().c_str()); //pull interface addresses if (_nl_send.send_get(_send_sock, RTM_GETADDR, event.get_index())) { diff --git a/watchlink/netlink_listener.cc b/watchlink/netlink_listener.cc index 454931ba..57f6e00a 100644 --- a/watchlink/netlink_listener.cc +++ b/watchlink/netlink_listener.cc @@ -13,6 +13,7 @@ #include <linux/rtnetlink.h> #include <syslog.h> +#include <map> #include <vector> #include <string> #include <iostream> @@ -116,15 +117,29 @@ NetlinkListener::init() * **/ bool -NetlinkListener::process(NetlinkEvent &e, set<string> filter) +NetlinkListener::process(NetlinkEvent &e, multimap<string,IPv4net> filter) { bool state = process(e); - - if (state == true && (filter.find(e.get_iface()) != filter.end()) || - (e.get_type() == RTM_DELLINK || e.get_type() == RTM_NEWLINK) && e.get_ifi_type() != 1/*ARPHRD_ETHER*/) { + //is this a non-ethernet msg? + if ((e.get_type() == RTM_DELLINK || e.get_type() == RTM_NEWLINK) && e.get_ifi_type() != 1/*ARPHRD_ETHER*/) { e = NetlinkEvent(); state = false; } + else { + multimap<string,IPv4net>::iterator iter = filter.begin(); + while (iter != filter.end()) { + if (iter->first == e.get_iface()) { //found interface exclusion + if (iter->second.get_mask_length() == 0 || (iter->second.get_addr() == e.get_local_addr().get() && iter->second.get_mask_length() == e.get_mask_len())) { //addr match + e = NetlinkEvent(); + state = false; + break; + } + } + ++iter; + } + } + + return state; } diff --git a/watchlink/netlink_listener.hh b/watchlink/netlink_listener.hh index e2277f04..b74589a8 100644 --- a/watchlink/netlink_listener.hh +++ b/watchlink/netlink_listener.hh @@ -10,7 +10,7 @@ #define __NETLINK_LISTENER_HH__ #include "netlink_event.hh" -#include <set> +#include <map> #include <string> class NetlinkListener @@ -29,7 +29,7 @@ public: //methods process(NetlinkEvent &e); bool - process(NetlinkEvent &e, std::set<std::string> filter); + process(NetlinkEvent &e, std::multimap<std::string,IPv4net> filter); int get_sock() {return _fd;} diff --git a/watchlink/watchlink.cc b/watchlink/watchlink.cc index 4d8f0787..849e2f20 100644 --- a/watchlink/watchlink.cc +++ b/watchlink/watchlink.cc @@ -10,7 +10,7 @@ #include <iostream> #include <stdio.h> #include <string> -#include <set> +#include <map> #include <fcntl.h> #include <syslog.h> #include <errno.h> @@ -36,7 +36,7 @@ struct option longopts[] = { 0 } }; -set<string> g_exclude; +multimap<string,IPv4net> g_exclude; string g_link_dir = "/var/linkstatus"; /** @@ -59,10 +59,10 @@ usage() * * **/ -set<string> +multimap<string,IPv4net> load_exclusion_file(const string &link_dir) { - set<string> coll; + multimap<string,IPv4net> coll; string file = link_dir + "/exclude"; FILE *fp = fopen(file.c_str(), "r"); @@ -76,9 +76,14 @@ load_exclusion_file(const string &link_dir) while (fgets(str, 1024, fp)) { string line(str); - StrProc tokens(line, ","); - for (int i = 0; i < tokens.size(); ++i) { - coll.insert(tokens.get(i)); + StrProc tokens(line, " "); + if (tokens.size() == 1) { + string any("0/0"); + coll.insert(pair<string,IPv4net>(tokens.get(0),IPv4net(any))); + } + else if (tokens.size() == 2) { + string net(tokens.get(1)); + coll.insert(pair<string,IPv4net>(tokens.get(0),IPv4net(net))); } } fclose(fp); @@ -183,8 +188,6 @@ main(int argc, char* const argv[]) NetlinkLinkStatus nl_ls(sock, g_link_dir, debug); while (true) { - // cout << "watchlink: now entering listening mode: " << endl; - NetlinkEvent nl_event; if (nl_listener.process(nl_event, g_exclude) == true) { if (send_request) { |