Java程序辅导

C C++ Java Python Processing编程在线培训 程序编写 软件开发 视频讲解

客服在线QQ:2653320439 微信:ittutor Email:itutor@qq.com
wx: cjtutor
QQ: 2653320439
ns-3: src/fd-net-device/helper/tap-fd-net-device-helper.cc Source File A Discrete-Event Network Simulator   Home Tutorials  ▼ English Portuguese Docs    ▼ Wiki Manual Models Develop ▼ API Bugs API Main Page Related Pages Modules Namespaces Classes Files File List  All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages tap-fd-net-device-helper.cc 1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 /* 3  * Copyright (c) 2012 INRIA, 2012 University of Washington 4  * 5  * This program is free software; you can redistribute it and/or modify 6  * it under the terms of the GNU General Public License version 2 as 7  * published by the Free Software Foundation; 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  19 #include "tap-fd-net-device-helper.h" 20 #include "encode-decode.h" 21  22 #include "ns3/abort.h" 23 #include "ns3/config.h" 24 #include "ns3/fd-net-device.h" 25 #include "ns3/log.h" 26 #include "ns3/names.h" 27 #include "ns3/object-factory.h" 28 #include "ns3/packet.h" 29 #include "ns3/simulator.h" 30 #include "ns3/trace-helper.h" 31 #include "ns3/internet-module.h" 32  33 #include 34 #include 35 #include 36 #include 37 #include 38 #include 39 #include 40 #include 41 #include 42 #include 43 #include 44  45 #include 46 #include 47 #include 48 #include 49 #include 50 #include 51 #include 52 #include 53 #include 54  55 #include 56  57 NS_LOG_COMPONENT_DEFINE ("TapFdNetDeviceHelper"); 58  59 namespace ns3 { 60  61 #define TAP_MAGIC 95549 62  63 TapFdNetDeviceHelper::TapFdNetDeviceHelper () 64 { 65  m_deviceName = ""; 66  m_modePi = false; 67  m_tapIp4 = ""; 68  m_tapMask4 = ""; 69  m_tapIp6 = ""; 70  m_tapPrefix6 = 64; 71  m_tapMac = Mac48Address::Allocate (); 72 } 73  74 void 75 TapFdNetDeviceHelper::SetModePi (bool modePi) 76 { 77  m_modePi = modePi; 78 } 79  80 void 81 TapFdNetDeviceHelper::SetTapIpv4Address (Ipv4Address address) 82 { 83  m_tapIp4 = address; 84 } 85  86 void 87 TapFdNetDeviceHelper::SetTapIpv4Mask (Ipv4Mask mask) 88 { 89  m_tapMask4 = mask; 90 } 91  92 void 93 TapFdNetDeviceHelper::SetTapIpv6Address (Ipv6Address address) 94 { 95  m_tapIp6 = address; 96 } 97  98 void 99 TapFdNetDeviceHelper::SetTapIpv6Prefix (int prefix) 100 { 101  m_tapPrefix6 = prefix; 102 } 103  104 void 105 TapFdNetDeviceHelper::SetTapMacAddress (Mac48Address mac) 106 { 107  m_tapMac = mac; 108 } 109  110 Ptr 111 TapFdNetDeviceHelper::InstallPriv (Ptr node) const 112 { 113  Ptr d = FdNetDeviceHelper::InstallPriv (node); 114  Ptr device = d->GetObject (); 115  Ptr fdnd = device->GetObject (); 116  117  // 118  // We need to explicitly set the encapsulation mode for the traffic 119  // traversing the TAP device, so the FdNetDevice is able to know 120  // how to treat the traffic in a way that in compatible with the 121  // TAP device. 122  // 123  if (m_modePi) 124  { 125  fdnd->SetEncapsulationMode (FdNetDevice::DIXPI); 126  } 127  128  SetFileDescriptor (device); 129  return device; 130 } 131  132 void 133 TapFdNetDeviceHelper::SetFileDescriptor (Ptr device) const 134 { 135  NS_LOG_LOGIC ("Creating TAP device"); 136  137  // 138  // Call out to a separate process running as suid root in order to create a 139  // TAP device. We do this to avoid having the entire simulation running as root. 140  // 141  int fd = CreateFileDescriptor (); 142  device->SetFileDescriptor (fd); 143 } 144  145 int 146 TapFdNetDeviceHelper::CreateFileDescriptor (void) const 147 { 148  NS_LOG_FUNCTION (this); 149  150  // 151  // We're going to fork and exec that program soon, but first we need to have 152  // a socket to talk to it with. So we create a local interprocess (Unix) 153  // socket for that purpose. 154  // 155  int sock = socket (PF_UNIX, SOCK_DGRAM, 0); 156  NS_ABORT_MSG_IF (sock == -1, "TapFdNetDeviceHelper::CreateFileDescriptor(): Unix socket creation error, errno = " << strerror (errno)); 157  158  // 159  // Bind to that socket and let the kernel allocate an endpoint 160  // 161  struct sockaddr_un un; 162  memset (&un, 0, sizeof (un)); 163  un.sun_family = AF_UNIX; 164  int status = bind (sock, (struct sockaddr*)&un, sizeof (sa_family_t)); 165  NS_ABORT_MSG_IF (status == -1, "TapFdNetDeviceHelper::CreateFileDescriptor(): Could not bind(): errno = " << strerror (errno)); 166  NS_LOG_INFO ("Created Unix socket"); 167  NS_LOG_INFO ("sun_family = " << un.sun_family); 168  NS_LOG_INFO ("sun_path = " << un.sun_path); 169  170  // 171  // We have a socket here, but we want to get it there -- to the program we're 172  // going to exec. What we'll do is to do a getsockname and then encode the 173  // resulting address information as a string, and then send the string to the 174  // program as an argument. So we need to get the sock name. 175  // 176  socklen_t len = sizeof (un); 177  status = getsockname (sock, (struct sockaddr*)&un, &len); 178  NS_ABORT_MSG_IF (status == -1, "TapFdNetDeviceHelper::CreateFileDescriptor(): Could not getsockname(): errno = " << strerror (errno)); 179  180  // 181  // Now encode that socket name (family and path) as a string of hex digits 182  // 183  std::string path = BufferToString ((uint8_t *)&un, len); 184  NS_LOG_INFO ("Encoded Unix socket as \"" << path << "\""); 185  186  // 187  // Fork and exec the process to create our socket. If we're us (the parent) 188  // we wait for the child (the creator) to complete and read the socket it 189  // created and passed back using the ancillary data mechanism. 190  // 191  pid_t pid = ::fork (); 192  if (pid == 0) 193  { 194  NS_LOG_DEBUG ("Child process"); 195  196  // 197  // build a command line argument from the encoded endpoint string that 198  // the socket creation process will use to figure out how to respond to 199  // the (now) parent process. We're going to have to give this program 200  // quite a bit of information. 201  // 202  // -d The name of the tap device we want to create; 203  // -m The MAC-48 address to assign to the new tap device; 204  // -i The IP v4 address to assign to the new tap device; 205  // -I The IP v6 address to assign to the new tap device; 206  // -n The network IPv4 mask to assign to the new tap device; 207  // -N The network IPv6 mask to assign to the new tap device; 208  // -t Set teh IFF_TAP flag 209  // -h Set the IFF_NO_PI flag 210  // -p the path to the unix socket described above. 211  // 212  // Example tap-creator -dnewdev -i1.2.3.1 -m08:00:2e:00:01:23 -n255.255.255.0 -t -h -pblah 213  // 214  215  // 216  // The device-name is something we may want the system to make up in 217  // every case. We also rely on it being configured via an Attribute 218  // through the helper. By default, it is set to the empty string 219  // which tells the system to make up a device name such as "tap123". 220  // 221  std::ostringstream ossDeviceName; 222  if (m_deviceName != "") 223  { 224  ossDeviceName << "-d" << m_deviceName; 225  } 226  227  std::ostringstream ossMac; 228  ossMac << "-m" << m_tapMac; 229  230  std::ostringstream ossIp4; 231  if (m_tapIp4 != "") 232  { 233  ossIp4 << "-i" << m_tapIp4; 234  } 235  236  std::ostringstream ossIp6; 237  if (m_tapIp6 != "") 238  { 239  ossIp6 << "-I" << m_tapIp6; 240  } 241  242  std::ostringstream ossNetmask4; 243  if (m_tapMask4 != "" ) 244  { 245  ossNetmask4 << "-n" << m_tapMask4; 246  } 247  248  std::ostringstream ossPrefix6; 249  ossPrefix6 << "-P" << m_tapPrefix6; 250  251  std::ostringstream ossMode; 252  ossMode << "-t"; 253  254  std::ostringstream ossPI; 255  if (m_modePi) 256  { 257  ossPI << "-h"; 258  } 259  260  std::ostringstream ossPath; 261  ossPath << "-p" << path; 262  263  // 264  // Execute the socket creation process image. 265  // 266  status = ::execlp (TAP_DEV_CREATOR, 267  TAP_DEV_CREATOR, // argv[0] (filename) 268  ossDeviceName.str ().c_str (), // argv[1] (-d) 269  ossMac.str ().c_str (), // argv[2] (-m 270  ossIp4.str ().c_str (), // argv[3] (-i) 271  ossIp6.str ().c_str (), // argv[4] (-I) 272  ossNetmask4.str ().c_str (), // argv[5] (-n) 273  ossPrefix6.str ().c_str (), // argv[6] (-P) 274  ossMode.str ().c_str (), // argv[7] (-t ) 275  ossPI.str ().c_str (), // argv[8] (-h ) 276  ossPath.str ().c_str (), // argv[9] (-p) 277  (char *)NULL); 278  279  // 280  // If the execlp successfully completes, it never returns. If it returns it failed or the OS is 281  // broken. In either case, we bail. 282  // 283  NS_FATAL_ERROR ("TapFdNetDeviceHelper::CreateFileDescriptor(): Back from execlp(), errno = " << ::strerror (errno)); 284  } 285  else 286  { 287  NS_LOG_DEBUG ("Parent process"); 288  // 289  // We're the process running the emu net device. We need to wait for the 290  // socket creator process to finish its job. 291  // 292  int st; 293  pid_t waited = waitpid (pid, &st, 0); 294  NS_ABORT_MSG_IF (waited == -1, "TapFdNetDeviceHelper::CreateFileDescriptor(): waitpid() fails, errno = " << strerror (errno)); 295  NS_ASSERT_MSG (pid == waited, "TapFdNetDeviceHelper::CreateFileDescriptor(): pid mismatch"); 296  297  // 298  // Check to see if the socket creator exited normally and then take a 299  // look at the exit code. If it bailed, so should we. If it didn't 300  // even exit normally, we bail too. 301  // 302  if (WIFEXITED (st)) 303  { 304  int exitStatus = WEXITSTATUS (st); 305  NS_ABORT_MSG_IF (exitStatus != 0, 306  "TapFdNetDeviceHelper::CreateFileDescriptor(): socket creator exited normally with status " << exitStatus); 307  } 308  else 309  { 310  NS_FATAL_ERROR ("TapFdNetDeviceHelper::CreateFileDescriptor(): socket creator exited abnormally"); 311  } 312  313  // 314  // At this point, the socket creator has run successfully and should 315  // have created our tap device, initialized it with the information we 316  // passed and sent it back to the socket address we provided. A socket 317  // (fd) we can use to talk to this tap device should be waiting on the 318  // Unix socket we set up to receive information back from the creator 319  // program. We've got to do a bunch of grunt work to get at it, though. 320  // 321  // The struct iovec below is part of a scatter-gather list. It describes a 322  // buffer. In this case, it describes a buffer (an integer) that will 323  // get the data that comes back from the socket creator process. It will 324  // be a magic number that we use as a consistency/sanity check. 325  // 326  struct iovec iov; 327  uint32_t magic; 328  iov.iov_base = &magic; 329  iov.iov_len = sizeof(magic); 330  331  // 332  // The CMSG macros you'll see below are used to create and access control 333  // messages (which is another name for ancillary data). The ancillary 334  // data is made up of pairs of struct cmsghdr structures and associated 335  // data arrays. 336  // 337  // First, we're going to allocate a buffer on the stack to receive our 338  // data array (that contains the socket). Sometimes you'll see this called 339  // an "ancillary element" but the msghdr uses the control message termimology 340  // so we call it "control." 341  // 342  size_t msg_size = sizeof(int); 343  char control[CMSG_SPACE (msg_size)]; 344  345  // 346  // There is a msghdr that is used to minimize the number of parameters 347  // passed to recvmsg (which we will use to receive our ancillary data). 348  // This structure uses terminology corresponding to control messages, so 349  // you'll see msg_control, which is the pointer to the ancillary data and 350  // controllen which is the size of the ancillary data array. 351  // 352  // So, initialize the message header that describes the ancillary/control 353  // data we expect to receive and point it to buffer. 354  // 355  struct msghdr msg; 356  msg.msg_name = 0; 357  msg.msg_namelen = 0; 358  msg.msg_iov = &iov; 359  msg.msg_iovlen = 1; 360  msg.msg_control = control; 361  msg.msg_controllen = sizeof (control); 362  msg.msg_flags = 0; 363  364  // 365  // Now we can actually receive the interesting bits from the tap 366  // creator process. Lots of pain to get four bytes. 367  // 368  ssize_t bytesRead = recvmsg (sock, &msg, 0); 369  NS_ABORT_MSG_IF (bytesRead != sizeof(int), "TapFdNetDeviceHelper::CreateFileDescriptor(): Wrong byte count from socket creator"); 370  371  // 372  // There may be a number of message headers/ancillary data arrays coming in. 373  // Let's look for the one with a type SCM_RIGHTS which indicates it's the 374  // one we're interested in. 375  // 376  struct cmsghdr *cmsg; 377  for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg)) 378  { 379  if (cmsg->cmsg_level == SOL_SOCKET 380  && cmsg->cmsg_type == SCM_RIGHTS) 381  { 382  // 383  // This is the type of message we want. Check to see if the magic 384  // number is correct and then pull out the socket we care about if 385  // it matches 386  // 387  if (magic == TAP_MAGIC) 388  { 389  NS_LOG_INFO ("Got SCM_RIGHTS with correct magic " << magic); 390  int *rawSocket = (int*)CMSG_DATA (cmsg); 391  NS_LOG_INFO ("Got the socket from the socket creator = " << *rawSocket); 392  return *rawSocket; 393  } 394  else 395  { 396  NS_LOG_INFO ("Got SCM_RIGHTS, but with bad magic " << magic); 397  } 398  } 399  } 400  NS_FATAL_ERROR ("Did not get the raw socket from the socket creator"); 401  } 402  403 } 404  405 } // namespace ns3 406  407  ns3::Ptr smart pointer class similar to boost::intrusive_ptr Definition: ptr.h:59 NS_LOG_FUNCTION #define NS_LOG_FUNCTION(parameters) Definition: log.h:311 ns3::TapFdNetDeviceHelper::m_tapIp4 Ipv4Address m_tapIp4 Definition: tap-fd-net-device-helper.h:123 ns3::Ipv4Mask a class to represent an Ipv4 address mask Definition: ipv4-address.h:210 ns3::FdNetDevice::DIXPI Definition: fd-net-device.h:94 ns3::TapFdNetDeviceHelper::SetFileDescriptor virtual void SetFileDescriptor(Ptr< FdNetDevice > device) const Definition: tap-fd-net-device-helper.cc:133 NS_LOG_COMPONENT_DEFINE #define NS_LOG_COMPONENT_DEFINE(name) Definition: log.h:122 ns3::TapFdNetDeviceHelper::m_modePi bool m_modePi Definition: tap-fd-net-device-helper.h:116 NS_LOG_INFO #define NS_LOG_INFO(msg) Definition: log.h:264 NS_FATAL_ERROR #define NS_FATAL_ERROR(msg) fatal error handling Definition: fatal-error.h:72 ns3::TapFdNetDeviceHelper::SetTapIpv4Address void SetTapIpv4Address(Ipv4Address address) Definition: tap-fd-net-device-helper.cc:81 ns3::Mac48Address::Allocate static Mac48Address Allocate(void) Definition: mac48-address.cc:130 ns3::BufferToString std::string BufferToString(uint8_t *buffer, uint32_t len) Convert a byte buffer to a string containing a hex representation of the buffer. Make the string pret... Definition: encode-decode.cc:37 ns3::TapFdNetDeviceHelper::SetTapMacAddress void SetTapMacAddress(Mac48Address mac) Definition: tap-fd-net-device-helper.cc:105 ns3::TapFdNetDeviceHelper::CreateFileDescriptor virtual int CreateFileDescriptor(void) const Definition: tap-fd-net-device-helper.cc:146 ns3::TapFdNetDeviceHelper::TapFdNetDeviceHelper TapFdNetDeviceHelper() Definition: tap-fd-net-device-helper.cc:63 NS_LOG_LOGIC #define NS_LOG_LOGIC(msg) Definition: log.h:334 ns3::FdNetDevice::SetEncapsulationMode void SetEncapsulationMode(FdNetDevice::EncapsulationMode mode) Definition: fd-net-device.cc:184 ns3::TapFdNetDeviceHelper::m_tapPrefix6 int m_tapPrefix6 Definition: tap-fd-net-device-helper.h:145 ns3::Mac48Address an EUI-48 address Definition: mac48-address.h:41 ns3::TapFdNetDeviceHelper::SetTapIpv4Mask void SetTapIpv4Mask(Ipv4Mask mask) Definition: tap-fd-net-device-helper.cc:87 ns3::TapFdNetDeviceHelper::m_tapMac Mac48Address m_tapMac Definition: tap-fd-net-device-helper.h:153 NS_ASSERT_MSG #define NS_ASSERT_MSG(condition, message) Definition: assert.h:86 ns3::Ipv6Address Describes an IPv6 address. Definition: ipv6-address.h:44 ns3::Ipv4Address Ipv4 addresses are stored in host order in this class. Definition: ipv4-address.h:38 ns3::TapFdNetDeviceHelper::SetTapIpv6Prefix void SetTapIpv6Prefix(int prefix) Definition: tap-fd-net-device-helper.cc:99 ns3::TapFdNetDeviceHelper::SetTapIpv6Address void SetTapIpv6Address(Ipv6Address address) Definition: tap-fd-net-device-helper.cc:93 ns3::TapFdNetDeviceHelper::m_tapIp6 Ipv6Address m_tapIp6 Definition: tap-fd-net-device-helper.h:130 NS_LOG_DEBUG #define NS_LOG_DEBUG(msg) Definition: log.h:255 ns3::FdNetDevice a NetDevice to read/write network traffic from/into a file descriptor. Definition: fd-net-device.h:82 ns3::TapFdNetDeviceHelper::m_tapMask4 Ipv4Mask m_tapMask4 Definition: tap-fd-net-device-helper.h:138 NS_ABORT_MSG_IF #define NS_ABORT_MSG_IF(cond, msg) Abnormal program termination if cond is true. Definition: abort.h:98 ns3::TapFdNetDeviceHelper::SetModePi void SetModePi(bool pi) Definition: tap-fd-net-device-helper.cc:75 ns3::EmuFdNetDeviceHelper::m_deviceName std::string m_deviceName Definition: emu-fd-net-device-helper.h:86 src fd-net-device helper tap-fd-net-device-helper.cc Generated on Sun Mar 16 2014 11:25:03 for ns-3 by 1.8.6