From bc70f587efb94db2f946aebdf37459cdc5aacb9e Mon Sep 17 00:00:00 2001 From: Daniel Adolfsson Date: Sat, 28 Jan 2012 20:25:57 +0100 Subject: [PATCH] Refactor source - Change coding style - Switch from own implementation of smart pointers to std::smart_ptr and std::weak_ptr --- Makefile | 4 +- src/address.cc | 288 +++++++++---------- src/address.h | 44 +-- src/conf.cc | 165 ++++++----- src/conf.h | 8 +- src/iface.cc | 733 ++++++++++++++++++++++++------------------------- src/iface.h | 100 +++---- src/log.cc | 76 +++-- src/log.h | 10 +- src/ndppd.cc | 144 +++++----- src/ndppd.h | 2 +- src/proxy.cc | 166 ++++++----- src/proxy.h | 42 +-- src/ptr.h | 243 ---------------- src/rule.cc | 44 +-- src/rule.h | 22 +- src/session.cc | 122 ++++---- src/session.h | 64 ++--- 18 files changed, 988 insertions(+), 1289 deletions(-) delete mode 100644 src/ptr.h diff --git a/Makefile b/Makefile index 8a897fd..d8b0659 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ ifdef DEBUG -CXXFLAGS ?= -g -DDEBUG +CXXFLAGS ?= -g -std=c++0x -DDEBUG else -CXXFLAGS ?= -O3 +CXXFLAGS ?= -O3 -std=c++0x endif PREFIX ?= /usr/local diff --git a/src/address.cc b/src/address.cc index 1c8498c..054e57c 100644 --- a/src/address.cc +++ b/src/address.cc @@ -32,265 +32,245 @@ __NDPPD_NS_BEGIN address::address() { - _addr.s6_addr32[0] = 0; - _addr.s6_addr32[1] = 0; - _addr.s6_addr32[2] = 0; - _addr.s6_addr32[3] = 0; - - _mask.s6_addr32[0] = 0xffffffff; - _mask.s6_addr32[1] = 0xffffffff; - _mask.s6_addr32[2] = 0xffffffff; - _mask.s6_addr32[3] = 0xffffffff; + reset(); } address::address(const address& addr) { - _addr.s6_addr32[0] = addr._addr.s6_addr32[0]; - _addr.s6_addr32[1] = addr._addr.s6_addr32[1]; - _addr.s6_addr32[2] = addr._addr.s6_addr32[2]; - _addr.s6_addr32[3] = addr._addr.s6_addr32[3]; + _addr.s6_addr32[0] = addr._addr.s6_addr32[0]; + _addr.s6_addr32[1] = addr._addr.s6_addr32[1]; + _addr.s6_addr32[2] = addr._addr.s6_addr32[2]; + _addr.s6_addr32[3] = addr._addr.s6_addr32[3]; - _mask.s6_addr32[0] = addr._mask.s6_addr32[0]; - _mask.s6_addr32[1] = addr._mask.s6_addr32[1]; - _mask.s6_addr32[2] = addr._mask.s6_addr32[2]; - _mask.s6_addr32[3] = addr._mask.s6_addr32[3]; + _mask.s6_addr32[0] = addr._mask.s6_addr32[0]; + _mask.s6_addr32[1] = addr._mask.s6_addr32[1]; + _mask.s6_addr32[2] = addr._mask.s6_addr32[2]; + _mask.s6_addr32[3] = addr._mask.s6_addr32[3]; } address::address(const std::string& str) { - if(!parse_string(str)) - { - _addr.s6_addr32[0] = 0; - _addr.s6_addr32[1] = 0; - _addr.s6_addr32[2] = 0; - _addr.s6_addr32[3] = 0; - - _mask.s6_addr32[0] = 0xffffffff; - _mask.s6_addr32[1] = 0xffffffff; - _mask.s6_addr32[2] = 0xffffffff; - _mask.s6_addr32[3] = 0xffffffff; - } + parse_string(str); } address::address(const char *str) { - if(!parse_string(str)) - { - _addr.s6_addr32[0] = 0; - _addr.s6_addr32[1] = 0; - _addr.s6_addr32[2] = 0; - _addr.s6_addr32[3] = 0; - - _mask.s6_addr32[0] = 0xffffffff; - _mask.s6_addr32[1] = 0xffffffff; - _mask.s6_addr32[2] = 0xffffffff; - _mask.s6_addr32[3] = 0xffffffff; - } + parse_string(str); } address::address(const in6_addr& addr) { - _addr.s6_addr32[0] = addr.s6_addr32[0]; - _addr.s6_addr32[1] = addr.s6_addr32[1]; - _addr.s6_addr32[2] = addr.s6_addr32[2]; - _addr.s6_addr32[3] = addr.s6_addr32[3]; + _addr.s6_addr32[0] = addr.s6_addr32[0]; + _addr.s6_addr32[1] = addr.s6_addr32[1]; + _addr.s6_addr32[2] = addr.s6_addr32[2]; + _addr.s6_addr32[3] = addr.s6_addr32[3]; - _mask.s6_addr32[0] = 0xffffffff; - _mask.s6_addr32[1] = 0xffffffff; - _mask.s6_addr32[2] = 0xffffffff; - _mask.s6_addr32[3] = 0xffffffff; + _mask.s6_addr32[0] = 0xffffffff; + _mask.s6_addr32[1] = 0xffffffff; + _mask.s6_addr32[2] = 0xffffffff; + _mask.s6_addr32[3] = 0xffffffff; } address::address(const in6_addr& addr, const in6_addr& mask) { - _addr.s6_addr32[0] = addr.s6_addr32[0]; - _addr.s6_addr32[1] = addr.s6_addr32[1]; - _addr.s6_addr32[2] = addr.s6_addr32[2]; - _addr.s6_addr32[3] = addr.s6_addr32[3]; + _addr.s6_addr32[0] = addr.s6_addr32[0]; + _addr.s6_addr32[1] = addr.s6_addr32[1]; + _addr.s6_addr32[2] = addr.s6_addr32[2]; + _addr.s6_addr32[3] = addr.s6_addr32[3]; - _mask.s6_addr32[0] = mask.s6_addr32[0]; - _mask.s6_addr32[1] = mask.s6_addr32[1]; - _mask.s6_addr32[2] = mask.s6_addr32[2]; - _mask.s6_addr32[3] = mask.s6_addr32[3]; + _mask.s6_addr32[0] = mask.s6_addr32[0]; + _mask.s6_addr32[1] = mask.s6_addr32[1]; + _mask.s6_addr32[2] = mask.s6_addr32[2]; + _mask.s6_addr32[3] = mask.s6_addr32[3]; } address::address(const in6_addr& addr, int pf) { - _addr.s6_addr32[0] = addr.s6_addr32[0]; - _addr.s6_addr32[1] = addr.s6_addr32[1]; - _addr.s6_addr32[2] = addr.s6_addr32[2]; - _addr.s6_addr32[3] = addr.s6_addr32[3]; + _addr.s6_addr32[0] = addr.s6_addr32[0]; + _addr.s6_addr32[1] = addr.s6_addr32[1]; + _addr.s6_addr32[2] = addr.s6_addr32[2]; + _addr.s6_addr32[3] = addr.s6_addr32[3]; - prefix(pf); + prefix(pf); } bool address::operator==(const address& addr) const { - return !(((_addr.s6_addr32[0] ^ addr._addr.s6_addr32[0]) & _mask.s6_addr32[0]) | - ((_addr.s6_addr32[1] ^ addr._addr.s6_addr32[1]) & _mask.s6_addr32[1]) | - ((_addr.s6_addr32[2] ^ addr._addr.s6_addr32[2]) & _mask.s6_addr32[2]) | - ((_addr.s6_addr32[3] ^ addr._addr.s6_addr32[3]) & _mask.s6_addr32[3])); -} - -bool address::operator!=(const address& addr) const -{ - return !!(((_addr.s6_addr32[0] ^ addr._addr.s6_addr32[0]) & _mask.s6_addr32[0]) | + return !(((_addr.s6_addr32[0] ^ addr._addr.s6_addr32[0]) & _mask.s6_addr32[0]) | ((_addr.s6_addr32[1] ^ addr._addr.s6_addr32[1]) & _mask.s6_addr32[1]) | ((_addr.s6_addr32[2] ^ addr._addr.s6_addr32[2]) & _mask.s6_addr32[2]) | ((_addr.s6_addr32[3] ^ addr._addr.s6_addr32[3]) & _mask.s6_addr32[3])); } +bool address::operator!=(const address& addr) const +{ + return !!(((_addr.s6_addr32[0] ^ addr._addr.s6_addr32[0]) & _mask.s6_addr32[0]) | + ((_addr.s6_addr32[1] ^ addr._addr.s6_addr32[1]) & _mask.s6_addr32[1]) | + ((_addr.s6_addr32[2] ^ addr._addr.s6_addr32[2]) & _mask.s6_addr32[2]) | + ((_addr.s6_addr32[3] ^ addr._addr.s6_addr32[3]) & _mask.s6_addr32[3])); +} + +void address::reset() +{ + _addr.s6_addr32[0] = 0; + _addr.s6_addr32[1] = 0; + _addr.s6_addr32[2] = 0; + _addr.s6_addr32[3] = 0; + + _mask.s6_addr32[0] = 0xffffffff; + _mask.s6_addr32[1] = 0xffffffff; + _mask.s6_addr32[2] = 0xffffffff; + _mask.s6_addr32[3] = 0xffffffff; +} + int address::prefix() const { - if(!_mask.s6_addr[0]) - return 0; + if (!_mask.s6_addr[0]) + return 0; - for(int p = 0; p < 128; p++) - { - int byi = p / 8, bii = 7 - (p % 8); - if(!(_mask.s6_addr[byi] & (1 << bii))) - return p; - } + for (int p = 0; p < 128; p++) { + int byi = p / 8, bii = 7 - (p % 8); + if (!(_mask.s6_addr[byi] & (1 << bii))) + return p; + } - return 128; + return 128; } void address::prefix(int pf) { - if((pf < 0) || (pf > 128)) - return; + if ((pf < 0) || (pf > 128)) + return; - _mask.s6_addr32[0] = 0; - _mask.s6_addr32[1] = 0; - _mask.s6_addr32[2] = 0; - _mask.s6_addr32[3] = 0; + _mask.s6_addr32[0] = 0; + _mask.s6_addr32[1] = 0; + _mask.s6_addr32[2] = 0; + _mask.s6_addr32[3] = 0; - while(pf--) - { - int byi = pf / 8, bii = 7 - (pf % 8); - _mask.s6_addr[byi] |= 1 << bii; - } + while (pf--) { + int byi = pf / 8, bii = 7 - (pf % 8); + _mask.s6_addr[byi] |= 1 << bii; + } } const std::string address::to_string() const { - char buf[INET6_ADDRSTRLEN + 8]; + char buf[INET6_ADDRSTRLEN + 8]; - if(!inet_ntop(AF_INET6, &_addr, buf, INET6_ADDRSTRLEN)) - return "::1"; + if (!inet_ntop(AF_INET6, &_addr, buf, INET6_ADDRSTRLEN)) + return "::1"; - // TODO: What to do about invalid ip? + // TODO: What to do about invalid ip? - int p; + int p; - if((p = prefix()) < 128) - sprintf(buf + strlen(buf), "/%d", p); + if ((p = prefix()) < 128) + sprintf(buf + strlen(buf), "/%d", p); - return buf; + return buf; } bool address::parse_string(const std::string& str) { - char buf[INET6_ADDRSTRLEN], *b; - int sz, pfx; + char buf[INET6_ADDRSTRLEN], *b; + int sz, pfx; - sz = 0; - b = buf; + sz = 0; + b = buf; - const char *p = str.c_str(); + reset(); - while(*p && isspace(*p)) - p++; + const char *p = str.c_str(); - while(*p) - { - if((*p == '/') || isspace(*p)) - break; + while (*p && isspace(*p)) + p++; - if((*p != ':') && !isxdigit(*p)) - return false; + while (*p) { + if ((*p == '/') || isspace(*p)) + break; - if(sz >= (INET6_ADDRSTRLEN - 1)) - return false; + if ((*p != ':') && !isxdigit(*p)) + return false; - *b++ = *p++; + if (sz >= (INET6_ADDRSTRLEN - 1)) + return false; - sz++; - } + *b++ = *p++; - *b = '\0'; + sz++; + } - if(inet_pton(AF_INET6, buf, &_addr) <= 0) - return false; + *b = '\0'; - while(*p && isspace(*p)) - p++; + if (inet_pton(AF_INET6, buf, &_addr) <= 0) + return false; - if(*p == '\0') - { - _mask.s6_addr32[0] = 0xffffffff; - _mask.s6_addr32[1] = 0xffffffff; - _mask.s6_addr32[2] = 0xffffffff; - _mask.s6_addr32[3] = 0xffffffff; - return true; - } + while (*p && isspace(*p)) + p++; - if(*p++ != '/') - return false; + if (*p == '\0') { + _mask.s6_addr32[0] = 0xffffffff; + _mask.s6_addr32[1] = 0xffffffff; + _mask.s6_addr32[2] = 0xffffffff; + _mask.s6_addr32[3] = 0xffffffff; + return true; + } - while(*p && isspace(*p)) - p++; + if (*p++ != '/') + return false; - sz = 0; - b = buf; + while (*p && isspace(*p)) + p++; - while(*p) - { - if(!isdigit(*p)) - return false; + sz = 0; + b = buf; - if(sz > 3) - return false; + while (*p) { + if (!isdigit(*p)) + return false; - *b++ = *p++; - sz++; - } + if (sz > 3) + return false; - *b = '\0'; + *b++ = *p++; + sz++; + } - prefix(atoi(buf)); + *b = '\0'; - return true; + prefix(atoi(buf)); + + return true; } address::operator std::string() const { - return to_string(); + return to_string(); } struct in6_addr& address::addr() { - return _addr; + return _addr; } const struct in6_addr& address::const_addr() const { - return _addr; + return _addr; } struct in6_addr& address::mask() { - return _mask; + return _mask; } bool address::is_multicast() const { - return _addr.s6_addr[0] == 0xff; + return _addr.s6_addr[0] == 0xff; } bool address::is_unicast() const { - return _addr.s6_addr[0] != 0xff; + return _addr.s6_addr[0] != 0xff; } __NDPPD_NS_END diff --git a/src/address.h b/src/address.h index 5d17e7f..ccc9887 100644 --- a/src/address.h +++ b/src/address.h @@ -29,41 +29,43 @@ class iface; class address { private: - struct in6_addr _addr, _mask; + struct in6_addr _addr, _mask; public: - address(); - address(const address& addr); - address(const std::string& str); - address(const char *str); - address(const in6_addr& addr); - address(const in6_addr& addr, const in6_addr& mask); - address(const in6_addr& addr, int prefix); + address(); + address(const address& addr); + address(const std::string& str); + address(const char *str); + address(const in6_addr& addr); + address(const in6_addr& addr, const in6_addr& mask); + address(const in6_addr& addr, int prefix); - struct in6_addr& addr(); + struct in6_addr& addr(); - const struct in6_addr& const_addr() const; + const struct in6_addr& const_addr() const; - struct in6_addr& mask(); + struct in6_addr& mask(); - // Compare _a/_m against a._a. - bool operator==(const address& addr) const; + // Compare _a/_m against a._a. + bool operator==(const address& addr) const; - bool operator!=(const address& addr) const; + bool operator!=(const address& addr) const; - const std::string to_string() const; + void reset(); - bool parse_string(const std::string& str); + const std::string to_string() const; - int prefix() const; + bool parse_string(const std::string& str); - void prefix(int n); + int prefix() const; - bool is_unicast() const; + void prefix(int n); - bool is_multicast() const; + bool is_unicast() const; - operator std::string() const; + bool is_multicast() const; + + operator std::string() const; }; diff --git a/src/conf.cc b/src/conf.cc index 24b9032..0c209ff 100644 --- a/src/conf.cc +++ b/src/conf.cc @@ -24,131 +24,126 @@ __NDPPD_NS_BEGIN void conf::error_printf(cfg_t *cfg, const char *fmt, va_list ap) { - char buf[256]; + char buf[256]; - if(vsnprintf(buf, sizeof(buf), fmt, ap) <= 0) - return; + if (vsnprintf(buf, sizeof(buf), fmt, ap) <= 0) + return; - ERR("[Config] %s", buf); + ERR("[Config] %s", buf); } int conf::validate_rule(cfg_t *cfg, cfg_opt_t *opt) { - struct in6_addr addr, mask; + struct in6_addr addr, mask; - cfg_t *rule_cfg = cfg_opt_getnsec(opt, cfg_opt_size(opt) - 1); + cfg_t *rule_cfg = cfg_opt_getnsec(opt, cfg_opt_size(opt) - 1); - if(!rule_cfg) - return -1; + if (!rule_cfg) + return -1; - // TODO: Maybe we should validate IP here? + // TODO: Maybe we should validate IP here? - return 0; + return 0; } bool conf::setup(cfg_t *cfg) { - int i; + int i; - for(i = 0; i < cfg_size(cfg, "proxy"); i++) - { - cfg_t *proxy_cfg = cfg_getnsec(cfg, "proxy", i); + for (i = 0; i < cfg_size(cfg, "proxy"); i++) { + cfg_t *proxy_cfg = cfg_getnsec(cfg, "proxy", i); - if(proxy_cfg) - { - cfg_t *rule_cfg; - int i2; - - strong_ptr pr = proxy::open(cfg_title(proxy_cfg)); - - if(pr.is_null()) - continue; - - pr->router(cfg_getbool(proxy_cfg, "router")); - - pr->ttl(cfg_getint(proxy_cfg, "ttl")); - - pr->timeout(cfg_getint(proxy_cfg, "timeout")); - - for(i2 = 0; i2 < cfg_size(proxy_cfg, "rule"); i2++) - { + if (proxy_cfg) { cfg_t *rule_cfg; + int i2; - if(!(rule_cfg = cfg_getnsec(proxy_cfg, "rule", i2))) - continue; + std::shared_ptr pr = proxy::open(cfg_title(proxy_cfg)); - address addr(cfg_title(rule_cfg)); + if (!pr) + continue; - std::string ifname(cfg_getstr(rule_cfg, "iface")); + pr->router(cfg_getbool(proxy_cfg, "router")); - if(ifname.empty()) - { - if(addr.prefix() <= 120) - NCE("Static rule prefix /%d <= 120 - is this what you want?", addr.prefix()); + pr->ttl(cfg_getint(proxy_cfg, "ttl")); - pr->add_rule(addr); + pr->timeout(cfg_getint(proxy_cfg, "timeout")); + + for (i2 = 0; i2 < cfg_size(proxy_cfg, "rule"); i2++) { + cfg_t *rule_cfg; + + if (!(rule_cfg = cfg_getnsec(proxy_cfg, "rule", i2))) + continue; + + address addr(cfg_title(rule_cfg)); + + std::string ifname(cfg_getstr(rule_cfg, "iface")); + + if (ifname.empty()) { + if (addr.prefix() <= 120) + NCE("Static rule prefix /%d <= 120 - is this what you want?", addr.prefix()); + + pr->add_rule(addr); + } + else + { + pr->add_rule(addr, iface::open_ifd(ifname)); + } } - else - { - pr->add_rule(addr, iface::open_ifd(ifname)); - } - } - } - } + } + } - return 0; + return 0; } bool conf::load(const std::string& path) { - cfg_t *cfg; - int i, sz; + cfg_t *cfg; + int i, sz; - #define _S (char *) + #define _S (char *) - static cfg_opt_t rule_opts[] = - { - CFG_STR (_S "iface", _S "", CFGF_NONE), - CFG_END () - }; + static cfg_opt_t rule_opts[] = + { + CFG_STR (_S "iface", _S "", CFGF_NONE), + CFG_END () + }; - static cfg_opt_t proxy_opts[] = - { - CFG_SEC (_S "rule", rule_opts, CFGF_MULTI | CFGF_TITLE), - CFG_BOOL (_S "router", cfg_true, CFGF_NONE), - CFG_INT (_S "ttl", 30000, CFGF_NONE), - CFG_INT (_S "timeout", 500, CFGF_NONE), - CFG_END () - }; + static cfg_opt_t proxy_opts[] = + { + CFG_SEC (_S "rule", rule_opts, CFGF_MULTI | CFGF_TITLE), + CFG_BOOL (_S "router", cfg_true, CFGF_NONE), + CFG_INT (_S "ttl", 30000, CFGF_NONE), + CFG_INT (_S "timeout", 500, CFGF_NONE), + CFG_END () + }; - static cfg_opt_t opts[] = - { - CFG_SEC (_S "proxy", proxy_opts, CFGF_MULTI | CFGF_TITLE), - CFG_FUNC (_S "include", &cfg_include), - CFG_END() - }; + static cfg_opt_t opts[] = + { + CFG_SEC (_S "proxy", proxy_opts, CFGF_MULTI | CFGF_TITLE), + CFG_FUNC (_S "include", &cfg_include), + CFG_END() + }; - cfg = cfg_init(opts, CFGF_NOCASE); + cfg = cfg_init(opts, CFGF_NOCASE); - cfg_set_error_function(cfg, &error_printf); + cfg_set_error_function(cfg, &error_printf); - cfg_set_validate_func(cfg, "proxy|rule", &validate_rule); + cfg_set_validate_func(cfg, "proxy|rule", &validate_rule); - switch(cfg_parse(cfg, path.c_str())) - { - case CFG_SUCCESS: - break; + switch (cfg_parse(cfg, path.c_str())) { + case CFG_SUCCESS: + break; - default: - ERR("Failed to load configuration file '%s'", path.c_str()); - return false; - } + default: + ERR("Failed to load configuration file '%s'", path.c_str()); + return false; + } - setup(cfg); + setup(cfg); - cfg_free(cfg); + cfg_free(cfg); - return true; + return true; } __NDPPD_NS_END diff --git a/src/conf.h b/src/conf.h index fc86f34..4b0867a 100644 --- a/src/conf.h +++ b/src/conf.h @@ -30,11 +30,11 @@ __NDPPD_NS_BEGIN class conf { private: - static bool setup(::cfg_t *cfg); - static void error_printf(::cfg_t *cfg, const char *fmt, va_list ap); - static int validate_rule(::cfg_t *cfg, ::cfg_opt_t *opt); + static bool setup(::cfg_t *cfg); + static void error_printf(::cfg_t *cfg, const char *fmt, va_list ap); + static int validate_rule(::cfg_t *cfg, ::cfg_opt_t *opt); public: - static bool load(const std::string& path); + static bool load(const std::string& path); }; __NDPPD_NS_END diff --git a/src/iface.cc b/src/iface.cc index 98f88f9..4b65855 100644 --- a/src/iface.cc +++ b/src/iface.cc @@ -42,583 +42,560 @@ __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) { } iface::~iface() { - DBG("iface::~iface()"); + DBG("iface::~iface()"); - if(_ifd >= 0) - close(_ifd); + if (_ifd >= 0) + close(_ifd); - if(_pfd >= 0) - { - allmulti(_prev_allmulti); - close(_pfd); - } + if (_pfd >= 0) { + allmulti(_prev_allmulti); + close(_pfd); + } } -strong_ptr iface::open_pfd(const std::string& name) +std::shared_ptr iface::open_pfd(const std::string& name) { - int fd; + int fd; - std::map >::iterator it = _map.find(name); + std::map >::iterator it = _map.find(name); - strong_ptr ifa; + std::shared_ptr ifa; - if(it != _map.end()) - { - if(it->second->_pfd >= 0) - return it->second; + if (it != _map.end()) { + if (it->second->_pfd >= 0) + return it->second; - ifa = it->second; - } - else - { - // We need an _ifs, so let's set one up. - ifa = open_ifd(name); - } + ifa = it->second; + } else { + // We need an _ifs, so let's set one up. + ifa = open_ifd(name); + } - if(ifa.is_null()) - return strong_ptr(); + if (!ifa) + return std::shared_ptr(); + + // Create a socket. - // Create a socket. + if ((fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IPV6))) < 0) { + ERR("Unable to create socket"); + return std::shared_ptr(); + } - if((fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IPV6))) < 0) - { - ERR("Unable to create socket"); - return strong_ptr(); - } + // Bind to the specified interface. - // Bind to the specified interface. + struct sockaddr_ll lladdr; - struct sockaddr_ll lladdr; + memset(&lladdr, 0, sizeof(struct sockaddr_ll)); + lladdr.sll_family = AF_PACKET; + lladdr.sll_protocol = htons(ETH_P_IPV6); - memset(&lladdr, 0, sizeof(struct sockaddr_ll)); - lladdr.sll_family = AF_PACKET; - lladdr.sll_protocol = htons(ETH_P_IPV6); + if (!(lladdr.sll_ifindex = if_nametoindex(name.c_str()))) { + close(fd); + ERR("Failed to bind to interface '%s'", name.c_str()); + return std::shared_ptr(); + } - if(!(lladdr.sll_ifindex = if_nametoindex(name.c_str()))) - { - close(fd); - ERR("Failed to bind to interface '%s'", name.c_str()); - return strong_ptr(); - } + if (bind(fd, (struct sockaddr *)&lladdr, sizeof(struct sockaddr_ll)) < 0) { + close(fd); + ERR("Failed to bind to interface '%s'", name.c_str()); + return std::shared_ptr(); + } - if(bind(fd, (struct sockaddr *)&lladdr, sizeof(struct sockaddr_ll)) < 0) - { - close(fd); - ERR("Failed to bind to interface '%s'", name.c_str()); - return strong_ptr(); - } + // Switch to non-blocking mode. - // Switch to non-blocking mode. + int on = 1; - int on = 1; + if (ioctl(fd, FIONBIO, (char *)&on) < 0) { + close(fd); + ERR("Failed to switch to non-blocking on interface '%s'", name.c_str()); + return std::shared_ptr(); + } - if(ioctl(fd, FIONBIO, (char *)&on) < 0) - { - close(fd); - ERR("Failed to switch to non-blocking on interface '%s'", name.c_str()); - return strong_ptr(); - } + // Set up filter. - // Set up filter. + struct sock_fprog fprog; - struct sock_fprog fprog; + static const struct sock_filter filter[] = + { + // Load the ether_type. + BPF_STMT(BPF_LD | BPF_H | BPF_ABS, + offsetof(struct ether_header, ether_type)), + // Bail if it's *not* ETHERTYPE_IPV6. + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ETHERTYPE_IPV6, 0, 5), + // Load the next header type. + BPF_STMT(BPF_LD | BPF_B | BPF_ABS, + sizeof(struct ether_header) + offsetof(struct ip6_hdr, ip6_nxt)), + // Bail if it's *not* IPPROTO_ICMPV6. + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3), + // Load the ICMPv6 type. + BPF_STMT(BPF_LD | BPF_B | BPF_ABS, + sizeof(struct ether_header) + sizeof(ip6_hdr) + offsetof(struct icmp6_hdr, icmp6_type)), + // Bail if it's *not* ND_NEIGHBOR_SOLICIT. + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_NEIGHBOR_SOLICIT, 0, 1), + // Keep packet. + BPF_STMT(BPF_RET | BPF_K, -1), + // Drop packet. + BPF_STMT(BPF_RET | BPF_K, 0) + }; - static const struct sock_filter filter[] = - { - // Load the ether_type. - BPF_STMT(BPF_LD | BPF_H | BPF_ABS, - offsetof(struct ether_header, ether_type)), - // Bail if it's *not* ETHERTYPE_IPV6. - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ETHERTYPE_IPV6, 0, 5), - // Load the next header type. - BPF_STMT(BPF_LD | BPF_B | BPF_ABS, - sizeof(struct ether_header) + offsetof(struct ip6_hdr, ip6_nxt)), - // Bail if it's *not* IPPROTO_ICMPV6. - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3), - // Load the ICMPv6 type. - BPF_STMT(BPF_LD | BPF_B | BPF_ABS, - sizeof(struct ether_header) + sizeof(ip6_hdr) + offsetof(struct icmp6_hdr, icmp6_type)), - // Bail if it's *not* ND_NEIGHBOR_SOLICIT. - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_NEIGHBOR_SOLICIT, 0, 1), - // Keep packet. - BPF_STMT(BPF_RET | BPF_K, -1), - // Drop packet. - BPF_STMT(BPF_RET | BPF_K, 0) - }; + fprog.filter = (struct sock_filter *)filter; + fprog.len = 8; - fprog.filter = (struct sock_filter *)filter; - fprog.len = 8; + if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) < 0) { + ERR("Failed to set filter"); + return std::shared_ptr(); + } - if(setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) < 0) - { - ERR("Failed to set filter"); - return strong_ptr(); - } + // Set up an instance of 'iface'. - // Set up an instance of 'iface'. + ifa->_pfd = fd; - ifa->_pfd = fd; + fixup_pollfds(); - fixup_pollfds(); - - return ifa; + return ifa; } -strong_ptr iface::open_ifd(const std::string& name) +std::shared_ptr iface::open_ifd(const std::string& name) { - int fd; + 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; + if ((it != _map.end()) && it->second->_ifd) + return it->second; - // Create a socket. + // Create a socket. - if((fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) - { - ERR("Unable to create socket"); - return strong_ptr(); - } + if ((fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { + ERR("Unable to create socket"); + return std::shared_ptr(); + } - // Bind to the specified interface. + // Bind to the specified interface. - struct ifreq ifr; + struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1); - ifr.ifr_name[IFNAMSIZ - 1] = '\0'; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1); + ifr.ifr_name[IFNAMSIZ - 1] = '\0'; - if(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) - { - close(fd); - ERR("Failed to bind to interface '%s'", name.c_str()); - return strong_ptr(); - } + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) { + close(fd); + ERR("Failed to bind to interface '%s'", name.c_str()); + return std::shared_ptr(); + } - // Detect the link-layer address. + // Detect the link-layer address. - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1); - ifr.ifr_name[IFNAMSIZ - 1] = '\0'; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1); + ifr.ifr_name[IFNAMSIZ - 1] = '\0'; - if(ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) - { - close(fd); - ERR("Failed to detect link-layer address for interface '%s'", name.c_str()); - return strong_ptr(); - } + if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { + close(fd); + ERR("Failed to detect link-layer address for interface '%s'", name.c_str()); + return std::shared_ptr(); + } - DBG("fd=%d, hwaddr=%s", fd, ether_ntoa((const struct ether_addr *)&ifr.ifr_hwaddr.sa_data)); + DBG("fd=%d, hwaddr=%s", fd, ether_ntoa((const struct ether_addr *)&ifr.ifr_hwaddr.sa_data)); - // Set max hops. + // Set max hops. - int hops = 255; + int hops = 255; - if(setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) < 0) - { - close(fd); - ERR("iface::open_ifd() failed IPV6_MULTICAST_HOPS"); - return strong_ptr(); - } + if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) < 0) { + close(fd); + ERR("iface::open_ifd() failed IPV6_MULTICAST_HOPS"); + return std::shared_ptr(); + } - if(setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof(hops)) < 0) - { - close(fd); - ERR("iface::open_ifd() failed IPV6_UNICAST_HOPS"); - return strong_ptr(); - } + if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof(hops)) < 0) { + close(fd); + ERR("iface::open_ifd() failed IPV6_UNICAST_HOPS"); + return std::shared_ptr(); + } - // Switch to non-blocking mode. + // Switch to non-blocking mode. - int on = 1; + int on = 1; - if(ioctl(fd, FIONBIO, (char *)&on) < 0) - { - close(fd); - ERR("Failed to switch to non-blocking on interface '%s'", name.c_str()); - return strong_ptr(); - } + if (ioctl(fd, FIONBIO, (char *)&on) < 0) { + close(fd); + ERR("Failed to switch to non-blocking on interface '%s'", name.c_str()); + return std::shared_ptr(); + } - // Set up filter. + // Set up filter. - struct icmp6_filter filter; - ICMP6_FILTER_SETBLOCKALL(&filter); - ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter); + struct icmp6_filter filter; + ICMP6_FILTER_SETBLOCKALL(&filter); + ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter); - if(setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) < 0) - { - ERR("Failed to set filter"); - return strong_ptr(); - } + if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) < 0) { + ERR("Failed to set filter"); + return std::shared_ptr(); + } - // Set up an instance of 'iface'. + // Set up an instance of 'iface'. - strong_ptr ifa; + std::shared_ptr ifa; - if(it == _map.end()) - { - ifa = new iface(); + if (it == _map.end()) { + ifa.reset(new iface()); + ifa->_name = name; + ifa->_ptr = ifa; - ifa->_name = name; - ifa->_ptr = ifa; + _map[name] = ifa; + } else { + ifa = it->second; + } - _map[name] = ifa; - } - else - { - ifa = it->second; - } + ifa->_ifd = fd; - ifa->_ifd = fd; + memcpy(&ifa->hwaddr, ifr.ifr_hwaddr.sa_data, sizeof(struct ether_addr)); - memcpy(&ifa->hwaddr, ifr.ifr_hwaddr.sa_data, sizeof(struct ether_addr)); + fixup_pollfds(); - fixup_pollfds(); - - return ifa; + return ifa; } ssize_t iface::read(int fd, struct sockaddr *saddr, uint8_t *msg, size_t size) { - struct msghdr mhdr; - struct iovec iov; - char cbuf[256]; - int len; + struct msghdr mhdr; + struct iovec iov; + char cbuf[256]; + int len; - if(!msg || (size < 0)) - return -1; + if (!msg || (size < 0)) + return -1; - iov.iov_len = size; - iov.iov_base = (caddr_t)msg; + iov.iov_len = size; + iov.iov_base = (caddr_t)msg; - memset(&mhdr, 0, sizeof(mhdr)); - mhdr.msg_name = (caddr_t)saddr; - mhdr.msg_namelen = sizeof(struct sockaddr); - mhdr.msg_iov = &iov; - mhdr.msg_iovlen = 1; + memset(&mhdr, 0, sizeof(mhdr)); + mhdr.msg_name = (caddr_t)saddr; + mhdr.msg_namelen = sizeof(struct sockaddr); + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; - if((len = recvmsg(fd, &mhdr, 0)) < 0) - return -1; + if ((len = recvmsg(fd, &mhdr, 0)) < 0) + return -1; - if(len < sizeof(struct icmp6_hdr)) - return -1; + if (len < sizeof(struct icmp6_hdr)) + return -1; - DBG("iface::read() len=%d", len); + DBG("iface::read() len=%d", len); - return len; + return len; } ssize_t iface::write(int fd, const address& daddr, const uint8_t *msg, size_t size) { - struct sockaddr_in6 daddr_tmp; - struct msghdr mhdr; - struct iovec iov; + struct sockaddr_in6 daddr_tmp; + struct msghdr mhdr; + struct iovec iov; - memset(&daddr_tmp, 0, sizeof(struct sockaddr_in6)); - daddr_tmp.sin6_family = AF_INET6; - daddr_tmp.sin6_port = htons(IPPROTO_ICMPV6); // Needed? - memcpy(&daddr_tmp.sin6_addr, &daddr.const_addr(), sizeof(struct in6_addr)); + memset(&daddr_tmp, 0, sizeof(struct sockaddr_in6)); + daddr_tmp.sin6_family = AF_INET6; + daddr_tmp.sin6_port = htons(IPPROTO_ICMPV6); // Needed? + memcpy(&daddr_tmp.sin6_addr, &daddr.const_addr(), sizeof(struct in6_addr)); - iov.iov_len = size; - iov.iov_base = (caddr_t)msg; + iov.iov_len = size; + iov.iov_base = (caddr_t)msg; - memset(&mhdr, 0, sizeof(mhdr)); - mhdr.msg_name = (caddr_t)&daddr_tmp; - mhdr.msg_namelen = sizeof(sockaddr_in6); - mhdr.msg_iov = &iov; - mhdr.msg_iovlen = 1; + memset(&mhdr, 0, sizeof(mhdr)); + mhdr.msg_name = (caddr_t)&daddr_tmp; + mhdr.msg_namelen = sizeof(sockaddr_in6); + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; - DBG("iface::write() daddr=%s, len=%d", daddr.to_string().c_str(), size); + DBG("iface::write() daddr=%s, len=%d", daddr.to_string().c_str(), size); - int len; + int len; - if((len = sendmsg(fd, &mhdr, 0)) < 0) - return -1; + if ((len = sendmsg(fd, &mhdr, 0)) < 0) + return -1; - return len; + return len; } ssize_t iface::read_solicit(address& saddr, address& daddr, address& taddr) { - struct sockaddr_ll t_saddr; - uint8_t msg[256]; - ssize_t len; + struct sockaddr_ll t_saddr; + uint8_t msg[256]; + ssize_t len; - if((len = read(_pfd, (struct sockaddr *)&t_saddr, msg, sizeof(msg))) < 0) - return -1; + if ((len = read(_pfd, (struct sockaddr *)&t_saddr, msg, sizeof(msg))) < 0) + return -1; - struct ip6_hdr *ip6h = - (struct ip6_hdr *)(msg + ETH_HLEN); + struct ip6_hdr *ip6h = + (struct ip6_hdr *)(msg + ETH_HLEN); - struct icmp6_hdr *icmph = - (struct icmp6_hdr *)(msg + ETH_HLEN + sizeof( struct ip6_hdr)); + struct icmp6_hdr *icmph = + (struct icmp6_hdr *)(msg + ETH_HLEN + sizeof( struct ip6_hdr)); - struct nd_neighbor_solicit *ns = - (struct nd_neighbor_solicit *)(msg + ETH_HLEN + sizeof( struct ip6_hdr)); + struct nd_neighbor_solicit *ns = + (struct nd_neighbor_solicit *)(msg + ETH_HLEN + sizeof( struct ip6_hdr)); - taddr = ns->nd_ns_target; - daddr = ip6h->ip6_dst; - saddr = ip6h->ip6_src; + taddr = ns->nd_ns_target; + daddr = ip6h->ip6_dst; + saddr = ip6h->ip6_src; - DBG("iface::read_solicit() saddr=%s, daddr=%s, taddr=%s, len=%d", - saddr.to_string().c_str(), daddr.to_string().c_str(), - taddr.to_string().c_str(), len); + DBG("iface::read_solicit() saddr=%s, daddr=%s, taddr=%s, len=%d", + saddr.to_string().c_str(), daddr.to_string().c_str(), + taddr.to_string().c_str(), len); - return len; + return len; } ssize_t iface::write_solicit(const address& taddr) { - char buf[128]; + char buf[128]; - memset(buf, 0, sizeof(buf)); + memset(buf, 0, sizeof(buf)); - struct nd_neighbor_solicit *ns = - (struct nd_neighbor_solicit *)&buf[0]; + struct nd_neighbor_solicit *ns = + (struct nd_neighbor_solicit *)&buf[0]; - struct nd_opt_hdr *opt = - (struct nd_opt_hdr *)&buf[sizeof(struct nd_neighbor_solicit)]; + struct nd_opt_hdr *opt = + (struct nd_opt_hdr *)&buf[sizeof(struct nd_neighbor_solicit)]; - opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; - opt->nd_opt_len = 1; + opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; + opt->nd_opt_len = 1; - ns->nd_ns_type = ND_NEIGHBOR_SOLICIT; + ns->nd_ns_type = ND_NEIGHBOR_SOLICIT; - memcpy(&ns->nd_ns_target, &taddr.const_addr(), sizeof(struct in6_addr)); + memcpy(&ns->nd_ns_target, &taddr.const_addr(), sizeof(struct in6_addr)); - memcpy(buf + sizeof(struct nd_neighbor_solicit) + sizeof(struct nd_opt_hdr), &hwaddr, 6); + memcpy(buf + sizeof(struct nd_neighbor_solicit) + sizeof(struct nd_opt_hdr), &hwaddr, 6); - // FIXME: Alright, I'm lazy. - static address multicast("ff02::1:ff00:0000"); + // FIXME: Alright, I'm lazy. + static address multicast("ff02::1:ff00:0000"); - address daddr; + address daddr; - daddr = multicast; + daddr = multicast; - daddr.addr().s6_addr[13] = taddr.const_addr().s6_addr[13]; - daddr.addr().s6_addr[14] = taddr.const_addr().s6_addr[14]; - daddr.addr().s6_addr[15] = taddr.const_addr().s6_addr[15]; + daddr.addr().s6_addr[13] = taddr.const_addr().s6_addr[13]; + daddr.addr().s6_addr[14] = taddr.const_addr().s6_addr[14]; + daddr.addr().s6_addr[15] = taddr.const_addr().s6_addr[15]; - DBG("iface::write_solicit() taddr=%s, daddr=%s", - taddr.to_string().c_str(), daddr.to_string().c_str()); + DBG("iface::write_solicit() taddr=%s, daddr=%s", + taddr.to_string().c_str(), daddr.to_string().c_str()); - return write(_ifd, daddr, (uint8_t *)buf, sizeof(struct nd_neighbor_solicit) + sizeof(struct nd_opt_hdr) + 6); + return write(_ifd, daddr, (uint8_t *)buf, sizeof(struct nd_neighbor_solicit) + sizeof(struct nd_opt_hdr) + 6); } ssize_t iface::write_advert(const address& daddr, const address& taddr, bool router) { - char buf[128]; + char buf[128]; - memset(buf, 0, sizeof(buf)); + memset(buf, 0, sizeof(buf)); - struct nd_neighbor_advert *na = - (struct nd_neighbor_advert *)&buf[0]; + struct nd_neighbor_advert *na = + (struct nd_neighbor_advert *)&buf[0]; - struct nd_opt_hdr *opt = - (struct nd_opt_hdr *)&buf[sizeof(struct nd_neighbor_advert)]; + struct nd_opt_hdr *opt = + (struct nd_opt_hdr *)&buf[sizeof(struct nd_neighbor_advert)]; - opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; - opt->nd_opt_len = 1; + opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; + opt->nd_opt_len = 1; - na->nd_na_type = ND_NEIGHBOR_ADVERT; - na->nd_na_flags_reserved = ND_NA_FLAG_SOLICITED | (router ? ND_NA_FLAG_ROUTER : 0); + na->nd_na_type = ND_NEIGHBOR_ADVERT; + na->nd_na_flags_reserved = ND_NA_FLAG_SOLICITED | (router ? ND_NA_FLAG_ROUTER : 0); - memcpy(&na->nd_na_target, &taddr.const_addr(), sizeof(struct in6_addr)); + memcpy(&na->nd_na_target, &taddr.const_addr(), sizeof(struct in6_addr)); - memcpy(buf + sizeof(struct nd_neighbor_advert) + sizeof(struct nd_opt_hdr), &hwaddr, 6); + memcpy(buf + sizeof(struct nd_neighbor_advert) + sizeof(struct nd_opt_hdr), &hwaddr, 6); - DBG("iface::write_advert() daddr=%s, taddr=%s", - daddr.to_string().c_str(), taddr.to_string().c_str()); + DBG("iface::write_advert() daddr=%s, taddr=%s", + daddr.to_string().c_str(), taddr.to_string().c_str()); - return write(_ifd, daddr, (uint8_t *)buf, sizeof(struct nd_neighbor_advert) + - sizeof(struct nd_opt_hdr) + 6); + return write(_ifd, daddr, (uint8_t *)buf, sizeof(struct nd_neighbor_advert) + + sizeof(struct nd_opt_hdr) + 6); } ssize_t iface::read_advert(address& saddr, address& taddr) { - struct sockaddr_in6 t_saddr; - uint8_t msg[256]; - ssize_t len; + struct sockaddr_in6 t_saddr; + uint8_t msg[256]; + ssize_t len; - if((len = read(_ifd, (struct sockaddr *)&t_saddr, msg, sizeof(msg))) < 0) - return -1; + if ((len = read(_ifd, (struct sockaddr *)&t_saddr, msg, sizeof(msg))) < 0) + return -1; - saddr = t_saddr.sin6_addr; + saddr = t_saddr.sin6_addr; - if(((struct icmp6_hdr *)msg)->icmp6_type != ND_NEIGHBOR_ADVERT) - return -1; + if (((struct icmp6_hdr *)msg)->icmp6_type != ND_NEIGHBOR_ADVERT) + return -1; - taddr = ((struct nd_neighbor_solicit *)msg)->nd_ns_target; + taddr = ((struct nd_neighbor_solicit *)msg)->nd_ns_target; - DBG("iface::read_advert() saddr=%s, taddr=%s, len=%d", - saddr.to_string().c_str(), taddr.to_string().c_str(), len); + DBG("iface::read_advert() saddr=%s, taddr=%s, len=%d", + saddr.to_string().c_str(), taddr.to_string().c_str(), len); - return len; + return len; } void iface::fixup_pollfds() { - _pollfds.resize(_map.size() * 2); + _pollfds.resize(_map.size() * 2); - int i = 0; + int i = 0; - DBG("iface::fixup_pollfds() _map.size()=%d", _map.size()); + DBG("iface::fixup_pollfds() _map.size()=%d", _map.size()); - for(std::map >::iterator it = _map.begin(); - it != _map.end(); it++) - { - _pollfds[i].fd = it->second->_ifd; - _pollfds[i].events = POLLIN; - _pollfds[i].revents = 0; - i++; + for (std::map >::iterator it = _map.begin(); + it != _map.end(); it++) { + _pollfds[i].fd = it->second->_ifd; + _pollfds[i].events = POLLIN; + _pollfds[i].revents = 0; + i++; - _pollfds[i].fd = it->second->_pfd; - _pollfds[i].events = POLLIN; - _pollfds[i].revents = 0; - i++; - } + _pollfds[i].fd = it->second->_pfd; + _pollfds[i].events = POLLIN; + _pollfds[i].revents = 0; + i++; + } } -void iface::remove_session(const strong_ptr& se) +void iface::remove_session(const std::shared_ptr& se) { - _sessions.remove(se); + for (std::list >::iterator it = _sessions.begin(); + it != _sessions.end(); it++) { + if (it->lock() == se) { + _sessions.erase(it); + break; + } + } } -void iface::add_session(const strong_ptr& se) +void iface::add_session(const std::shared_ptr& se) { - _sessions.push_back(se); + _sessions.push_back(se); } int iface::poll_all() { - if(_pollfds.size() == 0) - { - ::sleep(1); - return 0; - } + if (_pollfds.size() == 0) { + ::sleep(1); + return 0; + } - assert(_pollfds.size() == _map.size() * 2); + assert(_pollfds.size() == _map.size() * 2); - int len; + int len; - if((len = ::poll(&_pollfds[0], _pollfds.size(), 50)) < 0) - return -1; + if ((len = ::poll(&_pollfds[0], _pollfds.size(), 50)) < 0) + return -1; - if(len == 0) - return 0; + if (len == 0) + return 0; - std::map >::iterator i_it = _map.begin(); + std::map >::iterator i_it = _map.begin(); - int i = 0; + int i = 0; - for(std::vector::iterator f_it = _pollfds.begin(); - f_it != _pollfds.end(); f_it++) - { - assert(i_it != _map.end()); + for (std::vector::iterator f_it = _pollfds.begin(); + f_it != _pollfds.end(); f_it++) { + assert(i_it != _map.end()); - if(i && !(i % 2)) - i_it++; + if (i && !(i % 2)) + i_it++; - bool is_pfd = i++ % 2; + bool is_pfd = i++ % 2; - if(!(f_it->revents & POLLIN)) - continue; - - strong_ptr ifa = i_it->second; - - address saddr, daddr, taddr; - - if(is_pfd) - { - if(ifa->read_solicit(saddr, daddr, taddr) < 0) - { - ERR("Failed to read from interface '%s'", ifa->_name.c_str()); - continue; - } - - if(!saddr.is_unicast() || !daddr.is_multicast()) + if (!(f_it->revents & POLLIN)) continue; - ifa->_pr->handle_solicit(saddr, daddr, taddr); - } - else - { - if(ifa->read_advert(saddr, taddr) < 0) - { - ERR("Failed to read from interface '%s'", ifa->_name.c_str()); - continue; - } + std::shared_ptr ifa = i_it->second; - for(std::list >::iterator s_it = ifa->_sessions.begin(); - s_it != ifa->_sessions.end(); s_it++) - { - if(((*s_it)->taddr() == taddr) && ((*s_it)->status() == session::WAITING)) - { - (*s_it)->handle_advert(); - break; + address saddr, daddr, taddr; + + if (is_pfd) { + if (ifa->read_solicit(saddr, daddr, taddr) < 0) { + ERR("Failed to read from interface '%s'", ifa->_name.c_str()); + continue; } - } - } - } - return 0; + if (!saddr.is_unicast() || !daddr.is_multicast()) + continue; + + ifa->_pr->handle_solicit(saddr, daddr, taddr); + } else { + if (ifa->read_advert(saddr, taddr) < 0) { + ERR("Failed to read from interface '%s'", ifa->_name.c_str()); + continue; + } + + for (std::list >::iterator s_it = ifa->_sessions.begin(); + s_it != ifa->_sessions.end(); s_it++) { + const std::shared_ptr sess = s_it->lock(); + if ((sess->taddr() == taddr) && (sess->status() == session::WAITING)) { + sess->handle_advert(); + break; + } + } + } + } + + return 0; } int iface::allmulti(int state) { - struct ifreq ifr; + struct ifreq ifr; - DBG("iface::allmulti() state=%d, _name=\"%s\"", - state, _name.c_str()); + DBG("iface::allmulti() state=%d, _name=\"%s\"", + state, _name.c_str()); - state = !!state; + state = !!state; - strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ); + strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ); - if(ioctl(_pfd, SIOCGIFFLAGS, &ifr) < 0) - return -1; + 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) - return old_state; + if (state == old_state) + return old_state; - if(state) - ifr.ifr_flags |= IFF_ALLMULTI; - else - ifr.ifr_flags &= ~IFF_ALLMULTI; + if (state) + ifr.ifr_flags |= IFF_ALLMULTI; + else + ifr.ifr_flags &= ~IFF_ALLMULTI; - if(ioctl(_pfd, SIOCSIFFLAGS, &ifr) < 0) - return -1; + if (ioctl(_pfd, SIOCSIFFLAGS, &ifr) < 0) + return -1; - return old_state; + return old_state; } const std::string& iface::name() const { - return _name; + return _name; } -void iface::pr(const strong_ptr& pr) +void iface::pr(const std::shared_ptr& pr) { - _pr = pr; + _pr = pr; } -const strong_ptr& iface::pr() const +const std::shared_ptr& iface::pr() const { - return _pr; + return _pr; } __NDPPD_NS_END diff --git a/src/iface.h b/src/iface.h index c1e4bae..08b5b12 100644 --- a/src/iface.h +++ b/src/iface.h @@ -34,85 +34,85 @@ class proxy; class iface { private: - // Weak pointer so this object can reference itself. - weak_ptr _ptr; + // Weak pointer so this object can reference itself. + std::weak_ptr _ptr; - static std::map > _map; + static std::map > _map; - // An array of objects used with ::poll. - static std::vector _pollfds; + // An array of objects used with ::poll. + static std::vector _pollfds; - // Updates the array above. - static void fixup_pollfds(); + // Updates the array above. + static void fixup_pollfds(); - // The "generic" ICMPv6 socket for reading/writing NB_NEIGHBOR_ADVERT - // messages as well as writing NB_NEIGHBOR_SOLICIT messages. - int _ifd; + // The "generic" ICMPv6 socket for reading/writing NB_NEIGHBOR_ADVERT + // messages as well as writing NB_NEIGHBOR_SOLICIT messages. + int _ifd; - // This is the PF_PACKET socket we use in order to read - // NB_NEIGHBOR_SOLICIT messages. - int _pfd; + // This is the PF_PACKET socket we use in order to read + // NB_NEIGHBOR_SOLICIT messages. + int _pfd; - // Previous state of ALLMULTI for the interface. - int _prev_allmulti; + // Previous state of ALLMULTI for the interface. + int _prev_allmulti; - // Name of this interface. - std::string _name; + // Name of this interface. + std::string _name; - // An array of sessions that are monitoring this interface for - // ND_NEIGHBOR_ADVERT messages. - std::list > _sessions; + // An array of sessions that are monitoring this interface for + // ND_NEIGHBOR_ADVERT messages. + std::list > _sessions; - strong_ptr _pr; + std::shared_ptr _pr; - // The link-layer address of this interface. - struct ether_addr hwaddr; + // The link-layer address of this interface. + struct ether_addr hwaddr; - // Turns on/off ALLMULTI for this interface - returns the previous state - // or -1 if there was an error. - int allmulti(int state); + // Turns on/off ALLMULTI for this interface - returns the previous state + // or -1 if there was an error. + int allmulti(int state); - // Constructor. - iface(); + // Constructor. + iface(); public: - // Destructor. - ~iface(); + // Destructor. + ~iface(); - static strong_ptr open_ifd(const std::string& name); + static std::shared_ptr open_ifd(const std::string& name); - static strong_ptr open_pfd(const std::string& name); + static std::shared_ptr open_pfd(const std::string& name); - static int poll_all(); + static int poll_all(); - static ssize_t read(int fd, struct sockaddr *saddr, uint8_t *msg, size_t size); + static ssize_t read(int fd, struct sockaddr *saddr, uint8_t *msg, size_t size); - static ssize_t write(int fd, const address& daddr, const uint8_t *msg, size_t size); + static ssize_t write(int fd, const address& daddr, const uint8_t *msg, size_t size); - // Writes a NB_NEIGHBOR_SOLICIT message to the _ifd socket. - ssize_t write_solicit(const address& taddr); + // Writes a NB_NEIGHBOR_SOLICIT message to the _ifd socket. + ssize_t write_solicit(const address& taddr); - // Writes a NB_NEIGHBOR_ADVERT message to the _ifd socket; - ssize_t write_advert(const address& daddr, const address& taddr, bool router); + // Writes a NB_NEIGHBOR_ADVERT message to the _ifd socket; + ssize_t write_advert(const address& daddr, const address& taddr, bool router); - // Reads a NB_NEIGHBOR_SOLICIT message from the _pfd socket. - ssize_t read_solicit(address& saddr, address& daddr, address& taddr); + // Reads a NB_NEIGHBOR_SOLICIT message from the _pfd socket. + ssize_t read_solicit(address& saddr, address& daddr, address& taddr); - // Reads a NB_NEIGHBOR_ADVERT message from the _ifd socket; - ssize_t read_advert(address& saddr, address& taddr); + // Reads a NB_NEIGHBOR_ADVERT message from the _ifd socket; + ssize_t read_advert(address& saddr, address& taddr); - // Returns the name of the interface. - const std::string& name() const; + // Returns the name of the interface. + const std::string& name() const; - // Adds a session to be monitored for ND_NEIGHBOR_ADVERT messages. - void add_session(const strong_ptr& se); + // Adds a session to be monitored for ND_NEIGHBOR_ADVERT messages. + void add_session(const std::shared_ptr& se); - void remove_session(const strong_ptr& se); + void remove_session(const std::shared_ptr& se); - void pr(const strong_ptr& pr); + void pr(const std::shared_ptr& pr); - const strong_ptr& pr() const; + const std::shared_ptr& pr() const; }; __NDPPD_NS_END diff --git a/src/log.cc b/src/log.cc index eb4a249..24c685e 100644 --- a/src/log.cc +++ b/src/log.cc @@ -25,68 +25,66 @@ __NDPPD_NS_BEGIN const char *log::_level_str[] = { - "fatal", - "alert", - "critical", - "error", - "warning", - "notice", - "info", - "debug" + "fatal", + "alert", + "critical", + "error", + "warning", + "notice", + "info", + "debug" }; bool log::_syslog = false; void log::puts(int level, const char *str) { - const char *ls; + const char *ls; - if((level < 0) || (level > LOG_DEBUG)) - ls = "unknown"; - else - ls = _level_str[level]; + if ((level < 0) || (level > LOG_DEBUG)) + ls = "unknown"; + else + ls = _level_str[level]; - if(_syslog) - ::syslog(level, "(%s) %s", ls, str); - else - fprintf(stderr, "(% 8s) %s\n", ls, str); + if (_syslog) + ::syslog(level, "(%s) %s", ls, str); + else + fprintf(stderr, "(% 8s) %s\n", ls, str); } void log::printf(int level, const char *fmt, ...) { - char buf[256]; - va_list args; - int ret; + char buf[256]; + va_list args; + int ret; - va_start(args, fmt); + va_start(args, fmt); - if(vsnprintf(buf, sizeof(buf), fmt, args) > 0) - { - puts(level, buf); - } + if (vsnprintf(buf, sizeof(buf), fmt, args) > 0) { + puts(level, buf); + } - va_end(args); + va_end(args); } void log::syslog(bool sl) { - if(sl == _syslog) - return; + if (sl == _syslog) + return; - if(_syslog = sl) - { + if (_syslog = sl) { #ifdef DEBUG - setlogmask(LOG_UPTO(LOG_DEBUG)); - openlog("ndppd", LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER); + setlogmask(LOG_UPTO(LOG_DEBUG)); + openlog("ndppd", LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER); #else - setlogmask(LOG_UPTO(LOG_INFO)); - openlog("ndppd", LOG_CONS, LOG_USER); + setlogmask(LOG_UPTO(LOG_INFO)); + openlog("ndppd", LOG_CONS, LOG_USER); #endif - } - else - { - closelog(); - } + } + else + { + closelog(); + } } __NDPPD_NS_END diff --git a/src/log.h b/src/log.h index 0a256d3..4569a35 100644 --- a/src/log.h +++ b/src/log.h @@ -35,16 +35,16 @@ __NDPPD_NS_BEGIN class log { private: - static const char *_level_str[]; + static const char *_level_str[]; - static bool _syslog; + static bool _syslog; public: - static void puts(int level, const char *str); + static void puts(int level, const char *str); - static void printf(int level, const char *fmt, ...); + static void printf(int level, const char *fmt, ...); - static void syslog(bool enable); + static void syslog(bool enable); }; __NDPPD_NS_END diff --git a/src/ndppd.cc b/src/ndppd.cc index 0b7a9f4..053b2e4 100644 --- a/src/ndppd.cc +++ b/src/ndppd.cc @@ -29,111 +29,105 @@ using namespace ndppd; int daemonize() { - pid_t pid = fork(); + pid_t pid = fork(); - if(pid < 0) - return -1; + if (pid < 0) + return -1; - if(pid > 0) - exit(0); + if (pid > 0) + exit(0); - pid_t sid = setsid(); + pid_t sid = setsid(); - if(sid < 0) - return -1; + if (sid < 0) + return -1; - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); - return 0; + return 0; } int main(int argc, char *argv[], char *env[]) { - std::string config_path("/etc/ndppd.conf"); - std::string pidfile; - bool daemon = false; + std::string config_path("/etc/ndppd.conf"); + std::string pidfile; + bool daemon = false; - while(1) - { - int c, opt; + while (1) { + int c, opt; - static struct option long_options[] = - { - { "config", 1, 0, 'c' }, - { "daemon", 0, 0, 'd' }, - { 0, 0, 0, 0} - }; + static struct option long_options[] = + { + { "config", 1, 0, 'c' }, + { "daemon", 0, 0, 'd' }, + { 0, 0, 0, 0} + }; - c = getopt_long(argc, argv, "c:dp:", long_options, &opt); + c = getopt_long(argc, argv, "c:dp:", long_options, &opt); - if(c == -1) - break; + if (c == -1) + break; - switch(c) - { - case 'c': - config_path = optarg; - break; + switch (c) { + case 'c': + config_path = optarg; + break; - case 'd': - daemon = true; - break; + case 'd': + daemon = true; + break; - case 'p': - pidfile = optarg; - break; - } - } + case 'p': + pidfile = optarg; + break; + } + } - if(daemon) - { - log::syslog(true); + if (daemon) { + log::syslog(true); - if(daemonize() < 0) - { - ERR("Failed to daemonize process"); - return 1; - } - } + if (daemonize() < 0) { + ERR("Failed to daemonize process"); + return 1; + } + } - if(!pidfile.empty()) - { - std::ofstream pf; - pf.open(pidfile.c_str(), std::ios::out | std::ios::trunc); - pf << getpid() << std::endl; - pf.close(); - } + if (!pidfile.empty()) { + std::ofstream pf; + pf.open(pidfile.c_str(), std::ios::out | std::ios::trunc); + pf << getpid() << std::endl; + pf.close(); + } - NFO("ndppd (NDP Proxy Daemon) version " NDPPD_VERSION); + NFO("ndppd (NDP Proxy Daemon) version " NDPPD_VERSION); - NFO("Using configuration file '%s'", config_path.c_str()); + NFO("Using configuration file '%s'", config_path.c_str()); - if(!conf::load(config_path)) - return -1; + if (!conf::load(config_path)) + return -1; - struct timeval t1, t2; + struct timeval t1, t2; - gettimeofday(&t1, 0); + gettimeofday(&t1, 0); - while(iface::poll_all() >= 0) - { - int elapsed_time; - gettimeofday(&t2, 0); + while (iface::poll_all() >= 0) { + int elapsed_time; + gettimeofday(&t2, 0); - elapsed_time = - ((t2.tv_sec - t1.tv_sec) * 1000) + - ((t2.tv_usec - t1.tv_usec) / 1000); + elapsed_time = + ((t2.tv_sec - t1.tv_sec) * 1000) + + ((t2.tv_usec - t1.tv_usec) / 1000); - t1.tv_sec = t2.tv_sec; - t1.tv_usec = t2.tv_usec; + t1.tv_sec = t2.tv_sec; + t1.tv_usec = t2.tv_usec; - session::update_all(elapsed_time); - } + session::update_all(elapsed_time); + } - ERR("iface::poll_all() failed"); + ERR("iface::poll_all() failed"); - return 0; + return 0; } diff --git a/src/ndppd.h b/src/ndppd.h index 7445e91..2ed88f2 100644 --- a/src/ndppd.h +++ b/src/ndppd.h @@ -17,6 +17,7 @@ #define __NDPPD_H #include +#include #define __NDPPD_NS_BEGIN namespace ndppd { #define __NDPPD_NS_END } @@ -26,7 +27,6 @@ #include #include "log.h" -#include "ptr.h" #include "conf.h" #include "address.h" diff --git a/src/proxy.cc b/src/proxy.cc index aa878d1..973ba1b 100644 --- a/src/proxy.cc +++ b/src/proxy.cc @@ -27,151 +27,145 @@ __NDPPD_NS_BEGIN proxy::proxy() : - _router(true), _ttl(30000), _timeout(500) + _router(true), _ttl(30000), _timeout(500) { } -strong_ptr proxy::create(const strong_ptr& ifa) +std::shared_ptr proxy::create(const std::shared_ptr& ifa) { - strong_ptr pr(new proxy()); - pr->_ptr = pr; - pr->_ifa = ifa; + std::shared_ptr pr(new proxy()); + pr->_ptr = pr; + pr->_ifa = ifa; - ifa->pr(pr); + ifa->pr(pr); - DBG("proxy::create() if=%x", ifa->name().c_str()); + DBG("proxy::create() if=%x", ifa->name().c_str()); - return pr; + return pr; } -strong_ptr proxy::open(const std::string& ifname) +std::shared_ptr proxy::open(const std::string& ifname) { - strong_ptr ifa = iface::open_pfd(ifname); + std::shared_ptr ifa = iface::open_pfd(ifname); - if(ifa.is_null()) - return strong_ptr(); + if (!ifa) + return std::shared_ptr(); - return create(ifa); + return create(ifa); } void proxy::handle_solicit(const address& saddr, const address& daddr, - const address& taddr) + const address& taddr) { - DBG("proxy::handle_solicit() saddr=%s, taddr=%s", - saddr.to_string().c_str(), taddr.to_string().c_str()); + DBG("proxy::handle_solicit() saddr=%s, taddr=%s", + saddr.to_string().c_str(), taddr.to_string().c_str()); - // Let's check this proxy's list of sessions to see if we can - // find one with the same target address. + // Let's check this proxy's list of sessions to see if we can + // find one with the same target address. - for(std::list >::iterator sit = _sessions.begin(); - sit != _sessions.end(); sit++) - { - if((*sit)->taddr() == taddr) - { - switch((*sit)->status()) - { - case session::WAITING: - case session::INVALID: - break; + for (std::list >::iterator sit = _sessions.begin(); + sit != _sessions.end(); sit++) { + + if ((*sit)->taddr() == taddr) { + switch ((*sit)->status()) { + case session::WAITING: + case session::INVALID: + break; - case session::VALID: - (*sit)->send_advert(); - } + case session::VALID: + (*sit)->send_advert(); + } - return; - } - } - - // Since we couldn't find a session that matched, we'll try to find - // a matching rule instead, and then set up a new session. - - strong_ptr se; - - for(std::list >::iterator it = _rules.begin(); - it != _rules.end(); it++) - { - strong_ptr ru = *it; - - DBG("comparing %s against %s", - ru->addr().to_string().c_str(), taddr.to_string().c_str()); - - if(ru->addr() == taddr) - { - if(se.is_null()) - se = session::create(_ptr, saddr, daddr, taddr); - - if(ru->ifa().is_null()) - { - // This rule doesn't have an interface, and thus we'll consider - // it "static" and immediately send the response. - - se->handle_advert(); return; - } + } + } - se->add_iface((*it)->ifa()); - } - } + // Since we couldn't find a session that matched, we'll try to find + // a matching rule instead, and then set up a new session. - if(se) - { - _sessions.push_back(se); - se->send_solicit(); - } + std::shared_ptr se; + + for (std::list >::iterator it = _rules.begin(); + it != _rules.end(); it++) { + std::shared_ptr ru = *it; + + DBG("comparing %s against %s", + ru->addr().to_string().c_str(), taddr.to_string().c_str()); + + if (ru->addr() == taddr) { + if (!se) + se = session::create(_ptr.lock(), saddr, daddr, taddr); + + if (!ru->ifa()) { + // This rule doesn't have an interface, and thus we'll consider + // it "static" and immediately send the response. + + se->handle_advert(); + return; + } + + se->add_iface((*it)->ifa()); + } + } + + if (se) { + _sessions.push_back(se); + se->send_solicit(); + } } -strong_ptr proxy::add_rule(const address& addr, const strong_ptr& ifa) +std::shared_ptr proxy::add_rule(const address& addr, const std::shared_ptr& ifa) { - strong_ptr ru(rule::create(_ptr, addr, ifa)); - _rules.push_back(ru); - return ru; + std::shared_ptr ru(rule::create(_ptr.lock(), addr, ifa)); + _rules.push_back(ru); + return ru; } -strong_ptr proxy::add_rule(const address& addr) +std::shared_ptr proxy::add_rule(const address& addr) { - strong_ptr ru(rule::create(_ptr, addr)); - _rules.push_back(ru); - return ru; + std::shared_ptr ru(rule::create(_ptr.lock(), addr)); + _rules.push_back(ru); + return ru; } -void proxy::remove_session(const strong_ptr& se) +void proxy::remove_session(const std::shared_ptr& se) { - _sessions.remove(se); + _sessions.remove(se); } -const strong_ptr& proxy::ifa() const +const std::shared_ptr& proxy::ifa() const { - return _ifa; + return _ifa; } bool proxy::router() const { - return _router; + return _router; } void proxy::router(bool val) { - _router = val; + _router = val; } int proxy::ttl() const { - return _ttl; + return _ttl; } void proxy::ttl(int val) { - _ttl = (val >= 0) ? val : 30000; + _ttl = (val >= 0) ? val : 30000; } int proxy::timeout() const { - return _timeout; + return _timeout; } void proxy::timeout(int val) { - _timeout = (val >= 0) ? val : 500; + _timeout = (val >= 0) ? val : 500; } __NDPPD_NS_END diff --git a/src/proxy.h b/src/proxy.h index 47ad70f..d64ddae 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -32,47 +32,47 @@ class rule; class proxy { private: - weak_ptr _ptr; + std::weak_ptr _ptr; - strong_ptr _ifa; + std::shared_ptr _ifa; - std::list > _rules; + std::list > _rules; - std::list > _sessions; + std::list > _sessions; - bool _router; + bool _router; - int _ttl, _timeout; + int _ttl, _timeout; - proxy(); + proxy(); public: - static strong_ptr create(const strong_ptr& ifa); + static std::shared_ptr create(const std::shared_ptr& ifa); - static strong_ptr open(const std::string& ifn); + static std::shared_ptr open(const std::string& ifn); - void handle_solicit(const address& saddr, const address& daddr, - const address& taddr); + void handle_solicit(const address& saddr, const address& daddr, + const address& taddr); - void remove_session(const strong_ptr& se); + void remove_session(const std::shared_ptr& se); - strong_ptr add_rule(const address& addr, const strong_ptr& ifa); + std::shared_ptr add_rule(const address& addr, const std::shared_ptr& ifa); - strong_ptr add_rule(const address& addr); + std::shared_ptr add_rule(const address& addr); - const strong_ptr& ifa() const; + const std::shared_ptr& ifa() const; - bool router() const; + bool router() const; - void router(bool val); + void router(bool val); - int timeout() const; + int timeout() const; - void timeout(int val); + void timeout(int val); - int ttl() const; + int ttl() const; - void ttl(int val); + void ttl(int val); }; __NDPPD_NS_END diff --git a/src/ptr.h b/src/ptr.h deleted file mode 100644 index 76a9094..0000000 --- a/src/ptr.h +++ /dev/null @@ -1,243 +0,0 @@ -// ndppd - NDP Proxy Daemon -// Copyright (C) 2011 Daniel Adolfsson -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -#ifndef __NDPPD_PTR_H -#define __NDPPD_PTR_H - -#include - -__NDPPD_NS_BEGIN - -// This template class simplifies the usage of pointers. It's basically -// a reference-counting smart pointer that supports both weak and -// strong references. - -template -class ptr -{ -protected: - struct ref - { - public: - T* p; - int n_strong; - int n_weak; - }; - - ref *_ref; - - bool _strong; - - void acquire(T* p) - { - if(_ref) - release(); - - if(p) - { - _ref = new ref; - _ref->p = p; - _ref->n_strong = _strong ? 1 : 0; - _ref->n_weak = _strong ? 0 : 1; - } - } - - void acquire(const ptr& p) - { - if(_ref) - release(); - - if(p._ref && p._ref->n_strong) - { - _ref = p._ref; - - if(_strong) - _ref->n_strong++; - else - _ref->n_weak++; - } - } - - void release() - { - if(!_ref) - return; - - if(_strong) - { - // Assert _ref->n_strong > 0. - - if(_ref->n_strong == 1) - { - delete _ref->p; - _ref->p = 0; - } - - _ref->n_strong--; - } - else - { - _ref->n_weak--; - } - - if(!_ref->n_weak && !_ref->n_strong) - delete _ref; - - _ref = 0; - } - - ptr(bool strong) : - _strong(strong), _ref(0) - { - } - - ptr(bool strong, T* p) : - _strong(strong), _ref(0) - { - if(p) - acquire(p); - } - - ptr(bool strong, const ptr& p) : - _strong(strong), _ref(0) - { - acquire(p); - } - - virtual ~ptr() - { - if(_ref) - release(); - } - -public: - - void operator=(T* p) - { - acquire(p); - } - - void operator=(const ptr& p) - { - acquire(p); - } - - bool operator==(const ptr& other) const - { - return other._ref == _ref; - } - - bool operator!=(const ptr& other) const - { - return other._ref != _ref; - } - - bool is_null() const - { - return !((_ref != 0) && (_ref->p != 0)); - } - - T& operator*() const - { - return *_ref.p; - } - - T* operator->() const - { - return _ref ? _ref->p : 0; - } - - operator T*() const - { - return _ref->p; - } - - operator bool() const - { - return !is_null(); - } - - bool is_strong() const - { - return _strong; - } - - bool is_weak() const - { - return !_strong; - } - - void reset(T *p = 0) - { - acquire(p); - } -}; - -template -class weak_ptr; - -template -class strong_ptr : public ptr -{ -public: - strong_ptr() : ptr(true) - { - } - - strong_ptr(T* p) : ptr(true, p) - { - } - - strong_ptr(const ptr& p) : ptr(true, p) - { - } - - strong_ptr(const strong_ptr& p) : ptr(true, p) - { - } - - strong_ptr(const weak_ptr& p) : ptr(true, p) - { - } -}; - -template -class weak_ptr : public ptr -{ -public: - weak_ptr() : ptr(false) - { - } - - weak_ptr(T* p) : ptr(false, p) - { - } - - weak_ptr(const ptr& p) : ptr(false, p) - { - } - - weak_ptr(const strong_ptr& p) : ptr(false, p) - { - } - - weak_ptr(const weak_ptr& p) : ptr(false, p) - { - } -}; - -__NDPPD_NS_END - -#endif // __NDPPD_PTR_H diff --git a/src/rule.cc b/src/rule.cc index 07bfee4..4aa7cce 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -28,51 +28,51 @@ rule::rule() { } -strong_ptr rule::create(const strong_ptr& pr, const address& addr, const strong_ptr& ifa) +std::shared_ptr rule::create(const std::shared_ptr& pr, const address& addr, const std::shared_ptr& ifa) { - strong_ptr ru(new rule()); - ru->_ptr = ru; - ru->_pr = pr; - ru->_ifa = ifa; - ru->_addr = addr; + std::shared_ptr ru(new rule()); + ru->_ptr = ru; + ru->_pr = pr; + ru->_ifa = ifa; + ru->_addr = addr; - DBG("rule::create() if=%s, addr=%s", - pr->ifa()->name().c_str(), addr.to_string().c_str()); + DBG("rule::create() if=%s, addr=%s", + pr->ifa()->name().c_str(), addr.to_string().c_str()); - return ru; + return ru; } -strong_ptr rule::create(const strong_ptr& pr, const address& addr) +std::shared_ptr rule::create(const std::shared_ptr& pr, const address& addr) { - strong_ptr ru(new rule()); - ru->_ptr = ru; - ru->_pr = pr; - ru->_addr = addr; + std::shared_ptr ru(new rule()); + ru->_ptr = ru; + ru->_pr = pr; + ru->_addr = addr; - DBG("rule::create() if=%s, addr=%s", - pr->ifa()->name().c_str(), addr.to_string().c_str()); + DBG("rule::create() if=%s, addr=%s", + pr->ifa()->name().c_str(), addr.to_string().c_str()); - return ru; + return ru; } const address& rule::addr() const { - return _addr; + return _addr; } -strong_ptr rule::ifa() const +std::shared_ptr rule::ifa() const { - return _ifa; + return _ifa; } bool rule::is_static() const { - return !!_ifa; + return !!_ifa; } bool rule::check(const address& addr) const { - return _addr == addr; + return _addr == addr; } __NDPPD_NS_END diff --git a/src/rule.h b/src/rule.h index 1d36610..a8a49ed 100644 --- a/src/rule.h +++ b/src/rule.h @@ -32,28 +32,28 @@ class proxy; class rule { private: - weak_ptr _ptr; + std::weak_ptr _ptr; - strong_ptr _pr; + std::shared_ptr _pr; - strong_ptr _ifa; + std::shared_ptr _ifa; - address _addr; + address _addr; - rule(); + rule(); public: - static strong_ptr create(const strong_ptr& pr, const address& addr, const strong_ptr& ifa); + static std::shared_ptr create(const std::shared_ptr& pr, const address& addr, const std::shared_ptr& ifa); - static strong_ptr create(const strong_ptr& pr, const address& addr); + static std::shared_ptr create(const std::shared_ptr& pr, const address& addr); - const address& addr() const; + const address& addr() const; - strong_ptr ifa() const; + std::shared_ptr ifa() const; - bool is_static() const; + bool is_static() const; - bool check(const address& addr) const; + bool check(const address& addr) const; }; diff --git a/src/session.cc b/src/session.cc index 75b0bc5..266265f 100644 --- a/src/session.cc +++ b/src/session.cc @@ -22,123 +22,125 @@ __NDPPD_NS_BEGIN -std::list > session::_sessions; +std::list > session::_sessions; void session::update_all(int elapsed_time) { - for(std::list >::iterator it = _sessions.begin(); - it != _sessions.end(); ) - { - strong_ptr se = *it++; + for (std::list >::iterator it = _sessions.begin(); + it != _sessions.end(); ) { + std::shared_ptr se = (*it++).lock(); - if((se->_ttl -= elapsed_time) >= 0) - continue; + if ((se->_ttl -= elapsed_time) >= 0) + continue; - switch(se->_status) - { - case session::WAITING: - DBG("session is now invalid"); - se->_status = session::INVALID; - se->_ttl = se->_pr->ttl(); - break; + switch (se->_status) { + case session::WAITING: + DBG("session is now invalid"); + se->_status = session::INVALID; + se->_ttl = se->_pr->ttl(); + break; - default: - se->_pr->remove_session(se); - } - } + default: + se->_pr->remove_session(se); + } + } } session::~session() { - DBG("session::~session() this=%x", this); + DBG("session::~session() this=%x", this); - _sessions.remove(_ptr); + for (std::list >::iterator it = _sessions.begin(); + it != _sessions.end(); it++) { + if (it->lock() == _ptr.lock()) { + _sessions.erase(it); + break; + } + } - for(std::list >::iterator it = _ifaces.begin(); - it != _ifaces.end(); it++) - { - (*it)->remove_session(_ptr); - } + for (std::list >::iterator it = _ifaces.begin(); + it != _ifaces.end(); it++) { + (*it)->remove_session(_ptr.lock()); + } } -strong_ptr session::create(const strong_ptr& pr, const address& saddr, - const address& daddr, const address& taddr) +std::shared_ptr session::create(const std::shared_ptr& pr, const address& saddr, + const address& daddr, const address& taddr) { - strong_ptr se(new session()); + std::shared_ptr se(new session()); - se->_ptr = se; - se->_pr = pr; - se->_saddr = saddr; - se->_taddr = taddr; - se->_daddr = daddr; - se->_ttl = pr->timeout(); + se->_ptr = se; + se->_pr = pr; + se->_saddr = saddr; + se->_taddr = taddr; + se->_daddr = daddr; + se->_ttl = pr->timeout(); - _sessions.push_back(se); + _sessions.push_back(se); - DBG("session::create() pr=%x, saddr=%s, daddr=%s, taddr=%s, =%x", - (proxy *)pr, saddr.to_string().c_str(), daddr.to_string().c_str(), - taddr.to_string().c_str(), (session *)se); + DBG("session::create() pr=%x, saddr=%s, daddr=%s, taddr=%s, =%x", + (proxy *)pr, saddr.to_string().c_str(), daddr.to_string().c_str(), + taddr.to_string().c_str(), (session *)se); - return se; + return se; } -void session::add_iface(const strong_ptr& ifa) +void session::add_iface(const std::shared_ptr& ifa) { - if(std::find(_ifaces.begin(), _ifaces.end(), ifa) != _ifaces.end()) - return; + if (std::find(_ifaces.begin(), _ifaces.end(), ifa) != _ifaces.end()) + return; - ifa->add_session(_ptr); - _ifaces.push_back(ifa); + ifa->add_session(_ptr.lock()); + _ifaces.push_back(ifa); } void session::send_solicit() { - DBG("session::send_solicit() (%d)", _ifaces.size()); + DBG("session::send_solicit() (%d)", _ifaces.size()); - for(std::list >::iterator it = _ifaces.begin(); - it != _ifaces.end(); it++) - { - DBG(" - %s", (*it)->name().c_str()); - (*it)->write_solicit(_taddr); - } + for (std::list >::iterator it = _ifaces.begin(); + it != _ifaces.end(); it++) { + DBG(" - %s", (*it)->name().c_str()); + (*it)->write_solicit(_taddr); + } } void session::send_advert() { - _pr->ifa()->write_advert(_saddr, _taddr, _pr->router()); + _pr->ifa()->write_advert(_saddr, _taddr, _pr->router()); } void session::handle_advert() { - _status = VALID; - _ttl = _pr->ttl(); + _status = VALID; + _ttl = _pr->ttl(); - send_advert(); + send_advert(); } const address& session::taddr() const { - return _taddr; + return _taddr; } const address& session::saddr() const { - return _saddr; + return _saddr; } const address& session::daddr() const { - return _daddr; + return _daddr; } int session::status() const { - return _status; + return _status; } void session::status(int val) { - _status = val; + _status = val; } __NDPPD_NS_END diff --git a/src/session.h b/src/session.h index 3ec5cd0..78fb75a 100644 --- a/src/session.h +++ b/src/session.h @@ -28,59 +28,59 @@ class iface; class session { private: - weak_ptr _ptr; + std::weak_ptr _ptr; - strong_ptr _pr; + std::shared_ptr _pr; - address _saddr, _daddr, _taddr; + address _saddr, _daddr, _taddr; - // An array of interfaces this session is monitoring for - // ND_NEIGHBOR_ADVERT on. - std::list > _ifaces; + // An array of interfaces this session is monitoring for + // ND_NEIGHBOR_ADVERT on. + std::list > _ifaces; - // The remaining time in miliseconds the object will stay in the - // interface's session array or cache. - int _ttl; + // The remaining time in miliseconds the object will stay in the + // interface's session array or cache. + int _ttl; - int _status; + int _status; - static std::list > _sessions; + static std::list > _sessions; public: - enum - { - WAITING, // Waiting for an advert response. - VALID, // Valid; - INVALID // Invalid; - }; + enum + { + WAITING, // Waiting for an advert response. + VALID, // Valid; + INVALID // Invalid; + }; - static void update_all(int elapsed_time); + static void update_all(int elapsed_time); - // Destructor. - ~session(); + // Destructor. + ~session(); - static strong_ptr create(const strong_ptr& pr, const address& saddr, - const address& daddr, const address& taddr); + static std::shared_ptr create(const std::shared_ptr& pr, const address& saddr, + const address& daddr, const address& taddr); - void add_iface(const strong_ptr& ifa); + void add_iface(const std::shared_ptr& ifa); - const address& taddr() const; + const address& taddr() const; - const address& daddr() const; + const address& daddr() const; - const address& saddr() const; + const address& saddr() const; - int status() const; + int status() const; - void status(int val); + void status(int val); - void handle_advert(); + void handle_advert(); - void send_advert(); + void send_advert(); - void send_solicit(); + void send_solicit(); - void refesh(); + void refesh(); };