15 IPOut::IPOut(const IPAddr& ip, RouteTable& rtable, Dev& forward_que, std::ostream& log):
16 ip(ip), rtable(rtable), forward_que(forward_que), log(log)
20 void IPOut::drop(const std::string& msg, const std::string& buf)
22 log << "IPOut::drop (" << ip << "): " << msg << "\n\tBuffer: " << buf
26 void IPOut::drop(const std::string& msg, const IPHeader& iph)
28 log << "IPOut::drop (" << ip << "): " << msg << "\n\tIPHeader: " << iph
32 /// Envía un paquete IP
33 bool IPOut::send(const std::string& data, uint8_t proto, IPAddr dst, IPAddr src,
34 bool df, uint8_t ttl, uint16_t id)
35 throw (std::runtime_error)
42 IPHeader iph(4, IPHeader::header_len() + data.size(), id, df, 0, 0,
43 ttl, proto, src, dst);
45 return send(iph, data);
48 /// Envía un paquete IP
49 bool IPOut::send(IPHeader iph, std::string data) throw (std::runtime_error)
52 RouteTable::Route* r = rtable.get(iph.dst);
56 drop("No existe una ruta para el destino -> ICMP", iph);
59 // No quieren fragmentar
60 if (iph.df && (IPHeader::header_len() + data.size() > r->mtu))
63 drop("Tamaño de paquete más grande que MTU y DF=1", iph);
66 // Fragmenta (de ser necesario)
67 int max_payload = r->mtu - IPHeader::header_len();
68 int cant_frag = data.size() / max_payload;
69 if (data.size() % max_payload)
71 for (int i = 0; i < cant_frag; ++i)
74 if (i != (cant_frag - 1))
76 iph2.offset += i * max_payload;
77 iph2.total_len -= i * max_payload;
79 std::string buf((char*) &iph2, sizeof(IPHeader));
80 buf += data.substr(i * max_payload, max_payload);
82 std::cout << "IPOut::send (" << ip << "): Fragmento " << i
83 << " => IPHeader: " << iph2 << "\n";
84 std::string tmp = data.substr(i * max_payload, max_payload);
85 std::cout << "\tdata (" << tmp.size() << ") = " << tmp << "\n";
87 r->iface->transmit(buf, r->gateway ? r->gateway : IPAddr(iph.dst));
92 /// Realiza el forwarding de paquetes (en un loop infinito)
93 void IPOut::forward_loop()
94 throw (std::runtime_error)
98 std::string buf = forward_que.receive();
101 std::cout << "IPOut::forward_loop (" << ip << "): A forwardear (id "
102 << iph.id << ", offset " << iph.offset << ")\n";
104 send(iph, buf.substr(iph.header_len()));
108 /// Obtiene un identificador para el paquete
109 uint16_t IPOut::get_id() const
111 static uint16_t st = time(NULL);
112 uint16_t tt = time(NULL);
113 return (tt == st) ? ++st : tt;
116 // vim: set et sw=4 sts=4 :