예제 #1
0
QList<int> getListenFds()
{
	QList<int> fds;
	int n = sd_listen_fds(0);

	for(int i=0;i<n;++i) {
		int fd = SD_LISTEN_FDS_START + i;
		if(sd_is_socket_inet(fd, AF_UNSPEC, SOCK_STREAM, 1, 0) < 0) {
			logger::error() << "Socket" << i << " is not listening inet socket!";
		} else {
			fds.append(fd);
		}
	}

	return fds;
}
예제 #2
0
static int
setup_socket_from_systemd(void)
{
    int fd = SD_LISTEN_FDS_START;

    if (!sd_is_socket_inet(fd, AF_UNSPEC, SOCK_STREAM, 1, 0))
        lwan_status_critical("Passed file descriptor is not a "
            "listening TCP socket");

    int flags = fcntl(fd, F_GETFD);
    if (flags < 0)
        lwan_status_critical_perror("Could not obtain socket flags");
    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
        lwan_status_critical_perror("Could not set socket flags");

    return fd;
}
예제 #3
0
static PyObject* is_socket_inet(PyObject *self, PyObject *args) {
        int r;
        int fd, family = AF_UNSPEC, type = 0, listening = -1, port = 0;

        if (!PyArg_ParseTuple(args, "i|iiii:_is_socket_inet",
                              &fd, &family, &type, &listening, &port))
                return NULL;

        if (port < 0 || port > UINT16_MAX) {
                set_error(-EINVAL, NULL, "port must fit into uint16_t");
                return NULL;
        }

        r = sd_is_socket_inet(fd, family, type, listening, (uint16_t) port);
        if (set_error(r, NULL, NULL) < 0)
                return NULL;

        return PyBool_FromLong(r);
}
예제 #4
0
/*! starts listening on a TCP/IP (v4 or v6) address.
 *
 * \param address the IP address to bind to
 * \param port the TCP/IP port number to listen to
 * \param flags some flags, such as O_CLOEXEC and O_NONBLOCK (the most prominent) to set on server socket and each created client socket
 *
 * \retval true successfully initialized
 * \retval false some failure occured during setting up the server socket.
 */
bool ServerSocket::open(const std::string& address, int port, int flags)
{
#ifndef NDEBUG
	setLoggingPrefix("ServerSocket(%s:%d)", address.c_str(), port);
#endif
	TRACE("opening");

	int sd_fd_count = sd_listen_fds(false);
	addrinfo* res = nullptr;
	addrinfo hints;

	addrinfo* ri = nullptr;
	int rc;
	int fd = -1;
	in6_addr saddr;

	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = AI_NUMERICSERV;
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	if ((rc = inet_pton(AF_INET, address.c_str(), &saddr)) == 1) {
		hints.ai_family = AF_INET;
		hints.ai_flags |= AI_NUMERICHOST;
	} else if ((rc = inet_pton(AF_INET6, address.c_str(), &saddr)) == 1) {
		hints.ai_family = AF_INET6;
		hints.ai_flags |= AI_NUMERICHOST;
	} else {
		switch (rc) {
			case -1: // errno is set properly
				errorText_ = strerror(errno);
				break;
			case 0: // invalid network addr format
				errorText_ = strerror(EINVAL);
				break;
			default: // unknown error
				errorText_ = strerror(EINVAL);
				break;
		}
		return false;
	}

	char sport[16];
	snprintf(sport, sizeof(sport), "%d", port);

	if ((rc = getaddrinfo(address.c_str(), sport, &hints, &res)) != 0) {
		errorText_ = gai_strerror(rc);
		goto err;
	}

	typeMask_ = 0;
	flags_ = flags;

	if (flags & O_CLOEXEC) {
		flags_ &= ~O_CLOEXEC;
		typeMask_ |= SOCK_CLOEXEC;
	}

	if (flags & O_NONBLOCK) {
		flags_ &= ~O_NONBLOCK;
		typeMask_ |= SOCK_NONBLOCK;
	}

	// check if passed by parent x0d first
	for (ri = res; ri != nullptr; ri = ri->ai_next) {
		if ((fd = x0::getSocketInet(address.c_str(), port)) >= 0) {
			// socket found, but ensure our expected `flags` are set.
			if ((flags & O_NONBLOCK) && fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) < 0)
				goto syserr;

			if ((flags & O_CLOEXEC) && fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC) < 0)
				goto syserr;

			goto done;
		}
	}

	// check if systemd created the socket for us
	if (sd_fd_count > 0) {
		fd = SD_LISTEN_FDS_START;
		int last = fd + sd_fd_count;

		for (addrinfo* ri = res; ri != nullptr; ri = ri->ai_next) {
			for (; fd < last; ++fd) {
				if (sd_is_socket_inet(fd, ri->ai_family, ri->ai_socktype, true, port) > 0) {
					// socket found, but ensure our expected `flags` are set.
					if ((flags & O_NONBLOCK) && fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) < 0)
						goto syserr;

					if ((flags & O_CLOEXEC) && fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC) < 0)
						goto syserr;

#if defined(TCP_QUICKACK)
					if (::setsockopt(fd, SOL_TCP, TCP_QUICKACK, &rc, sizeof(rc)) < 0)
						goto syserr;
#endif

#if defined(TCP_DEFER_ACCEPT) && defined(WITH_TCP_DEFER_ACCEPT)
					if (::setsockopt(fd, SOL_TCP, TCP_DEFER_ACCEPT, &rc, sizeof(rc)) < 0)
						goto syserr;
#endif
					goto done;
				}
			}
		}

		char buf[256];
		snprintf(buf, sizeof(buf), "Running under systemd socket unit, but we received no socket for %s:%d.", address.c_str(), port);
		errorText_ = buf;
		goto err;
	}

	// create socket manually
	for (ri = res; ri != nullptr; ri = ri->ai_next) {
		fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (fd < 0)
			goto syserr;

		if ((flags & O_NONBLOCK) && fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) < 0)
			goto syserr;

		if ((flags & O_CLOEXEC) && fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC) < 0)
			goto syserr;

		rc = 1;

#if defined(SO_REUSEADDR)
		if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &rc, sizeof(rc)) < 0)
			goto syserr;
#endif

#if defined(TCP_QUICKACK)
		if (::setsockopt(fd, SOL_TCP, TCP_QUICKACK, &rc, sizeof(rc)) < 0)
			goto syserr;
#endif

#if defined(TCP_DEFER_ACCEPT) && defined(WITH_TCP_DEFER_ACCEPT)
		if (::setsockopt(fd, SOL_TCP, TCP_DEFER_ACCEPT, &rc, sizeof(rc)) < 0)
			goto syserr;
#endif

		// TODO so_linger(false, 0)
		// TODO so_keepalive(true)

		if (::bind(fd, res->ai_addr, res->ai_addrlen) < 0)
			goto syserr;

		if (::listen(fd, backlog_) < 0)
			goto syserr;

		goto done;
	}

done:
	fd_ = fd;
	addressFamily_ = res->ai_family;
	freeaddrinfo(res);
	address_ = address;
	port_ = port;

	io_.set<ServerSocket, &ServerSocket::accept>(this);
	start();

	return true;

syserr:
	errorText_ = strerror(errno);

err:
	if (res)
		freeaddrinfo(res);

	if (fd >= 0)
		::close(fd);

	return false;
}
예제 #5
0
파일: net.c 프로젝트: ChopSui258/beanstalkd
int
make_server_socket(char *host, char *port)
{
    int fd = -1, flags, r;
    struct linger linger = {0, 0};
    struct addrinfo *airoot, *ai, hints;

    /* See if we got a listen fd from systemd. If so, all socket options etc
     * are already set, so we check that the fd is a TCP listen socket and
     * return. */
    r = sd_listen_fds(1);
    if (r < 0) {
        return twarn("sd_listen_fds"), -1;
    }
    if (r > 0) {
        if (r > 1) {
            twarnx("inherited more than one listen socket;"
                   " ignoring all but the first");
            r = 1;
        }
        fd = SD_LISTEN_FDS_START;
        r = sd_is_socket_inet(fd, 0, SOCK_STREAM, 1, 0);
        if (r < 0) {
            errno = -r;
            twarn("sd_is_socket_inet");
            return -1;
        }
        if (!r) {
            twarnx("inherited fd is not a TCP listen socket");
            return -1;
        }
        return fd;
    }

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;
    r = getaddrinfo(host, port, &hints, &airoot);
    if (r == -1)
      return twarn("getaddrinfo()"), -1;

    for(ai = airoot; ai; ai = ai->ai_next) {
      fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
      if (fd == -1) {
        twarn("socket()");
        continue;
      }

      flags = fcntl(fd, F_GETFL, 0);
      if (flags < 0) {
        twarn("getting flags");
        close(fd);
        continue;
      }

      r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
      if (r == -1) {
        twarn("setting O_NONBLOCK");
        close(fd);
        continue;
      }

      flags = 1;
      setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof flags);
      setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof flags);
      setsockopt(fd, SOL_SOCKET, SO_LINGER,   &linger, sizeof linger);
      setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof flags);

      if (verbose) {
          char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV], *h = host, *p = port;
          r = getnameinfo(ai->ai_addr, ai->ai_addrlen,
                  hbuf, sizeof hbuf,
                  pbuf, sizeof pbuf,
                  NI_NUMERICHOST|NI_NUMERICSERV);
          if (!r) {
              h = hbuf;
              p = pbuf;
          }
          if (ai->ai_family == AF_INET6) {
              printf("bind %d [%s]:%s\n", fd, h, p);
          } else {
              printf("bind %d %s:%s\n", fd, h, p);
          }
      }
      r = bind(fd, ai->ai_addr, ai->ai_addrlen);
      if (r == -1) {
        twarn("bind()");
        close(fd);
        continue;
      }

      r = listen(fd, 1024);
      if (r == -1) {
        twarn("listen()");
        close(fd);
        continue;
      }

      break;
    }

    freeaddrinfo(airoot);

    if(ai == NULL)
      fd = -1;

    return fd;
}