00001
00002
00003
00004
00005
00006
00007
00008
00009 static const char rcsid[] __attribute__((used)) = "$Id: EtherSocket.cpp 1197 2014-10-14 22:26:11Z sella $";
00010
00011 #include "EtherSocket.h"
00012 #include "../util/Interface.h"
00013
00014 #include <sys/types.h>
00015 #include <sys/socket.h>
00016 #include <string.h>
00017 #include <net/if.h>
00018 #include <net/ethernet.h>
00019
00020 using namespace sella::net;
00021 using namespace sella::util;
00022
00023 const unsigned char EtherSocket::BroadcastMAC[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
00024
00025 EtherSocket::EtherSocket(int etherType, const std::string &interface, bool raw) throw (SocketException) :
00026 Socket(AF_PACKET, (raw) ? SOCK_RAW : SOCK_DGRAM, htons(etherType)),
00027 etherType(etherType),
00028 raw(raw)
00029 {
00030 try {
00031 ifIndex = Interface::getIndex(interface);
00032
00033 } catch (InterfaceException &e) {
00034 RETHROW(SocketException, e);
00035 }
00036 }
00037
00038 EtherSocket::EtherSocket(int etherType, int ifIndex, bool raw) throw (SocketException) :
00039 Socket(AF_PACKET, (raw) ? SOCK_RAW : SOCK_DGRAM, htons(etherType)),
00040 etherType(etherType),
00041 ifIndex(ifIndex),
00042 raw(raw)
00043 { }
00044
00045 EtherSocket::EtherSocket(int etherType, bool raw) throw (SocketException) :
00046 Socket(AF_PACKET, (raw) ? SOCK_RAW : SOCK_DGRAM, htons(etherType)),
00047 etherType(etherType),
00048 ifIndex(-1),
00049 raw(raw)
00050 { }
00051
00052 EtherSocket::~EtherSocket() {
00053 }
00054
00055 const EtherSocket::shared EtherSocket::shared_ptr(int etherType) throw (SocketException) {
00056 return std::make_shared<EtherSocket>(etherType);
00057 }
00058
00059 EtherSocket& EtherSocket::setInterface(const std::string &interface) throw (SocketException) {
00060 if ((ifIndex = if_nametoindex(interface.c_str())) == 0) {
00061 THROW2(SocketException, "if_nametoindex()");
00062 }
00063
00064 return *this;
00065 }
00066
00067 EtherSocket& EtherSocket::setIfIndex(int ifIndex) throw () {
00068 this->ifIndex = ifIndex;
00069
00070 return *this;
00071 }
00072
00073 int EtherSocket::getEtherType(void) const throw () {
00074 return etherType;
00075 }
00076
00077 std::string EtherSocket::getInterface(void) const throw (SocketException) {
00078 char buf[IF_NAMESIZE];
00079
00080 if (ifIndex == -1) {
00081 THROW(SocketException, "Interface or index must be set prior to getInterface()");
00082 }
00083
00084 if (if_indextoname(ifIndex, buf) == NULL) {
00085 THROW2(SocketException, "if_indextoname()");
00086 }
00087
00088 return buf;
00089 }
00090
00091 int EtherSocket::getIfIndex(void) const throw () {
00092 return ifIndex;
00093 }
00094
00095 bool EtherSocket::isRaw(void) const throw () {
00096 return raw;
00097 }
00098
00099 void EtherSocket::bindInterface(void) throw (SocketException) {
00100 sockaddr_ll sll;
00101 socklen_t addrlen = sizeof(sockaddr_ll);
00102
00103 if (ifIndex == -1) {
00104 THROW(SocketException, "Interface or index must be set prior to bindInterface()");
00105 }
00106
00107 sll.sll_family = AF_PACKET;
00108 sll.sll_ifindex = ifIndex;
00109 sll.sll_protocol = htons(etherType);
00110
00111 if (::bind(s, (sockaddr*) &sll, addrlen) < 0) {
00112 THROW2(SocketException, "bind()");
00113 }
00114 }
00115
00116 void EtherSocket::setSoBindToDevice(const std::string &interface) throw (SocketException) {
00117 Socket::setSoBindToDevice(interface);
00118 }
00119
00120 void EtherSocket::setSoBindToDevice(void) throw (SocketException) {
00121 Socket::setSoBindToDevice(getInterface());
00122 }
00123
00124 void EtherSocket::setPromiscous(bool on) throw (SocketException) {
00125 struct ifreq ifr;
00126
00127 if (ifIndex == -1) {
00128 THROW(SocketException, "Interface or index must be set prior to setPromiscous()");
00129 }
00130
00131 const std::string &name = getInterface();
00132 memset(&ifr, 0, sizeof(ifr));
00133
00134 strncpy(ifr.ifr_name, name.c_str(), name.size());
00135
00136 if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
00137 THROW2(SocketException, "ioctl()");
00138 }
00139
00140 if (on) {
00141 ifr.ifr_flags |= IFF_PROMISC;
00142 } else {
00143 ifr.ifr_flags &= ~IFF_PROMISC;
00144 }
00145
00146 if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) {
00147 THROW2(SocketException, "ioctl()");
00148 }
00149 }
00150
00151 ssize_t EtherSocket::sendto(const void *data, size_t len, const std::string &dst_mac, int flags) throw (SocketException) {
00152 unsigned char addr[6] = { 0, 0, 0, 0, 0, 0 };
00153
00154 try {
00155 Interface::convertMAC(addr, dst_mac);
00156 } catch (InterfaceException &e) {
00157 RETHROW(SocketException, e);
00158 }
00159
00160 return sendto(data, len, addr, flags);
00161 }
00162
00163 ssize_t EtherSocket::sendto(const void *data, size_t len, const unsigned char *dst_mac, int flags) throw (SocketException) {
00164 sockaddr_ll dest_addr = { 0 };
00165 socklen_t addrlen = sizeof(sockaddr_ll);
00166
00167 if (ifIndex == -1) {
00168 THROW(SocketException, "Interface must be set prior to sendto()");
00169 }
00170
00171 dest_addr.sll_family = AF_PACKET;
00172 dest_addr.sll_ifindex = ifIndex;
00173 dest_addr.sll_halen = ETHER_ADDR_LEN;
00174 dest_addr.sll_protocol = htons(etherType);
00175 memcpy(dest_addr.sll_addr, dst_mac, ETHER_ADDR_LEN);
00176
00177 return sendto(data, len, flags, (const struct sockaddr_ll*) &dest_addr, addrlen);
00178 }
00179
00180 ssize_t EtherSocket::sendto(const void *data, size_t len, int flags, const sockaddr_ll *dest_addr, socklen_t addrlen) throw (SocketException) {
00181 ssize_t c, r = len;
00182
00183 do {
00184 if ((c = ::sendto(s, data, len, flags, (const struct sockaddr*) dest_addr, addrlen)) < 0) {
00185 switch (errno) {
00186 case EINTR:
00187 case EAGAIN:
00188 case EMSGSIZE:
00189 case ENOBUFS:
00190 break;
00191
00192 default:
00193 usable = false;
00194 }
00195
00196 THROW2(SocketException, "sendto()");
00197 } else if (c == 0) {
00198 usable = false;
00199 }
00200 } while ((r -= c) > 0);
00201
00202 write = false;
00203
00204 return len;
00205 }
00206
00207 ssize_t EtherSocket::recvfrom(void *data, size_t len, int flags, sockaddr_ll *src_addr, socklen_t *addrlen) throw (SocketException) {
00208 ssize_t c;
00209
00210 if ((c = ::recvfrom(s, data, len, flags, (sockaddr*) src_addr, addrlen)) < 0) {
00211 switch (errno) {
00212 case EINTR:
00213 case EAGAIN:
00214 break;
00215
00216 default:
00217 usable = false;
00218 }
00219
00220 THROW2(SocketException, "recv()");
00221 } else if (c == 0) {
00222 usable = false;
00223 }
00224
00225 read = except = false;
00226
00227 return c;
00228 }
00229
00230 ssize_t EtherSocket::recvfrom(void *data, size_t len, std::string &src_mac, int flags) throw (SocketException) {
00231 sockaddr_ll src_addr;
00232 socklen_t addrlen = sizeof(sockaddr_ll);
00233 ssize_t c;
00234
00235 if ((c = recvfrom(data, len, flags, (sockaddr_ll*) &src_addr, &addrlen)) > 0) {
00236 Interface::convertMAC(src_mac, (const unsigned char*) src_addr.sll_addr);
00237 } else {
00238 src_mac.clear();
00239 }
00240
00241 return c;
00242 }
00243
00244
00245
00246