CC=g++
# Programas
-targets=test_send test_recv test_ipaddr
+targets=test_send test_recv test_ipaddr test_ipin
# Fuentes
fuentes ?= $(wildcard *.cpp)
test_recv: test_recv.o dev.o
-test_ipaddr: test_ipaddr.o ipaddr.o
+test_ipaddr: test_ipaddr.o ipaddr.o ipheader.o
+
+test_ipin: test_ipin.o ipin.o ipaddr.o ipheader.o dev.o
depend:
@makedepend $(fuentes) > /dev/null 2>&1
dev.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h
dev.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h /usr/include/bits/msq.h
ipaddr.o: ipaddr.h
-ipin.o: ipin.h dev.h
+ipheader.o: ipheader.h ipaddr.h /usr/include/stdint.h /usr/include/features.h
+ipheader.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h
+ipheader.o: /usr/include/bits/wchar.h /usr/include/bits/wordsize.h
+ipin.o: ipin.h ipaddr.h ipheader.h /usr/include/stdint.h
+ipin.o: /usr/include/features.h /usr/include/sys/cdefs.h
+ipin.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h
+ipin.o: /usr/include/bits/wordsize.h dev.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_ipaddr.o: /usr/include/bits/wordsize.h
+test_ipin.o: ipin.h ipaddr.h ipheader.h /usr/include/stdint.h
+test_ipin.o: /usr/include/features.h /usr/include/sys/cdefs.h
+test_ipin.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h
+test_ipin.o: /usr/include/bits/wordsize.h dev.h /usr/include/unistd.h
+test_ipin.o: /usr/include/bits/posix_opt.h /usr/include/bits/types.h
+test_ipin.o: /usr/include/bits/typesizes.h /usr/include/bits/confname.h
+test_ipin.o: /usr/include/getopt.h /usr/include/fcntl.h
+test_ipin.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h
+test_ipin.o: /usr/include/time.h /usr/include/endian.h
+test_ipin.o: /usr/include/bits/endian.h /usr/include/sys/select.h
+test_ipin.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+test_ipin.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+test_ipin.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h
+test_ipin.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h
+test_ipin.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h
+test_ipin.o: /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
#include "ipaddr.h"
#include <sstream>
+/// Constructor
+IPAddr::IPAddr()
+{
+ atoms[0] = 0;
+ atoms[1] = 0;
+ atoms[2] = 0;
+ atoms[3] = 0;
+}
+
/// Constructor
IPAddr::IPAddr(atom a1, atom a2, atom a3, atom a4)
{
/// Representación interna
atom atoms[4];
+ /// Constructor
+ IPAddr();
+
/// Constructor
IPAddr(atom a1, atom a2, atom a3, atom a4);
--- /dev/null
+#include "ipheader.h"
+
+IPHeader::IPHeader(uint8_t version, uint16_t total_len, uint16_t id, bool df,
+ bool mf, uint16_t offset, uint8_t ttl, uint8_t proto,
+ const IPAddr& src, const IPAddr& dst):
+ version(version), total_len(total_len), id(id), reserved_flag(0),
+ df(df), mf(mf), offset(offset), ttl(ttl), proto(proto), checksum(0),
+ src(src), dst(dst)
+{
+ do_checksum();
+}
+
+IPHeader::IPHeader(const std::string& s)
+{
+ *this = *((IPHeader*)s.c_str());
+}
+
+size_t IPHeader::header_len()
+{
+ return sizeof(IPHeader);
+}
+
+bool IPHeader::check_checksum() const
+{
+ IPHeader iph = *this;
+ iph.checksum = 0;
+ char* raw = (char*) &iph;
+ uint16_t sum = 0;
+ for (unsigned i = 0; i < sizeof(IPHeader); ++i)
+ sum += raw[i];
+ return sum == checksum;
+}
+
+void IPHeader::do_checksum()
+{
+ checksum = 0;
+ char* raw = (char*) this;
+ uint16_t sum = 0;
+ for (unsigned i = 0; i < sizeof(IPHeader); ++i)
+ sum += raw[i];
+ checksum = sum;
+}
+
+std::ostream& operator<<(std::ostream& os, const IPHeader& iph)
+{
+ return os
+ << "version=" << iph.version
+ << " total_len=" << iph.total_len
+ << " id=" << iph.id
+ << " DF=" << bool(iph.df)
+ << " MF=" << bool(iph.mf)
+ << " offset=" << unsigned(iph.offset)
+ << " TTL=" << unsigned(iph.ttl)
+ << " proto=" << unsigned(iph.proto)
+ << " checksum=" << iph.checksum
+ << " src=" << IPAddr(iph.src)
+ << " dst=" << IPAddr(iph.dst);
+}
+
+// vim: set et sw=4 sts=4 :
IPHeader(uint8_t version, uint16_t total_len, uint16_t id, bool df,
bool mf, uint16_t offset, uint8_t ttl, uint8_t proto,
- const IPAddr& src, const IPAddr& dst):
- version(version), total_len(total_len), id(id), reserved_flag(0),
- df(df), mf(mf), offset(offset), ttl(ttl), proto(proto), checksum(0),
- src(src), dst(dst)
- {
- do_checksum();
- }
+ const IPAddr& src, const IPAddr& dst);
- IPHeader(const std::string& s)
- {
- *this = *((IPHeader*)s.c_str());
- }
+ IPHeader(const std::string& s);
- bool check_checksum() const
- {
- IPHeader iph = *this;
- iph.checksum = 0;
- char* raw = (char*) &iph;
- uint16_t sum = 0;
- for (unsigned i = 0; i < sizeof(IPHeader); ++i)
- sum += raw[i];
- return sum == checksum;
- }
+ static size_t header_len();
- void do_checksum()
- {
- checksum = 0;
- char* raw = (char*) this;
- uint16_t sum = 0;
- for (unsigned i = 0; i < sizeof(IPHeader); ++i)
- sum += raw[i];
- checksum = sum;
- }
+ bool check_checksum() const;
+
+ void do_checksum();
};
-std::ostream& operator<<(std::ostream& os, const IPHeader& iph)
-{
- return os
- << "version=" << iph.version
- << " total_len=" << iph.total_len
- << " id=" << iph.id
- << " DF=" << bool(iph.df)
- << " MF=" << bool(iph.mf)
- << " offset=" << unsigned(iph.offset)
- << " TTL=" << unsigned(iph.ttl)
- << " proto=" << unsigned(iph.proto)
- << " checksum=" << iph.checksum
- << " src=" << IPAddr(iph.src)
- << " dst=" << IPAddr(iph.dst);
-}
+std::ostream& operator<<(std::ostream& os, const IPHeader& iph);
#endif // _IPHEADER_H_
--- /dev/null
+
+#include "ipin.h"
+#include "ipheader.h"
+
+/// Constructor
+IPIn::IPIn(const IPAddr& ip, Dev& dev, std::ostream& log):
+ ip(ip), dev(dev), log(log)
+{}
+
+void IPIn::drop(const std::string& msg, const std::string& buf)
+{
+ log << "IPIn::drop: " << msg << "\n\tBuffer: " << buf << "\n";
+}
+
+void IPIn::drop(const std::string& msg, const IPHeader& iph)
+{
+ log << "IPIn::drop: " << msg << "\n\tIPHeader: " << iph << "\n";
+}
+
+/// Recibe un paquete IP
+std::string IPIn::recv(uint8_t proto, IPAddr& src, IPAddr& dst) throw (std::runtime_error)
+{
+ while (true)
+ {
+ std::string buf = dev.receive();
+ // No es siquiera IP
+ if (buf.size() < IPHeader::header_len())
+ {
+ drop("Cabecera incompleta o no es IP", buf);
+ continue;
+ }
+ IPHeader iph(buf);
+#ifdef DEBUG
+ log << iph << "\n";
+#endif
+ if (iph.version != 4)
+ {
+ drop("Versión IP incorrecta", iph);
+ continue;
+ }
+ if (!iph.check_checksum())
+ {
+ drop("Mal checksum", iph);
+ continue;
+ }
+ // TODO forwarding (ponerlo en una cola para el proceso que manda)
+ if (iph.dst != ip)
+ {
+ drop("No es para nosotros y no hacemos forward", iph);
+ continue;
+ }
+ //TODO a un buffer
+ if (iph.proto != proto)
+ {
+ drop("No es el protocolo pedido", iph);
+ continue;
+ }
+ src = iph.src;
+ dst = iph.dst;
+ std::string data = buf.substr(iph.total_len - iph.header_len());
+ return data;
+ }
+}
+
+// vim: set et sw=4 sts=4 :
--- /dev/null
+#ifndef _IPIN_H_
+#define _IPIN_H_
+
+#include "ipaddr.h"
+#include "ipheader.h"
+#include "dev.h"
+#include <iostream>
+#include <string>
+#include <stdexcept>
+
+/// IP de recepción
+struct IPIn
+{
+
+ /// Dirección MAC
+ IPAddr ip;
+
+ /// Dispositivo de red
+ Dev& dev;
+
+ /// Dispositivo de logging
+ std::ostream& log;
+
+ /// Constructor
+ IPIn(const IPAddr& ip, Dev& dev, 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);
+
+ /// Recibe un paquete IP
+ std::string recv(uint8_t proto, IPAddr& src, IPAddr& dst)
+ throw (std::runtime_error);
+
+ // Nada de andar copiando placas...
+ private:
+ IPIn(const IPIn&);
+ IPIn& operator=(const IPIn&);
+
+};
+
+#endif // _IPIN_H_
+
+// vim: set et sw=4 sts=4 :
--- /dev/null
+
+#include "ipin.h"
+#include "ipaddr.h"
+#include <iostream>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+
+int main()
+{
+ Dev dev(4321);
+ IPIn ipin(IPAddr("10.10.10.1"), dev);
+ struct msqid_ds minfo;
+ for (msgctl(dev.que_id, IPC_STAT, &minfo); minfo.msg_qnum;
+ msgctl(dev.que_id, IPC_STAT, &minfo))
+ {
+ 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";
+ }
+ return 0;
+}
+
+// vim: set et sw=4 sts=4 :