00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "config.h"
00010
00011 #include <iostream>
00012 #include <stdlib.h>
00013
00014
00015 #include "ibrdtn/api/Client.h"
00016
00017
00018 #include "ibrdtn/api/Bundle.h"
00019 #include "ibrdtn/api/BLOBBundle.h"
00020
00021
00022 #include "ibrdtn/api/StringBundle.h"
00023
00024
00025 #include "ibrcommon/net/tcpclient.h"
00026
00027
00028 #include "ibrcommon/thread/Mutex.h"
00029 #include "ibrcommon/thread/MutexLock.h"
00030
00031
00032 #include <iostream>
00033
00034
00035 #include <queue>
00036
00037 #include <csignal>
00038
00039 #include <unistd.h>
00040 #include <fcntl.h>
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <string.h>
00044 #include <errno.h>
00045
00046 #include <sys/ioctl.h>
00047 #include <sys/socket.h>
00048 #include <linux/if.h>
00049
00050 using namespace std;
00051
00052
00053
00054
00055
00056 static int tun_open_common0(char *dev, int istun)
00057 {
00058 char tunname[14];
00059 int i, fd, err;
00060
00061 if( *dev ) {
00062 sprintf(tunname, "/dev/%s", dev);
00063 return open(tunname, O_RDWR);
00064 }
00065
00066 sprintf(tunname, "/dev/%s", istun ? "tun" : "tap");
00067 err = 0;
00068 for(i=0; i < 255; i++){
00069 sprintf(tunname + 8, "%d", i);
00070
00071 if( (fd=open(tunname, O_RDWR)) > 0 ) {
00072 strcpy(dev, tunname + 5);
00073 return fd;
00074 }
00075 else if (errno != ENOENT)
00076 err = errno;
00077 else if (i)
00078 break;
00079 }
00080 if (err)
00081 errno = err;
00082 return -1;
00083 }
00084
00085 #ifdef HAVE_LINUX_IF_TUN_H
00086 #include <linux/if_tun.h>
00087
00088 #ifndef OTUNSETNOCSUM
00089
00090 #define OTUNSETNOCSUM (('T'<< 8) | 200)
00091 #define OTUNSETDEBUG (('T'<< 8) | 201)
00092 #define OTUNSETIFF (('T'<< 8) | 202)
00093 #define OTUNSETPERSIST (('T'<< 8) | 203)
00094 #define OTUNSETOWNER (('T'<< 8) | 204)
00095 #endif
00096
00097 static int tun_open_common(char *dev, int istun)
00098 {
00099 struct ifreq ifr;
00100 int fd;
00101
00102 if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
00103 return tun_open_common0(dev, istun);
00104
00105 memset(&ifr, 0, sizeof(ifr));
00106 ifr.ifr_flags = (istun ? IFF_TUN : IFF_TAP) | IFF_NO_PI;
00107 if (*dev)
00108 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
00109
00110 if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
00111 if (errno == EBADFD) {
00112
00113 if (ioctl(fd, OTUNSETIFF, (void *) &ifr) < 0)
00114 goto failed;
00115 } else
00116 goto failed;
00117 }
00118
00119 strcpy(dev, ifr.ifr_name);
00120 return fd;
00121
00122 failed:
00123 close(fd);
00124 return -1;
00125 }
00126
00127 #else
00128
00129 # define tun_open_common(dev, type) tun_open_common0(dev, type)
00130
00131 #endif
00132
00133 int tun_open(char *dev) { return tun_open_common(dev, 1); }
00134 int tap_open(char *dev) { return tun_open_common(dev, 0); }
00135
00136 class TUN2BundleGateway : public dtn::api::Client
00137 {
00138 public:
00139 TUN2BundleGateway(int fd, string app, string address = "127.0.0.1", int port = 4550)
00140 : dtn::api::Client(app, _tcpclient), _fd(fd), _tcpclient(address, port)
00141 {
00142
00143 _tcpclient.enableNoDelay();
00144 };
00145
00149 virtual ~TUN2BundleGateway()
00150 {
00151
00152 _tcpclient.close();
00153 };
00154
00155 private:
00156
00157 int _fd;
00158
00164 void received(dtn::api::Bundle &b)
00165 {
00166 ibrcommon::BLOB::Reference ref = b.getData();
00167 ibrcommon::BLOB::iostream stream = ref.iostream();
00168 char data[65536];
00169 stream->read(data, sizeof(data));
00170 size_t ret = stream->gcount();
00171 if (::write(_fd, data, ret) < 0)
00172 {
00173 std::cerr << "error while writing" << std::endl;
00174 }
00175 }
00176
00177 ibrcommon::tcpclient _tcpclient;
00178 };
00179
00180 bool m_running = true;
00181 int tunnel_fd = -1;
00182
00183 void term(int signal)
00184 {
00185 if (signal >= 1)
00186 {
00187 m_running = false;
00188 ::close(tunnel_fd);
00189 tunnel_fd = -1;
00190 }
00191 }
00192
00193 int main(int argc, char *argv[])
00194 {
00195
00196 signal(SIGINT, term);
00197 signal(SIGTERM, term);
00198
00199 cout << "IBR-DTN IP <-> Bundle Tunnel" << endl;
00200
00201 if (argc < 5)
00202 {
00203 cout << "Syntax: " << argv[0] << " <dev> <ip> <ptp> <dst>" << endl;
00204 cout << " <dev> Virtual network device to create" << endl;
00205 cout << " <ip> Own IP address to set" << endl;
00206 cout << " <ptp> IP address of the Point-To-Point partner" << endl;
00207 cout << " <dst> EID of the destination" << endl;
00208 return -1;
00209 }
00210
00211 int tunnel_fd = tun_open(argv[1]);
00212
00213 if (tunnel_fd == -1)
00214 {
00215 cerr << "Error: failed to open tun device" << endl;
00216 return -1;
00217 }
00218
00219
00220 TUN2BundleGateway gateway(tunnel_fd, "tun");
00221
00222
00223 stringstream ifconfig;
00224 ifconfig << "ifconfig " << argv[1] << " -pointopoint " << argv[2] << " dstaddr " << argv[3];
00225 if ( system(ifconfig.str().c_str()) > 0 )
00226 {
00227 std::cerr << "can not the interface address" << std::endl;
00228 }
00229
00230 gateway.connect();
00231
00232 cout << "ready" << endl;
00233
00234 while (m_running)
00235 {
00236 char data[65536];
00237 int ret = ::read(tunnel_fd, data, sizeof(data));
00238
00239 cout << "received " << ret << " bytes" << endl;
00240
00241
00242 ibrcommon::BLOB::Reference blob = ibrcommon::StringBLOB::create();
00243
00244
00245 blob.iostream()->write(data, ret);
00246
00247
00248 dtn::api::BLOBBundle b(dtn::data::EID(argv[4]), blob);
00249
00250
00251 gateway << b;
00252 gateway.flush();
00253 }
00254
00255 gateway.close();
00256
00257 ::close(tunnel_fd);
00258 tunnel_fd = -1;
00259
00260 return 0;
00261 }