+ 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->iface->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 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);