X-Git-Url: https://git.llucax.com/z.facultad/75.74/practicos.git/blobdiff_plain/51f24d14e8c4c52776a98c8e2aaacf95f90ad1f4..9ee7a97ec97d3dc41e1367f1f457d5ed5d5270ea:/practicas/pipi/src/ipout.cpp?ds=inline diff --git a/practicas/pipi/src/ipout.cpp b/practicas/pipi/src/ipout.cpp index d673f8d..84a3733 100644 --- a/practicas/pipi/src/ipout.cpp +++ b/practicas/pipi/src/ipout.cpp @@ -2,20 +2,31 @@ #include "ipout.h" #include "ipheader.h" #include +#include +#include +#include +#include +#include +#ifdef DEBUG +#include +#endif /// Constructor -IPOut::IPOut(const IPAddr& ip, Dev& dev, std::ostream& log): - ip(ip), dev(dev), log(log) -{} +IPOut::IPOut(const IPAddr& ip, RouteTable& rtable, Dev& forward_que, std::ostream& log): + ip(ip), rtable(rtable), forward_que(forward_que), log(log) +{ +} void IPOut::drop(const std::string& msg, const std::string& buf) { - log << "IPOut::drop: " << msg << "\n\tBuffer: " << buf << "\n"; + log << "IPOut::drop (" << ip << "): " << msg << "\n\tBuffer: " << buf + << "\n"; } void IPOut::drop(const std::string& msg, const IPHeader& iph) { - log << "IPOut::drop: " << msg << "\n\tIPHeader: " << iph << "\n"; + log << "IPOut::drop (" << ip << "): " << msg << "\n\tIPHeader: " << iph + << "\n"; } /// Envía un paquete IP @@ -23,20 +34,37 @@ bool IPOut::send(const std::string& data, uint8_t proto, IPAddr dst, IPAddr src, bool df, uint8_t ttl, uint16_t id) throw (std::runtime_error) { - // No quieren fragmentar - if (df && (IPHeader::header_len() + data.size() > dev.mtu)) - { - drop("Tamaño de paquete más grande que MTU y DF=1", data); - return false; - } + // Armamos cabecera if (!src) src = ip; if (!id) id = get_id(); IPHeader iph(4, IPHeader::header_len() + data.size(), id, df, 0, 0, ttl, proto, src, dst); + // Enviamos + return send(iph, data); +} + +/// Envía un paquete IP +bool IPOut::send(IPHeader iph, std::string data) throw (std::runtime_error) +{ + // Buscamos ruta + RouteTable::Route* r = rtable.get(iph.dst); + if (!r) + { + // ICMP + drop("No existe una ruta para el destino -> ICMP", iph); + return false; + } + // No quieren fragmentar + if (iph.df && (IPHeader::header_len() + data.size() > r->mtu)) + { + // Silencioso + drop("Tamaño de paquete más grande que MTU y DF=1", iph); + return false; + } // Fragmenta (de ser necesario) - int max_payload = dev.mtu - IPHeader::header_len(); + int max_payload = r->mtu - IPHeader::header_len(); int cant_frag = data.size() / max_payload; if (data.size() % max_payload) ++cant_frag; @@ -51,18 +79,38 @@ bool IPOut::send(const std::string& data, uint8_t proto, IPAddr dst, IPAddr src, std::string buf((char*) &iph2, sizeof(IPHeader)); buf += data.substr(i * max_payload, max_payload); #ifdef DEBUG - log << "IPOut::send: Fragmento 0 => IPHeader: " << iph2 << "\n"; - log << "\tbuf (" << buf.size() << ") = " << buf << "\n"; + std::cout << "IPOut::send (" << ip << "): Fragmento " << i + << " => IPHeader: " << iph2 << "\n"; + std::string tmp = data.substr(i * max_payload, max_payload); + std::cout << "\tdata (" << tmp.size() << ") = " << tmp << "\n"; #endif - dev.transmit(buf, dst); + r->iface->transmit(buf, r->gateway ? r->gateway : IPAddr(iph.dst)); } return true; } +/// Realiza el forwarding de paquetes (en un loop infinito) +void IPOut::forward_loop() + throw (std::runtime_error) +{ + while (true) + { + std::string buf = forward_que.receive(); + IPHeader iph(buf); +#ifdef DEBUG + std::cout << "IPOut::forward_loop (" << ip << "): A forwardear (id " + << iph.id << ", offset " << iph.offset << ")\n"; +#endif + send(iph, buf.substr(iph.header_len())); + } +} + /// Obtiene un identificador para el paquete uint16_t IPOut::get_id() const { - return time(NULL); + static uint16_t st = time(NULL); + uint16_t tt = time(NULL); + return (tt == st) ? ++st : tt; } // vim: set et sw=4 sts=4 :