From 7d84dbeb183fc8ebad431b57346cf2c288e53b74 Mon Sep 17 00:00:00 2001 From: Daniel Adolfsson Date: Tue, 13 Sep 2011 21:26:12 +0200 Subject: [PATCH] Initial commit --- .gitignore | 3 + Makefile | 9 ++ README | 6 + ndppd.conf | 7 + src/Makefile | 17 ++ src/address.cc | 275 +++++++++++++++++++++++++++++++++ src/address.h | 66 ++++++++ src/conf.cc | 151 ++++++++++++++++++ src/conf.h | 44 ++++++ src/iface.cc | 411 +++++++++++++++++++++++++++++++++++++++++++++++++ src/iface.h | 101 ++++++++++++ src/log.cc | 48 ++++++ src/log.h | 57 +++++++ src/ndppd.cc | 77 +++++++++ src/ndppd.h | 163 ++++++++++++++++++++ src/proxy.cc | 122 +++++++++++++++ src/proxy.h | 63 ++++++++ src/ptr.h | 211 +++++++++++++++++++++++++ src/rule.cc | 79 ++++++++++ src/rule.h | 64 ++++++++ src/session.cc | 107 +++++++++++++ src/session.h | 84 ++++++++++ 22 files changed, 2165 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README create mode 100644 ndppd.conf create mode 100644 src/Makefile create mode 100644 src/address.cc create mode 100644 src/address.h create mode 100644 src/conf.cc create mode 100644 src/conf.h create mode 100644 src/iface.cc create mode 100644 src/iface.h create mode 100644 src/log.cc create mode 100644 src/log.h create mode 100644 src/ndppd.cc create mode 100644 src/ndppd.h create mode 100644 src/proxy.cc create mode 100644 src/proxy.h create mode 100644 src/ptr.h create mode 100644 src/rule.cc create mode 100644 src/rule.h create mode 100644 src/session.cc create mode 100644 src/session.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f15df37 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +ndppd +*.o + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7a85f02 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +all: + cd src && make all && cp ndppd .. + +clean: + rm -f ndppd + cd src && make clean + + + diff --git a/README b/README new file mode 100644 index 0000000..4f1685f --- /dev/null +++ b/README @@ -0,0 +1,6 @@ +ndppd - NDP Proxy Daemon + + + + + diff --git a/ndppd.conf b/ndppd.conf new file mode 100644 index 0000000..179347b --- /dev/null +++ b/ndppd.conf @@ -0,0 +1,7 @@ +proxy eth0 { + rule 2a01:4f8:121:a1::10 { + iface = eth0 + } +} + + diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..ce47775 --- /dev/null +++ b/src/Makefile @@ -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} + + diff --git a/src/address.cc b/src/address.cc new file mode 100644 index 0000000..a0606da --- /dev/null +++ b/src/address.cc @@ -0,0 +1,275 @@ +// ndppd - NDP Proxy Daemon +// Copyright (C) 2011 Daniel Adolfsson +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +#include +#include +#include + +#include +#include +#include + +#include +#include + +#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 + + + diff --git a/src/address.h b/src/address.h new file mode 100644 index 0000000..319d129 --- /dev/null +++ b/src/address.h @@ -0,0 +1,66 @@ +// ndppd - NDP Proxy Daemon +// Copyright (C) 2011 Daniel Adolfsson +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +#ifndef __NDPPD_ADDR_H +#define __NDPPD_ADDR_H + +#include + +#include + +#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 + + diff --git a/src/conf.cc b/src/conf.cc new file mode 100644 index 0000000..91b291e --- /dev/null +++ b/src/conf.cc @@ -0,0 +1,151 @@ +// ndppd - NDP Proxy Daemon +// Copyright (C) 2011 Daniel Adolfsson +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +#include +#include +#include +#include + +#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 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 + + diff --git a/src/conf.h b/src/conf.h new file mode 100644 index 0000000..6b9d8fa --- /dev/null +++ b/src/conf.h @@ -0,0 +1,44 @@ +// ndppd - NDP Proxy Daemon +// Copyright (C) 2011 Daniel Adolfsson +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +#ifndef __NDPPD_CONF_H +#define __NDPPD_CONF_H + +#include + +#include + +#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 + + diff --git a/src/iface.cc b/src/iface.cc new file mode 100644 index 0000000..340401c --- /dev/null +++ b/src/iface.cc @@ -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 . +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 > iface::_map; + +std::vector iface::_pollfds; + +iface::iface() +{ +} + +iface::~iface() +{ + DBG("iface destroyed"); +} + +ptr 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 >::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::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(); + } + + // 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(); + } + + 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(); + } + + // 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(); + } + + // 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(); + } + + // Set up an instance of 'iface'. + + ptr 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 >::iterator it = _map.begin(); + it != _map.end(); it++) + { + _pollfds[i].fd = it->second->_fd; + _pollfds[i].events = POLLIN; + _pollfds[i].revents = 0; + i++; + } +} + +ptr iface::get_proxy() const +{ + return _proxy; +} + +void iface::set_proxy(const ptr& pr) +{ + _proxy = pr; +} + +void iface::add_session(const ptr& 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::iterator fit; + std::map >::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 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 >::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 + diff --git a/src/iface.h b/src/iface.h new file mode 100644 index 0000000..d84d533 --- /dev/null +++ b/src/iface.h @@ -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 . +#ifndef __NDPPD_IFACE_H +#define __NDPPD_IFACE_H + +#include +#include +#include +#include + +#include +#include + +#include "ndppd.h" + +__NDPPD_NS_BEGIN + +class proxy; +class session; + +class iface +{ +private: + // Weak pointer so this object can reference itself. + ptr _weak_ptr; + + static std::map > _map; + + // An array of objects used with ::poll. + static std::vector _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 > _sessions; + + ptr _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 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 get_proxy() const; + + void set_proxy(const ptr& pr); + + // Adds a session to be monitored for ND_NEIGHBOR_ADVERT messages. + void add_session(const ptr& se); + +}; + +__NDPPD_NS_END + +#endif // __NDPPD_IFACE_H + + diff --git a/src/log.cc b/src/log.cc new file mode 100644 index 0000000..303071b --- /dev/null +++ b/src/log.cc @@ -0,0 +1,48 @@ +// ndppd - NDP Proxy Daemon +// Copyright (C) 2011 Daniel Adolfsson +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +#include +#include + +#include "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 + + diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..ff3d5a5 --- /dev/null +++ b/src/log.h @@ -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 . +#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 + + diff --git a/src/ndppd.cc b/src/ndppd.cc new file mode 100644 index 0000000..f34665c --- /dev/null +++ b/src/ndppd.cc @@ -0,0 +1,77 @@ +// ndppd - NDP Proxy Daemon +// Copyright (C) 2011 Daniel Adolfsson +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include + +#include + +#include "ndppd.h" + +#include "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; +} + + + diff --git a/src/ndppd.h b/src/ndppd.h new file mode 100644 index 0000000..631d49c --- /dev/null +++ b/src/ndppd.h @@ -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 . + +#ifndef __NDPPD_H +#define __NDPPD_H + +#include + +#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 */ + + diff --git a/src/proxy.cc b/src/proxy.cc new file mode 100644 index 0000000..f9fa2bf --- /dev/null +++ b/src/proxy.cc @@ -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 . +#include +#include +#include + +#include "ndppd.h" + +#include "proxy.h" +#include "iface.h" +#include "rule.h" +#include "session.h" + +__NDPPD_NS_BEGIN + +proxy::proxy() +{ +} + +ptr proxy::create(const ptr& ifa) +{ + ptr 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::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 >::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 se; + + for(std::list >::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 proxy::add_rule(const address& addr, const ptr& ifa) +{ + ptr ru(rule::create(_weak_ptr.strong_copy(), addr, ifa)); + _rules.push_back(ru); + return ru; +} + +ptr proxy::add_rule(const address& addr) +{ + ptr ru(rule::create(_weak_ptr.strong_copy(), addr)); + _rules.push_back(ru); + return ru; +} + +__NDPPD_NS_END + + diff --git a/src/proxy.h b/src/proxy.h new file mode 100644 index 0000000..cb95806 --- /dev/null +++ b/src/proxy.h @@ -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 . +#ifndef __NDPPD_PROXY_H +#define __NDPPD_PROXY_H + +#include +#include +#include + +#include + +#include "ndppd.h" + +__NDPPD_NS_BEGIN + +class iface; +class rule; + +class proxy +{ +private: + ptr _ifa; + + std::list > _rules; + + std::list > _sessions; + + ptr _weak_ptr; + + proxy(); + +public: + static ptr create(const ptr& ifa); + + static ptr open(const std::string& ifn); + + void handle_solicit(const address& saddr, const address& daddr, + const address& taddr); + + ptr add_rule(const address& addr, const ptr& ifa); + + ptr add_rule(const address& addr); + +}; + +__NDPPD_NS_END + +#endif // __NDPPD_PROXY_H + + diff --git a/src/ptr.h b/src/ptr.h new file mode 100644 index 0000000..f700c6d --- /dev/null +++ b/src/ptr.h @@ -0,0 +1,211 @@ +// ndppd - NDP Proxy Daemon +// Copyright (C) 2011 Daniel Adolfsson +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +#ifndef __NDPPD_PTR_H +#define __NDPPD_PTR_H + +__NDPPD_NS_BEGIN + +// This template class simplifies the usage of pointers. It's basically +// a reference-counting smart-pointer that supports both weak and +// strong references. + +template +class ptr +{ +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& 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&) 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& p) : + _ref(0), _weak(false) + { + acquire(p, p._weak); + } + + ptr(const ptr& 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& p) + { + acquire(p, p._weak); + } + + bool operator==(const ptr& other) const + { + return other._ref == _ref; + } + + bool operator!=(const ptr& other) const + { + return other._ref != _ref; + } + + bool is_null() const + { + return !((_ref != 0) && (_ref->p != 0)); + } + + bool is_weak() const + { + return _weak; + } + + bool is_strong() const + { + return !_weak; + } + + ptr weak_copy() const + { + return ptr(*this, true); + } + + ptr strong_copy() const + { + return ptr(*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 + + diff --git a/src/rule.cc b/src/rule.cc new file mode 100644 index 0000000..9db960a --- /dev/null +++ b/src/rule.cc @@ -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 . +#include +#include +#include + +#include "ndppd.h" +#include "rule.h" +#include "proxy.h" +#include "iface.h" + +__NDPPD_NS_BEGIN + +rule::rule() +{ +} + +ptr rule::create(const ptr& pr, const address& addr, const ptr& ifa) +{ + ptr 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::create(const ptr& pr, const address& addr) +{ + ptr 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 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 + + diff --git a/src/rule.h b/src/rule.h new file mode 100644 index 0000000..e8ca652 --- /dev/null +++ b/src/rule.h @@ -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 . +#ifndef __NDPPD_RULE_H +#define __NDPPD_RULE_H + +#include +#include +#include + +#include + +#include "ndppd.h" + +__NDPPD_NS_BEGIN + +class iface; +class proxy; + +class rule +{ +private: + ptr _weak_ptr; + + ptr _pr; + + ptr _ifa; + + address _addr; + + rule(); + +public: + static ptr create(const ptr& pr, const address& addr, const ptr& ifa); + + static ptr create(const ptr& pr, const address& addr); + + const address& addr() const; + + ptr ifa() const; + + bool is_static() const; + + bool check(const address& addr) const; + +}; + +__NDPPD_NS_END + +#endif // __NDPPD_PROXY_H + + diff --git a/src/session.cc b/src/session.cc new file mode 100644 index 0000000..c72062b --- /dev/null +++ b/src/session.cc @@ -0,0 +1,107 @@ +// ndppd - NDP Proxy Daemon +// Copyright (C) 2011 Daniel Adolfsson +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +#include + +#include "ndppd.h" +#include "proxy.h" +#include "iface.h" +#include "session.h" + +__NDPPD_NS_BEGIN + +session::session() +{ +} + +ptr session::create(const ptr& pr, const address& saddr, + const address& daddr, const address& taddr) +{ + ptr 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& 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 >::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 + + diff --git a/src/session.h b/src/session.h new file mode 100644 index 0000000..01048a0 --- /dev/null +++ b/src/session.h @@ -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 . +#ifndef __NDPPD_SESSION_H +#define __NDPPD_SESSION_H + +#include + +#include "ndppd.h" + +__NDPPD_NS_BEGIN + +class proxy; +class iface; + +class session +{ +private: + ptr _weak_ptr; + + ptr _pr; + + address _saddr, _daddr, _taddr; + + // An array of interfaces this session is monitoring for + // ND_NEIGHBOR_ADVERT on. + std::list > _ifaces; + + // The remaining time in miliseconds the object will stay in the + // interface's session array or cache. + int _ttl; + + int _status; + + // Constructor. + session(); + +public: + enum + { + WAITING, // Waiting for an advert response. + VALID, // Valid; + INVALID // Invalid; + }; + + static ptr create(const ptr& pr, const address& saddr, + const address& daddr, const address& taddr); + + void add_iface(const ptr& 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 + +