11 #include <sys/types.h> 12 #include <sys/socket.h> 16 #include <netinet/in.h> 29 #include <boost/noncopyable.hpp> 46 using namespace internal;
53 sizeof(
struct sockaddr_storage) * 2;
80 memset(&sock_un_, 0,
sizeof(sock_un_));
83 struct sockaddr_un sock_un_;
89 SocketSessionForwarder::SocketSessionForwarder(
const std::string& unix_file) :
94 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
99 if (
sizeof(impl.
sock_un_.sun_path) - 1 < unix_file.length()) {
101 "File name for a UNIX domain socket is too long: " <<
109 strncpy(impl.
sock_un_.sun_path, unix_file.c_str(),
110 sizeof(impl.
sock_un_.sun_path) - 1);
112 impl.
sock_un_len_ = offsetof(
struct sockaddr_un, sun_path) +
124 if (impl_->
fd_ != -1) {
132 if (impl_->
fd_ != -1) {
134 "endpoint " << impl_->
sock_un_.sun_path);
137 impl_->
fd_ = socket(AF_UNIX, SOCK_STREAM, 0);
138 if (impl_->
fd_ == -1) {
143 int fcntl_flags = fcntl(impl_->
fd_, F_GETFL, 0);
144 if (fcntl_flags != -1) {
145 fcntl_flags |= O_NONBLOCK;
146 fcntl_flags = fcntl(impl_->
fd_, F_SETFL, fcntl_flags);
148 if (fcntl_flags == -1) {
151 "Failed to make UNIX domain socket non blocking: " <<
157 socklen_t sndbuf_size_len =
sizeof(sndbuf_size);
158 if (getsockopt(impl_->
fd_, SOL_SOCKET, SO_SNDBUF, &sndbuf_size,
159 &sndbuf_size_len) == -1 ||
161 if (setsockopt(impl_->
fd_, SOL_SOCKET, SO_SNDBUF, &SOCKSESSION_BUFSIZE,
162 sizeof(SOCKSESSION_BUFSIZE)) == -1) {
165 "Failed to set send buffer size to " <<
166 SOCKSESSION_BUFSIZE);
173 "endpoint " << impl_->
sock_un_.sun_path <<
": " <<
180 if (impl_->
fd_ == -1) {
189 const struct sockaddr& local_end,
190 const struct sockaddr& remote_end,
191 const void* data,
size_t data_len)
193 if (impl_->
fd_ == -1) {
196 if ((local_end.sa_family != AF_INET && local_end.sa_family != AF_INET6) ||
197 (remote_end.sa_family != AF_INET && remote_end.sa_family != AF_INET6))
200 "AF_INET or AF_INET6; " <<
201 static_cast<int>(local_end.sa_family) <<
", " <<
202 static_cast<int>(remote_end.sa_family) <<
" given");
204 if (family != local_end.sa_family || family != remote_end.sa_family) {
206 << static_cast<int>(family) <<
"; " 207 << static_cast<int>(local_end.sa_family) <<
", " 208 << static_cast<int>(remote_end.sa_family) <<
" given");
210 if (data_len == 0 || data == NULL) {
213 if (data_len > MAX_DATASIZE) {
215 data_len <<
", must not exceed " << MAX_DATASIZE);
237 const uint32_t data_len32 =
static_cast<uint32_t
>(data_len);
243 const struct iovec iov[2] = {
245 {
const_cast<void*
>(data), data_len }
247 const int cc = writev(impl_->
fd_, iov, 2);
251 "Write failed in forwarding a socket session: " <<
255 "Incomplete write in forwarding a socket session: " << cc <<
261 const sockaddr* local_end,
262 const sockaddr* remote_end,
263 const void* data,
size_t data_len) :
264 sock_(sock), family_(family), type_(type), protocol_(protocol),
265 local_end_(local_end), remote_end_(remote_end),
266 data_(data), data_len_(data_len)
268 if (local_end == NULL || remote_end == NULL) {
283 header_buf_(DEFAULT_HEADER_BUFLEN),
284 data_buf_(INITIAL_BUFSIZE)
286 memset(&ss_local_, 0,
sizeof(ss_local_));
287 memset(&ss_remote_, 0,
sizeof(ss_remote_));
289 if (setsockopt(
fd_, SOL_SOCKET, SO_RCVBUF, &SOCKSESSION_BUFSIZE,
290 sizeof(SOCKSESSION_BUFSIZE)) == -1) {
292 "Failed to set receive buffer size to " <<
293 SOCKSESSION_BUFSIZE);
298 struct sockaddr_storage ss_local_;
300 struct sockaddr_storage ss_remote_;
320 readFail(
int actual_len,
int expected_len) {
321 if (expected_len < 0) {
323 "SocketSessionForwarder: " << strerror(errno));
326 "SocketSessionForwarder: " << actual_len <<
"/" <<
333 struct ScopedSocket : boost::noncopyable {
334 ScopedSocket(
int fd) :
fd_(fd) {}
351 ScopedSocket passed_sock(
recv_fd(impl_->fd_));
355 }
else if (passed_sock.fd_ < 0) {
360 const int cc_hlen = recv(impl_->fd_, &header_len,
sizeof(header_len),
362 if (cc_hlen <
sizeof(header_len)) {
363 readFail(cc_hlen,
sizeof(header_len));
366 if (header_len > DEFAULT_HEADER_BUFLEN) {
370 impl_->header_buf_.clear();
371 impl_->header_buf_.resize(header_len);
372 const int cc_hdr = recv(impl_->fd_, &impl_->header_buf_[0], header_len,
374 if (cc_hdr < header_len) {
375 readFail(cc_hdr, header_len);
378 InputBuffer ibuffer(&impl_->header_buf_[0], header_len);
380 const int family =
static_cast<int>(ibuffer.
readUint32());
381 if (family != AF_INET && family != AF_INET6) {
383 "Unsupported address family is passed: " << family);
385 const int type =
static_cast<int>(ibuffer.
readUint32());
386 const int protocol =
static_cast<int>(ibuffer.
readUint32());
387 const socklen_t local_end_len = ibuffer.
readUint32();
388 const socklen_t endpoint_minlen = (family == AF_INET) ?
389 sizeof(
struct sockaddr_in) :
sizeof(
struct sockaddr_in6);
390 if (local_end_len < endpoint_minlen ||
391 local_end_len >
sizeof(impl_->ss_local_)) {
395 ibuffer.
readData(&impl_->ss_local_, local_end_len);
396 const socklen_t remote_end_len = ibuffer.
readUint32();
397 if (remote_end_len < endpoint_minlen ||
398 remote_end_len >
sizeof(impl_->ss_remote_)) {
402 ibuffer.
readData(&impl_->ss_remote_, remote_end_len);
403 if (family != impl_->sa_local_->sa_family ||
404 family != impl_->sa_remote_->sa_family) {
406 static_cast<int>(impl_->sa_local_->sa_family) <<
", " <<
407 static_cast<int>(impl_->sa_remote_->sa_family) <<
408 " given, must be " << family);
411 if (data_len == 0 || data_len > MAX_DATASIZE) {
413 "Invalid socket session data size: " << data_len <<
414 ", must be > 0 and <= " << MAX_DATASIZE);
417 impl_->data_buf_.clear();
418 impl_->data_buf_.resize(data_len);
419 const int cc_data = recv(impl_->fd_, &impl_->data_buf_[0], data_len,
421 if (cc_data < data_len) {
422 readFail(cc_data, data_len);
425 return (
SocketSession(passed_sock.release(), family, type, protocol,
426 impl_->sa_local_, impl_->sa_remote_,
427 &impl_->data_buf_[0], data_len));
int recv_fd(const int sock)
Receives a file descriptor.
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
vector< uint8_t > data_buf_
socklen_t getSALength(const struct sockaddr &sa)
struct sockaddr_un sock_un_
void skip(size_t len)
Insert a specified length of gap at the end of the buffer.
virtual void push(int sock, int family, int type, int protocol, const struct sockaddr &local_end, const struct sockaddr &remote_end, const void *data, size_t data_len)
Forward a socket session to the receiver.
struct sockaddr *const sa_remote_
struct sockaddr *const sa_local_
virtual ~SocketSessionForwarder()
The destructor.
Support to transfer file descriptors between processes.
SocketSession(int sock, int family, int type, int protocol, const sockaddr *local_end, const sockaddr *remote_end, const void *data, size_t data_len)
The constructor.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
An exception indicating general errors that takes place in the socket session related class objects...
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
void writeUint16At(uint16_t data, size_t pos)
Write an unsigned 16-bit integer in host byte order at the specified position of the buffer in networ...
A generic exception that is thrown when an unexpected error condition occurs.
const size_t INITIAL_BUFSIZE
const size_t DEFAULT_HEADER_BUFLEN
int send_fd(const int sock, const int fd)
Sends a file descriptor.
const void * getData() const
Return a pointer to the head of the data stored in the buffer.
void clear()
Clear buffer content.
A standard DNS module exception that is thrown if an out-of-range buffer operation is being performed...
vector< uint8_t > header_buf_
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
size_t getLength() const
Return the length of data written in the buffer.
void writeUint32(uint32_t data)
Write an unsigned 32-bit integer in host byte order into the buffer in network byte order...
Defines the logger used by the top-level component of kea-lfc.
const struct sockaddr * convertSockAddr(const SAType *sa)
SocketSession pop()
Receive a socket session from the forwarder.
const int SOCKSESSION_BUFSIZE
~SocketSessionReceiver()
The destructor.
virtual void connectToReceiver()
Establish a connection to the receiver.
SocketSessionReceiver(int fd)
The constructor.
virtual void close()
Close the connection to the receiver.
const int FD_SYSTEM_ERROR