diff --git a/tests/.gitignore b/tests/.gitignore index 9504dd36..b53ef6ad 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -3,6 +3,7 @@ inet-accept-connect-send-recv mmsg net-accept-connect netlink_inet_diag +netlink_unix_diag scm_rights set_ptracer_any sigaction diff --git a/tests/Makefile.am b/tests/Makefile.am index f17e8c0f..e307c577 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -8,6 +8,7 @@ check_PROGRAMS = \ mmsg \ net-accept-connect \ netlink_inet_diag \ + netlink_unix_diag \ scm_rights \ set_ptracer_any \ sigaction \ diff --git a/tests/netlink_unix_diag.c b/tests/netlink_unix_diag.c new file mode 100644 index 00000000..7208117c --- /dev/null +++ b/tests/netlink_unix_diag.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +send_query(const int fd, const int family, const int proto) +{ + struct sockaddr_nl nladdr = { + .nl_family = AF_NETLINK + }; + struct { + struct nlmsghdr nlh; + struct unix_diag_req udr; + } req = { + .nlh = { + .nlmsg_len = sizeof(req), + .nlmsg_type = SOCK_DIAG_BY_FAMILY, + .nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST + }, + .udr = { + .sdiag_family = family, + .sdiag_protocol = proto, + .udiag_states = -1, + .udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER + } + }; + struct iovec iov = { + .iov_base = &req, + .iov_len = sizeof(req) + }; + struct msghdr msg = { + .msg_name = (void*)&nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1 + }; + + return sendmsg(fd, &msg, 0) > 0; +} + +static int +check_responses(const int fd) +{ + static char buf[8192]; + struct sockaddr_nl nladdr = { + .nl_family = AF_NETLINK + }; + struct iovec iov = { + .iov_base = buf, + .iov_len = sizeof(buf) + }; + struct msghdr msg = { + .msg_name = (void*)&nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1 + }; + + ssize_t ret = recvmsg(fd, &msg, 0); + if (ret <= 0) + return 0; + + struct nlmsghdr *h = (struct nlmsghdr*)buf; + return (NLMSG_OK(h, ret) && + h->nlmsg_type != NLMSG_ERROR && + h->nlmsg_type != NLMSG_DONE) ? 1 : 0; +} + +#define SUN_PATH "netlink_unix_diag_socket" +int main(void) +{ + struct sockaddr_un addr = { + .sun_family = AF_UNIX, + .sun_path = SUN_PATH + }; + socklen_t len = offsetof(struct sockaddr_un, sun_path) + sizeof(SUN_PATH); + + close(0); + close(1); + + (void) unlink(SUN_PATH); + assert(socket(PF_LOCAL, SOCK_STREAM, 0) == 0); + assert(bind(0, (struct sockaddr *) &addr, len) == 0); + assert(listen(0, 5) == 0); + assert(unlink(SUN_PATH) == 0); + + if (socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG) != 1) + return 77; + + return (send_query(1, AF_UNIX, 0) && + check_responses(1)) ? 0 : 77; +} diff --git a/tests/unix-yy.test b/tests/unix-yy.test index 6e7bd563..1114e17d 100755 --- a/tests/unix-yy.test +++ b/tests/unix-yy.test @@ -17,11 +17,11 @@ rm -f $LOG.* $LOG-* ./net-accept-connect || fail_ 'net-accept-connect failed' -./netlink_inet_diag || { +./netlink_unix_diag || { if [ $? -eq 77 ]; then - framework_skip_ 'NETLINK_INET_DIAG is not available' + framework_skip_ 'NETLINK_SOCK_DIAG for unix domain sockets is not available' else - fail_ 'netlink_inet_diag failed' + fail_ 'netlink_unix_diag failed' fi }