diff --git a/include/ip.h b/include/ip.h index 6756cf1..3225c18 100644 --- a/include/ip.h +++ b/include/ip.h @@ -5,15 +5,14 @@ #include #endif #include -#include #include "pdu.h" namespace Tins { class IP : public PDU { public: - IP(const std::string &ip_dst = "", const std::string &ip_src = ""); - IP(uint32_t ip_dst = 0, uint32_t ip_src = 0); + IP(const std::string &ip_dst = "", const std::string &ip_src = "", PDU *child = 0); + IP(uint32_t ip_dst = 0, uint32_t ip_src = 0, PDU *child = 0); inline uint8_t tos() const { return _ip.tos; } inline uint16_t tot_len() const { return _ip.tot_len; } @@ -63,6 +62,8 @@ namespace Tins { /*The options start here. */ } __attribute__((packed)); + static const uint8_t DEFAULT_TTL; + void init_ip_fields(); void write_serialization(uint8_t *buffer, uint32_t total_sz); diff --git a/include/packetsender.h b/include/packetsender.h index 11c9f4c..068736b 100644 --- a/include/packetsender.h +++ b/include/packetsender.h @@ -2,7 +2,7 @@ #define __PACKET_SENDER_H -#include +#include #include #include "pdu.h" @@ -11,6 +11,8 @@ namespace Tins { class PacketSender { public: + PacketSender(); + /* Opens a socket, using flag as protocol family. * Return true if it was possible to open it(or it was already open), * false otherwise. */ @@ -22,11 +24,13 @@ namespace Tins { bool send_l3(PDU *pdu, const struct sockaddr* link_addr, uint32_t len_link_addr); private: - typedef std::map SocketMap; + enum SocketType { + IP_SOCKET, + SOCKETS_END + }; + static const int INVALID_RAW_SOCKET = -10; - static const uint32_t IP_SOCKET; - - SocketMap _sockets; + std::vector _sockets; }; }; diff --git a/include/tcp.h b/include/tcp.h new file mode 100644 index 0000000..a7ee5fa --- /dev/null +++ b/include/tcp.h @@ -0,0 +1,93 @@ +#ifndef __TCP_H +#define __TCP_H + + +#include +#ifndef WIN32 + #include +#endif +#include "pdu.h" + +namespace Tins { + + class TCP : public PDU { + public: + enum Flags { + FIN, + SYN, + RST, + PSH, + ACK, + URG, + ECE, + CWR + }; + + TCP(uint16_t dport = 0, uint16_t sport = 0); + + inline uint16_t dport() const { return _tcp.dport; } + inline uint16_t sport() const { return _tcp.sport; } + inline uint32_t seq() const { return _tcp.seq; } + inline uint32_t ack_seq() const { return _tcp.ack_seq; } + inline uint16_t window() const { return _tcp.window; } + inline uint16_t check() const { return _tcp.check; } + inline uint16_t urg_ptr() const { return _tcp.urg_ptr; } + + void dport(uint16_t new_dport); + void sport(uint16_t new_sport); + void seq(uint32_t new_seq); + void ack_seq(uint32_t new_ack_seq); + void window(uint16_t new_window); + void check(uint16_t new_check); + void urg_ptr(uint16_t new_urg_ptr); + + void set_flag(Flags tcp_flag, uint8_t value); + + uint16_t do_checksum() const; + + /* Virtual methods */ + uint32_t header_size() const; + void write_serialization(uint8_t *buffer, uint32_t total_sz); + private: + struct tcphdr { + uint16_t sport; + uint16_t dport; + uint32_t seq; + uint32_t ack_seq; + #if __BYTE_ORDER == __LITTLE_ENDIAN + uint16_t res1:4, + doff:4, + fin:1, + syn:1, + rst:1, + psh:1, + ack:1, + urg:1, + ece:1, + cwr:1; + #elif __BYTE_ORDER == __BIG_ENDIAN + uint16_t doff:4, + res1:4, + cwr:1, + ece:1, + urg:1, + ack:1, + psh:1, + rst:1, + syn:1, + fin:1; + #else + #error "Endian is not LE nor BE..." + #endif + uint16_t window; + uint16_t check; + uint16_t urg_ptr; + } __attribute__((packed)); + + static const uint16_t DEFAULT_WINDOW; + + tcphdr _tcp; + }; +}; + +#endif diff --git a/include/utils.h b/include/utils.h index 4f44505..ae1b2ef 100644 --- a/include/utils.h +++ b/include/utils.h @@ -14,12 +14,13 @@ namespace Tins { uint32_t resolve_ip(const std::string &to_resolve); inline uint32_t net_to_host_l(uint32_t address) { - return (((address & 0xff000000) >> 24) | - ((address & 0x00ff0000) >> 8) | - ((address & 0x0000ff00) << 8) | - ((address & 0x000000ff) << 24)); + return (((address & 0xff000000) >> 24) | ((address & 0x00ff0000) >> 8) | + ((address & 0x0000ff00) << 8) | ((address & 0x000000ff) << 24)); } + inline uint32_t net_to_host_s(uint16_t address) { + return ((address & 0xff00) >> 8) | ((address & 0x00ff) << 8); + } }; }; diff --git a/src/ip.cpp b/src/ip.cpp index 6297999..35c254d 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -10,8 +10,9 @@ using namespace std; +const uint8_t Tins::IP::DEFAULT_TTL = 128; -Tins::IP::IP(const string &ip_dst, const string &ip_src) : PDU(IPPROTO_IP) { +Tins::IP::IP(const string &ip_dst, const string &ip_src, PDU *child) : PDU(IPPROTO_IP, child) { init_ip_fields(); if(ip_dst.size()) _ip.daddr = Utils::resolve_ip(ip_dst); @@ -20,7 +21,7 @@ Tins::IP::IP(const string &ip_dst, const string &ip_src) : PDU(IPPROTO_IP) { } -Tins::IP::IP(uint32_t ip_dst, uint32_t ip_src) : PDU(IPPROTO_IP) { +Tins::IP::IP(uint32_t ip_dst, uint32_t ip_src, PDU *child) : PDU(IPPROTO_IP, child) { init_ip_fields(); _ip.daddr = ip_dst; _ip.saddr = ip_src; @@ -30,7 +31,7 @@ void Tins::IP::init_ip_fields() { memset(&_ip, 0, sizeof(iphdr)); _ip.version = 4; _ip.ihl = sizeof(iphdr) / sizeof(uint32_t); - _ip.ttl = 128; + _ip.ttl = DEFAULT_TTL; } /* Setters */ diff --git a/src/packetsender.cpp b/src/packetsender.cpp index 0fba90a..04b4fb2 100644 --- a/src/packetsender.cpp +++ b/src/packetsender.cpp @@ -13,18 +13,18 @@ #include #include "packetsender.h" -const uint32_t Tins::PacketSender::IP_SOCKET = 0; + +Tins::PacketSender::PacketSender() : _sockets(SOCKETS_END, INVALID_RAW_SOCKET) { + +} bool Tins::PacketSender::open_l3_socket() { - if(_sockets.find(IP_SOCKET) != _sockets.end()) + if(_sockets[IP_SOCKET] != INVALID_RAW_SOCKET) return true; int sockfd; sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); - if (sockfd < 0) { - std::cout << "No se pudo abrir el fucking socket\n"; - std::cout << "Errno: " << errno << "\n"; + if (sockfd < 0) return false; - } const int on = 1; setsockopt(sockfd, IPPROTO_IP,IP_HDRINCL,(const void *)&on,sizeof(on)); @@ -34,11 +34,10 @@ bool Tins::PacketSender::open_l3_socket() { } bool Tins::PacketSender::close_socket(uint32_t flag) { - SocketMap::iterator it = _sockets.find(flag); - if(it == _sockets.end()) + if(flag >= SOCKETS_END || _sockets[flag] == INVALID_RAW_SOCKET) return false; - close(it->second); - _sockets.erase(it); + close(_sockets[flag]); + _sockets[flag] = INVALID_RAW_SOCKET; return true; } diff --git a/src/tcp.cpp b/src/tcp.cpp new file mode 100644 index 0000000..f599cff --- /dev/null +++ b/src/tcp.cpp @@ -0,0 +1,93 @@ +#include +#include +#ifndef WIN32 + #include +#endif +#include "tcp.h" +#include "utils.h" + + +const uint16_t Tins::TCP::DEFAULT_WINDOW = 32678; + +Tins::TCP::TCP(uint16_t dport, uint16_t sport) : PDU(IPPROTO_TCP) { + std::memset(&_tcp, 0, sizeof(tcphdr)); + _tcp.dport = Utils::net_to_host_s(dport); + _tcp.sport = Utils::net_to_host_s(sport); + _tcp.doff = sizeof(tcphdr) / sizeof(uint32_t); + _tcp.window = Utils::net_to_host_s(DEFAULT_WINDOW); +} + +void Tins::TCP::dport(uint16_t new_dport) { + _tcp.dport = Utils::net_to_host_s(new_dport); +} + +void Tins::TCP::sport(uint16_t new_sport) { + _tcp.sport = Utils::net_to_host_s(new_sport); +} + +void Tins::TCP::seq(uint32_t new_seq) { + _tcp.seq = new_seq; +} + +void Tins::TCP::ack_seq(uint32_t new_ack_seq) { + _tcp.ack_seq = new_ack_seq; +} + +void Tins::TCP::window(uint16_t new_window) { + _tcp.window = new_window; +} + +void Tins::TCP::check(uint16_t new_check) { + _tcp.check = new_check; +} + +void Tins::TCP::urg_ptr(uint16_t new_urg_ptr) { + _tcp.urg_ptr = new_urg_ptr; +} + +void Tins::TCP::set_flag(Flags tcp_flag, uint8_t value) { + switch(tcp_flag) { + case FIN: + _tcp.fin = value; + break; + case SYN: + _tcp.syn = value; + break; + case RST: + _tcp.rst = value; + break; + case PSH: + _tcp.psh = value; + break; + case ACK: + _tcp.ack = value; + break; + case URG: + _tcp.urg = value; + break; + case ECE: + _tcp.ece = value; + break; + case CWR: + _tcp.cwr = value; + break; + }; +} + +uint16_t Tins::TCP::do_checksum() const { + const uint8_t *ptr = (const uint8_t*)&_tcp, *end = (const uint8_t*)&_tcp + sizeof(tcphdr); + uint16_t checksum(0); + while(ptr < end) + checksum += *(ptr++); + return checksum; +} + +uint32_t Tins::TCP::header_size() const { + return sizeof(tcphdr); +} + +void Tins::TCP::write_serialization(uint8_t *buffer, uint32_t total_sz) { + assert(total_sz >= sizeof(tcphdr)); + _tcp.check = Utils::net_to_host_s(do_checksum()); + memcpy(buffer, &_tcp, sizeof(tcphdr)); +}