#include "ipout.h"
#include "ipheader.h"
#include <ctime>
+#include <unistd.h>
+#include <fcntl.h>
+#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, std::ostream& log):
- ip(ip), rtable(rtable), 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)
{
}
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
+ std::cout << "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);
+ 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(dst);
+ RouteTable::Route* r = rtable.get(iph.dst);
if (!r)
{
drop("No existe una ruta para el destino", iph);
return false;
}
// No quieren fragmentar
- if (df && (IPHeader::header_len() + data.size() > r->iface->mtu))
+ if (iph.df && (IPHeader::header_len() + data.size() > r->iface->mtu))
{
drop("Tamaño de paquete más grande que MTU y DF=1", iph);
return false;
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: Fragmento 0 => IPHeader: " << iph2 << "\n";
+ std::string tmp = data.substr(i * max_payload, max_payload);
+ std::cout << "\tdata (" << tmp.size() << ") = " << tmp << "\n";
#endif
- r->iface->transmit(buf, r->gateway ? r->gateway : dst);
+ r->iface->transmit(buf, r->gateway ? r->gateway : IPAddr(iph.dst));
}
return true;
}
return time(NULL);
}
+/// Se fija si hay paquetes a forwardear (y devuelve cuantos hay)
+unsigned IPOut::to_forward()
+{
+ struct msqid_ds minfo;
+ msgctl(forward_que.que_id, IPC_STAT, &minfo);
+ return minfo.msg_qnum;
+}
+
// vim: set et sw=4 sts=4 :