diff --git a/include/ip.h b/include/ip.h index c72429f..2ca3fdd 100644 --- a/include/ip.h +++ b/include/ip.h @@ -38,7 +38,7 @@ namespace Tins { void dest_address(uint32_t ip); /* Virtual methods */ - uint32_t header_size(); + uint32_t header_size() const; void write_serialization(uint8_t *buffer, uint32_t total_sz); private: struct iphdr { diff --git a/include/packetsender.h b/include/packetsender.h new file mode 100644 index 0000000..4657fd8 --- /dev/null +++ b/include/packetsender.h @@ -0,0 +1,29 @@ +#ifndef __PACKET_SENDER_H +#define __PACKET_SENDER_H + + +#include +#include +#include "pdu.h" + +namespace Tins { + + class PacketSender { + public: + /* 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 close_socket(uint32_t flag); + + bool send(PDU *pdu); + private: + typedef std::map SocketMap; + bool write(int sock, uint8_t *buffer, uint32_t size); + + SocketMap _sockets; + }; +}; + +#endif diff --git a/include/pdu.h b/include/pdu.h index 954c8cf..993631d 100644 --- a/include/pdu.h +++ b/include/pdu.h @@ -27,7 +27,7 @@ namespace Tins { void inner_pdu(PDU *next_pdu); /* Serializes the whole chain of PDU's, including this one. */ - uint8_t *serialize(); + uint8_t *serialize(uint32_t &sz); /* Serialize this PDU storing the result in buffer. */ void serialize(uint8_t *buffer, uint32_t total_sz); diff --git a/src/ip.cpp b/src/ip.cpp index 09ab654..4b0693d 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -67,7 +67,7 @@ void Tins::IP::dest_address(uint32_t ip) { _ip.daddr = ip; } -uint32_t Tins::IP::header_size() { +uint32_t Tins::IP::header_size() const { return sizeof(iphdr); } diff --git a/src/packetsender.cpp b/src/packetsender.cpp new file mode 100644 index 0000000..f38b722 --- /dev/null +++ b/src/packetsender.cpp @@ -0,0 +1,82 @@ +#ifndef WIN32 + #include + #include + #include + #include + #include + #include +#endif +#include +#include +#include +#include +#include "packetsender.h" + + +bool Tins::PacketSender::open_socket(uint32_t flag) { + if(_sockets.find(flag) != _sockets.end()) + return true; + int sockfd; + sockfd = socket(PF_PACKET, SOCK_RAW, 255); + if (sockfd < 0) { + std::cout << "Flag: " << flag << "\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; + return true; +} + +bool Tins::PacketSender::close_socket(uint32_t flag) { + SocketMap::iterator it = _sockets.find(flag); + if(it == _sockets.end()) + return false; + close(it->second); + _sockets.erase(it); + 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) { + uint32_t sz, flag(pdu->flag()); + uint8_t *buffer = pdu->serialize(sz); + bool ret_val = true; + if(!open_socket(flag) || !write(_sockets[flag], buffer, sz)) + ret_val = false; + delete[] buffer; + return ret_val; +} diff --git a/src/pdu.cpp b/src/pdu.cpp index 6dd8544..8c2ba90 100644 --- a/src/pdu.cpp +++ b/src/pdu.cpp @@ -28,8 +28,8 @@ void Tins::PDU::inner_pdu(PDU *next_pdu) { _inner_pdu = next_pdu; } -uint8_t *Tins::PDU::serialize() { - uint32_t sz(size()); +uint8_t *Tins::PDU::serialize(uint32_t &sz) { + sz = size(); uint8_t *buffer = new uint8_t[sz]; serialize(buffer, sz); return buffer;