From: Steinar H. Gunderson Date: Sat, 7 Feb 2015 00:11:37 +0000 (+0100) Subject: Move GREProtocol into its own files, and Reorderer into a .h file. X-Git-Url: https://git.sesse.net/?p=greproxy;a=commitdiff_plain;h=7c67b21504e7758f4148386befc8cd80455a1a85 Move GREProtocol into its own files, and Reorderer into a .h file. --- diff --git a/greprotocol.cpp b/greprotocol.cpp new file mode 100644 index 0000000..b826a52 --- /dev/null +++ b/greprotocol.cpp @@ -0,0 +1,112 @@ +#include +#include +#include + +#include "greprotocol.h" +#include "reorderer.h" + +using namespace std; + +struct gre_header { + uint8_t reserved0_hi : 4; + uint8_t has_seq : 1; + uint8_t has_key : 1; + uint8_t unused : 1; + uint8_t has_checksum : 1; + + uint8_t version : 3; + uint8_t reserved0_lo: 5; + + uint16_t protocol_type; +}; + + +GREProtocol::GREProtocol(const in6_addr &src, const in6_addr &dst) + : seq(0) +{ + memset(&dstaddr, 0, sizeof(dstaddr)); + dstaddr.sin6_family = AF_INET6; + dstaddr.sin6_addr = dst; + + sock = socket(AF_INET6, SOCK_RAW, IPPROTO_GRE); + if (sock == -1) { + perror("socket"); + exit(1); + } + + sockaddr_in6 my_addr; + memset(&my_addr, 0, sizeof(my_addr)); + my_addr.sin6_family = AF_INET6; + my_addr.sin6_addr = src; + if (::bind(sock, (sockaddr *)&my_addr, sizeof(my_addr)) == -1) { + perror("bind"); + exit(1); + } +} + +void GREProtocol::send_packet(uint16_t proto, const string &data) +{ + char buf[4096]; + gre_header *gre = (gre_header *)buf; + + memset(gre, 0, sizeof(*gre)); + gre->has_seq = 1; + gre->version = 0; + gre->protocol_type = htons(proto); + + char *ptr = buf + sizeof(*gre); + int seq_be = htonl(seq++); + memcpy(ptr, &seq_be, sizeof(seq_be)); + ptr += sizeof(seq_be); + + memcpy(ptr, data.data(), data.size()); + + if (sendto(sock, buf, data.size() + sizeof(seq_be) + sizeof(*gre), 0, (sockaddr *)&dstaddr, sizeof(dstaddr)) == -1) { + perror("sendto"); + return; + } +} + +int GREProtocol::fd() const +{ + return sock; +} + +void GREProtocol::read_packet(Reorderer *sender) +{ + struct sockaddr_storage addr; + socklen_t addrlen = sizeof(addr); + char buf[4096]; + int ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&addr, &addrlen); + if (ret == -1) { + perror("recvfrom"); + exit(1); + } + if (addr.ss_family != AF_INET6) { + return; + } + struct in6_addr *addr6 = &((struct sockaddr_in6 *)&addr)->sin6_addr; + if (memcmp(addr6, &dstaddr.sin6_addr, sizeof(*addr6)) != 0) { + // ignore + return; + } + gre_header* gre = (gre_header *)buf; + + char* ptr = buf + sizeof(gre_header); + if (gre->has_checksum) { + ptr += 4; + } + if (gre->has_key) { + ptr += 4; + } + uint32_t seq; + if (gre->has_seq) { + seq = ntohl(*(uint32_t *)ptr); + ptr += 4; + } + + //printf("gre packet: proto=%x\n", ntohs(gre->protocol_type)); + + sender->handle_packet(ntohs(gre->protocol_type), string(ptr, buf + ret), seq); +} + diff --git a/greprotocol.h b/greprotocol.h new file mode 100644 index 0000000..6930f20 --- /dev/null +++ b/greprotocol.h @@ -0,0 +1,25 @@ +#ifndef _GREPROTOCOL_H +#define _GREPROTOCOL_H + +#include "protocol.h" + +#include +#include +#include + +class Reorderer; + +class GREProtocol : public Protocol { +public: + GREProtocol(const in6_addr &myaddr, const in6_addr &dst); + virtual void send_packet(uint16_t proto, const std::string &data); + virtual int fd() const; + void read_packet(Reorderer* sender); + +private: + int seq; + int sock; + sockaddr_in6 dstaddr; +}; + +#endif // !defined(_GREPROTOCOL_H) diff --git a/reorderer.h b/reorderer.h new file mode 100644 index 0000000..476093f --- /dev/null +++ b/reorderer.h @@ -0,0 +1,39 @@ +#ifndef _REORDERER_H +#define _REORDERER_H 1 + +#include + +#include +#include +#include +#include +#include + +class Protocol; + +struct GREPacket { + int seq; + uint16_t proto; + std::string data; + + bool operator> (const GREPacket &other) const { + return seq > other.seq; + } +}; + +class Reorderer { +public: + Reorderer(Protocol* sender); + void handle_packet(uint16_t proto, const std::string& data, int seq); + +private: + void send_packet(uint16_t proto, const std::string &data, bool silence); + + Protocol* sender; + int last_seq; + + std::priority_queue, std::greater> packet_buffer; + std::map ccs; +}; + +#endif // !defined(_REORDERER_H)