]> git.llucax.com Git - z.facultad/75.74/practicos.git/blob - practicas/pipi/src/ipin.cpp
55bc85626cf086b438b1c4b7cd1a8e591a268b06
[z.facultad/75.74/practicos.git] / practicas / pipi / src / ipin.cpp
1
2 #include "ipin.h"
3 #include "ipheader.h"
4
5 /// Constructor
6 IPIn::IPIn(const IPAddr& ip, Dev& dev, Dev& forward_que, bool router,
7         bool forward, std::ostream& log):
8     ip(ip), dev(dev), forward_que(forward_que), router(router),
9     forward(forward), log(log)
10 {
11     if (router) forward = true;
12 }
13
14 void IPIn::drop(const std::string& msg, const std::string& buf)
15 {
16     log << "IPIn::drop: " << msg << "\n\tBuffer: " << buf << "\n";
17 }
18
19 void IPIn::drop(const std::string& msg, const IPHeader& iph)
20 {
21     log << "IPIn::drop: " << msg << "\n\tIPHeader: " << iph << "\n";
22 }
23
24 /// Recibe un paquete IP
25 std::string IPIn::recv(uint8_t proto, IPAddr& src, IPAddr& dst) throw (std::runtime_error)
26 {
27     while (true)
28     {
29         std::string buf = dev.receive();
30         // No es siquiera IP
31         if (buf.size() < IPHeader::header_len())
32         {
33             drop("Cabecera incompleta o no es IP", buf);
34             continue;
35         }
36         IPHeader iph(buf);
37 #ifdef DEBUG
38         log << "IPIn::recv: IPHeader: " << iph << "\n";
39         std::string tmp = buf.substr(iph.header_len());
40         log << "\tdata (" << tmp.size() << ") = " << tmp << "\n";
41 #endif
42         if (iph.version != 4)
43         {
44             drop("Versión IP incorrecta", iph);
45             continue;
46         }
47         if (!iph.check_checksum())
48         {
49             drop("Mal checksum", iph);
50             continue;
51         }
52         // No es para nosotros y no forwardeamos
53         if (iph.dst != ip && !forward)
54         {
55             drop("No es para nosotros y no hacemos forward", iph);
56             continue;
57         }
58         // No es para nosotros pero forwardeamos
59         else if (iph.dst != ip)
60         {
61             forward_que.transmit(buf, ip);
62             continue;
63         }
64         // Es para nosotros pero somos router
65         else if (router)
66         {
67             drop("Es para nosotros pero somos un router", iph);
68             continue;
69         }
70         // Es para nosotros y somos un host
71         // Guarda en buffer
72         buffer[iph][iph.offset] = buf.substr(iph.header_len());
73         // Si tiene más fragmentos o es un protocolo distinto, sigo
74         if (iph.mf || (iph.proto != proto))
75             continue;
76         // No hay más fragmentos, reensamblamos (de ser necesario)
77         std::string data;
78         for (offsetmap_type::iterator i = buffer[iph].begin();
79                 i != buffer[iph].end(); ++i)
80         {
81             //TODO chequear que los fragmentos estén todos
82             data += i->second;
83         }
84 #ifdef DEBUG
85         log << "IPIn::recv: Paquete completo: data = '" << data << "'\n";
86 #endif
87         buffer.erase(iph);
88         //TODO faltaría limpiar fragmentos viejos cada tanto (timer?)
89         src = iph.src;
90         dst = iph.dst;
91         return data;
92     }
93 }
94
95 // vim: set et sw=4 sts=4 :