22 #include "ns3/abort.h"    23 #include "ns3/config.h"    24 #include "ns3/fd-net-device.h"    26 #include "ns3/names.h"    27 #include "ns3/object-factory.h"    28 #include "ns3/packet.h"    29 #include "ns3/simulator.h"    30 #include "ns3/trace-helper.h"    32 #include <arpa/inet.h>    37 #include <linux/if_tun.h>    39 #include <net/ethernet.h>    41 #include <netinet/in.h>    42 #include <netpacket/packet.h>    48 #include <sys/socket.h>    50 #include <sys/ioctl.h>    60 #define EMU_MAGIC 65867   102       NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::SetFileDescriptor (): m_deviceName is not set");
   110   device->SetFileDescriptor (fd);
   116   bzero (&ifr, 
sizeof(ifr));
   117   strncpy ((
char *)ifr.ifr_name, 
m_deviceName.c_str (), IFNAMSIZ - 1);
   120   int32_t rc = ioctl (fd, SIOCGIFINDEX, &ifr);
   123       NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::SetFileDescriptor (): Can't get interface index");
   129   struct sockaddr_ll ll;
   130   bzero (&ll, 
sizeof(ll));
   132   ll.sll_family = AF_PACKET;
   133   ll.sll_ifindex = ifr.ifr_ifindex;
   134   ll.sll_protocol = htons (ETH_P_ALL);
   138   rc = bind (fd, (
struct sockaddr *)&ll, 
sizeof (ll));
   141       NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::SetFileDescriptor (): Can't bind to specified interface");
   144   rc = ioctl (fd, SIOCGIFFLAGS, &ifr);
   147       NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::SetFileDescriptor (): Can't get interface flags");
   152 #ifdef PACKET_QDISC_BYPASS   153       static const int32_t sock_qdisc_bypass = 1;
   154       int32_t sock_qdisc_ret = setsockopt (fd, SOL_PACKET, PACKET_QDISC_BYPASS, &sock_qdisc_bypass,
   155                                            sizeof (sock_qdisc_bypass));
   157       if (sock_qdisc_ret == -1)
   163       NS_LOG_ERROR (
"PACKET_QDISC_BYPASS undefined; cannot use the qdisc bypass option");
   178   if ((ifr.ifr_flags & IFF_PROMISC) == 0)
   183   if ((ifr.ifr_flags & IFF_BROADCAST) != IFF_BROADCAST)
   189       device->SetIsBroadcast (
false);
   192   if ((ifr.ifr_flags & IFF_MULTICAST) == IFF_MULTICAST)
   195       device->SetIsMulticast (
true);
   201   bzero (&ifr2, 
sizeof (ifr2));
   204   int32_t mtufd = socket (PF_INET, SOCK_DGRAM, IPPROTO_IP);
   206   rc = ioctl (mtufd, SIOCGIFMTU, &ifr2);
   209       NS_FATAL_ERROR (
"FdNetDevice::SetFileDescriptor (): Can't ioctl SIOCGIFMTU");
   213   device->SetMtu (ifr2.ifr_mtu);
   230   int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
   233       NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::CreateFileDescriptor(): Unix socket creation error, errno = " << strerror (errno));
   239   struct sockaddr_un un;
   240   memset (&un, 0, 
sizeof (un));
   241   un.sun_family = AF_UNIX;
   242   int status = bind (sock, (
struct sockaddr*)&un, 
sizeof (sa_family_t));
   245       NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::CreateFileDescriptor(): Could not bind(): errno = " << strerror (errno));
   258   socklen_t len = 
sizeof (un);
   259   status = getsockname (sock, (
struct sockaddr*)&un, &len);
   262       NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::CreateFileDescriptor(): Could not getsockname(): errno = " << strerror (errno));
   269   NS_LOG_INFO (
"Encoded Unix socket as \"" << path << 
"\"");
   281   pid_t pid = ::fork ();
   291       std::ostringstream oss;
   293       NS_LOG_INFO (
"Parameters set to \"" << oss.str () << 
"\"");
   298       status = ::execlp (RAW_SOCK_CREATOR,
   307       NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::CreateFileDescriptor(): Back from execlp(), status = " <<
   308                       status << 
", errno = " << ::strerror (errno));
   318       pid_t waited = waitpid (pid, &st, 0);
   321           NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::CreateFileDescriptor(): waitpid() fails, errno = " << strerror (errno));
   323       NS_ASSERT_MSG (pid == waited, 
"EmuFdNetDeviceHelper::CreateFileDescriptor(): pid mismatch");
   332           int exitStatus = WEXITSTATUS (st);
   335               NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::CreateFileDescriptor(): socket creator exited normally with status " << exitStatus);
   340           NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::CreateFileDescriptor(): socket creator exited abnormally");
   356       iov.iov_base = &magic;
   357       iov.iov_len = 
sizeof(magic);
   370       size_t msg_size = 
sizeof(int);
   371       char control[CMSG_SPACE (msg_size)];
   388       msg.msg_control = control;
   389       msg.msg_controllen = 
sizeof (control);
   396       ssize_t bytesRead = recvmsg (sock, &msg, 0);
   397       if (bytesRead != 
sizeof(
int))
   399           NS_FATAL_ERROR (
"EmuFdNetDeviceHelper::CreateFileDescriptor(): Wrong byte count from socket creator");
   407       struct cmsghdr *cmsg;
   408       for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg))
   410           if (cmsg->cmsg_level == SOL_SOCKET
   411               && cmsg->cmsg_type == SCM_RIGHTS)
   420                   NS_LOG_INFO (
"Got SCM_RIGHTS with correct magic " << magic);
   421                   int *rawSocket = (
int*)CMSG_DATA (cmsg);
   422                   NS_LOG_INFO (
"Got the socket from the socket creator = " << *rawSocket);
   427                   NS_LOG_INFO (
"Got SCM_RIGHTS, but with bad magic " << magic);
   431       NS_FATAL_ERROR (
"Did not get the raw socket from the socket creator");
 virtual Ptr< NetDevice > InstallPriv(Ptr< Node > node) const
This method creates an ns3::FdNetDevice and associates it to a node. 
Smart pointer class similar to boost::intrusive_ptr. 
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void HostQdiscBypass(bool hostQdiscBypass)
Request host qdisc bypass. 
ns3::StringValue attribute value declarations. 
EmuFdNetDeviceHelper()
Construct a EmuFdNetDeviceHelper. 
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name. 
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO. 
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate. 
virtual int CreateFileDescriptor(void) const
Call out to a separate process running as suid root in order to get a raw socket. ...
std::string BufferToString(uint8_t *buffer, uint32_t len)
Convert a byte buffer to a string containing a hex representation of the buffer. 
virtual void SetFileDescriptor(Ptr< FdNetDevice > device) const
Sets a file descriptor on the FileDescriptorNetDevice. 
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC. 
Ptr< NetDevice > InstallPriv(Ptr< Node > node) const
This method creates an ns3::FdNetDevice attached to a physical network interface. ...
void SetDeviceName(std::string deviceName)
Set the device name of this device. 
Every class exported by the ns3 library is enclosed in the ns3 namespace. 
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
std::string GetDeviceName(void)
Get the device name of this device. 
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG. 
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR. 
a NetDevice to read/write network traffic from/into a file descriptor. 
std::string m_deviceName
The Unix/Linux name of the underlying device (e.g., eth0)