static PyObject* is_socket_unix(PyObject *self, PyObject *args) { int r; int fd, type = 0, listening = -1; char* path = NULL; Py_ssize_t length = 0; #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1 _cleanup_Py_DECREF_ PyObject *_path = NULL; if (!PyArg_ParseTuple(args, "i|iiO&:_is_socket_unix", &fd, &type, &listening, Unicode_FSConverter, &_path)) return NULL; if (_path) { assert(PyBytes_Check(_path)); if (PyBytes_AsStringAndSize(_path, &path, &length)) return NULL; } #else if (!PyArg_ParseTuple(args, "i|iiz#:_is_socket_unix", &fd, &type, &listening, &path, &length)) return NULL; #endif r = sd_is_socket_unix(fd, type, listening, path, length); if (set_error(r, path, NULL) < 0) return NULL; return PyBool_FromLong(r); }
int SocketManager::GetSocketFromSystemD( const GenericSocketService::ServiceDescription &desc) { int fd; // TODO optimalization - do it once in object constructor // and remember all information path->sockfd int n = sd_listen_fds(0); LogInfo("sd_listen_fds returns: " << n); if (n < 0) { LogError("Error in sd_listend_fds"); ThrowMsg(Exception::InitFailed, "Error in sd_listend_fds"); } for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START+n; ++fd) { if (0 < sd_is_socket_unix(fd, SOCK_STREAM, 1, desc.serviceHandlerPath.c_str(), 0)) { LogInfo("Useable socket " << desc.serviceHandlerPath << " was passed by SystemD under descriptor " << fd); return fd; } } LogError("No useable sockets were passed by systemd."); return -1; }
static gboolean systemd_syslog_sd_acquire_socket(AFSocketSourceDriver *s, gint *acquired_fd) { gint fd, number_of_fds; *acquired_fd = -1; fd = -1; number_of_fds = sd_listen_fds(0); if (number_of_fds > 1) { msg_error("Systemd socket activation failed: got more than one fd", evt_tag_int("number", number_of_fds), NULL); return TRUE; } else if (number_of_fds < 1) { msg_error("Failed to acquire /run/systemd/journal/syslog socket, disabling systemd-syslog source", NULL); return TRUE; } else { fd = SD_LISTEN_FDS_START; msg_debug("Systemd socket activation", evt_tag_int("file-descriptor", fd), NULL); if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, NULL, 0)) { *acquired_fd = fd; } else { msg_error("The systemd supplied UNIX domain socket is of a" " different type, check the configured driver and" " the matching systemd unit file", evt_tag_int("systemd-sock-fd", fd), evt_tag_str("expecting", "unix-dgram()"), NULL); *acquired_fd = -1; return TRUE; } } if (*acquired_fd != -1) { g_fd_set_nonblock(*acquired_fd, TRUE); msg_verbose("Acquired systemd syslog socket", evt_tag_int("systemd-syslog-sock-fd", *acquired_fd), NULL); return TRUE; } return TRUE; }
int get_socket() { int fd, n; size_t name_length; socklen_t new_length; name_length = strlen(ABSTRACT_SOCKET_NAME) + 1; if (HAVE_LIBSYSTEMD == 1) { /* Check for file descriptors passed by the system manager */ n = sd_listen_fds(0); } else { n = 0; } if (n < 0) { /* Below 0 is an error code */ fprintf(stderr, "sd_listen_fds(): %s\n", strerror(-n)); exit(EXIT_FAILURE); } else if (n > 1) { /* Only need one socket */ fprintf(stderr, "Too many file descriptors received.\n"); exit(EXIT_FAILURE); } else if (n == 1) { /* Got one socket */ fd = SD_LISTEN_FDS_START + 0; /* Check it is correct type */ if (sd_is_socket_unix(fd, SOCK_STREAM, -1, "\0", name_length) <= 0) { fprintf(stderr, "Invalid socket passed.\n"); exit(EXIT_FAILURE); } } else { /* No socket from system manager. Lets make our own then */ struct sockaddr_un addr; memset(&addr, 0, sizeof(struct sockaddr_un)); /* Clear address structure */ addr.sun_family = AF_UNIX; /* UNIX domain address */ /* addr.sun_path[0] has already been set to 0 by memset() */ strncpy(&addr.sun_path[1], ABSTRACT_SOCKET_NAME, strlen(ABSTRACT_SOCKET_NAME)); fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); if (fd == -1) { printf("socket error"); exit(EXIT_FAILURE); } new_length = (socklen_t) sizeof(sa_family_t) + (socklen_t) name_length; if (bind(fd, (struct sockaddr *) &addr, new_length) == -1) { printf("socket binding error"); exit(EXIT_FAILURE); } } return fd; }
/* Will work regardless of the order systemd gives them to us */ static int oxen_get_sd_fd(const char *connect_to) { int fd = SD_LISTEN_FDS_START; int r; while (fd <= SD_LISTEN_FDS_START + 1) { r = sd_is_socket_unix(fd, SOCK_STREAM, 1, connect_to, 0); if (r > 0) return fd; fd++; } return -EBADR; }
static char * system_linux_find_dev_log(void) { int r, fd; r = sd_listen_fds(0); if (r == 0) return "/dev/log"; if (r < 0) { msg_error ("system(): sd_listen_fds() failed", evt_tag_int("errno", r), NULL); return NULL; } /* We only support socket activation for /dev/log, meaning * one socket only. Bail out if we get more. */ if (r != 1) { msg_error("system(): Too many sockets passed in for socket activation, syslog-ng only supports one.", NULL); return NULL; } fd = SD_LISTEN_FDS_START; if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/run/systemd/journal/syslog", 0) != 1) { msg_error("system(): Socket activation is only supported on /run/systemd/journal/syslog", NULL); return NULL; } return "/run/systemd/journal/syslog"; }
/*! starts listening on a UNIX domain server socket. * * \param path the path on the local file system, that this socket is 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& path, int flags) { #ifndef NDEBUG setLoggingPrefix("ServerSocket(%s)", path.c_str()); #endif TRACE("opening"); int fd = -1; size_t addrlen; int sd_fd_count = sd_listen_fds(false); 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 if ((fd = x0::getSocketUnix(path.c_str())) >= 0) { // socket found, but ensure our expected `flags` are set. if (flags && fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | flags) < 0) { goto syserr; } else { 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 (; fd < last; ++fd) { if (sd_is_socket_unix(fd, AF_UNIX, SOCK_STREAM, path.c_str(), path.size()) > 0) { // socket found, but ensure our expected `flags` are set. if (flags && fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | flags) < 0) { goto syserr; } else { goto done; } } } errorText_ = "Running under systemd socket unit, but we received no UNIX-socket for \"" + path + "\"."; goto err; } // create socket manually fd = ::socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) goto syserr; if (flags && fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | flags) < 0) goto syserr; struct sockaddr_un addr; addr.sun_family = AF_UNIX; if (path.size() >= sizeof(addr.sun_path)) { errno = ENAMETOOLONG; goto syserr; } addrlen = sizeof(addr.sun_family) + strlen(strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path))); if (::bind(fd, reinterpret_cast<struct sockaddr*>(&addr), addrlen) < 0) goto syserr; if (::listen(fd, backlog_)) goto syserr; if (chmod(path.c_str(), 0666) < 0) { perror("chmod"); } done: fd_ = fd; addressFamily_ = AF_UNIX; address_ = path; port_ = 0; io_.set<ServerSocket, &ServerSocket::accept>(this); start(); return true; syserr: errorText_ = strerror(errno); err: if (fd >= 0) ::close(fd); return false; }
/** * Entry point into bt-daemon * @param argc Number of arguments passed * @param argv An array of string arguments * @returns EXIT_SUCCESS if the operation succeeded, otherwise EXIT_FAILURE */ int main(int argc, char *argv[]) { int fd; int smackfd = -1; socklen_t addr_len; struct sockaddr_un remote; int descriptors; int ret; bool manual_start = false; struct sigaction sa; if (!buxton_cache_smack_rules()) exit(EXIT_FAILURE); smackfd = buxton_watch_smack_rules(); if (smackfd < 0 && errno) exit(EXIT_FAILURE); self.nfds_alloc = 0; self.accepting_alloc = 0; self.nfds = 0; self.buxton.client.direct = true; self.buxton.client.uid = geteuid(); if (!buxton_direct_open(&self.buxton)) exit(EXIT_FAILURE); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = my_handler; ret = sigaction(SIGINT, &sa, NULL); if (ret == -1) exit(EXIT_FAILURE); ret = sigaction(SIGTERM, &sa, NULL); if (ret == -1) exit(EXIT_FAILURE); /* For client notifications */ self.notify_mapping = hashmap_new(string_hash_func, string_compare_func); /* Store a list of connected clients */ LIST_HEAD_INIT(client_list_item, self.client_list); descriptors = sd_listen_fds(0); if (descriptors < 0) { buxton_log("sd_listen_fds: %m\n"); exit(EXIT_FAILURE); } else if (descriptors == 0) { /* Manual invocation */ manual_start = true; union { struct sockaddr sa; struct sockaddr_un un; } sa; fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { buxton_log("socket(): %m\n"); exit(EXIT_FAILURE); } memset(&sa, 0, sizeof(sa)); sa.un.sun_family = AF_UNIX; strncpy(sa.un.sun_path, BUXTON_SOCKET, sizeof(sa.un.sun_path) - 1); sa.un.sun_path[sizeof(sa.un.sun_path)-1] = 0; ret = unlink(sa.un.sun_path); if (ret == -1 && errno != ENOENT) { exit(EXIT_FAILURE); } if (bind(fd, &sa.sa, sizeof(sa)) < 0) { buxton_log("bind(): %m\n"); exit(EXIT_FAILURE); } chmod(sa.un.sun_path, 0666); if (listen(fd, SOMAXCONN) < 0) { buxton_log("listen(): %m\n"); exit(EXIT_FAILURE); } add_pollfd(&self, fd, POLLIN | POLLPRI, true); } else { /* systemd socket activation */ for (fd = SD_LISTEN_FDS_START + 0; fd < SD_LISTEN_FDS_START + descriptors; fd++) { if (sd_is_fifo(fd, NULL)) { add_pollfd(&self, fd, POLLIN, false); buxton_debug("Added fd %d type FIFO\n", fd); } else if (sd_is_socket_unix(fd, SOCK_STREAM, -1, BUXTON_SOCKET, 0)) { add_pollfd(&self, fd, POLLIN | POLLPRI, true); buxton_debug("Added fd %d type UNIX\n", fd); } else if (sd_is_socket(fd, AF_UNSPEC, 0, -1)) { add_pollfd(&self, fd, POLLIN | POLLPRI, true); buxton_debug("Added fd %d type SOCKET\n", fd); } } } if (smackfd >= 0) { /* add Smack rule fd to pollfds */ add_pollfd(&self, smackfd, POLLIN | POLLPRI, false); } buxton_log("%s: Started\n", argv[0]); /* Enter loop to accept clients */ for (;;) { ret = poll(self.pollfds, self.nfds, -1); if (ret < 0) { buxton_log("poll(): %m\n"); if (errno == EINTR) { if (do_shutdown) break; else continue; } break; } if (ret == 0) continue; for (nfds_t i=0; i<self.nfds; i++) { client_list_item *cl = NULL; char discard[256]; if (self.pollfds[i].revents == 0) continue; if (self.pollfds[i].fd == -1) { /* TODO: Remove client from list */ buxton_debug("Removing / Closing client for fd %d\n", self.pollfds[i].fd); del_pollfd(&self, i); continue; } if (smackfd >= 0) { if (self.pollfds[i].fd == smackfd) { if (!buxton_cache_smack_rules()) exit(EXIT_FAILURE); buxton_log("Reloaded Smack access rules\n"); /* discard inotify data itself */ while (read(smackfd, &discard, 256) == 256); continue; } } if (self.accepting[i] == true) { struct timeval tv; int fd; int on = 1; addr_len = sizeof(remote); if ((fd = accept(self.pollfds[i].fd, (struct sockaddr *)&remote, &addr_len)) == -1) { buxton_log("accept(): %m\n"); break; } buxton_debug("New client fd %d connected through fd %d\n", fd, self.pollfds[i].fd); cl = malloc0(sizeof(client_list_item)); if (!cl) exit(EXIT_FAILURE); LIST_INIT(client_list_item, item, cl); cl->fd = fd; cl->cred = (struct ucred) {0, 0, 0}; LIST_PREPEND(client_list_item, item, self.client_list, cl); /* poll for data on this new client as well */ add_pollfd(&self, cl->fd, POLLIN | POLLPRI, false); /* Mark our packets as high prio */ if (setsockopt(cl->fd, SOL_SOCKET, SO_PRIORITY, &on, sizeof(on)) == -1) buxton_log("setsockopt(SO_PRIORITY): %m\n"); /* Set socket recv timeout */ tv.tv_sec = SOCKET_TIMEOUT; tv.tv_usec = 0; if (setsockopt(cl->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) == -1) buxton_log("setsockopt(SO_RCVTIMEO): %m\n"); /* check if this is optimal or not */ break; } assert(self.accepting[i] == 0); if (smackfd >= 0) assert(self.pollfds[i].fd != smackfd); /* handle data on any connection */ /* TODO: Replace with hash table lookup */ LIST_FOREACH(item, cl, self.client_list) if (self.pollfds[i].fd == cl->fd) break; assert(cl); handle_client(&self, cl, i); } } buxton_log("%s: Closing all connections\n", argv[0]); if (manual_start) unlink(BUXTON_SOCKET); for (int i = 0; i < self.nfds; i++) { close(self.pollfds[i].fd); } for (client_list_item *i = self.client_list; i;) { client_list_item *j = i->item_next; free(i); i = j; } hashmap_free(self.notify_mapping); buxton_direct_close(&self.buxton); return EXIT_SUCCESS; }
static gboolean afunix_sd_acquire_named_socket(AFSocketSourceDriver *s, gint *result_fd, const gchar *filename) { AFUnixSourceDriver *self = (AFUnixSourceDriver *) s; gint fd, fds; *result_fd = -1; fd = -1; fds = sd_listen_fds(0); if (fds == 0) return TRUE; msg_debug("Systemd socket activation", evt_tag_int("systemd-sockets", fds), evt_tag_str("systemd-listen-pid", getenv("LISTEN_PID")), evt_tag_str("systemd-listen-fds", getenv("LISTEN_FDS")), NULL); if (fds < 0) { msg_error("Failed to acquire systemd sockets, incorrectly set LISTEN_FDS environment variable?", NULL); return FALSE; } else if (fds > 0) { for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + fds; fd++) { /* check if any type is available */ if (sd_is_socket_unix(fd, 0, -1, filename, 0)) { /* check if it matches our idea of the socket type */ if (sd_is_socket_unix(fd, self->super.transport_mapper->sock_type, -1, filename, 0)) { *result_fd = fd; break; } else { msg_error("The systemd supplied UNIX domain socket is of a different type, check the configured driver and the matching systemd unit file", evt_tag_str("filename", filename), evt_tag_int("systemd-sock-fd", fd), evt_tag_str("expecting", self->super.transport_mapper->sock_type == SOCK_STREAM ? "unix-stream()" : "unix-dgram()"), NULL); return FALSE; } } else { /* systemd passed an fd we didn't really care about. This is * not an error, but might be worth mentioning it at the debug * level. */ msg_debug("Ignoring systemd supplied fd as it is not a UNIX domain socket", evt_tag_str("filename", filename), evt_tag_int("systemd-sock-fd", fd), NULL); } } } if (*result_fd != -1) { g_fd_set_nonblock(*result_fd, TRUE); g_fd_set_cloexec(*result_fd, TRUE); msg_verbose("Acquired systemd socket", evt_tag_str("filename", filename), evt_tag_int("systemd-sock-fd", *result_fd), NULL); return TRUE; } return TRUE; }