OverSim
tunoutscheduler.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 
24 #include "tunoutscheduler.h"
25 
27 
28 // Note: this is defined in tunoutscheduler.cc
29 extern cConfigOption *CFGID_EXTERNALAPP_APP_PORT;
30 
32 {
33  if (additional_fd >= 0) {
34 #ifdef _WIN32
35  closesocket(additional_fd);
36 #else
37  close(additional_fd);
38 #endif
39  }
40 
41  delete dev;
42 }
43 
44 
46 {
47 #if defined _WIN32 || defined __APPLE__
48  throw cRuntimeError("TunOutSchedulter::initializeNetwork():"
49  "TUN interface not supported on Windows/Max OS!");
50  return -1;
51 #else
52  // Initialize TUN device for network communication
53  // see /usr/src/linux/Documentation/network/tuntap.txt
54  struct ifreq ifr;
55  int err;
56  dev = new char[IFNAMSIZ];
57 
58  // get app port (0 if external app is not used)
59  int appPort = ev.getConfig()->getAsInt(CFGID_EXTERNALAPP_APP_PORT, 0);
60 
61  // Initialize TCP socket for App communication if desired
62  if (appPort > 0) {
63  struct sockaddr_in server;
64  SOCKET sock;
65 
66  // Waiting for a TCP connection
67  // WARNING: Will only accept exactly ONE app connecting to the socket
68  sock = socket( AF_INET, SOCK_STREAM, 0 );
69  if (sock == INVALID_SOCKET) {
70  opp_error("Error creating socket");
71  return -1;
72  }
73 
74  int on = 1;
75  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
76 
77  memset( &server, 0, sizeof (server));
78  server.sin_family = AF_INET;
79  server.sin_addr.s_addr = htonl( INADDR_ANY );
80  server.sin_port = htons( appPort );
81 
82  if (bind( sock, (struct sockaddr*)&server, sizeof( server)) < 0) {
83  opp_error("Error binding to app socket");
84  return -1;
85  }
86  if (listen( sock, 5 ) == -1 ) {
87  opp_error("Error listening on app socket");
88  return -1;
89  }
90  // Set additional_fd so we will be called if data
91  // (i.e. connection requests) is available at sock
92  additional_fd = sock;
93  FD_SET(additional_fd, &all_fds);
95  }
96 
97  if (netw_fd != INVALID_SOCKET) {
98  opp_error("Already bound to TUN device!");
99  return -1;
100  }
101 
102  if ((netw_fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
103  opp_warning("Error opening tun device");
104  return 0;
105  } else {
106  ev << "[TunOutScheduler::initializeNetwork()]\n"
107  << "\t Successfully opened TUN device"
108  << endl;
109  }
110 
111  memset(&ifr, 0, sizeof(ifr));
112 
113  /* Flags: IFF_TUN - TUN device (no Ethernet headers)
114  * IFF_TAP - TAP device
115  *
116  * IFF_NO_PI - Do not provide packet information
117  */
118  ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
119  strncpy(ifr.ifr_name, "tun%d", IFNAMSIZ);
120 
121  if((err = ioctl(netw_fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
122  close(netw_fd);
123  opp_error("Error ioctl tun device");
124  return -1;
125  }
126 
127  strncpy(dev, ifr.ifr_name, IFNAMSIZ);
128  ev << "[TunOutScheduler::initializeNetwork()]\n"
129  << " Bound to device " << dev << "\n"
130  << " Remember to bring up TUN device with ifconfig before proceeding"
131  << endl;
132 
133  FD_SET(netw_fd, &all_fds);
134  if( netw_fd> maxfd ) maxfd = netw_fd;
135  return 0;
136 #endif
137 }
138 
140  sockaddr* from = (sockaddr*) new sockaddr_in;
141  socklen_t addrlen = sizeof(sockaddr_in);
142 
143  SOCKET new_sock = accept( additional_fd, 0, 0 );
144  if (new_sock == INVALID_SOCKET) {
145  opp_warning("Error connecting to remote app");
146  return;
147  }
148  if (appConnectionLimit) {
149  int count = 0;
150  for (SOCKET fd = 0; fd < maxfd; fd++) {
151  if( fd == netw_fd ) continue;
152  if( fd == additional_fd ) continue;
153  if( FD_ISSET(fd, &all_fds)) count++;
154  }
155  if( count > appConnectionLimit ) {
156  // We already have too many connections to external applications
157  // "reject" connection
158  close(new_sock);
159  ev << "[UdpOutScheduler::additionalFD()]\n"
160  << " Rejecting new app connection (FD: " << new_sock << ")"
161  << endl;
162  return;
163  }
164  }
165 
166  FD_SET(new_sock, &all_fds);
167  if( new_sock > maxfd ) maxfd = new_sock;
168 
169  // Inform app about new connection
170  appPacketBuffer->push_back(PacketBufferEntry(0, 0, from, addrlen,
173 
174  ev << "[UdpOutScheduler::additionalFD()]\n"
175  << " Accepting new app connection (FD: " << new_sock << ")"
176  << endl;
177 
178 }
179