Initial commit
This commit is contained in:
commit
7d84dbeb18
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
ndppd
|
||||||
|
*.o
|
||||||
|
|
9
Makefile
Normal file
9
Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
all:
|
||||||
|
cd src && make all && cp ndppd ..
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ndppd
|
||||||
|
cd src && make clean
|
||||||
|
|
||||||
|
|
||||||
|
|
7
ndppd.conf
Normal file
7
ndppd.conf
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
proxy eth0 {
|
||||||
|
rule 2a01:4f8:121:a1::10 {
|
||||||
|
iface = eth0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
17
src/Makefile
Normal file
17
src/Makefile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
CC = g++
|
||||||
|
CFLAGS = -g -DDEBUG
|
||||||
|
LDFLAGS = -lconfuse
|
||||||
|
OBJ = log.o ndppd.o iface.o proxy.o address.o rule.o session.o conf.o
|
||||||
|
|
||||||
|
all: ndppd
|
||||||
|
|
||||||
|
ndppd: ${OBJ}
|
||||||
|
${CC} -o ndppd ${LDFLAGS} ${OBJ}
|
||||||
|
|
||||||
|
.cc.o:
|
||||||
|
${CC} -c $(CFLAGS) $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ndppd ${OBJ}
|
||||||
|
|
||||||
|
|
275
src/address.cc
Normal file
275
src/address.cc
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
// ndppd - NDP Proxy Daemon
|
||||||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel.adolfsson@tuhox.com>
|
||||||
|
//
|
||||||
|
// 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 <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
#include "address.h"
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
address::address()
|
||||||
|
{
|
||||||
|
_addr.s6_addr32[0] = 0;
|
||||||
|
_addr.s6_addr32[1] = 0;
|
||||||
|
_addr.s6_addr32[2] = 0;
|
||||||
|
_addr.s6_addr32[3] = 0;
|
||||||
|
|
||||||
|
_mask.s6_addr32[0] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[1] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[2] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[3] = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
address::address(const address& addr)
|
||||||
|
{
|
||||||
|
_addr.s6_addr32[0] = addr._addr.s6_addr32[0];
|
||||||
|
_addr.s6_addr32[1] = addr._addr.s6_addr32[1];
|
||||||
|
_addr.s6_addr32[2] = addr._addr.s6_addr32[2];
|
||||||
|
_addr.s6_addr32[3] = addr._addr.s6_addr32[3];
|
||||||
|
|
||||||
|
_mask.s6_addr32[0] = addr._mask.s6_addr32[0];
|
||||||
|
_mask.s6_addr32[1] = addr._mask.s6_addr32[1];
|
||||||
|
_mask.s6_addr32[2] = addr._mask.s6_addr32[2];
|
||||||
|
_mask.s6_addr32[3] = addr._mask.s6_addr32[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
address::address(const std::string& str)
|
||||||
|
{
|
||||||
|
if(!parse_string(str))
|
||||||
|
{
|
||||||
|
_addr.s6_addr32[0] = 0;
|
||||||
|
_addr.s6_addr32[1] = 0;
|
||||||
|
_addr.s6_addr32[2] = 0;
|
||||||
|
_addr.s6_addr32[3] = 0;
|
||||||
|
|
||||||
|
_mask.s6_addr32[0] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[1] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[2] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[3] = 0xffffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
address::address(const char *str)
|
||||||
|
{
|
||||||
|
if(!parse_string(str))
|
||||||
|
{
|
||||||
|
_addr.s6_addr32[0] = 0;
|
||||||
|
_addr.s6_addr32[1] = 0;
|
||||||
|
_addr.s6_addr32[2] = 0;
|
||||||
|
_addr.s6_addr32[3] = 0;
|
||||||
|
|
||||||
|
_mask.s6_addr32[0] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[1] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[2] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[3] = 0xffffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
address::address(const in6_addr& addr)
|
||||||
|
{
|
||||||
|
_addr.s6_addr32[0] = addr.s6_addr32[0];
|
||||||
|
_addr.s6_addr32[1] = addr.s6_addr32[1];
|
||||||
|
_addr.s6_addr32[2] = addr.s6_addr32[2];
|
||||||
|
_addr.s6_addr32[3] = addr.s6_addr32[3];
|
||||||
|
|
||||||
|
_mask.s6_addr32[0] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[1] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[2] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[3] = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
address::address(const in6_addr& addr, const in6_addr& mask)
|
||||||
|
{
|
||||||
|
_addr.s6_addr32[0] = addr.s6_addr32[0];
|
||||||
|
_addr.s6_addr32[1] = addr.s6_addr32[1];
|
||||||
|
_addr.s6_addr32[2] = addr.s6_addr32[2];
|
||||||
|
_addr.s6_addr32[3] = addr.s6_addr32[3];
|
||||||
|
|
||||||
|
_mask.s6_addr32[0] = mask.s6_addr32[0];
|
||||||
|
_mask.s6_addr32[1] = mask.s6_addr32[1];
|
||||||
|
_mask.s6_addr32[2] = mask.s6_addr32[2];
|
||||||
|
_mask.s6_addr32[3] = mask.s6_addr32[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
address::address(const in6_addr& addr, int pf)
|
||||||
|
{
|
||||||
|
_addr.s6_addr32[0] = addr.s6_addr32[0];
|
||||||
|
_addr.s6_addr32[1] = addr.s6_addr32[1];
|
||||||
|
_addr.s6_addr32[2] = addr.s6_addr32[2];
|
||||||
|
_addr.s6_addr32[3] = addr.s6_addr32[3];
|
||||||
|
|
||||||
|
prefix(pf);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool address::operator==(const address& addr) const
|
||||||
|
{
|
||||||
|
return !(((_addr.s6_addr32[0] ^ addr._addr.s6_addr32[0]) & _mask.s6_addr32[0]) |
|
||||||
|
((_addr.s6_addr32[1] ^ addr._addr.s6_addr32[1]) & _mask.s6_addr32[1]) |
|
||||||
|
((_addr.s6_addr32[2] ^ addr._addr.s6_addr32[2]) & _mask.s6_addr32[2]) |
|
||||||
|
((_addr.s6_addr32[3] ^ addr._addr.s6_addr32[3]) & _mask.s6_addr32[3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int address::prefix() const
|
||||||
|
{
|
||||||
|
if(!_mask.s6_addr[0])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for(int p = 0; p < 128; p++)
|
||||||
|
{
|
||||||
|
int byi = p / 8, bii = 7 - (p % 8);
|
||||||
|
if(!(_mask.s6_addr[byi] & (1 << bii)))
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
void address::prefix(int pf)
|
||||||
|
{
|
||||||
|
if((pf < 0) || (pf > 128))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_mask.s6_addr32[0] = 0;
|
||||||
|
_mask.s6_addr32[1] = 0;
|
||||||
|
_mask.s6_addr32[2] = 0;
|
||||||
|
_mask.s6_addr32[3] = 0;
|
||||||
|
|
||||||
|
while(pf--)
|
||||||
|
{
|
||||||
|
int byi = pf / 8, bii = 7 - (pf % 8);
|
||||||
|
_mask.s6_addr[byi] |= 1 << bii;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string address::to_string() const
|
||||||
|
{
|
||||||
|
char buf[INET6_ADDRSTRLEN + 8];
|
||||||
|
|
||||||
|
if(!inet_ntop(AF_INET6, &_addr, buf, INET6_ADDRSTRLEN))
|
||||||
|
return "::1";
|
||||||
|
|
||||||
|
// TODO: What to do about invalid ip?
|
||||||
|
|
||||||
|
int p;
|
||||||
|
|
||||||
|
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;
|
||||||
|
int sz, pfx;
|
||||||
|
|
||||||
|
sz = 0;
|
||||||
|
b = buf;
|
||||||
|
|
||||||
|
const char *p = str.c_str();
|
||||||
|
|
||||||
|
while(*p && isspace(*p))
|
||||||
|
p++;
|
||||||
|
|
||||||
|
while(*p)
|
||||||
|
{
|
||||||
|
if((*p == '/') || isspace(*p))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if((*p != ':') && !isxdigit(*p))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(sz >= (INET6_ADDRSTRLEN - 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*b++ = *p++;
|
||||||
|
|
||||||
|
sz++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*b = '\0';
|
||||||
|
|
||||||
|
if(inet_pton(AF_INET6, buf, &_addr) <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while(*p && isspace(*p))
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if(*p == '\0')
|
||||||
|
{
|
||||||
|
_mask.s6_addr32[0] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[1] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[2] = 0xffffffff;
|
||||||
|
_mask.s6_addr32[3] = 0xffffffff;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*p++ != '/')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while(*p && isspace(*p))
|
||||||
|
p++;
|
||||||
|
|
||||||
|
sz = 0;
|
||||||
|
b = buf;
|
||||||
|
|
||||||
|
while(*p)
|
||||||
|
{
|
||||||
|
if(!isdigit(*p))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(sz > 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*b++ = *p++;
|
||||||
|
sz++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*b = '\0';
|
||||||
|
|
||||||
|
prefix(atoi(buf));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
address::operator std::string() const
|
||||||
|
{
|
||||||
|
return to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct in6_addr& address::addr()
|
||||||
|
{
|
||||||
|
return _addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct in6_addr& address::mask()
|
||||||
|
{
|
||||||
|
return _mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
|
||||||
|
|
66
src/address.h
Normal file
66
src/address.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// ndppd - NDP Proxy Daemon
|
||||||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel.adolfsson@tuhox.com>
|
||||||
|
//
|
||||||
|
// 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/>.
|
||||||
|
#ifndef __NDPPD_ADDR_H
|
||||||
|
#define __NDPPD_ADDR_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
class iface;
|
||||||
|
|
||||||
|
class address
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct in6_addr _addr, _mask;
|
||||||
|
|
||||||
|
public:
|
||||||
|
address();
|
||||||
|
address(const address& addr);
|
||||||
|
address(const std::string& str);
|
||||||
|
address(const char *str);
|
||||||
|
address(const in6_addr& addr);
|
||||||
|
address(const in6_addr& addr, const in6_addr& mask);
|
||||||
|
address(const in6_addr& addr, int prefix);
|
||||||
|
|
||||||
|
struct in6_addr& addr();
|
||||||
|
|
||||||
|
struct in6_addr& mask();
|
||||||
|
|
||||||
|
// Compare _a/_m against a._a.
|
||||||
|
bool operator==(const address& addr) const;
|
||||||
|
|
||||||
|
const std::string to_string() const;
|
||||||
|
|
||||||
|
bool parse_string(const std::string& str);
|
||||||
|
|
||||||
|
int prefix() const;
|
||||||
|
|
||||||
|
void prefix(int n);
|
||||||
|
|
||||||
|
operator std::string() const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
#endif // __NDPPD_PROXY_H
|
||||||
|
|
||||||
|
|
151
src/conf.cc
Normal file
151
src/conf.cc
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// ndppd - NDP Proxy Daemon
|
||||||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel.adolfsson@tuhox.com>
|
||||||
|
//
|
||||||
|
// 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 <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#include <confuse.h>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
void conf::error_printf(::cfg_t *cfg, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
if(::vsnprintf(buf, sizeof(buf), fmt, ap) <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ERR("[Config] %s", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int conf::validate_rule(::cfg_t *cfg, ::cfg_opt_t *opt)
|
||||||
|
{
|
||||||
|
struct in6_addr addr, mask;
|
||||||
|
|
||||||
|
::cfg_t *rule_cfg = ::cfg_opt_getnsec(opt, ::cfg_opt_size(opt) - 1);
|
||||||
|
|
||||||
|
if(!rule_cfg)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(::cfg_getbool(rule_cfg, "static") == ::cfg_true)
|
||||||
|
{
|
||||||
|
if(::cfg_getstr(rule_cfg, "iface") != 0)
|
||||||
|
{
|
||||||
|
::cfg_error(rule_cfg, "'static' cannot be 'true' if 'iface' is set");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(::cfg_getstr(rule_cfg, "iface") == 0)
|
||||||
|
{
|
||||||
|
::cfg_error(rule_cfg, "'iface' must be set unless 'static' is 'true'");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool conf::setup(::cfg_t *cfg)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < ::cfg_size(cfg, "proxy"); i++)
|
||||||
|
{
|
||||||
|
::cfg_t *proxy_cfg = ::cfg_getnsec(cfg, "proxy", i);
|
||||||
|
|
||||||
|
if(proxy_cfg)
|
||||||
|
{
|
||||||
|
::cfg_t *rule_cfg;
|
||||||
|
int i2;
|
||||||
|
|
||||||
|
ptr<proxy> pr = proxy::open(::cfg_title(proxy_cfg));
|
||||||
|
|
||||||
|
for(i2 = 0; i2 < ::cfg_size(proxy_cfg, "rule"); i2++)
|
||||||
|
{
|
||||||
|
::cfg_t *rule_cfg;
|
||||||
|
|
||||||
|
if(!(rule_cfg = ::cfg_getnsec(proxy_cfg, "rule", i)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
address addr(::cfg_title(rule_cfg));
|
||||||
|
|
||||||
|
std::string ifname(::cfg_getstr(rule_cfg, "iface"));
|
||||||
|
|
||||||
|
if(ifname == "static")
|
||||||
|
pr->add_rule(addr);
|
||||||
|
else
|
||||||
|
pr->add_rule(addr, iface::open(ifname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool conf::load(const std::string& path)
|
||||||
|
{
|
||||||
|
::cfg_t *cfg;
|
||||||
|
int i, sz;
|
||||||
|
|
||||||
|
static ::cfg_opt_t rule_opts[] =
|
||||||
|
{
|
||||||
|
CFG_BOOL((char *)"static", ::cfg_false, CFGF_NONE),
|
||||||
|
CFG_STR((char *)"iface", (char *)"static", CFGF_NONE),
|
||||||
|
CFG_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
static ::cfg_opt_t proxy_opts[] =
|
||||||
|
{
|
||||||
|
CFG_SEC((char *)"rule", rule_opts, CFGF_MULTI | CFGF_TITLE),
|
||||||
|
CFG_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
static ::cfg_opt_t opts[] =
|
||||||
|
{
|
||||||
|
CFG_SEC((char *)"proxy", proxy_opts, CFGF_MULTI | CFGF_TITLE),
|
||||||
|
CFG_FUNC((char *)"include", &::cfg_include),
|
||||||
|
CFG_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
cfg = ::cfg_init(opts, CFGF_NOCASE);
|
||||||
|
|
||||||
|
::cfg_set_error_function(cfg, &error_printf);
|
||||||
|
|
||||||
|
::cfg_set_validate_func(cfg, "proxy|rule", &validate_rule);
|
||||||
|
|
||||||
|
switch(::cfg_parse(cfg, path.c_str()))
|
||||||
|
{
|
||||||
|
case CFG_SUCCESS:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ERR("Failed to load configuration file '%s'", path.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup(cfg);
|
||||||
|
|
||||||
|
::cfg_free(cfg);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
|
44
src/conf.h
Normal file
44
src/conf.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// ndppd - NDP Proxy Daemon
|
||||||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel.adolfsson@tuhox.com>
|
||||||
|
//
|
||||||
|
// 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/>.
|
||||||
|
#ifndef __NDPPD_CONF_H
|
||||||
|
#define __NDPPD_CONF_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <cstdarg>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
struct cfg_t;
|
||||||
|
struct cfg_opt_t;
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
class conf
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static bool setup(::cfg_t *cfg);
|
||||||
|
static void error_printf(::cfg_t *cfg, const char *fmt, va_list ap);
|
||||||
|
static int validate_rule(::cfg_t *cfg, ::cfg_opt_t *opt);
|
||||||
|
public:
|
||||||
|
static bool load(const std::string& path);
|
||||||
|
};
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
#endif // __NDPPD_CONF_H
|
||||||
|
|
||||||
|
|
411
src/iface.cc
Normal file
411
src/iface.cc
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#include <netinet/icmp6.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netpacket/packet.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
#include "iface.h"
|
||||||
|
#include "proxy.h"
|
||||||
|
#include "session.h"
|
||||||
|
#include "rule.h"
|
||||||
|
|
||||||
|
#if defined IPV6_PKTINFO && !defined IPV6_RECVPKTINFO
|
||||||
|
#define IPV6_RECVPKTINFO IPV6_PKTINFO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
std::map<std::string, ptr<iface> > iface::_map;
|
||||||
|
|
||||||
|
std::vector<struct pollfd> iface::_pollfds;
|
||||||
|
|
||||||
|
iface::iface()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
iface::~iface()
|
||||||
|
{
|
||||||
|
DBG("iface destroyed");
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<iface> iface::open(const std::string& name)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
DBG("iface::open() name=\"%s\"", name.c_str());
|
||||||
|
|
||||||
|
// Check if the interface is already opened.
|
||||||
|
|
||||||
|
std::map<std::string, ptr<iface> >::iterator it = _map.find(name);
|
||||||
|
|
||||||
|
if(it != _map.end())
|
||||||
|
return (*it).second;
|
||||||
|
|
||||||
|
// Create a socket.
|
||||||
|
|
||||||
|
if((fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
|
||||||
|
{
|
||||||
|
ERR("Unable to create socket");
|
||||||
|
return ptr<iface>::null();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind to the specified interface.
|
||||||
|
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1);
|
||||||
|
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
|
||||||
|
|
||||||
|
if(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
ERR("Failed to bind to interface '%s'", name.c_str());
|
||||||
|
return ptr<iface>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect the link-layer address.
|
||||||
|
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1);
|
||||||
|
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
|
||||||
|
|
||||||
|
if(ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
ERR("Failed to detect link-layer address for interface '%s'", name.c_str());
|
||||||
|
return ptr<iface>();
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG("fd=%d, hwaddr=%s", fd, ether_ntoa((const struct ether_addr *)&ifr.ifr_hwaddr.sa_data));
|
||||||
|
|
||||||
|
// Switch to non-blocking mode.
|
||||||
|
|
||||||
|
int on = 1;
|
||||||
|
|
||||||
|
if(ioctl(fd, FIONBIO, (char *)&on) < 0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
ERR("Failed to switch to non-blocking on interface '%s'", name.c_str());
|
||||||
|
return ptr<iface>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need the destination address, so let's turn on (RECV)PKTINFO.
|
||||||
|
|
||||||
|
if(setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0)
|
||||||
|
{
|
||||||
|
ERR("IPV6_RECVPKTINFO failed");
|
||||||
|
return ptr<iface>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up filter.
|
||||||
|
|
||||||
|
struct icmp6_filter filter;
|
||||||
|
|
||||||
|
ICMP6_FILTER_SETBLOCKALL(&filter);
|
||||||
|
ICMP6_FILTER_SETPASS(ND_NEIGHBOR_SOLICIT, &filter);
|
||||||
|
ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter);
|
||||||
|
|
||||||
|
if(setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) < 0)
|
||||||
|
{
|
||||||
|
ERR("Failed to set filter");
|
||||||
|
return ptr<iface>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up an instance of 'iface'.
|
||||||
|
|
||||||
|
ptr<iface> ifa(new iface());
|
||||||
|
|
||||||
|
ifa->_name = name;
|
||||||
|
ifa->_fd = fd;
|
||||||
|
ifa->_weak_ptr = ifa.weak_copy();
|
||||||
|
|
||||||
|
memcpy(&ifa->hwaddr, ifr.ifr_hwaddr.sa_data, sizeof(struct ether_addr));
|
||||||
|
|
||||||
|
_map[name] = ifa;
|
||||||
|
|
||||||
|
fixup_pollfds();
|
||||||
|
|
||||||
|
return ifa;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t iface::read(address& saddr, address& daddr, uint8_t *msg, size_t size)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 saddr_tmp;
|
||||||
|
struct msghdr mhdr;
|
||||||
|
struct iovec iov;
|
||||||
|
char cbuf[256];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if(!msg || (size < 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
iov.iov_len = size;
|
||||||
|
iov.iov_base = (caddr_t) msg;
|
||||||
|
|
||||||
|
memset(&mhdr, 0, sizeof(mhdr));
|
||||||
|
mhdr.msg_name = (caddr_t)&saddr_tmp;
|
||||||
|
mhdr.msg_namelen = sizeof(saddr_tmp);
|
||||||
|
mhdr.msg_iov = &iov;
|
||||||
|
mhdr.msg_iovlen = 1;
|
||||||
|
mhdr.msg_control = cbuf;
|
||||||
|
mhdr.msg_controllen = sizeof(cbuf);
|
||||||
|
|
||||||
|
if((len = recvmsg(_fd, &mhdr, 0)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(len < sizeof(struct icmp6_hdr))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Get the destination address.
|
||||||
|
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
|
||||||
|
for(cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg))
|
||||||
|
{
|
||||||
|
if(cmsg->cmsg_type == IPV6_PKTINFO)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!cmsg)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
saddr = saddr_tmp.sin6_addr;
|
||||||
|
daddr = ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_addr;
|
||||||
|
|
||||||
|
DBG("recv() saddr=%s, daddr=%s, len=%d",
|
||||||
|
saddr.to_string().c_str(), daddr.to_string().c_str(), len);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ssize_t iface::write(address& saddr, address& daddr, uint8_t *msg, size_t size)
|
||||||
|
|
||||||
|
ssize_t iface::write(address& daddr, uint8_t *msg, size_t size)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 daddr_tmp;
|
||||||
|
struct msghdr mhdr;
|
||||||
|
struct iovec iov;
|
||||||
|
|
||||||
|
memset(&daddr_tmp, 0, sizeof(struct sockaddr_in6));
|
||||||
|
//daddr_tmp.sin6_len = sizeof(struct sockaddr_in6);
|
||||||
|
daddr_tmp.sin6_family = AF_INET6;
|
||||||
|
daddr_tmp.sin6_port = htons(IPPROTO_ICMPV6); // Needed?
|
||||||
|
memcpy(&daddr_tmp.sin6_addr, &daddr.addr(), sizeof(struct in6_addr));
|
||||||
|
|
||||||
|
iov.iov_len = size;
|
||||||
|
iov.iov_base = (caddr_t)msg;
|
||||||
|
|
||||||
|
memset(&mhdr, 0, sizeof(mhdr));
|
||||||
|
mhdr.msg_name = (caddr_t)&daddr_tmp;
|
||||||
|
mhdr.msg_namelen = sizeof(sockaddr_in6);
|
||||||
|
mhdr.msg_iov = &iov;
|
||||||
|
mhdr.msg_iovlen = 1;
|
||||||
|
|
||||||
|
/*mhdr.msg_control = (void *)cmsg;
|
||||||
|
mhdr.msg_controllen = sizeof(chdr);*/
|
||||||
|
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if((len = sendmsg(_fd, &mhdr, 0)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t iface::write_solicit(address& taddr)
|
||||||
|
{
|
||||||
|
struct nd_neighbor_solicit msg;
|
||||||
|
|
||||||
|
// FIXME: Alright, I'm lazy.
|
||||||
|
static address multicast("ff02::1:ff00:0000");
|
||||||
|
|
||||||
|
address daddr;
|
||||||
|
|
||||||
|
memset(&msg, 0, sizeof(struct nd_neighbor_solicit));
|
||||||
|
|
||||||
|
msg.nd_ns_hdr.icmp6_type = ND_NEIGHBOR_SOLICIT;
|
||||||
|
|
||||||
|
memcpy(&msg.nd_ns_target, &taddr.addr(), sizeof(struct in6_addr));
|
||||||
|
|
||||||
|
daddr = multicast;
|
||||||
|
|
||||||
|
daddr.addr().s6_addr[13] = taddr.addr().s6_addr[13];
|
||||||
|
daddr.addr().s6_addr[14] = taddr.addr().s6_addr[14];
|
||||||
|
daddr.addr().s6_addr[15] = taddr.addr().s6_addr[15];
|
||||||
|
|
||||||
|
DBG("iface::write_solicit() taddr=%s, daddr=%s",
|
||||||
|
taddr.to_string().c_str(), daddr.to_string().c_str());
|
||||||
|
|
||||||
|
return write(daddr, (uint8_t *)&msg, sizeof(struct nd_neighbor_solicit));
|
||||||
|
}
|
||||||
|
|
||||||
|
int iface::read_nd(address& saddr, address& daddr, address& taddr)
|
||||||
|
{
|
||||||
|
uint8_t msg[256];
|
||||||
|
|
||||||
|
if(read(saddr, daddr, msg, sizeof(msg)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch(((struct icmp6_hdr *)msg)->icmp6_type)
|
||||||
|
{
|
||||||
|
case ND_NEIGHBOR_SOLICIT:
|
||||||
|
taddr = ((struct nd_neighbor_solicit *)msg)->nd_ns_target;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ND_NEIGHBOR_ADVERT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((struct icmp6_hdr *)msg)->icmp6_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void iface::fixup_pollfds()
|
||||||
|
{
|
||||||
|
_pollfds.resize(_map.size());
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
DBG("iface::fixup_pollfds() _map.size()=%d", _map.size());
|
||||||
|
|
||||||
|
for(std::map<std::string, ptr<iface> >::iterator it = _map.begin();
|
||||||
|
it != _map.end(); it++)
|
||||||
|
{
|
||||||
|
_pollfds[i].fd = it->second->_fd;
|
||||||
|
_pollfds[i].events = POLLIN;
|
||||||
|
_pollfds[i].revents = 0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<proxy> iface::get_proxy() const
|
||||||
|
{
|
||||||
|
return _proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iface::set_proxy(const ptr<proxy>& pr)
|
||||||
|
{
|
||||||
|
_proxy = pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iface::add_session(const ptr<session>& se)
|
||||||
|
{
|
||||||
|
_sessions.push_back(se);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iface::poll_all()
|
||||||
|
{
|
||||||
|
if(_pollfds.size() == 0)
|
||||||
|
{
|
||||||
|
::sleep(1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
DBG("iface::poll() _pollfds.size()=%d, _map.size()=%d",
|
||||||
|
_pollfds.size(), _map.size());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO: Assert _pollfds.size() == _map.size().
|
||||||
|
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if((len = ::poll(&_pollfds[0], _pollfds.size(), 100)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(len == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
std::vector<struct pollfd>::iterator fit;
|
||||||
|
std::map<std::string, ptr<iface> >::iterator iit;
|
||||||
|
|
||||||
|
for(fit = _pollfds.begin(), iit = _map.begin(); fit != _pollfds.end(); fit++, iit++)
|
||||||
|
{
|
||||||
|
if(!(fit->revents & POLLIN))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// We assume here that _pollfds is perfectly aligned with _map.
|
||||||
|
|
||||||
|
ptr<iface> ifa = iit->second;
|
||||||
|
|
||||||
|
//DBG("POLLIN on %s", ifa->_name.c_str());
|
||||||
|
|
||||||
|
int icmp6_type;
|
||||||
|
address saddr, daddr, taddr;
|
||||||
|
|
||||||
|
if((icmp6_type = ifa->read_nd(saddr, daddr, taddr)) < 0)
|
||||||
|
{
|
||||||
|
ERR("Failed to read from interface '%s'", ifa->_name.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((icmp6_type == ND_NEIGHBOR_SOLICIT) && ifa->_proxy)
|
||||||
|
{
|
||||||
|
DBG("ND_NEIGHBOR_SOLICIT");
|
||||||
|
|
||||||
|
// TODO: Check the cache for recent sessions.
|
||||||
|
|
||||||
|
ifa->_proxy->handle_solicit(saddr, daddr, taddr);
|
||||||
|
}
|
||||||
|
else if(icmp6_type == ND_NEIGHBOR_ADVERT)
|
||||||
|
{
|
||||||
|
DBG("ND_NEIGHBOR_ADVERT");
|
||||||
|
|
||||||
|
for(std::list<ptr<session> >::iterator s_it = ifa->_sessions.begin();
|
||||||
|
s_it != ifa->_sessions.end(); s_it++)
|
||||||
|
{
|
||||||
|
/*if((*s_it)->addr() == taddr)
|
||||||
|
{
|
||||||
|
(*s_it)->handle_advert();
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::string& iface::name() const
|
||||||
|
{
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
101
src/iface.h
Normal file
101
src/iface.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#ifndef __NDPPD_IFACE_H
|
||||||
|
#define __NDPPD_IFACE_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#include <net/ethernet.h>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
class proxy;
|
||||||
|
class session;
|
||||||
|
|
||||||
|
class iface
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// Weak pointer so this object can reference itself.
|
||||||
|
ptr<iface> _weak_ptr;
|
||||||
|
|
||||||
|
static std::map<std::string, ptr<iface> > _map;
|
||||||
|
|
||||||
|
// An array of objects used with ::poll.
|
||||||
|
static std::vector<struct pollfd> _pollfds;
|
||||||
|
|
||||||
|
// Updates the array above.
|
||||||
|
static void fixup_pollfds();
|
||||||
|
|
||||||
|
// Socket.
|
||||||
|
int _fd;
|
||||||
|
|
||||||
|
// Name of this interface.
|
||||||
|
std::string _name;
|
||||||
|
|
||||||
|
// An array of sessions that are monitoring this interface for
|
||||||
|
// ND_NEIGHBOR_ADVERT messages.
|
||||||
|
std::list<ptr<session> > _sessions;
|
||||||
|
|
||||||
|
ptr<proxy> _proxy;
|
||||||
|
|
||||||
|
// The link-layer address of this interface.
|
||||||
|
struct ether_addr hwaddr;
|
||||||
|
|
||||||
|
// Constructor.
|
||||||
|
iface();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
~iface();
|
||||||
|
|
||||||
|
// Opens the specified interface, and returns a pointer to
|
||||||
|
// the object, or null if there was a problem.
|
||||||
|
static ptr<iface> open(const std::string& name);
|
||||||
|
|
||||||
|
static int poll_all();
|
||||||
|
|
||||||
|
ssize_t read(address& saddr, address& daddr, uint8_t *msg, size_t size);
|
||||||
|
|
||||||
|
ssize_t write(address& daddr, uint8_t *msg, size_t size);
|
||||||
|
|
||||||
|
ssize_t write_solicit(address& taddr);
|
||||||
|
|
||||||
|
int read_nd(address& saddr, address& daddr, address& taddr);
|
||||||
|
|
||||||
|
// Returns the name of the interface.
|
||||||
|
const std::string& name() const;
|
||||||
|
|
||||||
|
ptr<proxy> get_proxy() const;
|
||||||
|
|
||||||
|
void set_proxy(const ptr<proxy>& pr);
|
||||||
|
|
||||||
|
// Adds a session to be monitored for ND_NEIGHBOR_ADVERT messages.
|
||||||
|
void add_session(const ptr<session>& se);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
#endif // __NDPPD_IFACE_H
|
||||||
|
|
||||||
|
|
48
src/log.cc
Normal file
48
src/log.cc
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// ndppd - NDP Proxy Daemon
|
||||||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel.adolfsson@tuhox.com>
|
||||||
|
//
|
||||||
|
// 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 <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
using namespace ndppd;
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
void log::puts(int level, const char *str)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "(%d) : %s\n", level, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log::printf(int level, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
va_list args;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
if(vsnprintf(buf, sizeof(buf), fmt, args) > 0)
|
||||||
|
{
|
||||||
|
puts(level, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
|
57
src/log.h
Normal file
57
src/log.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#ifndef __NDPPD_LOG_H
|
||||||
|
#define __NDPPD_LOG_H
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define DBG(...) log::printf(log::L_DEBUG, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DBG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ERR(...) log::printf(log::L_ERROR, __VA_ARGS__)
|
||||||
|
#define WRN(...) log::printf(log::L_WARNING, __VA_ARGS__)
|
||||||
|
#define BUG(...) log::printf(log::L_BUG, __VA_ARGS__)
|
||||||
|
#define NFO(...) log::printf(log::L_INFO, __VA_ARGS__)
|
||||||
|
#define NCE(...) log::printf(log::L_NOTICE, __VA_ARGS__)
|
||||||
|
#define FTL(...) log::printf(log::L_FATAL, __VA_ARGS__)
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
class log
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
L_FATAL,
|
||||||
|
L_ERROR,
|
||||||
|
L_WARNING,
|
||||||
|
L_BUG,
|
||||||
|
L_NOTICE,
|
||||||
|
L_INFO,
|
||||||
|
L_DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
|
static void puts(int level, const char *str);
|
||||||
|
|
||||||
|
static void printf(int level, const char *fmt, ...);
|
||||||
|
};
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
#endif // __NDPPD_LOG_H
|
||||||
|
|
||||||
|
|
77
src/ndppd.cc
Normal file
77
src/ndppd.cc
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// ndppd - NDP Proxy Daemon
|
||||||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel.adolfsson@tuhox.com>
|
||||||
|
//
|
||||||
|
// 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 <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
#include "iface.h"
|
||||||
|
#include "proxy.h"
|
||||||
|
#include "rule.h"
|
||||||
|
#include "session.h"
|
||||||
|
|
||||||
|
using namespace ndppd;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[], char *env[])
|
||||||
|
{
|
||||||
|
std::string config_path("/etc/ndppd.conf");
|
||||||
|
|
||||||
|
std::cout << "ndppd - NDP Proxy Daemon" << std::endl;
|
||||||
|
std::cout << "Version " NDPPD_VERSION << std::endl;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
int c, opt;
|
||||||
|
|
||||||
|
static struct option long_options[] =
|
||||||
|
{
|
||||||
|
{ "config", 1, 0, 'c' },
|
||||||
|
{ 0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
c = getopt_long(argc, argv, "c:v", long_options, &opt);
|
||||||
|
|
||||||
|
if(c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case 'c':
|
||||||
|
if(!optarg)
|
||||||
|
{
|
||||||
|
ERR("Invalid arguments");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
config_path = optarg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NFO("Using configuration file '%s'", config_path.c_str());
|
||||||
|
|
||||||
|
if(!conf::load(config_path))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while(iface::poll_all() >= 0) ;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
163
src/ndppd.h
Normal file
163
src/ndppd.h
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef __NDPPD_H
|
||||||
|
#define __NDPPD_H
|
||||||
|
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
|
||||||
|
#define __NDPPD_NS_BEGIN namespace ndppd {
|
||||||
|
#define __NDPPD_NS_END }
|
||||||
|
|
||||||
|
#define NDPPD_VERSION "0.1-alpha"
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "ptr.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "address.h"
|
||||||
|
|
||||||
|
#include "iface.h"
|
||||||
|
#include "proxy.h"
|
||||||
|
#include "session.h"
|
||||||
|
#include "rule.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
#define NDPPD_LOG_FATAL 10
|
||||||
|
#define NDPPD_LOG_ERROR 20
|
||||||
|
#define NDPPD_LOG_WARNING 30
|
||||||
|
#define NDPPD_LOG_BUG 40
|
||||||
|
#define NDPPD_LOG_NOTICE 50
|
||||||
|
#define NDPPD_LOG_INFO 60
|
||||||
|
#define NDPPD_LOG_DEBUG 70
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define DBG(...) log_printf(NDPPD_LOG_DEBUG, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DBG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ERR(...) log_printf(NDPPD_LOG_ERROR, __VA_ARGS__)
|
||||||
|
#define WRN(...) log_printf(NDPPD_LOG_WARNING, __VA_ARGS__)
|
||||||
|
#define BUG(...) log_printf(NDPPD_LOG_BUG, __VA_ARGS__)
|
||||||
|
#define NFO(...) log_printf(NDPPD_LOG_INFO, __VA_ARGS__)
|
||||||
|
#define NCE(...) log_printf(NDPPD_LOG_NOTICE, __VA_ARGS__)
|
||||||
|
#define FTL(...) log_printf(NDPPD_LOG_FATAL, __VA_ARGS__)
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL ((void *)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef null
|
||||||
|
#define null 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct net_socket net_socket_t;
|
||||||
|
typedef struct proxy proxy_t;
|
||||||
|
typedef struct rule rule_t;
|
||||||
|
typedef struct list list_t;
|
||||||
|
typedef struct list_item list_item_t;
|
||||||
|
typedef struct ndpsn ndpsn_t;
|
||||||
|
|
||||||
|
struct list
|
||||||
|
{
|
||||||
|
list_item_t *first, *last;
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct list_item
|
||||||
|
{
|
||||||
|
list_t *list;
|
||||||
|
list_item_t *next, *prev;
|
||||||
|
void *ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_socket
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
char iface[64];
|
||||||
|
|
||||||
|
list_t ndpsn_list;
|
||||||
|
|
||||||
|
list_t proxy_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ndpsn
|
||||||
|
{
|
||||||
|
net_socket_t *sns, *ans;
|
||||||
|
struct in6_addr saddr, aaddr, taddr;
|
||||||
|
int ttl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct proxy
|
||||||
|
{
|
||||||
|
net_socket_t *ns;
|
||||||
|
list_t rule_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rule
|
||||||
|
{
|
||||||
|
proxy_t *proxy;
|
||||||
|
struct in6_addr addr;
|
||||||
|
struct in6_addr mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* log.c */
|
||||||
|
void log_printf(int level, const char *fmt, ...);
|
||||||
|
|
||||||
|
/* icmp6.c */
|
||||||
|
net_socket_t *net_open(const char *iface);
|
||||||
|
int net_read(net_socket_t *ns, struct in6_addr *saddr, unsigned char *msg, size_t size);
|
||||||
|
|
||||||
|
/* conf.c */
|
||||||
|
int conf_load(const char *path);
|
||||||
|
|
||||||
|
/* list.c */
|
||||||
|
list_item_t *list_add(list_t *list, void *ptr);
|
||||||
|
void list_remove(list_item_t *li);
|
||||||
|
void list_clear(list_t *list);
|
||||||
|
void list_init(list_t *list);
|
||||||
|
|
||||||
|
/* ndpsn.c */
|
||||||
|
ndpsn_t *ndpsn_new(net_socket_t *ns, struct in6_addr *saddr, struct in6_addr *taddr);
|
||||||
|
|
||||||
|
/* util.c */
|
||||||
|
int util_parse_addr6(const char *ip, struct in6_addr *addr, struct in6_addr *mask);
|
||||||
|
int util_match_addr6(struct in6_addr *addr1, struct in6_addr *addr2, struct in6_addr *mask);
|
||||||
|
const char *util_ntop6(struct in6_addr *addr, struct in6_addr *mask);
|
||||||
|
int util_prefix2mask(int prefix, struct in6_addr *mask);
|
||||||
|
int util_mask2prefix(struct in6_addr *mask);
|
||||||
|
|
||||||
|
|
||||||
|
/* proxy.h */
|
||||||
|
proxy_t *proxy_new(const char *iface);
|
||||||
|
|
||||||
|
/* rule.h */
|
||||||
|
rule_t *rule_new(proxy_t *p, struct in6_addr *addr, struct in6_addr *mask);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __NDPPD_H */
|
||||||
|
|
||||||
|
|
122
src/proxy.cc
Normal file
122
src/proxy.cc
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
#include "proxy.h"
|
||||||
|
#include "iface.h"
|
||||||
|
#include "rule.h"
|
||||||
|
#include "session.h"
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
proxy::proxy()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<proxy> proxy::create(const ptr<iface>& ifa)
|
||||||
|
{
|
||||||
|
ptr<proxy> pr(new proxy());
|
||||||
|
pr->_weak_ptr = pr.weak_copy();
|
||||||
|
pr->_ifa = ifa;
|
||||||
|
|
||||||
|
ifa->set_proxy(pr);
|
||||||
|
|
||||||
|
DBG("proxy_create() ifa=%x =%x", (iface *)ifa, (proxy *)pr);
|
||||||
|
|
||||||
|
return pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<proxy> proxy::open(const std::string& ifname)
|
||||||
|
{
|
||||||
|
return create(iface::open(ifname));
|
||||||
|
}
|
||||||
|
|
||||||
|
void proxy::handle_solicit(const address& saddr, const address& daddr,
|
||||||
|
const address& taddr)
|
||||||
|
{
|
||||||
|
DBG("proxy::handle_solicit() saddr=%s, taddr=%s",
|
||||||
|
saddr.to_string().c_str(), taddr.to_string().c_str());
|
||||||
|
|
||||||
|
// Let's check this proxy's list of sessions to see if we can
|
||||||
|
// find one with the same target address.
|
||||||
|
|
||||||
|
for(std::list<ptr<session> >::iterator sit = _sessions.begin();
|
||||||
|
sit != _sessions.end(); sit++)
|
||||||
|
{
|
||||||
|
if((*sit)->taddr() == taddr)
|
||||||
|
{
|
||||||
|
switch((*sit)->status())
|
||||||
|
{
|
||||||
|
case session::WAITING:
|
||||||
|
case session::INVALID:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case session::VALID:
|
||||||
|
DBG("valid session..");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since we couldn't find a session that matched, we'll try to find
|
||||||
|
// a matching rule instead, and then set up a new session.
|
||||||
|
|
||||||
|
ptr<session> se;
|
||||||
|
|
||||||
|
for(std::list<ptr<rule> >::iterator it = _rules.begin();
|
||||||
|
it != _rules.end(); it++)
|
||||||
|
{
|
||||||
|
DBG("comparing %s against %s",
|
||||||
|
(*it)->addr().to_string().c_str(), taddr.to_string().c_str());
|
||||||
|
|
||||||
|
if((*it)->addr() == taddr)
|
||||||
|
{
|
||||||
|
if(se.is_null())
|
||||||
|
se = session::create(_weak_ptr.strong_copy(), saddr, daddr, taddr);
|
||||||
|
|
||||||
|
se->add_iface((*it)->ifa());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(se)
|
||||||
|
{
|
||||||
|
_sessions.push_back(se);
|
||||||
|
se->send_solicit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<rule> proxy::add_rule(const address& addr, const ptr<iface>& ifa)
|
||||||
|
{
|
||||||
|
ptr<rule> ru(rule::create(_weak_ptr.strong_copy(), addr, ifa));
|
||||||
|
_rules.push_back(ru);
|
||||||
|
return ru;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<rule> proxy::add_rule(const address& addr)
|
||||||
|
{
|
||||||
|
ptr<rule> ru(rule::create(_weak_ptr.strong_copy(), addr));
|
||||||
|
_rules.push_back(ru);
|
||||||
|
return ru;
|
||||||
|
}
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
|
63
src/proxy.h
Normal file
63
src/proxy.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#ifndef __NDPPD_PROXY_H
|
||||||
|
#define __NDPPD_PROXY_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <sys/poll.h>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
class iface;
|
||||||
|
class rule;
|
||||||
|
|
||||||
|
class proxy
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ptr<iface> _ifa;
|
||||||
|
|
||||||
|
std::list<ptr<rule> > _rules;
|
||||||
|
|
||||||
|
std::list<ptr<session> > _sessions;
|
||||||
|
|
||||||
|
ptr<proxy> _weak_ptr;
|
||||||
|
|
||||||
|
proxy();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ptr<proxy> create(const ptr<iface>& ifa);
|
||||||
|
|
||||||
|
static ptr<proxy> open(const std::string& ifn);
|
||||||
|
|
||||||
|
void handle_solicit(const address& saddr, const address& daddr,
|
||||||
|
const address& taddr);
|
||||||
|
|
||||||
|
ptr<rule> add_rule(const address& addr, const ptr<iface>& ifa);
|
||||||
|
|
||||||
|
ptr<rule> add_rule(const address& addr);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
#endif // __NDPPD_PROXY_H
|
||||||
|
|
||||||
|
|
211
src/ptr.h
Normal file
211
src/ptr.h
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
// ndppd - NDP Proxy Daemon
|
||||||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel.adolfsson@tuhox.com>
|
||||||
|
//
|
||||||
|
// 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/>.
|
||||||
|
#ifndef __NDPPD_PTR_H
|
||||||
|
#define __NDPPD_PTR_H
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
// This template class simplifies the usage of pointers. It's basically
|
||||||
|
// a reference-counting smart-pointer that supports both weak and
|
||||||
|
// strong references.
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class ptr
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct ref
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
T* p; // Pointer.
|
||||||
|
int ns; // Number of strong references.
|
||||||
|
int nw; // Number of weak references.
|
||||||
|
};
|
||||||
|
|
||||||
|
ref *_ref;
|
||||||
|
bool _weak;
|
||||||
|
|
||||||
|
void acquire(T* p)
|
||||||
|
{
|
||||||
|
if(_ref)
|
||||||
|
release();
|
||||||
|
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
_ref = new ref;
|
||||||
|
_ref->p = p;
|
||||||
|
_ref->ns = 1;
|
||||||
|
_ref->nw = 0;
|
||||||
|
_weak = false;
|
||||||
|
|
||||||
|
// DBG("acquire(T*) p=%x, count=%d", p, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void acquire(const ptr<T>& p, bool weak = false)
|
||||||
|
{
|
||||||
|
if(_ref)
|
||||||
|
release();
|
||||||
|
|
||||||
|
if(p._ref && p._ref->ns)
|
||||||
|
{
|
||||||
|
_ref = p._ref;
|
||||||
|
_weak = weak;
|
||||||
|
|
||||||
|
if(_weak)
|
||||||
|
_ref->nw++;
|
||||||
|
else
|
||||||
|
_ref->ns++;
|
||||||
|
|
||||||
|
// DBG("acquire(const ptr<T>&) p=%x, count=%d", _ref->p, _ref->count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void release()
|
||||||
|
{
|
||||||
|
if(!_ref)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!_weak && _ref->ns)
|
||||||
|
{
|
||||||
|
if(!--_ref->ns && _ref->p)
|
||||||
|
{
|
||||||
|
delete _ref->p;
|
||||||
|
_ref->p = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_weak)
|
||||||
|
_ref->nw--;
|
||||||
|
|
||||||
|
if(!_ref->ns && !_ref->nw)
|
||||||
|
delete _ref;
|
||||||
|
|
||||||
|
_ref = 0;
|
||||||
|
_weak = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ptr() :
|
||||||
|
_ref(0), _weak(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit ptr(T* p) :
|
||||||
|
_ref(0), _weak(false)
|
||||||
|
{
|
||||||
|
acquire(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr(const ptr<T>& p) :
|
||||||
|
_ref(0), _weak(false)
|
||||||
|
{
|
||||||
|
acquire(p, p._weak);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr(const ptr<T>& p, bool weak) :
|
||||||
|
_ref(0), _weak(false)
|
||||||
|
{
|
||||||
|
acquire(p, weak);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ptr()
|
||||||
|
{
|
||||||
|
if(_ref)
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ptr null()
|
||||||
|
{
|
||||||
|
return ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator=(T* p)
|
||||||
|
{
|
||||||
|
acquire(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator=(const ptr<T>& p)
|
||||||
|
{
|
||||||
|
acquire(p, p._weak);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 != 0) && (_ref->p != 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_weak() const
|
||||||
|
{
|
||||||
|
return _weak;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_strong() const
|
||||||
|
{
|
||||||
|
return !_weak;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<T> weak_copy() const
|
||||||
|
{
|
||||||
|
return ptr<T>(*this, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<T> strong_copy() const
|
||||||
|
{
|
||||||
|
return ptr<T>(*this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator*() const
|
||||||
|
{
|
||||||
|
return *_ref.p;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* operator->() const
|
||||||
|
{
|
||||||
|
return _ref ? _ref->p : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator T*() const
|
||||||
|
{
|
||||||
|
return _ref->p;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool() const
|
||||||
|
{
|
||||||
|
return !is_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(T *p = 0)
|
||||||
|
{
|
||||||
|
acquire(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
#endif // __NDPPD_PTR_H
|
||||||
|
|
||||||
|
|
79
src/rule.cc
Normal file
79
src/rule.cc
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
#include "rule.h"
|
||||||
|
#include "proxy.h"
|
||||||
|
#include "iface.h"
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
rule::rule()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr, const ptr<iface>& ifa)
|
||||||
|
{
|
||||||
|
ptr<rule> ru(new rule());
|
||||||
|
ru->_weak_ptr = ru.weak_copy();
|
||||||
|
ru->_pr = pr;
|
||||||
|
ru->_ifa = ifa;
|
||||||
|
ru->_addr = addr;
|
||||||
|
|
||||||
|
DBG("rule addr set to %s", addr.to_string().c_str());
|
||||||
|
|
||||||
|
return ru;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr)
|
||||||
|
{
|
||||||
|
ptr<rule> ru(new rule());
|
||||||
|
ru->_weak_ptr = ru.weak_copy();
|
||||||
|
ru->_pr = pr;
|
||||||
|
ru->_addr = addr;
|
||||||
|
|
||||||
|
DBG("rule addr set to %s", addr.to_string().c_str());
|
||||||
|
|
||||||
|
return ru;
|
||||||
|
}
|
||||||
|
|
||||||
|
const address& rule::addr() const
|
||||||
|
{
|
||||||
|
DBG("rule addr set to %s", _addr.to_string().c_str());
|
||||||
|
return _addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<iface> rule::ifa() const
|
||||||
|
{
|
||||||
|
return _ifa;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rule::is_static() const
|
||||||
|
{
|
||||||
|
return !!_ifa;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rule::check(const address& addr) const
|
||||||
|
{
|
||||||
|
return _addr == addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
|
64
src/rule.h
Normal file
64
src/rule.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#ifndef __NDPPD_RULE_H
|
||||||
|
#define __NDPPD_RULE_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <sys/poll.h>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
class iface;
|
||||||
|
class proxy;
|
||||||
|
|
||||||
|
class rule
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ptr<rule> _weak_ptr;
|
||||||
|
|
||||||
|
ptr<proxy> _pr;
|
||||||
|
|
||||||
|
ptr<iface> _ifa;
|
||||||
|
|
||||||
|
address _addr;
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
#endif // __NDPPD_PROXY_H
|
||||||
|
|
||||||
|
|
107
src/session.cc
Normal file
107
src/session.cc
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// ndppd - NDP Proxy Daemon
|
||||||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel.adolfsson@tuhox.com>
|
||||||
|
//
|
||||||
|
// 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 <algorithm>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
#include "proxy.h"
|
||||||
|
#include "iface.h"
|
||||||
|
#include "session.h"
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
session::session()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<session> session::create(const ptr<proxy>& pr, const address& saddr,
|
||||||
|
const address& daddr, const address& taddr)
|
||||||
|
{
|
||||||
|
ptr<session> se(new session());
|
||||||
|
|
||||||
|
se->_weak_ptr = se.weak_copy();
|
||||||
|
se->_pr = pr;
|
||||||
|
se->_saddr = saddr;
|
||||||
|
se->_taddr = taddr;
|
||||||
|
se->_daddr = daddr;
|
||||||
|
|
||||||
|
DBG("session::create() pr=%x, saddr=%s, daddr=%s, taddr=%s, =%x",
|
||||||
|
(proxy *)pr, saddr.to_string().c_str(), daddr.to_string().c_str(),
|
||||||
|
taddr.to_string().c_str(), (session *)se);
|
||||||
|
|
||||||
|
return se;
|
||||||
|
}
|
||||||
|
|
||||||
|
void session::add_iface(const ptr<iface>& ifa)
|
||||||
|
{
|
||||||
|
if(std::find(_ifaces.begin(), _ifaces.end(), ifa) != _ifaces.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ifa->add_session(_weak_ptr.strong_copy());
|
||||||
|
_ifaces.push_back(ifa);
|
||||||
|
}
|
||||||
|
|
||||||
|
void session::send_solicit()
|
||||||
|
{
|
||||||
|
DBG("sending solicit");
|
||||||
|
|
||||||
|
for(std::list<ptr<iface> >::iterator it = _ifaces.begin();
|
||||||
|
it != _ifaces.end(); it++)
|
||||||
|
{
|
||||||
|
DBG(" on %s", (*it)->name().c_str());
|
||||||
|
(*it)->write_solicit(_taddr);
|
||||||
|
// huhh hahh.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void session::send_advert()
|
||||||
|
{
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void session::handle_advert()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const address& session::taddr() const
|
||||||
|
{
|
||||||
|
return _taddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const address& session::saddr() const
|
||||||
|
{
|
||||||
|
return _saddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const address& session::daddr() const
|
||||||
|
{
|
||||||
|
return _daddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int session::status() const
|
||||||
|
{
|
||||||
|
return _status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
|
84
src/session.h
Normal file
84
src/session.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#ifndef __NDPPD_SESSION_H
|
||||||
|
#define __NDPPD_SESSION_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ndppd.h"
|
||||||
|
|
||||||
|
__NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
class proxy;
|
||||||
|
class iface;
|
||||||
|
|
||||||
|
class session
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ptr<session> _weak_ptr;
|
||||||
|
|
||||||
|
ptr<proxy> _pr;
|
||||||
|
|
||||||
|
address _saddr, _daddr, _taddr;
|
||||||
|
|
||||||
|
// An array of interfaces this session is monitoring for
|
||||||
|
// ND_NEIGHBOR_ADVERT on.
|
||||||
|
std::list<ptr<iface> > _ifaces;
|
||||||
|
|
||||||
|
// The remaining time in miliseconds the object will stay in the
|
||||||
|
// interface's session array or cache.
|
||||||
|
int _ttl;
|
||||||
|
|
||||||
|
int _status;
|
||||||
|
|
||||||
|
// Constructor.
|
||||||
|
session();
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
WAITING, // Waiting for an advert response.
|
||||||
|
VALID, // Valid;
|
||||||
|
INVALID // Invalid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ptr<session> create(const ptr<proxy>& pr, const address& saddr,
|
||||||
|
const address& daddr, const address& taddr);
|
||||||
|
|
||||||
|
void add_iface(const ptr<iface>& ifa);
|
||||||
|
|
||||||
|
const address& taddr() const;
|
||||||
|
|
||||||
|
const address& daddr() const;
|
||||||
|
|
||||||
|
const address& saddr() const;
|
||||||
|
|
||||||
|
int status() const;
|
||||||
|
|
||||||
|
void handle_advert();
|
||||||
|
|
||||||
|
void send_solicit();
|
||||||
|
|
||||||
|
void refesh();
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
__NDPPD_NS_END
|
||||||
|
|
||||||
|
#endif // __NDPPD_PROXY_H
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user