}
};
-class Sender {
+class Protocol {
public:
virtual void send_packet(uint16_t proto, const string &data) = 0;
+ virtual int fd() const = 0;
};
-class GRESender : public Sender {
+class Reorderer;
+class Protocol;
+
+class GREProtocol : public Protocol {
public:
- GRESender(int sock, const in6_addr &dst);
+ GREProtocol(const in6_addr &myaddr, const in6_addr &dst);
virtual void send_packet(uint16_t proto, const string &data);
+ virtual int fd() const;
+ void read_packet(Reorderer* sender);
private:
int seq;
sockaddr_in6 dstaddr;
};
-class TUNSender : public Sender {
+class TUNProtocol : public Protocol {
public:
- TUNSender(int tunfd);
+ TUNProtocol(const char *devname);
virtual void send_packet(uint16_t proto, const string &data);
+ virtual int fd() const;
+ void read_packet(Protocol* sender);
private:
int tunfd;
class Reorderer {
public:
- Reorderer(Sender* sender);
+ Reorderer(Protocol* sender);
void handle_packet(uint16_t proto, const string& data, int seq);
private:
void send_packet(uint16_t proto, const string &data, bool silence);
- Sender* sender;
+ Protocol* sender;
int last_seq;
priority_queue<GREPacket, vector<GREPacket>, greater<GREPacket>> packet_buffer;
map<int, int> ccs;
};
-GRESender::GRESender(int sock, const in6_addr &dst)
- : sock(sock), seq(0)
+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 GRESender::send_packet(uint16_t proto, const string &data)
+void GREProtocol::send_packet(uint16_t proto, const string &data)
{
char buf[4096];
gre_header *gre = (gre_header *)buf;
return;
}
}
+
+int GREProtocol::fd() const
+{
+ return sock;
+}
-TUNSender::TUNSender(int tunfd)
- : tunfd(tunfd) {}
+TUNProtocol::TUNProtocol(const char *devname)
+ : tunfd(tun_open(devname)) {
+}
-void TUNSender::send_packet(uint16_t proto, const string &data)
+void TUNProtocol::send_packet(uint16_t proto, const string &data)
{
char buf[4096];
}
}
-Reorderer::Reorderer(Sender* sender)
+int TUNProtocol::fd() const
+{
+ return tunfd;
+}
+
+Reorderer::Reorderer(Protocol* sender)
: sender(sender), last_seq(-1)
{
}
sender->send_packet(proto, data);
}
-void read_gre_packet(int gresock, const in6_addr &remoteaddr, Reorderer *sender)
+void GREProtocol::read_packet(Reorderer *sender)
{
struct sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
char buf[4096];
- int ret = recvfrom(gresock, buf, sizeof(buf), 0, (struct sockaddr *)&addr, &addrlen);
+ int ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&addr, &addrlen);
if (ret == -1) {
perror("recvfrom");
exit(1);
return;
}
struct in6_addr *addr6 = &((struct sockaddr_in6 *)&addr)->sin6_addr;
- if (memcmp(addr6, &remoteaddr, sizeof(*addr6)) != 0) {
+ if (memcmp(addr6, &dstaddr.sin6_addr, sizeof(*addr6)) != 0) {
// ignore
return;
}
sender->handle_packet(ntohs(gre->protocol_type), string(ptr, buf + ret), seq);
}
-void read_tun_packet(int tunfd, Sender *sender)
+void TUNProtocol::read_packet(Protocol *sender)
{
char buf[4096];
int ret = read(tunfd, buf, sizeof(buf));
int main(int argc, char **argv)
{
- int tunfd = tun_open("tungre");
- int gresock = socket(AF_INET6, SOCK_RAW, IPPROTO_GRE);
- if (gresock == -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 = get_addr(argv[1]);
- if (bind(gresock, (sockaddr *)&my_addr, sizeof(my_addr)) == -1) {
- perror("bind");
- exit(1);
- }
-
+ in6_addr myaddr = get_addr(argv[1]);
in6_addr remoteaddr = get_addr(argv[2]);
- GRESender gre_sender(gresock, remoteaddr);
- TUNSender tun_sender(tunfd);
+ GREProtocol gre(myaddr, remoteaddr);
+ TUNProtocol tun("tungre");
- Reorderer tun_reorderer(&tun_sender);
+ Reorderer tun_reorderer(&tun);
fd_set fds;
FD_ZERO(&fds);
for ( ;; ) {
- FD_SET(gresock, &fds);
- FD_SET(tunfd, &fds);
+ FD_SET(gre.fd(), &fds);
+ FD_SET(tun.fd(), &fds);
int ret = select(1024, &fds, NULL, NULL, NULL);
if (ret == -1) {
perror("select");
continue;
}
- if (FD_ISSET(gresock, &fds)) {
- read_gre_packet(gresock, remoteaddr, &tun_reorderer);
+ if (FD_ISSET(gre.fd(), &fds)) {
+ gre.read_packet(&tun_reorderer);
}
- if (FD_ISSET(tunfd, &fds)) {
- read_tun_packet(tunfd, &gre_sender);
+ if (FD_ISSET(tun.fd(), &fds)) {
+ tun.read_packet(&gre);
}
}
}