LinuxPacketSocketProtocol.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 "LinuxPacketSocketProtocol.ih"
19 
20 // Custom includes
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <linux/if_packet.h>
24 #include <net/if.h>
25 #include <net/ethernet.h>
26 #include <netinet/in.h>
27 
28 //#include "LinuxPacketSocketProtocol.mpp"
29 #define prefix_
30 //-/////////////////////////////////////////////////////////////////////////////////////////////////
31 
32 namespace {
33 
34  void do_mc(int fd, std::string const & interface, senf::MACAddress address, bool add)
35  {
36  struct ::packet_mreq mreq;
37  ::memset(&mreq, 0, sizeof(mreq));
38  mreq.mr_ifindex = ::if_nametoindex(interface.c_str());
39  if (mreq.mr_ifindex == 0)
40  throw senf::SystemException(EINVAL);
41  mreq.mr_type = PACKET_MR_MULTICAST;
42  mreq.mr_alen = 6;
43  std::copy(address.begin(), address.end(), &mreq.mr_address[0]);
44  if (::setsockopt(fd, SOL_PACKET,
45  add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
46  &mreq, sizeof(mreq)) < 0)
47  throw senf::SystemException();
48  }
49 }
50 
51 prefix_ void senf::LinuxPacketSocketProtocol::mcAdd(std::string const & interface,
52  MACAddress const & address)
53  const
54 {
55  do_mc(fd(), interface, address, true);
56 }
57 
58 prefix_ void senf::LinuxPacketSocketProtocol::mcDrop(std::string const & interface,
59  MACAddress const & address)
60  const
61 {
62  do_mc(fd(), interface, address, false);
63 }
64 
65 prefix_ void senf::LinuxPacketSocketProtocol::promisc(std::string const & interface, bool mode)
66  const
67 {
68  struct packet_mreq mreq;
69  ::memset(&mreq, 0, sizeof(mreq));
70  mreq.mr_ifindex = ::if_nametoindex(interface.c_str());
71  if (mreq.mr_ifindex == 0)
72  throw senf::SystemException(EINVAL);
73  mreq.mr_type = PACKET_MR_PROMISC;
74  if (::setsockopt(fd(), SOL_PACKET,
75  mode ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
76  &mreq, sizeof(mreq)) < 0)
77  throw senf::SystemException();
78 }
79 
81  const
82 {
83  struct ::tpacket_stats stats;
84  ::socklen_t len = sizeof(stats);
85  if (::getsockopt(fd(), SOL_PACKET, PACKET_STATISTICS,
86  reinterpret_cast<char *>(&stats), &len) < 0)
87  SENF_THROW_SYSTEM_EXCEPTION("::getsocketopt(SOL_PACKET, PACKET_STATISTICS) failed");
88  return stats.tp_drops;
89 }
90 
92  const
93 {
94 // this is defined by our WiBACK-kernel patches
95 #ifndef PACKET_STATISTICS_TX
96 # define PACKET_STATISTICS_TX 31
97 #endif
98  unsigned wrongFormat (0);
99  ::socklen_t len = sizeof(wrongFormat);
100  if (::getsockopt(fd(), SOL_PACKET, PACKET_STATISTICS_TX,
101  reinterpret_cast<char *>(&wrongFormat), &len) < 0)
102  SENF_THROW_SYSTEM_EXCEPTION("::getsocketopt(SOL_PACKET, PACKET_STATISTICS_TX) failed");
103  return wrongFormat;
104 }
105 
107  const
108 {
109  return false;
110 }
111 
113  const
114 {
115  int socktype = SOCK_RAW;
116  if (type == DatagramSocket)
117  socktype = SOCK_DGRAM;
118  if (protocol == -1)
119  protocol = ETH_P_ALL;
120  int sock = ::socket(PF_PACKET, socktype | SOCK_CLOEXEC, htons(protocol));
121  if (sock < 0)
122  SENF_THROW_SYSTEM_EXCEPTION("::socket(PF_PACKET) failed.");
123  fd(sock);
124 }
125 
127  const
128 {
129  if (! fh().readable())
130  return 0;
131  ssize_t l = ::recv(fd(),0,0,MSG_PEEK | MSG_TRUNC);
132  if (l < 0)
133  SENF_THROW_SYSTEM_EXCEPTION("::recv(socket_fd) failed.");
134  return l;
135 }
136 
137 //-/////////////////////////////////////////////////////////////////////////////////////////////////
138 #undef prefix_
139 //#include "LinuxPacketSocketProtocol.mpp"
140 
141 
142 // Local Variables:
143 // mode: c++
144 // fill-column: 100
145 // comment-column: 40
146 // c-file-style: "senf"
147 // indent-tabs-mode: nil
148 // ispell-local-dictionary: "american"
149 // compile-command: "scons -u test"
150 // End:
#define prefix_
#define SENF_THROW_SYSTEM_EXCEPTION(desc)
unsigned txWrongFormat() const
packets dropped by kernel due to wrong format (too large) since last call
Ethernet MAC address.
Definition: MACAddress.hh:72
unsigned rxQueueDropped() const
packets dropped by kernel since last call
int fd() const
Get file descriptor.
unsigned available() const
Return (maximum) number of bytes available for reading without < blocking.
void mcDrop(std::string const &interface, MACAddress const &address) const
Disable reception of a multicast group.
void init_packetSocket(SocketType type, int protocol) const
FileHandle fh() const
Get a FileHandle for this instance.
LinuxPacketSocketProtocol public header.
void promisc(std::string const &interface, bool mode) const
enable/disable promiscuous mode
void mcAdd(std::string const &interface, MACAddress const &address) const
Enable reception of a multicast group.
#define PACKET_STATISTICS_TX
bool eof() const
Check for end-of-file condition.