Several large changes for the upcoming 0.2.2 version
- Bugfixes. - New 'auto' configuration to be used in a 'rule' section. When using this option, the routing table /proc/net/ipv6_route will be used to auto-detect which interface to use when forwarding solicitation messages. - New 'route' class to resolve which interface to query when using 'auto' configuration. - Cleaned up the code some more.
This commit is contained in:
parent
ab0ebe09ff
commit
6723f2f4b6
2
Makefile
2
Makefile
@ -15,7 +15,7 @@ SBINDIR ?= ${DESTDIR}${PREFIX}/sbin
|
|||||||
LIBS =
|
LIBS =
|
||||||
|
|
||||||
OBJS = src/logger.o src/ndppd.o src/iface.o src/proxy.o src/address.o \
|
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
|
all: ndppd ndppd.1.gz ndppd.conf.5.gz
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ address::address(const std::string& str)
|
|||||||
parse_string(str);
|
parse_string(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
address::address(const char *str)
|
address::address(const char* str)
|
||||||
{
|
{
|
||||||
parse_string(str);
|
parse_string(str);
|
||||||
}
|
}
|
||||||
@ -125,13 +125,16 @@ void address::reset()
|
|||||||
|
|
||||||
int address::prefix() const
|
int address::prefix() const
|
||||||
{
|
{
|
||||||
if (!_mask.s6_addr[0])
|
if (!_mask.s6_addr[0]) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (int p = 0; p < 128; p++) {
|
for (int p = 0; p < 128; p++) {
|
||||||
int byi = p / 8, bii = 7 - (p % 8);
|
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 p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 128;
|
return 128;
|
||||||
@ -139,40 +142,58 @@ int address::prefix() const
|
|||||||
|
|
||||||
void address::prefix(int pf)
|
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;
|
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;
|
if (pf <= 0) {
|
||||||
_mask.s6_addr32[1] = 0;
|
return;
|
||||||
_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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
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))
|
if (!inet_ntop(AF_INET6,& _addr, buf, INET6_ADDRSTRLEN))
|
||||||
return "::1";
|
return "::1";
|
||||||
|
|
||||||
// TODO: What to do about invalid ip?
|
// TODO: What to do about invalid ip?
|
||||||
|
|
||||||
int p;
|
int p;
|
||||||
|
|
||||||
if ((p = prefix()) < 128)
|
if ((p = prefix()) < 128) {
|
||||||
sprintf(buf + strlen(buf), "/%d", p);
|
sprintf(buf + strlen(buf), "/%d", p);
|
||||||
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool address::parse_string(const std::string& str)
|
bool address::parse_string(const std::string& str)
|
||||||
{
|
{
|
||||||
char buf[INET6_ADDRSTRLEN], *b;
|
char buf[INET6_ADDRSTRLEN],* b;
|
||||||
int sz, pfx;
|
int sz, pfx;
|
||||||
|
|
||||||
sz = 0;
|
sz = 0;
|
||||||
@ -180,33 +201,38 @@ bool address::parse_string(const std::string& str)
|
|||||||
|
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
const char *p = str.c_str();
|
const char* p = str.c_str();
|
||||||
|
|
||||||
while (*p && isspace(*p))
|
while (*p && isspace(*p))
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
while (*p) {
|
while (*p) {
|
||||||
if ((*p == '/') || isspace(*p))
|
if ((*p == '/') || isspace(*p)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ((*p != ':') && !isxdigit(*p))
|
if ((*p != ':') && !isxdigit(*p)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (sz >= (INET6_ADDRSTRLEN - 1))
|
if (sz >= (INET6_ADDRSTRLEN - 1)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
*b++ = *p++;
|
* b++ =* p++;
|
||||||
|
|
||||||
sz++;
|
sz++;
|
||||||
}
|
}
|
||||||
|
|
||||||
*b = '\0';
|
* b = '\0';
|
||||||
|
|
||||||
if (inet_pton(AF_INET6, buf, &_addr) <= 0)
|
if (inet_pton(AF_INET6, buf,& _addr) <= 0) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
while (*p && isspace(*p))
|
while (*p && isspace(*p)) {
|
||||||
p++;
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
if (*p == '\0') {
|
if (*p == '\0') {
|
||||||
_mask.s6_addr32[0] = 0xffffffff;
|
_mask.s6_addr32[0] = 0xffffffff;
|
||||||
@ -232,11 +258,11 @@ bool address::parse_string(const std::string& str)
|
|||||||
if (sz > 3)
|
if (sz > 3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*b++ = *p++;
|
* b++ =* p++;
|
||||||
sz++;
|
sz++;
|
||||||
}
|
}
|
||||||
|
|
||||||
*b = '\0';
|
* b = '\0';
|
||||||
|
|
||||||
prefix(atoi(buf));
|
prefix(atoi(buf));
|
||||||
|
|
||||||
|
@ -24,16 +24,12 @@ NDPPD_NS_BEGIN
|
|||||||
|
|
||||||
class iface;
|
class iface;
|
||||||
|
|
||||||
class address
|
class address {
|
||||||
{
|
|
||||||
private:
|
|
||||||
struct in6_addr _addr, _mask;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
address();
|
address();
|
||||||
address(const address& addr);
|
address(const address& addr);
|
||||||
address(const std::string& str);
|
address(const std::string& str);
|
||||||
address(const char *str);
|
address(const char* str);
|
||||||
address(const in6_addr& addr);
|
address(const in6_addr& addr);
|
||||||
address(const in6_addr& addr, const in6_addr& mask);
|
address(const in6_addr& addr, const in6_addr& mask);
|
||||||
address(const in6_addr& addr, int prefix);
|
address(const in6_addr& addr, int prefix);
|
||||||
@ -65,6 +61,8 @@ public:
|
|||||||
|
|
||||||
operator std::string() const;
|
operator std::string() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct in6_addr _addr, _mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
NDPPD_NS_END
|
NDPPD_NS_END
|
||||||
|
102
src/conf.cc
102
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"))
|
if (!strcasecmp(_value.c_str(), "true") || !strcasecmp(_value.c_str(), "yes"))
|
||||||
return true;
|
return true;
|
||||||
@ -47,31 +57,36 @@ bool conf::bool_value() const
|
|||||||
return false;
|
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());
|
return atoi(_value.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void conf::value(const std::string &value)
|
bool conf::empty() const
|
||||||
{
|
{
|
||||||
_value = value;
|
return _value == "";
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<conf> conf::load(const std::string &path)
|
ptr<conf> conf::load(const std::string& path)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
std::ifstream ifs;
|
std::ifstream ifs;
|
||||||
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||||
ifs.open(path.c_str(), std::ios::in);
|
ifs.open(path.c_str(), std::ios::in);
|
||||||
|
ifs.exceptions(std::ifstream::badbit);
|
||||||
std::string buf((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
|
std::string buf((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
|
||||||
|
|
||||||
const char *c_buf = buf.c_str();
|
const char* c_buf = buf.c_str();
|
||||||
|
|
||||||
ptr<conf> cf(new conf);
|
ptr<conf> cf(new conf);
|
||||||
|
|
||||||
if (cf->parse_block(&c_buf)) {
|
if (cf->parse_block(&c_buf)) {
|
||||||
logger l(LOG_DEBUG);
|
cf->dump(LOG_DEBUG);
|
||||||
cf->dump(l, 0);
|
|
||||||
return cf;
|
return cf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +103,7 @@ bool conf::is_block() const
|
|||||||
return _is_block;
|
return _is_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *conf::skip(const char *str, bool all)
|
const char* conf::skip(const char* str, bool all)
|
||||||
{
|
{
|
||||||
if (!all) {
|
if (!all) {
|
||||||
while (*str && (*str != '\n') && isspace(*str))
|
while (*str && (*str != '\n') && isspace(*str))
|
||||||
@ -127,18 +142,18 @@ const char *conf::skip(const char *str, bool all)
|
|||||||
return str;
|
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;
|
_is_block = true;
|
||||||
|
|
||||||
while (*p) {
|
while (*p) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
p = skip(p);
|
p = skip(p, true);
|
||||||
|
|
||||||
if (*p == '}') {
|
if ((*p == '}') || !*p) {
|
||||||
*str = p;
|
*str = p;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -164,9 +179,9 @@ bool conf::parse_block(const char **str)
|
|||||||
return true;
|
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;
|
std::stringstream ss;
|
||||||
|
|
||||||
p = skip(p, false);
|
p = skip(p, false);
|
||||||
@ -175,12 +190,14 @@ bool conf::parse(const char **str)
|
|||||||
return false;
|
return false;
|
||||||
} else if ((*p == '\'') || (*p == '"')) {
|
} else if ((*p == '\'') || (*p == '"')) {
|
||||||
for (char e = *p++; *p && (*p != e); p++)
|
for (char e = *p++; *p && (*p != e); p++)
|
||||||
ss << *p;
|
ss <<* p;
|
||||||
} else if (isalnum(*p)) {
|
} else if (isalnum(*p)) {
|
||||||
while (*p && (isalnum(*p) || strchr(":/.", *p)))
|
while (*p && (isalnum(*p) || strchr(":/.",* p)))
|
||||||
ss << *p++;
|
ss <<* p++;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
_value = "";
|
||||||
|
*str = p;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_value = ss.str();
|
_value = ss.str();
|
||||||
@ -203,13 +220,13 @@ bool conf::parse(const char **str)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void conf::dump() const
|
void conf::dump(int pri) const
|
||||||
{
|
{
|
||||||
logger l(LOG_ERR);
|
logger l(pri);
|
||||||
dump(l, 0);
|
dump(l, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void conf::dump(logger &l, int level) const
|
void conf::dump(logger& l, int level) const
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -238,23 +255,42 @@ void conf::dump(logger &l, int level) const
|
|||||||
l << logger::endl;
|
l << logger::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<conf> conf::operator[](const std::string& name) const
|
ptr<conf> conf::operator()(const std::string& name, int index) const
|
||||||
{
|
{
|
||||||
std::multimap<std::string, ptr<conf> >::const_iterator it;
|
return find(name, index);
|
||||||
|
|
||||||
if ((it = _map.find(name)) == _map.end())
|
|
||||||
return ptr<conf>();
|
|
||||||
else
|
|
||||||
return it->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ptr<conf> > conf::find(const std::string& name) const
|
ptr<conf> conf::find(const std::string& name, int index) const
|
||||||
{
|
{
|
||||||
std::vector<ptr<conf> > vec;
|
|
||||||
std::multimap<std::string, ptr<conf> >::const_iterator it;
|
std::multimap<std::string, ptr<conf> >::const_iterator it;
|
||||||
for (it = _map.find(name); it != _map.end(); it++) {
|
for (it = _map.find(name); it != _map.end(); it++) {
|
||||||
|
if (index-- <= 0)
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr<conf>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<conf> conf::operator[](const std::string& name) const
|
||||||
|
{
|
||||||
|
return find(name, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ptr<conf> > conf::find_all(const std::string& name) const
|
||||||
|
{
|
||||||
|
std::vector<ptr<conf> > vec;
|
||||||
|
|
||||||
|
std::multimap<std::string, ptr<conf> >::const_iterator it;
|
||||||
|
|
||||||
|
std::pair<std::multimap<std::string, ptr<conf> >::const_iterator,
|
||||||
|
std::multimap<std::string, ptr<conf> >::const_iterator> ret;
|
||||||
|
|
||||||
|
ret = _map.equal_range(name);
|
||||||
|
|
||||||
|
for (it = ret.first; it != ret.second; it++) {
|
||||||
vec.push_back(it->second);
|
vec.push_back(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
41
src/conf.h
41
src/conf.h
@ -25,8 +25,7 @@
|
|||||||
|
|
||||||
NDPPD_NS_BEGIN
|
NDPPD_NS_BEGIN
|
||||||
|
|
||||||
class conf
|
class conf {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -36,33 +35,39 @@ private:
|
|||||||
|
|
||||||
std::multimap<std::string, ptr<conf> > _map;
|
std::multimap<std::string, ptr<conf> > _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:
|
public:
|
||||||
conf();
|
conf();
|
||||||
|
|
||||||
const std::string &value() const;
|
static ptr<conf> load(const std::string& path);
|
||||||
|
|
||||||
bool bool_value() const;
|
|
||||||
|
|
||||||
int int_value() const;
|
|
||||||
|
|
||||||
void value(const std::string &value);
|
|
||||||
|
|
||||||
static ptr<conf> load(const std::string &path);
|
|
||||||
|
|
||||||
bool is_block() const;
|
bool is_block() const;
|
||||||
|
|
||||||
ptr<conf> operator[](const std::string &name) const;
|
ptr<conf> operator[](const std::string& name) const;
|
||||||
std::vector<ptr<conf> > find(const std::string &name) const;
|
ptr<conf> 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<ptr<conf> > find_all(const std::string& name) const;
|
||||||
|
|
||||||
|
ptr<conf> find(const std::string& name, int index = 0) const;
|
||||||
|
|
||||||
|
void dump(int pri = LOG_INFO) const;
|
||||||
|
|
||||||
operator const std::string&();
|
operator const std::string&();
|
||||||
|
|
||||||
|
114
src/iface.cc
114
src/iface.cc
@ -106,7 +106,7 @@ ptr<iface> iface::open_pfd(const std::string& name)
|
|||||||
return ptr<iface>();
|
return ptr<iface>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind(fd, (struct sockaddr *)&lladdr, sizeof(struct sockaddr_ll)) < 0) {
|
if (bind(fd, (struct sockaddr* )&lladdr, sizeof(struct sockaddr_ll)) < 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
logger::error() << "Failed to bind to interface '" << name << "'";
|
logger::error() << "Failed to bind to interface '" << name << "'";
|
||||||
return ptr<iface>();
|
return ptr<iface>();
|
||||||
@ -116,7 +116,7 @@ ptr<iface> iface::open_pfd(const std::string& name)
|
|||||||
|
|
||||||
int on = 1;
|
int on = 1;
|
||||||
|
|
||||||
if (ioctl(fd, FIONBIO, (char *)&on) < 0) {
|
if (ioctl(fd, FIONBIO, (char* )&on) < 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
logger::error() << "Failed to switch to non-blocking on interface '" << name << "'";
|
logger::error() << "Failed to switch to non-blocking on interface '" << name << "'";
|
||||||
return ptr<iface>();
|
return ptr<iface>();
|
||||||
@ -131,17 +131,17 @@ ptr<iface> iface::open_pfd(const std::string& name)
|
|||||||
// Load the ether_type.
|
// Load the ether_type.
|
||||||
BPF_STMT(BPF_LD | BPF_H | BPF_ABS,
|
BPF_STMT(BPF_LD | BPF_H | BPF_ABS,
|
||||||
offsetof(struct ether_header, ether_type)),
|
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),
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ETHERTYPE_IPV6, 0, 5),
|
||||||
// Load the next header type.
|
// Load the next header type.
|
||||||
BPF_STMT(BPF_LD | BPF_B | BPF_ABS,
|
BPF_STMT(BPF_LD | BPF_B | BPF_ABS,
|
||||||
sizeof(struct ether_header) + offsetof(struct ip6_hdr, ip6_nxt)),
|
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),
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3),
|
||||||
// Load the ICMPv6 type.
|
// Load the ICMPv6 type.
|
||||||
BPF_STMT(BPF_LD | BPF_B | BPF_ABS,
|
BPF_STMT(BPF_LD | BPF_B | BPF_ABS,
|
||||||
sizeof(struct ether_header) + sizeof(ip6_hdr) + offsetof(struct icmp6_hdr, icmp6_type)),
|
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),
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_NEIGHBOR_SOLICIT, 0, 1),
|
||||||
// Keep packet.
|
// Keep packet.
|
||||||
BPF_STMT(BPF_RET | BPF_K, -1),
|
BPF_STMT(BPF_RET | BPF_K, -1),
|
||||||
@ -149,10 +149,10 @@ ptr<iface> iface::open_pfd(const std::string& name)
|
|||||||
BPF_STMT(BPF_RET | BPF_K, 0)
|
BPF_STMT(BPF_RET | BPF_K, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
fprog.filter = (struct sock_filter *)filter;
|
fprog.filter = (struct sock_filter* )filter;
|
||||||
fprog.len = 8;
|
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";
|
logger::error() << "Failed to set filter";
|
||||||
return ptr<iface>();
|
return ptr<iface>();
|
||||||
}
|
}
|
||||||
@ -190,7 +190,7 @@ ptr<iface> iface::open_ifd(const std::string& name)
|
|||||||
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1);
|
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1);
|
||||||
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
|
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);
|
close(fd);
|
||||||
logger::error() << "Failed to bind to interface '" << name << "'";
|
logger::error() << "Failed to bind to interface '" << name << "'";
|
||||||
return ptr<iface>();
|
return ptr<iface>();
|
||||||
@ -202,25 +202,25 @@ ptr<iface> iface::open_ifd(const std::string& name)
|
|||||||
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1);
|
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1);
|
||||||
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
|
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
|
||||||
|
|
||||||
if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
|
if (ioctl(fd, SIOCGIFHWADDR,& ifr) < 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
logger::error() << "Failed to detect link-layer address for interface '" << name << "'";
|
logger::error() << "Failed to detect link-layer address for interface '" << name << "'";
|
||||||
return ptr<iface>();
|
return ptr<iface>();
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
// Set max hops.
|
||||||
|
|
||||||
int hops = 255;
|
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);
|
close(fd);
|
||||||
logger::error() << "iface::open_ifd() failed IPV6_MULTICAST_HOPS";
|
logger::error() << "iface::open_ifd() failed IPV6_MULTICAST_HOPS";
|
||||||
return ptr<iface>();
|
return ptr<iface>();
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
close(fd);
|
||||||
logger::error() << "iface::open_ifd() failed IPV6_UNICAST_HOPS";
|
logger::error() << "iface::open_ifd() failed IPV6_UNICAST_HOPS";
|
||||||
return ptr<iface>();
|
return ptr<iface>();
|
||||||
@ -230,7 +230,7 @@ ptr<iface> iface::open_ifd(const std::string& name)
|
|||||||
|
|
||||||
int on = 1;
|
int on = 1;
|
||||||
|
|
||||||
if (ioctl(fd, FIONBIO, (char *)&on) < 0) {
|
if (ioctl(fd, FIONBIO, (char* )&on) < 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
logger::error() << "Failed to switch to non-blocking on interface '" << name << "'";
|
logger::error() << "Failed to switch to non-blocking on interface '" << name << "'";
|
||||||
return ptr<iface>();
|
return ptr<iface>();
|
||||||
@ -240,9 +240,9 @@ ptr<iface> iface::open_ifd(const std::string& name)
|
|||||||
|
|
||||||
struct icmp6_filter filter;
|
struct icmp6_filter filter;
|
||||||
ICMP6_FILTER_SETBLOCKALL(&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";
|
logger::error() << "Failed to set filter";
|
||||||
return ptr<iface>();
|
return ptr<iface>();
|
||||||
}
|
}
|
||||||
@ -270,7 +270,7 @@ ptr<iface> iface::open_ifd(const std::string& name)
|
|||||||
return ifa;
|
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 msghdr mhdr;
|
||||||
struct iovec iov;
|
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));
|
memset(&mhdr, 0, sizeof(mhdr));
|
||||||
mhdr.msg_name = (caddr_t)saddr;
|
mhdr.msg_name = (caddr_t)saddr;
|
||||||
mhdr.msg_namelen = sizeof(struct sockaddr);
|
mhdr.msg_namelen = sizeof(struct sockaddr);
|
||||||
mhdr.msg_iov = &iov;
|
mhdr.msg_iov =& iov;
|
||||||
mhdr.msg_iovlen = 1;
|
mhdr.msg_iovlen = 1;
|
||||||
|
|
||||||
if ((len = recvmsg(fd, &mhdr, 0)) < 0)
|
if ((len = recvmsg(fd,& mhdr, 0)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (len < sizeof(struct icmp6_hdr))
|
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;
|
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 sockaddr_in6 daddr_tmp;
|
||||||
struct msghdr mhdr;
|
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));
|
memset(&daddr_tmp, 0, sizeof(struct sockaddr_in6));
|
||||||
daddr_tmp.sin6_family = AF_INET6;
|
daddr_tmp.sin6_family = AF_INET6;
|
||||||
daddr_tmp.sin6_port = htons(IPPROTO_ICMPV6); // Needed?
|
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_len = size;
|
||||||
iov.iov_base = (caddr_t)msg;
|
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));
|
memset(&mhdr, 0, sizeof(mhdr));
|
||||||
mhdr.msg_name = (caddr_t)&daddr_tmp;
|
mhdr.msg_name = (caddr_t)&daddr_tmp;
|
||||||
mhdr.msg_namelen = sizeof(sockaddr_in6);
|
mhdr.msg_namelen = sizeof(sockaddr_in6);
|
||||||
mhdr.msg_iov = &iov;
|
mhdr.msg_iov =& iov;
|
||||||
mhdr.msg_iovlen = 1;
|
mhdr.msg_iovlen = 1;
|
||||||
|
|
||||||
logger::debug() << "iface::write() daddr=" << daddr.to_string() << ", len=" << size;
|
logger::debug() << "iface::write() daddr=" << daddr.to_string() << ", len=" << size;
|
||||||
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if ((len = sendmsg(fd, &mhdr, 0)) < 0)
|
if ((len = sendmsg(fd,& mhdr, 0)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
@ -336,17 +336,17 @@ ssize_t iface::read_solicit(address& saddr, address& daddr, address& taddr)
|
|||||||
uint8_t msg[256];
|
uint8_t msg[256];
|
||||||
ssize_t len;
|
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;
|
return -1;
|
||||||
|
|
||||||
struct ip6_hdr *ip6h =
|
struct ip6_hdr* ip6h =
|
||||||
(struct ip6_hdr *)(msg + ETH_HLEN);
|
(struct ip6_hdr* )(msg + ETH_HLEN);
|
||||||
|
|
||||||
struct icmp6_hdr *icmph =
|
struct icmp6_hdr* icmph =
|
||||||
(struct icmp6_hdr *)(msg + ETH_HLEN + sizeof( struct ip6_hdr));
|
(struct icmp6_hdr* )(msg + ETH_HLEN + sizeof( struct ip6_hdr));
|
||||||
|
|
||||||
struct nd_neighbor_solicit *ns =
|
struct nd_neighbor_solicit* ns =
|
||||||
(struct nd_neighbor_solicit *)(msg + ETH_HLEN + sizeof( struct ip6_hdr));
|
(struct nd_neighbor_solicit* )(msg + ETH_HLEN + sizeof( struct ip6_hdr));
|
||||||
|
|
||||||
taddr = ns->nd_ns_target;
|
taddr = ns->nd_ns_target;
|
||||||
daddr = ip6h->ip6_dst;
|
daddr = ip6h->ip6_dst;
|
||||||
@ -363,20 +363,20 @@ ssize_t iface::write_solicit(const address& taddr)
|
|||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
struct nd_neighbor_solicit *ns =
|
struct nd_neighbor_solicit* ns =
|
||||||
(struct nd_neighbor_solicit *)&buf[0];
|
(struct nd_neighbor_solicit* )&buf[0];
|
||||||
|
|
||||||
struct nd_opt_hdr *opt =
|
struct nd_opt_hdr* opt =
|
||||||
(struct nd_opt_hdr *)&buf[sizeof(struct nd_neighbor_solicit)];
|
(struct nd_opt_hdr* )&buf[sizeof(struct nd_neighbor_solicit)];
|
||||||
|
|
||||||
opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
|
opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
|
||||||
opt->nd_opt_len = 1;
|
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.
|
// FIXME: Alright, I'm lazy.
|
||||||
static address multicast("ff02::1:ff00:0000");
|
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();
|
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)
|
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));
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
struct nd_neighbor_advert *na =
|
struct nd_neighbor_advert* na =
|
||||||
(struct nd_neighbor_advert *)&buf[0];
|
(struct nd_neighbor_advert* )&buf[0];
|
||||||
|
|
||||||
struct nd_opt_hdr *opt =
|
struct nd_opt_hdr* opt =
|
||||||
(struct nd_opt_hdr *)&buf[sizeof(struct nd_neighbor_advert)];
|
(struct nd_opt_hdr* )&buf[sizeof(struct nd_neighbor_advert)];
|
||||||
|
|
||||||
opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
|
opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
|
||||||
opt->nd_opt_len = 1;
|
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_type = ND_NEIGHBOR_ADVERT;
|
||||||
na->nd_na_flags_reserved = ND_NA_FLAG_SOLICITED | (router ? ND_NA_FLAG_ROUTER : 0);
|
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();
|
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);
|
sizeof(struct nd_opt_hdr) + 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,15 +428,15 @@ ssize_t iface::read_advert(address& saddr, address& taddr)
|
|||||||
uint8_t msg[256];
|
uint8_t msg[256];
|
||||||
ssize_t len;
|
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;
|
return -1;
|
||||||
|
|
||||||
saddr = t_saddr.sin6_addr;
|
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;
|
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;
|
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()
|
void iface::fixup_pollfds()
|
||||||
{
|
{
|
||||||
_pollfds.resize(_map.size() * 2);
|
_pollfds.resize(_map.size()* 2);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
@ -488,7 +488,7 @@ int iface::poll_all()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(_pollfds.size() == _map.size() * 2);
|
assert(_pollfds.size() == _map.size()* 2);
|
||||||
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
@ -506,13 +506,15 @@ int iface::poll_all()
|
|||||||
f_it != _pollfds.end(); f_it++) {
|
f_it != _pollfds.end(); f_it++) {
|
||||||
assert(i_it != _map.end());
|
assert(i_it != _map.end());
|
||||||
|
|
||||||
if (i && !(i % 2))
|
if (i && !(i % 2)) {
|
||||||
i_it++;
|
i_it++;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_pfd = i++ % 2;
|
bool is_pfd = i++ % 2;
|
||||||
|
|
||||||
if (!(f_it->revents & POLLIN))
|
if (!(f_it->revents& POLLIN)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ptr<iface> ifa = i_it->second;
|
ptr<iface> ifa = i_it->second;
|
||||||
|
|
||||||
@ -524,8 +526,9 @@ int iface::poll_all()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!saddr.is_unicast() || !daddr.is_multicast())
|
if (!saddr.is_unicast() || !daddr.is_multicast()) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ifa->_pr->handle_solicit(saddr, daddr, taddr);
|
ifa->_pr->handle_solicit(saddr, daddr, taddr);
|
||||||
} else {
|
} else {
|
||||||
@ -536,7 +539,8 @@ int iface::poll_all()
|
|||||||
|
|
||||||
for (std::list<weak_ptr<session> >::iterator s_it = ifa->_sessions.begin();
|
for (std::list<weak_ptr<session> >::iterator s_it = ifa->_sessions.begin();
|
||||||
s_it != ifa->_sessions.end(); s_it++) {
|
s_it != ifa->_sessions.end(); s_it++) {
|
||||||
const ptr<session> sess = *s_it;
|
const ptr<session> sess =* s_it;
|
||||||
|
|
||||||
if ((sess->taddr() == taddr) && (sess->status() == session::WAITING)) {
|
if ((sess->taddr() == taddr) && (sess->status() == session::WAITING)) {
|
||||||
sess->handle_advert();
|
sess->handle_advert();
|
||||||
break;
|
break;
|
||||||
@ -558,10 +562,10 @@ int iface::allmulti(int state)
|
|||||||
|
|
||||||
strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ);
|
strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ);
|
||||||
|
|
||||||
if (ioctl(_pfd, SIOCGIFFLAGS, &ifr) < 0)
|
if (ioctl(_pfd, SIOCGIFFLAGS,& ifr) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int old_state = !!(ifr.ifr_flags & IFF_ALLMULTI);
|
int old_state = !!(ifr.ifr_flags& IFF_ALLMULTI);
|
||||||
|
|
||||||
if (state == old_state)
|
if (state == old_state)
|
||||||
return old_state;
|
return old_state;
|
||||||
@ -571,7 +575,7 @@ int iface::allmulti(int state)
|
|||||||
else
|
else
|
||||||
ifr.ifr_flags &= ~IFF_ALLMULTI;
|
ifr.ifr_flags &= ~IFF_ALLMULTI;
|
||||||
|
|
||||||
if (ioctl(_pfd, SIOCSIFFLAGS, &ifr) < 0)
|
if (ioctl(_pfd, SIOCSIFFLAGS,& ifr) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return old_state;
|
return old_state;
|
||||||
|
@ -30,8 +30,7 @@ NDPPD_NS_BEGIN
|
|||||||
class session;
|
class session;
|
||||||
class proxy;
|
class proxy;
|
||||||
|
|
||||||
class iface
|
class iface {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
// Weak pointer so this object can reference itself.
|
// Weak pointer so this object can reference itself.
|
||||||
weak_ptr<iface> _ptr;
|
weak_ptr<iface> _ptr;
|
||||||
@ -85,9 +84,9 @@ public:
|
|||||||
|
|
||||||
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.
|
// Writes a NB_NEIGHBOR_SOLICIT message to the _ifd socket.
|
||||||
ssize_t write_solicit(const address& taddr);
|
ssize_t write_solicit(const address& taddr);
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
NDPPD_NS_BEGIN
|
NDPPD_NS_BEGIN
|
||||||
|
|
||||||
/*const char *log::_level_str[] =
|
/*const char* log::_level_str[] =
|
||||||
{
|
{
|
||||||
"fatal",
|
"fatal",
|
||||||
"alert",
|
"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())
|
_pri(l._pri) //, _ss(l._ss.str())
|
||||||
{
|
{
|
||||||
_ss << l._ss.rdbuf();
|
_ss << l._ss.rdbuf();
|
||||||
@ -100,34 +100,34 @@ logger logger::debug()
|
|||||||
return logger(LOG_DEBUG);
|
return logger(LOG_DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger &logger::operator<<(const std::string &str)
|
logger& logger::operator<<(const std::string& str)
|
||||||
{
|
{
|
||||||
_ss << str;
|
_ss << str;
|
||||||
return *this;
|
return* this;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger &logger::operator<<(int n)
|
logger& logger::operator<<(int n)
|
||||||
{
|
{
|
||||||
_ss << n;
|
_ss << n;
|
||||||
return *this;
|
return* this;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger &logger::operator<<(logger &(*pf)(logger &))
|
logger& logger::operator<<(logger& (*pf)(logger& ))
|
||||||
{
|
{
|
||||||
pf(*this);
|
pf(*this);
|
||||||
return *this;
|
return* this;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger &logger::endl(logger &__l)
|
logger& logger::endl(logger& __l)
|
||||||
{
|
{
|
||||||
__l.flush();
|
__l.flush();
|
||||||
return __l;
|
return __l;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger &logger::force_log(bool b)
|
logger& logger::force_log(bool b)
|
||||||
{
|
{
|
||||||
_force_log = b;
|
_force_log = b;
|
||||||
return *this;
|
return* this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void logger::flush()
|
void logger::flush()
|
||||||
@ -175,9 +175,9 @@ void logger::max_pri(int pri)
|
|||||||
_max_pri = 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) {
|
if (!*c_name) {
|
||||||
return false;
|
return false;
|
||||||
|
25
src/logger.h
25
src/logger.h
@ -30,26 +30,17 @@
|
|||||||
# define LOG_DEBUG 7 /* debug-level messages */
|
# define LOG_DEBUG 7 /* debug-level messages */
|
||||||
#endif
|
#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
|
NDPPD_NS_BEGIN
|
||||||
|
|
||||||
class logger
|
class logger {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
logger(int pri = LOG_INFO);
|
logger(int pri = LOG_INFO);
|
||||||
|
|
||||||
logger(const logger &l);
|
logger(const logger& l);
|
||||||
|
|
||||||
~logger();
|
~logger();
|
||||||
|
|
||||||
static std::string format(const std::string &fmt, ...);
|
static std::string format(const std::string& fmt, ...);
|
||||||
|
|
||||||
static void syslog(bool enable);
|
static void syslog(bool enable);
|
||||||
static bool syslog();
|
static bool syslog();
|
||||||
@ -58,15 +49,15 @@ public:
|
|||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
static bool verbosity(const std::string &name);
|
static bool verbosity(const std::string& name);
|
||||||
|
|
||||||
logger& operator<<(const std::string &str);
|
logger& operator<<(const std::string& str);
|
||||||
logger& operator<<(logger &(*pf)(logger &));
|
logger& operator<<(logger& (*pf)(logger& ));
|
||||||
logger& operator<<(int n);
|
logger& operator<<(int n);
|
||||||
|
|
||||||
logger& force_log(bool b = true);
|
logger& force_log(bool b = true);
|
||||||
|
|
||||||
static logger& endl(logger &__l);
|
static logger& endl(logger& __l);
|
||||||
|
|
||||||
// Shortcuts.
|
// Shortcuts.
|
||||||
|
|
||||||
@ -83,7 +74,7 @@ private:
|
|||||||
bool _force_log;
|
bool _force_log;
|
||||||
|
|
||||||
struct pri_name {
|
struct pri_name {
|
||||||
const char *name;
|
const char* name;
|
||||||
int pri;
|
int pri;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
57
src/ndppd.cc
57
src/ndppd.cc
@ -27,6 +27,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "ndppd.h"
|
#include "ndppd.h"
|
||||||
|
#include "route.h"
|
||||||
|
|
||||||
using namespace ndppd;
|
using namespace ndppd;
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ int daemonize()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool configure(const std::string &path)
|
bool configure(const std::string& path)
|
||||||
{
|
{
|
||||||
ptr<conf> cf;
|
ptr<conf> cf;
|
||||||
|
|
||||||
@ -61,61 +62,65 @@ bool configure(const std::string &path)
|
|||||||
|
|
||||||
std::vector<ptr<conf> >::const_iterator p_it;
|
std::vector<ptr<conf> >::const_iterator p_it;
|
||||||
|
|
||||||
std::vector<ptr<conf> > proxies(cf->find("proxy"));
|
std::vector<ptr<conf> > proxies(cf->find_all("proxy"));
|
||||||
|
|
||||||
for (p_it = proxies.begin(); p_it != proxies.end(); p_it++) {
|
for (p_it = proxies.begin(); p_it != proxies.end(); p_it++) {
|
||||||
ptr<conf> pr_cf = *p_it, x_cf;
|
ptr<conf> pr_cf =* p_it, x_cf;
|
||||||
|
|
||||||
if (pr_cf->value() == "") {
|
if (pr_cf->empty()) {
|
||||||
logger::error() << "'proxy' section is missing interface name";
|
logger::error() << "'proxy' section is missing interface name";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<proxy> pr = proxy::open(pr_cf->value());
|
ptr<proxy> pr = proxy::open(*pr_cf);
|
||||||
|
|
||||||
if (!pr) {
|
if (!pr) {
|
||||||
logger::error() << "Configuration failed for proxy '" << pr_cf->value() << "'";
|
logger::error() << "Configuration failed for proxy '" << (const std::string& )*pr_cf << "'";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(x_cf = (*pr_cf)["router"]))
|
if (!(x_cf = pr_cf->find("router")))
|
||||||
pr->router(true);
|
pr->router(true);
|
||||||
else
|
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);
|
pr->ttl(30000);
|
||||||
else
|
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);
|
pr->timeout(500);
|
||||||
else
|
else
|
||||||
pr->timeout(x_cf->int_value());
|
pr->timeout(*x_cf);
|
||||||
|
|
||||||
std::vector<ptr<conf> >::const_iterator r_it;
|
std::vector<ptr<conf> >::const_iterator r_it;
|
||||||
|
|
||||||
std::vector<ptr<conf> > rules(pr_cf->find("rule"));
|
std::vector<ptr<conf> > rules(pr_cf->find_all("rule"));
|
||||||
|
|
||||||
for (r_it = rules.begin(); r_it != rules.end(); r_it++) {
|
for (r_it = rules.begin(); r_it != rules.end(); r_it++) {
|
||||||
ptr<conf> ru_cf = *r_it;
|
ptr<conf> ru_cf =* r_it;
|
||||||
|
|
||||||
if (ru_cf->value() == "") {
|
if (ru_cf->empty()) {
|
||||||
logger::error() << "'rule' is missing an IPv6 address/net";
|
logger::error() << "'rule' is missing an IPv6 address/net";
|
||||||
return false;
|
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) {
|
if (addr.prefix() <= 120) {
|
||||||
logger::warning() << "Static rule prefix /" << addr.prefix() << " <= 120 - is this what you want?";
|
logger::warning() << "Static rule prefix /" << addr.prefix() << " <= 120 - is this what you want?";
|
||||||
pr->add_rule(addr);
|
|
||||||
}
|
}
|
||||||
} else if (x_cf->value() == "") {
|
pr->add_rule(addr, false);
|
||||||
logger::error() << "'iface' expected an interface name or 'auto' as argument";
|
|
||||||
} else {
|
|
||||||
pr->add_rule(addr, iface::open_ifd(x_cf->value()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,7 +128,7 @@ bool configure(const std::string &path)
|
|||||||
return true;
|
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 config_path("/etc/ndppd.conf");
|
||||||
std::string pidfile;
|
std::string pidfile;
|
||||||
@ -141,7 +146,7 @@ int main(int argc, char *argv[], char *env[])
|
|||||||
{ 0, 0, 0, 0}
|
{ 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)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
@ -195,6 +200,8 @@ int main(int argc, char *argv[], char *env[])
|
|||||||
if (!configure(config_path))
|
if (!configure(config_path))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
route::load("/proc/net/ipv6_route");
|
||||||
|
|
||||||
// Time stuff.
|
// Time stuff.
|
||||||
|
|
||||||
struct timeval t1, t2;
|
struct timeval t1, t2;
|
||||||
@ -206,7 +213,7 @@ int main(int argc, char *argv[], char *env[])
|
|||||||
gettimeofday(&t2, 0);
|
gettimeofday(&t2, 0);
|
||||||
|
|
||||||
elapsed_time =
|
elapsed_time =
|
||||||
((t2.tv_sec - t1.tv_sec) * 1000) +
|
((t2.tv_sec - t1.tv_sec)* 1000) +
|
||||||
((t2.tv_usec - t1.tv_usec) / 1000);
|
((t2.tv_usec - t1.tv_usec) / 1000);
|
||||||
|
|
||||||
t1.tv_sec = t2.tv_sec;
|
t1.tv_sec = t2.tv_sec;
|
||||||
|
44
src/proxy.cc
44
src/proxy.cc
@ -20,6 +20,7 @@
|
|||||||
#include "ndppd.h"
|
#include "ndppd.h"
|
||||||
|
|
||||||
#include "proxy.h"
|
#include "proxy.h"
|
||||||
|
#include "route.h"
|
||||||
#include "iface.h"
|
#include "iface.h"
|
||||||
#include "rule.h"
|
#include "rule.h"
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
@ -48,8 +49,9 @@ ptr<proxy> proxy::open(const std::string& ifname)
|
|||||||
{
|
{
|
||||||
ptr<iface> ifa = iface::open_pfd(ifname);
|
ptr<iface> ifa = iface::open_pfd(ifname);
|
||||||
|
|
||||||
if (!ifa)
|
if (!ifa) {
|
||||||
return ptr<proxy>();
|
return ptr<proxy>();
|
||||||
|
}
|
||||||
|
|
||||||
return create(ifa);
|
return create(ifa);
|
||||||
}
|
}
|
||||||
@ -57,8 +59,9 @@ ptr<proxy> proxy::open(const std::string& ifname)
|
|||||||
void proxy::handle_solicit(const address& saddr, const address& daddr,
|
void proxy::handle_solicit(const address& saddr, const address& daddr,
|
||||||
const address& taddr)
|
const address& taddr)
|
||||||
{
|
{
|
||||||
logger::debug() << "proxy::handle_solicit() saddr=" << saddr.to_string()
|
logger::debug()
|
||||||
<< ", taddr=" << taddr.to_string();
|
<< "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
|
// Let's check this proxy's list of sessions to see if we can
|
||||||
// find one with the same target address.
|
// find one with the same target address.
|
||||||
@ -86,24 +89,31 @@ void proxy::handle_solicit(const address& saddr, const address& daddr,
|
|||||||
ptr<session> se;
|
ptr<session> se;
|
||||||
|
|
||||||
for (std::list<ptr<rule> >::iterator it = _rules.begin();
|
for (std::list<ptr<rule> >::iterator it = _rules.begin();
|
||||||
it != _rules.end(); it++) {
|
it != _rules.end(); it++) {
|
||||||
ptr<rule> ru = *it;
|
ptr<rule> ru =* it;
|
||||||
|
|
||||||
logger::debug() << "checking " << ru->addr().to_string() << " against " << taddr;
|
logger::debug() << "checking " << ru->addr() << " against " << taddr;
|
||||||
|
|
||||||
if (ru->addr() == taddr) {
|
if (ru->addr() == taddr) {
|
||||||
if (!se)
|
if (!se) {
|
||||||
se = session::create(_ptr, saddr, daddr, taddr);
|
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<iface> 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<rule> proxy::add_rule(const address& addr, const ptr<iface>& ifa)
|
|||||||
return ru;
|
return ru;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<rule> proxy::add_rule(const address& addr)
|
ptr<rule> proxy::add_rule(const address& addr, bool aut)
|
||||||
{
|
{
|
||||||
ptr<rule> ru(rule::create(_ptr, addr));
|
ptr<rule> ru(rule::create(_ptr, addr, aut));
|
||||||
_rules.push_back(ru);
|
_rules.push_back(ru);
|
||||||
return ru;
|
return ru;
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,7 @@ NDPPD_NS_BEGIN
|
|||||||
class iface;
|
class iface;
|
||||||
class rule;
|
class rule;
|
||||||
|
|
||||||
class proxy
|
class proxy {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
weak_ptr<proxy> _ptr;
|
weak_ptr<proxy> _ptr;
|
||||||
|
|
||||||
@ -57,7 +56,7 @@ public:
|
|||||||
|
|
||||||
ptr<rule> add_rule(const address& addr, const ptr<iface>& ifa);
|
ptr<rule> add_rule(const address& addr, const ptr<iface>& ifa);
|
||||||
|
|
||||||
ptr<rule> add_rule(const address& addr);
|
ptr<rule> add_rule(const address& addr, bool aut = false);
|
||||||
|
|
||||||
const ptr<iface>& ifa() const;
|
const ptr<iface>& ifa() const;
|
||||||
|
|
||||||
|
244
src/ptr.h
Normal file
244
src/ptr.h
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
// ndppd - NDP Proxy Daemon
|
||||||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel@priv.nu>
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
class invalid_pointer : public std::exception {
|
||||||
|
public:
|
||||||
|
invalid_pointer() throw() {};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
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 <typename T>
|
||||||
|
class ptr {
|
||||||
|
template <typename U>
|
||||||
|
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<T* >(_ref->ptr);
|
||||||
|
_ref->ptr = 0;
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_ref->sc && !_ref->wc)
|
||||||
|
delete _ref;
|
||||||
|
|
||||||
|
_ref = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
void acquire(const ptr<U>& ptr)
|
||||||
|
{
|
||||||
|
T* t = static_cast<U* >(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<T>& p, bool weak = false) :
|
||||||
|
_weak(weak), _ref(0)
|
||||||
|
{
|
||||||
|
acquire(p._ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr(const weak_ptr<T>& p, bool weak = false) :
|
||||||
|
_weak(weak), _ref(0)
|
||||||
|
{
|
||||||
|
acquire(p._ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
ptr(const ptr<U>& p, bool weak = false) :
|
||||||
|
_weak(weak), _ref(0)
|
||||||
|
{
|
||||||
|
T* x = (U*)0;
|
||||||
|
acquire(p._ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
ptr(const weak_ptr<U>& p, bool weak = false) :
|
||||||
|
_weak(weak), _ref(0)
|
||||||
|
{
|
||||||
|
T* x = (U*)0;
|
||||||
|
acquire(p._ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ptr()
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator=(T* p)
|
||||||
|
{
|
||||||
|
acquire(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<T>& operator=(const ptr<T>& p)
|
||||||
|
{
|
||||||
|
acquire(p);
|
||||||
|
return* this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const ptr<T>& other) const
|
||||||
|
{
|
||||||
|
return other._ref == _ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const ptr<T>& 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<T* >(_ref->ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class weak_ptr : public ptr<T> {
|
||||||
|
public:
|
||||||
|
weak_ptr() :
|
||||||
|
ptr<T>(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
weak_ptr(T* p) :
|
||||||
|
ptr<T>(p, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
weak_ptr(const ptr<T>& p) :
|
||||||
|
ptr<T>(p, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
weak_ptr(const weak_ptr<T>& p) :
|
||||||
|
ptr<T>(p, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
weak_ptr(const ptr<U>& p) :
|
||||||
|
ptr<T>(p, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
weak_ptr(const weak_ptr<U>& p) :
|
||||||
|
ptr<T>(p, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NDPPD_NS_END
|
||||||
|
|
||||||
|
|
165
src/route.cc
Normal file
165
src/route.cc
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
// ndppd - NDP Proxy Daemon
|
||||||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel@priv.nu>
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
#include "route.h"
|
||||||
|
|
||||||
|
NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
std::list<ptr<route> > 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> route::create(const address& addr, const std::string& ifname)
|
||||||
|
{
|
||||||
|
ptr<route> rt(new route(addr, ifname));
|
||||||
|
logger::debug() << "route::create() addr=" << addr << ", ifname=" << ifname;
|
||||||
|
_routes.push_back(rt);
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<route> route::find(const address& addr)
|
||||||
|
{
|
||||||
|
for (std::list<ptr<route> >::iterator it = _routes.begin();
|
||||||
|
it != _routes.end(); it++) {
|
||||||
|
if ((*it)->addr() == addr)
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr<route>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<iface> route::find_and_open(const address& addr)
|
||||||
|
{
|
||||||
|
ptr<route> rt;
|
||||||
|
|
||||||
|
if (rt = find(addr)) {
|
||||||
|
return rt->ifa();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr<iface>();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& route::ifname() const
|
||||||
|
{
|
||||||
|
return _ifname;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<iface> route::ifa()
|
||||||
|
{
|
||||||
|
if (!_ifa) {
|
||||||
|
return _ifa = iface::open_ifd(_ifname);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr<iface>();
|
||||||
|
}
|
||||||
|
|
||||||
|
const address& route::addr() const
|
||||||
|
{
|
||||||
|
return _addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
NDPPD_NS_END
|
||||||
|
|
59
src/route.h
Normal file
59
src/route.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// ndppd - NDP Proxy Daemon
|
||||||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel@priv.nu>
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
class route {
|
||||||
|
public:
|
||||||
|
static ptr<route> create(const address& addr, const std::string& ifname);
|
||||||
|
|
||||||
|
static ptr<route> find(const address& addr);
|
||||||
|
|
||||||
|
static ptr<iface> find_and_open(const address& addr);
|
||||||
|
|
||||||
|
static void load(const std::string& path);
|
||||||
|
|
||||||
|
const std::string& ifname() const;
|
||||||
|
|
||||||
|
const address& addr() const;
|
||||||
|
|
||||||
|
ptr<iface> ifa();
|
||||||
|
|
||||||
|
private:
|
||||||
|
address _addr;
|
||||||
|
|
||||||
|
std::string _ifname;
|
||||||
|
|
||||||
|
ptr<iface> _ifa;
|
||||||
|
|
||||||
|
static size_t hexdec(const char* str, unsigned char* buf, size_t size);
|
||||||
|
|
||||||
|
static std::string token(const char* str);
|
||||||
|
|
||||||
|
static std::list<ptr<route> > _routes;
|
||||||
|
|
||||||
|
route(const address& addr, const std::string& ifname);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
NDPPD_NS_END
|
12
src/rule.cc
12
src/rule.cc
@ -35,20 +35,24 @@ ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr, const ptr<ifac
|
|||||||
ru->_pr = pr;
|
ru->_pr = pr;
|
||||||
ru->_ifa = ifa;
|
ru->_ifa = ifa;
|
||||||
ru->_addr = addr;
|
ru->_addr = addr;
|
||||||
|
ru->_aut = false;
|
||||||
|
|
||||||
logger::debug() << "rule::create() if=" << pr->ifa()->name() << ", addr=" << addr;
|
logger::debug() << "rule::create() if=" << pr->ifa()->name() << ", addr=" << addr;
|
||||||
|
|
||||||
return ru;
|
return ru;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr)
|
ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr, bool aut)
|
||||||
{
|
{
|
||||||
ptr<rule> ru(new rule());
|
ptr<rule> ru(new rule());
|
||||||
ru->_ptr = ru;
|
ru->_ptr = ru;
|
||||||
ru->_pr = pr;
|
ru->_pr = pr;
|
||||||
ru->_addr = addr;
|
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;
|
return ru;
|
||||||
}
|
}
|
||||||
@ -63,9 +67,9 @@ ptr<iface> rule::ifa() const
|
|||||||
return _ifa;
|
return _ifa;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rule::is_static() const
|
bool rule::is_auto() const
|
||||||
{
|
{
|
||||||
return !!_ifa;
|
return _aut;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rule::check(const address& addr) const
|
bool rule::check(const address& addr) const
|
||||||
|
32
src/rule.h
32
src/rule.h
@ -28,8 +28,20 @@ NDPPD_NS_BEGIN
|
|||||||
class iface;
|
class iface;
|
||||||
class proxy;
|
class proxy;
|
||||||
|
|
||||||
class rule
|
class rule {
|
||||||
{
|
public:
|
||||||
|
static ptr<rule> create(const ptr<proxy>& pr, const address& addr, const ptr<iface>& ifa);
|
||||||
|
|
||||||
|
static ptr<rule> create(const ptr<proxy>& pr, const address& addr, bool stc = true);
|
||||||
|
|
||||||
|
const address& addr() const;
|
||||||
|
|
||||||
|
ptr<iface> ifa() const;
|
||||||
|
|
||||||
|
bool is_auto() const;
|
||||||
|
|
||||||
|
bool check(const address& addr) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
weak_ptr<rule> _ptr;
|
weak_ptr<rule> _ptr;
|
||||||
|
|
||||||
@ -39,21 +51,9 @@ private:
|
|||||||
|
|
||||||
address _addr;
|
address _addr;
|
||||||
|
|
||||||
|
bool _aut;
|
||||||
|
|
||||||
rule();
|
rule();
|
||||||
|
|
||||||
public:
|
|
||||||
static ptr<rule> create(const ptr<proxy>& pr, const address& addr, const ptr<iface>& ifa);
|
|
||||||
|
|
||||||
static ptr<rule> create(const ptr<proxy>& pr, const address& addr);
|
|
||||||
|
|
||||||
const address& addr() const;
|
|
||||||
|
|
||||||
ptr<iface> ifa() const;
|
|
||||||
|
|
||||||
bool is_static() const;
|
|
||||||
|
|
||||||
bool check(const address& addr) const;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NDPPD_NS_END
|
NDPPD_NS_END
|
||||||
|
@ -79,8 +79,8 @@ ptr<session> session::create(const ptr<proxy>& pr, const address& saddr,
|
|||||||
_sessions.push_back(se);
|
_sessions.push_back(se);
|
||||||
|
|
||||||
logger::debug()
|
logger::debug()
|
||||||
<< "session::create() pr=" << logger::format("%x", (proxy *)pr) << ", saddr=" << saddr
|
<< "session::create() pr=" << logger::format("%x", (proxy* )pr) << ", saddr=" << saddr
|
||||||
<< ", daddr=" << daddr << ", taddr=" << taddr << " =" << logger::format("%x", (session *)se);
|
<< ", daddr=" << daddr << ", taddr=" << taddr << " =" << logger::format("%x", (session* )se);
|
||||||
|
|
||||||
return se;
|
return se;
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,7 @@ NDPPD_NS_BEGIN
|
|||||||
class proxy;
|
class proxy;
|
||||||
class iface;
|
class iface;
|
||||||
|
|
||||||
class session
|
class session {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
weak_ptr<session> _ptr;
|
weak_ptr<session> _ptr;
|
||||||
|
|
||||||
@ -80,8 +79,6 @@ public:
|
|||||||
void send_solicit();
|
void send_solicit();
|
||||||
|
|
||||||
void refesh();
|
void refesh();
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NDPPD_NS_END
|
NDPPD_NS_END
|
||||||
|
Loading…
x
Reference in New Issue
Block a user