diff --git a/Makefile b/Makefile index fc49401..de0d737 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ SBINDIR ?= ${DESTDIR}${PREFIX}/sbin LIBS = OBJS = src/logger.o src/ndppd.o src/iface.o src/proxy.o src/address.o \ - src/rule.o src/session.o src/conf.o + src/rule.o src/session.o src/conf.o src/route.o all: ndppd ndppd.1.gz ndppd.conf.5.gz diff --git a/src/address.cc b/src/address.cc index 5c678e6..1097f63 100644 --- a/src/address.cc +++ b/src/address.cc @@ -53,7 +53,7 @@ address::address(const std::string& str) parse_string(str); } -address::address(const char *str) +address::address(const char* str) { parse_string(str); } @@ -125,13 +125,16 @@ void address::reset() int address::prefix() const { - if (!_mask.s6_addr[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))) + + if (!(_mask.s6_addr[byi]& (1 << bii))) { return p; + } } return 128; @@ -139,40 +142,58 @@ int address::prefix() const void address::prefix(int pf) { - if ((pf < 0) || (pf > 128)) + const unsigned char maskbit[] = { + 0x00, 0x80, 0xc0, 0xe0, 0xf0, + 0xf8, 0xfc, 0xfe, 0xff + }; + + if (pf >= 128) { + _mask.s6_addr32[0] = 0xffffffff; + _mask.s6_addr32[1] = 0xffffffff; + _mask.s6_addr32[2] = 0xffffffff; + _mask.s6_addr32[3] = 0xffffffff; return; + } else { + _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; + if (pf <= 0) { + return; + } } + + int offset = pf / 8, n; + + for (n = 0; n < offset; n++) { + _mask.s6_addr[n] = 0xff; + } + + _mask.s6_addr[offset] = maskbit[pf % 8]; } const std::string address::to_string() const { char buf[INET6_ADDRSTRLEN + 8]; - if (!inet_ntop(AF_INET6, &_addr, buf, INET6_ADDRSTRLEN)) + if (!inet_ntop(AF_INET6,& _addr, buf, INET6_ADDRSTRLEN)) return "::1"; // TODO: What to do about invalid ip? int p; - if ((p = prefix()) < 128) + if ((p = prefix()) < 128) { sprintf(buf + strlen(buf), "/%d", p); + } return buf; } bool address::parse_string(const std::string& str) { - char buf[INET6_ADDRSTRLEN], *b; + char buf[INET6_ADDRSTRLEN],* b; int sz, pfx; sz = 0; @@ -180,33 +201,38 @@ bool address::parse_string(const std::string& str) reset(); - const char *p = str.c_str(); + const char* p = str.c_str(); while (*p && isspace(*p)) p++; while (*p) { - if ((*p == '/') || isspace(*p)) + if ((*p == '/') || isspace(*p)) { break; + } - if ((*p != ':') && !isxdigit(*p)) + if ((*p != ':') && !isxdigit(*p)) { return false; + } - if (sz >= (INET6_ADDRSTRLEN - 1)) + if (sz >= (INET6_ADDRSTRLEN - 1)) { return false; + } - *b++ = *p++; +* b++ =* p++; sz++; } - *b = '\0'; +* b = '\0'; - if (inet_pton(AF_INET6, buf, &_addr) <= 0) + if (inet_pton(AF_INET6, buf,& _addr) <= 0) { return false; + } - while (*p && isspace(*p)) + while (*p && isspace(*p)) { p++; + } if (*p == '\0') { _mask.s6_addr32[0] = 0xffffffff; @@ -232,11 +258,11 @@ bool address::parse_string(const std::string& str) if (sz > 3) return false; - *b++ = *p++; +* b++ =* p++; sz++; } - *b = '\0'; +* b = '\0'; prefix(atoi(buf)); diff --git a/src/address.h b/src/address.h index 93e4fe0..dc2ad18 100644 --- a/src/address.h +++ b/src/address.h @@ -24,16 +24,12 @@ NDPPD_NS_BEGIN class iface; -class address -{ -private: - struct in6_addr _addr, _mask; - +class address { public: address(); address(const address& addr); address(const std::string& str); - address(const char *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); @@ -65,6 +61,8 @@ public: operator std::string() const; +private: + struct in6_addr _addr, _mask; }; NDPPD_NS_END diff --git a/src/conf.cc b/src/conf.cc index 0ede487..00cf3fa 100644 --- a/src/conf.cc +++ b/src/conf.cc @@ -34,12 +34,22 @@ conf::conf() : } -const std::string &conf::value() const +conf::operator int() const { - return _value; + return as_int(); } -bool conf::bool_value() const +conf::operator const std::string&() const +{ + return as_str(); +} + +conf::operator bool() const +{ + return as_bool(); +} + +bool conf::as_bool() const { if (!strcasecmp(_value.c_str(), "true") || !strcasecmp(_value.c_str(), "yes")) return true; @@ -47,31 +57,36 @@ bool conf::bool_value() const return false; } -int conf::int_value() const +const std::string& conf::as_str() const +{ + return _value; +} + +int conf::as_int() const { return atoi(_value.c_str()); } -void conf::value(const std::string &value) +bool conf::empty() const { - _value = value; + return _value == ""; } -ptr conf::load(const std::string &path) +ptr conf::load(const std::string& path) { try { std::ifstream ifs; ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); ifs.open(path.c_str(), std::ios::in); + ifs.exceptions(std::ifstream::badbit); std::string buf((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); - const char *c_buf = buf.c_str(); + const char* c_buf = buf.c_str(); ptr cf(new conf); if (cf->parse_block(&c_buf)) { - logger l(LOG_DEBUG); - cf->dump(l, 0); + cf->dump(LOG_DEBUG); return cf; } @@ -88,7 +103,7 @@ bool conf::is_block() const return _is_block; } -const char *conf::skip(const char *str, bool all) +const char* conf::skip(const char* str, bool all) { if (!all) { while (*str && (*str != '\n') && isspace(*str)) @@ -127,18 +142,18 @@ const char *conf::skip(const char *str, bool all) return str; } -bool conf::parse_block(const char **str) +bool conf::parse_block(const char** str) { - const char *p = *str; + const char* p = *str; _is_block = true; while (*p) { std::stringstream ss; - p = skip(p); + p = skip(p, true); - if (*p == '}') { + if ((*p == '}') || !*p) { *str = p; return true; } @@ -164,9 +179,9 @@ bool conf::parse_block(const char **str) return true; } -bool conf::parse(const char **str) +bool conf::parse(const char** str) { - const char *p = *str; + const char* p = *str; std::stringstream ss; p = skip(p, false); @@ -175,12 +190,14 @@ bool conf::parse(const char **str) return false; } else if ((*p == '\'') || (*p == '"')) { for (char e = *p++; *p && (*p != e); p++) - ss << *p; + ss <<* p; } else if (isalnum(*p)) { - while (*p && (isalnum(*p) || strchr(":/.", *p))) - ss << *p++; + while (*p && (isalnum(*p) || strchr(":/.",* p))) + ss <<* p++; } else { - return false; + _value = ""; + *str = p; + return true; } _value = ss.str(); @@ -203,13 +220,13 @@ bool conf::parse(const char **str) return true; } -void conf::dump() const +void conf::dump(int pri) const { - logger l(LOG_ERR); + logger l(pri); dump(l, 0); } -void conf::dump(logger &l, int level) const +void conf::dump(logger& l, int level) const { int i; @@ -238,23 +255,42 @@ void conf::dump(logger &l, int level) const l << logger::endl; } -ptr conf::operator[](const std::string& name) const +ptr conf::operator()(const std::string& name, int index) const { - std::multimap >::const_iterator it; - - if ((it = _map.find(name)) == _map.end()) - return ptr(); - else - return it->second; + return find(name, index); } -std::vector > conf::find(const std::string& name) const +ptr conf::find(const std::string& name, int index) const { - std::vector > vec; std::multimap >::const_iterator it; for (it = _map.find(name); it != _map.end(); it++) { + if (index-- <= 0) + return it->second; + } + + return ptr(); +} + +ptr conf::operator[](const std::string& name) const +{ + return find(name, 0); +} + +std::vector > conf::find_all(const std::string& name) const +{ + std::vector > vec; + + std::multimap >::const_iterator it; + + std::pair >::const_iterator, + std::multimap >::const_iterator> ret; + + ret = _map.equal_range(name); + + for (it = ret.first; it != ret.second; it++) { vec.push_back(it->second); } + return vec; } diff --git a/src/conf.h b/src/conf.h index 4e75d8c..3865169 100644 --- a/src/conf.h +++ b/src/conf.h @@ -25,8 +25,7 @@ NDPPD_NS_BEGIN -class conf -{ +class conf { public: private: @@ -36,33 +35,39 @@ private: std::multimap > _map; - void dump(logger &l, int level) const; + void dump(logger& l, int level) const; - static const char *skip(const char *str, bool all = true); + static const char* skip(const char* str, bool all = true); - bool parse_block(const char **str); + bool parse_block(const char* *str); - bool parse(const char **str); + bool parse(const char* *str); public: conf(); - const std::string &value() const; - - bool bool_value() const; - - int int_value() const; - - void value(const std::string &value); - - static ptr load(const std::string &path); + static ptr load(const std::string& path); bool is_block() const; - ptr operator[](const std::string &name) const; - std::vector > find(const std::string &name) const; + ptr operator[](const std::string& name) const; + ptr operator()(const std::string& name, int index = 0) const; - void dump() const; + operator const std::string&() const; + operator int() const; + operator bool() const; + + bool as_bool() const; + const std::string& as_str() const; + int as_int() const; + + bool empty() const; + + std::vector > find_all(const std::string& name) const; + + ptr find(const std::string& name, int index = 0) const; + + void dump(int pri = LOG_INFO) const; operator const std::string&(); diff --git a/src/iface.cc b/src/iface.cc index 905c07e..3fd949f 100644 --- a/src/iface.cc +++ b/src/iface.cc @@ -106,7 +106,7 @@ ptr iface::open_pfd(const std::string& name) return ptr(); } - if (bind(fd, (struct sockaddr *)&lladdr, sizeof(struct sockaddr_ll)) < 0) { + if (bind(fd, (struct sockaddr* )&lladdr, sizeof(struct sockaddr_ll)) < 0) { close(fd); logger::error() << "Failed to bind to interface '" << name << "'"; return ptr(); @@ -116,7 +116,7 @@ ptr iface::open_pfd(const std::string& name) int on = 1; - if (ioctl(fd, FIONBIO, (char *)&on) < 0) { + if (ioctl(fd, FIONBIO, (char* )&on) < 0) { close(fd); logger::error() << "Failed to switch to non-blocking on interface '" << name << "'"; return ptr(); @@ -131,17 +131,17 @@ ptr iface::open_pfd(const std::string& name) // 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. + // 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. + // 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. + // 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), @@ -149,10 +149,10 @@ ptr iface::open_pfd(const std::string& name) BPF_STMT(BPF_RET | BPF_K, 0) }; - fprog.filter = (struct sock_filter *)filter; + fprog.filter = (struct sock_filter* )filter; fprog.len = 8; - 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(); } @@ -190,7 +190,7 @@ ptr iface::open_ifd(const std::string& name) 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) { + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,& ifr, sizeof(ifr)) < 0) { close(fd); logger::error() << "Failed to bind to interface '" << name << "'"; return ptr(); @@ -202,25 +202,25 @@ ptr iface::open_ifd(const std::string& name) strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1); ifr.ifr_name[IFNAMSIZ - 1] = '\0'; - if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { + if (ioctl(fd, SIOCGIFHWADDR,& ifr) < 0) { close(fd); logger::error() << "Failed to detect link-layer address for interface '" << name << "'"; return ptr(); } - logger::debug() << "fd=" << fd << ", hwaddr=" << ether_ntoa((const struct ether_addr *)&ifr.ifr_hwaddr.sa_data);; + logger::debug() << "fd=" << fd << ", hwaddr=" << ether_ntoa((const struct ether_addr* )&ifr.ifr_hwaddr.sa_data);; // Set max hops. int hops = 255; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) < 0) { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,& hops, sizeof(hops)) < 0) { close(fd); logger::error() << "iface::open_ifd() failed IPV6_MULTICAST_HOPS"; return ptr(); } - if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof(hops)) < 0) { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,& hops, sizeof(hops)) < 0) { close(fd); logger::error() << "iface::open_ifd() failed IPV6_UNICAST_HOPS"; return ptr(); @@ -230,7 +230,7 @@ ptr iface::open_ifd(const std::string& name) int on = 1; - if (ioctl(fd, FIONBIO, (char *)&on) < 0) { + if (ioctl(fd, FIONBIO, (char* )&on) < 0) { close(fd); logger::error() << "Failed to switch to non-blocking on interface '" << name << "'"; return ptr(); @@ -240,9 +240,9 @@ ptr iface::open_ifd(const std::string& name) struct icmp6_filter filter; ICMP6_FILTER_SETBLOCKALL(&filter); - ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter); + ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT,& filter); - if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) < 0) { + if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER,& filter, sizeof(filter)) < 0) { logger::error() << "Failed to set filter"; return ptr(); } @@ -270,7 +270,7 @@ ptr iface::open_ifd(const std::string& name) return ifa; } -ssize_t iface::read(int fd, struct sockaddr *saddr, uint8_t *msg, size_t size) +ssize_t iface::read(int fd, struct sockaddr* saddr, uint8_t* msg, size_t size) { struct msghdr mhdr; struct iovec iov; @@ -286,10 +286,10 @@ ssize_t iface::read(int fd, struct sockaddr *saddr, uint8_t *msg, size_t size) memset(&mhdr, 0, sizeof(mhdr)); mhdr.msg_name = (caddr_t)saddr; mhdr.msg_namelen = sizeof(struct sockaddr); - mhdr.msg_iov = &iov; + mhdr.msg_iov =& iov; mhdr.msg_iovlen = 1; - if ((len = recvmsg(fd, &mhdr, 0)) < 0) + if ((len = recvmsg(fd,& mhdr, 0)) < 0) return -1; if (len < sizeof(struct icmp6_hdr)) @@ -300,7 +300,7 @@ ssize_t iface::read(int fd, struct sockaddr *saddr, uint8_t *msg, size_t size) return len; } -ssize_t iface::write(int fd, const address& daddr, const uint8_t *msg, size_t size) +ssize_t iface::write(int fd, const address& daddr, const uint8_t* msg, size_t size) { struct sockaddr_in6 daddr_tmp; struct msghdr mhdr; @@ -309,7 +309,7 @@ ssize_t iface::write(int fd, const address& daddr, const uint8_t *msg, size_t si 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)); + memcpy(&daddr_tmp.sin6_addr,& daddr.const_addr(), sizeof(struct in6_addr)); iov.iov_len = size; iov.iov_base = (caddr_t)msg; @@ -317,14 +317,14 @@ ssize_t iface::write(int fd, const address& daddr, const uint8_t *msg, size_t si memset(&mhdr, 0, sizeof(mhdr)); mhdr.msg_name = (caddr_t)&daddr_tmp; mhdr.msg_namelen = sizeof(sockaddr_in6); - mhdr.msg_iov = &iov; + mhdr.msg_iov =& iov; mhdr.msg_iovlen = 1; logger::debug() << "iface::write() daddr=" << daddr.to_string() << ", len=" << size; int len; - if ((len = sendmsg(fd, &mhdr, 0)) < 0) + if ((len = sendmsg(fd,& mhdr, 0)) < 0) return -1; return len; @@ -336,17 +336,17 @@ ssize_t iface::read_solicit(address& saddr, address& daddr, address& taddr) uint8_t msg[256]; ssize_t len; - if ((len = read(_pfd, (struct sockaddr *)&t_saddr, msg, sizeof(msg))) < 0) + 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; @@ -363,20 +363,20 @@ ssize_t iface::write_solicit(const address& taddr) 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; 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"); @@ -391,7 +391,7 @@ ssize_t iface::write_solicit(const address& taddr) logger::debug() << "iface::write_solicit() taddr=" << taddr.to_string() << ", daddr=" << daddr.to_string(); - 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) @@ -400,11 +400,11 @@ ssize_t iface::write_advert(const address& daddr, const address& taddr, bool rou 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; @@ -412,13 +412,13 @@ ssize_t iface::write_advert(const address& daddr, const address& taddr, bool rou 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); logger::debug() << "iface::write_advert() daddr=" << daddr.to_string() << ", taddr=" << taddr.to_string(); - return write(_ifd, daddr, (uint8_t *)buf, sizeof(struct nd_neighbor_advert) + + return write(_ifd, daddr, (uint8_t* )buf, sizeof(struct nd_neighbor_advert) + sizeof(struct nd_opt_hdr) + 6); } @@ -428,15 +428,15 @@ ssize_t iface::read_advert(address& saddr, address& taddr) uint8_t msg[256]; ssize_t len; - if ((len = read(_ifd, (struct sockaddr *)&t_saddr, msg, sizeof(msg))) < 0) + if ((len = read(_ifd, (struct sockaddr* )&t_saddr, msg, sizeof(msg))) < 0) return -1; saddr = t_saddr.sin6_addr; - if (((struct icmp6_hdr *)msg)->icmp6_type != ND_NEIGHBOR_ADVERT) + 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; logger::debug() << "iface::read_advert() saddr=" << saddr.to_string() << ", taddr=" << taddr.to_string() << ", len=" << len; @@ -445,7 +445,7 @@ ssize_t iface::read_advert(address& saddr, address& taddr) void iface::fixup_pollfds() { - _pollfds.resize(_map.size() * 2); + _pollfds.resize(_map.size()* 2); int i = 0; @@ -488,7 +488,7 @@ int iface::poll_all() return 0; } - assert(_pollfds.size() == _map.size() * 2); + assert(_pollfds.size() == _map.size()* 2); int len; @@ -506,13 +506,15 @@ int iface::poll_all() f_it != _pollfds.end(); f_it++) { assert(i_it != _map.end()); - if (i && !(i % 2)) + if (i && !(i % 2)) { i_it++; + } bool is_pfd = i++ % 2; - if (!(f_it->revents & POLLIN)) + if (!(f_it->revents& POLLIN)) { continue; + } ptr ifa = i_it->second; @@ -524,8 +526,9 @@ int iface::poll_all() continue; } - if (!saddr.is_unicast() || !daddr.is_multicast()) + if (!saddr.is_unicast() || !daddr.is_multicast()) { continue; + } ifa->_pr->handle_solicit(saddr, daddr, taddr); } else { @@ -536,7 +539,8 @@ int iface::poll_all() for (std::list >::iterator s_it = ifa->_sessions.begin(); s_it != ifa->_sessions.end(); s_it++) { - const ptr sess = *s_it; + const ptr sess =* s_it; + if ((sess->taddr() == taddr) && (sess->status() == session::WAITING)) { sess->handle_advert(); break; @@ -558,10 +562,10 @@ int iface::allmulti(int state) 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) return old_state; @@ -571,7 +575,7 @@ int iface::allmulti(int state) 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 a3b870b..0bcdf7b 100644 --- a/src/iface.h +++ b/src/iface.h @@ -30,8 +30,7 @@ NDPPD_NS_BEGIN class session; class proxy; -class iface -{ +class iface { private: // Weak pointer so this object can reference itself. weak_ptr _ptr; @@ -85,9 +84,9 @@ public: 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); diff --git a/src/logger.cc b/src/logger.cc index 87d3ab0..72fbf38 100644 --- a/src/logger.cc +++ b/src/logger.cc @@ -26,7 +26,7 @@ NDPPD_NS_BEGIN -/*const char *log::_level_str[] = +/*const char* log::_level_str[] = { "fatal", "alert", @@ -59,7 +59,7 @@ logger::logger(int pri) : { } -logger::logger(const logger &l) : +logger::logger(const logger& l) : _pri(l._pri) //, _ss(l._ss.str()) { _ss << l._ss.rdbuf(); @@ -100,34 +100,34 @@ logger logger::debug() return logger(LOG_DEBUG); } -logger &logger::operator<<(const std::string &str) +logger& logger::operator<<(const std::string& str) { _ss << str; - return *this; + return* this; } -logger &logger::operator<<(int n) +logger& logger::operator<<(int n) { _ss << n; - return *this; + return* this; } -logger &logger::operator<<(logger &(*pf)(logger &)) +logger& logger::operator<<(logger& (*pf)(logger& )) { pf(*this); - return *this; + return* this; } -logger &logger::endl(logger &__l) +logger& logger::endl(logger& __l) { __l.flush(); return __l; } -logger &logger::force_log(bool b) +logger& logger::force_log(bool b) { _force_log = b; - return *this; + return* this; } void logger::flush() @@ -175,9 +175,9 @@ void logger::max_pri(int pri) _max_pri = pri; } -bool logger::verbosity(const std::string &name) +bool logger::verbosity(const std::string& name) { - const char *c_name = name.c_str(); + const char* c_name = name.c_str(); if (!*c_name) { return false; diff --git a/src/logger.h b/src/logger.h index 638aa2f..7f12349 100644 --- a/src/logger.h +++ b/src/logger.h @@ -30,26 +30,17 @@ # define LOG_DEBUG 7 /* debug-level messages */ #endif - -/*#define DBG(...) logger(logger::DEBUG) << logger::F(__VA_ARGS__) << logger::endl; -#define ERR(...) logger(logger::ERROR) << logger::F(__VA_ARGS__) << logger::endl; -#define WRN(...) logger(logger::WARNING) << logger::F(__VA_ARGS__) << logger::endl; -#define NFO(...) logger(logger::INFO) << logger::F(__VA_ARGS__) << logger::endl;*/ - -/* LOG_ERR; LOG_WARNING; LOG_CRIT; LOG_INFO; LOG_NOTICE */ - NDPPD_NS_BEGIN -class logger -{ +class logger { public: logger(int pri = LOG_INFO); - logger(const logger &l); + logger(const logger& l); ~logger(); - static std::string format(const std::string &fmt, ...); + static std::string format(const std::string& fmt, ...); static void syslog(bool enable); static bool syslog(); @@ -58,15 +49,15 @@ public: void flush(); - static bool verbosity(const std::string &name); + static bool verbosity(const std::string& name); - logger& operator<<(const std::string &str); - logger& operator<<(logger &(*pf)(logger &)); + logger& operator<<(const std::string& str); + logger& operator<<(logger& (*pf)(logger& )); logger& operator<<(int n); logger& force_log(bool b = true); - static logger& endl(logger &__l); + static logger& endl(logger& __l); // Shortcuts. @@ -83,7 +74,7 @@ private: bool _force_log; struct pri_name { - const char *name; + const char* name; int pri; }; diff --git a/src/ndppd.cc b/src/ndppd.cc index e21e9f4..3171f93 100644 --- a/src/ndppd.cc +++ b/src/ndppd.cc @@ -27,6 +27,7 @@ #include #include "ndppd.h" +#include "route.h" using namespace ndppd; @@ -52,7 +53,7 @@ int daemonize() return 0; } -bool configure(const std::string &path) +bool configure(const std::string& path) { ptr cf; @@ -61,61 +62,65 @@ bool configure(const std::string &path) std::vector >::const_iterator p_it; - std::vector > proxies(cf->find("proxy")); + std::vector > proxies(cf->find_all("proxy")); for (p_it = proxies.begin(); p_it != proxies.end(); p_it++) { - ptr pr_cf = *p_it, x_cf; + ptr pr_cf =* p_it, x_cf; - if (pr_cf->value() == "") { + if (pr_cf->empty()) { logger::error() << "'proxy' section is missing interface name"; return false; } - ptr pr = proxy::open(pr_cf->value()); + ptr pr = proxy::open(*pr_cf); if (!pr) { - logger::error() << "Configuration failed for proxy '" << pr_cf->value() << "'"; + logger::error() << "Configuration failed for proxy '" << (const std::string& )*pr_cf << "'"; return false; } - if (!(x_cf = (*pr_cf)["router"])) + if (!(x_cf = pr_cf->find("router"))) pr->router(true); else - pr->router(x_cf->bool_value()); + pr->router(*x_cf); - if (!(x_cf = (*pr_cf)["ttl"])) + if (!(x_cf = pr_cf->find("ttl"))) pr->ttl(30000); else - pr->ttl(x_cf->int_value()); + pr->ttl(*x_cf); - if (!(x_cf = (*pr_cf)["timeout"])) + if (!(x_cf = pr_cf->find("timeout"))) pr->timeout(500); else - pr->timeout(x_cf->int_value()); + pr->timeout(*x_cf); std::vector >::const_iterator r_it; - std::vector > rules(pr_cf->find("rule")); + std::vector > rules(pr_cf->find_all("rule")); for (r_it = rules.begin(); r_it != rules.end(); r_it++) { - ptr ru_cf = *r_it; + ptr ru_cf =* r_it; - if (ru_cf->value() == "") { + if (ru_cf->empty()) { logger::error() << "'rule' is missing an IPv6 address/net"; return false; } - address addr(ru_cf->value()); + address addr(*ru_cf); - if (!(x_cf = (*ru_cf)["iface"])) { + if (x_cf = ru_cf->find("iface")) { + if ((const std::string& )*x_cf == "") { + logger::error() << "'iface' expected an interface name"; + } else { + pr->add_rule(addr, iface::open_ifd(*x_cf)); + } + } else if (ru_cf->find("auto")) { + pr->add_rule(addr, true); + } else { if (addr.prefix() <= 120) { logger::warning() << "Static rule prefix /" << addr.prefix() << " <= 120 - is this what you want?"; - pr->add_rule(addr); } - } else if (x_cf->value() == "") { - logger::error() << "'iface' expected an interface name or 'auto' as argument"; - } else { - pr->add_rule(addr, iface::open_ifd(x_cf->value())); + pr->add_rule(addr, false); } } } @@ -123,7 +128,7 @@ bool configure(const std::string &path) return true; } -int main(int argc, char *argv[], char *env[]) +int main(int argc, char* argv[], char* env[]) { std::string config_path("/etc/ndppd.conf"); std::string pidfile; @@ -141,7 +146,7 @@ int main(int argc, char *argv[], char *env[]) { 0, 0, 0, 0} }; - c = getopt_long(argc, argv, "c:dp:v::", long_options, &opt); + c = getopt_long(argc, argv, "c:dp:v::", long_options,& opt); if (c == -1) break; @@ -195,6 +200,8 @@ int main(int argc, char *argv[], char *env[]) if (!configure(config_path)) return -1; + route::load("/proc/net/ipv6_route"); + // Time stuff. struct timeval t1, t2; @@ -206,7 +213,7 @@ int main(int argc, char *argv[], char *env[]) gettimeofday(&t2, 0); elapsed_time = - ((t2.tv_sec - t1.tv_sec) * 1000) + + ((t2.tv_sec - t1.tv_sec)* 1000) + ((t2.tv_usec - t1.tv_usec) / 1000); t1.tv_sec = t2.tv_sec; diff --git a/src/proxy.cc b/src/proxy.cc index 34e06f4..a3f6f71 100644 --- a/src/proxy.cc +++ b/src/proxy.cc @@ -20,6 +20,7 @@ #include "ndppd.h" #include "proxy.h" +#include "route.h" #include "iface.h" #include "rule.h" #include "session.h" @@ -48,8 +49,9 @@ ptr proxy::open(const std::string& ifname) { ptr ifa = iface::open_pfd(ifname); - if (!ifa) + if (!ifa) { return ptr(); + } return create(ifa); } @@ -57,8 +59,9 @@ ptr proxy::open(const std::string& ifname) void proxy::handle_solicit(const address& saddr, const address& daddr, const address& taddr) { - logger::debug() << "proxy::handle_solicit() saddr=" << saddr.to_string() - << ", taddr=" << taddr.to_string(); + logger::debug() + << "proxy::handle_solicit() saddr=" << saddr.to_string() + << ", taddr=" << taddr.to_string(); // Let's check this proxy's list of sessions to see if we can // find one with the same target address. @@ -86,24 +89,31 @@ void proxy::handle_solicit(const address& saddr, const address& daddr, ptr se; for (std::list >::iterator it = _rules.begin(); - it != _rules.end(); it++) { - ptr ru = *it; + it != _rules.end(); it++) { + ptr ru =* it; - logger::debug() << "checking " << ru->addr().to_string() << " against " << taddr; + logger::debug() << "checking " << ru->addr() << " against " << taddr; if (ru->addr() == taddr) { - if (!se) + if (!se) { se = session::create(_ptr, 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 (ru->is_auto()) { + ptr ifa = route::find_and_open(taddr); + // TODO: Check if it's a good interface. + if (ifa) { + se->add_iface(ifa); + continue; + } + } else 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; + } else { + se->add_iface((*it)->ifa()); + } } } @@ -120,9 +130,9 @@ ptr proxy::add_rule(const address& addr, const ptr& ifa) return ru; } -ptr proxy::add_rule(const address& addr) +ptr proxy::add_rule(const address& addr, bool aut) { - ptr ru(rule::create(_ptr, addr)); + ptr ru(rule::create(_ptr, addr, aut)); _rules.push_back(ru); return ru; } diff --git a/src/proxy.h b/src/proxy.h index 18dffd5..1611a09 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -28,8 +28,7 @@ NDPPD_NS_BEGIN class iface; class rule; -class proxy -{ +class proxy { private: weak_ptr _ptr; @@ -57,7 +56,7 @@ public: ptr add_rule(const address& addr, const ptr& ifa); - ptr add_rule(const address& addr); + ptr add_rule(const address& addr, bool aut = false); const ptr& ifa() const; diff --git a/src/ptr.h b/src/ptr.h new file mode 100644 index 0000000..f860621 --- /dev/null +++ b/src/ptr.h @@ -0,0 +1,244 @@ +// 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 . +#pragma once + +#include + +#include "ndppd.h" + +NDPPD_NS_BEGIN + +class invalid_pointer : public std::exception { +public: + invalid_pointer() throw() {}; +}; + +template +class weak_ptr; + +// 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 { + template + friend class ptr; + + struct ptr_ref { + T* ptr; + int wc, sc; + }; + +protected: + ptr_ref* _ref; + + bool _weak; + + void acquire(ptr_ref* ref) + { + if (_ref) + release(); + + if (_ref = ref) { + if (_weak) + _ref->wc++; + else + _ref->sc++; + } + } + + void acquire(void* ptr) + { + _ref = new ptr_ref(); + _ref->ptr = (T* )ptr; + _ref->wc = !!_weak; + _ref->sc = !_weak; + } + + void release() + { + 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) + delete _ref; + + _ref = 0; + } + + template + void acquire(const ptr& ptr) + { + T* t = static_cast(0); + acquire(ptr._ref); + } + +public: + ptr(bool weak = false) : + _weak(weak), _ref(0) + { + } + + ptr(T* p, bool weak = false) : + _weak(weak), _ref(0) + { + acquire(p); + } + + ptr(const ptr& p, bool weak = false) : + _weak(weak), _ref(0) + { + acquire(p._ref); + } + + ptr(const weak_ptr& p, bool weak = false) : + _weak(weak), _ref(0) + { + acquire(p._ref); + } + + template + ptr(const ptr& p, bool weak = false) : + _weak(weak), _ref(0) + { + T* x = (U*)0; + acquire(p._ref); + } + + template + ptr(const weak_ptr& p, bool weak = false) : + _weak(weak), _ref(0) + { + T* x = (U*)0; + acquire(p._ref); + } + + ~ptr() + { + release(); + } + + void operator=(T* p) + { + acquire(p); + } + + ptr& operator=(const ptr& p) + { + acquire(p); + return* this; + } + + 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 || !_ref->ptr; + } + + T& operator*() const + { + return* get_pointer(); + } + + T* operator->() const + { + return get_pointer(); + } + + operator T*() const + { + return get_pointer(); + } + + operator bool() const + { + return !is_null(); + } + + void reset(T* p = 0) + { + acquire(p); + } + + T* get_pointer() const + { + if (!_ref || !_ref->ptr) + throw new invalid_pointer; + + return static_cast(_ref->ptr); + } +}; + +template +class weak_ptr : public ptr { +public: + weak_ptr() : + ptr(true) + { + } + + weak_ptr(T* p) : + ptr(p, true) + { + } + + weak_ptr(const ptr& p) : + ptr(p, true) + { + } + + weak_ptr(const weak_ptr& p) : + ptr(p, true) + { + } + + template + weak_ptr(const ptr& p) : + ptr(p, true) + { + } + + template + weak_ptr(const weak_ptr& p) : + ptr(p, true) + { + } +}; + +NDPPD_NS_END + + diff --git a/src/route.cc b/src/route.cc new file mode 100644 index 0000000..b1fc3a6 --- /dev/null +++ b/src/route.cc @@ -0,0 +1,165 @@ +// 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 . +#include +#include +#include + +#include "ndppd.h" +#include "route.h" + +NDPPD_NS_BEGIN + +std::list > route::_routes; + +route::route(const address& addr, const std::string& ifname) : + _addr(addr), _ifname(ifname) +{ +} + +size_t route::hexdec(const char* str, unsigned char* buf, size_t size) +{ + for (size_t i = 0; ; i++) { + if (i >= size) + return i; + + char c1 = tolower(str[i* 2]), c2 = tolower(str[i* 2 + 1]); + + if (!isxdigit(c1) || !isxdigit(c2)) + return i; + + if ((c1 >= '0') && (c1 <= '9')) + buf[i] = (c1 - '0') << 4; + else + buf[i] = ((c1 - 'a') + 10) << 4; + + if ((c2 >= '0') && (c2 <= '9')) + buf[i] |= c2 - '0'; + else + buf[i] |= (c2 - 'a') + 10; + } +} + +std::string route::token(const char* str) +{ + while (*str && isspace(*str)) { + str++; + } + + if (!*str) { + return ""; + } + + std::stringstream ss; + + while (*str && !isspace(*str)) { + ss <<* str++; + } + + return ss.str(); +} + +void route::load(const std::string& path) +{ + _routes.clear(); + + try { + std::ifstream ifs; + ifs.exceptions(std::ifstream::badbit | std::ifstream::failbit); + ifs.open(path.c_str(), std::ios::in); + ifs.exceptions(std::ifstream::badbit); + + while (!ifs.eof()) { + char buf[1024]; + ifs.getline(buf, sizeof(buf)); + + if (ifs.gcount() < 149) + continue; + + address addr; + + unsigned char pfx; + + if (hexdec(buf, (unsigned char* )&addr.addr(), 16) != 16) { + // TODO: Warn here? + continue; + } + + if (hexdec(buf + 33,& pfx, 1) != 1) { + // TODO: Warn here? + continue; + } + + addr.prefix((int)pfx); + + route::create(addr, token(buf + 141)); + } + } catch (std::ifstream::failure e) { + logger::warning() << "Failed to parse IPv6 routing data from '" << path << "'"; + logger::error() << e.what(); + } +} + +ptr route::create(const address& addr, const std::string& ifname) +{ + ptr rt(new route(addr, ifname)); + logger::debug() << "route::create() addr=" << addr << ", ifname=" << ifname; + _routes.push_back(rt); + return rt; +} + +ptr route::find(const address& addr) +{ + for (std::list >::iterator it = _routes.begin(); + it != _routes.end(); it++) { + if ((*it)->addr() == addr) + return *it; + } + + return ptr(); +} + +ptr route::find_and_open(const address& addr) +{ + ptr rt; + + if (rt = find(addr)) { + return rt->ifa(); + } + + return ptr(); +} + +const std::string& route::ifname() const +{ + return _ifname; +} + +ptr route::ifa() +{ + if (!_ifa) { + return _ifa = iface::open_ifd(_ifname); + } + + return ptr(); +} + +const address& route::addr() const +{ + return _addr; +} + +NDPPD_NS_END + diff --git a/src/route.h b/src/route.h new file mode 100644 index 0000000..555fb1b --- /dev/null +++ b/src/route.h @@ -0,0 +1,59 @@ +// 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 . +#pragma once + +#include +#include +#include + +#include "ndppd.h" + +NDPPD_NS_BEGIN + +class route { +public: + static ptr create(const address& addr, const std::string& ifname); + + static ptr find(const address& addr); + + static ptr find_and_open(const address& addr); + + static void load(const std::string& path); + + const std::string& ifname() const; + + const address& addr() const; + + ptr ifa(); + +private: + address _addr; + + std::string _ifname; + + ptr _ifa; + + static size_t hexdec(const char* str, unsigned char* buf, size_t size); + + static std::string token(const char* str); + + static std::list > _routes; + + route(const address& addr, const std::string& ifname); + +}; + +NDPPD_NS_END diff --git a/src/rule.cc b/src/rule.cc index 76adabb..9e72480 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -35,20 +35,24 @@ ptr rule::create(const ptr& pr, const address& addr, const ptr_pr = pr; ru->_ifa = ifa; ru->_addr = addr; + ru->_aut = false; logger::debug() << "rule::create() if=" << pr->ifa()->name() << ", addr=" << addr; return ru; } -ptr rule::create(const ptr& pr, const address& addr) +ptr rule::create(const ptr& pr, const address& addr, bool aut) { ptr ru(new rule()); ru->_ptr = ru; ru->_pr = pr; ru->_addr = addr; + ru->_aut = aut; - logger::debug() << "rule::create() if=" << pr->ifa()->name().c_str() << ", addr=" << addr; + logger::debug() + << "rule::create() if=" << pr->ifa()->name().c_str() << ", addr=" << addr + << ", auto=" << (aut ? "yes" : "no"); return ru; } @@ -63,9 +67,9 @@ ptr rule::ifa() const return _ifa; } -bool rule::is_static() const +bool rule::is_auto() const { - return !!_ifa; + return _aut; } bool rule::check(const address& addr) const diff --git a/src/rule.h b/src/rule.h index e35bf02..ad721ce 100644 --- a/src/rule.h +++ b/src/rule.h @@ -28,8 +28,20 @@ NDPPD_NS_BEGIN class iface; class proxy; -class rule -{ +class rule { +public: + static ptr create(const ptr& pr, const address& addr, const ptr& ifa); + + static ptr create(const ptr& pr, const address& addr, bool stc = true); + + const address& addr() const; + + ptr ifa() const; + + bool is_auto() const; + + bool check(const address& addr) const; + private: weak_ptr _ptr; @@ -39,21 +51,9 @@ private: address _addr; + bool _aut; + rule(); - -public: - static ptr create(const ptr& pr, const address& addr, const ptr& ifa); - - static ptr create(const ptr& pr, const address& addr); - - const address& addr() const; - - ptr ifa() const; - - bool is_static() const; - - bool check(const address& addr) const; - }; NDPPD_NS_END diff --git a/src/session.cc b/src/session.cc index 0618152..15774de 100644 --- a/src/session.cc +++ b/src/session.cc @@ -79,8 +79,8 @@ ptr session::create(const ptr& pr, const address& saddr, _sessions.push_back(se); logger::debug() - << "session::create() pr=" << logger::format("%x", (proxy *)pr) << ", saddr=" << saddr - << ", daddr=" << daddr << ", taddr=" << taddr << " =" << logger::format("%x", (session *)se); + << "session::create() pr=" << logger::format("%x", (proxy* )pr) << ", saddr=" << saddr + << ", daddr=" << daddr << ", taddr=" << taddr << " =" << logger::format("%x", (session* )se); return se; } diff --git a/src/session.h b/src/session.h index 8db7e79..1b1c5ab 100644 --- a/src/session.h +++ b/src/session.h @@ -24,8 +24,7 @@ NDPPD_NS_BEGIN class proxy; class iface; -class session -{ +class session { private: weak_ptr _ptr; @@ -80,8 +79,6 @@ public: void send_solicit(); void refesh(); - - }; NDPPD_NS_END