#include "ipout.h"
#include "ipheader.h"
+#include <ctime>
/// Constructor
IPOut::IPOut(const IPAddr& ip, Dev& dev, std::ostream& log):
}
/// Envía un paquete IP
-bool IPOut::send(const std::string& data, IPAddr& src, IPAddr& dst,
- uint8_t proto, bool df, uint8_t ttl, uint16_t id)
+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)
{
- // TODO fragmentar
- if (IPHeader::header_len() + data.size() > dev.mtu)
+ // No quieren fragmentar
+ if (df && (IPHeader::header_len() + data.size() > dev.mtu))
{
- drop("Tamaño de paquete más grande que MTU", data);
+ drop("Tamaño de paquete más grande que MTU y DF=1", data);
return false;
}
+ 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);
- std::string buf((char*) &iph, sizeof(IPHeader));
- buf += data;
+ // Fragmenta (de ser necesario)
+ int max_payload = dev.mtu - IPHeader::header_len();
+ int cant_frag = data.size() / max_payload;
+ if (data.size() % max_payload)
+ ++cant_frag;
+ for (int i = 0; i < cant_frag; ++i)
+ {
+ IPHeader iph2 = iph;
+ if (i != (cant_frag - 1))
+ iph2.mf = 1;
+ iph2.offset += i * max_payload;
+ iph2.total_len -= i * max_payload;
+ iph2.do_checksum();
+ std::string buf((char*) &iph2, sizeof(IPHeader));
+ buf += data.substr(i * max_payload, max_payload);
#ifdef DEBUG
- log << "IPOut::send: IPHeader: " << iph << "\n";
- log << "IPOut::send: buf = " << buf << "\n";
+ log << "IPOut::send: Fragmento 0 => IPHeader: " << iph2 << "\n";
+ log << "\tbuf (" << buf.size() << ") = " << buf << "\n";
#endif
- dev.transmit(buf, dst /*TODO rutear */);
+ dev.transmit(buf, dst);
+ }
return true;
}
+/// Obtiene un identificador para el paquete
+uint16_t IPOut::get_id() const
+{
+ return time(NULL);
+}
+
// vim: set et sw=4 sts=4 :