1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/devices/emutap/host-tap-net-device.cc Mon Oct 27 13:01:28 2008 -0700
1.3 @@ -0,0 +1,194 @@
1.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
1.5 +/*
1.6 + * Copyright (c) 2008 INRIA
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 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
1.22 + */
1.23 +#include "host-tap-net-device.h"
1.24 +#include "ns3/node.h"
1.25 +#include "ns3/tap-channel.h"
1.26 +#include "ns3/log.h"
1.27 +
1.28 +NS_LOG_COMPONENT_DEFINE ("HostTapNetDevice");
1.29 +
1.30 +namespace ns3 {
1.31 +
1.32 +TypeId
1.33 +HostTapNetDevice::GetTypeId (void)
1.34 +{
1.35 + static TypeId tid = TypeId ("ns3::HostTapNetDevice")
1.36 + .SetParent<NetDevice> ()
1.37 + .AddConstructor<HostTapNetDevice> ()
1.38 + ;
1.39 + return tid;
1.40 +}
1.41 +
1.42 +HostTapNetDevice::HostTapNetDevice ()
1.43 + : m_node (0),
1.44 + m_mtu (0xffff),
1.45 + m_name (""),
1.46 + m_ifIndex (0)
1.47 +{
1.48 + NS_LOG_FUNCTION (this);
1.49 +}
1.50 +
1.51 +void
1.52 +HostTapNetDevice::SetChannel (Ptr<TapChannel> channel)
1.53 +{
1.54 + m_channel = channel;
1.55 + m_channel->SetHostDevice (this);
1.56 +}
1.57 +
1.58 +void
1.59 +HostTapNetDevice::SetAddress (Mac48Address address)
1.60 +{
1.61 + m_address = address;
1.62 +}
1.63 +
1.64 +Mac48Address
1.65 +HostTapNetDevice::GetMacAddress (void) const
1.66 +{
1.67 + return m_address;
1.68 +}
1.69 +
1.70 +void
1.71 +HostTapNetDevice::SetName(const std::string name)
1.72 +{
1.73 + m_name = name;
1.74 +}
1.75 +std::string
1.76 +HostTapNetDevice::GetName(void) const
1.77 +{
1.78 + return m_name;
1.79 +}
1.80 +void
1.81 +HostTapNetDevice::SetIfIndex(const uint32_t index)
1.82 +{
1.83 + m_ifIndex = index;
1.84 +}
1.85 +uint32_t
1.86 +HostTapNetDevice::GetIfIndex(void) const
1.87 +{
1.88 + return m_ifIndex;
1.89 +}
1.90 +Ptr<Channel>
1.91 +HostTapNetDevice::GetChannel (void) const
1.92 +{
1.93 + return m_channel;
1.94 +}
1.95 +Address
1.96 +HostTapNetDevice::GetAddress (void) const
1.97 +{
1.98 + return m_address;
1.99 +}
1.100 +bool
1.101 +HostTapNetDevice::SetMtu (const uint16_t mtu)
1.102 +{
1.103 + m_mtu = mtu;
1.104 + return true;
1.105 +}
1.106 +uint16_t
1.107 +HostTapNetDevice::GetMtu (void) const
1.108 +{
1.109 + return m_mtu;
1.110 +}
1.111 +bool
1.112 +HostTapNetDevice::IsLinkUp (void) const
1.113 +{
1.114 + return true;
1.115 +}
1.116 +void
1.117 +HostTapNetDevice::SetLinkChangeCallback (Callback<void> callback)
1.118 +{}
1.119 +bool
1.120 +HostTapNetDevice::IsBroadcast (void) const
1.121 +{
1.122 + return true;
1.123 +}
1.124 +Address
1.125 +HostTapNetDevice::GetBroadcast (void) const
1.126 +{
1.127 + return Mac48Address ("ff:ff:ff:ff:ff:ff");
1.128 +}
1.129 +bool
1.130 +HostTapNetDevice::IsMulticast (void) const
1.131 +{
1.132 + return true;
1.133 +}
1.134 +Address
1.135 +HostTapNetDevice::GetMulticast (void) const
1.136 +{
1.137 + return Mac48Address::GetMulticastPrefix ();
1.138 +}
1.139 +Address
1.140 +HostTapNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
1.141 +{
1.142 + return Mac48Address::GetMulticast (multicastGroup);
1.143 +}
1.144 +bool
1.145 +HostTapNetDevice::IsPointToPoint (void) const
1.146 +{
1.147 + return false;
1.148 +}
1.149 +bool
1.150 +HostTapNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
1.151 +{
1.152 + return false;
1.153 +}
1.154 +bool
1.155 +HostTapNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
1.156 +{
1.157 + return false;
1.158 +}
1.159 +Ptr<Node>
1.160 +HostTapNetDevice::GetNode (void) const
1.161 +{
1.162 + return m_node;
1.163 +}
1.164 +void
1.165 +HostTapNetDevice::SetNode (Ptr<Node> node)
1.166 +{
1.167 + m_node = node;
1.168 +}
1.169 +bool
1.170 +HostTapNetDevice::NeedsArp (void) const
1.171 +{
1.172 + return false;
1.173 +}
1.174 +void
1.175 +HostTapNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
1.176 +{}
1.177 +
1.178 +void
1.179 +HostTapNetDevice::DoDispose (void)
1.180 +{
1.181 + NS_LOG_FUNCTION (this);
1.182 + m_node = 0;
1.183 + m_channel = 0;
1.184 + NetDevice::DoDispose ();
1.185 +}
1.186 +
1.187 +void
1.188 +HostTapNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
1.189 +{}
1.190 +
1.191 +bool
1.192 +HostTapNetDevice::SupportsSendFrom (void) const
1.193 +{
1.194 + return false;
1.195 +}
1.196 +
1.197 +} // namespace ns3
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/src/devices/emutap/host-tap-net-device.h Mon Oct 27 13:01:28 2008 -0700
2.3 @@ -0,0 +1,90 @@
2.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2.5 +/*
2.6 + * Copyright (c) 2008 INRIA
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 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
2.22 + */
2.23 +#ifndef HOST_TAP_NET_DEVICE_H
2.24 +#define HOST_TAP_NET_DEVICE_H
2.25 +
2.26 +#include "ns3/net-device.h"
2.27 +#include "ns3/mac48-address.h"
2.28 +#include "ns3/traced-callback.h"
2.29 +#include <stdint.h>
2.30 +#include <string>
2.31 +
2.32 +namespace ns3 {
2.33 +
2.34 +class Node;
2.35 +class TapChannel;
2.36 +
2.37 +
2.38 +/**
2.39 + * \ingroup netdevice
2.40 + *
2.41 + * \brief a NetDevice to get packets to and from a host tap device.
2.42 + */
2.43 +class HostTapNetDevice : public NetDevice
2.44 +{
2.45 +public:
2.46 + static TypeId GetTypeId (void);
2.47 + HostTapNetDevice ();
2.48 +
2.49 + void SetAddress (Mac48Address address);
2.50 + void SetChannel (Ptr<TapChannel> channel);
2.51 +
2.52 + Mac48Address GetMacAddress (void) const;
2.53 +
2.54 + // inherited from NetDevice base class.
2.55 + virtual void SetName(const std::string name);
2.56 + virtual std::string GetName(void) const;
2.57 + virtual void SetIfIndex(const uint32_t index);
2.58 + virtual uint32_t GetIfIndex(void) const;
2.59 + virtual Ptr<Channel> GetChannel (void) const;
2.60 + virtual Address GetAddress (void) const;
2.61 + virtual bool SetMtu (const uint16_t mtu);
2.62 + virtual uint16_t GetMtu (void) const;
2.63 + virtual bool IsLinkUp (void) const;
2.64 + virtual void SetLinkChangeCallback (Callback<void> callback);
2.65 + virtual bool IsBroadcast (void) const;
2.66 + virtual Address GetBroadcast (void) const;
2.67 + virtual bool IsMulticast (void) const;
2.68 + virtual Address GetMulticast (void) const;
2.69 + virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
2.70 + virtual bool IsPointToPoint (void) const;
2.71 + virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
2.72 + virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
2.73 + virtual Ptr<Node> GetNode (void) const;
2.74 + virtual void SetNode (Ptr<Node> node);
2.75 + virtual bool NeedsArp (void) const;
2.76 + virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
2.77 + virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
2.78 + virtual bool SupportsSendFrom (void) const;
2.79 +
2.80 +protected:
2.81 + virtual void DoDispose (void);
2.82 +private:
2.83 + Ptr<Node> m_node;
2.84 + uint16_t m_mtu;
2.85 + std::string m_name;
2.86 + uint32_t m_ifIndex;
2.87 + Mac48Address m_address;
2.88 + Ptr<TapChannel> m_channel;
2.89 +};
2.90 +
2.91 +} // namespace ns3
2.92 +
2.93 +#endif /* HOST_TAP_NET_DEVICE_H */
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/src/devices/emutap/tap-channel.cc Mon Oct 27 13:01:28 2008 -0700
3.3 @@ -0,0 +1,61 @@
3.4 +#include "tap-channel.h"
3.5 +#include "host-tap-net-device.h"
3.6 +#include "tap-net-device.h"
3.7 +
3.8 +namespace ns3 {
3.9 +
3.10 +
3.11 +TapChannel::TapChannel ()
3.12 + : m_hostDevice (0),
3.13 + m_device (0)
3.14 +{}
3.15 +
3.16 +void
3.17 +TapChannel::DoDispose (void)
3.18 +{
3.19 + m_device = 0;
3.20 + m_hostDevice = 0;
3.21 + Channel::DoDispose ();
3.22 +}
3.23 +
3.24 +void
3.25 +TapChannel::SetDevice (Ptr<TapNetDevice> device)
3.26 +{
3.27 + m_device = device;
3.28 +}
3.29 +
3.30 +void
3.31 +TapChannel::SetHostDevice (Ptr<HostTapNetDevice> device)
3.32 +{
3.33 + m_hostDevice = device;
3.34 +}
3.35 +
3.36 +Ptr<HostTapNetDevice>
3.37 +TapChannel::GetHostDevice (void) const
3.38 +{
3.39 + return m_hostDevice;
3.40 +}
3.41 +
3.42 +uint32_t
3.43 +TapChannel::GetNDevices (void) const
3.44 +{
3.45 + return 2;
3.46 +}
3.47 +Ptr<NetDevice>
3.48 +TapChannel::GetDevice (uint32_t i) const
3.49 +{
3.50 + if (i == 0)
3.51 + {
3.52 + return m_device;
3.53 + }
3.54 + else if (i == 1)
3.55 + {
3.56 + return m_hostDevice;
3.57 + }
3.58 + else
3.59 + {
3.60 + return 0;
3.61 + }
3.62 +}
3.63 +
3.64 +} // namespace ns3
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/src/devices/emutap/tap-channel.h Mon Oct 27 13:01:28 2008 -0700
4.3 @@ -0,0 +1,36 @@
4.4 +#ifndef TAP_CHANNEL_H
4.5 +#define TAP_CHANNEL_H
4.6 +
4.7 +#include "ns3/channel.h"
4.8 +
4.9 +namespace ns3 {
4.10 +
4.11 +class HostTapNetDevice;
4.12 +class TapNetDevice;
4.13 +class NetDevice;
4.14 +
4.15 +
4.16 +class TapChannel : public Channel
4.17 +{
4.18 +public:
4.19 + TapChannel ();
4.20 +
4.21 + void SetHostDevice (Ptr<HostTapNetDevice> device);
4.22 + void SetDevice (Ptr<TapNetDevice> device);
4.23 +
4.24 + Ptr<HostTapNetDevice> GetHostDevice (void) const;
4.25 +
4.26 + // overriden from Channel base class
4.27 + virtual uint32_t GetNDevices (void) const;
4.28 + virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
4.29 +
4.30 +private:
4.31 + virtual void DoDispose (void);
4.32 +
4.33 + Ptr<HostTapNetDevice> m_hostDevice;
4.34 + Ptr<TapNetDevice> m_device;
4.35 +};
4.36 +
4.37 +} // namespace ns3
4.38 +
4.39 +#endif /* TAP_CHANNEL_H */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/src/devices/emutap/tap-manager-client.cc Mon Oct 27 13:01:28 2008 -0700
5.3 @@ -0,0 +1,180 @@
5.4 +#include "tap-manager-client.h"
5.5 +#include "ns3/log.h"
5.6 +#include <sys/socket.h>
5.7 +#include <sys/wait.h>
5.8 +#include <sys/stat.h>
5.9 +#include <linux/un.h>
5.10 +#include <errno.h>
5.11 +#include <string.h>
5.12 +#include <iomanip>
5.13 +#include <iostream>
5.14 +#include <list>
5.15 +
5.16 +
5.17 +NS_LOG_COMPONENT_DEFINE("TapManagerClient");
5.18 +
5.19 +#define TAP_MANAGER "ns3-tap-manager"
5.20 +
5.21 +namespace ns3 {
5.22 +
5.23 +static std::string
5.24 +EncodeAsString (struct sockaddr_un un, int len)
5.25 +{
5.26 + uint8_t *buffer = (uint8_t *)&un;
5.27 + std::ostringstream oss;
5.28 + oss.setf (std::ios::hex, std::ios::basefield);
5.29 + oss.fill('0');
5.30 + for (uint8_t i = 0; i < len; i++)
5.31 + {
5.32 + oss << ":" << std::setw (2) << (uint32_t)buffer[i];
5.33 + }
5.34 + return oss.str ();
5.35 +}
5.36 +
5.37 +bool
5.38 +TapManagerClient::Exists (std::string filename) const
5.39 +{
5.40 + struct stat st;
5.41 + int retval = ::stat (filename.c_str (), &st);
5.42 + return retval == 0;
5.43 +}
5.44 +
5.45 +std::string
5.46 +TapManagerClient::FindManager (void) const
5.47 +{
5.48 + std::list<std::string> locations;
5.49 + locations.push_back ("./src/devices/tap");
5.50 + locations.push_back ("./build/debug/src/devices/tap");
5.51 + locations.push_back ("./build/optimized/src/devices/tap");
5.52 + for (std::list<std::string>::const_iterator i = locations.begin (); i != locations.end (); ++i)
5.53 + {
5.54 + if (Exists (*i + "/" + TAP_MANAGER))
5.55 + {
5.56 + return *i + "/" + TAP_MANAGER;
5.57 + }
5.58 + }
5.59 + NS_FATAL_ERROR ("Could not find manager");
5.60 + return ""; // quiet compiler
5.61 +}
5.62 +
5.63 +int
5.64 +TapManagerClient::AllocateTap (Mac48Address host, Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway)
5.65 +{
5.66 + NS_LOG_FUNCTION (host << ad << mask << gateway);
5.67 + // create a socket to get information back from the tap manager.
5.68 + int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
5.69 + if (sock == -1)
5.70 + {
5.71 + NS_FATAL_ERROR ("Socket creation, errno=" << strerror (errno));
5.72 + }
5.73 +
5.74 + struct sockaddr_un un;
5.75 + memset (&un, 0, sizeof (un));
5.76 + un.sun_family = AF_UNIX;
5.77 + int status = bind (sock, (struct sockaddr*)&un, sizeof (sa_family_t)); // let the kernel allocate an endpoint for us.
5.78 + if (status == -1)
5.79 + {
5.80 + NS_FATAL_ERROR ("Could not bind: errno=" << strerror (errno));
5.81 + }
5.82 + socklen_t len = sizeof (un);
5.83 + status = getsockname (sock, (struct sockaddr*)&un, &len);
5.84 + if (status == -1)
5.85 + {
5.86 + NS_FATAL_ERROR ("Could not get socket address: errno=" << strerror (errno));
5.87 + }
5.88 + NS_LOG_DEBUG ("Allocated enpoint=" << EncodeAsString (un, len) << ", len=" << len);
5.89 +
5.90 + pid_t pid = ::fork ();
5.91 + if (pid == 0)
5.92 + {
5.93 + // child.
5.94 + NS_LOG_DEBUG ("Child");
5.95 +
5.96 + std::ostringstream oss;
5.97 + oss << "--path=" << EncodeAsString (un, len);
5.98 + std::string pathArg = oss.str ();
5.99 + oss.str ("");
5.100 + oss << "--mac-addr=" << host;
5.101 + std::string hostArg = oss.str ();
5.102 + oss.str ("");
5.103 + oss << "--ip-addr=" << ad;
5.104 + std::string ipArg = oss.str ();
5.105 + oss.str ("");
5.106 + oss << "--ip-gw=" << gateway;
5.107 + std::string ipGw = oss.str ();
5.108 + oss.str ("");
5.109 + oss << "--ip-netmask=" << mask;
5.110 + std::string ipMask = oss.str ();
5.111 + oss.str ("");
5.112 + status = ::execl (FindManager ().c_str (),
5.113 + TAP_MANAGER,
5.114 + pathArg.c_str (),
5.115 + hostArg.c_str (),
5.116 + ipArg.c_str (),
5.117 + ipGw.c_str (),
5.118 + ipMask.c_str (),
5.119 + (char *)NULL);
5.120 + if (status == -1)
5.121 + {
5.122 + NS_LOG_ERROR ("Cannot execl tap-manager, errno=" << ::strerror (errno));
5.123 + }
5.124 + ::_exit (-1);
5.125 + }
5.126 + else
5.127 + {
5.128 + // parent
5.129 + NS_LOG_DEBUG ("Parent");
5.130 + int st;
5.131 + pid_t waited = waitpid (pid, &st, 0);
5.132 + if (waited == -1)
5.133 + {
5.134 + NS_FATAL_ERROR ("Cannot wait for tap-manager, errno=" << strerror (errno));
5.135 + }
5.136 + NS_ASSERT (pid == waited);
5.137 + if (!WIFEXITED (st))
5.138 + {
5.139 + // tap manager did not complete successfully
5.140 + NS_FATAL_ERROR ("tap-manager did not exit correctly");
5.141 + }
5.142 + else if (WEXITSTATUS (st) != 0)
5.143 + {
5.144 + NS_FATAL_ERROR ("tap-manager did not complete successfully, err=" << WEXITSTATUS (st));
5.145 + }
5.146 + // the tap fd should be available on our unix socket now.
5.147 + size_t msg_size = sizeof(int);
5.148 + char control[CMSG_SPACE(msg_size)];
5.149 + struct cmsghdr *cmsg;
5.150 + uint8_t buffer;
5.151 + struct iovec iov;
5.152 + iov.iov_base = &buffer;
5.153 + iov.iov_len = 1;
5.154 + struct msghdr msg;
5.155 + msg.msg_name = 0;
5.156 + msg.msg_namelen = 0;
5.157 + msg.msg_iov = &iov;
5.158 + msg.msg_iovlen = 1;
5.159 + msg.msg_control = control;
5.160 + msg.msg_controllen = sizeof (control);
5.161 + msg.msg_flags = 0;
5.162 + ssize_t bytesRead = recvmsg (sock, &msg, 0);
5.163 + if (bytesRead != 1)
5.164 + {
5.165 + NS_FATAL_ERROR ("Did not get byte from tap-manager");
5.166 + }
5.167 + NS_LOG_ERROR ("read bytes=" << bytesRead);
5.168 + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
5.169 + {
5.170 + if (cmsg->cmsg_level == SOL_SOCKET &&
5.171 + cmsg->cmsg_type == SCM_RIGHTS)
5.172 + {
5.173 + int *fd = (int*)CMSG_DATA (cmsg);
5.174 + NS_LOG_ERROR ("got tap fd=" << *fd);
5.175 + return *fd;
5.176 + }
5.177 + }
5.178 + NS_FATAL_ERROR ("Did not get SCM_RIGHTS from tap-manager");
5.179 + }
5.180 + return -1;
5.181 +}
5.182 +
5.183 +} // namespace ns3
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/src/devices/emutap/tap-manager-client.h Mon Oct 27 13:01:28 2008 -0700
6.3 @@ -0,0 +1,21 @@
6.4 +#ifndef TAP_MANAGER_CLIENT_H
6.5 +#define TAP_MANAGER_CLIENT_H
6.6 +
6.7 +#include "ns3/mac48-address.h"
6.8 +#include "ns3/ipv4-address.h"
6.9 +#include <string>
6.10 +
6.11 +namespace ns3 {
6.12 +
6.13 +class TapManagerClient
6.14 +{
6.15 +public:
6.16 + int AllocateTap (Mac48Address host, Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway);
6.17 +private:
6.18 + std::string FindManager (void) const;
6.19 + bool Exists (std::string filename) const;
6.20 +};
6.21 +
6.22 +} // namespace ns3
6.23 +
6.24 +#endif /* TAP_MANAGER_CLIENT_H */
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/src/devices/emutap/tap-manager.cc Mon Oct 27 13:01:28 2008 -0700
7.3 @@ -0,0 +1,339 @@
7.4 +#include <fcntl.h>
7.5 +#include <sys/ioctl.h>
7.6 +#include <sys/types.h>
7.7 +#include <sys/socket.h>
7.8 +#include <linux/un.h>
7.9 +#include <linux/if.h>
7.10 +#include <linux/if_tun.h>
7.11 +#include <linux/route.h>
7.12 +#include <netinet/in.h>
7.13 +#include <stdint.h>
7.14 +#include <iostream>
7.15 +#include <sstream>
7.16 +#include <iomanip>
7.17 +#include <string.h>
7.18 +#include <errno.h>
7.19 +#include <stdlib.h>
7.20 +
7.21 +#define noENABLE_LOG
7.22 +
7.23 +#define EXIT_ERROR(x, err) \
7.24 + std::cout << __FILE__ << ":" << __LINE__ << ": Unrecoverable Error: " << x; \
7.25 + std::cout << " errno=" << strerror (errno) << std::endl; \
7.26 + exit (err)
7.27 +#ifdef ENABLE_LOG
7.28 +#define LOG(x) \
7.29 + std::cout << x << std::endl;
7.30 +#else
7.31 +#define LOG(x)
7.32 +#endif
7.33 +
7.34 +
7.35 +#define CHECK_ARG(el,var) \
7.36 + { \
7.37 + char start[] = "--" el "="; \
7.38 + if (strncmp (*argv, start, strlen (start)) == 0) \
7.39 + { \
7.40 + var = *argv + strlen (start); \
7.41 + LOG ("--" << el << "=" << var); \
7.42 + } \
7.43 + }
7.44 +
7.45 +#define ASCII_DOT (0x2e)
7.46 +#define ASCII_ZERO (0x30)
7.47 +#define ASCII_a (0x41)
7.48 +#define ASCII_z (0x5a)
7.49 +#define ASCII_A (0x61)
7.50 +#define ASCII_Z (0x7a)
7.51 +#define ASCII_COLON (0x3a)
7.52 +#define ASCII_ZERO (0x30)
7.53 +static char
7.54 +AsciiToLowCase (char c)
7.55 +{
7.56 + if (c >= ASCII_a && c <= ASCII_z) {
7.57 + return c;
7.58 + } else if (c >= ASCII_A && c <= ASCII_Z) {
7.59 + return c + (ASCII_a - ASCII_A);
7.60 + } else {
7.61 + return c;
7.62 + }
7.63 +}
7.64 +static uint32_t
7.65 +AsciiToIpv4 (const char *address)
7.66 +{
7.67 + uint32_t host = 0;
7.68 + while (true) {
7.69 + uint8_t byte = 0;
7.70 + while (*address != ASCII_DOT &&
7.71 + *address != 0) {
7.72 + byte *= 10;
7.73 + byte += *address - ASCII_ZERO;
7.74 + address++;
7.75 + }
7.76 + host <<= 8;
7.77 + host |= byte;
7.78 + if (*address == 0) {
7.79 + break;
7.80 + }
7.81 + address++;
7.82 + }
7.83 + return host;
7.84 +}
7.85 +
7.86 +static void
7.87 +AsciiToMac48 (const char *str, uint8_t addr[6])
7.88 +{
7.89 + int i = 0;
7.90 + while (*str != 0 && i < 6)
7.91 + {
7.92 + uint8_t byte = 0;
7.93 + while (*str != ASCII_COLON && *str != 0)
7.94 + {
7.95 + byte <<= 4;
7.96 + char low = AsciiToLowCase (*str);
7.97 + if (low >= ASCII_a)
7.98 + {
7.99 + byte |= low - ASCII_a + 10;
7.100 + }
7.101 + else
7.102 + {
7.103 + byte |= low - ASCII_ZERO;
7.104 + }
7.105 + str++;
7.106 + }
7.107 + addr[i] = byte;
7.108 + i++;
7.109 + if (*str == 0)
7.110 + {
7.111 + break;
7.112 + }
7.113 + str++;
7.114 + }
7.115 +}
7.116 +
7.117 +static void
7.118 +SetInetAddress (sockaddr *ad, uint32_t networkOrder)
7.119 +{
7.120 + struct sockaddr_in *sin = (struct sockaddr_in*)ad;
7.121 + sin->sin_family = AF_INET;
7.122 + sin->sin_port = 0; // unused
7.123 + sin->sin_addr.s_addr = htonl (networkOrder);
7.124 +}
7.125 +
7.126 +
7.127 +static int
7.128 +CreateTap (const char *mac_addr, const char *ip,
7.129 + const char *gw, const char *netmask)
7.130 +{
7.131 + // opening the tun device usually requires root privs
7.132 + int tap = open ("/dev/net/tun", O_RDWR);
7.133 + if (tap == -1)
7.134 + {
7.135 + EXIT_ERROR ("Could not open /dev/net/tun", 1);
7.136 + }
7.137 + // now, crate a tap device.
7.138 + struct ifreq ifr;
7.139 + // make sure that the tap device will not send us the tun_pi header.
7.140 + ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
7.141 + ifr.ifr_name[0] = 0; // allow the kernel to pick a device name.
7.142 + int status = ioctl (tap, TUNSETIFF, (void *) &ifr);
7.143 + if (status == -1)
7.144 + {
7.145 + EXIT_ERROR ("Could not allocate a tap device", 2);
7.146 + }
7.147 + std::string tapDeviceName = (char *)ifr.ifr_name;
7.148 + LOG ("Allocated TAP device=" << tapDeviceName);
7.149 +
7.150 + // set its hardware address to something we know will be unique within the simulation
7.151 + ifr.ifr_hwaddr.sa_family = 1; // this is ARPHRD_ETHER from if_arp.h
7.152 + AsciiToMac48 (mac_addr, (uint8_t*)ifr.ifr_hwaddr.sa_data);
7.153 + status = ioctl (tap, SIOCSIFHWADDR, &ifr);
7.154 + if (status == -1)
7.155 + {
7.156 + EXIT_ERROR ("Could not set hardware address=" << mac_addr << " for=" << (char *)ifr.ifr_name, 3);
7.157 + }
7.158 + LOG ("device=" << (char *)ifr.ifr_name << " addr=" << mac_addr);
7.159 +
7.160 +
7.161 + // The ip address must be set using an AF_INET socket.
7.162 + int fd = socket (AF_INET, SOCK_DGRAM, 0);
7.163 +
7.164 + // set interface up.
7.165 + status = ioctl (fd, SIOCGIFFLAGS, &ifr);
7.166 + if (status == -1)
7.167 + {
7.168 + EXIT_ERROR ("Could not get flags for interface=" << (char *)ifr.ifr_name, 4);
7.169 + }
7.170 + ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
7.171 + status = ioctl (fd, SIOCSIFFLAGS, &ifr);
7.172 + if (status == -1)
7.173 + {
7.174 + EXIT_ERROR ("Could not bring interface " << (char *)ifr.ifr_name << " up", 5);
7.175 + }
7.176 + LOG ("device=" << (char *)ifr.ifr_name << " is up");
7.177 +
7.178 +
7.179 + // set its ip address.
7.180 + SetInetAddress (&ifr.ifr_addr, AsciiToIpv4 (ip));
7.181 + status = ioctl (fd, SIOCSIFADDR, &ifr);
7.182 + if (status == -1)
7.183 + {
7.184 + EXIT_ERROR ("Could not set ip address=" << ip << " for=" << (char *)ifr.ifr_name, 6);
7.185 + }
7.186 + LOG ("device=" << (char *)ifr.ifr_name << " addr=" << ip);
7.187 +
7.188 + // set its ip mask to be /32
7.189 + SetInetAddress (&ifr.ifr_netmask, 0xffffffff);
7.190 + status = ioctl (fd, SIOCSIFNETMASK, &ifr);
7.191 + if (status == -1)
7.192 + {
7.193 + EXIT_ERROR ("Could not set ip mask=" << netmask << " for=" << (char *)ifr.ifr_name, 7);
7.194 + }
7.195 + LOG ("device=" << (char *)ifr.ifr_name << " mask=" << netmask);
7.196 +
7.197 + // add routing entry for gateway.
7.198 + struct rtentry rt;
7.199 + SetInetAddress (&rt.rt_dst, AsciiToIpv4 (gw));
7.200 + SetInetAddress (&rt.rt_genmask, 0xffffffff);
7.201 + rt.rt_flags = RTF_UP;
7.202 + rt.rt_metric = 2;
7.203 + rt.rt_dev = (char*)tapDeviceName.c_str ();
7.204 + status = ioctl (fd, SIOCADDRT, &rt);
7.205 + if (status == -1)
7.206 + {
7.207 + EXIT_ERROR ("Could not add routing table entry", 8);
7.208 + }
7.209 + LOG ("added routing table entry for gw.");
7.210 +
7.211 + // add routing entry for subnet through gateway.
7.212 + uint32_t network = AsciiToIpv4 (ip) & AsciiToIpv4 (netmask);
7.213 + SetInetAddress (&rt.rt_dst, network);
7.214 + SetInetAddress (&rt.rt_gateway, AsciiToIpv4 (gw));
7.215 + SetInetAddress (&rt.rt_genmask, AsciiToIpv4 (netmask));
7.216 + rt.rt_flags = RTF_UP | RTF_GATEWAY;
7.217 + rt.rt_metric = 2;
7.218 + rt.rt_dev = (char*)tapDeviceName.c_str ();
7.219 + status = ioctl (fd, SIOCADDRT, &rt);
7.220 + if (status == -1)
7.221 + {
7.222 + EXIT_ERROR ("Could not add routing table entry", 9);
7.223 + }
7.224 + LOG ("added routing table entry for subnet.");
7.225 +
7.226 + return tap;
7.227 +}
7.228 +
7.229 +static struct sockaddr_un
7.230 +DecodeFromString (const char *path, socklen_t *len)
7.231 +{
7.232 + sockaddr_un un;
7.233 + uint8_t *buffer = (uint8_t *)&un;
7.234 + std::istringstream iss;
7.235 + iss.str (path);
7.236 + uint8_t n = 0;
7.237 + while (!iss.bad () && !iss.eof () && !iss.fail ())
7.238 + {
7.239 + char c;
7.240 + iss.read (&c, 1);
7.241 + uint32_t tmp;
7.242 + iss >> std::hex >> tmp;
7.243 + //LOG (std::hex << tmp);
7.244 + buffer[n] = tmp;
7.245 + n++;
7.246 + }
7.247 + *len = n;
7.248 + return un;
7.249 +}
7.250 +
7.251 +static void
7.252 +SendFd (const char *path, int fd)
7.253 +{
7.254 + // send back configuration to caller.
7.255 + int sock = socket (PF_UNIX, SOCK_DGRAM, 0);
7.256 + if (sock == -1)
7.257 + {
7.258 + EXIT_ERROR ("Socket creation", 10);
7.259 + }
7.260 + LOG ("Socket Created");
7.261 +
7.262 + socklen_t local_len;
7.263 + struct sockaddr_un local = DecodeFromString (path, &local_len);
7.264 + LOG ("len=" << local_len);
7.265 + int status = connect (sock, (struct sockaddr*)&local, local_len);
7.266 + if (status == -1)
7.267 + {
7.268 + EXIT_ERROR ("Could not connect to caller", 11);
7.269 + }
7.270 + LOG ("Socket Connected");
7.271 +
7.272 + // we send a single byte whose content is meaningless.
7.273 + // we also return as ancillary data the tap file descriptor
7.274 + struct cmsghdr *cmsg;
7.275 + size_t msg_size = sizeof(int);
7.276 + char control[CMSG_SPACE(msg_size)];
7.277 + struct iovec iov;
7.278 + struct msghdr msg;
7.279 + char buffer = 0;
7.280 + iov.iov_base = &buffer;
7.281 + iov.iov_len = 1;
7.282 + msg.msg_name = 0;
7.283 + msg.msg_namelen = 0;
7.284 + msg.msg_iov = &iov;
7.285 + msg.msg_iovlen = 1;
7.286 + msg.msg_control = control;
7.287 + msg.msg_controllen = sizeof (control);
7.288 + msg.msg_flags = 0;
7.289 +
7.290 + cmsg = CMSG_FIRSTHDR(&msg);
7.291 + cmsg->cmsg_level = SOL_SOCKET;
7.292 + cmsg->cmsg_type = SCM_RIGHTS;
7.293 + cmsg->cmsg_len = CMSG_LEN(msg_size);
7.294 + msg.msg_controllen = cmsg->cmsg_len;
7.295 +
7.296 + int *fdptr = (int*) (CMSG_DATA(cmsg));
7.297 + *fdptr = fd;
7.298 +
7.299 + ssize_t len = sendmsg(sock, &msg, 0);
7.300 + if (len == -1)
7.301 + {
7.302 + EXIT_ERROR ("Could not send SCM_RIGHTS", 12);
7.303 + }
7.304 + LOG ("Sent SCM_RIGHTS");
7.305 +}
7.306 +
7.307 +
7.308 +
7.309 +
7.310 +int main (int argc, char *argv[])
7.311 +{
7.312 + char *path = 0;
7.313 + char *mac_addr = 0;
7.314 + char *ip_addr = 0;
7.315 + char *ip_gw = 0;
7.316 + char *ip_netmask = 0;
7.317 + char *stop = 0;
7.318 + argv++;
7.319 + argc--;
7.320 + while (argc > 0)
7.321 + {
7.322 + CHECK_ARG("path", path);
7.323 + CHECK_ARG("mac-addr", mac_addr);
7.324 + CHECK_ARG("ip-addr", ip_addr);
7.325 + CHECK_ARG("ip-gw", ip_gw);
7.326 + CHECK_ARG("ip-netmask", ip_netmask);
7.327 + CHECK_ARG("stop", stop);
7.328 + argv++;
7.329 + argc--;
7.330 + }
7.331 +
7.332 + int tap = CreateTap (mac_addr, ip_addr, ip_gw, ip_netmask);
7.333 +
7.334 + if (stop)
7.335 + {
7.336 + while (1) {}
7.337 + }
7.338 +
7.339 + SendFd (path, tap);
7.340 +
7.341 + return 0;
7.342 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/src/devices/emutap/tap-net-device.cc Mon Oct 27 13:01:28 2008 -0700
8.3 @@ -0,0 +1,323 @@
8.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
8.5 +/*
8.6 + * Copyright (c) 2008 INRIA
8.7 + *
8.8 + * This program is free software; you can redistribute it and/or modify
8.9 + * it under the terms of the GNU General Public License version 2 as
8.10 + * published by the Free Software Foundation;
8.11 + *
8.12 + * This program is distributed in the hope that it will be useful,
8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.15 + * GNU General Public License for more details.
8.16 + *
8.17 + * You should have received a copy of the GNU General Public License
8.18 + * along with this program; if not, write to the Free Software
8.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8.20 + *
8.21 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
8.22 + */
8.23 +#include "tap-net-device.h"
8.24 +#include "tap-manager-client.h"
8.25 +#include "ns3/node.h"
8.26 +#include "ns3/channel.h"
8.27 +#include "ns3/packet.h"
8.28 +#include "ns3/log.h"
8.29 +#include "ns3/system-thread.h"
8.30 +#include "ns3/realtime-simulator-impl.h"
8.31 +#include "ns3/make-event.h"
8.32 +#include "ns3/simulator.h"
8.33 +#include "ns3/ethernet-header.h"
8.34 +#include "ns3/trace-source-accessor.h"
8.35 +#include "host-tap-net-device.h"
8.36 +#include "tap-channel.h"
8.37 +#include <errno.h>
8.38 +#include <stdlib.h>
8.39 +
8.40 +NS_LOG_COMPONENT_DEFINE ("TapNetDevice");
8.41 +
8.42 +namespace ns3 {
8.43 +
8.44 +TypeId
8.45 +TapNetDevice::GetTypeId (void)
8.46 +{
8.47 + static TypeId tid = TypeId ("ns3::TapNetDevice")
8.48 + .SetParent<NetDevice> ()
8.49 + .AddConstructor<TapNetDevice> ()
8.50 + .AddTraceSource ("Rx", "A packet has been received",
8.51 + MakeTraceSourceAccessor (&TapNetDevice::m_rxTrace))
8.52 + .AddTraceSource ("Tx", "A packet has been sent",
8.53 + MakeTraceSourceAccessor (&TapNetDevice::m_txTrace))
8.54 + .AddTraceSource ("Drop", "A packet has been dropped",
8.55 + MakeTraceSourceAccessor (&TapNetDevice::m_dropTrace))
8.56 + ;
8.57 + return tid;
8.58 +}
8.59 +
8.60 +TapNetDevice::TapNetDevice ()
8.61 + : m_node (0),
8.62 + m_mtu (0xffff),
8.63 + m_name (""),
8.64 + m_ifIndex (0),
8.65 + m_tap (-1)
8.66 +{
8.67 + NS_LOG_FUNCTION (this);
8.68 +}
8.69 +
8.70 +void
8.71 +TapNetDevice::SetChannel (Ptr<TapChannel> channel)
8.72 +{
8.73 + m_channel = channel;
8.74 + m_channel->SetDevice (this);
8.75 +}
8.76 +
8.77 +void
8.78 +TapNetDevice::SetupHost (Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway)
8.79 +{
8.80 + NS_LOG_FUNCTION (this << ad << mask << gateway);
8.81 + NS_ASSERT (m_tap == -1);
8.82 +
8.83 + Mac48Address hostMacAddress = m_channel->GetHostDevice ()->GetMacAddress ();
8.84 +
8.85 + TapManagerClient manager;
8.86 + m_tap = manager.AllocateTap (hostMacAddress, ad, mask, gateway);
8.87 +
8.88 + m_thread = Create<SystemThread> (MakeCallback (&TapNetDevice::ReadThread, this));
8.89 + m_thread->Start ();
8.90 +}
8.91 +
8.92 +
8.93 +void
8.94 +TapNetDevice::ReadThread (void)
8.95 +{
8.96 + NS_LOG_FUNCTION (this);
8.97 +
8.98 + while (1)
8.99 + {
8.100 + uint8_t *buffer = (uint8_t *)malloc (0xffff);
8.101 + ssize_t bytesRead = read (m_tap, buffer, 0xffff);
8.102 + if (bytesRead == -1)
8.103 + {
8.104 + if (errno == EBADF || errno == EINTR)
8.105 + {
8.106 + // the device was closed from under us by ::DoDispose
8.107 + return;
8.108 + }
8.109 + NS_FATAL_ERROR ("Error reading from tap device: errno=" << strerror (errno));
8.110 + }
8.111 + // Note: we purposedly don't use a smart pointer to manage this packet
8.112 + // because the want to hand over ownership of this packet to the ForwardUp
8.113 + // method.
8.114 + DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ())->
8.115 + ScheduleRealtimeNow (MakeEvent (&TapNetDevice::ForwardUp, this, buffer, (uint32_t)bytesRead));
8.116 + }
8.117 +}
8.118 +
8.119 +void
8.120 +TapNetDevice::ForwardUp (uint8_t *buffer, uint32_t size)
8.121 +{
8.122 + NS_LOG_FUNCTION (this << buffer << size);
8.123 +
8.124 + // swallow packet reference in smart pointer.
8.125 + Ptr<Packet> packet = Create<Packet> (buffer, size);
8.126 + free (buffer);
8.127 + Ptr<Packet> copy = packet->Copy ();
8.128 +
8.129 + EthernetHeader header = EthernetHeader (false);
8.130 + packet->RemoveHeader (header);
8.131 +
8.132 + uint16_t protocol = header.GetLengthType ();
8.133 + Mac48Address to = header.GetDestination ();
8.134 + Mac48Address from = header.GetSource ();
8.135 +
8.136 + NetDevice::PacketType packetType;
8.137 + if (to == m_address)
8.138 + {
8.139 + packetType = NetDevice::PACKET_HOST;
8.140 + }
8.141 + else if (to.IsBroadcast ())
8.142 + {
8.143 + packetType = NetDevice::PACKET_HOST;
8.144 + }
8.145 + else if (to.IsMulticast ())
8.146 + {
8.147 + packetType = NetDevice::PACKET_MULTICAST;
8.148 + }
8.149 + else
8.150 + {
8.151 + packetType = NetDevice::PACKET_OTHERHOST;
8.152 + }
8.153 + m_rxTrace (copy, from, to);
8.154 + if (packetType != NetDevice::PACKET_OTHERHOST)
8.155 + {
8.156 + m_rxCallback (this, packet, protocol, from);
8.157 + }
8.158 + if (!m_promiscCallback.IsNull ())
8.159 + {
8.160 + m_promiscCallback (this, packet, protocol, from, to, packetType);
8.161 + }
8.162 +}
8.163 +
8.164 +void
8.165 +TapNetDevice::SetAddress (Mac48Address address)
8.166 +{
8.167 + m_address = address;
8.168 +}
8.169 +
8.170 +void
8.171 +TapNetDevice::SetName(const std::string name)
8.172 +{
8.173 + m_name = name;
8.174 +}
8.175 +std::string
8.176 +TapNetDevice::GetName(void) const
8.177 +{
8.178 + return m_name;
8.179 +}
8.180 +void
8.181 +TapNetDevice::SetIfIndex(const uint32_t index)
8.182 +{
8.183 + m_ifIndex = index;
8.184 +}
8.185 +uint32_t
8.186 +TapNetDevice::GetIfIndex(void) const
8.187 +{
8.188 + return m_ifIndex;
8.189 +}
8.190 +Ptr<Channel>
8.191 +TapNetDevice::GetChannel (void) const
8.192 +{
8.193 + return m_channel;
8.194 +}
8.195 +Address
8.196 +TapNetDevice::GetAddress (void) const
8.197 +{
8.198 + return m_address;
8.199 +}
8.200 +bool
8.201 +TapNetDevice::SetMtu (const uint16_t mtu)
8.202 +{
8.203 + m_mtu = mtu;
8.204 + return true;
8.205 +}
8.206 +uint16_t
8.207 +TapNetDevice::GetMtu (void) const
8.208 +{
8.209 + return m_mtu;
8.210 +}
8.211 +bool
8.212 +TapNetDevice::IsLinkUp (void) const
8.213 +{
8.214 + return true;
8.215 +}
8.216 +void
8.217 +TapNetDevice::SetLinkChangeCallback (Callback<void> callback)
8.218 +{}
8.219 +bool
8.220 +TapNetDevice::IsBroadcast (void) const
8.221 +{
8.222 + return true;
8.223 +}
8.224 +Address
8.225 +TapNetDevice::GetBroadcast (void) const
8.226 +{
8.227 + return Mac48Address ("ff:ff:ff:ff:ff:ff");
8.228 +}
8.229 +bool
8.230 +TapNetDevice::IsMulticast (void) const
8.231 +{
8.232 + return true;
8.233 +}
8.234 +Address
8.235 +TapNetDevice::GetMulticast (void) const
8.236 +{
8.237 + return Mac48Address::GetMulticastPrefix ();
8.238 +}
8.239 +Address
8.240 +TapNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
8.241 +{
8.242 + return Mac48Address::GetMulticast (multicastGroup);
8.243 +}
8.244 +bool
8.245 +TapNetDevice::IsPointToPoint (void) const
8.246 +{
8.247 + return false;
8.248 +}
8.249 +bool
8.250 +TapNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
8.251 +{
8.252 + NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
8.253 + return SendFrom (packet, m_address, dest, protocolNumber);
8.254 +}
8.255 +bool
8.256 +TapNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
8.257 +{
8.258 + NS_LOG_FUNCTION (this << packet << source << dest << protocolNumber);
8.259 + Mac48Address to = Mac48Address::ConvertFrom (dest);
8.260 + Mac48Address from = Mac48Address::ConvertFrom (source);
8.261 +
8.262 + EthernetHeader header = EthernetHeader (false);
8.263 + header.SetSource (from);
8.264 + header.SetDestination (to);
8.265 + header.SetLengthType (protocolNumber);
8.266 + packet->AddHeader (header);
8.267 +
8.268 + ssize_t written = write (m_tap, packet->PeekData (), packet->GetSize ());
8.269 + if (written == -1 || written != (ssize_t)packet->GetSize ())
8.270 + {
8.271 + m_dropTrace (packet, from, to);
8.272 + return false;
8.273 + }
8.274 +
8.275 + m_txTrace (packet, from, to);
8.276 +
8.277 + return true;
8.278 +}
8.279 +
8.280 +Ptr<Node>
8.281 +TapNetDevice::GetNode (void) const
8.282 +{
8.283 + return m_node;
8.284 +}
8.285 +void
8.286 +TapNetDevice::SetNode (Ptr<Node> node)
8.287 +{
8.288 + m_node = node;
8.289 +}
8.290 +bool
8.291 +TapNetDevice::NeedsArp (void) const
8.292 +{
8.293 + return true;
8.294 +}
8.295 +void
8.296 +TapNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
8.297 +{
8.298 + m_rxCallback = cb;
8.299 +}
8.300 +
8.301 +void
8.302 +TapNetDevice::DoDispose (void)
8.303 +{
8.304 + NS_LOG_FUNCTION (this);
8.305 + close (m_tap);
8.306 + m_thread->Join ();
8.307 + m_thread = 0;
8.308 + m_node = 0;
8.309 + m_channel = 0;
8.310 + NetDevice::DoDispose ();
8.311 +}
8.312 +
8.313 +
8.314 +void
8.315 +TapNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
8.316 +{
8.317 + m_promiscCallback = cb;
8.318 +}
8.319 +
8.320 +bool
8.321 +TapNetDevice::SupportsSendFrom (void) const
8.322 +{
8.323 + return true;
8.324 +}
8.325 +
8.326 +} // namespace ns3
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/src/devices/emutap/tap-net-device.h Mon Oct 27 13:01:28 2008 -0700
9.3 @@ -0,0 +1,103 @@
9.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
9.5 +/*
9.6 + * Copyright (c) 2008 INRIA
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 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
9.22 + */
9.23 +#ifndef TAP_NET_DEVICE_H
9.24 +#define TAP_NET_DEVICE_H
9.25 +
9.26 +#include "ns3/net-device.h"
9.27 +#include "ns3/mac48-address.h"
9.28 +#include "ns3/traced-callback.h"
9.29 +#include <stdint.h>
9.30 +#include <string>
9.31 +
9.32 +namespace ns3 {
9.33 +
9.34 +class Node;
9.35 +class SystemThread;
9.36 +class TapChannel;
9.37 +
9.38 +/**
9.39 + * \ingroup netdevice
9.40 + *
9.41 + * \brief a NetDevice to get packets to and from a host tap device.
9.42 + */
9.43 +class TapNetDevice : public NetDevice
9.44 +{
9.45 +public:
9.46 + static TypeId GetTypeId (void);
9.47 + TapNetDevice ();
9.48 +
9.49 + void SetAddress (Mac48Address address);
9.50 +
9.51 + void SetChannel (Ptr<TapChannel> channel);
9.52 +
9.53 + void SetupHost (Ipv4Address ad, Ipv4Mask mask, Ipv4Address gateway);
9.54 +
9.55 + // inherited from NetDevice base class.
9.56 + virtual void SetName(const std::string name);
9.57 + virtual std::string GetName(void) const;
9.58 + virtual void SetIfIndex(const uint32_t index);
9.59 + virtual uint32_t GetIfIndex(void) const;
9.60 + virtual Ptr<Channel> GetChannel (void) const;
9.61 + virtual Address GetAddress (void) const;
9.62 + virtual bool SetMtu (const uint16_t mtu);
9.63 + virtual uint16_t GetMtu (void) const;
9.64 + virtual bool IsLinkUp (void) const;
9.65 + virtual void SetLinkChangeCallback (Callback<void> callback);
9.66 + virtual bool IsBroadcast (void) const;
9.67 + virtual Address GetBroadcast (void) const;
9.68 + virtual bool IsMulticast (void) const;
9.69 + virtual Address GetMulticast (void) const;
9.70 + virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
9.71 + virtual bool IsPointToPoint (void) const;
9.72 + virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
9.73 + virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
9.74 + virtual Ptr<Node> GetNode (void) const;
9.75 + virtual void SetNode (Ptr<Node> node);
9.76 + virtual bool NeedsArp (void) const;
9.77 + virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
9.78 + virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
9.79 + virtual bool SupportsSendFrom (void) const;
9.80 +
9.81 +protected:
9.82 + virtual void DoDispose (void);
9.83 +private:
9.84 + void Receive (Ptr<Packet> packet, uint16_t protocol,
9.85 + Mac48Address to, Mac48Address from);
9.86 + void ForwardUp (uint8_t *buffer, uint32_t size);
9.87 + void ReadThread (void);
9.88 +
9.89 + NetDevice::ReceiveCallback m_rxCallback;
9.90 + NetDevice::PromiscReceiveCallback m_promiscCallback;
9.91 + Ptr<Node> m_node;
9.92 + uint16_t m_mtu;
9.93 + std::string m_name;
9.94 + uint32_t m_ifIndex;
9.95 + Mac48Address m_address;
9.96 + int m_tap;
9.97 + Ptr<SystemThread> m_thread;
9.98 + TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_rxTrace;
9.99 + TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_txTrace;
9.100 + TracedCallback<Ptr<const Packet>,Mac48Address,Mac48Address> m_dropTrace;
9.101 + Ptr<TapChannel> m_channel;
9.102 +};
9.103 +
9.104 +} // namespace ns3
9.105 +
9.106 +#endif /* TAP_NET_DEVICE_H */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/src/devices/emutap/wscript Mon Oct 27 13:01:28 2008 -0700
10.3 @@ -0,0 +1,26 @@
10.4 +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
10.5 +
10.6 +
10.7 +def build(bld):
10.8 + obj = bld.create_suid_program('ns3-tap-manager')
10.9 + obj.source = [
10.10 + 'tap-manager.cc',
10.11 + ]
10.12 +
10.13 + module = bld.create_ns3_module('emutap', ['node'])
10.14 + module.uselib = 'CAP'
10.15 + module.source = [
10.16 + 'tap-net-device.cc',
10.17 + 'tap-manager-client.cc',
10.18 + 'tap-channel.cc',
10.19 + 'host-tap-net-device.cc',
10.20 + ]
10.21 + headers = bld.create_obj('ns3header')
10.22 + headers.module = 'emutap'
10.23 + headers.source = [
10.24 + 'tap-net-device.h',
10.25 + 'host-tap-net-device.h',
10.26 + 'tap-channel.h',
10.27 + ]
10.28 +
10.29 +
11.1 --- a/src/wscript Mon Oct 27 16:40:03 2008 +0100
11.2 +++ b/src/wscript Mon Oct 27 13:01:28 2008 -0700
11.3 @@ -19,6 +19,8 @@
11.4 'internet-stack',
11.5 'devices/point-to-point',
11.6 'devices/csma',
11.7 + 'devices/bridge',
11.8 + 'devices/emutap',
11.9 'applications/onoff',
11.10 'applications/packet-sink',
11.11 'applications/udp-echo',
11.12 @@ -27,7 +29,6 @@
11.13 'mobility',
11.14 'devices/wifi',
11.15 'helper',
11.16 - 'devices/bridge',
11.17 'contrib/stats',
11.18 )
11.19
12.1 --- a/wscript Mon Oct 27 16:40:03 2008 +0100
12.2 +++ b/wscript Mon Oct 27 13:01:28 2008 -0700
12.3 @@ -12,6 +12,7 @@
12.4 import Params
12.5 import Object
12.6 import ccroot
12.7 +import Task
12.8
12.9 Params.g_autoconfig = 1
12.10
12.11 @@ -166,6 +167,10 @@
12.12 help=('For regression testing, only run/generate the indicated regression tests, '
12.13 'specified as a comma separated list of test names'),
12.14 dest='regression_tests', type="string")
12.15 + opt.add_option('--disable-sudo',
12.16 + help=('Do not attempt to use sudo to setup suid bits on ns3 executables.'),
12.17 + dest='disable_sudo', action='store_true',
12.18 + default=False)
12.19
12.20 # options provided in a script in a subdirectory named "src"
12.21 opt.sub_options('src')
12.22 @@ -275,6 +280,9 @@
12.23 # we cannot run regression tests without diff
12.24 conf.find_program('diff', var='DIFF')
12.25
12.26 + # for suid bits
12.27 + conf.find_program('sudo', var='SUDO')
12.28 +
12.29 # we cannot pull regression traces without mercurial
12.30 conf.find_program('hg', var='MERCURIAL')
12.31
12.32 @@ -288,6 +296,41 @@
12.33 print "%-30s: %s" % (caption, status)
12.34
12.35
12.36 +class SuidBuildTask(Task.TaskBase):
12.37 + """task that makes a binary Suid
12.38 + """
12.39 + def __init__(self, bld, program):
12.40 + self.m_display = 'build-suid'
12.41 + self.prio = 1000 # build after the rest of ns-3
12.42 + self.__program = program
12.43 + self.__env = bld.env ()
12.44 + super(SuidBuildTask, self).__init__()
12.45 +
12.46 + def run(self):
12.47 + try:
12.48 + program_obj = _find_program(self.__program.target, self.__env)
12.49 + except ValueError, ex:
12.50 + Params.fatal(str(ex))
12.51 +
12.52 + try:
12.53 + program_node = program_obj.path.find_build(ccroot.get_target_name(program_obj))
12.54 + except AttributeError:
12.55 + Params.fatal("%s does not appear to be a program" % (program_name,))
12.56 +
12.57 + filename = program_node.abspath(self.__env)
12.58 + os.system ('sudo chown root ' + filename)
12.59 + os.system ('sudo chmod u+s ' + filename)
12.60 +
12.61 +def create_suid_program(bld, name):
12.62 + program = bld.create_obj('cpp', 'program')
12.63 + program.is_ns3_program = True
12.64 + program.module_deps = list()
12.65 + program.name = name
12.66 + program.target = name
12.67 + if bld.env ()['SUDO'] and not Params.g_options.disable_sudo:
12.68 + SuidBuildTask (bld, program)
12.69 + return program
12.70 +
12.71 def create_ns3_program(bld, name, dependencies=('simulator',)):
12.72 program = bld.create_obj('cpp', 'program')
12.73 program.is_ns3_program = True
12.74 @@ -340,6 +383,7 @@
12.75
12.76 Params.g_cwd_launch = Params.g_build.m_curdirnode.abspath()
12.77 bld.create_ns3_program = types.MethodType(create_ns3_program, bld)
12.78 + bld.create_suid_program = types.MethodType(create_suid_program, bld)
12.79 variant_name = bld.env_of_name('default')['NS3_ACTIVE_VARIANT']
12.80 variant_env = bld.env_of_name(variant_name)
12.81 bld.m_allenvs['default'] = variant_env # switch to the active variant