]> git.llucax.com Git - z.facultad/75.74/practicos.git/blobdiff - practicas/pipi/src/ipout.cpp
Ya estamos fragmentando! (falta testing intensivo pero parece andar)
[z.facultad/75.74/practicos.git] / practicas / pipi / src / ipout.cpp
index fb60ffd02ba32907187b253e46e29c679b6612d8..d673f8d133cb6c566b6c7f89bcd245a853d8c01e 100644 (file)
@@ -23,10 +23,10 @@ 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)
@@ -35,13 +35,27 @@ bool IPOut::send(const std::string& data, uint8_t proto, IPAddr dst, IPAddr src,
         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;
 }