cambiar algunas cosas via línea de comandos.
test_ipin: test_ipin.o ipin.o ipaddr.o ipheader.o dev.o
-test_ipout: test_ipout.o ipout.o ipaddr.o ipheader.o dev.o
+test_ipout: test_ipout.o ipout.o ipaddr.o ipheader.o dev.o routetable.o
depend:
@makedepend $(fuentes) > /dev/null 2>&1
ipout.o: ipout.h ipaddr.h ipheader.h /usr/include/stdint.h
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 dev.h
+ipout.o: /usr/include/bits/wordsize.h routetable.h dev.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
test_ipaddr.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h
test_ipout.o: ipout.h ipaddr.h ipheader.h /usr/include/stdint.h
test_ipout.o: /usr/include/features.h /usr/include/sys/cdefs.h
test_ipout.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h
-test_ipout.o: /usr/include/bits/wordsize.h dev.h /usr/include/unistd.h
-test_ipout.o: /usr/include/bits/posix_opt.h /usr/include/bits/types.h
-test_ipout.o: /usr/include/bits/typesizes.h /usr/include/bits/confname.h
-test_ipout.o: /usr/include/getopt.h /usr/include/fcntl.h
-test_ipout.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h
-test_ipout.o: /usr/include/time.h /usr/include/endian.h
-test_ipout.o: /usr/include/bits/endian.h /usr/include/sys/select.h
-test_ipout.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
-test_ipout.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
-test_ipout.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h
-test_ipout.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h
-test_ipout.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h
-test_ipout.o: /usr/include/bits/msq.h
+test_ipout.o: /usr/include/bits/wordsize.h routetable.h dev.h
+test_ipout.o: /usr/include/unistd.h /usr/include/bits/posix_opt.h
+test_ipout.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+test_ipout.o: /usr/include/bits/confname.h /usr/include/getopt.h
+test_ipout.o: /usr/include/fcntl.h /usr/include/bits/fcntl.h
+test_ipout.o: /usr/include/sys/types.h /usr/include/time.h
+test_ipout.o: /usr/include/endian.h /usr/include/bits/endian.h
+test_ipout.o: /usr/include/sys/select.h /usr/include/bits/select.h
+test_ipout.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+test_ipout.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+test_ipout.o: /usr/include/bits/sched.h /usr/include/sys/ipc.h
+test_ipout.o: /usr/include/bits/ipctypes.h /usr/include/bits/ipc.h
+test_ipout.o: /usr/include/sys/msg.h /usr/include/bits/msq.h
test_recv.o: dev.h /usr/include/unistd.h /usr/include/features.h
test_recv.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h
test_recv.o: /usr/include/bits/posix_opt.h /usr/include/bits/types.h
}
/// Constructor
-IPAddr::IPAddr(unsigned ip)
+IPAddr::IPAddr(int ip)
{
atoms[0] = ip >> 24;
atoms[1] = ip >> 16;
}
/// Constructor
-IPAddr::IPAddr(std::string ip) throw (std::logic_error)
+IPAddr::IPAddr(const char* ip) throw (std::logic_error)
{
std::istringstream iss(ip);
+ std::string ips;
for (int i = 0; i < 4; ++i)
{
- if (!std::getline(iss, ip, '.'))
+ if (!std::getline(iss, ips, '.'))
throw std::logic_error("Dirección IP inválida");
- atoms[i] = std::atoi(ip.c_str());
+ atoms[i] = std::atoi(ips.c_str());
}
}
IPAddr(atom a1, atom a2, atom a3, atom a4);
/// Constructor
- IPAddr(unsigned ip);
+ IPAddr(int ip);
/// Constructor
- IPAddr(std::string ip) throw (std::logic_error);
+ IPAddr(const char* ip) throw (std::logic_error);
/// Operador de casteo a unsigned
operator unsigned () const;
#include <ctime>
/// Constructor
-IPOut::IPOut(const IPAddr& ip, Dev& dev, std::ostream& log):
- ip(ip), dev(dev), log(log)
-{}
+IPOut::IPOut(const IPAddr& ip, RouteTable& rtable, std::ostream& log):
+ ip(ip), rtable(rtable), log(log)
+{
+}
void IPOut::drop(const std::string& msg, const std::string& buf)
{
bool df, uint8_t ttl, uint16_t id)
throw (std::runtime_error)
{
- // No quieren fragmentar
- if (df && (IPHeader::header_len() + data.size() > dev.mtu))
- {
- drop("Tamaño de paquete más grande que MTU y DF=1", data);
- return false;
- }
+ // Armamos cabecera
if (!src)
src = ip;
if (!id)
id = get_id();
IPHeader iph(4, IPHeader::header_len() + data.size(), id, df, 0, 0,
ttl, proto, src, dst);
+ // Buscamos ruta
+ RouteTable::Route* r = rtable.get(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))
+ {
+ drop("Tamaño de paquete más grande que MTU y DF=1", iph);
+ return false;
+ }
// Fragmenta (de ser necesario)
- int max_payload = dev.mtu - IPHeader::header_len();
+ int max_payload = r->iface->mtu - IPHeader::header_len();
int cant_frag = data.size() / max_payload;
if (data.size() % max_payload)
++cant_frag;
log << "IPOut::send: Fragmento 0 => IPHeader: " << iph2 << "\n";
log << "\tbuf (" << buf.size() << ") = " << buf << "\n";
#endif
- dev.transmit(buf, dst);
+ r->iface->transmit(buf, r->gateway ? r->gateway : dst);
}
return true;
}
#include "ipaddr.h"
#include "ipheader.h"
-#include "dev.h"
+#include "routetable.h"
#include <iostream>
#include <string>
#include <stdexcept>
/// Dirección MAC
IPAddr ip;
- /// Dispositivo de red
- Dev& dev;
+ /// Dispositivo de logging
+ RouteTable& rtable;
/// Dispositivo de logging
std::ostream& log;
/// Constructor
- IPOut(const IPAddr& ip, Dev& dev, std::ostream& log = std::cout);
+ IPOut(const IPAddr& ip, RouteTable& rtable, std::ostream& log = std::cout);
/// Descarta un paquete
void drop(const std::string& msg, const std::string& buf);
--- /dev/null
+#include "routetable.h"
+
+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);
+}
+
+void RouteTable::del(const IPAddr& net)
+{
+ table.erase(net);
+}
+
+RouteTable::Route* RouteTable::get(const IPAddr& dst)
+{
+ // No existe
+ if (table.find(dst) == table.end())
+ return 0;
+ return &table[dst];
+}
+
+// vim: set et sw=4 sts=4 :
--- /dev/null
+#ifndef _ROUTETABLE_H_
+#define _ROUTETABLE_H_
+
+#include "dev.h"
+#include "ipaddr.h"
+#include <map>
+
+/// Tabla de ruteo
+struct RouteTable
+{
+
+ /// Ruta
+ struct Route
+ {
+ IPAddr gateway;
+ unsigned metric;
+ Dev* iface;
+ Route(): gateway(0), metric(0), iface(0) {}
+ Route(const IPAddr& gateway, unsigned metric, Dev& iface):
+ gateway(gateway), metric(metric), iface(&iface) {}
+ };
+
+ /// Tabla
+ std::map< IPAddr, Route > table;
+
+ /// Interfaz por default
+ Dev& default_iface;
+
+ /// Constructor
+ RouteTable(Dev& default_iface);
+
+ /// Agrega ruta
+ void add(const IPAddr& net, const IPAddr& gw, unsigned metric, Dev& iface);
+
+ /// Borra ruta
+ void del(const IPAddr& net);
+
+ /// Obtiene dirección e interfaz por la cual salir para un destino
+ Route* get(const IPAddr& dst);
+
+};
+
+#endif // _ROUTETABLE_H_
+
+// vim: set et sw=4 sts=4 :
#include "ipaddr.h"
#include "dev.h"
#include <iostream>
+#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
-int main()
+// Uso: ./test_ipin ip mtu proto queue_id
+
+int main(int argc, char* argv[])
{
IPAddr addr("10.10.10.1");
- Dev dev(addr);
+ unsigned mtu = 25;
+ unsigned proto = 0;
+ key_t queue_id = DEV_DEFAULT_KEY;
+ if (argc > 1)
+ addr = IPAddr(argv[1]);
+ if (argc > 2)
+ mtu = atoi(argv[2]);
+ if (argc > 3)
+ proto = atoi(argv[3]);
+ if (argc > 4)
+ queue_id = atoi(argv[4]);
+ Dev dev(addr, mtu, queue_id);
IPIn ipin(addr, dev);
struct msqid_ds minfo;
for (msgctl(dev.que_id, IPC_STAT, &minfo); minfo.msg_qnum;
{
IPAddr src, dst;
std::cout << "Quedan " << minfo.msg_qnum << " mensajes en la cola\n";
- std::string s = ipin.recv(0, src, dst);
- std::cout << "Recibido '" << s << "' (len " << s.size() << ")\n";
+ std::string s = ipin.recv(proto, src, dst);
+ std::cout << "Recibido '" << s << "' (len " << s.size() << ") de "
+ << src << " para " << dst << " (proto = " << proto << ")\n";
}
return 0;
}
#include "ipout.h"
#include "ipaddr.h"
+#include "routetable.h"
#include "dev.h"
#include <iostream>
+#include <string>
#include <cassert>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/msg.h>
-int main()
+// Uso: ./test_ipout ip dst msg mtu proto queue_id
+
+int main(int argc, char* argv[])
{
- int que_id = msgget(DEV_DEFAULT_KEY, IPC_CREAT | 0666);
- assert(que_id != -1);
IPAddr addr("10.10.10.2");
- Dev dev(addr, 25);
- IPOut ipout(addr, dev);
- if (ipout.send("hola mundo", 0, IPAddr("10.10.10.1")))
- std::cout << "Enviado 'hola mundo' a 10.10.10.1\n";
+ IPAddr dst("10.10.10.1");
+ std::string msg = "hola mundo";
+ unsigned mtu = 25;
+ unsigned proto = 0;
+ key_t queue_id = DEV_DEFAULT_KEY;
+ if (argc > 1)
+ addr = IPAddr(argv[1]);
+ if (argc > 2)
+ dst = IPAddr(argv[2]);
+ if (argc > 3)
+ msg = argv[3];
+ if (argc > 4)
+ mtu = atoi(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);
+ Dev dev(addr, mtu, queue_id);
+ 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 'hola mundo' a 10.10.10.1\n";
+ std::cout << "NO SE PUDO ENVIAR '" << msg << "' a " << dst << "\n";
return 0;
}