summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Larson <slioch@eng-140.vyatta.com>2008-03-30 11:36:53 -0700
committerMichael Larson <slioch@eng-140.vyatta.com>2008-03-30 11:36:53 -0700
commit9357f49cd9387b9111c3ae7d03f149dfbd1e73f8 (patch)
tree845c3aab18dbfc5d80bcc060439c9e036cfa2985
parent8ef1c8ee0c694c0bf93e89368796ec212a6d710d (diff)
downloadquagga-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.cc2
-rw-r--r--watchlink/netlink_event.hh56
-rw-r--r--watchlink/netlink_linkstatus.cc2
-rw-r--r--watchlink/netlink_listener.cc23
-rw-r--r--watchlink/netlink_listener.hh4
-rw-r--r--watchlink/watchlink.cc21
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) {