NetdeviceController.cc
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
18 #include "NetdeviceController.hh"
19 //#include "NetdeviceController.ih"
20 
21 // Custom includes
22 #include <sys/socket.h>
23 #include <linux/sockios.h>
24 #include <sys/ioctl.h>
25 #include <net/if.h>
26 #include <linux/if_vlan.h>
27 #include <linux/net_tstamp.h>
28 #include <boost/weak_ptr.hpp>
29 #include <boost/filesystem/fstream.hpp>
30 #include <senf/Utils/Exception.hh>
31 #include <senf/Utils/String.hh>
33 
34 #define prefix_
35 //-/////////////////////////////////////////////////////////////////////////////////////////////////
36 
37 #define doIoctl(ifr, request, errorMsg) \
38  if ( ::ioctl( sockfd_->fd, request, &ifr ) < 0 ) \
39  SENF_THROW_SYSTEM_EXCEPTION("NetdeviceController: " errorMsg)
40 
41 
42 prefix_ senf::NetdeviceController::NetdeviceController(std::string const & interface_name)
43  : sockfd_ (sockfd())
44 {
45  reset(interface_name);
46 }
47 
49  : sockfd_ (sockfd())
50 {
51  ifindex_ = interface_index;
52 }
53 
54 prefix_ void senf::NetdeviceController::reset(std::string const & interface_name)
55 {
56  struct ifreq ifr;
57  ::memset( &ifr, 0, sizeof(ifr));
58  interface_name.copy( ifr.ifr_name, IFNAMSIZ);
59  doIoctl(ifr, SIOCGIFINDEX, "Could not discover the index of interface \"" + interface_name + "\"");
60  ifindex_ = ifr.ifr_ifindex;
61 }
62 
64  const
65 {
66  try {
67  struct ifreq ifr;
68  ifrName( ifr);
69  return std::string( ifr.ifr_name);
70  }
71  catch(...) {
72  return "(interface not known)";
73  }
74 }
75 
76 prefix_ void senf::NetdeviceController::interfaceName(std::string const & newname)
77 {
78  if (sizeof(newname) <= IFNAMSIZ) {
79  struct ifreq ifr;
80  ifrName(ifr);
81  newname.copy(ifr.ifr_newname, IFNAMSIZ);
82  doIoctl(ifr, SIOCSIFNAME, "Could not change the interface name. Is the interface really down?");
83  }
84  return;
85 }
86 
88  const
89 {
90  struct ifreq ifr;
91  ifrName( ifr);
92  doIoctl( ifr, SIOCGIFHWADDR, "Could not discover hardwareAddress");
93  return MACAddress::from_data( ifr.ifr_hwaddr.sa_data);
94 }
95 
97  struct ifreq ifr;
98  ifrName( ifr);
99  ifr.ifr_hwaddr.sa_family = 1; // TODO: lookup named constant; PF_LOCAL ???
100  std::copy(newAddress.begin(), newAddress.end(), ifr.ifr_hwaddr.sa_data);
101  doIoctl(ifr, SIOCSIFHWADDR, "Could not change the interface MAC address. Is the interface really down?");
102 }
103 
105  const
106 {
107  struct ifreq ifr;
108  ifrName( ifr);
109  doIoctl( ifr, SIOCGIFMTU, "Could not discover mtu");
110  return ifr.ifr_mtu;
111 }
112 
114 {
115  struct ifreq ifr;
116  ifrName( ifr);
117  ifr.ifr_mtu = new_mtu;
118  doIoctl( ifr, SIOCSIFMTU, "Could not set mtu");
119 }
120 
122  const
123 {
124  struct ifreq ifr;
125  ifrName( ifr);
126  doIoctl( ifr, SIOCGIFTXQLEN, "Could not discover txqueuelen");
127  return ifr.ifr_qlen;
128 }
129 
131 {
132  struct ifreq ifr;
133  ifrName( ifr);
134  ifr.ifr_qlen = new_txqueuelen;
135  doIoctl( ifr, SIOCSIFTXQLEN, "Could not set txqueuelen");
136 }
137 
138 
140  const
141 {
142  struct ifreq ifr;
143  ifrName( ifr);
144  doIoctl( ifr, SIOCGIFFLAGS, "Could not discover promisc mode");
145  return ifr.ifr_flags & IFF_PROMISC;
146 }
147 
149 {
150  struct ifreq ifr;
151  ifrName( ifr);
152  doIoctl( ifr, SIOCGIFFLAGS, "Could not set promisc mode");
153  if (mode)
154  ifr.ifr_flags |= IFF_PROMISC;
155  else
156  ifr.ifr_flags &= ~IFF_PROMISC;
157  doIoctl( ifr, SIOCSIFFLAGS, "Could not set promisc mode");
158 }
159 
161  const
162 {
163  struct ifreq ifr;
164  ifrName(ifr);
165  doIoctl(ifr, SIOCGIFFLAGS, "Could not discover interface status");
166  return ifr.ifr_flags & IFF_UP;
167 }
168 
170 {
171  struct ifreq ifr;
172  ifrName(ifr);
173  doIoctl(ifr, SIOCGIFFLAGS, "Could not set interface status");
174  ifr.ifr_flags |= IFF_UP;
175  doIoctl(ifr, SIOCSIFFLAGS, "Could not set interface status");
176 }
177 
179 {
180  struct ifreq ifr;
181  ifrName(ifr);
182  doIoctl(ifr, SIOCGIFFLAGS, "Could not set interface status");
183  ifr.ifr_flags &= ~IFF_UP;
184  doIoctl(ifr, SIOCSIFFLAGS, "Could not set interface status");
185 }
186 
187 prefix_ void senf::NetdeviceController::addVLAN(std::uint16_t vlanId)
188 {
189  vlan_ioctl_args vlan_request;
190  memset(&vlan_request, 0, sizeof(vlan_request));
191  vlan_request.cmd = ADD_VLAN_CMD;
192  vlan_request.u.VID = vlanId;
193  strncpy(vlan_request.device1, interfaceName().c_str(), sizeof(vlan_request.device1)-1);
194  doIoctl (vlan_request, SIOCSIFVLAN, "failed to add VLanId " + senf::str(vlanId) + " to " + interfaceName());
195 }
196 
197 prefix_ void senf::NetdeviceController::delVLAN(std::uint16_t vlanId)
198 {
199  vlan_ioctl_args vlan_request;
200  memset(&vlan_request, 0, sizeof(vlan_request));
201  vlan_request.cmd = DEL_VLAN_CMD;
202  strncpy(vlan_request.device1, (interfaceName() + "." + senf::str(vlanId)).c_str(), sizeof(vlan_request.device1)-1);
203  doIoctl (vlan_request, SIOCSIFVLAN, "failed to delete VLanId " + senf::str(vlanId) + " from " + interfaceName());
204 }
205 
206 prefix_ void senf::NetdeviceController::timestamping(int txType, int rxFilter)
207 {
208  struct hwtstamp_config hwconf = { 0, txType, rxFilter};
209  struct ifreq ifr;
210  ifrName( ifr);
211  ifr.ifr_data = (char*) &hwconf;
212  doIoctl( ifr, SIOCSHWTSTAMP, "Failed to set hw timestamp config");
213 }
214 
216  const
217 {
218  return ifindex_;
219 }
220 
222  const
223 {
224  ::memset( &ifr, 0, sizeof(ifr));
225  ifr.ifr_ifindex = ifindex_;
226  if ( ::ioctl( sockfd_->fd, SIOCGIFNAME, &ifr ) < 0 )
227  SENF_THROW_SYSTEM_EXCEPTION("NetdeviceController")
228  << " could not discover the name of the interface with index " << ifindex_ << ".";
229 }
230 
231 #undef doIoctl
232 
233 
234 //-/////////////////////////////////////////////////////////////////////////////////////////////////
235 // senf::NetdeviceController::SockFd
236 
238  : fd (::socket(PF_INET, SOCK_DGRAM, 0))
239 {
240  if ( fd < 0)
241  SENF_THROW_SYSTEM_EXCEPTION("Could not open socket for NetdeviceController.");
242 }
243 
245 {
246  ::close(fd);
247 }
248 
250 {
251  static boost::weak_ptr<SockFd> sockfd;
252  SockFd::ptr p (sockfd.lock());
253  if (!p)
254  sockfd = p = SockFd::ptr(new SockFd());
255  return p;
256 }
257 
258 
259 //-/////////////////////////////////////////////////////////////////////////////////////////////////
260 // senf::NetdeviceController::mactoName()
261 
263 {
264  boost::filesystem::ifstream file;
265  file.exceptions( std::ifstream::failbit | std::ifstream::badbit);
266  file.open(path, std::ios::in);
267  senf::MACAddress addr;
268  file >> addr;
269  file.close();
270  return addr;
271 }
272 
274 {
275  boost::filesystem::directory_iterator end_itr;
276  for (boost::filesystem::directory_iterator itr ("/sys/class/net/"); itr != end_itr; ++itr) {
277  try {
278  if (readMACAddressFromFile(itr->path()/"address") == mac)
279  return itr->path().filename().string();
280  } catch (std::exception &) {}
281  }
282  return "";
283 }
284 
285 
286 //-/////////////////////////////////////////////////////////////////////////////////////////////////
287 #undef prefix_
288 //#include "NetdeviceController.mpp"
289 
290 
291 // Local Variables:
292 // mode: c++
293 // fill-column: 100
294 // c-file-style: "senf"
295 // indent-tabs-mode: nil
296 // ispell-local-dictionary: "american"
297 // compile-command: "scons -u test"
298 // comment-column: 40
299 // End:
MACAddress public header.
int mtu() const
return the Maximum Transmission Unit
void timestamping(int txType, int rxFilter)
configures hw timestamping for RX and/or TX
#define SENF_THROW_SYSTEM_EXCEPTION(desc)
void addVLAN(std::uint16_t vlanId)
add a VLAN interface
Ethernet MAC address.
Definition: MACAddress.hh:72
void up()
ifconfig up interface
#define prefix_
bool isUp() const
return true if interface is up
void reset(std::string const &interface_name)
reset the ifindex_ from the given iface_name (i.e. after USB Ethernet unplug/plug ...
int txqueuelen() const
return the Tx Queue Length
void ifrName(ifreq &ifr) const
NetdeviceController public header.
boost::shared_ptr< SockFd > ptr
void down()
ifconfig down interface
bool promisc() const
return true if interface is in promiscuous mode
MACAddress hardwareAddress() const
return hardware address
void delVLAN(std::uint16_t vlanId)
delete a VLAN interface
int interfaceIndex() const
return the interface index
#define doIoctl(ifr, request, errorMsg)
NetdeviceController(std::string const &interface_name)
Construct a new controller for the given interface name.
static MACAddress from_data(InputIterator i)
Construct address from raw data.
static MACAddress readMACAddressFromFile(boost::filesystem::path const &path)
std::string interfaceName() const
return interface name
static std::string macToName(MACAddress const &mac)