rework to address suid root issues
authorCraig Dowell <craigdo@ee.washington.edu>
Wed Oct 29 22:39:36 2008 -0700 (15 months ago)
changeset 38308862b9be62bb
parent 3829 97ae21d8caca
child 3831 16c2970a0344
rework to address suid root issues
src/devices/emu/emu-encode-decode.cc
src/devices/emu/emu-encode-decode.h
src/devices/emu/emu-net-device.cc
src/devices/emu/emu-net-device.h
src/devices/emu/emu-sock-creator.cc
src/devices/emu/emu.h
src/devices/emu/waf
src/devices/emu/wscript
src/devices/emulated/emulated-net-device.cc
src/devices/emulated/emulated-net-device.h
src/devices/emulated/emulated.h
src/devices/emulated/waf
src/devices/emulated/wscript
src/helper/emu-helper.cc
src/helper/emu-helper.h
src/wscript
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/devices/emu/emu-encode-decode.cc	Wed Oct 29 22:39:36 2008 -0700
     1.3 @@ -0,0 +1,110 @@
     1.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     1.5 +/*
     1.6 + * Copyright (c) University of Washington
     1.7 + *
     1.8 + * This program is free software; you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License version 2 as
    1.10 + * published by the Free Software Foundation;
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License
    1.18 + * along with this program; if not, write to the Free Software
    1.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.20 + */
    1.21 +
    1.22 +#include <string>
    1.23 +#include <iostream>
    1.24 +#include <iomanip>
    1.25 +#include <sstream>
    1.26 +
    1.27 +namespace ns3 {
    1.28 +
    1.29 +/**
    1.30 + * \brief Convert a byte buffer to a string containing a hex representation
    1.31 + * of the buffer.  Make the string pretty by adding a colon (':') between
    1.32 + * the hex.
    1.33 + *
    1.34 + * \param buffer The input buffer to be converted.
    1.35 + * \param len The length of the input buffer.
    1.36 + * \returns A string containing a hex representation of the data in buffer.
    1.37 + */
    1.38 +  std::string
    1.39 +EmuBufferToString (uint8_t *buffer, uint32_t len)
    1.40 +{
    1.41 +  std::ostringstream oss;
    1.42 +  //
    1.43 +  // Tell the stream to make hex characters, zero-filled
    1.44 +  //
    1.45 +  oss.setf (std::ios::hex, std::ios::basefield);
    1.46 +  oss.fill('0');
    1.47 +
    1.48 +  //
    1.49 +  // Loop through the buffer, separating the two-digit-wide hex bytes
    1.50 +  // with a colon.
    1.51 +  //
    1.52 +  for (uint8_t i = 0; i < len; i++)
    1.53 +    {
    1.54 +      oss << ":" << std::setw (2) << (uint32_t)buffer[i];
    1.55 +    }
    1.56 +  return oss.str ();
    1.57 +}
    1.58 +
    1.59 +/**
    1.60 + * \brief Convert string encoded by the inverse function (EmuBufferToString)
    1.61 + * back into a byte buffer.
    1.62 + *
    1.63 + * \param s The input string.
    1.64 + * \param buffer The buffer to initialize with the converted bits.
    1.65 + * \param len The length of the data that is valid in the buffer.
    1.66 + * \returns True indicates a successful conversion.
    1.67 + */
    1.68 +  bool
    1.69 +EmuStringToBuffer (std::string s, uint8_t *buffer, uint32_t *len)
    1.70 +{
    1.71 +  //
    1.72 +  // If the string was made by our inverse function, the string length must
    1.73 +  // be a multiple of three characters in length.  Use this fact to do a
    1.74 +  // quick reasonableness test.
    1.75 +  //
    1.76 +  if ((s.length () % 3) != 0)
    1.77 +    {
    1.78 +      return false;
    1.79 +    }
    1.80 +
    1.81 +  std::istringstream iss;
    1.82 +  iss.str (s);
    1.83 +
    1.84 +  uint8_t n = 0;
    1.85 +
    1.86 +  while (iss.good ())
    1.87 +    {
    1.88 +      //
    1.89 +      // The first character in the "triplet" we're working on is always the
    1.90 +      // the ':' separator.  Read that into a char and make sure we're skipping
    1.91 +      // what we think we're skipping.
    1.92 +      //
    1.93 +      char c;
    1.94 +      iss.read (&c, 1);
    1.95 +      if (c != ':')
    1.96 +        {
    1.97 +          return false;
    1.98 +        }
    1.99 +      
   1.100 +      //
   1.101 +      // And then read in the real bits and convert them.
   1.102 +      //
   1.103 +      uint32_t tmp;
   1.104 +      iss >> std::hex >> tmp;
   1.105 +      buffer[n] = tmp;
   1.106 +      n++;
   1.107 +    }
   1.108 +
   1.109 +  *len = n;
   1.110 +  return true;
   1.111 +}
   1.112 +
   1.113 +} // namespace ns3
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/devices/emu/emu-encode-decode.h	Wed Oct 29 22:39:36 2008 -0700
     2.3 @@ -0,0 +1,33 @@
     2.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2.5 +/*
     2.6 + * Copyright (c) 2008 University of Washington
     2.7 + *
     2.8 + * This program is free software; you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License version 2 as
    2.10 + * published by the Free Software Foundation;
    2.11 + *
    2.12 + * This program is distributed in the hope that it will be useful,
    2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.15 + * GNU General Public License for more details.
    2.16 + *
    2.17 + * You should have received a copy of the GNU General Public License
    2.18 + * along with this program; if not, write to the Free Software
    2.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.20 + */
    2.21 +
    2.22 +#ifndef EMU_ENCODE_DECODE_H
    2.23 +#define EMU_ENCODE_DECODE_H
    2.24 +
    2.25 +#include <string>
    2.26 +
    2.27 +namespace ns3 {
    2.28 +
    2.29 +  std::string EmuBufferToString (uint8_t *buffer, uint32_t len);
    2.30 +  bool EmuStringToBuffer (std::string s, uint8_t *buffer, uint32_t *len);
    2.31 +
    2.32 +
    2.33 +} // namespace ns3
    2.34 +
    2.35 +#endif // EMU_ENCODE_DECODE_H
    2.36 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/devices/emu/emu-net-device.cc	Wed Oct 29 22:39:36 2008 -0700
     3.3 @@ -0,0 +1,861 @@
     3.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     3.5 +/*
     3.6 + * Copyright (c) 2008 University of Washington
     3.7 + *
     3.8 + * This program is free software; you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License version 2 as
    3.10 + * published by the Free Software Foundation;
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU General Public License
    3.18 + * along with this program; if not, write to the Free Software
    3.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    3.20 + */
    3.21 +
    3.22 +#include "emu-net-device.h"
    3.23 +#include "emu-encode-decode.h"
    3.24 +
    3.25 +#include "ns3/log.h"
    3.26 +#include "ns3/queue.h"
    3.27 +#include "ns3/simulator.h"
    3.28 +#include "ns3/realtime-simulator-impl.h"
    3.29 +#include "ns3/mac48-address.h"
    3.30 +#include "ns3/ethernet-header.h"
    3.31 +#include "ns3/ethernet-trailer.h"
    3.32 +#include "ns3/llc-snap-header.h"
    3.33 +#include "ns3/trace-source-accessor.h"
    3.34 +#include "ns3/pointer.h"
    3.35 +#include "ns3/channel.h"
    3.36 +#include "ns3/system-thread.h"
    3.37 +#include "ns3/string.h"
    3.38 +#include "ns3/boolean.h"
    3.39 +
    3.40 +#include <sys/wait.h>
    3.41 +#include <sys/stat.h>
    3.42 +#include <sys/socket.h>
    3.43 +#include <sys/un.h>
    3.44 +#include <sys/ioctl.h>
    3.45 +#include <net/ethernet.h>
    3.46 +#include <net/if.h>
    3.47 +#include <netinet/in.h>
    3.48 +#include <netpacket/packet.h>
    3.49 +#include <arpa/inet.h>
    3.50 +#include <errno.h>
    3.51 +
    3.52 +NS_LOG_COMPONENT_DEFINE ("EmuNetDevice");
    3.53 +
    3.54 +namespace ns3 {
    3.55 +
    3.56 +NS_OBJECT_ENSURE_REGISTERED (EmuNetDevice);
    3.57 +
    3.58 +TypeId 
    3.59 +EmuNetDevice::GetTypeId (void)
    3.60 +{
    3.61 +  static TypeId tid = TypeId ("ns3::EmuNetDevice")
    3.62 +    .SetParent<NetDevice> ()
    3.63 +    .AddConstructor<EmuNetDevice> ()
    3.64 +    .AddAttribute ("Address", 
    3.65 +                   "The ns-3 MAC address of this (virtual) device.",
    3.66 +                   Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
    3.67 +                   MakeMac48AddressAccessor (&EmuNetDevice::m_address),
    3.68 +                   MakeMac48AddressChecker ())
    3.69 +    .AddAttribute ("DeviceName", 
    3.70 +                   "The name of the underlying real device (e.g. eth1).",
    3.71 +                   StringValue ("eth1"),
    3.72 +                   MakeStringAccessor (&EmuNetDevice::m_deviceName),
    3.73 +                   MakeStringChecker ())
    3.74 +    .AddAttribute ("Start", 
    3.75 +                   "The simulation time at which to spin up the device thread.",
    3.76 +                   TimeValue (Seconds (0.)),
    3.77 +                   MakeTimeAccessor (&EmuNetDevice::m_tStart),
    3.78 +                   MakeTimeChecker ())
    3.79 +    .AddAttribute ("Stop", 
    3.80 +                   "The simulation time at which to tear down the device thread.",
    3.81 +                   TimeValue (Seconds (0.)),
    3.82 +                   MakeTimeAccessor (&EmuNetDevice::m_tStop),
    3.83 +                   MakeTimeChecker ())
    3.84 +    .AddAttribute ("TxQueue", 
    3.85 +                   "A queue to use as the transmit queue in the device.",
    3.86 +                   PointerValue (),
    3.87 +                   MakePointerAccessor (&EmuNetDevice::m_queue),
    3.88 +                   MakePointerChecker<Queue> ())
    3.89 +    .AddTraceSource ("Rx", 
    3.90 +                     "Trace source to fire on reception of a MAC packet.",
    3.91 +                     MakeTraceSourceAccessor (&EmuNetDevice::m_rxTrace))
    3.92 +    .AddTraceSource ("Drop", 
    3.93 +                     "Trace source to fire on when a MAC packet is dropped.",
    3.94 +                     MakeTraceSourceAccessor (&EmuNetDevice::m_dropTrace))
    3.95 +    ;
    3.96 +  return tid;
    3.97 +}
    3.98 +
    3.99 +
   3.100 +EmuNetDevice::EmuNetDevice () 
   3.101 +: 
   3.102 +  m_startEvent (),
   3.103 +  m_stopEvent (),
   3.104 +  m_sock (-1),
   3.105 +  m_readThread (0),
   3.106 +  m_ifIndex (-1),
   3.107 +  m_sll_ifindex (-1),
   3.108 +  m_name ("Emu NetDevice")
   3.109 +{
   3.110 +  NS_LOG_FUNCTION (this);
   3.111 +  Start (m_tStart);
   3.112 +}
   3.113 +
   3.114 +EmuNetDevice::~EmuNetDevice ()
   3.115 +{
   3.116 +}
   3.117 +
   3.118 +void 
   3.119 +EmuNetDevice::DoDispose()
   3.120 +{
   3.121 +  NS_LOG_FUNCTION_NOARGS ();
   3.122 +  m_node = 0;
   3.123 +  NetDevice::DoDispose ();
   3.124 +}
   3.125 +
   3.126 +void
   3.127 +EmuNetDevice::Start (Time tStart)
   3.128 +{
   3.129 +  NS_LOG_FUNCTION (tStart);
   3.130 +
   3.131 +  //
   3.132 +  // Cancel any pending start event and schedule a new one at some relative time in the future.
   3.133 +  //
   3.134 +  Simulator::Cancel (m_startEvent);
   3.135 +  m_startEvent = Simulator::Schedule (tStart, &EmuNetDevice::StartDevice, this);
   3.136 +}
   3.137 +
   3.138 +  void
   3.139 +EmuNetDevice::Stop (Time tStop)
   3.140 +{
   3.141 +  NS_LOG_FUNCTION (tStop);
   3.142 +  //
   3.143 +  // Cancel any pending stop event and schedule a new one at some relative time in the future.
   3.144 +  //
   3.145 +  Simulator::Cancel (m_stopEvent);
   3.146 +  m_startEvent = Simulator::Schedule (tStop, &EmuNetDevice::StopDevice, this);
   3.147 +}
   3.148 +
   3.149 +  void
   3.150 +EmuNetDevice::StartDevice (void)
   3.151 +{
   3.152 +  NS_LOG_FUNCTION_NOARGS ();
   3.153 +
   3.154 +  //
   3.155 +  // Spin up the emu net device and start receiving packets.
   3.156 +  //
   3.157 +  NS_ASSERT_MSG (m_sock == -1, "EmuNetDevice::StartDevice(): Device is already started");
   3.158 +
   3.159 +  NS_LOG_LOGIC ("Creating socket");
   3.160 +  //
   3.161 +  // Call out to a separate process running as suid root in order to get a raw 
   3.162 +  // socket.  We do this to avoid having the entire simulation running as root.
   3.163 +  // If this method returns, we'll have a raw socket waiting for us in m_sock.
   3.164 +  //
   3.165 +  CreateSocket ();
   3.166 +
   3.167 +  //
   3.168 +  // Figure out which interface index corresponds to the device name in the corresponding attribute.
   3.169 +  //
   3.170 +  struct ifreq ifr;
   3.171 +  bzero (&ifr, sizeof(ifr));
   3.172 +  strncpy ((char *)ifr.ifr_name, m_deviceName.c_str (), IFNAMSIZ);
   3.173 +
   3.174 +  NS_LOG_LOGIC ("Getting interface index");
   3.175 +  int32_t rc = ioctl (m_sock, SIOCGIFINDEX, &ifr);
   3.176 +  NS_ASSERT_MSG (rc != -1, "EmuNetDevice::StartDevice(): Can't get interface index");
   3.177 +
   3.178 +  //
   3.179 +  // Save the real interface index for later calls to sendto
   3.180 +  //
   3.181 +  m_sll_ifindex = ifr.ifr_ifindex;
   3.182 +
   3.183 +  //
   3.184 +  // Bind the socket to the interface we just found.
   3.185 +  //
   3.186 +  struct sockaddr_ll ll;
   3.187 +  bzero (&ll, sizeof(ll));
   3.188 +
   3.189 +  ll.sll_family = AF_PACKET;
   3.190 +  ll.sll_ifindex = m_sll_ifindex;
   3.191 +  ll.sll_protocol = htons(ETH_P_ALL); 
   3.192 +
   3.193 +  NS_LOG_LOGIC ("Binding socket to interface");
   3.194 +
   3.195 +  rc = bind (m_sock, (struct sockaddr *)&ll, sizeof (ll));
   3.196 +  NS_ASSERT_MSG (rc != -1, "EmuNetDevice::StartDevice(): Can't bind to specified interface");
   3.197 +
   3.198 +  //
   3.199 +  // Now spin up a read thread to read packets.
   3.200 +  //
   3.201 +  NS_ASSERT_MSG (m_readThread == 0, "EmuNetDevice::StartDevice(): Receive thread is already running");
   3.202 +
   3.203 +  NS_LOG_LOGIC ("Spinning up read thread");
   3.204 +
   3.205 +  m_readThread = Create<SystemThread> (MakeCallback (&EmuNetDevice::ReadThread, this));
   3.206 +  m_readThread->Start ();
   3.207 +
   3.208 +  NotifyLinkUp ();
   3.209 +}
   3.210 +
   3.211 +void
   3.212 +EmuNetDevice::CreateSocket (void)
   3.213 +{
   3.214 +  NS_LOG_FUNCTION_NOARGS ();
   3.215 +  //
   3.216 +  // We want to create a raw socket for our net device.  Unfortunately for us
   3.217 +  // you have to have root privileges to do that.  Instead of running the 
   3.218 +  // entire simulation as root, we decided to make a small program who's whole
   3.219 +  // reason for being is to run as suid root and create a raw socket.  We're
   3.220 +  // going to fork and exec that program soon, but we need to have a socket
   3.221 +  // to talk to it with.  So we create a local interprocess (Unix) socket 
   3.222 +  // for that purpose.
   3.223 +  //
   3.224 +  int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
   3.225 +  if (sock == -1)
   3.226 +    {
   3.227 +      NS_FATAL_ERROR ("EmuNetDevice::CreateSocket(): Unix socket creation error, errno = " << strerror (errno));
   3.228 +    }
   3.229 +
   3.230 +  //
   3.231 +  // Bind to that socket and let the kernel allocate an endpoint
   3.232 +  //
   3.233 +  struct sockaddr_un un;
   3.234 +  memset (&un, 0, sizeof (un));
   3.235 +  un.sun_family = AF_UNIX;
   3.236 +  int status = bind (sock, (struct sockaddr*)&un, sizeof (sa_family_t));
   3.237 +  if (status == -1)
   3.238 +    {
   3.239 +      NS_FATAL_ERROR ("EmuNetDevice::CreateSocket(): Could not bind(): errno = " << strerror (errno));
   3.240 +    }
   3.241 +
   3.242 +  //
   3.243 +  // We have a socket here, but we want to get it there -- to the program we're
   3.244 +  // going to exec.  What we'll do is to do a getsockname and then encode the
   3.245 +  // resulting address information as a string, and then send the string to the
   3.246 +  // program as an argument.  So we need to get the sock name.
   3.247 +  //
   3.248 +  socklen_t len = sizeof (un);
   3.249 +  status = getsockname (sock, (struct sockaddr*)&un, &len);
   3.250 +  if (status == -1)
   3.251 +    {
   3.252 +      NS_FATAL_ERROR ("EmuNetDevice::CreateSocket(): Could not getsockname(): errno = " << strerror (errno));
   3.253 +    }
   3.254 +
   3.255 +  //
   3.256 +  // Now encode that socket name (endpoint information) as a string
   3.257 +  //
   3.258 +  std::string endpoint = EmuBufferToString((uint8_t *)&un, len);
   3.259 +
   3.260 +  //
   3.261 +  // Fork and exec the process to create our socket.  If we're us (the parent)
   3.262 +  // we wait for the child (the socket creator) to complete and read the 
   3.263 +  // socket it created using the ancillary data mechanism.
   3.264 +  //
   3.265 +  pid_t pid = ::fork ();
   3.266 +  if (pid == 0)
   3.267 +    {
   3.268 +      NS_LOG_DEBUG ("Child process");
   3.269 +
   3.270 +      //
   3.271 +      // build a command line argument from the encoded endpoint string that 
   3.272 +      // the socket creation process will use to figure out how to respond to
   3.273 +      // the (now) parent process.
   3.274 +      //
   3.275 +      std::ostringstream oss;
   3.276 +      oss << "-p " << endpoint;
   3.277 +
   3.278 +      //
   3.279 +      // Execute the socket creation process image.
   3.280 +      //
   3.281 +      status = ::execl (FindCreator ().c_str (), "emu-sock-creator", oss.str ().c_str (), (char *)NULL);
   3.282 +
   3.283 +      //
   3.284 +      // If the execl successfully completes, it never returns.  If it returns it failed or the OS is
   3.285 +      // broken.  In either case, we bail.
   3.286 +      //
   3.287 +      NS_FATAL_ERROR ("EmuNetDevice::CreateSocket(): Back from execl(), errno = " << ::strerror (errno));
   3.288 +    }
   3.289 +  else
   3.290 +    {
   3.291 +      NS_LOG_DEBUG ("Parent process");
   3.292 +      //
   3.293 +      // We're the process running the emu net device.  We need to wait for the
   3.294 +      // socket creator process to finish its job.
   3.295 +      //
   3.296 +      int st;
   3.297 +      pid_t waited = waitpid (pid, &st, 0);
   3.298 +      if (waited == -1)
   3.299 +	{
   3.300 +	  NS_FATAL_ERROR ("EmuNetDevice::CreateSocket(): waitpid() fails, errno = " << strerror (errno));
   3.301 +	}
   3.302 +      NS_ASSERT_MSG (pid == waited, "EmuNetDevice::CreateSocket(): pid mismatch");
   3.303 +
   3.304 +      //
   3.305 +      // Check to see if the socket creator exited normally and then take a 
   3.306 +      // look at the exit code.  If it bailed, so should we.  If it didn't
   3.307 +      // even exit normally, we bail too.
   3.308 +      //
   3.309 +      if (WIFEXITED (st))
   3.310 +	{
   3.311 +          int exitStatus = WEXITSTATUS (st);
   3.312 +          if (exitStatus != 0)
   3.313 +            {
   3.314 +              NS_FATAL_ERROR ("EmuNetDevice::CreateSocket(): socket creator exited normally with status " << exitStatus);
   3.315 +            }
   3.316 +	}
   3.317 +      else 
   3.318 +	{
   3.319 +          NS_FATAL_ERROR ("EmuNetDevice::CreateSocket(): socket creator exited abnormally");
   3.320 +	}
   3.321 +
   3.322 +      //
   3.323 +      // At this point, the socket creator has run successfully and should 
   3.324 +      // have created our raw socket and sent it back to the socket address
   3.325 +      // we provided.  Our socket should be waiting on the Unix socket.  We've
   3.326 +      // got to do a bunch of grunto work to get at it, though.
   3.327 +      //
   3.328 +      // The struct iovec below is part of a scatter-gather list.  It describes a
   3.329 +      // buffer.  In this case, it describes a buffer (an integer) that will
   3.330 +      // get the data that comes back from the socket creator process.  It will
   3.331 +      // be a magic number that we use as a consistency/sanity check.
   3.332 +      // 
   3.333 +      struct iovec iov;
   3.334 +      uint32_t magic;
   3.335 +      iov.iov_base = &magic;
   3.336 +      iov.iov_len = sizeof(magic);
   3.337 +
   3.338 +      //
   3.339 +      // The CMSG macros you'll see below are used to create and access control 
   3.340 +      // messages (which is another name for ancillary data).  The ancillary 
   3.341 +      // data is made up of pairs of struct cmsghdr structures and associated
   3.342 +      // data arrays.
   3.343 +      //
   3.344 +      // First, we're going to allocate a buffer on the stack to receive our 
   3.345 +      // data array (that contains the socket).  Sometimes you'll see this called
   3.346 +      // an "ancillary element" but the msghdr uses the control message termimology
   3.347 +      // so we call it "control."
   3.348 +      //
   3.349 +      size_t msg_size = sizeof(int);
   3.350 +      char control[CMSG_SPACE(msg_size)];
   3.351 +
   3.352 +      //
   3.353 +      // There is a msghdr that is used to minimize the number of parameters
   3.354 +      // passed to recvmsg (which we will use to receive our ancillary data).  
   3.355 +      // This structure uses terminology corresponding to control messages, so
   3.356 +      // you'll see msg_control, which is the pointer to the ancillary data and 
   3.357 +      // controllen which is the size of the ancillary data array.
   3.358 +      //
   3.359 +      // So, initialize the message header that describes the ancillary/control
   3.360 +      // data we expect to receive and point it to buffer.
   3.361 +      //
   3.362 +      struct msghdr msg;
   3.363 +      msg.msg_name = 0;
   3.364 +      msg.msg_namelen = 0;
   3.365 +      msg.msg_iov = &iov;
   3.366 +      msg.msg_iovlen = 1;
   3.367 +      msg.msg_control = control;
   3.368 +      msg.msg_controllen = sizeof (control);
   3.369 +      msg.msg_flags = 0;
   3.370 +
   3.371 +      //
   3.372 +      // Now we can actually receive the interesting bits from the socket
   3.373 +      // creator process.
   3.374 +      //
   3.375 +      ssize_t bytesRead = recvmsg (sock, &msg, 0);
   3.376 +      if (bytesRead != sizeof(int))
   3.377 +	{
   3.378 +          NS_FATAL_ERROR ("EmuNetDevice::CreateSocket(): Wrong byte count from socket creator");
   3.379 +	}
   3.380 +
   3.381 +      //
   3.382 +      // There may be a number of message headers/ancillary data arrays coming in.
   3.383 +      // Let's look for the one with a type SCM_RIGHTS which indicates it' the
   3.384 +      // one we're interested in.
   3.385 +      //
   3.386 +      struct cmsghdr *cmsg;
   3.387 +      for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) 
   3.388 +	{
   3.389 +	  if (cmsg->cmsg_level == SOL_SOCKET &&
   3.390 +	      cmsg->cmsg_type == SCM_RIGHTS)
   3.391 +	    {
   3.392 +	      int *rawSocket = (int*)CMSG_DATA (cmsg);
   3.393 +	      NS_LOG_INFO ("Got the socket from the socket creator = " << *rawSocket);
   3.394 +              m_sock = *rawSocket;
   3.395 +              return;
   3.396 +	    }
   3.397 +	}
   3.398 +      NS_FATAL_ERROR ("Did not get the raw socket from the socket creator");
   3.399 +    }
   3.400 +}
   3.401 +
   3.402 +std::string
   3.403 +EmuNetDevice::FindCreator (void)
   3.404 +{
   3.405 +  struct stat st;
   3.406 +  std::string debug = "./build/debug/src/devices/emu/emu-sock-creator";
   3.407 +  std::string optimized = "./build/optimized/src/devices/emu/emu-sock-creator";
   3.408 +
   3.409 +  if (::stat (debug.c_str (), &st) == 0)
   3.410 +    {
   3.411 +      return debug;
   3.412 +    }
   3.413 +
   3.414 +  if (::stat (optimized.c_str (), &st) == 0)
   3.415 +    {
   3.416 +      return optimized;
   3.417 +    }
   3.418 +
   3.419 +  NS_FATAL_ERROR ("EmuNetDevice::FindCreator(): Couldn't find creator");
   3.420 +  return ""; // quiet compiler
   3.421 +}
   3.422 +
   3.423 +void
   3.424 +EmuNetDevice::StopDevice (void)
   3.425 +{
   3.426 +  NS_LOG_FUNCTION_NOARGS ();
   3.427 +
   3.428 +  close (m_sock);
   3.429 +  m_sock = -1;
   3.430 +
   3.431 +  NS_ASSERT_MSG (m_readThread != 0, "EmuNetDevice::StopDevice(): Receive thread is not running");
   3.432 +
   3.433 +  NS_LOG_LOGIC ("Joining read thread");
   3.434 +  m_readThread->Join ();
   3.435 +  m_readThread = 0;
   3.436 +}
   3.437 +
   3.438 +void
   3.439 +EmuNetDevice::ForwardUp (uint8_t *buf, uint32_t len)
   3.440 +{
   3.441 +  NS_LOG_FUNCTION (buf << len);
   3.442 +
   3.443 +  //
   3.444 +  // Create a packet out of the buffer we received and free that buffer.
   3.445 +  //
   3.446 +  Ptr<Packet> packet = Create<Packet> (reinterpret_cast<const uint8_t *> (buf), len);
   3.447 +  free (buf);
   3.448 +  buf = 0;
   3.449 +
   3.450 +  //
   3.451 +  // Trace sinks will expect complete packets, not packets without some of the
   3.452 +  // headers.
   3.453 +  //
   3.454 +  Ptr<Packet> originalPacket = packet->Copy ();
   3.455 +
   3.456 +  //
   3.457 +  // Checksum the packet
   3.458 +  //
   3.459 +  EthernetTrailer trailer;
   3.460 +  packet->RemoveTrailer (trailer);
   3.461 +  trailer.CheckFcs (packet);
   3.462 +
   3.463 +  EthernetHeader header (false);
   3.464 +  packet->RemoveHeader (header);
   3.465 +
   3.466 +  NS_LOG_LOGIC ("Pkt source is " << header.GetSource ());
   3.467 +  NS_LOG_LOGIC ("Pkt destination is " << header.GetDestination ());
   3.468 +
   3.469 +  //
   3.470 +  // An IP host group address is mapped to an Ethernet multicast address
   3.471 +  // by placing the low-order 23-bits of the IP address into the low-order
   3.472 +  // 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 (hex).
   3.473 +  //
   3.474 +  // We are going to receive all packets destined to any multicast address,
   3.475 +  // which means clearing the low-order 23 bits the header destination 
   3.476 +  //
   3.477 +  Mac48Address mcDest;
   3.478 +  uint8_t      mcBuf[6];
   3.479 +
   3.480 +  header.GetDestination ().CopyTo (mcBuf);
   3.481 +  mcBuf[3] &= 0x80;
   3.482 +  mcBuf[4] = 0;
   3.483 +  mcBuf[5] = 0;
   3.484 +  mcDest.CopyFrom (mcBuf);
   3.485 +
   3.486 +  Mac48Address multicast = Mac48Address::ConvertFrom (GetMulticast ());
   3.487 +  Mac48Address broadcast = Mac48Address::ConvertFrom (GetBroadcast ());
   3.488 +  Mac48Address destination = Mac48Address::ConvertFrom (GetAddress ());
   3.489 +
   3.490 +  LlcSnapHeader llc;
   3.491 +  packet->RemoveHeader (llc);
   3.492 +  uint16_t protocol = llc.GetType ();
   3.493 +
   3.494 +  PacketType packetType;
   3.495 +      
   3.496 +  if (header.GetDestination () == broadcast)
   3.497 +    {
   3.498 +      NS_LOG_LOGIC ("Pkt destination is PACKET_BROADCAST");
   3.499 +      packetType = NS3_PACKET_BROADCAST;
   3.500 +    }
   3.501 +  else if (mcDest == multicast)
   3.502 +    {
   3.503 +      NS_LOG_LOGIC ("Pkt destination is PACKET_MULTICAST");
   3.504 +      packetType = NS3_PACKET_MULTICAST;
   3.505 +    }
   3.506 +  else if (header.GetDestination () == destination)
   3.507 +    {
   3.508 +      NS_LOG_LOGIC ("Pkt destination is PACKET_HOST");
   3.509 +      packetType = NS3_PACKET_HOST;
   3.510 +    }
   3.511 +  else
   3.512 +    {
   3.513 +      NS_LOG_LOGIC ("Pkt destination is PACKET_OTHERHOST");
   3.514 +      packetType = NS3_PACKET_OTHERHOST;
   3.515 +    }
   3.516 +
   3.517 +  if (!m_promiscRxCallback.IsNull ())
   3.518 +    {
   3.519 +      NS_LOG_LOGIC ("calling m_promiscRxCallback");
   3.520 +      m_promiscRxCallback (this, packet->Copy (), protocol, header.GetSource (), header.GetDestination (), packetType);
   3.521 +    }
   3.522 +
   3.523 +  if (packetType != NS3_PACKET_OTHERHOST)
   3.524 +    {
   3.525 +      m_rxTrace (originalPacket);
   3.526 +      NS_LOG_LOGIC ("calling m_rxCallback");
   3.527 +      m_rxCallback (this, packet, protocol, header.GetSource ());
   3.528 +    }
   3.529 +}
   3.530 +
   3.531 +void
   3.532 +EmuNetDevice::ReadThread (void)
   3.533 +{
   3.534 +  NS_LOG_FUNCTION_NOARGS ();
   3.535 +
   3.536 +  //
   3.537 +  // It's important to remember that we're in a completely different thread than the simulator is running in.  We
   3.538 +  // need to synchronize with that other thread to get the packet up into ns-3.  What we will need to do is to schedule 
   3.539 +  // a method to forward up the packet using the multithreaded simulator we are most certainly running.  However, I just 
   3.540 +  // said it -- we are talking about two threads here, so it is very, very dangerous to do any kind of reference couning
   3.541 +  // on a shared object.  Just don't do it.  So what we're going to do is to allocate a buffer on the heap and pass that
   3.542 +  // buffer into the ns-3 context thread where it will create the packet.
   3.543 +  //
   3.544 +
   3.545 +  int32_t len = -1;
   3.546 +  struct sockaddr_ll addr;
   3.547 +  socklen_t addrSize = sizeof (addr);
   3.548 +
   3.549 +  for (;;) 
   3.550 +    {
   3.551 +      uint32_t bufferSize = 65536;
   3.552 +      uint8_t *buf = (uint8_t *)malloc (bufferSize);
   3.553 +      NS_ASSERT_MSG (buf, "EmuNetDevice::ReadThread(): malloc packet buffer failed");
   3.554 +      NS_LOG_LOGIC ("Calling recvfrom");
   3.555 +      len = recvfrom (m_sock, buf, bufferSize, 0, (struct sockaddr *)&addr, &addrSize);
   3.556 +
   3.557 +      if (len == -1)
   3.558 +        {
   3.559 +          free (buf);
   3.560 +          buf = 0;
   3.561 +          return;
   3.562 +        }
   3.563 +
   3.564 +      NS_LOG_INFO ("EmuNetDevice::ReadThread(): Received packet");
   3.565 +      NS_LOG_INFO ("EmuNetDevice::ReadThread(): Scheduling handler");
   3.566 +      DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ())->ScheduleRealtimeNow (
   3.567 +        MakeEvent (&EmuNetDevice::ForwardUp, this, buf, len));
   3.568 +      buf = 0;
   3.569 +    }
   3.570 +}
   3.571 +
   3.572 +bool 
   3.573 +EmuNetDevice::Send (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
   3.574 +{
   3.575 +  NS_LOG_FUNCTION (packet << dest << protocolNumber);
   3.576 +  //
   3.577 +  // The immediate questions here are how are we going to encapsulate packets and what do we use as the MAC source and 
   3.578 +  // destination (hardware) addresses?
   3.579 +  //
   3.580 +  // If we return false from EmuNetDevice::NeedsArp, the ArpIpv4Interface will pass the broadcast address as the 
   3.581 +  // hardware (Ethernet) destination by default.  If we return true from EmuNetDevice::NeedsArp, then the hardware
   3.582 +  // destination is actually meaningful, but we'll have an ns-3 ARP running on this device.  There can also be an ARP
   3.583 +  // running on the underlying OS so we have to be very careful, both about multiple ARPs and also about TCP, UDP, etc.
   3.584 +  //
   3.585 +  // We are operating in promiscuous mode on the receive side (all ns-3 net devices are required to implement the 
   3.586 +  // promiscuous callback in a meaningful way), so we have an option regarding the hardware addresses.  We don't actually have
   3.587 +  // to use the real hardware addresses and IP addresses of the underlying system.  We can completely use MAC-spoofing to
   3.588 +  // fake out the OS by using the ns-3 assigned MAC address (and also the ns-3 assigned IP addresses).  Ns-3 starts its 
   3.589 +  // MAC address allocation using the OUI (vendor-code) 00:00:00 which is unassigned to any organization and is a globally
   3.590 +  // administered address, so there shouldn't be any collisions with real hardware.
   3.591 +  //
   3.592 +  // So what we do is we return true from EmuNetDevice::NeedsArp which tells ns-3 to use its own ARP.  We spoof the 
   3.593 +  // MAC address of the device and use promiscuous mode to receive traffic destined to that address.
   3.594 +  //
   3.595 +  return SendFrom (packet, m_address, dest, protocolNumber);
   3.596 +}
   3.597 +
   3.598 +bool 
   3.599 +EmuNetDevice::SendFrom (Ptr<Packet> packet, const Address &src, const Address &dest, uint16_t protocolNumber)
   3.600 +{
   3.601 +  NS_LOG_FUNCTION (packet << src << dest << protocolNumber);
   3.602 +
   3.603 +  if (IsLinkUp () == false)
   3.604 +    {
   3.605 +      NS_LOG_LOGIC ("Link is down, returning");
   3.606 +      return false;
   3.607 +    }
   3.608 +
   3.609 +  Mac48Address destination = Mac48Address::ConvertFrom (dest);
   3.610 +  Mac48Address source = Mac48Address::ConvertFrom (src);
   3.611 +
   3.612 +  NS_LOG_LOGIC ("Transmit packet with UID " << packet->GetUid ());
   3.613 +  NS_LOG_LOGIC ("Transmit packet from " << source);
   3.614 +  NS_LOG_LOGIC ("Transmit packet to " << destination);
   3.615 +
   3.616 +#if 0
   3.617 +  {
   3.618 +    struct ifreq ifr;
   3.619 +    bzero (&ifr, sizeof(ifr));
   3.620 +    strncpy ((char *)ifr.ifr_name, m_deviceName.c_str (), IFNAMSIZ);
   3.621 +
   3.622 +    NS_LOG_LOGIC ("Getting MAC address");
   3.623 +    int32_t rc = ioctl (m_sock, SIOCGIFHWADDR, &ifr);
   3.624 +    NS_ASSERT_MSG (rc != -1, "EmuNetDevice::SendFrom(): Can't get MAC address");
   3.625 +
   3.626 +    std::ostringstream oss;
   3.627 +    oss << std::hex <<
   3.628 +      (ifr.ifr_hwaddr.sa_data[0] & 0xff) << ":" <<
   3.629 +      (ifr.ifr_hwaddr.sa_data[1] & 0xff) << ":" <<
   3.630 +      (ifr.ifr_hwaddr.sa_data[2] & 0xff) << ":" <<
   3.631 +      (ifr.ifr_hwaddr.sa_data[3] & 0xff) << ":" <<
   3.632 +      (ifr.ifr_hwaddr.sa_data[4] & 0xff) << ":" <<
   3.633 +      (ifr.ifr_hwaddr.sa_data[5] & 0xff) << std::dec;
   3.634 +
   3.635 +    NS_LOG_LOGIC ("Fixup source to HW MAC " << oss.str ());
   3.636 +    source = Mac48Address (oss.str ().c_str ());
   3.637 +    NS_LOG_LOGIC ("source now " << source);
   3.638 +  }
   3.639 +#endif
   3.640 +
   3.641 +  LlcSnapHeader llc;
   3.642 +  llc.SetType (protocolNumber);
   3.643 +  packet->AddHeader (llc);
   3.644 +
   3.645 +  EthernetHeader header (false);
   3.646 +  header.SetSource (source);
   3.647 +  header.SetDestination (destination);
   3.648 +  header.SetLengthType (packet->GetSize ());
   3.649 +  packet->AddHeader (header);
   3.650 +
   3.651 +  EthernetTrailer trailer;
   3.652 +  trailer.CalcFcs (packet);
   3.653 +  packet->AddTrailer (trailer);
   3.654 +
   3.655 +  // 
   3.656 +  // Enqueue and dequeue the packet to hit the tracing hooks.
   3.657 +  //
   3.658 +  m_queue->Enqueue (packet);
   3.659 +  packet = m_queue->Dequeue ();
   3.660 +
   3.661 +  struct sockaddr_ll ll;
   3.662 +  bzero (&ll, sizeof (ll));
   3.663 +
   3.664 +  ll.sll_family = AF_PACKET;
   3.665 +  ll.sll_ifindex = m_sll_ifindex;
   3.666 +  ll.sll_protocol = htons(ETH_P_ALL); 
   3.667 +
   3.668 +  NS_LOG_LOGIC ("calling sendto");
   3.669 +
   3.670 +  int32_t rc;
   3.671 +  rc = sendto (m_sock, packet->PeekData (), packet->GetSize (), 0, reinterpret_cast<struct sockaddr *> (&ll), sizeof (ll));
   3.672 +
   3.673 +  NS_LOG_LOGIC ("sendto returns " << rc);
   3.674 +
   3.675 +  return rc == -1 ? false : true;
   3.676 +}
   3.677 +
   3.678 +void 
   3.679 +EmuNetDevice::SetDataRate(DataRate bps)
   3.680 +{
   3.681 +  NS_LOG_FUNCTION (this << bps);
   3.682 +  NS_ASSERT_MSG (false, "EmuNetDevice::SetDataRate():  Unable."); 
   3.683 +}
   3.684 +
   3.685 +void
   3.686 +EmuNetDevice::SetQueue (Ptr<Queue> q)
   3.687 +{
   3.688 +  NS_LOG_FUNCTION (this << q);
   3.689 +  m_queue = q;
   3.690 +}
   3.691 +
   3.692 +Ptr<Queue> 
   3.693 +EmuNetDevice::GetQueue(void) const 
   3.694 +{ 
   3.695 +  NS_LOG_FUNCTION_NOARGS ();
   3.696 +  return m_queue;
   3.697 +}
   3.698 +
   3.699 +void
   3.700 +EmuNetDevice::NotifyLinkUp (void)
   3.701 +{
   3.702 +  m_linkUp = true;
   3.703 +  if (!m_linkChangeCallback.IsNull ())
   3.704 +    {
   3.705 +      m_linkChangeCallback ();
   3.706 +    }
   3.707 +}
   3.708 +
   3.709 +void 
   3.710 +EmuNetDevice::SetName(const std::string name)
   3.711 +{
   3.712 +  m_name = name;
   3.713 +}
   3.714 +
   3.715 +std::string 
   3.716 +EmuNetDevice::GetName(void) const
   3.717 +{
   3.718 +  return m_name;
   3.719 +}
   3.720 +
   3.721 +void 
   3.722 +EmuNetDevice::SetIfIndex(const uint32_t index)
   3.723 +{
   3.724 +  m_ifIndex = index;
   3.725 +}
   3.726 +
   3.727 +uint32_t 
   3.728 +EmuNetDevice::GetIfIndex(void) const
   3.729 +{
   3.730 +  return m_ifIndex;
   3.731 +}
   3.732 +
   3.733 +Ptr<Channel> 
   3.734 +EmuNetDevice::GetChannel (void) const
   3.735 +{
   3.736 +  NS_ASSERT_MSG (false, "EmuNetDevice::GetChannel():  Unable."); 
   3.737 +  return 0;
   3.738 +}
   3.739 +
   3.740 +void 
   3.741 +EmuNetDevice::SetAddress (Mac48Address addr)
   3.742 +{
   3.743 +  NS_LOG_FUNCTION (addr);
   3.744 +  m_address = addr;
   3.745 +}
   3.746 +
   3.747 +Address 
   3.748 +EmuNetDevice::GetAddress (void) const
   3.749 +{
   3.750 +  NS_LOG_FUNCTION_NOARGS ();
   3.751 +  return m_address;
   3.752 +}
   3.753 +
   3.754 +bool 
   3.755 +EmuNetDevice::SetMtu (const uint16_t mtu)
   3.756 +{
   3.757 +  NS_ASSERT_MSG (false, "EmuNetDevice::SetMtu():  Unable."); 
   3.758 +  return false;
   3.759 +}
   3.760 +
   3.761 +uint16_t 
   3.762 +EmuNetDevice::GetMtu (void) const
   3.763 +{
   3.764 +  struct ifreq ifr;
   3.765 +  bzero (&ifr, sizeof (ifr));
   3.766 +  strcpy(ifr.ifr_name, m_deviceName.c_str ());
   3.767 +
   3.768 +  int32_t fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
   3.769 +
   3.770 +  int32_t rc = ioctl(fd, SIOCGIFMTU, &ifr);
   3.771 +  NS_ASSERT_MSG (rc != -1, "EmuNetDevice::GetMtu(): Can't ioctl SIOCGIFMTU");
   3.772 +
   3.773 +  close (fd);
   3.774 +
   3.775 +  return ifr.ifr_mtu;
   3.776 +}
   3.777 +
   3.778 +bool 
   3.779 +EmuNetDevice::IsLinkUp (void) const
   3.780 +{
   3.781 +  return m_linkUp;
   3.782 +}
   3.783 +
   3.784 +void 
   3.785 +EmuNetDevice::SetLinkChangeCallback (Callback<void> callback)
   3.786 +{
   3.787 +  m_linkChangeCallback = callback;
   3.788 +}
   3.789 +
   3.790 +bool 
   3.791 +EmuNetDevice::IsBroadcast (void) const
   3.792 +{
   3.793 +  return true;
   3.794 +}
   3.795 +
   3.796 +Address
   3.797 +EmuNetDevice::GetBroadcast (void) const
   3.798 +{
   3.799 +  return Mac48Address ("ff:ff:ff:ff:ff:ff");
   3.800 +}
   3.801 +
   3.802 +bool 
   3.803 +EmuNetDevice::IsMulticast (void) const
   3.804 +{
   3.805 +  return false;
   3.806 +}
   3.807 +
   3.808 +Address 
   3.809 +EmuNetDevice::GetMulticast (void) const
   3.810 +{
   3.811 +  return Mac48Address ("01:00:5e:00:00:00");
   3.812 +}
   3.813 +
   3.814 +Address 
   3.815 +EmuNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
   3.816 +{
   3.817 +  return Mac48Address ("01:00:5e:00:00:00");
   3.818 +}
   3.819 +
   3.820 +bool 
   3.821 +EmuNetDevice::IsPointToPoint (void) const
   3.822 +{
   3.823 +  return false;
   3.824 +}
   3.825 +
   3.826 +void
   3.827 +EmuNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
   3.828 +{
   3.829 +  NS_ASSERT_MSG (false, "EmuNetDevice::SetPromiscReceiveCallback(): Not implemented");
   3.830 +}
   3.831 +
   3.832 +  bool 
   3.833 +EmuNetDevice::SupportsSendFrom () const
   3.834 +{
   3.835 +  NS_LOG_FUNCTION_NOARGS ();
   3.836 +  return true;
   3.837 +}
   3.838 +
   3.839 +
   3.840 +Ptr<Node> 
   3.841 +EmuNetDevice::GetNode (void) const
   3.842 +{
   3.843 +  return m_node;
   3.844 +}
   3.845 +
   3.846 +void 
   3.847 +EmuNetDevice::SetNode (Ptr<Node> node)
   3.848 +{
   3.849 +  m_node = node;
   3.850 +}
   3.851 +
   3.852 +bool 
   3.853 +EmuNetDevice::NeedsArp (void) const
   3.854 +{
   3.855 +  return true;
   3.856 +}
   3.857 +
   3.858 +void 
   3.859 +EmuNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
   3.860 +{
   3.861 +  m_rxCallback = cb;
   3.862 +}
   3.863 +
   3.864 +} // namespace ns3
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/devices/emu/emu-net-device.h	Wed Oct 29 22:39:36 2008 -0700
     4.3 @@ -0,0 +1,333 @@
     4.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     4.5 +/*
     4.6 + * Copyright (c) 2008 University of Washington
     4.7 + *
     4.8 + * This program is free software; you can redistribute it and/or modify
     4.9 + * it under the terms of the GNU General Public License version 2 as
    4.10 + * published by the Free Software Foundation;
    4.11 + *
    4.12 + * This program is distributed in the hope that it will be useful,
    4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.15 + * GNU General Public License for more details.
    4.16 + *
    4.17 + * You should have received a copy of the GNU General Public License
    4.18 + * along with this program; if not, write to the Free Software
    4.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    4.20 + */
    4.21 +
    4.22 +#ifndef EMU_NET_DEVICE_H
    4.23 +#define EMU_NET_DEVICE_H
    4.24 +
    4.25 +#include <string.h>
    4.26 +#include "ns3/address.h"
    4.27 +#include "ns3/net-device.h"
    4.28 +#include "ns3/node.h"
    4.29 +#include "ns3/callback.h"
    4.30 +#include "ns3/packet.h"
    4.31 +#include "ns3/traced-callback.h"
    4.32 +#include "ns3/event-id.h"
    4.33 +#include "ns3/nstime.h"
    4.34 +#include "ns3/data-rate.h"
    4.35 +#include "ns3/ptr.h"
    4.36 +#include "ns3/mac48-address.h"
    4.37 +#include "ns3/system-thread.h"
    4.38 +
    4.39 +namespace ns3 {
    4.40 +
    4.41 +class Queue;
    4.42 +
    4.43 +/**
    4.44 + * \class EmuNetDevice
    4.45 + * \brief A Device for an Emu Network Link.
    4.46 + */
    4.47 +class EmuNetDevice : public NetDevice 
    4.48 +{
    4.49 +public:
    4.50 +  static TypeId GetTypeId (void);
    4.51 +
    4.52 +  /**
    4.53 +   * Construct a EmuNetDevice
    4.54 +   *
    4.55 +   * This is the constructor for the EmuNetDevice.  It takes as a
    4.56 +   */
    4.57 +  EmuNetDevice ();
    4.58 +
    4.59 +  /**
    4.60 +   * Destroy a EmuNetDevice
    4.61 +   *
    4.62 +   * This is the destructor for the EmuNetDevice.
    4.63 +   */
    4.64 +  virtual ~EmuNetDevice ();
    4.65 +
    4.66 +  /**
    4.67 +   * Set the Data Rate used for transmission of packets.  
    4.68 +   *
    4.69 +   * @see Attach ()
    4.70 +   * @param bps the data rate at which this object operates
    4.71 +   */
    4.72 +  void SetDataRate (DataRate bps);
    4.73 +
    4.74 +  /**
    4.75 +   * Set the inteframe gap used to separate packets.  The interframe gap
    4.76 +   * defines the minimum space required between packets sent by this device.
    4.77 +   *
    4.78 +   * @param t the interframe gap time
    4.79 +   */
    4.80 +  void SetInterframeGap (Time t);
    4.81 +
    4.82 +  /**
    4.83 +   * Set a start time for the device.
    4.84 +   *
    4.85 +   * @param tStart the start time
    4.86 +   */
    4.87 +  void Start (Time tStart);
    4.88 +
    4.89 +  /**
    4.90 +   * Set a stop time for the device.
    4.91 +   *
    4.92 +   * @param tStop the stop time
    4.93 +   */
    4.94 +  void Stop (Time tStop);
    4.95 +
    4.96 +  /**
    4.97 +   * Attach a queue to the EmuNetDevice.
    4.98 +   *
    4.99 +   * The EmuNetDevice "owns" a queue that implements a queueing 
   4.100 +   * method such as DropTail or RED.  
   4.101 +   *
   4.102 +   * @see Queue
   4.103 +   * @see DropTailQueue
   4.104 +   * @param queue Ptr to the new queue.
   4.105 +   */
   4.106 +  void SetQueue (Ptr<Queue> queue);
   4.107 +
   4.108 +  /**
   4.109 +   * Receive a packet.
   4.110 +   *
   4.111 +   * The EmuNetDevice receives packets from its socket reader
   4.112 +   * and forwards them up the protocol stack.  This is the public method
   4.113 +   * used by the reader to indicate that a packet has arrived at the device.
   4.114 +   *
   4.115 +   * @param p Ptr to the received packet.
   4.116 +   */
   4.117 +  void Receive (Ptr<Packet> p);
   4.118 +
   4.119 +  /**
   4.120 +   * Assign a MAC address to this device.
   4.121 +   *
   4.122 +   * @see Mac48Address
   4.123 +   * @param addr The new address.
   4.124 +   */
   4.125 +  void SetAddress (Mac48Address addr);
   4.126 +
   4.127 +//
   4.128 +// Pure virtual methods inherited from NetDevice we must implement.
   4.129 +//
   4.130 +  virtual void SetName(const std::string name);
   4.131 +  virtual std::string GetName(void) const;
   4.132 +
   4.133 +  virtual void SetIfIndex(const uint32_t index);
   4.134 +  virtual uint32_t GetIfIndex(void) const;
   4.135 +
   4.136 +  virtual Ptr<Channel> GetChannel (void) const;
   4.137 +  virtual Address GetAddress (void) const;
   4.138 +
   4.139 +  virtual bool SetMtu (const uint16_t mtu);
   4.140 +  virtual uint16_t GetMtu (void) const;
   4.141 +
   4.142 +  virtual bool IsLinkUp (void) const;
   4.143 +
   4.144 +  virtual void SetLinkChangeCallback (Callback<void> callback);
   4.145 +
   4.146 +  virtual bool IsBroadcast (void) const;
   4.147 +  virtual Address GetBroadcast (void) const;
   4.148 +
   4.149 +  virtual bool IsMulticast (void) const;
   4.150 +  virtual Address GetMulticast (void) const;
   4.151 +  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
   4.152 +
   4.153 +  virtual bool IsPointToPoint (void) const;
   4.154 +
   4.155 +  virtual bool Send(Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber);
   4.156 +
   4.157 +  virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
   4.158 +
   4.159 +  virtual Ptr<Node> GetNode (void) const;
   4.160 +  virtual void SetNode (Ptr<Node> node);
   4.161 +
   4.162 +  virtual bool NeedsArp (void) const;
   4.163 +
   4.164 +  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
   4.165 +  virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
   4.166 +
   4.167 +  virtual bool SupportsSendFrom (void) const;
   4.168 +
   4.169 +private:
   4.170 +
   4.171 +  virtual void DoDispose (void);
   4.172 +
   4.173 +  /**
   4.174 +   * Call out to a separate process running as suid root in order to get a raw 
   4.175 +   * socket.  We do this to avoid having the entire simulation running as root.
   4.176 +   * If this method returns, we'll have a raw socket waiting for us in m_sock.
   4.177 +   */
   4.178 +  void CreateSocket (void);
   4.179 +
   4.180 +  /**
   4.181 +   * Figure out where the raw socket creation process lives on the system.
   4.182 +   */
   4.183 +  std::string FindCreator (void);
   4.184 +
   4.185 +  /**
   4.186 +   * Get a copy of the attached Queue.
   4.187 +   *
   4.188 +   * This method is provided for any derived class that may need to get
   4.189 +   * direct access to the underlying queue.
   4.190 +   *
   4.191 +   * @returns Ptr to the queue.
   4.192 +   */
   4.193 +  Ptr<Queue> GetQueue(void) const; 
   4.194 +
   4.195 +  /**
   4.196 +   * Spin up the device
   4.197 +   */
   4.198 +  void StartDevice (void);
   4.199 +
   4.200 +  /**
   4.201 +   * Tear down the device
   4.202 +   */
   4.203 +  void StopDevice (void);
   4.204 +
   4.205 +  /**
   4.206 +   * Loop to read and process packets
   4.207 +   */
   4.208 +  void ReadThread (void);
   4.209 +
   4.210 +  /**
   4.211 +   * Method to handle received packets.  Synchronized with simulator via ScheduleNow from ReadThread.
   4.212 +   */
   4.213 +  void ForwardUp (uint8_t *buf, uint32_t len);
   4.214 +
   4.215 +  /**
   4.216 +   * Adds the necessary headers and trailers to a packet of data in order to
   4.217 +   * respect the protocol implemented by the agent.
   4.218 +   */
   4.219 +  void AddHeader(Ptr<Packet> p, uint16_t protocolNumber);
   4.220 +
   4.221 +  /**
   4.222 +   * Removes, from a packet of data, all headers and trailers that
   4.223 +   * relate to the protocol implemented by the agent
   4.224 +   * \return Returns true if the packet should be forwarded up the
   4.225 +   * protocol stack.
   4.226 +   */
   4.227 +  bool ProcessHeader(Ptr<Packet> p, uint16_t& param);
   4.228 +
   4.229 +  /**
   4.230 +   * Start Sending a Packet Down the Wire.
   4.231 +   *
   4.232 +   * @returns true if success, false on failure
   4.233 +   */
   4.234 +  bool TransmitStart (Ptr<Packet> p);
   4.235 +
   4.236 +  void NotifyLinkUp (void);
   4.237 +
   4.238 +  /**
   4.239 +   * The Queue which this EmuNetDevice uses as a packet source.
   4.240 +   * Management of this Queue has been delegated to the EmuNetDevice
   4.241 +   * and it has the responsibility for deletion.
   4.242 +   * @see class Queue
   4.243 +   * @see class DropTailQueue
   4.244 +   */
   4.245 +  Ptr<Queue> m_queue;
   4.246 +
   4.247 +  /**
   4.248 +   * The trace source for the packet reception events that the device can
   4.249 +   * fire.
   4.250 +   *
   4.251 +   * @see class CallBackTraceSource
   4.252 +   */
   4.253 +  TracedCallback<Ptr<const Packet> > m_rxTrace;
   4.254 +
   4.255 +  /**
   4.256 +   * The trace source for the packet drop events that the device can
   4.257 +   * fire.
   4.258 +   *
   4.259 +   * @see class CallBackTraceSource
   4.260 +   */
   4.261 +  TracedCallback<Ptr<const Packet> > m_dropTrace;
   4.262 +
   4.263 +  /**
   4.264 +   * Time to start spinning up the device
   4.265 +   */
   4.266 +  Time m_tStart;
   4.267 +
   4.268 +  /**
   4.269 +   * Time to start tearing down the device
   4.270 +   */
   4.271 +  Time m_tStop;
   4.272 +
   4.273 +  EventId m_startEvent;
   4.274 +  EventId m_stopEvent;
   4.275 +
   4.276 +  int32_t m_sock;
   4.277 +
   4.278 +  Ptr<SystemThread> m_readThread;
   4.279 +
   4.280 +  /**
   4.281 +   * The Node to which this device is attached.
   4.282 +   */
   4.283 +  Ptr<Node> m_node;
   4.284 +
   4.285 +  /**
   4.286 +   * The MAC address which has been assigned to this device.
   4.287 +   */
   4.288 +  Mac48Address m_address;
   4.289 +
   4.290 +  /**
   4.291 +   * The callback used to notify higher layers that a packet has been received.
   4.292 +   */
   4.293 +  NetDevice::ReceiveCallback m_rxCallback;
   4.294 +
   4.295 +  /**
   4.296 +   * The callback used to notify higher layers that a packet has been received in promiscuous mode.
   4.297 +   */
   4.298 +  NetDevice::PromiscReceiveCallback m_promiscRxCallback;
   4.299 +
   4.300 +  /**
   4.301 +   * The ns-3 interface index (in the sense of net device index) that has been assigned to this network device.
   4.302 +   */
   4.303 +  uint32_t m_ifIndex;
   4.304 +
   4.305 +  /**
   4.306 +   * The Unix interface index that we got from the system and which corresponds to the interface (e.g., "eth1")
   4.307 +   * we are using to talk to the network.  Valid when m_sock is valid.
   4.308 +   */
   4.309 +  int32_t m_sll_ifindex;
   4.310 +
   4.311 +  /**
   4.312 +   * The human readable name of this device.
   4.313 +   */
   4.314 +  std::string m_name;
   4.315 +
   4.316 +  /**
   4.317 +   * Flag indicating whether or not the link is up.  In this case,
   4.318 +   * whether or not the device is connected to a channel.
   4.319 +   */
   4.320 +  bool m_linkUp;
   4.321 +
   4.322 +  /**
   4.323 +   * Callback to fire if the link changes state (up or down).
   4.324 +   */
   4.325 +  Callback<void> m_linkChangeCallback;
   4.326 +
   4.327 +  /**
   4.328 +   * The unix/linux name of the underlying device (e.g., eth0)
   4.329 +   */
   4.330 +  std::string m_deviceName;
   4.331 +};
   4.332 +
   4.333 +} // namespace ns3
   4.334 +
   4.335 +#endif // EMU_NET_DEVICE_H
   4.336 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/devices/emu/emu-sock-creator.cc	Wed Oct 29 22:39:36 2008 -0700
     5.3 @@ -0,0 +1,246 @@
     5.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     5.5 +/*
     5.6 + * Copyright (c) University of Washington
     5.7 + *
     5.8 + * This program is free software; you can redistribute it and/or modify
     5.9 + * it under the terms of the GNU General Public License version 2 as
    5.10 + * published by the Free Software Foundation;
    5.11 + *
    5.12 + * This program is distributed in the hope that it will be useful,
    5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 + * GNU General Public License for more details.
    5.16 + *
    5.17 + * You should have received a copy of the GNU General Public License
    5.18 + * along with this program; if not, write to the Free Software
    5.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    5.20 + */
    5.21 +
    5.22 +#include <unistd.h>
    5.23 +#include <string>
    5.24 +#include <iostream>
    5.25 +#include <iomanip>
    5.26 +#include <sstream>
    5.27 +#include <stdlib.h>
    5.28 +#include <errno.h>
    5.29 +
    5.30 +#include <sys/socket.h>
    5.31 +#include <sys/un.h>
    5.32 +#include <sys/ioctl.h>
    5.33 +#include <net/ethernet.h>
    5.34 +#include <net/if.h>
    5.35 +#include <netinet/in.h>
    5.36 +#include <netpacket/packet.h>
    5.37 +#include <arpa/inet.h>
    5.38 +
    5.39 +#include "emu-encode-decode.h"
    5.40 +
    5.41 +#define EMU_MAGIC 65867
    5.42 +
    5.43 +static int gVerbose = 0;
    5.44 +
    5.45 +#define LOG(msg) \
    5.46 +  if (gVerbose) \
    5.47 +    { \
    5.48 +      std::cout << msg << std::endl; \
    5.49 +    }
    5.50 +
    5.51 +#define ABORT(msg) \
    5.52 +  std::cout << __FILE__ << __FUNCTION__ <<  ": fatal error at line " << __LINE__ << ": " << msg << std::endl; \
    5.53 +  exit (-1);
    5.54 +
    5.55 +#define ABORT_IF(cond, msg, printErrno) \
    5.56 +  if (cond) \
    5.57 +    { \
    5.58 +      std::cout << __FILE__ << __FUNCTION__ <<  ": fatal error at line " << __LINE__ << ": " << msg << std::endl; \
    5.59 +      if (printErrno) \
    5.60 +        { \
    5.61 +          std::cout << "  errno = " << errno << "(" << strerror (errno) << ")" << std::endl; \
    5.62 +        } \
    5.63 +      exit (-1); \
    5.64 +    }
    5.65 +
    5.66 +/**
    5.67 + * \brief Send the socket file descriptor we created back to the emu device, 
    5.68 + * which will read it as soon as we're done.
    5.69 + *
    5.70 + * \param path The socket address information from the Unix socket we use
    5.71 + * to send the created socket back to.
    5.72 + * \param fd The socket we're going to send. 
    5.73 + */
    5.74 +  static void
    5.75 +SendSocket (const char *path, int fd)
    5.76 +{
    5.77 +  //
    5.78 +  // Open a Unix (local interprocess) socket to call back to the emu net
    5.79 +  // device.
    5.80 +  //
    5.81 +  LOG ("SendSocket(): Create Unix socket");
    5.82 +  int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
    5.83 +  ABORT_IF (sock == -1, "SendSocket(): Unable to open socket", 1);
    5.84 +  
    5.85 +  //
    5.86 +  // We have this string called path, which is really a hex representation
    5.87 +  // of the endpoint that the net device created.  It used a forward encoding
    5.88 +  // method (EmuBufferToString) to take the sockaddr_un it made and passed 
    5.89 +  // the resulting string to us.  So we need to take the inverse method
    5.90 +  // (EmuStringToBuffer) and build the same sockaddr_un over here.
    5.91 +  //
    5.92 +  socklen_t clientAddrLen;
    5.93 +  struct sockaddr_un clientAddr;
    5.94 +
    5.95 +  LOG ("SendSocket(): Decode address");
    5.96 +  bool rc = ns3::EmuStringToBuffer (path, (uint8_t *)&clientAddr, &clientAddrLen);
    5.97 +  ABORT_IF (rc == false, "SendSocket(): Unable to decode path", 0);
    5.98 +
    5.99 +  LOG ("SendSocket(): Connect");
   5.100 +  int status = connect (sock, (struct sockaddr*)&clientAddr, clientAddrLen);
   5.101 +  ABORT_IF (status != -1, "SendSocket(): Unable to connect to emu device", 1);
   5.102 +
   5.103 +  LOG ("SendSocket(): Connected");
   5.104 +
   5.105 +  //
   5.106 +  // This is arcane enough that a few words are worthwhile to explain what's 
   5.107 +  // going on here.
   5.108 +  //
   5.109 +  // The interesting information (the socket FD) is going to go back to the
   5.110 +  // emu net device as an integer of ancillary data.  Ancillary data is bits 
   5.111 +  // that are not a part a socket payload (out-of-band data).  We're also 
   5.112 +  // going to send one integer back.  It's just initialized to a magic number
   5.113 +  // we use to make sure that the emu device is talking to the emu socket 
   5.114 +  // creator and not some other creator process.
   5.115 +  //
   5.116 +  // The struct iovec below is part of a scatter-gather list.  It describes a
   5.117 +  // buffer.  In this case, it describes a buffer (an integer) containing the
   5.118 +  // data that we're going to send back to the emu net device (that magic 
   5.119 +  // number).
   5.120 +  // 
   5.121 +  struct iovec iov;
   5.122 +  uint32_t magic = EMU_MAGIC;
   5.123 +  iov.iov_base = &magic;
   5.124 +  iov.iov_len = sizeof(magic);
   5.125 +
   5.126 +  //
   5.127 +  // The CMSG macros you'll see below are used to create and access control 
   5.128 +  // messages (which is another name for ancillary data).  The ancillary 
   5.129 +  // data is made up of pairs of struct cmsghdr structures and associated
   5.130 +  // data arrays.
   5.131 +  // 
   5.132 +  // First, we're going to allocate a buffer on the stack to contain our 
   5.133 +  // data array (that contains the socket).  Sometimes you'll see this called
   5.134 +  // an "ancillary element" but the msghdr uses the control message termimology
   5.135 +  // so we call it "control."
   5.136 +  //
   5.137 +  size_t msg_size = sizeof(int);
   5.138 +  char control[CMSG_SPACE(msg_size)];
   5.139 +
   5.140 +  //
   5.141 +  // There is a msghdr that is used to minimize the number of parameters
   5.142 +  // passed to sendmsg (which we will use to send our ancillary data).  This
   5.143 +  // structure uses terminology corresponding to control messages, so you'll
   5.144 +  // see msg_control, which is the pointer to the ancillary data and controllen
   5.145 +  // which is the size of the ancillary data array.
   5.146 +  //
   5.147 +  // So, initialize the message header that describes our ancillary/control data
   5.148 +  // and point it to the control message/ancillary data we just allocated space
   5.149 +  // for.
   5.150 +  //
   5.151 +  struct msghdr msg;
   5.152 +  msg.msg_name = 0;
   5.153 +  msg.msg_namelen = 0;
   5.154 +  msg.msg_iov = &iov;
   5.155 +  msg.msg_iovlen = 1;
   5.156 +  msg.msg_control = control;
   5.157 +  msg.msg_controllen = sizeof (control);
   5.158 +  msg.msg_flags = 0;
   5.159 +
   5.160 +  //
   5.161 +  // A cmsghdr contains a length field that is the length of the header and
   5.162 +  // the data.  It has a cmsg_level field corresponding to the originating 
   5.163 +  // protocol.  This takes values which are legal levels for getsockopt and
   5.164 +  // setsockopt (here SOL_SOCKET).  We're going to use the SCM_RIGHTS type of 
   5.165 +  // cmsg, that indicates that the ancillary data array contains access rights 
   5.166 +  // that we are sending back to the emu net device.
   5.167 +  //
   5.168 +  // We have to put together the first (and only) cmsghdr that will describe
   5.169 +  // the whole package we're sending.
   5.170 +  //
   5.171 +  struct cmsghdr *cmsg;
   5.172 +  cmsg = CMSG_FIRSTHDR(&msg);
   5.173 +  cmsg->cmsg_level = SOL_SOCKET;
   5.174 +  cmsg->cmsg_type = SCM_RIGHTS;
   5.175 +  cmsg->cmsg_len = CMSG_LEN(msg_size);
   5.176 +  //
   5.177 +  // We also have to update the controllen in case other stuff is actually
   5.178 +  // in there we may not be aware of (due to macros).
   5.179 +  //
   5.180 +  msg.msg_controllen = cmsg->cmsg_len;
   5.181 +
   5.182 +  //
   5.183 +  // Finally, we get a pointer to the start of the ancillary data array and
   5.184 +  // put our file descriptor in.
   5.185 +  //
   5.186 +  int *fdptr = (int*) (CMSG_DATA(cmsg));
   5.187 +  *fdptr = fd; // 
   5.188 +
   5.189 +  //
   5.190 +  // Actually send the file descriptor back to the emulated net device.
   5.191 +  //
   5.192 +  ssize_t len = sendmsg(sock, &msg, 0);
   5.193 +  ABORT_IF (len == -1, "Could not send socket back to emu net device", 1);
   5.194 +
   5.195 +  LOG ("SendSocket(): sendmsg complete");
   5.196 +}
   5.197 +
   5.198 +  int 
   5.199 +main (int argc, char *argv[])
   5.200 +{
   5.201 +  int c;
   5.202 +  char *path = NULL;
   5.203 +
   5.204 +  opterr = 0;
   5.205 +
   5.206 +  while ((c = getopt (argc, argv, "vp:")) != -1)
   5.207 +    {
   5.208 +      switch (c)
   5.209 +        {
   5.210 +        case 'v':
   5.211 +          gVerbose = true;
   5.212 +          break;
   5.213 +        case 'p':
   5.214 +          path = optarg;
   5.215 +          break;
   5.216 +        }
   5.217 +    }
   5.218 +
   5.219 +  //
   5.220 +  // This program is spawned by an emu net device running in a simulation.  It
   5.221 +  // wants to create a raw socket as described below.  We are going to do the
   5.222 +  // work here since we're running suid root.  Once we create the raw socket,
   5.223 +  // we have to send it back to the emu net device.  We do that over a Unix
   5.224 +  // (local interprocess) socket.  The emu net device created a socket to 
   5.225 +  // listen for our response on, and it is expected to have encoded the address
   5.226 +  // information as a string and to have passed that string as an argument to
   5.227 +  // us.  We see it here as the "path" string.  We can't do anything useful 
   5.228 +  // unless we have that string.
   5.229 +  //
   5.230 +  ABORT_IF (path == NULL, "path is a required argument", 0);
   5.231 +
   5.232 +  //
   5.233 +  // The whole reason for all of the hoops we went through to call out to this
   5.234 +  // program will pay off here.  We created this program to run as suid root
   5.235 +  // in order to keep the main simulation program from having to be run with
   5.236 +  // root privileges.  We need root privileges to be able to open a raw socket
   5.237 +  // though.  So all of these hoops are to allow us to exeucte the following
   5.238 +  // single line of code:
   5.239 +  //
   5.240 +  int sock = socket (PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
   5.241 +  ABORT_IF (sock == -1, "CreateSocket(): Unable to open raw socket", 1);
   5.242 +
   5.243 +  //
   5.244 +  // Send the socket back to the emu net device so it can go about its business
   5.245 +  //
   5.246 +  SendSocket (path, sock);
   5.247 +
   5.248 +  return 0;
   5.249 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/devices/emu/emu.h	Wed Oct 29 22:39:36 2008 -0700
     6.3 @@ -0,0 +1,10 @@
     6.4 +/**
     6.5 + * \ingroup devices
     6.6 + * \defgroup Emulated Emulated Net Device Model
     6.7 + *
     6.8 + * \section Emulated Net Device Model
     6.9 + *
    6.10 + * This is a description of the emulated network device model.
    6.11 + *
    6.12 + * It is very detailed and comprehensive and answers all possible questions.
    6.13 + */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/devices/emu/waf	Wed Oct 29 22:39:36 2008 -0700
     7.3 @@ -0,0 +1,1 @@
     7.4 +exec "`dirname "$0"`"/../../../waf "$@"
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/devices/emu/wscript	Wed Oct 29 22:39:36 2008 -0700
     8.3 @@ -0,0 +1,22 @@
     8.4 +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
     8.5 +
     8.6 +
     8.7 +def build(bld):
     8.8 +    obj = bld.create_suid_program('emu-sock-creator')
     8.9 +    obj.source = [
    8.10 +       'emu-sock-creator.cc',
    8.11 +       'emu-encode-decode.cc',
    8.12 +       ]
    8.13 +
    8.14 +    module = bld.create_ns3_module('emu', ['node'])
    8.15 +    module.source = [
    8.16 +        'emu-net-device.cc',
    8.17 +        'emu-encode-decode.cc',
    8.18 +        ]
    8.19 +
    8.20 +    headers = bld.create_obj('ns3header')
    8.21 +    headers.module = 'emu'
    8.22 +    headers.source = [
    8.23 +        'emu-net-device.h',
    8.24 +        ]
    8.25 +
     9.1 --- a/src/devices/emulated/emulated-net-device.cc	Wed Oct 29 11:49:21 2008 -0700
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,642 +0,0 @@
     9.4 -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     9.5 -/*
     9.6 - * Copyright (c) 2008 University of Washington
     9.7 - *
     9.8 - * This program is free software; you can redistribute it and/or modify
     9.9 - * it under the terms of the GNU General Public License version 2 as
    9.10 - * published by the Free Software Foundation;
    9.11 - *
    9.12 - * This program is distributed in the hope that it will be useful,
    9.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.15 - * GNU General Public License for more details.
    9.16 - *
    9.17 - * You should have received a copy of the GNU General Public License
    9.18 - * along with this program; if not, write to the Free Software
    9.19 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.20 - */
    9.21 -
    9.22 -#include "emulated-net-device.h"
    9.23 -
    9.24 -#include "ns3/log.h"
    9.25 -#include "ns3/queue.h"
    9.26 -#include "ns3/simulator.h"
    9.27 -#include "ns3/realtime-simulator-impl.h"
    9.28 -#include "ns3/mac48-address.h"
    9.29 -#include "ns3/ethernet-header.h"
    9.30 -#include "ns3/ethernet-trailer.h"
    9.31 -#include "ns3/llc-snap-header.h"
    9.32 -#include "ns3/trace-source-accessor.h"
    9.33 -#include "ns3/pointer.h"
    9.34 -#include "ns3/channel.h"
    9.35 -#include "ns3/system-thread.h"
    9.36 -#include "ns3/string.h"
    9.37 -#include "ns3/boolean.h"
    9.38 -
    9.39 -#include <sys/socket.h>
    9.40 -#include <sys/ioctl.h>
    9.41 -#include <net/ethernet.h>
    9.42 -#include <net/if.h>
    9.43 -#include <netinet/in.h>
    9.44 -#include <netpacket/packet.h>
    9.45 -#include <arpa/inet.h>
    9.46 -
    9.47 -NS_LOG_COMPONENT_DEFINE ("EmulatedNetDevice");
    9.48 -
    9.49 -namespace ns3 {
    9.50 -
    9.51 -NS_OBJECT_ENSURE_REGISTERED (EmulatedNetDevice);
    9.52 -
    9.53 -TypeId 
    9.54 -EmulatedNetDevice::GetTypeId (void)
    9.55 -{
    9.56 -  static TypeId tid = TypeId ("ns3::EmulatedNetDevice")
    9.57 -    .SetParent<NetDevice> ()
    9.58 -    .AddConstructor<EmulatedNetDevice> ()
    9.59 -    .AddAttribute ("Address", 
    9.60 -                   "The ns-3 MAC address of this (virtual) device.",
    9.61 -                   Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
    9.62 -                   MakeMac48AddressAccessor (&EmulatedNetDevice::m_address),
    9.63 -                   MakeMac48AddressChecker ())
    9.64 -    .AddAttribute ("DeviceName", 
    9.65 -                   "The name of the underlying real device (e.g. eth1).",
    9.66 -                   StringValue ("eth1"),
    9.67 -                   MakeStringAccessor (&EmulatedNetDevice::m_deviceName),
    9.68 -                   MakeStringChecker ())
    9.69 -    .AddAttribute ("Start", 
    9.70 -                   "The simulation time at which to spin up the device thread.",
    9.71 -                   TimeValue (Seconds (0.)),
    9.72 -                   MakeTimeAccessor (&EmulatedNetDevice::m_tStart),
    9.73 -                   MakeTimeChecker ())
    9.74 -    .AddAttribute ("Stop", 
    9.75 -                   "The simulation time at which to tear down the device thread.",
    9.76 -                   TimeValue (Seconds (0.)),
    9.77 -                   MakeTimeAccessor (&EmulatedNetDevice::m_tStop),
    9.78 -                   MakeTimeChecker ())
    9.79 -    .AddAttribute ("TxQueue", 
    9.80 -                   "A queue to use as the transmit queue in the device.",
    9.81 -                   PointerValue (),
    9.82 -                   MakePointerAccessor (&EmulatedNetDevice::m_queue),
    9.83 -                   MakePointerChecker<Queue> ())
    9.84 -    .AddTraceSource ("Rx", 
    9.85 -                     "Trace source to fire on reception of a MAC packet.",
    9.86 -                     MakeTraceSourceAccessor (&EmulatedNetDevice::m_rxTrace))
    9.87 -    .AddTraceSource ("Drop", 
    9.88 -                     "Trace source to fire on when a MAC packet is dropped.",
    9.89 -                     MakeTraceSourceAccessor (&EmulatedNetDevice::m_dropTrace))
    9.90 -    ;
    9.91 -  return tid;
    9.92 -}
    9.93 -
    9.94 -
    9.95 -EmulatedNetDevice::EmulatedNetDevice () 
    9.96 -: 
    9.97 -  m_startEvent (),
    9.98 -  m_stopEvent (),
    9.99 -  m_sock (-1),
   9.100 -  m_readThread (0),
   9.101 -  m_ifIndex (-1),
   9.102 -  m_sll_ifindex (-1),
   9.103 -  m_name ("Emulated NetDevice")
   9.104 -{
   9.105 -  NS_LOG_FUNCTION (this);
   9.106 -  Start (m_tStart);
   9.107 -}
   9.108 -
   9.109 -EmulatedNetDevice::~EmulatedNetDevice ()
   9.110 -{
   9.111 -}
   9.112 -
   9.113 -void 
   9.114 -EmulatedNetDevice::DoDispose()
   9.115 -{
   9.116 -  NS_LOG_FUNCTION_NOARGS ();
   9.117 -  m_node = 0;
   9.118 -  NetDevice::DoDispose ();
   9.119 -}
   9.120 -
   9.121 -void
   9.122 -EmulatedNetDevice::Start (Time tStart)
   9.123 -{
   9.124 -  NS_LOG_FUNCTION (tStart);
   9.125 -
   9.126 -  //
   9.127 -  // Cancel any pending start event and schedule a new one at some relative time in the future.
   9.128 -  //
   9.129 -  Simulator::Cancel (m_startEvent);
   9.130 -  m_startEvent = Simulator::Schedule (tStart, &EmulatedNetDevice::StartDevice, this);
   9.131 -}
   9.132 -
   9.133 -  void
   9.134 -EmulatedNetDevice::Stop (Time tStop)
   9.135 -{
   9.136 -  NS_LOG_FUNCTION (tStop);
   9.137 -  //
   9.138 -  // Cancel any pending stop event and schedule a new one at some relative time in the future.
   9.139 -  //
   9.140 -  Simulator::Cancel (m_stopEvent);
   9.141 -  m_startEvent = Simulator::Schedule (tStop, &EmulatedNetDevice::StopDevice, this);
   9.142 -}
   9.143 -
   9.144 -  void
   9.145 -EmulatedNetDevice::StartDevice (void)
   9.146 -{
   9.147 -  NS_LOG_FUNCTION_NOARGS ();
   9.148 -
   9.149 -  //
   9.150 -  // Spin up the emulated net device and start receiving packets.
   9.151 -  //
   9.152 -  NS_ASSERT_MSG (m_sock == -1, "EmulatedNetDevice::StartDevice(): Device is already started");
   9.153 -
   9.154 -  NS_LOG_LOGIC ("Creating socket");
   9.155 -
   9.156 -  m_sock = socket (PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
   9.157 -  //  m_sock = socket (AF_INET, SOCK_PACKET, htons(ETH_P_ALL));
   9.158 -  NS_ASSERT_MSG (m_sock != -1, "EmulatedNetDevice::StartDevice(): Unable to open socket");
   9.159 -
   9.160 -  //
   9.161 -  // Figure out which interface index corresponds to the device name in the corresponding attribute.
   9.162 -  //
   9.163 -  struct ifreq ifr;
   9.164 -  bzero (&ifr, sizeof(ifr));
   9.165 -  strncpy ((char *)ifr.ifr_name, m_deviceName.c_str (), IFNAMSIZ);
   9.166 -
   9.167 -  NS_LOG_LOGIC ("Getting interface index");
   9.168 -  int32_t rc = ioctl (m_sock, SIOCGIFINDEX, &ifr);
   9.169 -  NS_ASSERT_MSG (rc != -1, "EmulatedNetDevice::StartDevice(): Can't get interface index");
   9.170 -
   9.171 -  //
   9.172 -  // Save the real interface index for later calls to sendto
   9.173 -  //
   9.174 -  m_sll_ifindex = ifr.ifr_ifindex;
   9.175 -
   9.176 -  //
   9.177 -  // Bind the socket to the interface we just found.
   9.178 -  //
   9.179 -  struct sockaddr_ll ll;
   9.180 -  bzero (&ll, sizeof(ll));
   9.181 -
   9.182 -  ll.sll_family = AF_PACKET;
   9.183 -  ll.sll_ifindex = m_sll_ifindex;
   9.184 -  ll.sll_protocol = htons(ETH_P_ALL); 
   9.185 -
   9.186 -  NS_LOG_LOGIC ("Binding socket to interface");
   9.187 -
   9.188 -  rc = bind (m_sock, (struct sockaddr *)&ll, sizeof (ll));
   9.189 -  NS_ASSERT_MSG (rc != -1, "EmulatedNetDevice::StartDevice(): Can't bind to specified interface");
   9.190 -
   9.191 -  //
   9.192 -  // Now spin up a read thread to read packets.
   9.193 -  //
   9.194 -  NS_ASSERT_MSG (m_readThread == 0, "EmulatedNetDevice::StartDevice(): Receive thread is already running");
   9.195 -
   9.196 -  NS_LOG_LOGIC ("Spinning up read thread");
   9.197 -
   9.198 -  m_readThread = Create<SystemThread> (MakeCallback (&EmulatedNetDevice::ReadThread, this));
   9.199 -  m_readThread->Start ();
   9.200 -
   9.201 -  NotifyLinkUp ();
   9.202 -}
   9.203 -
   9.204 -void
   9.205 -EmulatedNetDevice::StopDevice (void)
   9.206 -{
   9.207 -  NS_LOG_FUNCTION_NOARGS ();
   9.208 -
   9.209 -  close (m_sock);
   9.210 -  m_sock = -1;
   9.211 -
   9.212 -  NS_ASSERT_MSG (m_readThread != 0, "EmulatedNetDevice::StopDevice(): Receive thread is not running");
   9.213 -
   9.214 -  NS_LOG_LOGIC ("Joining read thread");
   9.215 -  m_readThread->Join ();
   9.216 -  m_readThread = 0;
   9.217 -}
   9.218 -
   9.219 -void
   9.220 -EmulatedNetDevice::ForwardUp (uint8_t *buf, uint32_t len)
   9.221 -{
   9.222 -  NS_LOG_FUNCTION (buf << len);
   9.223 -
   9.224 -  //
   9.225 -  // Create a packet out of the buffer we received and free that buffer.
   9.226 -  //
   9.227 -  Ptr<Packet> packet = Create<Packet> (reinterpret_cast<const uint8_t *> (buf), len);
   9.228 -  free (buf);
   9.229 -  buf = 0;
   9.230 -
   9.231 -  //
   9.232 -  // Trace sinks will expect complete packets, not packets without some of the
   9.233 -  // headers.
   9.234 -  //
   9.235 -  Ptr<Packet> originalPacket = packet->Copy ();
   9.236 -
   9.237 -  //
   9.238 -  // Checksum the packet
   9.239 -  //
   9.240 -  EthernetTrailer trailer;
   9.241 -  packet->RemoveTrailer (trailer);
   9.242 -  trailer.CheckFcs (packet);
   9.243 -
   9.244 -  EthernetHeader header (false);
   9.245 -  packet->RemoveHeader (header);
   9.246 -
   9.247 -  NS_LOG_LOGIC ("Pkt source is " << header.GetSource ());
   9.248 -  NS_LOG_LOGIC ("Pkt destination is " << header.GetDestination ());
   9.249 -
   9.250 -  //
   9.251 -  // An IP host group address is mapped to an Ethernet multicast address
   9.252 -  // by placing the low-order 23-bits of the IP address into the low-order
   9.253 -  // 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 (hex).
   9.254 -  //
   9.255 -  // We are going to receive all packets destined to any multicast address,
   9.256 -  // which means clearing the low-order 23 bits the header destination 
   9.257 -  //
   9.258 -  Mac48Address mcDest;
   9.259 -  uint8_t      mcBuf[6];
   9.260 -
   9.261 -  header.GetDestination ().CopyTo (mcBuf);
   9.262 -  mcBuf[3] &= 0x80;
   9.263 -  mcBuf[4] = 0;
   9.264 -  mcBuf[5] = 0;
   9.265 -  mcDest.CopyFrom (mcBuf);
   9.266 -
   9.267 -  Mac48Address multicast = Mac48Address::ConvertFrom (GetMulticast ());
   9.268 -  Mac48Address broadcast = Mac48Address::ConvertFrom (GetBroadcast ());
   9.269 -  Mac48Address destination = Mac48Address::ConvertFrom (GetAddress ());
   9.270 -
   9.271 -  LlcSnapHeader llc;
   9.272 -  packet->RemoveHeader (llc);
   9.273 -  uint16_t protocol = llc.GetType ();
   9.274 -
   9.275 -  PacketType packetType;
   9.276 -      
   9.277 -  if (header.GetDestination () == broadcast)
   9.278 -    {
   9.279 -      NS_LOG_LOGIC ("Pkt destination is PACKET_BROADCAST");
   9.280 -      packetType = NS3_PACKET_BROADCAST;
   9.281 -    }
   9.282 -  else if (mcDest == multicast)
   9.283 -    {
   9.284 -      NS_LOG_LOGIC ("Pkt destination is PACKET_MULTICAST");
   9.285 -      packetType = NS3_PACKET_MULTICAST;
   9.286 -    }
   9.287 -  else if (header.GetDestination () == destination)
   9.288 -    {
   9.289 -      NS_LOG_LOGIC ("Pkt destination is PACKET_HOST");
   9.290 -      packetType = NS3_PACKET_HOST;
   9.291 -    }
   9.292 -  else
   9.293 -    {
   9.294 -      NS_LOG_LOGIC ("Pkt destination is PACKET_OTHERHOST");
   9.295 -      packetType = NS3_PACKET_OTHERHOST;
   9.296 -    }
   9.297 -
   9.298 -  if (!m_promiscRxCallback.IsNull ())
   9.299 -    {
   9.300 -      NS_LOG_LOGIC ("calling m_promiscRxCallback");
   9.301 -      m_promiscRxCallback (this, packet->Copy (), protocol, header.GetSource (), header.GetDestination (), packetType);
   9.302 -    }
   9.303 -
   9.304 -  if (packetType != NS3_PACKET_OTHERHOST)
   9.305 -    {
   9.306 -      m_rxTrace (originalPacket);
   9.307 -      NS_LOG_LOGIC ("calling m_rxCallback");
   9.308 -      m_rxCallback (this, packet, protocol, header.GetSource ());
   9.309 -    }
   9.310 -}
   9.311 -
   9.312 -void
   9.313 -EmulatedNetDevice::ReadThread (void)
   9.314 -{
   9.315 -  NS_LOG_FUNCTION_NOARGS ();
   9.316 -
   9.317 -  //
   9.318 -  // It's important to remember that we're in a completely different thread than the simulator is running in.  We
   9.319 -  // need to synchronize with that other thread to get the packet up into ns-3.  What we will need to do is to schedule 
   9.320 -  // a method to forward up the packet using the multithreaded simulator we are most certainly running.  However, I just 
   9.321 -  // said it -- we are talking about two threads here, so it is very, very dangerous to do any kind of reference couning
   9.322 -  // on a shared object.  Just don't do it.  So what we're going to do is to allocate a buffer on the heap and pass that
   9.323 -  // buffer into the ns-3 context thread where it will create the packet.
   9.324 -  //
   9.325 -
   9.326 -  int32_t len = -1;
   9.327 -  struct sockaddr_ll addr;
   9.328 -  socklen_t addrSize = sizeof (addr);
   9.329 -
   9.330 -  for (;;) 
   9.331 -    {
   9.332 -      uint32_t bufferSize = 65536;
   9.333 -      uint8_t *buf = (uint8_t *)malloc (bufferSize);
   9.334 -      NS_ASSERT_MSG (buf, "EmulatedNetDevice::ReadThread(): malloc packet buffer failed");
   9.335 -      NS_LOG_LOGIC ("Calling recvfrom");
   9.336 -      len = recvfrom (m_sock, buf, bufferSize, 0, (struct sockaddr *)&addr, &addrSize);
   9.337 -
   9.338 -      if (len == -1)
   9.339 -        {
   9.340 -          free (buf);
   9.341 -          buf = 0;
   9.342 -          return;
   9.343 -        }
   9.344 -
   9.345 -      NS_LOG_INFO ("EmulatedNetDevice::ReadThread(): Received packet");
   9.346 -      NS_LOG_INFO ("EmulatedNetDevice::ReadThread(): Scheduling handler");
   9.347 -      DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ())->ScheduleRealtimeNow (
   9.348 -        MakeEvent (&EmulatedNetDevice::ForwardUp, this, buf, len));
   9.349 -      buf = 0;
   9.350 -    }
   9.351 -}
   9.352 -
   9.353 -bool 
   9.354 -EmulatedNetDevice::Send (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
   9.355 -{
   9.356 -  NS_LOG_FUNCTION (packet << dest << protocolNumber);
   9.357 -  //
   9.358 -  // The immediate questions here are how are we going to encapsulate packets and what do we use as the MAC source and 
   9.359 -  // destination (hardware) addresses?
   9.360 -  //
   9.361 -  // If we return false from EmulatedNetDevice::NeedsArp, the ArpIpv4Interface will pass the broadcast address as the 
   9.362 -  // hardware (Ethernet) destination by default.  If we return true from EmulatedNetDevice::NeedsArp, then the hardware
   9.363 -  // destination is actually meaningful, but we'll have an ns-3 ARP running on this device.  There can also be an ARP
   9.364 -  // running on the underlying OS so we have to be very careful, both about multiple ARPs and also about TCP, UDP, etc.
   9.365 -  //
   9.366 -  // We are operating in promiscuous mode on the receive side (all ns-3 net devices are required to implement the 
   9.367 -  // promiscuous callback in a meaningful way), so we have an option regarding the hardware addresses.  We don't actually have
   9.368 -  // to use the real hardware addresses and IP addresses of the underlying system.  We can completely use MAC-spoofing to
   9.369 -  // fake out the OS by using the ns-3 assigned MAC address (and also the ns-3 assigned IP addresses).  Ns-3 starts its 
   9.370 -  // MAC address allocation using the OUI (vendor-code) 00:00:00 which is unassigned to any organization and is a globally
   9.371 -  // administered address, so there shouldn't be any collisions with real hardware.
   9.372 -  //
   9.373 -  // So what we do is we return true from EmulatedNetDevice::NeedsArp which tells ns-3 to use its own ARP.  We spoof the 
   9.374 -  // MAC address of the device and use promiscuous mode to receive traffic destined to that address.
   9.375 -  //
   9.376 -  return SendFrom (packet, m_address, dest, protocolNumber);
   9.377 -}
   9.378 -
   9.379 -bool 
   9.380 -EmulatedNetDevice::SendFrom (Ptr<Packet> packet, const Address &src, const Address &dest, uint16_t protocolNumber)
   9.381 -{
   9.382 -  NS_LOG_FUNCTION (packet << src << dest << protocolNumber);
   9.383 -
   9.384 -  if (IsLinkUp () == false)
   9.385 -    {
   9.386 -      NS_LOG_LOGIC ("Link is down, returning");
   9.387 -      return false;
   9.388 -    }
   9.389 -
   9.390 -  Mac48Address destination = Mac48Address::ConvertFrom (dest);
   9.391 -  Mac48Address source = Mac48Address::ConvertFrom (src);
   9.392 -
   9.393 -  NS_LOG_LOGIC ("Transmit packet with UID " << packet->GetUid ());
   9.394 -  NS_LOG_LOGIC ("Transmit packet from " << source);
   9.395 -  NS_LOG_LOGIC ("Transmit packet to " << destination);
   9.396 -
   9.397 -#if 0
   9.398 -  {
   9.399 -    struct ifreq ifr;
   9.400 -    bzero (&ifr, sizeof(ifr));
   9.401 -    strncpy ((char *)ifr.ifr_name, m_deviceName.c_str (), IFNAMSIZ);
   9.402 -
   9.403 -    NS_LOG_LOGIC ("Getting MAC address");
   9.404 -    int32_t rc = ioctl (m_sock, SIOCGIFHWADDR, &ifr);
   9.405 -    NS_ASSERT_MSG (rc != -1, "EmulatedNetDevice::SendFrom(): Can't get MAC address");
   9.406 -
   9.407 -    std::ostringstream oss;
   9.408 -    oss << std::hex <<
   9.409 -      (ifr.ifr_hwaddr.sa_data[0] & 0xff) << ":" <<
   9.410 -      (ifr.ifr_hwaddr.sa_data[1] & 0xff) << ":" <<
   9.411 -      (ifr.ifr_hwaddr.sa_data[2] & 0xff) << ":" <<
   9.412 -      (ifr.ifr_hwaddr.sa_data[3] & 0xff) << ":" <<
   9.413 -      (ifr.ifr_hwaddr.sa_data[4] & 0xff) << ":" <<
   9.414 -      (ifr.ifr_hwaddr.sa_data[5] & 0xff) << std::dec;
   9.415 -
   9.416 -    NS_LOG_LOGIC ("Fixup source to HW MAC " << oss.str ());
   9.417 -    source = Mac48Address (oss.str ().c_str ());
   9.418 -    NS_LOG_LOGIC ("source now " << source);
   9.419 -  }
   9.420 -#endif
   9.421 -
   9.422 -  LlcSnapHeader llc;
   9.423 -  llc.SetType (protocolNumber);
   9.424 -  packet->AddHeader (llc);
   9.425 -
   9.426 -  EthernetHeader header (false);
   9.427 -  header.SetSource (source);
   9.428 -  header.SetDestination (destination);
   9.429 -  header.SetLengthType (packet->GetSize ());
   9.430 -  packet->AddHeader (header);
   9.431 -
   9.432 -  EthernetTrailer trailer;
   9.433 -  trailer.CalcFcs (packet);
   9.434 -  packet->AddTrailer (trailer);
   9.435 -
   9.436 -  // 
   9.437 -  // Enqueue and dequeue the packet to hit the tracing hooks.
   9.438 -  //
   9.439 -  m_queue->Enqueue (packet);
   9.440 -  packet = m_queue->Dequeue ();
   9.441 -
   9.442 -  struct sockaddr_ll ll;
   9.443 -  bzero (&ll, sizeof (ll));
   9.444 -
   9.445 -  ll.sll_family = AF_PACKET;
   9.446 -  ll.sll_ifindex = m_sll_ifindex;
   9.447 -  ll.sll_protocol = htons(ETH_P_ALL); 
   9.448 -
   9.449 -  NS_LOG_LOGIC ("calling sendto");
   9.450 -
   9.451 -  int32_t rc;
   9.452 -  rc = sendto (m_sock, packet->PeekData (), packet->GetSize (), 0, reinterpret_cast<struct sockaddr *> (&ll), sizeof (ll));
   9.453 -
   9.454 -  NS_LOG_LOGIC ("sendto returns " << rc);
   9.455 -
   9.456 -  return rc == -1 ? false : true;
   9.457 -}
   9.458 -
   9.459 -void 
   9.460 -EmulatedNetDevice::SetDataRate(DataRate bps)
   9.461 -{
   9.462 -  NS_LOG_FUNCTION (this << bps);
   9.463 -  NS_ASSERT_MSG (false, "EmulatedNetDevice::SetDataRate():  Unable."); 
   9.464 -}
   9.465 -
   9.466 -void
   9.467 -EmulatedNetDevice::SetQueue (Ptr<Queue> q)
   9.468 -{
   9.469 -  NS_LOG_FUNCTION (this << q);
   9.470 -  m_queue = q;
   9.471 -}
   9.472 -
   9.473 -Ptr<Queue> 
   9.474 -EmulatedNetDevice::GetQueue(void) const 
   9.475 -{ 
   9.476 -  NS_LOG_FUNCTION_NOARGS ();
   9.477 -  return m_queue;
   9.478 -}
   9.479 -
   9.480 -void
   9.481 -EmulatedNetDevice::NotifyLinkUp (void)
   9.482 -{
   9.483 -  m_linkUp = true;
   9.484 -  if (!m_linkChangeCallback.IsNull ())
   9.485 -    {
   9.486 -      m_linkChangeCallback ();
   9.487 -    }
   9.488 -}
   9.489 -
   9.490 -void 
   9.491 -EmulatedNetDevice::SetName(const std::string name)
   9.492 -{
   9.493 -  m_name = name;
   9.494 -}
   9.495 -
   9.496 -std::string 
   9.497 -EmulatedNetDevice::GetName(void) const
   9.498 -{
   9.499 -  return m_name;
   9.500 -}
   9.501 -
   9.502 -void 
   9.503 -EmulatedNetDevice::SetIfIndex(const uint32_t index)
   9.504 -{
   9.505 -  m_ifIndex = index;
   9.506 -}
   9.507 -
   9.508 -uint32_t 
   9.509 -EmulatedNetDevice::GetIfIndex(void) const
   9.510 -{
   9.511 -  return m_ifIndex;
   9.512 -}
   9.513 -
   9.514 -Ptr<Channel> 
   9.515 -EmulatedNetDevice::GetChannel (void) const
   9.516 -{
   9.517 -  NS_ASSERT_MSG (false, "EmulatedNetDevice::GetChannel():  Unable."); 
   9.518 -  return 0;
   9.519 -}
   9.520 -
   9.521 -void 
   9.522 -EmulatedNetDevice::SetAddress (Mac48Address addr)
   9.523 -{
   9.524 -  NS_LOG_FUNCTION (addr);
   9.525 -  m_address = addr;
   9.526 -}
   9.527 -
   9.528 -Address 
   9.529 -EmulatedNetDevice::GetAddress (void) const
   9.530 -{
   9.531 -  NS_LOG_FUNCTION_NOARGS ();
   9.532 -  return m_address;
   9.533 -}
   9.534 -
   9.535 -bool 
   9.536 -EmulatedNetDevice::SetMtu (const uint16_t mtu)
   9.537 -{
   9.538 -  NS_ASSERT_MSG (false, "EmulatedNetDevice::SetMtu():  Unable."); 
   9.539 -  return false;
   9.540 -}
   9.541 -
   9.542 -uint16_t 
   9.543 -EmulatedNetDevice::GetMtu (void) const
   9.544 -{
   9.545 -  struct ifreq ifr;
   9.546 -  bzero (&ifr, sizeof (ifr));
   9.547 -  strcpy(ifr.ifr_name, m_deviceName.c_str ());
   9.548 -
   9.549 -  int32_t fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
   9.550 -
   9.551 -  int32_t rc = ioctl(fd, SIOCGIFMTU, &ifr);
   9.552 -  NS_ASSERT_MSG (rc != -1, "EmulatedNetDevice::GetMtu(): Can't ioctl SIOCGIFMTU");
   9.553 -
   9.554 -  close (fd);
   9.555 -
   9.556 -  return ifr.ifr_mtu;
   9.557 -}
   9.558 -
   9.559 -bool 
   9.560 -EmulatedNetDevice::IsLinkUp (void) const
   9.561 -{
   9.562 -  return m_linkUp;
   9.563 -}
   9.564 -
   9.565 -void 
   9.566 -EmulatedNetDevice::SetLinkChangeCallback (Callback<void> callback)
   9.567 -{
   9.568 -  m_linkChangeCallback = callback;
   9.569 -}
   9.570 -
   9.571 -bool 
   9.572 -EmulatedNetDevice::IsBroadcast (void) const
   9.573 -{
   9.574 -  return true;
   9.575 -}
   9.576 -
   9.577 -Address
   9.578 -EmulatedNetDevice::GetBroadcast (void) const
   9.579 -{
   9.580 -  return Mac48Address ("ff:ff:ff:ff:ff:ff");
   9.581 -}
   9.582 -
   9.583 -bool 
   9.584 -EmulatedNetDevice::IsMulticast (void) const
   9.585 -{
   9.586 -  return false;
   9.587 -}
   9.588 -
   9.589 -Address 
   9.590 -EmulatedNetDevice::GetMulticast (void) const
   9.591 -{
   9.592 -  return Mac48Address ("01:00:5e:00:00:00");
   9.593 -}
   9.594 -
   9.595 -Address 
   9.596 -EmulatedNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
   9.597 -{
   9.598 -  return Mac48Address ("01:00:5e:00:00:00");
   9.599 -}
   9.600 -
   9.601 -bool 
   9.602 -EmulatedNetDevice::IsPointToPoint (void) const
   9.603 -{
   9.604 -  return false;
   9.605 -}
   9.606 -
   9.607 -void
   9.608 -EmulatedNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
   9.609 -{
   9.610 -  NS_ASSERT_MSG (false, "EmulatedNetDevice::SetPromiscReceiveCallback(): Not implemented");
   9.611 -}
   9.612 -
   9.613 -  bool 
   9.614 -EmulatedNetDevice::SupportsSendFrom () const
   9.615 -{
   9.616 -  NS_LOG_FUNCTION_NOARGS ();
   9.617 -  return true;
   9.618 -}
   9.619 -
   9.620 -
   9.621 -Ptr<Node> 
   9.622 -EmulatedNetDevice::GetNode (void) const
   9.623 -{
   9.624 -  return m_node;
   9.625 -}
   9.626 -
   9.627 -void 
   9.628 -EmulatedNetDevice::SetNode (Ptr<Node> node)
   9.629 -{
   9.630 -  m_node = node;
   9.631 -}
   9.632 -
   9.633 -bool 
   9.634 -EmulatedNetDevice::NeedsArp (void) const
   9.635 -{
   9.636 -  return true;
   9.637 -}
   9.638 -
   9.639 -void 
   9.640 -EmulatedNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
   9.641 -{
   9.642 -  m_rxCallback = cb;
   9.643 -}
   9.644 -
   9.645 -} // namespace ns3
    10.1 --- a/src/devices/emulated/emulated-net-device.h	Wed Oct 29 11:49:21 2008 -0700
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,321 +0,0 @@
    10.4 -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
    10.5 -/*
    10.6 - * Copyright (c) 2008 University of Washington
    10.7 - *
    10.8 - * This program is free software; you can redistribute it and/or modify
    10.9 - * it under the terms of the GNU General Public License version 2 as
   10.10 - * published by the Free Software Foundation;
   10.11 - *
   10.12 - * This program is distributed in the hope that it will be useful,
   10.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.15 - * GNU General Public License for more details.
   10.16 - *
   10.17 - * You should have received a copy of the GNU General Public License
   10.18 - * along with this program; if not, write to the Free Software
   10.19 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   10.20 - */
   10.21 -
   10.22 -#ifndef EMULATED_NET_DEVICE_H
   10.23 -#define EMULATED_NET_DEVICE_H
   10.24 -
   10.25 -#include <string.h>
   10.26 -#include "ns3/address.h"
   10.27 -#include "ns3/net-device.h"
   10.28 -#include "ns3/node.h"
   10.29 -#include "ns3/callback.h"
   10.30 -#include "ns3/packet.h"
   10.31 -#include "ns3/traced-callback.h"
   10.32 -#include "ns3/event-id.h"
   10.33 -#include "ns3/nstime.h"
   10.34 -#include "ns3/data-rate.h"
   10.35 -#include "ns3/ptr.h"
   10.36 -#include "ns3/mac48-address.h"
   10.37 -#include "ns3/system-thread.h"
   10.38 -
   10.39 -namespace ns3 {
   10.40 -
   10.41 -class Queue;
   10.42 -
   10.43 -/**
   10.44 - * \class EmulatedNetDevice
   10.45 - * \brief A Device for an Emulated Network Link.
   10.46 - */
   10.47 -class EmulatedNetDevice : public NetDevice 
   10.48 -{
   10.49 -public:
   10.50 -  static TypeId GetTypeId (void);
   10.51 -
   10.52 -  /**
   10.53 -   * Construct a EmulatedNetDevice
   10.54 -   *
   10.55 -   * This is the constructor for the EmulatedNetDevice.  It takes as a
   10.56 -   */
   10.57 -  EmulatedNetDevice ();
   10.58 -
   10.59 -  /**
   10.60 -   * Destroy a EmulatedNetDevice
   10.61 -   *
   10.62 -   * This is the destructor for the EmulatedNetDevice.
   10.63 -   */
   10.64 -  virtual ~EmulatedNetDevice ();
   10.65 -
   10.66 -  /**
   10.67 -   * Set the Data Rate used for transmission of packets.  
   10.68 -   *
   10.69 -   * @see Attach ()
   10.70 -   * @param bps the data rate at which this object operates
   10.71 -   */
   10.72 -  void SetDataRate (DataRate bps);
   10.73 -
   10.74 -  /**
   10.75 -   * Set the inteframe gap used to separate packets.  The interframe gap
   10.76 -   * defines the minimum space required between packets sent by this device.
   10.77 -   *
   10.78 -   * @param t the interframe gap time
   10.79 -   */
   10.80 -  void SetInterframeGap (Time t);
   10.81 -
   10.82 -  /**
   10.83 -   * Set a start time for the device.
   10.84 -   *
   10.85 -   * @param tStart the start time
   10.86 -   */
   10.87 -  void Start (Time tStart);
   10.88 -
   10.89 -  /**
   10.90 -   * Set a stop time for the device.
   10.91 -   *
   10.92 -   * @param tStop the stop time
   10.93 -   */
   10.94 -  void Stop (Time tStop);
   10.95 -
   10.96 -  /**
   10.97 -   * Attach a queue to the EmulatedNetDevice.
   10.98 -   *
   10.99 -   * The EmulatedNetDevice "owns" a queue that implements a queueing 
  10.100 -   * method such as DropTail or RED.  
  10.101 -   *
  10.102 -   * @see Queue
  10.103 -   * @see DropTailQueue
  10.104 -   * @param queue Ptr to the new queue.
  10.105 -   */
  10.106 -  void SetQueue (Ptr<Queue> queue);
  10.107 -
  10.108 -  /**
  10.109 -   * Receive a packet.
  10.110 -   *
  10.111 -   * The EmulatedNetDevice receives packets from its socket reader
  10.112 -   * and forwards them up the protocol stack.  This is the public method
  10.113 -   * used by the reader to indicate that a packet has arrived at the device.
  10.114 -   *
  10.115 -   * @param p Ptr to the received packet.
  10.116 -   */
  10.117 -  void Receive (Ptr<Packet> p);
  10.118 -
  10.119 -  /**
  10.120 -   * Assign a MAC address to this device.
  10.121 -   *
  10.122 -   * @see Mac48Address
  10.123 -   * @param addr The new address.
  10.124 -   */
  10.125 -  void SetAddress (Mac48Address addr);
  10.126 -
  10.127 -//
  10.128 -// Pure virtual methods inherited from NetDevice we must implement.
  10.129 -//
  10.130 -  virtual void SetName(const std::string name);
  10.131 -  virtual std::string GetName(void) const;
  10.132 -
  10.133 -  virtual void SetIfIndex(const uint32_t index);
  10.134 -  virtual uint32_t GetIfIndex(void) const;
  10.135 -
  10.136 -  virtual Ptr<Channel> GetChannel (void) const;
  10.137 -  virtual Address GetAddress (void) const;
  10.138 -
  10.139 -  virtual bool SetMtu (const uint16_t mtu);
  10.140 -  virtual uint16_t GetMtu (void) const;
  10.141 -
  10.142 -  virtual bool IsLinkUp (void) const;
  10.143 -
  10.144 -  virtual void SetLinkChangeCallback (Callback<void> callback);
  10.145 -
  10.146 -  virtual bool IsBroadcast (void) const;
  10.147 -  virtual Address GetBroadcast (void) const;
  10.148 -
  10.149 -  virtual bool IsMulticast (void) const;
  10.150 -  virtual Address GetMulticast (void) const;
  10.151 -  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
  10.152 -
  10.153 -  virtual bool IsPointToPoint (void) const;
  10.154 -
  10.155 -  virtual bool Send(Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber);
  10.156 -
  10.157 -  virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
  10.158 -
  10.159 -  virtual Ptr<Node> GetNode (void) const;
  10.160 -  virtual void SetNode (Ptr<Node> node);
  10.161 -
  10.162 -  virtual bool NeedsArp (void) const;
  10.163 -
  10.164 -  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
  10.165 -  virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
  10.166 -
  10.167 -  virtual bool SupportsSendFrom (void) const;
  10.168 -
  10.169 -private:
  10.170 -
  10.171 -  virtual void DoDispose (void);
  10.172 -
  10.173 -  /**
  10.174 -   * Get a copy of the attached Queue.
  10.175 -   *
  10.176 -   * This method is provided for any derived class that may need to get
  10.177 -   * direct access to the underlying queue.
  10.178 -   *
  10.179 -   * @returns Ptr to the queue.
  10.180 -   */
  10.181 -  Ptr<Queue> GetQueue(void) const; 
  10.182 -
  10.183 -  /**
  10.184 -   * Spin up the device
  10.185 -   */
  10.186 -  void StartDevice (void);
  10.187 -
  10.188 -  /**
  10.189 -   * Tear down the device
  10.190 -   */
  10.191 -  void StopDevice (void);
  10.192 -
  10.193 -  /**
  10.194 -   * Loop to read and process packets
  10.195 -   */
  10.196 -  void ReadThread (void);
  10.197 -
  10.198 -  /**
  10.199 -   * Method to handle received packets.  Synchronized with simulator via ScheduleNow from ReadThread.
  10.200 -   */
  10.201 -  void ForwardUp (uint8_t *buf, uint32_t len);
  10.202 -
  10.203 -  /**
  10.204 -   * Adds the necessary headers and trailers to a packet of data in order to
  10.205 -   * respect the protocol implemented by the agent.
  10.206 -   */
  10.207 -  void AddHeader(Ptr<Packet> p, uint16_t protocolNumber);
  10.208 -
  10.209 -  /**
  10.210 -   * Removes, from a packet of data, all headers and trailers that
  10.211 -   * relate to the protocol implemented by the agent
  10.212 -   * \return Returns true if the packet should be forwarded up the
  10.213 -   * protocol stack.
  10.214 -   */
  10.215 -  bool ProcessHeader(Ptr<Packet> p, uint16_t& param);
  10.216 -
  10.217 -  /**
  10.218 -   * Start Sending a Packet Down the Wire.
  10.219 -   *
  10.220 -   * @returns true if success, false on failure
  10.221 -   */
  10.222 -  bool TransmitStart (Ptr<Packet> p);
  10.223 -
  10.224 -  void NotifyLinkUp (void);
  10.225 -
  10.226 -  /**
  10.227 -   * The Queue which this EmulatedNetDevice uses as a packet source.
  10.228 -   * Management of this Queue has been delegated to the EmulatedNetDevice
  10.229 -   * and it has the responsibility for deletion.
  10.230 -   * @see class Queue
  10.231 -   * @see class DropTailQueue
  10.232 -   */
  10.233 -  Ptr<Queue> m_queue;
  10.234 -
  10.235 -  /**
  10.236 -   * The trace source for the packet reception events that the device can
  10.237 -   * fire.
  10.238 -   *
  10.239 -   * @see class CallBackTraceSource
  10.240 -   */
  10.241 -  TracedCallback<Ptr<const Packet> > m_rxTrace;
  10.242 -
  10.243 -  /**
  10.244 -   * The trace source for the packet drop events that the device can
  10.245 -   * fire.
  10.246 -   *
  10.247 -   * @see class CallBackTraceSource
  10.248 -   */
  10.249 -  TracedCallback<Ptr<const Packet> > m_dropTrace;
  10.250 -
  10.251 -  /**
  10.252 -   * Time to start spinning up the device
  10.253 -   */
  10.254 -  Time m_tStart;
  10.255 -
  10.256 -  /**
  10.257 -   * Time to start tearing down the device
  10.258 -   */
  10.259 -  Time m_tStop;
  10.260 -
  10.261 -  EventId m_startEvent;
  10.262 -  EventId m_stopEvent;
  10.263 -
  10.264 -  int32_t m_sock;
  10.265 -
  10.266 -  Ptr<SystemThread> m_readThread;
  10.267 -
  10.268 -  /**
  10.269 -   * The Node to which this device is attached.
  10.270 -   */
  10.271 -  Ptr<Node> m_node;
  10.272 -
  10.273 -  /**
  10.274 -   * The MAC address which has been assigned to this device.
  10.275 -   */
  10.276 -  Mac48Address m_address;
  10.277 -
  10.278 -  /**
  10.279 -   * The callback used to notify higher layers that a packet has been received.
  10.280 -   */
  10.281 -  NetDevice::ReceiveCallback m_rxCallback;
  10.282 -
  10.283 -  /**
  10.284 -   * The callback used to notify higher layers that a packet has been received in promiscuous mode.
  10.285 -   */
  10.286 -  NetDevice::PromiscReceiveCallback m_promiscRxCallback;
  10.287 -
  10.288 -  /**
  10.289 -   * The ns-3 interface index (in the sense of net device index) that has been assigned to this network device.
  10.290 -   */
  10.291 -  uint32_t m_ifIndex;
  10.292 -
  10.293 -  /**
  10.294 -   * The Unix interface index that we got from the system and which corresponds to the interface (e.g., "eth1")
  10.295 -   * we are using to talk to the network.  Valid when m_sock is valid.
  10.296 -   */
  10.297 -  int32_t m_sll_ifindex;
  10.298 -
  10.299 -  /**
  10.300 -   * The human readable name of this device.
  10.301 -   */
  10.302 -  std::string m_name;
  10.303 -
  10.304 -  /**
  10.305 -   * Flag indicating whether or not the link is up.  In this case,
  10.306 -   * whether or not the device is connected to a channel.
  10.307 -   */
  10.308 -  bool m_linkUp;
  10.309 -
  10.310 -  /**
  10.311 -   * Callback to fire if the link changes state (up or down).
  10.312 -   */
  10.313 -  Callback<void> m_linkChangeCallback;
  10.314 -
  10.315 -  /**
  10.316 -   * The unix/linux name of the underlying device (e.g., eth0)
  10.317 -   */
  10.318 -  std::string m_deviceName;
  10.319 -};
  10.320 -
  10.321 -} // namespace ns3
  10.322 -
  10.323 -#endif // EMULATED_NET_DEVICE_H
  10.324 -
    11.1 --- a/src/devices/emulated/emulated.h	Wed Oct 29 11:49:21 2008 -0700
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,10 +0,0 @@
    11.4 -/**
    11.5 - * \ingroup devices
    11.6 - * \defgroup Emulated Emulated Net Device Model
    11.7 - *
    11.8 - * \section Emulated Net Device Model
    11.9 - *
   11.10 - * This is a description of the emulated network device model.
   11.11 - *
   11.12 - * It is very detailed and comprehensive and answers all possible questions.
   11.13 - */
    12.1 --- a/src/devices/emulated/waf	Wed Oct 29 11:49:21 2008 -0700
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,1 +0,0 @@
    12.4 -exec "`dirname "$0"`"/../../../waf "$@"
    13.1 --- a/src/devices/emulated/wscript	Wed Oct 29 11:49:21 2008 -0700
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,14 +0,0 @@
    13.4 -## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
    13.5 -
    13.6 -
    13.7 -def build(bld):
    13.8 -    module = bld.create_ns3_module('emulated', ['node'])
    13.9 -    module.source = [
   13.10 -        'emulated-net-device.cc',
   13.11 -        ]
   13.12 -    headers = bld.create_obj('ns3header')
   13.13 -    headers.module = 'emulated'
   13.14 -    headers.source = [
   13.15 -        'emulated-net-device.h',
   13.16 -        ]
   13.17 -
    14.1 --- a/src/helper/emu-helper.cc	Wed Oct 29 11:49:21 2008 -0700
    14.2 +++ b/src/helper/emu-helper.cc	Wed Oct 29 22:39:36 2008 -0700
    14.3 @@ -22,7 +22,7 @@
    14.4  #include "ns3/simulator.h"
    14.5  #include "ns3/object-factory.h"
    14.6  #include "ns3/queue.h"
    14.7 -#include "ns3/emulated-net-device.h"
    14.8 +#include "ns3/emu-net-device.h"
    14.9  #include "ns3/pcap-writer.h"
   14.10  #include "ns3/config.h"
   14.11  #include "ns3/packet.h"
   14.12 @@ -37,7 +37,7 @@
   14.13  {
   14.14    NS_LOG_FUNCTION_NOARGS ();
   14.15    m_queueFactory.SetTypeId ("ns3::DropTailQueue");
   14.16 -  m_deviceFactory.SetTypeId ("ns3::EmulatedNetDevice");
   14.17 +  m_deviceFactory.SetTypeId ("ns3::EmuNetDevice");
   14.18  }
   14.19  
   14.20    void 
   14.21 @@ -78,13 +78,13 @@
   14.22  
   14.23    oss.str ("");
   14.24    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << 
   14.25 -    "/$ns3::EmulatedNetDevice/Rx";
   14.26 +    "/$ns3::EmuNetDevice/Rx";
   14.27    Config::ConnectWithoutContext (oss.str (), 
   14.28      MakeBoundCallback (&EmuHelper::RxEvent, pcap));
   14.29  
   14.30    oss.str ("");
   14.31    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << 
   14.32 -    "/$ns3::EmulatedNetDevice/TxQueue/Enqueue";
   14.33 +    "/$ns3::EmuNetDevice/TxQueue/Enqueue";
   14.34    Config::ConnectWithoutContext (oss.str (), 
   14.35      MakeBoundCallback (&EmuHelper::EnqueueEvent, pcap));
   14.36  }
   14.37 @@ -131,25 +131,25 @@
   14.38    std::ostringstream oss;
   14.39  
   14.40    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << 
   14.41 -    "/$ns3::EmulatedNetDevice/Rx";
   14.42 +    "/$ns3::EmuNetDevice/Rx";
   14.43    Config::Connect (oss.str (), 
   14.44      MakeBoundCallback (&EmuHelper::AsciiRxEvent, &os));
   14.45  
   14.46    oss.str ("");
   14.47    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << 
   14.48 -    "/$ns3::EmulatedNetDevice/TxQueue/Enqueue";
   14.49 +    "/$ns3::EmuNetDevice/TxQueue/Enqueue";
   14.50    Config::Connect (oss.str (), 
   14.51      MakeBoundCallback (&EmuHelper::AsciiEnqueueEvent, &os));
   14.52  
   14.53    oss.str ("");
   14.54    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << 
   14.55 -    "/$ns3::EmulatedNetDevice/TxQueue/Dequeue";
   14.56 +    "/$ns3::EmuNetDevice/TxQueue/Dequeue";
   14.57    Config::Connect (oss.str (), 
   14.58      MakeBoundCallback (&EmuHelper::AsciiDequeueEvent, &os));
   14.59  
   14.60    oss.str ("");
   14.61    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << 
   14.62 -    "/$ns3::EmulatedNetDevice/TxQueue/Drop";
   14.63 +    "/$ns3::EmuNetDevice/TxQueue/Drop";
   14.64    Config::Connect (oss.str (), 
   14.65      MakeBoundCallback (&EmuHelper::AsciiDropEvent, &os));
   14.66  }
   14.67 @@ -197,7 +197,7 @@
   14.68      {
   14.69        Ptr<Node> node = *i;
   14.70  
   14.71 -      Ptr<EmulatedNetDevice> device = m_deviceFactory.Create<EmulatedNetDevice> ();
   14.72 +      Ptr<EmuNetDevice> device = m_deviceFactory.Create<EmuNetDevice> ();
   14.73        //
   14.74        // This is a mac address used for ns-3 internal things.  It cannot override the real MAC address on the NIC in
   14.75        // question.
    15.1 --- a/src/helper/emu-helper.h	Wed Oct 29 11:49:21 2008 -0700
    15.2 +++ b/src/helper/emu-helper.h	Wed Oct 29 22:39:36 2008 -0700
    15.3 @@ -25,7 +25,7 @@
    15.4  #include "ns3/object-factory.h"
    15.5  #include "ns3/net-device-container.h"
    15.6  #include "ns3/node-container.h"
    15.7 -#include "ns3/emulated-net-device.h"
    15.8 +#include "ns3/emu-net-device.h"
    15.9  
   15.10  namespace ns3 {
   15.11  
    16.1 --- a/src/wscript	Wed Oct 29 11:49:21 2008 -0700
    16.2 +++ b/src/wscript	Wed Oct 29 22:39:36 2008 -0700
    16.3 @@ -21,7 +21,7 @@
    16.4      'devices/csma',
    16.5      'devices/bridge',
    16.6      'devices/tap',
    16.7 -    'devices/emulated',
    16.8 +    'devices/emu',
    16.9      'applications/onoff',
   16.10      'applications/packet-sink',
   16.11      'applications/udp-echo',