diff --git a/src/iface.cc b/src/iface.cc index 3fd949f..9a04f05 100644 --- a/src/iface.cc +++ b/src/iface.cc @@ -42,12 +42,12 @@ NDPPD_NS_BEGIN -std::map > iface::_map; +std::map > iface::_map; std::vector iface::_pollfds; iface::iface() : - _ifd(-1), _pfd(-1) + _ifd(-1), _pfd(-1), _name("") { } @@ -59,16 +59,20 @@ iface::~iface() close(_ifd); if (_pfd >= 0) { - allmulti(_prev_allmulti); + if (_prev_allmulti >= 0) { + allmulti(_prev_allmulti); + } close(_pfd); } + + _map.erase(_name); } ptr iface::open_pfd(const std::string& name) { - int fd; + int fd = 0; - std::map >::iterator it = _map.find(name); + std::map >::iterator it = _map.find(name); ptr ifa; @@ -124,10 +128,7 @@ ptr iface::open_pfd(const std::string& name) // Set up filter. - struct sock_fprog fprog; - - static const struct sock_filter filter[] = - { + static struct sock_filter filter[] = { // Load the ether_type. BPF_STMT(BPF_LD | BPF_H | BPF_ABS, offsetof(struct ether_header, ether_type)), @@ -149,14 +150,19 @@ ptr iface::open_pfd(const std::string& name) BPF_STMT(BPF_RET | BPF_K, 0) }; - fprog.filter = (struct sock_filter* )filter; - fprog.len = 8; + static struct sock_fprog fprog = { + 8, + filter + }; - if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER,& fprog, sizeof(fprog)) < 0) { + if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) < 0) { logger::error() << "Failed to set filter"; return ptr(); } + // Eh. Allmulti. + ifa->_prev_allmulti = ifa->allmulti(1); + // Set up an instance of 'iface'. ifa->_pfd = fd; @@ -170,7 +176,7 @@ ptr iface::open_ifd(const std::string& name) { int fd; - std::map >::iterator it = _map.find(name); + std::map >::iterator it = _map.find(name); if ((it != _map.end()) && it->second->_ifd) return it->second; @@ -451,7 +457,7 @@ void iface::fixup_pollfds() logger::debug() << "iface::fixup_pollfds() _map.size()=" << _map.size(); - for (std::map >::iterator it = _map.begin(); + for (std::map >::iterator it = _map.begin(); it != _map.end(); it++) { _pollfds[i].fd = it->second->_ifd; _pollfds[i].events = POLLIN; @@ -498,7 +504,7 @@ int iface::poll_all() if (len == 0) return 0; - std::map >::iterator i_it = _map.begin(); + std::map >::iterator i_it = _map.begin(); int i = 0; @@ -530,7 +536,9 @@ int iface::poll_all() continue; } - ifa->_pr->handle_solicit(saddr, daddr, taddr); + if (ifa->_pr) { + ifa->_pr->handle_solicit(saddr, daddr, taddr); + } } else { if (ifa->read_advert(saddr, taddr) < 0) { logger::error() << "Failed to read from interface '%s'", ifa->_name.c_str(); @@ -560,23 +568,29 @@ int iface::allmulti(int state) state = !!state; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ); - if (ioctl(_pfd, SIOCGIFFLAGS,& ifr) < 0) + if (ioctl(_pfd, SIOCGIFFLAGS, &ifr) < 0) { return -1; + } - int old_state = !!(ifr.ifr_flags& IFF_ALLMULTI); + int old_state = !!(ifr.ifr_flags & IFF_ALLMULTI); - if (state == old_state) + if (state == old_state) { return old_state; + } - if (state) + if (state) { ifr.ifr_flags |= IFF_ALLMULTI; - else + } else { ifr.ifr_flags &= ~IFF_ALLMULTI; + } - if (ioctl(_pfd, SIOCSIFFLAGS,& ifr) < 0) + if (ioctl(_pfd, SIOCSIFFLAGS, &ifr) < 0) { return -1; + } return old_state; } diff --git a/src/iface.h b/src/iface.h index 0bcdf7b..80bc01e 100644 --- a/src/iface.h +++ b/src/iface.h @@ -35,7 +35,7 @@ private: // Weak pointer so this object can reference itself. weak_ptr _ptr; - static std::map > _map; + static std::map > _map; // An array of objects used with ::poll. static std::vector _pollfds; @@ -61,7 +61,7 @@ private: // ND_NEIGHBOR_ADVERT messages. std::list > _sessions; - ptr _pr; + weak_ptr _pr; // The link-layer address of this interface. struct ether_addr hwaddr; diff --git a/src/logger.cc b/src/logger.cc index 72fbf38..82d3ff8 100644 --- a/src/logger.cc +++ b/src/logger.cc @@ -55,12 +55,12 @@ const logger::pri_name logger::_pri_names[] = { }; logger::logger(int pri) : - _pri(pri) + _pri(pri), _force_log(false) { } logger::logger(const logger& l) : - _pri(l._pri) //, _ss(l._ss.str()) + _pri(l._pri), _force_log(false) { _ss << l._ss.rdbuf(); } diff --git a/src/ndppd.cc b/src/ndppd.cc index 3171f93..2b1690f 100644 --- a/src/ndppd.cc +++ b/src/ndppd.cc @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include +#include #include #include @@ -128,8 +129,19 @@ bool configure(const std::string& path) return true; } +bool running = true; + +void exit_ndppd(int sig) +{ + logger::error() << "Shutting down..."; + running = 0; +} + int main(int argc, char* argv[], char* env[]) { + signal(SIGINT, exit_ndppd); + signal(SIGTERM, exit_ndppd); + std::string config_path("/etc/ndppd.conf"); std::string pidfile; std::string verbosity; @@ -208,7 +220,7 @@ int main(int argc, char* argv[], char* env[]) gettimeofday(&t1, 0); - while (iface::poll_all() >= 0) { + while (running && (iface::poll_all() >= 0)) { int elapsed_time; gettimeofday(&t2, 0); diff --git a/src/proxy.cc b/src/proxy.cc index a3f6f71..246014c 100644 --- a/src/proxy.cc +++ b/src/proxy.cc @@ -27,6 +27,8 @@ NDPPD_NS_BEGIN +std::list > proxy::_list; + proxy::proxy() : _router(true), _ttl(30000), _timeout(500) { @@ -38,6 +40,8 @@ ptr proxy::create(const ptr& ifa) pr->_ptr = pr; pr->_ifa = ifa; + _list.push_back(pr); + ifa->pr(pr); logger::debug() << "proxy::create() if=" << ifa->name(); diff --git a/src/proxy.h b/src/proxy.h index 1611a09..0a77698 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -29,21 +29,6 @@ class iface; class rule; class proxy { -private: - weak_ptr _ptr; - - ptr _ifa; - - std::list > _rules; - - std::list > _sessions; - - bool _router; - - int _ttl, _timeout; - - proxy(); - public: static ptr create(const ptr& ifa); @@ -71,6 +56,23 @@ public: int ttl() const; void ttl(int val); + +private: + static std::list > _list; + + weak_ptr _ptr; + + ptr _ifa; + + std::list > _rules; + + std::list > _sessions; + + bool _router; + + int _ttl, _timeout; + + proxy(); }; NDPPD_NS_END diff --git a/src/ptr.h b/src/ptr.h index f860621..ab45098 100644 --- a/src/ptr.h +++ b/src/ptr.h @@ -18,6 +18,7 @@ #include #include "ndppd.h" +#include "logger.h" NDPPD_NS_BEGIN @@ -50,43 +51,65 @@ protected: void acquire(ptr_ref* ref) { - if (_ref) + if (_ref) { release(); + } + + if (ref && !ref->sc) { + throw new invalid_pointer; + } if (_ref = ref) { - if (_weak) + if (_weak) { _ref->wc++; - else + } else { _ref->sc++; + } } } void acquire(void* ptr) { _ref = new ptr_ref(); - _ref->ptr = (T* )ptr; + _ref->ptr = (T*)ptr; _ref->wc = !!_weak; _ref->sc = !_weak; } void release() { - if (!_ref) + if (!_ref) { return; - - if (_weak) - _ref->wc--; - else - _ref->sc--; - - if (!_ref->sc && _ref->ptr) { - T* ptr = static_cast(_ref->ptr); - _ref->ptr = 0; - delete ptr; } - if (!_ref->sc && !_ref->wc) + //logger::debug() + // << "ptr::release() _ref=" << logger::format("%x", _ref) + // << ", _ref->wc=" << _ref->wc << ", _ref->sc=" << _ref->sc + // << ", _weak=" << (_weak ? "yes" : "no"); + + if (_weak) { + assert(_ref->wc > 0); + _ref->wc--; + } else { + assert(_ref->sc > 0); + if (!--_ref->sc && _ref->ptr) { + T* ptr = _ref->ptr; + _ref->ptr = 0; + _ref->wc++; + delete ptr; + _ref->wc--; + } + } + + /*if (!_weak && !_ref->sc && _ref->ptr) { + T* ptr = (T*)(_ref->ptr); + _ref->ptr = 0; + delete ptr; + }*/ + + if (!_ref->sc && !_ref->wc) { delete _ref; + } _ref = 0; } @@ -196,8 +219,9 @@ public: T* get_pointer() const { - if (!_ref || !_ref->ptr) + if (!_ref || !_ref->ptr) { throw new invalid_pointer; + } return static_cast(_ref->ptr); } diff --git a/src/route.cc b/src/route.cc index b1fc3a6..87bb41e 100644 --- a/src/route.cc +++ b/src/route.cc @@ -150,6 +150,7 @@ const std::string& route::ifname() const ptr route::ifa() { if (!_ifa) { + logger::debug() << "router::ifa() opening interface '" << _ifname << "'"; return _ifa = iface::open_ifd(_ifname); } diff --git a/src/rule.h b/src/rule.h index ad721ce..6663066 100644 --- a/src/rule.h +++ b/src/rule.h @@ -45,7 +45,7 @@ public: private: weak_ptr _ptr; - ptr _pr; + weak_ptr _pr; ptr _ifa; diff --git a/src/session.cc b/src/session.cc index 15774de..ff5272b 100644 --- a/src/session.cc +++ b/src/session.cc @@ -96,11 +96,11 @@ void session::add_iface(const ptr& ifa) void session::send_solicit() { - logger::debug() << "session::send_solicit() (" << _ifaces.size() << ")"; + logger::debug() << "session::send_solicit() (_ifaces.size() = " << _ifaces.size() << ")"; for (std::list >::iterator it = _ifaces.begin(); it != _ifaces.end(); it++) { - logger::debug() << " - %s" << (*it)->name(); + logger::debug() << " - " << (*it)->name(); (*it)->write_solicit(_taddr); } }