#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
+#ifdef DEBUG
+#include <iostream>
+#endif
/// Constructor
IPOut::IPOut(const IPAddr& ip, RouteTable& rtable, Dev& forward_que, std::ostream& 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
bool df, uint8_t ttl, uint16_t id)
throw (std::runtime_error)
{
- // Mando todo lo que tengo para forwardear
- while (to_forward())
- {
- std::string buf = forward_que.receive();
- IPHeader iph(buf);
-#ifdef DEBUG
- log << "IPOut::send: A forwardear\n";
-#endif
- send(iph, buf.substr(iph.header_len()));
- }
- // Mando el paquete en sí
// Armamos cabecera
if (!src)
src = ip;
id = get_id();
IPHeader iph(4, IPHeader::header_len() + data.size(), id, df, 0, 0,
ttl, proto, src, dst);
+ // Enviamos
return send(iph, data);
}
RouteTable::Route* r = rtable.get(iph.dst);
if (!r)
{
- drop("No existe una ruta para el destino", iph);
+ // 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->iface->mtu))
+ 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 = r->iface->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;
iph2.do_checksum();
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";
+#ifdef DEBUG_IP
+ std::cout << "IPOut::send (" << ip << "): Fragmento " << i
+ << " => IPHeader: " << iph2 << "\n";
std::string tmp = data.substr(i * max_payload, max_payload);
- log << "\tdata (" << tmp.size() << ") = " << tmp << "\n";
+ std::cout << "\tdata (" << tmp.size() << ") = " << tmp << "\n";
#endif
r->iface->transmit(buf, r->gateway ? r->gateway : IPAddr(iph.dst));
}
return true;
}
-/// Obtiene un identificador para el paquete
-uint16_t IPOut::get_id() const
+/// Realiza el forwarding de paquetes (en un loop infinito)
+void IPOut::forward_loop()
+ throw (std::runtime_error)
{
- return time(NULL);
+ while (true)
+ {
+ std::string buf = forward_que.receive();
+ IPHeader iph(buf);
+#ifdef DEBUG_IP
+ std::cout << "IPOut::forward_loop (" << ip << "): A forwardear (id "
+ << iph.id << ", offset " << iph.offset << ")\n";
+#endif
+ send(iph, buf.substr(iph.header_len()));
+ }
}
-/// Se fija si hay paquetes a forwardear (y devuelve cuantos hay)
-unsigned IPOut::to_forward()
+/// Obtiene un identificador para el paquete
+uint16_t IPOut::get_id() const
{
- struct msqid_ds minfo;
- msgctl(forward_que.que_id, IPC_STAT, &minfo);
- return minfo.msg_qnum;
+ static uint16_t st = time(NULL);
+ uint16_t tt = time(NULL);
+ return (tt == st) ? ++st : tt;
}
// vim: set et sw=4 sts=4 :