12#include "ns3/config.h"
13#include "ns3/fd-net-device.h"
16#include "ns3/object-factory.h"
17#include "ns3/packet.h"
18#include "ns3/simulator.h"
19#include "ns3/trace-helper.h"
27#include <net/ethernet.h>
29#include <netinet/in.h>
30#include <netpacket/packet.h>
35#include <sys/socket.h>
47#define EMU_MAGIC 65867
89 NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::SetFileDescriptor (): m_deviceName is not set");
97 device->SetFileDescriptor(fd);
104 bzero(&ifr,
sizeof(ifr));
105 strncpy((
char*)ifr.ifr_name,
m_deviceName.c_str(), IFNAMSIZ - 1);
108 int32_t rc = ioctl(fd, SIOCGIFINDEX, &ifr);
111 NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::SetFileDescriptor (): Can't get interface index");
117 struct sockaddr_ll ll;
118 bzero(&ll,
sizeof(ll));
120 ll.sll_family = AF_PACKET;
121 ll.sll_ifindex = ifr.ifr_ifindex;
122 ll.sll_protocol = htons(ETH_P_ALL);
126 rc = bind(fd, (
struct sockaddr*)&ll,
sizeof(ll));
130 "EmuFdNetDeviceHelper::SetFileDescriptor (): Can't bind to specified interface");
133 rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
136 NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::SetFileDescriptor (): Can't get interface flags");
141#ifdef PACKET_QDISC_BYPASS
142 static const int32_t sock_qdisc_bypass = 1;
143 int32_t sock_qdisc_ret = setsockopt(fd,
147 sizeof(sock_qdisc_bypass));
149 if (sock_qdisc_ret == -1)
155 NS_LOG_ERROR(
"PACKET_QDISC_BYPASS undefined; cannot use the qdisc bypass option");
170 if ((ifr.ifr_flags & IFF_PROMISC) == 0)
176 if ((ifr.ifr_flags & IFF_BROADCAST) != IFF_BROADCAST)
182 device->SetIsBroadcast(
false);
185 if ((ifr.ifr_flags & IFF_MULTICAST) == IFF_MULTICAST)
188 device->SetIsMulticast(
true);
194 bzero(&ifr2,
sizeof(ifr2));
197 int32_t mtufd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
199 rc = ioctl(mtufd, SIOCGIFMTU, &ifr2);
202 NS_FATAL_ERROR(
"FdNetDevice::SetFileDescriptor (): Can't ioctl SIOCGIFMTU");
206 device->SetMtu(ifr2.ifr_mtu);
223 int sock = socket(PF_UNIX, SOCK_DGRAM, 0);
227 "EmuFdNetDeviceHelper::CreateFileDescriptor(): Unix socket creation error, errno = "
234 struct sockaddr_un un;
235 memset(&un, 0,
sizeof(un));
236 un.sun_family = AF_UNIX;
237 int status = bind(sock, (
struct sockaddr*)&un,
sizeof(sa_family_t));
240 NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::CreateFileDescriptor(): Could not bind(): errno = "
254 socklen_t len =
sizeof(un);
255 status = getsockname(sock, (
struct sockaddr*)&un, &len);
259 "EmuFdNetDeviceHelper::CreateFileDescriptor(): Could not getsockname(): errno = "
267 NS_LOG_INFO(
"Encoded Unix socket as \"" << path <<
"\"");
279 pid_t pid = ::fork();
289 std::ostringstream oss;
291 NS_LOG_INFO(
"Parameters set to \"" << oss.str() <<
"\"");
296 status = ::execlp(RAW_SOCK_CREATOR,
305 NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::CreateFileDescriptor(): Back from execlp(), status = "
306 << status <<
", errno = " << ::strerror(errno));
316 pid_t waited = waitpid(pid, &st, 0);
319 NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::CreateFileDescriptor(): waitpid() fails, errno = "
322 NS_ASSERT_MSG(pid == waited,
"EmuFdNetDeviceHelper::CreateFileDescriptor(): pid mismatch");
331 int exitStatus = WEXITSTATUS(st);
334 NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::CreateFileDescriptor(): socket creator "
335 "exited normally with status "
342 "EmuFdNetDeviceHelper::CreateFileDescriptor(): socket creator exited abnormally");
358 iov.iov_base = &magic;
359 iov.iov_len =
sizeof(magic);
372 constexpr size_t msg_size =
sizeof(int);
373 char control[CMSG_SPACE(msg_size)];
386 msg.msg_name =
nullptr;
390 msg.msg_control = control;
391 msg.msg_controllen =
sizeof(control);
398 ssize_t bytesRead = recvmsg(sock, &msg, 0);
399 if (bytesRead !=
sizeof(
int))
401 NS_FATAL_ERROR(
"EmuFdNetDeviceHelper::CreateFileDescriptor(): Wrong byte count from "
410 struct cmsghdr* cmsg;
411 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg !=
nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg))
413 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
422 NS_LOG_INFO(
"Got SCM_RIGHTS with correct magic " << magic);
423 int* rawSocket = (
int*)CMSG_DATA(cmsg);
424 NS_LOG_INFO(
"Got the socket from the socket creator = " << *rawSocket);
429 NS_LOG_INFO(
"Got SCM_RIGHTS, but with bad magic " << magic);
433 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.