diff --git a/include/ip.h b/include/ip.h index 842e90c..6756cf1 100644 --- a/include/ip.h +++ b/include/ip.h @@ -9,12 +9,12 @@ #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); - + inline uint8_t tos() const { return _ip.tos; } inline uint16_t tot_len() const { return _ip.tot_len; } inline uint16_t id() const { return _ip.id; } @@ -24,7 +24,7 @@ namespace Tins { inline uint16_t check() const { return _ip.check; } inline uint32_t source_address() const { return _ip.saddr; } inline uint32_t dest_address() const { return _ip.daddr; } - + void tos(uint8_t new_tos); void tot_len(uint16_t new_tot_len); void id(uint16_t new_id); @@ -36,9 +36,10 @@ namespace Tins { void source_address(uint32_t ip); void dest_address(const std::string &ip); void dest_address(uint32_t ip); - + /* Virtual methods */ uint32_t header_size() const; + bool send(PacketSender* sender); private: struct iphdr { #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -48,7 +49,7 @@ namespace Tins { unsigned int version:4; unsigned int ihl:4; #else - # error "Endian is not LE nor BE..." + # error "Endian is not LE nor BE..." #endif uint8_t tos; uint16_t tot_len; @@ -61,10 +62,10 @@ namespace Tins { uint32_t daddr; /*The options start here. */ } __attribute__((packed)); - + void init_ip_fields(); void write_serialization(uint8_t *buffer, uint32_t total_sz); - + iphdr _ip; }; }; diff --git a/include/packetsender.h b/include/packetsender.h index 4657fd8..11c9f4c 100644 --- a/include/packetsender.h +++ b/include/packetsender.h @@ -7,21 +7,25 @@ #include "pdu.h" namespace Tins { + class PDU; class PacketSender { public: - /* Opens a socket, using flag as protocol family. + /* Opens a socket, using flag as protocol family. * Return true if it was possible to open it(or it was already open), * false otherwise. */ - bool open_socket(uint32_t flag); - + bool open_l3_socket(); + bool close_socket(uint32_t flag); - - bool send(PDU *pdu); + + bool send(PDU* pdu); + + bool send_l3(PDU *pdu, const struct sockaddr* link_addr, uint32_t len_link_addr); private: typedef std::map SocketMap; - bool write(int sock, uint8_t *buffer, uint32_t size); - + + static const uint32_t IP_SOCKET; + SocketMap _sockets; }; }; diff --git a/include/pdu.h b/include/pdu.h index 993631d..762c375 100644 --- a/include/pdu.h +++ b/include/pdu.h @@ -3,14 +3,17 @@ #include +#include "packetsender.h" namespace Tins { - + + class PacketSender; + class PDU { public: PDU(uint32_t flag, PDU *next_pdu = 0); virtual ~PDU(); - + /* This PDU's header size only. */ virtual uint32_t header_size() const = 0; /* This PDU's trailer size only. Defaults to 0. */ @@ -19,19 +22,22 @@ namespace Tins { inline uint32_t size() const; inline uint32_t flag() const { return _flag; } inline const PDU *inner_pdu() const { return _inner_pdu; } - + void flag(uint32_t new_flag); /* When setting a new inner_pdu, the instance takes * ownership of the object, therefore deleting it when * it's no longer required. */ void inner_pdu(PDU *next_pdu); - + /* Serializes the whole chain of PDU's, including this one. */ uint8_t *serialize(uint32_t &sz); - + + /* */ + virtual bool send(PacketSender* sender) {return false;} + protected: /* Serialize this PDU storing the result in buffer. */ void serialize(uint8_t *buffer, uint32_t total_sz); - protected: + /* Each PDU's own implementation of serialization. */ virtual void write_serialization(uint8_t *buffer, uint32_t total_sz) = 0; private: diff --git a/include/utils.h b/include/utils.h index b296801..cf1fa4b 100644 --- a/include/utils.h +++ b/include/utils.h @@ -10,6 +10,14 @@ namespace Tins { namespace Utils { uint32_t ip_to_int(const std::string &ip); std::string ip_to_string(uint32_t ip); + + inline uint32_t ntohl(uint32_t address) { + return (((address & 0xff000000) >> 24) | + ((address & 0x00ff0000) >> 8) | + ((address & 0x0000ff00) << 8) | + ((address & 0x000000ff) << 24)); + } + }; }; diff --git a/src/ip.cpp b/src/ip.cpp index a27a8b1..19306fe 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -6,6 +6,8 @@ #include "ip.h" #include "utils.h" +#include + using namespace std; @@ -15,7 +17,7 @@ Tins::IP::IP(const string &ip_dst, const string &ip_src) : PDU(IPPROTO_IP) { _ip.daddr = Utils::ip_to_int(ip_dst); if(ip_src.size()) _ip.saddr = Utils::ip_to_int(ip_src); - + } Tins::IP::IP(uint32_t ip_dst, uint32_t ip_src) : PDU(IPPROTO_IP) { @@ -28,6 +30,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; } /* Setters */ @@ -82,8 +85,21 @@ uint32_t Tins::IP::header_size() const { return sizeof(iphdr); } +bool Tins::IP::send(PacketSender* sender) { + + struct sockaddr_in link_addr; + + link_addr.sin_family = AF_INET; + link_addr.sin_port = 0; + link_addr.sin_addr.s_addr = _ip.daddr; + + return sender->send_l3(this, (const struct sockaddr*)&link_addr, sizeof(link_addr)); + +} + void Tins::IP::write_serialization(uint8_t *buffer, uint32_t total_sz) { - uint32_t my_sz = header_size() + trailer_size(), new_flag = inner_pdu()->flag(); + uint32_t my_sz = header_size() + trailer_size(); + uint32_t new_flag = inner_pdu()? inner_pdu()->flag() : 255; assert(total_sz >= my_sz); if(new_flag == IPPROTO_IP) new_flag = IPPROTO_IPIP; @@ -91,5 +107,6 @@ void Tins::IP::write_serialization(uint8_t *buffer, uint32_t total_sz) { _ip.protocol = new_flag; _ip.tot_len = total_sz; memcpy(buffer, &_ip, sizeof(iphdr)); + /* IP Options here... */ } diff --git a/src/packetsender.cpp b/src/packetsender.cpp index f38b722..0fba90a 100644 --- a/src/packetsender.cpp +++ b/src/packetsender.cpp @@ -1,10 +1,11 @@ #ifndef WIN32 #include - #include - #include + #include + #include #include #include #include + #include #endif #include #include @@ -12,37 +13,23 @@ #include #include "packetsender.h" +const uint32_t Tins::PacketSender::IP_SOCKET = 0; -bool Tins::PacketSender::open_socket(uint32_t flag) { - if(_sockets.find(flag) != _sockets.end()) +bool Tins::PacketSender::open_l3_socket() { + if(_sockets.find(IP_SOCKET) != _sockets.end()) return true; int sockfd; - sockfd = socket(PF_PACKET, SOCK_RAW, 255); + sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (sockfd < 0) { - std::cout << "Flag: " << flag << "\n"; + std::cout << "No se pudo abrir el fucking socket\n"; std::cout << "Errno: " << errno << "\n"; return false; } - struct sockaddr_ll sa; - memset(&sa, 0, sizeof(sa)); - sa.sll_family = AF_PACKET; - sa.sll_protocol = htons(ETH_P_IP); - sa.sll_ifindex = 1; - sa.sll_hatype = 1; - sa.sll_pkttype = PACKET_BROADCAST; - sa.sll_halen = 0; - sa.sll_addr[2] = 0xde; - if(bind(sockfd, (struct sockaddr *)&sa, sizeof(sockaddr_ll)) != 0) { - std::cout << "Error: " << errno << "\n"; - return false; - } - /* { - int one = 1; - const int *val = &one; - if (setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) - std::cout << "Warning: Cannot set HDRINCL!\n"; - }*/ - _sockets[flag] = sockfd; + + const int on = 1; + setsockopt(sockfd, IPPROTO_IP,IP_HDRINCL,(const void *)&on,sizeof(on)); + + _sockets[IP_SOCKET] = sockfd; return true; } @@ -55,28 +42,23 @@ bool Tins::PacketSender::close_socket(uint32_t flag) { return true; } -bool Tins::PacketSender::write(int sock, uint8_t *buffer, uint32_t size) { - uint32_t index = 0; - int ret; - while(size) { - if((ret = ::send(sock, &buffer[index], size, 0)) <= 0) { - std::cout << errno << "\n"; - return false; - } - index += ret; - size -= ret; - } - /*if(!sendto(sock, buffer, size, 0, - const struct sockaddr *dest_addr, socklen_t addrlen);))*/ - return true; +bool Tins::PacketSender::send(PDU *pdu) { + return pdu->send(this); } -bool Tins::PacketSender::send(PDU *pdu) { - uint32_t sz, flag(pdu->flag()); - uint8_t *buffer = pdu->serialize(sz); +bool Tins::PacketSender::send_l3(PDU *pdu, const struct sockaddr* link_addr, uint32_t len_link_addr) { bool ret_val = true; - if(!open_socket(flag) || !write(_sockets[flag], buffer, sz)) + if(!open_l3_socket()) ret_val = false; - delete[] buffer; + + if (ret_val) { + uint32_t sz; + int sock = _sockets[IP_SOCKET]; + uint8_t *buffer = pdu->serialize(sz); + ret_val = (sendto(sock, buffer, sz, 0, link_addr, len_link_addr) != -1); + delete[] buffer; + } + return ret_val; + } diff --git a/src/utils.cpp b/src/utils.cpp index d312a4d..b27b544 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -22,12 +22,13 @@ uint32_t Tins::Utils::ip_to_int(const string &ip) { } if(bytes_found < 4 || (i < ip.size() && bytes_found == 4)) throw std::runtime_error("Invalid ip address"); - return result; + return ntohl(result); } string Tins::Utils::ip_to_string(uint32_t ip) { ostringstream oss; int mask(24); + ip = ntohl(ip); while(mask >=0) { oss << ((ip >> mask) & 0xff); if(mask)