ndppd/src/proxy.cc
2012-02-02 20:35:09 +01:00

172 lines
3.7 KiB
C++

// ndppd - NDP Proxy Daemon
// Copyright (C) 2011 Daniel Adolfsson <daniel@priv.nu>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <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() :
_router(true), _ttl(30000), _timeout(500)
{
}
ptr<proxy> proxy::create(const ptr<iface>& ifa)
{
ptr<proxy> pr(new proxy());
pr->_ptr = pr;
pr->_ifa = ifa;
ifa->pr(pr);
logger::debug() << "proxy::create() if=" << ifa->name();
return pr;
}
ptr<proxy> proxy::open(const std::string& ifname)
{
ptr<iface> ifa = iface::open_pfd(ifname);
if (!ifa)
return ptr<proxy>();
return create(ifa);
}
void proxy::handle_solicit(const address& saddr, const address& daddr,
const address& taddr)
{
logger::debug() << "proxy::handle_solicit() saddr=" << saddr.to_string()
<< ", taddr=" << taddr.to_string();
// 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:
(*sit)->send_advert();
}
return;
}
}
// Since we couldn't find a session that matched, we'll try to find
// a matching rule instead, and then set up a new session.
ptr<session> se;
for (std::list<ptr<rule> >::iterator it = _rules.begin();
it != _rules.end(); it++) {
ptr<rule> ru = *it;
logger::debug() << "checking " << ru->addr().to_string() << " against " << taddr;
if (ru->addr() == taddr) {
if (!se)
se = session::create(_ptr, saddr, daddr, taddr);
if (!ru->ifa()) {
// This rule doesn't have an interface, and thus we'll consider
// it "static" and immediately send the response.
se->handle_advert();
return;
}
se->add_iface((*it)->ifa());
}
}
if (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(_ptr, addr, ifa));
_rules.push_back(ru);
return ru;
}
ptr<rule> proxy::add_rule(const address& addr)
{
ptr<rule> ru(rule::create(_ptr, addr));
_rules.push_back(ru);
return ru;
}
void proxy::remove_session(const ptr<session>& se)
{
_sessions.remove(se);
}
const ptr<iface>& proxy::ifa() const
{
return _ifa;
}
bool proxy::router() const
{
return _router;
}
void proxy::router(bool val)
{
_router = val;
}
int proxy::ttl() const
{
return _ttl;
}
void proxy::ttl(int val)
{
_ttl = (val >= 0) ? val : 30000;
}
int proxy::timeout() const
{
return _timeout;
}
void proxy::timeout(int val)
{
_timeout = (val >= 0) ? val : 500;
}
NDPPD_NS_END