42 #include <arpa/inet.h>
44 #include <sys/socket.h>
45 #include <sys/ioctl.h>
47 #include <linux/if_packet.h>
48 #include <netinet/ether.h>
60 static const in_addr_t bcast = htonl(INADDR_BROADCAST);
70 std::string iface_name)
72 return SocketLinux(AF_INET, SOCK_DGRAM, IPPROTO_UDP, dst_ip, port,
73 std::move(iface_name));
79 std::vector<SocketLinux> sockets;
86 for(ifaddrs *addr = addrs;
88 addr = addr->ifa_next)
90 auto baddr = addr->ifa_ifu.ifu_broadaddr;
91 if (addr->ifa_flags & IFF_UP &&
92 addr->ifa_name !=
nullptr &&
93 addr->ifa_addr !=
nullptr &&
94 addr->ifa_addr->sa_family == AF_INET &&
97 std::string name(addr->ifa_name);
98 if (name.length() != 0 && name !=
"lo")
100 const in_addr_t s_addr =
101 reinterpret_cast<struct sockaddr_in *
>(addr->ifa_addr)->
104 uint16_t local_port = 0;
111 addr.sin_family = AF_INET;
113 addr.sin_addr.s_addr = s_addr;
114 sockets.back().bind(addr);
119 struct sockaddr_in local_address;
120 socklen_t address_length =
sizeof(local_address);
121 getsockname(sockets.back().sock_,
122 reinterpret_cast<sockaddr *
>(&local_address),
124 local_port = local_address.sin_port;
132 addr.sin_family = AF_INET;
133 addr.sin_port = local_port;
134 addr.sin_addr.s_addr = htonl(INADDR_ANY);
135 sockets.back().bind(addr);
140 sockets.emplace_back(
142 reinterpret_cast<struct sockaddr_in *
>(baddr)->
143 sin_addr.s_addr, port, name));
145 addr.sin_family = AF_INET;
146 addr.sin_port = local_port;
147 addr.sin_addr.s_addr = htonl(INADDR_ANY);
148 sockets.back().bind(addr);
162 SocketLinux::SocketLinux(
int domain,
int type,
int protocol,
163 in_addr_t dst_ip, uint16_t port,
164 std::string iface_name) :
165 Socket(std::move(iface_name)),
169 sock_ = ::socket(domain, type, protocol);
185 if (::setsockopt(
sock_,
188 reinterpret_cast<const char *
>(&yes),
198 dst_addr_(std::move(other.dst_addr_))
200 std::swap(
sock_, other.sock_);
205 std::swap(
sock_, other.sock_);
225 reinterpret_cast<const sockaddr *
>(&addr),
226 sizeof(sockaddr)) == -1)
235 static_cast<const void *
>(sendbuf.data()),
238 reinterpret_cast<const sockaddr *
>(&
dst_addr_),
239 static_cast<socklen_t
>(
sizeof(sockaddr_in))) == -1)
241 if (errno == ENETUNREACH)
244 "Error while sending data - network unreachable", errno);
254 if (::setsockopt(
sock_,
257 reinterpret_cast<const char *
>(&yes),
266 int flags = fcntl(
sock_, F_GETFL, 0);
267 if (flags < 0 || fcntl(
sock_, F_SETFL, flags | O_RDWR | O_NONBLOCK) == -1)
269 throw SocketException(
"Error while setting socket non-blocking", errno);
275 if (::setsockopt(
sock_,
279 static_cast<socklen_t
>(device.size())) == -1)
286 throw SocketException(
"Error while binding to device \"" + device +
"\"",