• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

tools/src/dtntunnel.cpp

Go to the documentation of this file.
00001 //============================================================================
00002 // Name        : IPtunnel.cpp
00003 // Author      : IBR, TU Braunschweig
00004 // Version     :
00005 // Copyright   :
00006 // Description : Hello World in C++, Ansi-style
00007 //============================================================================
00008 
00009 #include "config.h"
00010 
00011 #include <iostream>
00012 #include <stdlib.h>
00013 
00014 // Base for send and receive bundle to/from the IBR-DTN daemon.
00015 #include "ibrdtn/api/Client.h"
00016 
00017 // Container for bundles.
00018 #include "ibrdtn/api/Bundle.h"
00019 #include "ibrdtn/api/BLOBBundle.h"
00020 
00021 // Container for bundles carrying strings.
00022 #include "ibrdtn/api/StringBundle.h"
00023 
00024 //  TCP client implemeted as a stream.
00025 #include "ibrcommon/net/tcpclient.h"
00026 
00027 // Some classes to be thread-safe.
00028 #include "ibrcommon/thread/Mutex.h"
00029 #include "ibrcommon/thread/MutexLock.h"
00030 
00031 // Basic functionalities for streaming.
00032 #include <iostream>
00033 
00034 // A queue for bundles.
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  * Allocate TUN device, returns opened fd.
00054  * Stores dev name in the first arg(must be large enough).
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        /* Open device */
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)      /* don't try all 256 devices */
00078           break;
00079     }
00080     if (err)
00081         errno = err;
00082     return -1;
00083 }
00084 
00085 #ifdef HAVE_LINUX_IF_TUN_H /* New driver support */
00086 #include <linux/if_tun.h>
00087 
00088 #ifndef OTUNSETNOCSUM
00089 /* pre 2.4.6 compatibility */
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           /* Try old ioctl */
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 /* New driver support */
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                         // enable nodelay option
00143                         _tcpclient.enableNoDelay();
00144                 };
00145 
00149                 virtual ~TUN2BundleGateway()
00150                 {
00151                         // Close the tcp connection.
00152                         _tcpclient.close();
00153                 };
00154 
00155         private:
00156                 // file descriptor for the tun device
00157                 int _fd;
00158 
00164                 void received(dtn::api::Bundle &b)
00165                 {
00166                         ibrcommon::BLOB::Reference ref = b.getData();
00167                         char data[65536];
00168                         size_t ret = (*ref).readsome(data, sizeof(data));
00169                         if (::write(_fd, data, ret) < 0)
00170                         {
00171                                 std::cerr << "error while writing" << std::endl;
00172                         }
00173                 }
00174 
00175                 ibrcommon::tcpclient _tcpclient;
00176 };
00177 
00178 bool m_running = true;
00179 int tunnel_fd = 0;
00180 
00181 void term(int signal)
00182 {
00183         if (signal >= 1)
00184         {
00185                 m_running = false;
00186                 ::close(tunnel_fd);
00187         }
00188 }
00189 
00190 int main(int argc, char *argv[])
00191 {
00192         // catch process signals
00193         signal(SIGINT, term);
00194         signal(SIGTERM, term);
00195 
00196         cout << "IBR-DTN IP <-> Bundle Tunnel" << endl;
00197 
00198         if (argc < 5)
00199         {
00200                 cout << "Syntax: " << argv[0] << " <dev> <ip> <ptp> <dst>" << endl;
00201                 cout << "  <dev>   Virtual network device to create" << endl;
00202                 cout << "  <ip>    Own IP address to set" << endl;
00203                 cout << "  <ptp>   IP address of the Point-To-Point partner" << endl;
00204                 cout << "  <dst>   EID of the destination" << endl;
00205                 return -1;
00206         }
00207 
00208         int tunnel_fd = tun_open(argv[1]);
00209 
00210         if (tunnel_fd == -1)
00211         {
00212                 cerr << "Error: failed to open tun device" << endl;
00213                 return -1;
00214         }
00215 
00216         // create a connection to the dtn daemon
00217         TUN2BundleGateway gateway(tunnel_fd, "tun");
00218 
00219         // set the interface addresses
00220         stringstream ifconfig;
00221         ifconfig << "ifconfig " << argv[1] << " -pointopoint " << argv[2] << " dstaddr " << argv[3];
00222         if ( system(ifconfig.str().c_str()) > 0 )
00223         {
00224                 std::cerr << "can not the interface address" << std::endl;
00225         }
00226 
00227         gateway.connect();
00228 
00229         cout << "ready" << endl;
00230 
00231         while (m_running)
00232         {
00233                 char data[65536];
00234                 int ret = ::read(tunnel_fd, data, sizeof(data));
00235 
00236                 cout << "received " << ret << " bytes" << endl;
00237 
00238                 // create a blob
00239                 ibrcommon::BLOB::Reference blob = ibrcommon::StringBLOB::create();
00240 
00241                 // add the data
00242                 (*blob).write(data, ret);
00243 
00244                 // create a new bundle
00245                 dtn::api::BLOBBundle b(dtn::data::EID(argv[4]), blob);
00246 
00247                 // transmit the packet
00248                 gateway << b;
00249                 gateway.flush();
00250         }
00251 
00252         gateway.close();
00253 
00254         ::close(tunnel_fd);
00255 
00256         return 0;
00257 }

Generated on Thu Nov 11 2010 09:49:47 for IBR-DTNSuite by  doxygen 1.7.1