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