9 static const char rcsid[] __attribute__((used)) =
"$Id: EtherSocket.cpp 1653 2016-02-28 19:54:59Z sella $";
11 #include "EtherSocket.h"
12 #include "../util/Interface.h"
14 #include <sys/types.h>
15 #include <sys/socket.h>
18 #include <net/ethernet.h>
20 using namespace sella::net;
21 using namespace sella::util;
23 const unsigned char EtherSocket::BroadcastMAC[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
25 EtherSocket::EtherSocket(
int etherType,
const std::string &interface,
bool raw)
throw (SocketException) :
26 Socket(AF_PACKET, (raw) ? SOCK_RAW : SOCK_DGRAM, htons(etherType)),
31 ifIndex = Interface::getIndex(interface);
33 }
catch (InterfaceException &e) {
34 RETHROW(SocketException, e);
38 EtherSocket::EtherSocket(
int etherType,
int ifIndex,
bool raw)
throw (SocketException) :
39 Socket(AF_PACKET, (raw) ? SOCK_RAW : SOCK_DGRAM, htons(etherType)),
45 EtherSocket::EtherSocket(
int etherType,
bool raw)
throw (SocketException) :
46 Socket(AF_PACKET, (raw) ? SOCK_RAW : SOCK_DGRAM, htons(etherType)),
52 EtherSocket::~EtherSocket() {
55 const EtherSocket::shared EtherSocket::shared_ptr(
int etherType)
throw (SocketException) {
56 return std::make_shared<EtherSocket>(etherType);
59 EtherSocket& EtherSocket::setInterface(
const std::string &interface)
throw (SocketException) {
60 if ((ifIndex = if_nametoindex(interface.c_str())) == 0) {
61 THROW2(SocketException,
"if_nametoindex()");
67 EtherSocket& EtherSocket::setIfIndex(
int ifIndex)
throw () {
68 this->ifIndex = ifIndex;
73 int EtherSocket::getEtherType(
void)
const throw () {
77 std::string EtherSocket::getInterface(
void)
const throw (SocketException) {
78 char buf[IF_NAMESIZE];
81 THROW(SocketException,
"Interface or index must be set prior to getInterface()");
84 if (if_indextoname(ifIndex, buf) == NULL) {
85 THROW2(SocketException,
"if_indextoname()");
91 int EtherSocket::getIfIndex(
void)
const throw () {
95 bool EtherSocket::isRaw(
void)
const throw () {
99 void EtherSocket::bindInterface(
void) throw (SocketException) {
101 socklen_t addrlen =
sizeof(sockaddr_ll);
104 THROW(SocketException,
"Interface or index must be set prior to bindInterface()");
107 sll.sll_family = AF_PACKET;
108 sll.sll_ifindex = ifIndex;
109 sll.sll_protocol = htons(etherType);
111 if (::bind(s, (sockaddr*) &sll, addrlen) < 0) {
112 THROW2(SocketException,
"bind()");
116 void EtherSocket::setSoBindToDevice(
const std::string &interface)
throw (SocketException) {
117 Socket::setSoBindToDevice(interface);
120 void EtherSocket::setSoBindToDevice(
void) throw (SocketException) {
121 Socket::setSoBindToDevice(getInterface());
124 void EtherSocket::setPromiscous(
bool on)
throw (SocketException) {
128 THROW(SocketException,
"Interface or index must be set prior to setPromiscous()");
131 const std::string &name = getInterface();
132 memset(&ifr, 0,
sizeof(ifr));
134 strncpy(ifr.ifr_name, name.c_str(), name.size());
136 if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
137 THROW2(SocketException,
"ioctl()");
141 ifr.ifr_flags |= IFF_PROMISC;
143 ifr.ifr_flags &= ~IFF_PROMISC;
146 if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) {
147 THROW2(SocketException,
"ioctl()");
151 ssize_t EtherSocket::sendto(
const void *data,
size_t len,
const std::string &dst_mac,
int flags)
throw (SocketException) {
152 unsigned char addr[6] = { 0, 0, 0, 0, 0, 0 };
155 Interface::convertMAC(addr, dst_mac);
156 }
catch (InterfaceException &e) {
157 RETHROW(SocketException, e);
160 return sendto(data, len, addr, flags);
163 ssize_t EtherSocket::sendto(
const void *data,
size_t len,
const unsigned char *dst_mac,
int flags)
throw (SocketException) {
164 sockaddr_ll dest_addr = { 0 };
165 socklen_t addrlen =
sizeof(sockaddr_ll);
168 THROW(SocketException,
"Interface must be set prior to sendto()");
171 dest_addr.sll_family = AF_PACKET;
172 dest_addr.sll_ifindex = ifIndex;
173 dest_addr.sll_halen = ETHER_ADDR_LEN;
174 dest_addr.sll_protocol = htons(etherType);
175 memcpy(dest_addr.sll_addr, dst_mac, ETHER_ADDR_LEN);
177 return sendto(data, len, flags, (
const struct sockaddr_ll*) &dest_addr, addrlen);
180 ssize_t EtherSocket::sendto(
const void *data,
size_t len,
int flags,
const sockaddr_ll *dest_addr, socklen_t addrlen)
throw (SocketException) {
184 if ((c = ::sendto(s, data, len, flags, (
const struct sockaddr*) dest_addr, addrlen)) < 0) {
196 THROW2(SocketException,
"sendto()");
200 }
while ((r -= c) > 0);
207 ssize_t EtherSocket::recvfrom(
void *data,
size_t len,
int flags, sockaddr_ll *src_addr, socklen_t *addrlen)
throw (SocketException) {
210 if ((c = ::recvfrom(s, data, len, flags, (sockaddr*) src_addr, addrlen)) < 0) {
220 THROW2(SocketException,
"recv()");
225 read = except =
false;
230 ssize_t EtherSocket::recvfrom(
void *data,
size_t len, std::string &src_mac,
int flags)
throw (SocketException) {
231 sockaddr_ll src_addr;
232 socklen_t addrlen =
sizeof(sockaddr_ll);
235 if ((c = recvfrom(data, len, flags, (sockaddr_ll*) &src_addr, &addrlen)) > 0) {
236 Interface::convertMAC(src_mac, (
const unsigned char*) src_addr.sll_addr);