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);
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),
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 +
"\"",
void bindToDevice(const std::string &device)
Binds this socket to a specific device (root privileges are required).
const int & getHandleImpl() const
Returns the native socket handle.
static std::vector< SocketLinux > createAndBindForAllInterfaces(uint16_t port)
Creates sockets for all interfaces and binds them to the respective interface.
const sockaddr_in & getDestSockAddr() const
Returns the sockaddr to which the socket is bound.
Exception representing an invalid socket operation.
void sendImpl(const std::vector< uint8_t > &sendbuf)
Sends data.
CRTP class for platform specific socket implementation.
Exception representing a Network Unreachable error (code 101 on Unix).
SocketLinux(int domain, int type, int protocol, in_addr_t dst_ip, uint16_t port, std::string iface_name)
Constructor.
void bind(const sockaddr_in &addr)
Binds the socket to an interface.
Exception representing an "operation not permitted" error.
static const in_addr_t & getBroadcastAddr()
Returns the broadcast address.
void enableNonBlockingImpl()
Enables non-blocking operation for this socket.
void bindImpl(const sockaddr_in &addr)
Binds the socket to a specific sockaddr.
static SocketLinux create(in_addr_t dst_ip, uint16_t port, std::string iface_name)
Create a new socket.
void enableBroadcastImpl()
Enables broadcast for this socket.
Socket implementation for Linux.
SocketLinux & operator=(SocketLinux &&other)