#include "ipin.h"
#include "ipheader.h"
+#ifdef DEBUG
+#include <iostream>
+#endif
/// Constructor
-IPIn::IPIn(const IPAddr& ip, Dev& dev, std::ostream& log):
- ip(ip), dev(dev), log(log)
-{}
+IPIn::IPIn(const IPAddr& ip, Dev& dev, Dev& forward_que, bool router,
+ bool forward, std::ostream& log):
+ ip(ip), dev(dev), forward_que(forward_que), router(router),
+ forward(forward), log(log)
+{
+ if (router) forward = true;
+}
void IPIn::drop(const std::string& msg, const std::string& buf)
{
- log << "IPIn::drop: " << msg << "\n\tBuffer: " << buf << "\n";
+ log << "IPIn::drop (" << ip << "): " << msg << "\n\tBuffer: " << buf
+ << "\n";
}
void IPIn::drop(const std::string& msg, const IPHeader& iph)
{
- log << "IPIn::drop: " << msg << "\n\tIPHeader: " << iph << "\n";
+ log << "IPIn::drop (" << ip << "): " << msg << "\n\tIPHeader: " << iph
+ << "\n";
}
/// Recibe un paquete IP
-std::string IPIn::recv(uint8_t proto, IPAddr& src, IPAddr& dst) throw (std::runtime_error)
+std::string IPIn::recv(uint8_t& proto, IPAddr& src, IPAddr& dst)
+ throw (std::runtime_error)
{
while (true)
{
// No es siquiera IP
if (buf.size() < IPHeader::header_len())
{
+ // Silencioso
drop("Cabecera incompleta o no es IP", buf);
continue;
}
IPHeader iph(buf);
-#ifdef DEBUG
- log << iph << "\n";
+#ifdef DEBUG_IP
+ std::cout << "IPIn::recv (" << ip << "): IPHeader: " << iph << "\n";
+ std::string tmp = buf.substr(iph.header_len());
+ std::cout << "\tdata (" << tmp.size() << ") = " << tmp << "\n";
#endif
if (iph.version != 4)
{
+ // Silencioso
drop("Versión IP incorrecta", iph);
continue;
}
if (!iph.check_checksum())
{
+ // Silencioso
drop("Mal checksum", iph);
continue;
}
- // TODO forwarding (ponerlo en una cola para el proceso que manda)
- if (iph.dst != ip)
+ // Si el TTL se va a 0
+ if (!--iph.ttl)
+ {
+ // ICMP
+ drop("TTL == 0 -> ICMP", iph);
+ continue;
+ }
+ // No es para nosotros y no forwardeamos
+ if (iph.dst != ip && !forward)
{
+ // Silencioso
drop("No es para nosotros y no hacemos forward", iph);
continue;
}
- //TODO a un buffer
- if (iph.proto != proto)
+ // No es para nosotros pero forwardeamos
+ else if (iph.dst != ip)
{
- drop("No es el protocolo pedido", iph);
+ forward_que.transmit(buf, ip);
continue;
}
+ // Es para nosotros pero somos router
+ else if (router)
+ {
+ // Silencioso
+ drop("Es para nosotros pero somos un router", iph);
+ continue;
+ }
+ // Es para nosotros y somos un host
+ // Guarda en buffer
+ buffer[iph][iph.offset] = buf.substr(iph.header_len());
+ // Si tiene más fragmentos, sigo
+ if (iph.mf)
+ continue;
+ // No hay más fragmentos, reensamblamos (de ser necesario)
+ std::string data;
+ for (offsetmap_type::iterator i = buffer[iph].begin();
+ i != buffer[iph].end(); ++i)
+ {
+ //TODO chequear que los fragmentos estén todos
+ data += i->second;
+ }
+#ifdef DEBUG_IP
+ std::cout << "IPIn::recv (" << ip << "): Paquete completo: data = '"
+ << data << "'\n";
+#endif
+ buffer.erase(iph);
+ //TODO faltaría limpiar fragmentos viejos cada tanto (timer?)
src = iph.src;
dst = iph.dst;
- std::string data = buf.substr(iph.total_len - iph.header_len());
+ proto = iph.proto;
return data;
}
}