tunoutscheduler.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include "tunoutscheduler.h"
00025 
00026 Register_Class(TunOutScheduler);
00027 
00028 // Note: this is defined in tunoutscheduler.cc
00029 extern cConfigOption *CFGID_EXTERNALAPP_APP_PORT;
00030 
00031 TunOutScheduler::~TunOutScheduler()
00032 {
00033     if (additional_fd >= 0) {
00034 #ifdef _WIN32
00035         closesocket(additional_fd);
00036 #else
00037         close(additional_fd);
00038 #endif
00039     }
00040 
00041     delete dev;
00042 }
00043 
00044 
00045 int TunOutScheduler::initializeNetwork()
00046 {
00047 #if defined _WIN32 || defined __APPLE__
00048     throw cRuntimeError("TunOutSchedulter::initializeNetwork():"
00049                         "TUN interface not supported on Windows/Max OS!");
00050     return -1;
00051 #else
00052     // Initialize TUN device for network communication
00053     // see /usr/src/linux/Documentation/network/tuntap.txt
00054     struct ifreq ifr;
00055     int err;
00056     dev = new char[IFNAMSIZ];
00057 
00058     // get app port (0 if external app is not used)
00059     int appPort = ev.getConfig()->getAsInt(CFGID_EXTERNALAPP_APP_PORT, 0);
00060 
00061     // Initialize TCP socket for App communication if desired
00062     if (appPort > 0) {
00063         struct sockaddr_in server;
00064         SOCKET sock;
00065 
00066         // Waiting for a TCP connection
00067         // WARNING: Will only accept exactly ONE app connecting to the socket
00068         sock = socket( AF_INET, SOCK_STREAM, 0 );
00069         if (sock == INVALID_SOCKET) {
00070             opp_error("Error creating socket");
00071             return -1;
00072         }
00073 
00074         int on = 1;
00075         setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
00076 
00077         memset( &server, 0, sizeof (server));
00078         server.sin_family = AF_INET;
00079         server.sin_addr.s_addr = htonl( INADDR_ANY );
00080         server.sin_port = htons( appPort );
00081 
00082         if (bind( sock, (struct sockaddr*)&server, sizeof( server)) < 0) {
00083             opp_error("Error binding to app socket");
00084             return -1;
00085         }
00086         if (listen( sock, 5 ) == -1 ) {
00087             opp_error("Error listening on app socket");
00088             return -1;
00089         }
00090         // Set additional_fd so we will be called if data
00091         // (i.e. connection requests) is available at sock
00092         additional_fd = sock;
00093         FD_SET(additional_fd, &all_fds);
00094         if (additional_fd > maxfd) maxfd = additional_fd;
00095     }
00096 
00097     if (netw_fd != INVALID_SOCKET) {
00098         opp_error("Already bound to TUN device!");
00099         return -1;
00100     }
00101 
00102     if ((netw_fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
00103         opp_warning("Error opening tun device");
00104         return 0;
00105     } else {
00106         ev << "[TunOutScheduler::initializeNetwork()]\n"
00107         << "\t Successfully opened TUN device"
00108         << endl;
00109     }
00110 
00111     memset(&ifr, 0, sizeof(ifr));
00112 
00113     /* Flags: IFF_TUN   - TUN device (no Ethernet headers)
00114      *        IFF_TAP   - TAP device
00115      *
00116      *        IFF_NO_PI - Do not provide packet information
00117      */
00118     ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
00119     strncpy(ifr.ifr_name, "tun%d", IFNAMSIZ);
00120 
00121     if((err = ioctl(netw_fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
00122         close(netw_fd);
00123         opp_error("Error ioctl tun device");
00124         return -1;
00125     }
00126 
00127     strncpy(dev, ifr.ifr_name, IFNAMSIZ);
00128     ev << "[TunOutScheduler::initializeNetwork()]\n"
00129        << "    Bound to device " << dev << "\n"
00130        << "    Remember to bring up TUN device with ifconfig before proceeding"
00131        << endl;
00132 
00133     FD_SET(netw_fd, &all_fds);
00134     if( netw_fd> maxfd ) maxfd = netw_fd;
00135     return 0;
00136 #endif
00137 }
00138 
00139 void TunOutScheduler::additionalFD() {
00140     sockaddr* from = (sockaddr*) new sockaddr_in;
00141     socklen_t addrlen = sizeof(sockaddr_in);
00142 
00143     SOCKET new_sock = accept( additional_fd, 0, 0 );
00144     if (new_sock == INVALID_SOCKET) {
00145         opp_warning("Error connecting to remote app");
00146         return;
00147     }
00148     if (appConnectionLimit) {
00149         int count = 0;
00150         for (SOCKET fd = 0; fd < maxfd; fd++) {
00151             if( fd == netw_fd ) continue;
00152             if( fd == additional_fd ) continue;
00153             if( FD_ISSET(fd, &all_fds)) count++;
00154         }
00155         if( count > appConnectionLimit ) {
00156             // We already have too many connections to external applications
00157             // "reject" connection
00158             close(new_sock);
00159             ev << "[UdpOutScheduler::additionalFD()]\n"
00160                 << "    Rejecting new app connection (FD: " << new_sock << ")"
00161                 << endl;
00162             return;
00163         }
00164     }
00165 
00166     FD_SET(new_sock, &all_fds);
00167     if( new_sock > maxfd ) maxfd = new_sock;
00168 
00169     // Inform app about new connection
00170     appPacketBuffer->push_back(PacketBufferEntry(0, 0, from, addrlen,
00171                                          PacketBufferEntry::PACKET_FD_NEW, new_sock));
00172     sendNotificationMsg(appNotificationMsg, appModule);
00173 
00174     ev << "[UdpOutScheduler::additionalFD()]\n"
00175         << "    Accepting new app connection (FD: " << new_sock << ")"
00176         << endl;
00177 
00178 }
00179 
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3