static int open_sockets(int *epoll_fd, bool accept) { char **address; int n, fd, r; int count = 0; n = sd_listen_fds(true); if (n < 0) { log_error("Failed to read listening file descriptors from environment: %s", strerror(-n)); return n; } if (n > 0) { log_info("Received %i descriptors via the environment.", n); for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { r = fd_cloexec(fd, arg_accept); if (r < 0) return r; count ++; } } /* Close logging and all other descriptors */ if (arg_listen) { int except[3 + n]; for (fd = 0; fd < SD_LISTEN_FDS_START + n; fd++) except[fd] = fd; log_close(); close_all_fds(except, 3 + n); } /** Note: we leak some fd's on error here. I doesn't matter * much, since the program will exit immediately anyway, but * would be a pain to fix. */ STRV_FOREACH(address, arg_listen) { fd = make_socket_fd(*address, SOCK_STREAM | (arg_accept*SOCK_CLOEXEC)); if (fd < 0) { log_open(); log_error("Failed to open '%s': %s", *address, strerror(-fd)); return fd; } assert(fd == SD_LISTEN_FDS_START + count); count ++; }
/*! Send DpiBye command to all active non-filter dpis */ void stop_active_dpis(struct dp *dpi_attr_list, int numdpis) { char *bye_cmd, *auth_cmd; int i, sock_fd; struct sockaddr_in sin; bye_cmd = a_Dpip_build_cmd("cmd=%s", "DpiBye"); auth_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", "auth", SharedKey); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); for (i = 0; i < numdpis; i++) { /* Skip inactive dpis and filters */ if (dpi_attr_list[i].pid == 1 || dpi_attr_list[i].filter) continue; if ((sock_fd = make_socket_fd()) == -1) { ERRMSG("stop_active_dpis", "socket", errno); continue; } sin.sin_port = htons(dpi_attr_list[i].port); if (ckd_connect(sock_fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { ERRMSG("stop_active_dpis", "connect", errno); MSG_ERR("%s\n", dpi_attr_list[i].path); } else if (CKD_WRITE(sock_fd, auth_cmd) == -1) { ERRMSG("stop_active_dpis", "write", errno); } else if (CKD_WRITE(sock_fd, bye_cmd) == -1) { ERRMSG("stop_active_dpis", "write", errno); } dClose(sock_fd); } dFree(auth_cmd); dFree(bye_cmd); /* Allow child dpis some time to read dpid_comm_keys before erasing it */ sleep (1); }
/*! Bind a socket port on localhost. Try to be close to base_port. * \Return * \li listening socket file descriptor on success * \li -1 on failure */ int bind_socket_fd(int base_port, int *p_port) { int sock_fd, port; struct sockaddr_in sin; int ok = 0, last_port = base_port + 50; if ((sock_fd = make_socket_fd()) == -1) { return (-1); /* avoids nested ifs */ } /* Set the socket FD to close on exec */ fcntl(sock_fd, F_SETFD, FD_CLOEXEC | fcntl(sock_fd, F_GETFD)); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* Try to bind a port on localhost */ for (port = base_port; port <= last_port; ++port) { sin.sin_port = htons(port); if ((bind(sock_fd, (struct sockaddr *)&sin, sizeof(sin))) == -1) { if (errno == EADDRINUSE || errno == EADDRNOTAVAIL) continue; ERRMSG("bind_socket_fd", "bind", errno); } else if (listen(sock_fd, QUEUE) == -1) { ERRMSG("bind_socket_fd", "listen", errno); } else { *p_port = port; ok = 1; break; } } if (port > last_port) { MSG_ERR("Hey! Can't find an available port from %d to %d\n", base_port, last_port); } return ok ? sock_fd : -1; }
static int print_socket(const char* desc, int fd) { int r; SocketAddress addr = { .size = sizeof(union sockaddr_union), .type = SOCK_STREAM, }; int family; r = getsockname(fd, &addr.sockaddr.sa, &addr.size); if (r < 0) { log_warning("Failed to query socket on fd:%d: %m", fd); return 0; } family = socket_address_family(&addr); switch(family) { case AF_INET: case AF_INET6: { char* _cleanup_free_ a = NULL; r = socket_address_print(&addr, &a); if (r < 0) log_warning("socket_address_print(): %s", strerror(-r)); else log_info("%s %s address %s", desc, family == AF_INET ? "IP" : "IPv6", a); break; } default: log_warning("Connection with unknown family %d", family); } return 0; } static int open_sockets(int *epoll_fd, bool accept) { int n, fd; int count = 0; char **address; n = sd_listen_fds(true); if (n < 0) { log_error("Failed to read listening file descriptors from environment: %s", strerror(-n)); return n; } log_info("Received %d descriptors", n); for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { log_debug("Received descriptor fd:%d", fd); print_socket("Listening on", fd); if (!arg_accept) { int r = set_nocloexec(fd); if (r < 0) return r; } count ++; } /** Note: we leak some fd's on error here. I doesn't matter * much, since the program will exit immediately anyway, but * would be a pain to fix. */ STRV_FOREACH(address, arg_listen) { log_info("Opening address %s", *address); fd = make_socket_fd(*address, SOCK_STREAM | (arg_accept*SOCK_CLOEXEC)); if (fd < 0) { log_error("Failed to open '%s': %s", *address, strerror(-fd)); return fd; } count ++; }
static int add_epoll(int epoll_fd, int fd) { struct epoll_event ev = { .events = EPOLLIN, .data.fd = fd, }; assert(epoll_fd >= 0); assert(fd >= 0); if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) return log_error_errno(errno, "Failed to add event on epoll fd:%d for fd:%d: %m", epoll_fd, fd); return 0; } static int open_sockets(int *epoll_fd, bool accept) { char **address; int n, fd, r; int count = 0; n = sd_listen_fds(true); if (n < 0) return log_error_errno(n, "Failed to read listening file descriptors from environment: %m"); if (n > 0) { log_info("Received %i descriptors via the environment.", n); for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { r = fd_cloexec(fd, arg_accept); if (r < 0) return r; count++; } } /* Close logging and all other descriptors */ if (arg_listen) { int except[3 + n]; for (fd = 0; fd < SD_LISTEN_FDS_START + n; fd++) except[fd] = fd; log_close(); close_all_fds(except, 3 + n); } /** Note: we leak some fd's on error here. I doesn't matter * much, since the program will exit immediately anyway, but * would be a pain to fix. */ STRV_FOREACH(address, arg_listen) { fd = make_socket_fd(LOG_DEBUG, *address, arg_socket_type, (arg_accept*SOCK_CLOEXEC)); if (fd < 0) { log_open(); return log_error_errno(fd, "Failed to open '%s': %m", *address); } assert(fd == SD_LISTEN_FDS_START + count); count++; }