OverSim
apptunoutscheduler.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 "apptunoutscheduler.h"
25 #include "IPvXAddress.h"
26 #include <regmacros.h>
27 
29 
30 // Note: this is defined in tunoutscheduler.cc
31 extern cConfigOption *CFGID_EXTERNALAPP_APP_PORT;
32 
34 {
35  if (additional_fd >= 0) {
36 #ifdef _WIN32
37  closesocket(additional_fd);
38 #else
39  close(additional_fd);
40 #endif
41  }
42 }
43 
45 {
46 #if defined _WIN32 || defined __APPLE__
47  throw cRuntimeError("TunOutSchedulter::initializeNetwork():"
48  "TUN interface not supported on Windows/Max OS!");
49  return -1;
50 #else
51  // get app port (0 if external app is not used)
52  int appPort = ev.getConfig()->getAsInt(CFGID_EXTERNALAPP_APP_PORT, 0);
53 
54  // Initialize TCP socket for App communication if desired
55  if (appPort > 0) {
56 
57  struct sockaddr_in server;
58  SOCKET sock;
59 
60  // Waiting for a TCP connection
61  sock = socket(AF_INET, SOCK_STREAM, 0);
62 
63  if (sock == INVALID_SOCKET) {
64  opp_error("Error creating socket");
65  return -1;
66  }
67 
68  int on = 1;
69  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
70 
71  memset(&server, 0, sizeof (server));
72  server.sin_family = AF_INET;
73  server.sin_addr.s_addr = htonl(INADDR_ANY);
74  server.sin_port = htons(appPort);
75 
76  if (bind( sock, (struct sockaddr*)&server, sizeof( server)) < 0) {
77  opp_error("Error binding to app socket");
78  return -1;
79  }
80 
81  if (listen( sock, 5 ) == -1) {
82  opp_error("Error listening on app socket");
83  return -1;
84  }
85  // Set additional_fd so we will be called if data
86  // (i.e. connection requests) is available at sock
87  additional_fd = sock;
88  FD_SET(additional_fd, &all_fds);
89  if (additional_fd > maxfd) {
91  }
92  }
93 
94  // Open UDP port
95  if (netw_fd != INVALID_SOCKET) {
96  // Port is already open, reuse it...
97  FD_SET(netw_fd, &all_fds);
98 
99  if (netw_fd> maxfd) {
100  maxfd = netw_fd;
101  }
102  }
103 
104  sockaddr_in addr;
105  netw_fd = socket(AF_INET, SOCK_DGRAM, 0);
106  memset(&addr, 0, sizeof(addr));
107  addr.sin_family = AF_INET;
108 
109  cModule* overlay = simulation.getModuleByPath(
110  "SingleHostUnderlayNetwork.overlayTerminal[0].overlay");
111 
112  if (overlay == NULL) {
113  throw cRuntimeError("UdpOutScheduler::initializeNetwork(): "
114  "Overlay module not found!");
115  }
116 
117  addr.sin_port = htons(overlay->gate("appIn")->getNextGate()->
118  getOwnerModule()->par("localPort").longValue());
119 
120  cModule* underlayConfigurator =
121  simulation.getModuleByPath("SingleHostUnderlayNetwork.underlayConfigurator");
122 
123  if (underlayConfigurator == NULL) {
124  throw cRuntimeError("UdpOutScheduler::initializeNetwork(): "
125  "UnderlayConfigurator module not found!");
126  }
127 
128  if (strlen(underlayConfigurator->par("nodeIP").stringValue())) {
129  addr.sin_addr.s_addr = htonl(IPAddress(underlayConfigurator->
130  par("nodeIP").stringValue()).getInt());
131  } else {
132  addr.sin_addr.s_addr = htonl(INADDR_ANY);
133  }
134 
135  if (bind( netw_fd, (sockaddr*)&addr, sizeof(addr)) < 0) {
136  opp_error("Error binding to UDP socket");
137  return -1;
138  }
139 
140  FD_SET(netw_fd, &all_fds);
141 
142  if (netw_fd> maxfd) {
143  maxfd = netw_fd;
144  }
145 
146  // Initialize TUN device for network communication
147  // see /usr/src/linux/Documentation/network/tuntap.txt
148  struct ifreq ifr;
149  int err;
150  dev = new char[IFNAMSIZ];
151 
152  if (apptun_fd != INVALID_SOCKET) {
153  opp_error("Already bound to application TUN device!");
154  return -1;
155  }
156 
157  if ((apptun_fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
158  opp_warning("Error opening application tun device");
159  return 0;
160  } else {
161  ev << "[AppTunOutScheduler::initializeNetwork()]\n"
162  << "\t Successfully opened application TUN device"
163  << endl;
164  }
165 
166  memset(&ifr, 0, sizeof(ifr));
167 
168  /* Flags: IFF_TUN - TUN device (no Ethernet headers)
169  * IFF_TAP - TAP device
170  *
171  * IFF_NO_PI - Do not provide packet information
172  */
173  ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
174  strncpy(ifr.ifr_name, "tun%d", IFNAMSIZ);
175 
176  if((err = ioctl(apptun_fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
177  close(apptun_fd);
178  opp_error("Error ioctl application tun device");
179  return -1;
180  }
181 
182  strncpy(dev, ifr.ifr_name, IFNAMSIZ);
183  ev << "[AppTunOutScheduler::initializeNetwork()]\n"
184  << " Bound to device " << dev << "\n"
185  << " Remember to bring up application TUN device with "
186  << "ifconfig before proceeding"
187  << endl;
188 
189  FD_SET(apptun_fd, &all_fds);
190  if( apptun_fd> maxfd ) maxfd = apptun_fd;
191  return 0;
192 #endif
193 }
194 
196  sockaddr* from = (sockaddr*) new sockaddr_in;
197  socklen_t addrlen = sizeof(sockaddr_in);
198 
199  SOCKET new_sock = accept( additional_fd, from, &addrlen );
200 
201  if (new_sock == INVALID_SOCKET) {
202  opp_warning("Error connecting to remote app");
203  return;
204  }
205 
206  if (appConnectionLimit) {
207  int count = 0;
208 
209  for (SOCKET fd = 0; fd <= maxfd; fd++) {
210  if (fd == netw_fd) continue;
211  if (fd == additional_fd) continue;
212  if (FD_ISSET(fd, &all_fds)) count++;
213  }
214 
215  if (count >= appConnectionLimit) {
216  // We already have too many connections to external applications
217  // "reject" connection
218 #ifdef _WIN32
219  closesocket(new_sock);
220 #else
221  close(new_sock);
222 #endif
223  ev << "[UdpOutScheduler::additionalFD()]\n"
224  << " Rejecting new app connection (FD: " << new_sock << ")"
225  << endl;
226 
227  return;
228  }
229  }
230 
231  FD_SET(new_sock, &all_fds);
232 
233  if (new_sock > maxfd) {
234  maxfd = new_sock;
235  }
236 
237  // Inform app about new connection
238  appPacketBuffer->push_back(PacketBufferEntry(0, 0, from, addrlen,
240 
242 
243  ev << "[UdpOutScheduler::additionalFD()]\n"
244  << " Accepting new app connection (FD: " << new_sock << ")"
245  << endl;
246 }