From c1b28b595a388df043997c87faf75c06959405d0 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Thu, 22 Jun 2006 12:09:57 +0000 Subject: [PATCH] =?utf8?q?Se=20agrega=20una=20primera=20aproximaci=C3=B3n?= =?utf8?q?=20al=20NameServer.=20Se=20implementa=20el=20parser=20y=20almace?= =?utf8?q?namiento=20en=20memoria=20de=20zonas=20(test=20inclu=C3=ADdo).?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- practicas/pipi/src/Makefile | 12 +- practicas/pipi/src/nameserver.cpp | 136 +++++++++++++++++++ practicas/pipi/src/nameserver.h | 70 ++++++++++ practicas/pipi/src/test_nameserver_file.cpp | 16 +++ practicas/pipi/src/test_nameserver_zones.txt | 24 ++++ 5 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 practicas/pipi/src/nameserver.cpp create mode 100644 practicas/pipi/src/nameserver.h create mode 100644 practicas/pipi/src/test_nameserver_file.cpp create mode 100644 practicas/pipi/src/test_nameserver_zones.txt diff --git a/practicas/pipi/src/Makefile b/practicas/pipi/src/Makefile index b3e071c..bbd1d67 100644 --- a/practicas/pipi/src/Makefile +++ b/practicas/pipi/src/Makefile @@ -32,7 +32,7 @@ CC=g++ # Programas targets=ip tests=test_send test_recv test_ipaddr test_ipin test_ipout test_devtcp \ - test_poll test_resolvprotos test_resolvprotoc + test_poll test_resolvprotos test_resolvprotoc test_nameserver_file # Fuentes fuentes ?= $(wildcard *.cpp) $(wildcard *.c) @@ -65,6 +65,8 @@ test_resolvprotos: test_resolvprotos.o libtcp.o ipaddr.o resolvproto.o test_resolvprotoc: test_resolvprotoc.o libtcp.o ipaddr.o resolvproto.o +test_nameserver_file: test_nameserver_file.o ipaddr.o nameserver.o + ip: ip.o ipout.o ipin.o ipaddr.o ipheader.o devque.o devtcp.o routetable.o libtcp.o depend: @@ -175,6 +177,10 @@ ipout.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h ipout.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h ipout.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h ipout.o: /usr/include/bits/msq.h +nameserver.o: nameserver.h ipaddr.h /usr/include/stdint.h +nameserver.o: /usr/include/features.h /usr/include/sys/cdefs.h +nameserver.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h +nameserver.o: /usr/include/bits/wordsize.h resolvproto.o: resolvproto.h ipaddr.h /usr/include/stdint.h resolvproto.o: /usr/include/features.h /usr/include/sys/cdefs.h resolvproto.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h @@ -276,6 +282,10 @@ test_ipout.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h test_ipout.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h test_ipout.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h test_ipout.o: /usr/include/bits/msq.h +test_nameserver_file.o: nameserver.h ipaddr.h /usr/include/stdint.h +test_nameserver_file.o: /usr/include/features.h /usr/include/sys/cdefs.h +test_nameserver_file.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h +test_nameserver_file.o: /usr/include/bits/wordsize.h test_recv.o: devque.h dev.h /usr/include/unistd.h /usr/include/features.h test_recv.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h test_recv.o: /usr/include/bits/posix_opt.h /usr/include/bits/types.h diff --git a/practicas/pipi/src/nameserver.cpp b/practicas/pipi/src/nameserver.cpp new file mode 100644 index 0000000..2814427 --- /dev/null +++ b/practicas/pipi/src/nameserver.cpp @@ -0,0 +1,136 @@ +#include "nameserver.h" +#include +#include +#include +#ifdef DEBUG2 +#include +#endif + +static void parsename(const std::string& s, NameServer::name_t& name) +{ + std::istringstream iss(s); + std::string tok; + while (std::getline(iss, tok, '.')) + { + name.push_back(tok); + } +} + +static std::ostream& operator<< (std::ostream& os, const NameServer::name_t& name) +{ + if (name.empty()) + return os; + std::copy(name.begin(), name.end() - 1, + std::ostream_iterator< std::string >(os, ".")); + return os << name.back(); +} + +/// Parsea una zona +static std::istream& parsezone(std::istream& is, NameServer::Zone& z) + throw (std::runtime_error) +{ + std::string line, sname, ip; + // [dominio] [ttl] [parent ip] + while (std::getline(is, line) && (line == "")); // Salteo líneas en blanco + if (!is) + return is; + std::istringstream iss(line); + if (!(iss >> sname >> z.ttl >> ip)) + throw std::runtime_error("Error al parsear"); + parsename(sname, z.name); +#ifdef DEBUG2 + std::cerr << "parsezone: IP = " << ip << "\n\n"; +#endif + z.parent = IPAddr(ip); + // un record por linea, sin líneas vacías + // [name] [type] [ip] + while (std::getline(is, line) && (line != "")) + { + iss.clear(); + iss.str(line); + std::string key, type; + if (!(iss >> key >> type >> ip)) + throw std::runtime_error("Error al parsear"); + typedef NameServer::Record Rec; +#ifdef DEBUG2 + std::cerr << "parsezone: IP = " << ip << "\n\n"; +#endif + Rec r((type == "NS") ? Rec::NS : Rec::A, IPAddr(ip)); + z.records.insert(NameServer::Zone::records_t::value_type(key, r)); + } +#ifdef DEBUG2 + std::cerr << "parsezone: " << z << "\n\n"; +#endif + return is; +} + +/// Constructor +NameServer::Zone::Zone(std::string sname, size_t ttl, const IPAddr& parent): + ttl(ttl), parent(parent) +{ + parsename(sname, name); +} + +/// Constructor +NameServer::Zone::Zone(std::istream& is) + throw (std::runtime_error) +{ + // Parsea la zona + if (!parsezone(is, *this)) + throw std::runtime_error("Error de parser, no hay zona"); +} + +/// Limpia una zona +void NameServer::Zone::clear() +{ + name.clear(); + records.clear(); +} + +/// Constructor +NameServer::NameServer(std::istream& is) + throw (std::runtime_error) +{ + Zone z; + while (parsezone(is, z)) + { + zones.push_back(z); + z.clear(); +#ifdef DEBUG2 + std::cerr << "NameServer: " << z << "\n\n"; +#endif + } +} + +std::ostream& operator<< (std::ostream& os, const NameServer::Record& r) +{ + if (r.type == NameServer::Record::NS) + os << "NS "; + else + os << "A "; + return os << r.ip; +} + +std::ostream& operator<< (std::ostream& os, + const NameServer::Zone::records_t::value_type& p) +{ + return os << p.first << ": " << p.second; +} + +std::ostream& operator<< (std::ostream& os, const NameServer::Zone& z) +{ + os << "Zone " << z.name << " " << z.ttl << " " << z.parent << "\n"; + std::copy(z.records.begin(), z.records.end(), std::ostream_iterator< + NameServer::Zone::records_t::value_type >(os, "\n")); + return os; +} + +std::ostream& operator<< (std::ostream& os, const NameServer& ns) +{ + os << "NameServer: zones[" << ns.zones.size() << "] (\n\n"; + std::copy(ns.zones.begin(), ns.zones.end(), + std::ostream_iterator< NameServer::Zone >(os, "\n")); + return os << ")"; +} + +// vim: set et sw=4 sts=4 : diff --git a/practicas/pipi/src/nameserver.h b/practicas/pipi/src/nameserver.h new file mode 100644 index 0000000..686fb52 --- /dev/null +++ b/practicas/pipi/src/nameserver.h @@ -0,0 +1,70 @@ +#ifndef _NAMESERVER_H_ +#define _NAMESERVER_H_ + +#include "ipaddr.h" +//XXX#include "resolvproto.h" +#include +#include +#include +#include +#include +#include + +/// Petición del resolver a un nameserver +struct NameServer +{ + + /// Nombre de un dominio dividido en tokens + typedef std::vector< std::string > name_t; + + /// Registro de una zona + struct Record + { + /// Tipo de registro + enum type_t { A, NS }; + type_t type; + /// Dirección IP del registro + IPAddr ip; + /// Constructor + Record(type_t t, const IPAddr& i): type(t), ip(i) {} + }; + + /// Zona + struct Zone + { + /// Nombre + name_t name; + /// Time to live + size_t ttl; + /// Nodo padre + IPAddr parent; + /// Registros + typedef std::multimap< std::string, Record > records_t; + records_t records; + /// Constructores + Zone() {} + Zone(std::string sname, size_t ttl, const IPAddr& parent); + Zone(std::istream& is) throw (std::runtime_error); + /// Limpia una zona + void clear(); + }; + + //TODO cache de _records_ (no zonas) + + /// Zonas para las que este servidor de nombres es autoridad + typedef std::vector< Zone > zones_t; + zones_t zones; + + /// Constructor + NameServer(std::istream& is) throw (std::runtime_error); + +}; + +/// Impresión (para debug) +std::ostream& operator<< (std::ostream& os, const NameServer& ns); +std::ostream& operator<< (std::ostream& os, const NameServer::Record& r); +std::ostream& operator<< (std::ostream& os, const NameServer::Zone& z); + +#endif // _NAMESERVER_H_ + +// vim: set et sw=4 sts=4 : diff --git a/practicas/pipi/src/test_nameserver_file.cpp b/practicas/pipi/src/test_nameserver_file.cpp new file mode 100644 index 0000000..43a4215 --- /dev/null +++ b/practicas/pipi/src/test_nameserver_file.cpp @@ -0,0 +1,16 @@ + +#include "nameserver.h" +#include +#include +#include +#include + +int main(int argc, char* argv[]) +{ + std::ifstream ifs("test_nameserver_zones.txt"); + NameServer ns(ifs); + std::cout << ns << "\n"; + return 0; +} + +// vim: set et sw=4 sts=4 : diff --git a/practicas/pipi/src/test_nameserver_zones.txt b/practicas/pipi/src/test_nameserver_zones.txt new file mode 100644 index 0000000..4752260 --- /dev/null +++ b/practicas/pipi/src/test_nameserver_zones.txt @@ -0,0 +1,24 @@ +mi.super.nombre 600 10.10.10.1 +tito A 10.10.100.1 +juan A 10.10.100.2 +juan A 10.10.100.3 +pepe A 10.10.100.4 +juan A 10.10.100.5 +pepe A 10.10.100.6 +otro NS 10.10.100.100 +otro NS 10.10.100.101 +mas NS 10.10.200.1 +otro NS 10.10.200.2 + +mas.super.nombres 9500 10.10.1.100 +tito A 10.1.100.1 +juan A 10.1.100.2 +juan A 10.1.100.3 +pepe A 10.1.100.4 +juan A 10.1.100.5 +pepe A 10.1.100.6 +otro NS 10.1.100.100 +otro NS 10.1.100.101 +mas NS 10.1.200.1 +otro NS 10.1.200.2 + -- 2.43.0