23#include "ns3/config.h" 
   24#include "ns3/fd-net-device.h" 
   27#include "ns3/object-factory.h" 
   28#include "ns3/packet.h" 
   29#include "ns3/simulator.h" 
   30#include "ns3/trace-helper.h" 
   38#include <net/ethernet.h> 
   40#include <netinet/in.h> 
   41#include <netpacket/packet.h> 
   46#include <sys/socket.h> 
   58#define EMU_MAGIC 65867 
  100        NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::SetFileDescriptor (): m_deviceName is not set");
 
  108    device->SetFileDescriptor(fd);
 
  115    bzero(&ifr, 
sizeof(ifr));
 
  116    strncpy((
char*)ifr.ifr_name, 
m_deviceName.c_str(), IFNAMSIZ - 1);
 
  119    int32_t rc = ioctl(fd, SIOCGIFINDEX, &ifr);
 
  122        NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::SetFileDescriptor (): Can't get interface index");
 
  128    struct sockaddr_ll ll;
 
  129    bzero(&ll, 
sizeof(ll));
 
  131    ll.sll_family = AF_PACKET;
 
  132    ll.sll_ifindex = ifr.ifr_ifindex;
 
  133    ll.sll_protocol = htons(ETH_P_ALL);
 
  137    rc = bind(fd, (
struct sockaddr*)&ll, 
sizeof(ll));
 
  141            "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,
 
  158                                            sizeof(sock_qdisc_bypass));
 
  160        if (sock_qdisc_ret == -1)
 
  166        NS_LOG_ERROR(
"PACKET_QDISC_BYPASS undefined; cannot use the qdisc bypass option");
 
  181    if ((ifr.ifr_flags & IFF_PROMISC) == 0)
 
  187    if ((ifr.ifr_flags & IFF_BROADCAST) != IFF_BROADCAST)
 
  193        device->SetIsBroadcast(
false);
 
  196    if ((ifr.ifr_flags & IFF_MULTICAST) == IFF_MULTICAST)
 
  199        device->SetIsMulticast(
true);
 
  205    bzero(&ifr2, 
sizeof(ifr2));
 
  208    int32_t mtufd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
 
  210    rc = ioctl(mtufd, SIOCGIFMTU, &ifr2);
 
  213        NS_FATAL_ERROR(
"FdNetDevice::SetFileDescriptor (): Can't ioctl SIOCGIFMTU");
 
  217    device->SetMtu(ifr2.ifr_mtu);
 
  234    int sock = socket(PF_UNIX, SOCK_DGRAM, 0);
 
  238            "EmuFdNetDeviceHelper::CreateFileDescriptor(): Unix socket creation error, errno = " 
  245    struct sockaddr_un un;
 
  246    memset(&un, 0, 
sizeof(un));
 
  247    un.sun_family = AF_UNIX;
 
  248    int status = bind(sock, (
struct sockaddr*)&un, 
sizeof(sa_family_t));
 
  251        NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::CreateFileDescriptor(): Could not bind(): errno = " 
  265    socklen_t len = 
sizeof(un);
 
  266    status = getsockname(sock, (
struct sockaddr*)&un, &len);
 
  270            "EmuFdNetDeviceHelper::CreateFileDescriptor(): Could not getsockname(): errno = " 
  290    pid_t pid = ::fork();
 
  300        std::ostringstream oss;
 
  302        NS_LOG_INFO(
"Parameters set to \"" << oss.str() << 
"\"");
 
  307        status = ::execlp(RAW_SOCK_CREATOR,
 
  316        NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::CreateFileDescriptor(): Back from execlp(), status = " 
  317                       << status << 
", errno = " << ::strerror(errno));
 
  327        pid_t waited = waitpid(pid, &st, 0);
 
  330            NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::CreateFileDescriptor(): waitpid() fails, errno = " 
  333        NS_ASSERT_MSG(pid == waited, 
"EmuFdNetDeviceHelper::CreateFileDescriptor(): pid mismatch");
 
  342            int exitStatus = WEXITSTATUS(st);
 
  345                NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::CreateFileDescriptor(): socket creator " 
  346                               "exited normally with status " 
  353                "EmuFdNetDeviceHelper::CreateFileDescriptor(): socket creator exited abnormally");
 
  369        iov.iov_base = &magic;
 
  370        iov.iov_len = 
sizeof(magic);
 
  383        size_t msg_size = 
sizeof(
int);
 
  384        char control[CMSG_SPACE(msg_size)];
 
  397        msg.msg_name = 
nullptr;
 
  401        msg.msg_control = control;
 
  402        msg.msg_controllen = 
sizeof(control);
 
  409        ssize_t bytesRead = recvmsg(sock, &msg, 0);
 
  410        if (bytesRead != 
sizeof(
int))
 
  412            NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::CreateFileDescriptor(): Wrong byte count from " 
  421        struct cmsghdr* cmsg;
 
  422        for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != 
nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg))
 
  424            if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
 
  433                    NS_LOG_INFO(
"Got SCM_RIGHTS with correct magic " << magic);
 
  434                    int* rawSocket = (
int*)CMSG_DATA(cmsg);
 
  435                    NS_LOG_INFO(
"Got the socket from the socket creator = " << *rawSocket);
 
  440                    NS_LOG_INFO(
"Got SCM_RIGHTS, but with bad magic " << magic);
 
  444        NS_FATAL_ERROR(
"Did not get the raw socket from the socket creator");
 
bool m_hostQdiscBypass
True if request host qdisc bypass.
 
std::string m_deviceName
The Unix/Linux name of the underlying device (e.g., eth0)
 
void HostQdiscBypass(bool hostQdiscBypass)
Request host qdisc bypass.
 
void SetDeviceName(std::string deviceName)
Set the device name of this device.
 
Ptr< NetDevice > InstallPriv(Ptr< Node > node) const override
This method creates an ns3::FdNetDevice attached to a physical network interface.
 
virtual void SetFileDescriptor(Ptr< FdNetDevice > device) const
Sets a file descriptor on the FileDescriptorNetDevice.
 
std::string GetDeviceName()
Get the device name of this device.
 
virtual int CreateFileDescriptor() const
Call out to a separate process running as suid root in order to get a raw socket.
 
EmuFdNetDeviceHelper()
Construct a EmuFdNetDeviceHelper.
 
virtual Ptr< NetDevice > InstallPriv(Ptr< Node > node) const
This method creates an ns3::FdNetDevice and associates it to a node.
 
a NetDevice to read/write network traffic from/into a file descriptor.
 
Smart pointer class similar to boost::intrusive_ptr.
 
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
 
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
 
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
 
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
 
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
 
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
 
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
 
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
 
Every class exported by the ns3 library is enclosed in the ns3 namespace.
 
std::string BufferToString(uint8_t *buffer, uint32_t len)
Convert a byte buffer to a string containing a hex representation of the buffer.
 
ns3::StringValue attribute value declarations.