A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 paramater 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  int nbytes;
146 
147  memset(errbuff, 0, 4096);
148 
149  in = fopen (VSYS_VIFUP_IN, "a");
150 
151  if (in == NULL)
152  {
153  ABORT_IF (in == NULL, "Failed to open " << VSYS_VIFUP_IN, 0);
154  }
155 
156  out = fopen (VSYS_VIFUP_OUT, "r");
157 
158  if (out == NULL)
159  {
160  ABORT_IF (out == NULL, "Failed to open " << VSYS_VIFUP_OUT, 0);
161  }
162 
163  // send input to process
164  fprintf (in, "%s\n%s\n%s\nsnat=1\n", if_name, ip, prefix);
165 
166  // close pipe to indicate end parameter passing and flush the fifo
167  fclose (in);
168 
169  nbytes = fread((void*)errbuff, 4096, 1, out);
170 
171  // the error buffer will not be empty if we read an error
172  ABORT_IF (strcmp(errbuff, "") != 0, errbuff, 0);
173 
174  fclose (out);
175 }
176 
177 int
178 main (int argc, char *argv[])
179 {
180  int c;
181  char *ip = NULL;
182  char *prefix = NULL;
183  char *path = NULL;
184  int iftype = IFF_TUN;
185  char if_name[4096];
186 
187  memset(if_name, 0, 4096);
188  opterr = 0;
189 
190  while ((c = getopt (argc, argv, "vi:n:tp:")) != -1)
191  {
192  switch (c)
193  {
194  case 'i':
195  ip = optarg; // ip address of the new device
196  break;
197  case 'n':
198  prefix = optarg; // prefix for the new device
199  break;
200  case 't':
201  iftype = IFF_TAP; // mode for the device (TAP or TUN)
202  break;
203  case 'p':
204  path = optarg; // path back to the tap bridge
205  break;
206  case 'v':
207  gVerbose = true;
208  break;
209  }
210  }
211 
212  ABORT_IF (ip == NULL, "IP Address is a required argument", 0);
213  LOG ("Provided IP Address is \"" << ip << "\"");
214 
215  ABORT_IF (prefix == NULL, "Prefix is a required argument", 0);
216  LOG ("Provided prefix \"" << prefix << "\"");
217 
218  ABORT_IF (path == NULL, "path is a required argument", 0);
219  LOG ("Provided path is \"" << path << "\"");
220 
221  LOG ("Creating Tap");
222  // allocate a TAP device in planetLab
223  int fd = TunAlloc (iftype, if_name);
224  ABORT_IF (fd == -1, "main(): Unable to create tap device", 1);
225 
226  // set the TAP interface up
227  SetTunUp (ip, prefix, (const char*)if_name);
228 
229  //
230  // Send the socket back to the tap net device so it can go about its business
231  //
232  SendSocket (path, fd, PLANETLAB_MAGIC);
233 
234  return 0;
235 }
#define ABORT_IF(cond, msg, printErrno)
#define PLANETLAB_MAGIC
int gVerbose
void SendSocket(const char *path, int fd, const int magic_number)
Send the file descriptor back to the code that invoked the creation.
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)
int main(int argc, char *argv[])
#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