12 IPOut::IPOut(const IPAddr& ip, RouteTable& rtable, Dev& forward_que, std::ostream& log):
13 ip(ip), rtable(rtable), forward_que(forward_que), log(log)
17 void IPOut::drop(const std::string& msg, const std::string& buf)
19 log << "IPOut::drop: " << msg << "\n\tBuffer: " << buf << "\n";
22 void IPOut::drop(const std::string& msg, const IPHeader& iph)
24 log << "IPOut::drop: " << msg << "\n\tIPHeader: " << iph << "\n";
27 /// Envía un paquete IP
28 bool IPOut::send(const std::string& data, uint8_t proto, IPAddr dst, IPAddr src,
29 bool df, uint8_t ttl, uint16_t id)
30 throw (std::runtime_error)
32 // Mando todo lo que tengo para forwardear
35 std::string buf = forward_que.receive();
38 log << "IPOut::send: A forwardear\n";
40 send(iph, buf.substr(iph.header_len()));
42 // Mando el paquete en sí
48 IPHeader iph(4, IPHeader::header_len() + data.size(), id, df, 0, 0,
49 ttl, proto, src, dst);
50 return send(iph, data);
53 /// Envía un paquete IP
54 bool IPOut::send(IPHeader iph, std::string data) throw (std::runtime_error)
57 RouteTable::Route* r = rtable.get(iph.dst);
60 drop("No existe una ruta para el destino", iph);
63 // No quieren fragmentar
64 if (iph.df && (IPHeader::header_len() + data.size() > r->iface->mtu))
66 drop("Tamaño de paquete más grande que MTU y DF=1", iph);
69 // Fragmenta (de ser necesario)
70 int max_payload = r->iface->mtu - IPHeader::header_len();
71 int cant_frag = data.size() / max_payload;
72 if (data.size() % max_payload)
74 for (int i = 0; i < cant_frag; ++i)
77 if (i != (cant_frag - 1))
79 iph2.offset += i * max_payload;
80 iph2.total_len -= i * max_payload;
82 std::string buf((char*) &iph2, sizeof(IPHeader));
83 buf += data.substr(i * max_payload, max_payload);
85 log << "IPOut::send: Fragmento 0 => IPHeader: " << iph2 << "\n";
86 std::string tmp = data.substr(i * max_payload, max_payload);
87 log << "\tdata (" << tmp.size() << ") = " << tmp << "\n";
89 r->iface->transmit(buf, r->gateway ? r->gateway : IPAddr(iph.dst));
94 /// Obtiene un identificador para el paquete
95 uint16_t IPOut::get_id() const
100 /// Se fija si hay paquetes a forwardear (y devuelve cuantos hay)
101 unsigned IPOut::to_forward()
103 struct msqid_ds minfo;
104 msgctl(forward_que.que_id, IPC_STAT, &minfo);
105 return minfo.msg_qnum;
108 // vim: set et sw=4 sts=4 :