--- /dev/null
+10.10.10.1 0.0.0.0 0
+10.10.10.2 0.0.0.0 0
+10.10.10.3 10.10.10.5 0
--- /dev/null
+10.10.10.1 0.0.0.0 0
+10.10.10.2 0.0.0.0 0
+10.10.10.3 10.10.10.5 0
+10.10.10.5 0.0.0.0 0
--- /dev/null
+10.10.10.1 0.0.0.0 0
+10.10.10.2 0.0.0.0 0
+10.10.10.3 10.10.10.5 0
+10.10.10.5 0.0.0.0 0
--- /dev/null
+10.10.10.1 10.10.10.5 0
+10.10.10.2 10.10.10.5 0
+10.10.10.3 0.0.0.0 0
+10.10.10.5 0.0.0.0 0
--- /dev/null
+10.10.10.1 0.0.0.0 0
+10.10.10.2 0.0.0.0 0
+10.10.10.3 0.0.0.0 0
+10.10.10.5 0.0.0.0 0
@makedepend $(fuentes) > /dev/null 2>&1
clean:
- @$(RM) -fv *.o $(targets)
+ @$(RM) -fv *.o Makefile.bak $(targets)
# DO NOT DELETE
ipout.o: /usr/include/features.h /usr/include/sys/cdefs.h
ipout.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h
ipout.o: /usr/include/bits/wordsize.h routetable.h dev.h
+ipout.o: /usr/include/unistd.h /usr/include/bits/posix_opt.h
+ipout.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+ipout.o: /usr/include/bits/confname.h /usr/include/getopt.h
+ipout.o: /usr/include/fcntl.h /usr/include/bits/fcntl.h
+ipout.o: /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h
+ipout.o: /usr/include/bits/endian.h /usr/include/sys/select.h
+ipout.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+ipout.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+ipout.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h
+ipout.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h
+ipout.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h
+ipout.o: /usr/include/bits/msq.h
routetable.o: routetable.h dev.h ipaddr.h
test_ipaddr.o: ipaddr.h ipheader.h /usr/include/stdint.h
test_ipaddr.o: /usr/include/features.h /usr/include/sys/cdefs.h
}
}
+/// Constructor
+//IPAddr::IPAddr(const std::string& ip) throw (std::logic_error)
+//{
+// IPAddr(ip.c_str());
+//}
+
/// Operador de casteo a unsigned
IPAddr::operator unsigned () const
{
/// Constructor
IPAddr(const char* ip) throw (std::logic_error);
+ /// Constructor
+ //IPAddr(const std::string& ip) throw (std::logic_error);
+
/// Operador de casteo a unsigned
operator unsigned () const;
#include "ipheader.h"
/// Constructor
-IPIn::IPIn(const IPAddr& ip, Dev& dev, std::ostream& log):
- ip(ip), dev(dev), log(log)
-{}
+IPIn::IPIn(const IPAddr& ip, Dev& dev, Dev& forward_que, bool router,
+ bool forward, std::ostream& log):
+ ip(ip), dev(dev), forward_que(forward_que), router(router),
+ forward(forward), log(log)
+{
+ if (router) forward = true;
+}
void IPIn::drop(const std::string& msg, const std::string& buf)
{
drop("Mal checksum", iph);
continue;
}
- //TODO forwarding (ponerlo en una cola para el proceso que manda)
- if (iph.dst != ip)
+ // No es para nosotros y no forwardeamos
+ if (iph.dst != ip && !forward)
{
drop("No es para nosotros y no hacemos forward", iph);
continue;
}
+ // No es para nosotros pero forwardeamos
+ else if (iph.dst != ip)
+ {
+ forward_que.transmit(buf, ip);
+ continue;
+ }
+ // Es para nosotros pero somos router
+ else if (router)
+ {
+ drop("Es para nosotros pero somos un router", iph);
+ continue;
+ }
+ // Es para nosotros y somos un host
// Guarda en buffer
buffer[iph][iph.offset] = buf.substr(iph.header_len());
// Si tiene más fragmentos o es un protocolo distinto, sigo
/// Dispositivo de red
Dev& dev;
+ /// Cola para forwardear paquetes
+ Dev& forward_que;
+
+ /// Indica si es un router
+ bool router;
+
+ /// Indica si hace forwarding
+ bool forward;
+
/// Dispositivo de logging
std::ostream& log;
buffer_type buffer;
/// Constructor
- IPIn(const IPAddr& ip, Dev& dev, std::ostream& log = std::cout);
+ IPIn(const IPAddr& ip, Dev& dev, Dev& forward_que, bool router = false,
+ bool forward = false, std::ostream& log = std::cout);
/// Descarta un paquete
void drop(const std::string& msg, const std::string& buf);
#include "ipout.h"
#include "ipheader.h"
#include <ctime>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
/// Constructor
-IPOut::IPOut(const IPAddr& ip, RouteTable& rtable, std::ostream& log):
- ip(ip), rtable(rtable), log(log)
+IPOut::IPOut(const IPAddr& ip, RouteTable& rtable, Dev& forward_que, std::ostream& log):
+ ip(ip), rtable(rtable), forward_que(forward_que), log(log)
{
}
bool df, uint8_t ttl, uint16_t id)
throw (std::runtime_error)
{
+ // Mando todo lo que tengo para forwardear
+ while (to_forward())
+ {
+ std::string buf = forward_que.receive();
+ IPHeader iph(buf);
+#ifdef DEBUG
+ log << "IPOut::send: A forwardear => IPHeader: " << iph << "\n";
+#endif
+ send(iph, buf.substr(iph.header_len()));
+ }
+ // Mando el paquete en sí
// Armamos cabecera
if (!src)
src = ip;
id = get_id();
IPHeader iph(4, IPHeader::header_len() + data.size(), id, df, 0, 0,
ttl, proto, src, dst);
+ return send(iph, data);
+}
+
+/// Envía un paquete IP
+bool IPOut::send(IPHeader iph, std::string data) throw (std::runtime_error)
+{
// Buscamos ruta
- RouteTable::Route* r = rtable.get(dst);
+ RouteTable::Route* r = rtable.get(iph.dst);
if (!r)
{
drop("No existe una ruta para el destino", iph);
return false;
}
// No quieren fragmentar
- if (df && (IPHeader::header_len() + data.size() > r->iface->mtu))
+ if (iph.df && (IPHeader::header_len() + data.size() > r->iface->mtu))
{
drop("Tamaño de paquete más grande que MTU y DF=1", iph);
return false;
log << "IPOut::send: Fragmento 0 => IPHeader: " << iph2 << "\n";
log << "\tbuf (" << buf.size() << ") = " << buf << "\n";
#endif
- r->iface->transmit(buf, r->gateway ? r->gateway : dst);
+ r->iface->transmit(buf, r->gateway ? r->gateway : IPAddr(iph.dst));
}
return true;
}
return time(NULL);
}
+/// Se fija si hay paquetes a forwardear (y devuelve cuantos hay)
+unsigned IPOut::to_forward()
+{
+ struct msqid_ds minfo;
+ msgctl(forward_que.que_id, IPC_STAT, &minfo);
+ return minfo.msg_qnum;
+}
+
// vim: set et sw=4 sts=4 :
/// Dispositivo de logging
RouteTable& rtable;
+ /// Cola para forwardear paquetes
+ Dev& forward_que;
+
/// Dispositivo de logging
std::ostream& log;
/// Constructor
- IPOut(const IPAddr& ip, RouteTable& rtable, std::ostream& log = std::cout);
+ IPOut(const IPAddr& ip, RouteTable& rtable, Dev& forward_que,
+ std::ostream& log = std::cout);
/// Descarta un paquete
void drop(const std::string& msg, const std::string& buf);
void drop(const std::string& msg, const IPHeader& iph);
- /// Envía un paquete IP
+ /// Envía un paquete IP a armar (y forwardea los encolados, de haber)
bool send(const std::string& data, uint8_t proto, IPAddr dst,
IPAddr src = 0, bool df = 0, uint8_t ttl = 64, uint16_t id = 0)
throw (std::runtime_error);
+ /// Envía un paquete IP ya armado
+ bool send(IPHeader iph, std::string data) throw (std::runtime_error);
+
/// Obtiene un identificador para el paquete
uint16_t get_id() const;
+ /// Se fija si hay paquetes a forwardear (y devuelve cuantos hay)
+ unsigned to_forward();
+
// Nada de andar copiando...
private:
IPOut(const IPOut&);
#include "routetable.h"
+#ifdef DEBUG
+#include <iostream>
+#endif
RouteTable::RouteTable(Dev& default_iface): default_iface(default_iface)
{
void RouteTable::add(const IPAddr& net, const IPAddr& gw, unsigned metric, Dev& iface)
{
table[net] = Route(gw, metric, iface);
+#ifdef DEBUG
+ std::cout << "Se agregó tabla para " << net << ": gw = " << gw
+ << ", metric = " << metric << "\n";
+#endif
}
void RouteTable::del(const IPAddr& net)
#include <sys/ipc.h>
#include <sys/msg.h>
-// Uso: ./test_ipin ip mtu proto queue_id
+// Uso: ./test_ipin ip mtu router forward proto queue_id
int main(int argc, char* argv[])
{
IPAddr addr("10.10.10.1");
unsigned mtu = 25;
+ bool router = false;
+ bool forward = false;
unsigned proto = 0;
key_t queue_id = DEV_DEFAULT_KEY;
if (argc > 1)
if (argc > 2)
mtu = atoi(argv[2]);
if (argc > 3)
- proto = atoi(argv[3]);
+ router = atoi(argv[3]);
if (argc > 4)
- queue_id = atoi(argv[4]);
+ forward = atoi(argv[4]);
+ if (argc > 5)
+ proto = atoi(argv[5]);
+ if (argc > 6)
+ queue_id = atoi(argv[6]);
Dev dev(addr, mtu, queue_id);
- IPIn ipin(addr, dev);
+ int que_id = msgget(queue_id+1, IPC_CREAT | 0666);
+ assert(que_id != -1);
+ Dev fwque(addr, mtu, queue_id+1);
+ IPIn ipin(addr, dev, fwque, router, forward);
struct msqid_ds minfo;
for (msgctl(dev.que_id, IPC_STAT, &minfo); minfo.msg_qnum;
msgctl(dev.que_id, IPC_STAT, &minfo))
#include "routetable.h"
#include "dev.h"
#include <iostream>
+#include <fstream>
+#include <sstream>
#include <string>
#include <cassert>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
-// Uso: ./test_ipout ip dst msg mtu proto queue_id
+// Uso: ./test_ipout ip dst mtu routes_file proto queue_id
+
+void add_routes(RouteTable& rt, std::istream& is, Dev& dev);
int main(int argc, char* argv[])
{
IPAddr addr("10.10.10.2");
IPAddr dst("10.10.10.1");
- std::string msg = "hola mundo";
unsigned mtu = 25;
unsigned proto = 0;
key_t queue_id = DEV_DEFAULT_KEY;
+ std::string fname = "route.txt";
if (argc > 1)
addr = IPAddr(argv[1]);
if (argc > 2)
dst = IPAddr(argv[2]);
if (argc > 3)
- msg = argv[3];
+ mtu = atoi(argv[3]);
if (argc > 4)
- mtu = atoi(argv[4]);
+ fname = argv[4];
if (argc > 5)
proto = atoi(argv[5]);
if (argc > 6)
queue_id = atoi(argv[6]);
- int que_id = msgget(queue_id, IPC_CREAT | 0666);
- assert(que_id != -1);
+ int que_id = msgget(queue_id, IPC_CREAT | 0666); assert(que_id != -1);
+ que_id = msgget(queue_id+1, IPC_CREAT | 0666); assert(que_id != -1);
+ std::ifstream ifs(fname.c_str()); assert(ifs);
Dev dev(addr, mtu, queue_id);
+ Dev fwque(addr, mtu, queue_id+1);
RouteTable table(dev);
- table.add("10.10.10.1", 0, 0, dev);
- table.add("10.10.10.2", 0, 0, dev);
- table.add("10.10.10.3", "10.10.10.10", 0, dev);
- IPOut ipout(addr, table);
- if (ipout.send(msg, proto, dst))
- std::cout << "Enviado '" << msg << "' a " << dst << "\n";
- else
- std::cout << "NO SE PUDO ENVIAR '" << msg << "' a " << dst << "\n";
+ add_routes(table, ifs, dev);
+ IPOut ipout(addr, table, fwque);
+ std::string msg;
+ while (std::getline(std::cin, msg))
+ {
+ if (ipout.send(msg, proto, dst))
+ std::cout << "Enviado '" << msg << "' a " << dst << "\n";
+ else
+ std::cout << "NO SE PUDO ENVIAR '" << msg << "' a " << dst << "\n";
+ }
return 0;
}
+void add_routes(RouteTable& rt, std::istream& is, Dev& dev)
+{
+ std::string line;
+ while (std::getline(is, line))
+ {
+ std::istringstream iss(line);
+ std::string net;
+ std::string gw;
+ unsigned metric;
+ iss >> net >> gw >> metric;
+ if (net == "0") net = "0.0.0.0";
+ if (gw == "0") gw = "0.0.0.0";
+ rt.add(net.c_str(), gw.c_str(), metric, dev);
+ }
+}
+
// vim: set et sw=4 sts=4 :