socket-util: add af_unix_get_qlen() helper to determine number of queued connections on AF_UNIX listener socket
This commit is contained in:
@@ -3,8 +3,12 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <linux/net_namespace.h>
|
||||
#include <linux/unix_diag.h>
|
||||
#include <net/if.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "errno-util.h"
|
||||
@@ -13,6 +17,7 @@
|
||||
#include "log.h"
|
||||
#include "memory-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "netlink-sock-diag.h"
|
||||
#include "netlink-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "socket-netlink.h"
|
||||
@@ -479,3 +484,63 @@ int netns_get_nsid(int netnsfd, uint32_t *ret) {
|
||||
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
int af_unix_get_qlen(int fd, uint32_t *ret) {
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ret);
|
||||
|
||||
/* Returns the current queue length for an AF_UNIX listening socket */
|
||||
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
if (!S_ISSOCK(st.st_mode))
|
||||
return -ENOTSOCK;
|
||||
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *nl = NULL;
|
||||
r = sd_sock_diag_socket_open(&nl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
uint64_t cookie = 0;
|
||||
socklen_t cookie_len = sizeof(cookie);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_COOKIE, &cookie, &cookie_len) < 0)
|
||||
return -errno;
|
||||
|
||||
assert(cookie_len == sizeof(cookie));
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
|
||||
r = sd_sock_diag_message_new_unix(nl, &message, st.st_ino, cookie, UDIAG_SHOW_RQLEN);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *reply = NULL;
|
||||
r = sd_netlink_call(nl, message, /* usec= */ 0, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (sd_netlink_message *m = reply; m; m = sd_netlink_message_next(m)) {
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_free_ void *data = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
r = sd_netlink_message_read_data(m, UNIX_DIAG_RQLEN, &size, &data);
|
||||
if (r == -ENODATA)
|
||||
continue;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
assert(size == sizeof(struct unix_diag_rqlen));
|
||||
const struct unix_diag_rqlen *udrql = ASSERT_PTR(data);
|
||||
|
||||
*ret = udrql->udiag_rqueue;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
@@ -45,3 +45,5 @@ int in_addr_full_new_from_string(const char *s, struct in_addr_full **ret);
|
||||
const char* in_addr_full_to_string(struct in_addr_full *a);
|
||||
|
||||
int netns_get_nsid(int netnsfd, uint32_t *ret);
|
||||
|
||||
int af_unix_get_qlen(int fd, uint32_t *ret);
|
||||
|
||||
Reference in New Issue
Block a user