A Discrete-Event Network Simulator
API
planetlab-tap-creator.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2012 INRIA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Alina Quereilhac <alina.quereilhac@inria.fr>
20  * Claudio Freire <klaussfreire@sourceforge.net>
21  *
22  */
23 
24 #include <unistd.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string>
29 #include <string.h> // for strerror
30 #include <iostream>
31 #include <iomanip>
32 #include <sstream>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <sys/ioctl.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <sys/un.h>
39 #include <net/if.h>
40 #include <linux/if_tun.h>
41 #include <net/route.h>
42 #include <netinet/in.h>
43 
44 #include "creator-utils.h"
45 
46 #define PLANETLAB_MAGIC 75867
47 
48 #define VSYS_TUNTAP "/vsys/fd_tuntap.control"
49 #define VSYS_VIFUP_IN "/vsys/vif_up.in"
50 #define VSYS_VIFUP_OUT "/vsys/vif_up.out"
51 
52 using namespace ns3;
53 
60 int
61 ReceiveVifFd (int fd, char *vif_name)
62 {
63  struct msghdr msg;
64  struct iovec iov;
65  int rv;
66  size_t ccmsg[CMSG_SPACE (sizeof(int)) / sizeof(size_t)];
67  struct cmsghdr *cmsg;
68 
69  /* Use IOV to read interface name */
70  iov.iov_base = vif_name;
71  iov.iov_len = IFNAMSIZ;
72 
73  msg.msg_name = 0;
74  msg.msg_namelen = 0;
75  msg.msg_iov = &iov;
76  msg.msg_iovlen = 1;
77  /* old BSD implementations should use msg_accrights instead of
78  * msg_control; the interface is different. */
79  msg.msg_control = ccmsg;
80  msg.msg_controllen = sizeof(ccmsg);
81 
82  while (((rv = recvmsg (fd, &msg, 0)) == -1) && errno == EINTR)
83  {
84  }
85  ABORT_IF (rv == -1, "Could not receive fd from Vsys", 0);
86  ABORT_IF (!rv, "Could not receive fd from Vsys (EOF)", 0);
87 
88  cmsg = CMSG_FIRSTHDR (&msg);
89  ABORT_IF (!cmsg->cmsg_type == SCM_RIGHTS, "got control message of unknown type" << cmsg->cmsg_type, 0);
90 
91  int* retfd = (int*)CMSG_DATA (cmsg);
92  return *retfd;
93 }
94 
104 int
105 TunAlloc (int iftype, char *if_name)
106 {
107  int control_fd;
108  struct sockaddr_un addr;
109  int ret;
110 
111  control_fd = socket (AF_UNIX, SOCK_STREAM, 0);
112  ABORT_IF (control_fd == -1, "Could not create UNIX socket", 0);
113 
114  memset (&addr, 0, sizeof(struct sockaddr_un));
115 
116  /* Clear structure */
117  addr.sun_family = AF_UNIX;
118  strncpy (addr.sun_path, VSYS_TUNTAP, sizeof(addr.sun_path) - 1);
119 
120  ret = connect (control_fd, (struct sockaddr *) &addr,
121  sizeof(struct sockaddr_un));
122  ABORT_IF (ret == -1, "Could not connect to Vsys control socket", 0);
123 
124  /* passing type param */
125  ret = send (control_fd, &iftype, sizeof(iftype), 0);
126  ABORT_IF (ret != sizeof(iftype), "Could not send parameter to Vsys control socket", 0);
127 
128  return ReceiveVifFd (control_fd, if_name);
129 
130 }
131 
139 void
140 SetTunUp (const char *ip, const char *prefix, const char *if_name)
141 {
142  FILE *in;
143  FILE *out;
144  char errbuff[4096];
145 
146  memset(errbuff, 0, 4096);
147 
148  in = fopen (VSYS_VIFUP_IN, "a");
149 
150  if (in == NULL)
151  {
152  ABORT_IF (in == NULL, "Failed to open " << VSYS_VIFUP_IN, 0);
153  }
154 
155  out = fopen (VSYS_VIFUP_OUT, "r");
156 
157  if (out == NULL)
158  {
159  ABORT_IF (out == NULL, "Failed to open " << VSYS_VIFUP_OUT, 0);
160  }
161 
162  // send input to process
163  fprintf (in, "%s\n%s\n%s\nsnat=1\n", if_name, ip, prefix);
164 
165  // close pipe to indicate end parameter passing and flush the fifo
166  fclose (in);
167 
168  fread((void*)errbuff, 4096, 1, out);
169 
170  // the error buffer will not be empty if we read an error
171  ABORT_IF (strcmp(errbuff, "") != 0, errbuff, 0);
172 
173  fclose (out);
174 }
175 
176 int
177 main (int argc, char *argv[])
178 {
179  int c;
180  char *ip = NULL;
181  char *prefix = NULL;
182  char *path = NULL;
183  int iftype = IFF_TUN;
184  char if_name[4096];
185 
186  memset(if_name, 0, 4096);
187  opterr = 0;
188 
189  while ((c = getopt (argc, argv, "vi:n:tp:")) != -1)
190  {
191  switch (c)
192  {
193  case 'i':
194  ip = optarg; // ip address of the new device
195  break;
196  case 'n':
197  prefix = optarg; // prefix for the new device
198  break;
199  case 't':
200  iftype = IFF_TAP; // mode for the device (TAP or TUN)
201  break;
202  case 'p':
203  path = optarg; // path back to the tap bridge
204  break;
205  case 'v':
206  gVerbose = true;
207  break;
208  }
209  }
210 
211  ABORT_IF (ip == NULL, "IP Address is a required argument", 0);
212  LOG ("Provided IP Address is \"" << ip << "\"");
213 
214  ABORT_IF (prefix == NULL, "Prefix is a required argument", 0);
215  LOG ("Provided prefix \"" << prefix << "\"");
216 
217  ABORT_IF (path == NULL, "path is a required argument", 0);
218  LOG ("Provided path is \"" << path << "\"");
219 
220  LOG ("Creating Tap");
221  // allocate a TAP device in planetLab
222  int fd = TunAlloc (iftype, if_name);
223  ABORT_IF (fd == -1, "main(): Unable to create tap device", 1);
224 
225  // set the TAP interface up
226  SetTunUp (ip, prefix, (const char*)if_name);
227 
228  //
229  // Send the socket back to the tap net device so it can go about its business
230  //
231  SendSocket (path, fd, PLANETLAB_MAGIC);
232 
233  return 0;
234 }
void SendSocket(const char *path, int fd, const int magic_number)
Send the file descriptor back to the code that invoked the creation.
ns3::StringValue attribute value declarations.
#define ABORT_IF(cond, msg, printErrno)
Definition: creator-utils.h:50
#define PLANETLAB_MAGIC
int gVerbose
Flag to enable / disable verbose log mode.
void SetTunUp(const char *ip, const char *prefix, const char *if_name)
Sets the TAP/TUN interface up.
int TunAlloc(int iftype, char *if_name)
Creates a TUN/TAP device on a PlanetLab virtual machine (sliver).
#define VSYS_TUNTAP
#define LOG(x)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
#define VSYS_VIFUP_OUT
int ReceiveVifFd(int fd, char *vif_name)
Reads vif FD from "fd", writes interface name to vif_name, and returns vif FD.
#define VSYS_VIFUP_IN